@clawos-dev/clawd 0.2.320 → 0.2.322
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +920 -359
- package/dist/dispatch/mcp-server.cjs +52 -0
- package/dist/persona-defaults/persona-clawd-butler/CLAUDE.md +5 -1
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-_8xl9KLi.js +554 -0
- package/dist/share-ui/assets/guest-at9vEwv7.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-BDxMsm17.js +0 -574
- package/dist/share-ui/assets/guest-Bho4yUyY.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: path81, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path81, ...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, path81, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path81;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -6072,7 +6072,9 @@ var init_feishu_auth = __esm({
|
|
|
6072
6072
|
"peerSession:remove",
|
|
6073
6073
|
// 设备目录 + 连接(决策 #15:daemon 代理中心 server,需要 owner 的 ttcJwt)
|
|
6074
6074
|
"device:list",
|
|
6075
|
-
"device:connect"
|
|
6075
|
+
"device:connect",
|
|
6076
|
+
// iOS TestFlight 意向登记(需要 owner unionId 上报中心 server)
|
|
6077
|
+
"onboarding:iosInterest"
|
|
6076
6078
|
];
|
|
6077
6079
|
DeviceEntrySchema = external_exports.object({
|
|
6078
6080
|
/**
|
|
@@ -6659,6 +6661,49 @@ var init_lark_bot_schemas = __esm({
|
|
|
6659
6661
|
}
|
|
6660
6662
|
});
|
|
6661
6663
|
|
|
6664
|
+
// ../protocol/src/onboarding-schemas.ts
|
|
6665
|
+
var OnboardingCompleteArgs, OnboardingCompleteResultSchema, ToolsProbeArgs, ToolsProbeResultSchema, SessionExternalScanArgs, ExternalSessionCandidateSchema, SessionExternalScanResultSchema, OnboardingIosInterestArgs, OnboardingIosInterestResultSchema;
|
|
6666
|
+
var init_onboarding_schemas = __esm({
|
|
6667
|
+
"../protocol/src/onboarding-schemas.ts"() {
|
|
6668
|
+
"use strict";
|
|
6669
|
+
init_zod();
|
|
6670
|
+
OnboardingCompleteArgs = external_exports.object({});
|
|
6671
|
+
OnboardingCompleteResultSchema = external_exports.object({
|
|
6672
|
+
/** 毫秒时间戳;重复调用幂等返回首次值(对齐 personaScanDoneAt 先例) */
|
|
6673
|
+
onboardingCompletedAt: external_exports.number()
|
|
6674
|
+
});
|
|
6675
|
+
ToolsProbeArgs = external_exports.object({});
|
|
6676
|
+
ToolsProbeResultSchema = external_exports.object({
|
|
6677
|
+
tools: external_exports.array(
|
|
6678
|
+
external_exports.object({
|
|
6679
|
+
id: external_exports.enum(["claude", "codex"]),
|
|
6680
|
+
available: external_exports.boolean(),
|
|
6681
|
+
version: external_exports.string().optional(),
|
|
6682
|
+
path: external_exports.string().optional()
|
|
6683
|
+
})
|
|
6684
|
+
)
|
|
6685
|
+
});
|
|
6686
|
+
SessionExternalScanArgs = external_exports.object({});
|
|
6687
|
+
ExternalSessionCandidateSchema = external_exports.object({
|
|
6688
|
+
tool: external_exports.enum(["claude", "codex"]),
|
|
6689
|
+
cwd: external_exports.string(),
|
|
6690
|
+
toolSessionId: external_exports.string(),
|
|
6691
|
+
label: external_exports.string().optional(),
|
|
6692
|
+
/** ISO datetime(直接回填给 session:importExternal) */
|
|
6693
|
+
createdAt: external_exports.string(),
|
|
6694
|
+
updatedAt: external_exports.string(),
|
|
6695
|
+
turns: external_exports.number()
|
|
6696
|
+
});
|
|
6697
|
+
SessionExternalScanResultSchema = external_exports.object({
|
|
6698
|
+
candidates: external_exports.array(ExternalSessionCandidateSchema)
|
|
6699
|
+
});
|
|
6700
|
+
OnboardingIosInterestArgs = external_exports.object({});
|
|
6701
|
+
OnboardingIosInterestResultSchema = external_exports.object({
|
|
6702
|
+
registered: external_exports.boolean()
|
|
6703
|
+
});
|
|
6704
|
+
}
|
|
6705
|
+
});
|
|
6706
|
+
|
|
6662
6707
|
// ../protocol/src/persona-schemas.ts
|
|
6663
6708
|
var PersonaFileSchema, PersonaSkillSummarySchema, PersonaPluginSummarySchema, PersonaSandboxSettingsSchema, PersonaInfoResponseSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema, CodexSandboxSettingsSchema;
|
|
6664
6709
|
var init_persona_schemas = __esm({
|
|
@@ -7906,6 +7951,7 @@ var init_methods = __esm({
|
|
|
7906
7951
|
init_shift_internal();
|
|
7907
7952
|
init_github();
|
|
7908
7953
|
init_lark_bot_schemas();
|
|
7954
|
+
init_onboarding_schemas();
|
|
7909
7955
|
init_persona_schemas();
|
|
7910
7956
|
init_schemas();
|
|
7911
7957
|
NO_ARGS = external_exports.object({});
|
|
@@ -7920,6 +7966,10 @@ var init_methods = __esm({
|
|
|
7920
7966
|
anyOf: [{ required: ["cwd"] }, { required: ["ownerPersonaId"] }]
|
|
7921
7967
|
}
|
|
7922
7968
|
},
|
|
7969
|
+
"session:externalScan": {
|
|
7970
|
+
summary: "\u626B\u63CF\u672C\u673A Claude Code / Codex \u5386\u53F2\u4F1A\u8BDD\uFF0C\u8FD4\u56DE\u53EF\u5BFC\u5165\u5019\u9009\u6E05\u5355\uFF08cwd/toolSessionId/\u65F6\u95F4\u6233/\u8F6E\u6570\uFF09\uFF1B\u6458\u8981\u7EDF\u8BA1\u4E0E\u65F6\u95F4\u7A97\u8FC7\u6EE4\u7531 UI \u6D3E\u751F\uFF0Cskip \u89C4\u5219\u4E0E clawd-session-import skill \u4E00\u81F4\uFF1Bowner-only",
|
|
7971
|
+
args: SessionExternalScanArgs
|
|
7972
|
+
},
|
|
7923
7973
|
"session:importExternal": {
|
|
7924
7974
|
summary: "\u628A Claude Code / Codex \u65E2\u6709\u5386\u53F2\u4F1A\u8BDD\u5BFC\u5165\u4E3A clawd \u5F15\u7528\uFF1A\u53EA\u5199 SessionFile\uFF0C\u4E0D\u62C9\u8D77 runner\uFF0C\u4E0D\u6539\u539F\u59CB transcript\uFF1B\u6309 toolSessionId \u8DE8 owned scope \u53BB\u91CD\uFF0C\u65B0\u5BFC\u5165\u4F1A\u5E7F\u64AD session:info",
|
|
7925
7975
|
args: SessionImportExternalArgs
|
|
@@ -8140,6 +8190,18 @@ var init_methods = __esm({
|
|
|
8140
8190
|
summary: "\u67E5 persona \u7684\u98DE\u4E66 bot \u72B6\u6001\uFF08unbound/bound/broken + \u670D\u52A1\u4E2D\u7FA4\u6E05\u5355\uFF09\uFF1Bowner-only",
|
|
8141
8191
|
args: LarkBotStatusArgs
|
|
8142
8192
|
},
|
|
8193
|
+
"onboarding:complete": {
|
|
8194
|
+
summary: "\u6807\u8BB0\u9996\u542F onboarding \u5B8C\u6210\uFF1A\u5F80 <dataDir>/profile.json \u5199 onboardingCompletedAt\uFF08\u6BEB\u79D2\u65F6\u95F4\u6233\uFF0C\u4FDD\u7559\u5176\u5B83\u5B57\u6BB5\uFF0C\u91CD\u590D\u8C03\u7528\u5E42\u7B49\uFF09\uFF1Binfo ready \u5E27\u643A\u5E26\u8BE5\u5B57\u6BB5\u4F9B UI \u5224\u5B9A\u662F\u5426\u8FDB wizard",
|
|
8195
|
+
args: OnboardingCompleteArgs
|
|
8196
|
+
},
|
|
8197
|
+
"tools:probe": {
|
|
8198
|
+
summary: "\u63A2\u6D4B\u672C\u673A claude / codex CLI \u771F\u5B9E\u53EF\u7528\u6027\u4E0E\u7248\u672C\uFF08which + <bin> --version\uFF0C\u8FDB\u7A0B\u7EA7\u7F13\u5B58\uFF09\uFF1Binfo \u5E27 tools[].available \u662F\u6CE8\u518C\u5360\u4F4D\u4E0D\u53CD\u6620\u5B89\u88C5\u72B6\u6001\uFF0Cwizard \u73AF\u5883\u68C0\u67E5\u7528\u672C\u65B9\u6CD5",
|
|
8199
|
+
args: ToolsProbeArgs
|
|
8200
|
+
},
|
|
8201
|
+
"onboarding:iosInterest": {
|
|
8202
|
+
summary: "\u767B\u8BB0 owner \u60F3\u8981 iOS TestFlight\uFF1Adaemon \u8F6C\u53D1\u4E2D\u5FC3 API\uFF08\u643A\u5E26 unionId/\u98DE\u4E66\u540D\uFF09\uFF0Cserver \u843D\u8868\u53BB\u91CD\u5E76\u7528\u5B98\u65B9 bot \u901A\u77E5 David \u8D70\u98DE\u4E66\u8054\u7CFB\uFF1B\u9700\u98DE\u4E66\u5DF2\u767B\u5F55\uFF08FEISHU_GATED\uFF09",
|
|
8203
|
+
args: OnboardingIosInterestArgs
|
|
8204
|
+
},
|
|
8143
8205
|
"skills:list": {
|
|
8144
8206
|
summary: "\u626B\u63CF\u5E76\u5217\u51FA\u8BE5\u76EE\u5F55\u53EF\u7528\u7684 skill",
|
|
8145
8207
|
args: SkillsListArgs
|
|
@@ -8592,6 +8654,7 @@ var init_runtime = __esm({
|
|
|
8592
8654
|
init_shift_internal();
|
|
8593
8655
|
init_lark_bot_schemas();
|
|
8594
8656
|
init_lark_bot_format();
|
|
8657
|
+
init_onboarding_schemas();
|
|
8595
8658
|
}
|
|
8596
8659
|
});
|
|
8597
8660
|
|
|
@@ -8866,8 +8929,8 @@ var require_req = __commonJS({
|
|
|
8866
8929
|
if (req.originalUrl) {
|
|
8867
8930
|
_req.url = req.originalUrl;
|
|
8868
8931
|
} else {
|
|
8869
|
-
const
|
|
8870
|
-
_req.url = typeof
|
|
8932
|
+
const path81 = req.path;
|
|
8933
|
+
_req.url = typeof path81 === "string" ? path81 : req.url ? req.url.path || req.url : void 0;
|
|
8871
8934
|
}
|
|
8872
8935
|
if (req.query) {
|
|
8873
8936
|
_req.query = req.query;
|
|
@@ -9032,14 +9095,14 @@ var require_redact = __commonJS({
|
|
|
9032
9095
|
}
|
|
9033
9096
|
return obj;
|
|
9034
9097
|
}
|
|
9035
|
-
function parsePath(
|
|
9098
|
+
function parsePath(path81) {
|
|
9036
9099
|
const parts = [];
|
|
9037
9100
|
let current = "";
|
|
9038
9101
|
let inBrackets = false;
|
|
9039
9102
|
let inQuotes = false;
|
|
9040
9103
|
let quoteChar = "";
|
|
9041
|
-
for (let i = 0; i <
|
|
9042
|
-
const char =
|
|
9104
|
+
for (let i = 0; i < path81.length; i++) {
|
|
9105
|
+
const char = path81[i];
|
|
9043
9106
|
if (!inBrackets && char === ".") {
|
|
9044
9107
|
if (current) {
|
|
9045
9108
|
parts.push(current);
|
|
@@ -9170,10 +9233,10 @@ var require_redact = __commonJS({
|
|
|
9170
9233
|
return current;
|
|
9171
9234
|
}
|
|
9172
9235
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9173
|
-
for (const
|
|
9174
|
-
const parts = parsePath(
|
|
9236
|
+
for (const path81 of paths) {
|
|
9237
|
+
const parts = parsePath(path81);
|
|
9175
9238
|
if (parts.includes("*")) {
|
|
9176
|
-
redactWildcardPath(obj, parts, censor,
|
|
9239
|
+
redactWildcardPath(obj, parts, censor, path81, remove);
|
|
9177
9240
|
} else {
|
|
9178
9241
|
if (remove) {
|
|
9179
9242
|
removeKey(obj, parts);
|
|
@@ -9258,8 +9321,8 @@ var require_redact = __commonJS({
|
|
|
9258
9321
|
}
|
|
9259
9322
|
} else {
|
|
9260
9323
|
if (afterWildcard.includes("*")) {
|
|
9261
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9262
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9324
|
+
const wrappedCensor = typeof censor === "function" ? (value, path81) => {
|
|
9325
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path81];
|
|
9263
9326
|
return censor(value, fullPath);
|
|
9264
9327
|
} : censor;
|
|
9265
9328
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9294,8 +9357,8 @@ var require_redact = __commonJS({
|
|
|
9294
9357
|
return null;
|
|
9295
9358
|
}
|
|
9296
9359
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9297
|
-
for (const
|
|
9298
|
-
const parts = parsePath(
|
|
9360
|
+
for (const path81 of pathsToClone) {
|
|
9361
|
+
const parts = parsePath(path81);
|
|
9299
9362
|
let current = pathStructure;
|
|
9300
9363
|
for (let i = 0; i < parts.length; i++) {
|
|
9301
9364
|
const part = parts[i];
|
|
@@ -9347,24 +9410,24 @@ var require_redact = __commonJS({
|
|
|
9347
9410
|
}
|
|
9348
9411
|
return cloneSelectively(obj, pathStructure);
|
|
9349
9412
|
}
|
|
9350
|
-
function validatePath(
|
|
9351
|
-
if (typeof
|
|
9413
|
+
function validatePath(path81) {
|
|
9414
|
+
if (typeof path81 !== "string") {
|
|
9352
9415
|
throw new Error("Paths must be (non-empty) strings");
|
|
9353
9416
|
}
|
|
9354
|
-
if (
|
|
9417
|
+
if (path81 === "") {
|
|
9355
9418
|
throw new Error("Invalid redaction path ()");
|
|
9356
9419
|
}
|
|
9357
|
-
if (
|
|
9358
|
-
throw new Error(`Invalid redaction path (${
|
|
9420
|
+
if (path81.includes("..")) {
|
|
9421
|
+
throw new Error(`Invalid redaction path (${path81})`);
|
|
9359
9422
|
}
|
|
9360
|
-
if (
|
|
9361
|
-
throw new Error(`Invalid redaction path (${
|
|
9423
|
+
if (path81.includes(",")) {
|
|
9424
|
+
throw new Error(`Invalid redaction path (${path81})`);
|
|
9362
9425
|
}
|
|
9363
9426
|
let bracketCount = 0;
|
|
9364
9427
|
let inQuotes = false;
|
|
9365
9428
|
let quoteChar = "";
|
|
9366
|
-
for (let i = 0; i <
|
|
9367
|
-
const char =
|
|
9429
|
+
for (let i = 0; i < path81.length; i++) {
|
|
9430
|
+
const char = path81[i];
|
|
9368
9431
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9369
9432
|
if (!inQuotes) {
|
|
9370
9433
|
inQuotes = true;
|
|
@@ -9378,20 +9441,20 @@ var require_redact = __commonJS({
|
|
|
9378
9441
|
} else if (char === "]" && !inQuotes) {
|
|
9379
9442
|
bracketCount--;
|
|
9380
9443
|
if (bracketCount < 0) {
|
|
9381
|
-
throw new Error(`Invalid redaction path (${
|
|
9444
|
+
throw new Error(`Invalid redaction path (${path81})`);
|
|
9382
9445
|
}
|
|
9383
9446
|
}
|
|
9384
9447
|
}
|
|
9385
9448
|
if (bracketCount !== 0) {
|
|
9386
|
-
throw new Error(`Invalid redaction path (${
|
|
9449
|
+
throw new Error(`Invalid redaction path (${path81})`);
|
|
9387
9450
|
}
|
|
9388
9451
|
}
|
|
9389
9452
|
function validatePaths(paths) {
|
|
9390
9453
|
if (!Array.isArray(paths)) {
|
|
9391
9454
|
throw new TypeError("paths must be an array");
|
|
9392
9455
|
}
|
|
9393
|
-
for (const
|
|
9394
|
-
validatePath(
|
|
9456
|
+
for (const path81 of paths) {
|
|
9457
|
+
validatePath(path81);
|
|
9395
9458
|
}
|
|
9396
9459
|
}
|
|
9397
9460
|
function slowRedact(options = {}) {
|
|
@@ -9559,8 +9622,8 @@ var require_redaction = __commonJS({
|
|
|
9559
9622
|
if (shape[k2] === null) {
|
|
9560
9623
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9561
9624
|
} else {
|
|
9562
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9563
|
-
return censor(value, [k2, ...
|
|
9625
|
+
const wrappedCensor = typeof censor === "function" ? (value, path81) => {
|
|
9626
|
+
return censor(value, [k2, ...path81]);
|
|
9564
9627
|
} : censor;
|
|
9565
9628
|
o[k2] = Redact({
|
|
9566
9629
|
paths: shape[k2],
|
|
@@ -9778,10 +9841,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
9778
9841
|
var require_sonic_boom = __commonJS({
|
|
9779
9842
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
9780
9843
|
"use strict";
|
|
9781
|
-
var
|
|
9844
|
+
var fs71 = require("fs");
|
|
9782
9845
|
var EventEmitter3 = require("events");
|
|
9783
9846
|
var inherits = require("util").inherits;
|
|
9784
|
-
var
|
|
9847
|
+
var path81 = require("path");
|
|
9785
9848
|
var sleep2 = require_atomic_sleep();
|
|
9786
9849
|
var assert = require("assert");
|
|
9787
9850
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -9835,20 +9898,20 @@ var require_sonic_boom = __commonJS({
|
|
|
9835
9898
|
const mode = sonic.mode;
|
|
9836
9899
|
if (sonic.sync) {
|
|
9837
9900
|
try {
|
|
9838
|
-
if (sonic.mkdir)
|
|
9839
|
-
const fd =
|
|
9901
|
+
if (sonic.mkdir) fs71.mkdirSync(path81.dirname(file), { recursive: true });
|
|
9902
|
+
const fd = fs71.openSync(file, flags, mode);
|
|
9840
9903
|
fileOpened(null, fd);
|
|
9841
9904
|
} catch (err) {
|
|
9842
9905
|
fileOpened(err);
|
|
9843
9906
|
throw err;
|
|
9844
9907
|
}
|
|
9845
9908
|
} else if (sonic.mkdir) {
|
|
9846
|
-
|
|
9909
|
+
fs71.mkdir(path81.dirname(file), { recursive: true }, (err) => {
|
|
9847
9910
|
if (err) return fileOpened(err);
|
|
9848
|
-
|
|
9911
|
+
fs71.open(file, flags, mode, fileOpened);
|
|
9849
9912
|
});
|
|
9850
9913
|
} else {
|
|
9851
|
-
|
|
9914
|
+
fs71.open(file, flags, mode, fileOpened);
|
|
9852
9915
|
}
|
|
9853
9916
|
}
|
|
9854
9917
|
function SonicBoom(opts) {
|
|
@@ -9889,8 +9952,8 @@ var require_sonic_boom = __commonJS({
|
|
|
9889
9952
|
this.flush = flushBuffer;
|
|
9890
9953
|
this.flushSync = flushBufferSync;
|
|
9891
9954
|
this._actualWrite = actualWriteBuffer;
|
|
9892
|
-
fsWriteSync = () =>
|
|
9893
|
-
fsWrite = () =>
|
|
9955
|
+
fsWriteSync = () => fs71.writeSync(this.fd, this._writingBuf);
|
|
9956
|
+
fsWrite = () => fs71.write(this.fd, this._writingBuf, this.release);
|
|
9894
9957
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
9895
9958
|
this._writingBuf = "";
|
|
9896
9959
|
this.write = write;
|
|
@@ -9899,15 +9962,15 @@ var require_sonic_boom = __commonJS({
|
|
|
9899
9962
|
this._actualWrite = actualWrite;
|
|
9900
9963
|
fsWriteSync = () => {
|
|
9901
9964
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9902
|
-
return
|
|
9965
|
+
return fs71.writeSync(this.fd, this._writingBuf);
|
|
9903
9966
|
}
|
|
9904
|
-
return
|
|
9967
|
+
return fs71.writeSync(this.fd, this._writingBuf, "utf8");
|
|
9905
9968
|
};
|
|
9906
9969
|
fsWrite = () => {
|
|
9907
9970
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9908
|
-
return
|
|
9971
|
+
return fs71.write(this.fd, this._writingBuf, this.release);
|
|
9909
9972
|
}
|
|
9910
|
-
return
|
|
9973
|
+
return fs71.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
9911
9974
|
};
|
|
9912
9975
|
} else {
|
|
9913
9976
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -9964,7 +10027,7 @@ var require_sonic_boom = __commonJS({
|
|
|
9964
10027
|
}
|
|
9965
10028
|
}
|
|
9966
10029
|
if (this._fsync) {
|
|
9967
|
-
|
|
10030
|
+
fs71.fsyncSync(this.fd);
|
|
9968
10031
|
}
|
|
9969
10032
|
const len = this._len;
|
|
9970
10033
|
if (this._reopening) {
|
|
@@ -10078,7 +10141,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10078
10141
|
const onDrain = () => {
|
|
10079
10142
|
if (!this._fsync) {
|
|
10080
10143
|
try {
|
|
10081
|
-
|
|
10144
|
+
fs71.fsync(this.fd, (err) => {
|
|
10082
10145
|
this._flushPending = false;
|
|
10083
10146
|
cb(err);
|
|
10084
10147
|
});
|
|
@@ -10180,7 +10243,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10180
10243
|
const fd = this.fd;
|
|
10181
10244
|
this.once("ready", () => {
|
|
10182
10245
|
if (fd !== this.fd) {
|
|
10183
|
-
|
|
10246
|
+
fs71.close(fd, (err) => {
|
|
10184
10247
|
if (err) {
|
|
10185
10248
|
return this.emit("error", err);
|
|
10186
10249
|
}
|
|
@@ -10229,7 +10292,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10229
10292
|
buf = this._bufs[0];
|
|
10230
10293
|
}
|
|
10231
10294
|
try {
|
|
10232
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10295
|
+
const n = Buffer.isBuffer(buf) ? fs71.writeSync(this.fd, buf) : fs71.writeSync(this.fd, buf, "utf8");
|
|
10233
10296
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10234
10297
|
buf = releasedBufObj.writingBuf;
|
|
10235
10298
|
this._len = releasedBufObj.len;
|
|
@@ -10245,7 +10308,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10245
10308
|
}
|
|
10246
10309
|
}
|
|
10247
10310
|
try {
|
|
10248
|
-
|
|
10311
|
+
fs71.fsyncSync(this.fd);
|
|
10249
10312
|
} catch {
|
|
10250
10313
|
}
|
|
10251
10314
|
}
|
|
@@ -10266,7 +10329,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10266
10329
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10267
10330
|
}
|
|
10268
10331
|
try {
|
|
10269
|
-
const n =
|
|
10332
|
+
const n = fs71.writeSync(this.fd, buf);
|
|
10270
10333
|
buf = buf.subarray(n);
|
|
10271
10334
|
this._len = Math.max(this._len - n, 0);
|
|
10272
10335
|
if (buf.length <= 0) {
|
|
@@ -10294,13 +10357,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10294
10357
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10295
10358
|
if (this.sync) {
|
|
10296
10359
|
try {
|
|
10297
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
10360
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs71.writeSync(this.fd, this._writingBuf) : fs71.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10298
10361
|
release(null, written);
|
|
10299
10362
|
} catch (err) {
|
|
10300
10363
|
release(err);
|
|
10301
10364
|
}
|
|
10302
10365
|
} else {
|
|
10303
|
-
|
|
10366
|
+
fs71.write(this.fd, this._writingBuf, release);
|
|
10304
10367
|
}
|
|
10305
10368
|
}
|
|
10306
10369
|
function actualWriteBuffer() {
|
|
@@ -10309,7 +10372,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10309
10372
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10310
10373
|
if (this.sync) {
|
|
10311
10374
|
try {
|
|
10312
|
-
const written =
|
|
10375
|
+
const written = fs71.writeSync(this.fd, this._writingBuf);
|
|
10313
10376
|
release(null, written);
|
|
10314
10377
|
} catch (err) {
|
|
10315
10378
|
release(err);
|
|
@@ -10318,7 +10381,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10318
10381
|
if (kCopyBuffer) {
|
|
10319
10382
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10320
10383
|
}
|
|
10321
|
-
|
|
10384
|
+
fs71.write(this.fd, this._writingBuf, release);
|
|
10322
10385
|
}
|
|
10323
10386
|
}
|
|
10324
10387
|
function actualClose(sonic) {
|
|
@@ -10334,12 +10397,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10334
10397
|
sonic._lens = [];
|
|
10335
10398
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10336
10399
|
try {
|
|
10337
|
-
|
|
10400
|
+
fs71.fsync(sonic.fd, closeWrapped);
|
|
10338
10401
|
} catch {
|
|
10339
10402
|
}
|
|
10340
10403
|
function closeWrapped() {
|
|
10341
10404
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10342
|
-
|
|
10405
|
+
fs71.close(sonic.fd, done);
|
|
10343
10406
|
} else {
|
|
10344
10407
|
done();
|
|
10345
10408
|
}
|
|
@@ -11016,7 +11079,7 @@ var require_thread_stream = __commonJS({
|
|
|
11016
11079
|
var require_transport = __commonJS({
|
|
11017
11080
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/lib/transport.js"(exports2, module2) {
|
|
11018
11081
|
"use strict";
|
|
11019
|
-
var { createRequire } = require("module");
|
|
11082
|
+
var { createRequire: createRequire2 } = require("module");
|
|
11020
11083
|
var getCallers = require_caller();
|
|
11021
11084
|
var { join: join16, isAbsolute: isAbsolute2, sep: sep3 } = require("path");
|
|
11022
11085
|
var sleep2 = require_atomic_sleep();
|
|
@@ -11127,7 +11190,7 @@ var require_transport = __commonJS({
|
|
|
11127
11190
|
for (const filePath of callers) {
|
|
11128
11191
|
try {
|
|
11129
11192
|
const context = filePath === "node:repl" ? process.cwd() + sep3 : filePath;
|
|
11130
|
-
fixTarget2 =
|
|
11193
|
+
fixTarget2 = createRequire2(context).resolve(origin);
|
|
11131
11194
|
break;
|
|
11132
11195
|
} catch (err) {
|
|
11133
11196
|
continue;
|
|
@@ -11549,12 +11612,12 @@ var require_levels = __commonJS({
|
|
|
11549
11612
|
function genLsCache(instance) {
|
|
11550
11613
|
const formatter = instance[formattersSym].level;
|
|
11551
11614
|
const { labels } = instance.levels;
|
|
11552
|
-
const
|
|
11615
|
+
const cache2 = {};
|
|
11553
11616
|
for (const label in labels) {
|
|
11554
11617
|
const level = formatter(labels[label], Number(label));
|
|
11555
|
-
|
|
11618
|
+
cache2[label] = JSON.stringify(level).slice(0, -1);
|
|
11556
11619
|
}
|
|
11557
|
-
instance[lsCacheSym] =
|
|
11620
|
+
instance[lsCacheSym] = cache2;
|
|
11558
11621
|
return instance;
|
|
11559
11622
|
}
|
|
11560
11623
|
function isStandardLevel(level, useOnlyCustomLevels) {
|
|
@@ -12703,7 +12766,7 @@ var require_multistream = __commonJS({
|
|
|
12703
12766
|
var require_pino = __commonJS({
|
|
12704
12767
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
12705
12768
|
"use strict";
|
|
12706
|
-
var
|
|
12769
|
+
var os25 = require("os");
|
|
12707
12770
|
var stdSerializers = require_pino_std_serializers();
|
|
12708
12771
|
var caller = require_caller();
|
|
12709
12772
|
var redaction = require_redaction();
|
|
@@ -12750,7 +12813,7 @@ var require_pino = __commonJS({
|
|
|
12750
12813
|
} = symbols;
|
|
12751
12814
|
var { epochTime, nullTime } = time;
|
|
12752
12815
|
var { pid } = process;
|
|
12753
|
-
var hostname =
|
|
12816
|
+
var hostname = os25.hostname();
|
|
12754
12817
|
var defaultErrorSerializer = stdSerializers.err;
|
|
12755
12818
|
var defaultOptions2 = {
|
|
12756
12819
|
level: "info",
|
|
@@ -13474,11 +13537,11 @@ var init_lib = __esm({
|
|
|
13474
13537
|
}
|
|
13475
13538
|
}
|
|
13476
13539
|
},
|
|
13477
|
-
addToPath: function addToPath(
|
|
13478
|
-
var last =
|
|
13540
|
+
addToPath: function addToPath(path81, added, removed, oldPosInc, options) {
|
|
13541
|
+
var last = path81.lastComponent;
|
|
13479
13542
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13480
13543
|
return {
|
|
13481
|
-
oldPos:
|
|
13544
|
+
oldPos: path81.oldPos + oldPosInc,
|
|
13482
13545
|
lastComponent: {
|
|
13483
13546
|
count: last.count + 1,
|
|
13484
13547
|
added,
|
|
@@ -13488,7 +13551,7 @@ var init_lib = __esm({
|
|
|
13488
13551
|
};
|
|
13489
13552
|
} else {
|
|
13490
13553
|
return {
|
|
13491
|
-
oldPos:
|
|
13554
|
+
oldPos: path81.oldPos + oldPosInc,
|
|
13492
13555
|
lastComponent: {
|
|
13493
13556
|
count: 1,
|
|
13494
13557
|
added,
|
|
@@ -13997,10 +14060,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
13997
14060
|
const memories = raw.map((m2) => {
|
|
13998
14061
|
if (!m2 || typeof m2 !== "object") return null;
|
|
13999
14062
|
const rec3 = m2;
|
|
14000
|
-
const
|
|
14063
|
+
const path81 = typeof rec3.path === "string" ? rec3.path : null;
|
|
14001
14064
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
14002
|
-
if (!
|
|
14003
|
-
const entry = { path:
|
|
14065
|
+
if (!path81 || content == null) return null;
|
|
14066
|
+
const entry = { path: path81, content };
|
|
14004
14067
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
14005
14068
|
return entry;
|
|
14006
14069
|
}).filter((m2) => m2 !== null);
|
|
@@ -14817,10 +14880,10 @@ function parseAttachment(obj) {
|
|
|
14817
14880
|
const memories = raw.map((m2) => {
|
|
14818
14881
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14819
14882
|
const rec3 = m2;
|
|
14820
|
-
const
|
|
14883
|
+
const path81 = typeof rec3.path === "string" ? rec3.path : null;
|
|
14821
14884
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
14822
|
-
if (!
|
|
14823
|
-
const out = { path:
|
|
14885
|
+
if (!path81 || content == null) return null;
|
|
14886
|
+
const out = { path: path81, content };
|
|
14824
14887
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
14825
14888
|
return out;
|
|
14826
14889
|
}).filter((m2) => m2 !== null);
|
|
@@ -35789,8 +35852,8 @@ var require_utils = __commonJS({
|
|
|
35789
35852
|
var result = transform[inputType][outputType](input);
|
|
35790
35853
|
return result;
|
|
35791
35854
|
};
|
|
35792
|
-
exports2.resolve = function(
|
|
35793
|
-
var parts =
|
|
35855
|
+
exports2.resolve = function(path81) {
|
|
35856
|
+
var parts = path81.split("/");
|
|
35794
35857
|
var result = [];
|
|
35795
35858
|
for (var index = 0; index < parts.length; index++) {
|
|
35796
35859
|
var part = parts[index];
|
|
@@ -41217,10 +41280,10 @@ var require_ZipFileWorker = __commonJS({
|
|
|
41217
41280
|
}
|
|
41218
41281
|
return hex;
|
|
41219
41282
|
};
|
|
41220
|
-
var generateUnixExternalFileAttr = function(unixPermissions,
|
|
41283
|
+
var generateUnixExternalFileAttr = function(unixPermissions, isDir3) {
|
|
41221
41284
|
var result = unixPermissions;
|
|
41222
41285
|
if (!unixPermissions) {
|
|
41223
|
-
result =
|
|
41286
|
+
result = isDir3 ? 16893 : 33204;
|
|
41224
41287
|
}
|
|
41225
41288
|
return (result & 65535) << 16;
|
|
41226
41289
|
};
|
|
@@ -41643,18 +41706,18 @@ var require_object = __commonJS({
|
|
|
41643
41706
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
41644
41707
|
this.files[name] = object;
|
|
41645
41708
|
};
|
|
41646
|
-
var parentFolder = function(
|
|
41647
|
-
if (
|
|
41648
|
-
|
|
41709
|
+
var parentFolder = function(path81) {
|
|
41710
|
+
if (path81.slice(-1) === "/") {
|
|
41711
|
+
path81 = path81.substring(0, path81.length - 1);
|
|
41649
41712
|
}
|
|
41650
|
-
var lastSlash =
|
|
41651
|
-
return lastSlash > 0 ?
|
|
41713
|
+
var lastSlash = path81.lastIndexOf("/");
|
|
41714
|
+
return lastSlash > 0 ? path81.substring(0, lastSlash) : "";
|
|
41652
41715
|
};
|
|
41653
|
-
var forceTrailingSlash = function(
|
|
41654
|
-
if (
|
|
41655
|
-
|
|
41716
|
+
var forceTrailingSlash = function(path81) {
|
|
41717
|
+
if (path81.slice(-1) !== "/") {
|
|
41718
|
+
path81 += "/";
|
|
41656
41719
|
}
|
|
41657
|
-
return
|
|
41720
|
+
return path81;
|
|
41658
41721
|
};
|
|
41659
41722
|
var folderAdd = function(name, createFolders) {
|
|
41660
41723
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -42656,7 +42719,7 @@ var require_lib3 = __commonJS({
|
|
|
42656
42719
|
// src/run-case/recorder.ts
|
|
42657
42720
|
function startRunCaseRecorder(opts) {
|
|
42658
42721
|
const now = opts.now ?? Date.now;
|
|
42659
|
-
const dir =
|
|
42722
|
+
const dir = import_node_path68.default.dirname(opts.recordPath);
|
|
42660
42723
|
let stream = null;
|
|
42661
42724
|
let closing = false;
|
|
42662
42725
|
let closedSettled = false;
|
|
@@ -42670,8 +42733,8 @@ function startRunCaseRecorder(opts) {
|
|
|
42670
42733
|
});
|
|
42671
42734
|
const ensureStream = () => {
|
|
42672
42735
|
if (stream) return stream;
|
|
42673
|
-
|
|
42674
|
-
stream =
|
|
42736
|
+
import_node_fs52.default.mkdirSync(dir, { recursive: true });
|
|
42737
|
+
stream = import_node_fs52.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
42675
42738
|
stream.on("close", () => closedResolve());
|
|
42676
42739
|
return stream;
|
|
42677
42740
|
};
|
|
@@ -42696,12 +42759,12 @@ function startRunCaseRecorder(opts) {
|
|
|
42696
42759
|
};
|
|
42697
42760
|
return { tap, close, closed };
|
|
42698
42761
|
}
|
|
42699
|
-
var
|
|
42762
|
+
var import_node_fs52, import_node_path68;
|
|
42700
42763
|
var init_recorder = __esm({
|
|
42701
42764
|
"src/run-case/recorder.ts"() {
|
|
42702
42765
|
"use strict";
|
|
42703
|
-
|
|
42704
|
-
|
|
42766
|
+
import_node_fs52 = __toESM(require("fs"), 1);
|
|
42767
|
+
import_node_path68 = __toESM(require("path"), 1);
|
|
42705
42768
|
}
|
|
42706
42769
|
});
|
|
42707
42770
|
|
|
@@ -42744,7 +42807,7 @@ var init_wire = __esm({
|
|
|
42744
42807
|
// src/run-case/controller.ts
|
|
42745
42808
|
async function runController(opts) {
|
|
42746
42809
|
const now = opts.now ?? Date.now;
|
|
42747
|
-
const cwd = opts.cwd ?? (0,
|
|
42810
|
+
const cwd = opts.cwd ?? (0, import_node_fs53.mkdtempSync)(import_node_path69.default.join(import_node_os24.default.tmpdir(), "clawd-runcase-"));
|
|
42748
42811
|
const ownsCwd = opts.cwd === void 0;
|
|
42749
42812
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
42750
42813
|
const spawnCtx = { cwd };
|
|
@@ -42905,19 +42968,19 @@ async function runController(opts) {
|
|
|
42905
42968
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
42906
42969
|
if (ownsCwd) {
|
|
42907
42970
|
try {
|
|
42908
|
-
(0,
|
|
42971
|
+
(0, import_node_fs53.rmSync)(cwd, { recursive: true, force: true });
|
|
42909
42972
|
} catch {
|
|
42910
42973
|
}
|
|
42911
42974
|
}
|
|
42912
42975
|
return exitCode ?? 0;
|
|
42913
42976
|
}
|
|
42914
|
-
var
|
|
42977
|
+
var import_node_fs53, import_node_os24, import_node_path69;
|
|
42915
42978
|
var init_controller = __esm({
|
|
42916
42979
|
"src/run-case/controller.ts"() {
|
|
42917
42980
|
"use strict";
|
|
42918
|
-
|
|
42919
|
-
|
|
42920
|
-
|
|
42981
|
+
import_node_fs53 = require("fs");
|
|
42982
|
+
import_node_os24 = __toESM(require("os"), 1);
|
|
42983
|
+
import_node_path69 = __toESM(require("path"), 1);
|
|
42921
42984
|
init_claude();
|
|
42922
42985
|
init_stdout_splitter();
|
|
42923
42986
|
init_permission_stdio();
|
|
@@ -43192,9 +43255,9 @@ Env (advanced):
|
|
|
43192
43255
|
`;
|
|
43193
43256
|
|
|
43194
43257
|
// src/index.ts
|
|
43195
|
-
var
|
|
43196
|
-
var
|
|
43197
|
-
var
|
|
43258
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
43259
|
+
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
43260
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
43198
43261
|
|
|
43199
43262
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
43200
43263
|
var byteToHex = [];
|
|
@@ -49444,8 +49507,8 @@ function turnStartInput(text) {
|
|
|
49444
49507
|
const items = [];
|
|
49445
49508
|
let leftover = text;
|
|
49446
49509
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
49447
|
-
const [marker, name,
|
|
49448
|
-
items.push({ type: "skill", name, path:
|
|
49510
|
+
const [marker, name, path81] = m2;
|
|
49511
|
+
items.push({ type: "skill", name, path: path81 });
|
|
49449
49512
|
leftover = leftover.replace(marker, "");
|
|
49450
49513
|
}
|
|
49451
49514
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -53394,13 +53457,13 @@ function mapSkillsListResponse(res) {
|
|
|
53394
53457
|
const r = s ?? {};
|
|
53395
53458
|
const name = str3(r.name);
|
|
53396
53459
|
if (!name) continue;
|
|
53397
|
-
const
|
|
53460
|
+
const path81 = str3(r.path);
|
|
53398
53461
|
const description = str3(r.description);
|
|
53399
53462
|
const isPlugin = name.includes(":");
|
|
53400
53463
|
out.push({
|
|
53401
53464
|
name,
|
|
53402
53465
|
source: isPlugin ? "plugin" : "project",
|
|
53403
|
-
...
|
|
53466
|
+
...path81 ? { path: path81 } : {},
|
|
53404
53467
|
...description ? { description } : {},
|
|
53405
53468
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
53406
53469
|
});
|
|
@@ -57215,24 +57278,34 @@ var import_node_fs42 = __toESM(require("fs"), 1);
|
|
|
57215
57278
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
57216
57279
|
var import_node_path47 = __toESM(require("path"), 1);
|
|
57217
57280
|
var PROFILE_FILENAME = "profile.json";
|
|
57218
|
-
function
|
|
57219
|
-
|
|
57220
|
-
|
|
57281
|
+
function profilePath(dataDir) {
|
|
57282
|
+
return import_node_path47.default.join(dataDir, PROFILE_FILENAME);
|
|
57283
|
+
}
|
|
57284
|
+
function loadOwnerProfile(dataDir) {
|
|
57221
57285
|
let raw;
|
|
57222
57286
|
try {
|
|
57223
|
-
raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
|
|
57287
|
+
raw = import_node_fs42.default.readFileSync(profilePath(dataDir), "utf8");
|
|
57224
57288
|
} catch {
|
|
57225
|
-
return
|
|
57289
|
+
return {};
|
|
57226
57290
|
}
|
|
57227
|
-
let parsed;
|
|
57228
57291
|
try {
|
|
57229
|
-
parsed = JSON.parse(raw);
|
|
57292
|
+
const parsed = JSON.parse(raw);
|
|
57293
|
+
if (parsed != null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
57294
|
+
return parsed;
|
|
57295
|
+
}
|
|
57230
57296
|
} catch (err) {
|
|
57231
|
-
console.warn(`[owner-profile] ${PROFILE_FILENAME} parse failed,
|
|
57232
|
-
return fallback;
|
|
57297
|
+
console.warn(`[owner-profile] ${PROFILE_FILENAME} parse failed, treating as empty:`, err);
|
|
57233
57298
|
}
|
|
57234
|
-
|
|
57235
|
-
|
|
57299
|
+
return {};
|
|
57300
|
+
}
|
|
57301
|
+
function patchOwnerProfile(dataDir, patch) {
|
|
57302
|
+
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
57303
|
+
import_node_fs42.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
57304
|
+
return merged;
|
|
57305
|
+
}
|
|
57306
|
+
function loadOwnerDisplayName(dataDir) {
|
|
57307
|
+
const fallback = import_node_os15.default.userInfo().username;
|
|
57308
|
+
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
57236
57309
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
57237
57310
|
if (displayName !== void 0) {
|
|
57238
57311
|
console.warn(`[owner-profile] displayName must be non-empty string, falling back to OS username`);
|
|
@@ -57428,9 +57501,9 @@ var CentralClientError = class extends Error {
|
|
|
57428
57501
|
code;
|
|
57429
57502
|
cause;
|
|
57430
57503
|
};
|
|
57431
|
-
async function centralRequest(opts,
|
|
57504
|
+
async function centralRequest(opts, path81, init) {
|
|
57432
57505
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
57433
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
57506
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path81}`;
|
|
57434
57507
|
const ctrl = new AbortController();
|
|
57435
57508
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
57436
57509
|
let res;
|
|
@@ -57737,6 +57810,321 @@ function forkSession(input) {
|
|
|
57737
57810
|
return { forkedToolSessionId, forkedFilePath };
|
|
57738
57811
|
}
|
|
57739
57812
|
|
|
57813
|
+
// src/session/external-scan.ts
|
|
57814
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
57815
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
57816
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
57817
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
57818
|
+
var import_node_module = require("module");
|
|
57819
|
+
var import_node_child_process11 = require("child_process");
|
|
57820
|
+
var import_meta4 = {};
|
|
57821
|
+
function defaultRoots() {
|
|
57822
|
+
const home = import_node_os17.default.homedir();
|
|
57823
|
+
return {
|
|
57824
|
+
claudeProjectsDir: import_node_path50.default.join(home, ".claude", "projects"),
|
|
57825
|
+
codexDir: import_node_path50.default.join(home, ".codex"),
|
|
57826
|
+
clawdDir: import_node_path50.default.join(home, ".clawd")
|
|
57827
|
+
};
|
|
57828
|
+
}
|
|
57829
|
+
function width(s) {
|
|
57830
|
+
let w2 = 0;
|
|
57831
|
+
for (const ch of s) w2 += /[ᄀ-ᅟ⺀-가-힣豈-︰-﹏-⦆¢-₩]/.test(ch) ? 2 : 1;
|
|
57832
|
+
return w2;
|
|
57833
|
+
}
|
|
57834
|
+
function clipW(text, n) {
|
|
57835
|
+
const s = String(text ?? "").split(/\s+/).filter(Boolean).join(" ");
|
|
57836
|
+
if (width(s) <= n) return s;
|
|
57837
|
+
let out = "";
|
|
57838
|
+
let w2 = 0;
|
|
57839
|
+
for (const ch of s) {
|
|
57840
|
+
const cw = width(ch);
|
|
57841
|
+
if (w2 + cw > n - 1) break;
|
|
57842
|
+
out += ch;
|
|
57843
|
+
w2 += cw;
|
|
57844
|
+
}
|
|
57845
|
+
return out + "\u2026";
|
|
57846
|
+
}
|
|
57847
|
+
function toMs(v2) {
|
|
57848
|
+
const n = Number(v2 || 0);
|
|
57849
|
+
return n > 1e11 ? Math.round(n) : Math.round(n * 1e3);
|
|
57850
|
+
}
|
|
57851
|
+
function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
|
|
57852
|
+
let entries;
|
|
57853
|
+
try {
|
|
57854
|
+
entries = import_node_fs45.default.readdirSync(dir, { withFileTypes: true });
|
|
57855
|
+
} catch {
|
|
57856
|
+
return out;
|
|
57857
|
+
}
|
|
57858
|
+
for (const e of entries) {
|
|
57859
|
+
const full = import_node_path50.default.join(dir, e.name);
|
|
57860
|
+
if (e.isDirectory()) {
|
|
57861
|
+
if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
|
|
57862
|
+
} else if (e.isFile()) {
|
|
57863
|
+
out.push(full);
|
|
57864
|
+
}
|
|
57865
|
+
}
|
|
57866
|
+
return out;
|
|
57867
|
+
}
|
|
57868
|
+
async function* jsonLines(file) {
|
|
57869
|
+
let raw;
|
|
57870
|
+
try {
|
|
57871
|
+
raw = await import_promises6.default.readFile(file, "utf8");
|
|
57872
|
+
} catch {
|
|
57873
|
+
return;
|
|
57874
|
+
}
|
|
57875
|
+
for (const line of raw.split("\n")) {
|
|
57876
|
+
const t = line.trim();
|
|
57877
|
+
if (!t) continue;
|
|
57878
|
+
try {
|
|
57879
|
+
yield JSON.parse(t);
|
|
57880
|
+
} catch {
|
|
57881
|
+
}
|
|
57882
|
+
}
|
|
57883
|
+
}
|
|
57884
|
+
function userText(msg) {
|
|
57885
|
+
const content = msg && typeof msg === "object" ? msg.content : null;
|
|
57886
|
+
if (typeof content === "string") return content;
|
|
57887
|
+
if (Array.isArray(content)) {
|
|
57888
|
+
return content.map((b2) => b2 && b2.type === "text" ? String(b2.text ?? "") : "").join("");
|
|
57889
|
+
}
|
|
57890
|
+
return "";
|
|
57891
|
+
}
|
|
57892
|
+
function isDir2(p2) {
|
|
57893
|
+
try {
|
|
57894
|
+
return import_node_fs45.default.statSync(p2).isDirectory();
|
|
57895
|
+
} catch {
|
|
57896
|
+
return false;
|
|
57897
|
+
}
|
|
57898
|
+
}
|
|
57899
|
+
async function scanClaude(roots) {
|
|
57900
|
+
const out = [];
|
|
57901
|
+
let dirs;
|
|
57902
|
+
try {
|
|
57903
|
+
dirs = import_node_fs45.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
57904
|
+
} catch {
|
|
57905
|
+
return out;
|
|
57906
|
+
}
|
|
57907
|
+
for (const d of dirs) {
|
|
57908
|
+
if (!d.isDirectory()) continue;
|
|
57909
|
+
let files;
|
|
57910
|
+
try {
|
|
57911
|
+
files = import_node_fs45.default.readdirSync(import_node_path50.default.join(roots.claudeProjectsDir, d.name));
|
|
57912
|
+
} catch {
|
|
57913
|
+
continue;
|
|
57914
|
+
}
|
|
57915
|
+
for (const name of files) {
|
|
57916
|
+
if (!name.endsWith(".jsonl")) continue;
|
|
57917
|
+
const file = import_node_path50.default.join(roots.claudeProjectsDir, d.name, name);
|
|
57918
|
+
let st;
|
|
57919
|
+
try {
|
|
57920
|
+
st = import_node_fs45.default.statSync(file);
|
|
57921
|
+
} catch {
|
|
57922
|
+
continue;
|
|
57923
|
+
}
|
|
57924
|
+
let cwd = "";
|
|
57925
|
+
let title = "";
|
|
57926
|
+
let firstUser = "";
|
|
57927
|
+
let turns = 0;
|
|
57928
|
+
let firstTs = 0;
|
|
57929
|
+
let lastTs = 0;
|
|
57930
|
+
let hasMainLine = false;
|
|
57931
|
+
for await (const rec3 of jsonLines(file)) {
|
|
57932
|
+
if (!cwd && typeof rec3.cwd === "string") cwd = rec3.cwd;
|
|
57933
|
+
if (typeof rec3.timestamp === "string") {
|
|
57934
|
+
const t = Date.parse(rec3.timestamp);
|
|
57935
|
+
if (Number.isFinite(t)) {
|
|
57936
|
+
firstTs ||= t;
|
|
57937
|
+
lastTs = t;
|
|
57938
|
+
}
|
|
57939
|
+
}
|
|
57940
|
+
if (rec3.type === "ai-title" && rec3.aiTitle) {
|
|
57941
|
+
title = String(rec3.aiTitle);
|
|
57942
|
+
continue;
|
|
57943
|
+
}
|
|
57944
|
+
if (rec3.type !== "user" && rec3.type !== "assistant") continue;
|
|
57945
|
+
if (!rec3.isSidechain) hasMainLine = true;
|
|
57946
|
+
if (rec3.type !== "user" || rec3.isSidechain || rec3.isMeta) continue;
|
|
57947
|
+
const text = userText(rec3.message || {});
|
|
57948
|
+
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
57949
|
+
turns += 1;
|
|
57950
|
+
firstUser ||= text;
|
|
57951
|
+
}
|
|
57952
|
+
const cand = {
|
|
57953
|
+
tool: "claude",
|
|
57954
|
+
toolSessionId: name.slice(0, -".jsonl".length),
|
|
57955
|
+
cwd,
|
|
57956
|
+
label: clipW(title || firstUser, 56),
|
|
57957
|
+
turns,
|
|
57958
|
+
createdMs: firstTs || st.mtimeMs,
|
|
57959
|
+
updatedMs: lastTs || st.mtimeMs,
|
|
57960
|
+
skip: ""
|
|
57961
|
+
};
|
|
57962
|
+
if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
|
|
57963
|
+
else if (!cwd) cand.skip = "\u65E0 cwd";
|
|
57964
|
+
out.push(cand);
|
|
57965
|
+
}
|
|
57966
|
+
}
|
|
57967
|
+
return out;
|
|
57968
|
+
}
|
|
57969
|
+
async function countCodexTurns(rolloutPath) {
|
|
57970
|
+
if (!rolloutPath || !import_node_fs45.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
57971
|
+
let turns = 0;
|
|
57972
|
+
let first = "";
|
|
57973
|
+
for await (const rec3 of jsonLines(rolloutPath)) {
|
|
57974
|
+
const p2 = rec3.payload || {};
|
|
57975
|
+
if (p2.type !== "message" || p2.role !== "user") continue;
|
|
57976
|
+
const text = (p2.content || []).map((b2) => String(b2 && b2.text || "")).join("");
|
|
57977
|
+
if (!text.trim() || text.trimStart().startsWith("<")) continue;
|
|
57978
|
+
turns += 1;
|
|
57979
|
+
first ||= text;
|
|
57980
|
+
}
|
|
57981
|
+
return { turns, first };
|
|
57982
|
+
}
|
|
57983
|
+
function readCodexThreads(db) {
|
|
57984
|
+
const COLS = ["id", "cwd", "created_at", "updated_at", "name", "title", "preview", "first_user_message", "archived", "rollout_path"];
|
|
57985
|
+
try {
|
|
57986
|
+
const { DatabaseSync } = (0, import_node_module.createRequire)(import_meta4.url)("node:sqlite");
|
|
57987
|
+
const conn = new DatabaseSync(db, { readOnly: true });
|
|
57988
|
+
try {
|
|
57989
|
+
const have = new Set(
|
|
57990
|
+
conn.prepare("PRAGMA table_info(threads)").all().map((r) => r.name)
|
|
57991
|
+
);
|
|
57992
|
+
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
57993
|
+
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
57994
|
+
return conn.prepare(`SELECT ${sel} FROM threads`).all();
|
|
57995
|
+
} finally {
|
|
57996
|
+
conn.close();
|
|
57997
|
+
}
|
|
57998
|
+
} catch {
|
|
57999
|
+
}
|
|
58000
|
+
try {
|
|
58001
|
+
const info = (0, import_node_child_process11.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
58002
|
+
if (info.status !== 0) return null;
|
|
58003
|
+
const have = new Set(
|
|
58004
|
+
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
58005
|
+
);
|
|
58006
|
+
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
58007
|
+
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
58008
|
+
const res = (0, import_node_child_process11.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
58009
|
+
encoding: "utf8",
|
|
58010
|
+
maxBuffer: 64 * 1024 * 1024
|
|
58011
|
+
});
|
|
58012
|
+
if (res.status !== 0 || !res.stdout.trim()) return null;
|
|
58013
|
+
return JSON.parse(res.stdout);
|
|
58014
|
+
} catch {
|
|
58015
|
+
return null;
|
|
58016
|
+
}
|
|
58017
|
+
}
|
|
58018
|
+
async function codexFromRows(rows) {
|
|
58019
|
+
const out = [];
|
|
58020
|
+
for (const r of rows) {
|
|
58021
|
+
const updatedMs = toMs(r.updated_at);
|
|
58022
|
+
const { turns, first } = await countCodexTurns(String(r.rollout_path || ""));
|
|
58023
|
+
const label = clipW(r.name || r.title || r.preview || r.first_user_message || first, 56);
|
|
58024
|
+
const cand = {
|
|
58025
|
+
tool: "codex",
|
|
58026
|
+
toolSessionId: String(r.id),
|
|
58027
|
+
cwd: String(r.cwd || ""),
|
|
58028
|
+
label,
|
|
58029
|
+
turns,
|
|
58030
|
+
createdMs: toMs(r.created_at) || updatedMs,
|
|
58031
|
+
updatedMs,
|
|
58032
|
+
skip: ""
|
|
58033
|
+
};
|
|
58034
|
+
if (r.archived) cand.skip = "\u5DF2\u5F52\u6863";
|
|
58035
|
+
else if (!label) cand.skip = "\u7A7A\u4F1A\u8BDD";
|
|
58036
|
+
out.push(cand);
|
|
58037
|
+
}
|
|
58038
|
+
return out;
|
|
58039
|
+
}
|
|
58040
|
+
async function scanCodexRollouts(roots) {
|
|
58041
|
+
const out = [];
|
|
58042
|
+
for (const file of listFiles(import_node_path50.default.join(roots.codexDir, "sessions"))) {
|
|
58043
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
58044
|
+
let st;
|
|
58045
|
+
try {
|
|
58046
|
+
st = import_node_fs45.default.statSync(file);
|
|
58047
|
+
} catch {
|
|
58048
|
+
continue;
|
|
58049
|
+
}
|
|
58050
|
+
let meta = null;
|
|
58051
|
+
for await (const rec3 of jsonLines(file)) {
|
|
58052
|
+
if (rec3.type === "session_meta") {
|
|
58053
|
+
meta = rec3.payload || {};
|
|
58054
|
+
break;
|
|
58055
|
+
}
|
|
58056
|
+
}
|
|
58057
|
+
const tid = meta && (meta.session_id || meta.id);
|
|
58058
|
+
if (!tid) continue;
|
|
58059
|
+
const { turns, first } = await countCodexTurns(file);
|
|
58060
|
+
const cand = {
|
|
58061
|
+
tool: "codex",
|
|
58062
|
+
toolSessionId: String(tid),
|
|
58063
|
+
cwd: String(meta?.cwd || ""),
|
|
58064
|
+
label: clipW(first, 56),
|
|
58065
|
+
turns,
|
|
58066
|
+
createdMs: st.mtimeMs,
|
|
58067
|
+
updatedMs: st.mtimeMs,
|
|
58068
|
+
skip: ""
|
|
58069
|
+
};
|
|
58070
|
+
if (!cand.cwd) cand.skip = "\u65E0 cwd";
|
|
58071
|
+
out.push(cand);
|
|
58072
|
+
}
|
|
58073
|
+
return out;
|
|
58074
|
+
}
|
|
58075
|
+
async function scanCodex(roots) {
|
|
58076
|
+
let dbs = [];
|
|
58077
|
+
try {
|
|
58078
|
+
dbs = import_node_fs45.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path50.default.join(roots.codexDir, n));
|
|
58079
|
+
} catch {
|
|
58080
|
+
}
|
|
58081
|
+
if (dbs.length) {
|
|
58082
|
+
const rows = readCodexThreads(dbs[dbs.length - 1]);
|
|
58083
|
+
if (rows) return codexFromRows(rows);
|
|
58084
|
+
}
|
|
58085
|
+
return scanCodexRollouts(roots);
|
|
58086
|
+
}
|
|
58087
|
+
async function scanExternalSessions(rootsIn) {
|
|
58088
|
+
const roots = { ...defaultRoots(), ...rootsIn };
|
|
58089
|
+
const personaRoot = import_node_path50.default.join(roots.clawdDir, "personas");
|
|
58090
|
+
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
58091
|
+
const out = [];
|
|
58092
|
+
for (const c of all) {
|
|
58093
|
+
if (c.skip) continue;
|
|
58094
|
+
if (c.turns < 1) continue;
|
|
58095
|
+
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
58096
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path50.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path50.default.sep)) {
|
|
58097
|
+
continue;
|
|
58098
|
+
}
|
|
58099
|
+
out.push({
|
|
58100
|
+
tool: c.tool,
|
|
58101
|
+
cwd: c.cwd,
|
|
58102
|
+
toolSessionId: c.toolSessionId,
|
|
58103
|
+
...c.label ? { label: c.label } : {},
|
|
58104
|
+
createdAt: new Date(c.createdMs).toISOString(),
|
|
58105
|
+
updatedAt: new Date(c.updatedMs).toISOString(),
|
|
58106
|
+
turns: c.turns
|
|
58107
|
+
});
|
|
58108
|
+
}
|
|
58109
|
+
return out;
|
|
58110
|
+
}
|
|
58111
|
+
|
|
58112
|
+
// src/session/import-ledger.ts
|
|
58113
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
58114
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58115
|
+
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
58116
|
+
function appendImportLedger(dataDir, entry) {
|
|
58117
|
+
const file = import_node_path51.default.join(dataDir, LEDGER_FILENAME);
|
|
58118
|
+
let entries = [];
|
|
58119
|
+
try {
|
|
58120
|
+
const parsed = JSON.parse(import_node_fs46.default.readFileSync(file, "utf8"));
|
|
58121
|
+
if (Array.isArray(parsed)) entries = parsed;
|
|
58122
|
+
} catch {
|
|
58123
|
+
}
|
|
58124
|
+
entries.push(entry);
|
|
58125
|
+
import_node_fs46.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
58126
|
+
}
|
|
58127
|
+
|
|
57740
58128
|
// src/handlers/session.ts
|
|
57741
58129
|
init_protocol();
|
|
57742
58130
|
function buildSessionHandlers(deps) {
|
|
@@ -57809,8 +58197,30 @@ function buildSessionHandlers(deps) {
|
|
|
57809
58197
|
creatorDisplayName,
|
|
57810
58198
|
creatorFeishuUnionId
|
|
57811
58199
|
);
|
|
58200
|
+
if (deps.dataDir && !("alreadyLinked" in response)) {
|
|
58201
|
+
appendImportLedger(deps.dataDir, {
|
|
58202
|
+
sessionId: String(response.sessionId),
|
|
58203
|
+
tool: args.tool,
|
|
58204
|
+
...args.label ? { label: args.label } : {},
|
|
58205
|
+
toolSessionId: args.toolSessionId,
|
|
58206
|
+
...args.ownerPersonaId ? { ownerPersonaId: args.ownerPersonaId } : {}
|
|
58207
|
+
});
|
|
58208
|
+
}
|
|
57812
58209
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
57813
58210
|
};
|
|
58211
|
+
const externalScan = async (frame, _client, ctx) => {
|
|
58212
|
+
if (ctx && ctx.principal.kind !== "owner") {
|
|
58213
|
+
throw new ClawdError(
|
|
58214
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
58215
|
+
`principal ${ctx.principal.kind}:${ctx.principal.id} cannot session:externalScan`
|
|
58216
|
+
);
|
|
58217
|
+
}
|
|
58218
|
+
parseArgs2(SessionExternalScanArgs, frame, "session:externalScan args");
|
|
58219
|
+
const owned = manager.list().response.sessions;
|
|
58220
|
+
const linked = new Set(owned.map((f) => f.toolSessionId).filter(Boolean));
|
|
58221
|
+
const candidates = (await scanExternalSessions()).filter((c) => !linked.has(c.toolSessionId));
|
|
58222
|
+
return { response: { candidates } };
|
|
58223
|
+
};
|
|
57814
58224
|
const list = async (frame, _client, ctx) => {
|
|
57815
58225
|
const args = SessionListArgs.parse(frame ?? {});
|
|
57816
58226
|
const narrow = (sessions) => {
|
|
@@ -58151,6 +58561,7 @@ function buildSessionHandlers(deps) {
|
|
|
58151
58561
|
};
|
|
58152
58562
|
return {
|
|
58153
58563
|
"session:create": create,
|
|
58564
|
+
"session:externalScan": externalScan,
|
|
58154
58565
|
"session:importExternal": importExternal,
|
|
58155
58566
|
"session:list": list,
|
|
58156
58567
|
"session:get": get,
|
|
@@ -58199,7 +58610,7 @@ function buildPermissionHandlers(deps) {
|
|
|
58199
58610
|
}
|
|
58200
58611
|
|
|
58201
58612
|
// src/handlers/history.ts
|
|
58202
|
-
var
|
|
58613
|
+
var path62 = __toESM(require("path"), 1);
|
|
58203
58614
|
init_protocol();
|
|
58204
58615
|
|
|
58205
58616
|
// src/session/recent-dirs.ts
|
|
@@ -58217,7 +58628,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
58217
58628
|
}
|
|
58218
58629
|
|
|
58219
58630
|
// src/permission/persona-paths.ts
|
|
58220
|
-
var
|
|
58631
|
+
var path61 = __toESM(require("path"), 1);
|
|
58221
58632
|
function getAllowedPersonaIds(grants, action) {
|
|
58222
58633
|
const ids = /* @__PURE__ */ new Set();
|
|
58223
58634
|
for (const g2 of grants) {
|
|
@@ -58230,42 +58641,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
58230
58641
|
return ids;
|
|
58231
58642
|
}
|
|
58232
58643
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
58233
|
-
const target =
|
|
58644
|
+
const target = path61.resolve(absPath);
|
|
58234
58645
|
if (userWorkDir) {
|
|
58235
|
-
const u =
|
|
58236
|
-
const usep = u.endsWith(
|
|
58646
|
+
const u = path61.resolve(userWorkDir);
|
|
58647
|
+
const usep = u.endsWith(path61.sep) ? "" : path61.sep;
|
|
58237
58648
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
58238
58649
|
}
|
|
58239
|
-
const root =
|
|
58240
|
-
const sep3 = root.endsWith(
|
|
58650
|
+
const root = path61.resolve(personaRoot);
|
|
58651
|
+
const sep3 = root.endsWith(path61.sep) ? "" : path61.sep;
|
|
58241
58652
|
if (!target.startsWith(root + sep3)) return false;
|
|
58242
|
-
const rel =
|
|
58653
|
+
const rel = path61.relative(root, target);
|
|
58243
58654
|
if (!rel || rel.startsWith("..")) return false;
|
|
58244
|
-
const personaId2 = rel.split(
|
|
58655
|
+
const personaId2 = rel.split(path61.sep)[0];
|
|
58245
58656
|
if (!personaId2) return false;
|
|
58246
58657
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
58247
58658
|
if (allowed === "*") return true;
|
|
58248
58659
|
return allowed.has(personaId2);
|
|
58249
58660
|
}
|
|
58250
58661
|
function personaIdFromPath(absPath, personaRoot) {
|
|
58251
|
-
const root =
|
|
58252
|
-
const target =
|
|
58253
|
-
const sep3 = root.endsWith(
|
|
58662
|
+
const root = path61.resolve(personaRoot);
|
|
58663
|
+
const target = path61.resolve(absPath);
|
|
58664
|
+
const sep3 = root.endsWith(path61.sep) ? "" : path61.sep;
|
|
58254
58665
|
if (!target.startsWith(root + sep3)) return null;
|
|
58255
|
-
const rel =
|
|
58666
|
+
const rel = path61.relative(root, target);
|
|
58256
58667
|
if (!rel || rel.startsWith("..")) return null;
|
|
58257
|
-
const id = rel.split(
|
|
58668
|
+
const id = rel.split(path61.sep)[0];
|
|
58258
58669
|
return id || null;
|
|
58259
58670
|
}
|
|
58260
58671
|
function isPathWithin(dir, absPath) {
|
|
58261
|
-
const d =
|
|
58262
|
-
const t =
|
|
58263
|
-
const sep3 = d.endsWith(
|
|
58672
|
+
const d = path61.resolve(dir);
|
|
58673
|
+
const t = path61.resolve(absPath);
|
|
58674
|
+
const sep3 = d.endsWith(path61.sep) ? "" : path61.sep;
|
|
58264
58675
|
return t === d || t.startsWith(d + sep3);
|
|
58265
58676
|
}
|
|
58266
58677
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
58267
58678
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
58268
|
-
return personaIdFromPath(
|
|
58679
|
+
return personaIdFromPath(path61.resolve(absPath), personaRoot) === personaId2;
|
|
58269
58680
|
}
|
|
58270
58681
|
|
|
58271
58682
|
// src/handlers/history.ts
|
|
@@ -58317,7 +58728,7 @@ function buildHistoryHandlers(deps) {
|
|
|
58317
58728
|
if (!pid) return false;
|
|
58318
58729
|
return isGuestPathAllowed(
|
|
58319
58730
|
ctx.grants,
|
|
58320
|
-
|
|
58731
|
+
path62.join(personaRoot, pid),
|
|
58321
58732
|
personaRoot,
|
|
58322
58733
|
"read",
|
|
58323
58734
|
userWorkDir
|
|
@@ -58329,7 +58740,7 @@ function buildHistoryHandlers(deps) {
|
|
|
58329
58740
|
};
|
|
58330
58741
|
const list = async (frame, _client, ctx) => {
|
|
58331
58742
|
const args = HistoryListArgs.parse(frame);
|
|
58332
|
-
assertGuestPath(ctx,
|
|
58743
|
+
assertGuestPath(ctx, path62.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
58333
58744
|
const sessions = await history.listSessions(args);
|
|
58334
58745
|
return { response: { type: "history:list", sessions } };
|
|
58335
58746
|
};
|
|
@@ -58373,14 +58784,14 @@ function buildHistoryHandlers(deps) {
|
|
|
58373
58784
|
};
|
|
58374
58785
|
const subagents = async (frame, _client, ctx) => {
|
|
58375
58786
|
const args = HistorySubagentsArgs.parse(frame);
|
|
58376
|
-
assertGuestPath(ctx,
|
|
58787
|
+
assertGuestPath(ctx, path62.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
58377
58788
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
58378
58789
|
const subs = await history.listSubagents(args);
|
|
58379
58790
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
58380
58791
|
};
|
|
58381
58792
|
const subagentRead = async (frame, _client, ctx) => {
|
|
58382
58793
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
58383
|
-
assertGuestPath(ctx,
|
|
58794
|
+
assertGuestPath(ctx, path62.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
58384
58795
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
58385
58796
|
const res = await history.readSubagent(args);
|
|
58386
58797
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -58390,7 +58801,7 @@ function buildHistoryHandlers(deps) {
|
|
|
58390
58801
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
58391
58802
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
58392
58803
|
const filtered = dirs.filter(
|
|
58393
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
58804
|
+
(d) => isGuestPathAllowed(ctx.grants, path62.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
58394
58805
|
);
|
|
58395
58806
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
58396
58807
|
}
|
|
@@ -58407,8 +58818,8 @@ function buildHistoryHandlers(deps) {
|
|
|
58407
58818
|
}
|
|
58408
58819
|
|
|
58409
58820
|
// src/handlers/workspace.ts
|
|
58410
|
-
var
|
|
58411
|
-
var
|
|
58821
|
+
var path63 = __toESM(require("path"), 1);
|
|
58822
|
+
var os17 = __toESM(require("os"), 1);
|
|
58412
58823
|
init_protocol();
|
|
58413
58824
|
init_protocol();
|
|
58414
58825
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -58448,23 +58859,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
58448
58859
|
const list = async (frame, _client, ctx) => {
|
|
58449
58860
|
const args = WorkspaceListArgs.parse(frame);
|
|
58450
58861
|
const isGuest = ctx?.principal.kind === "guest";
|
|
58451
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
58452
|
-
const resolvedCwd =
|
|
58453
|
-
const target = args.path ?
|
|
58862
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os17.homedir();
|
|
58863
|
+
const resolvedCwd = path63.resolve(args.cwd ?? fallbackCwd);
|
|
58864
|
+
const target = args.path ? path63.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
58454
58865
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
58455
58866
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
58456
58867
|
return { response: { type: "workspace:list", ...res } };
|
|
58457
58868
|
};
|
|
58458
58869
|
const read = async (frame, _client, ctx) => {
|
|
58459
58870
|
const args = WorkspaceReadArgs.parse(frame);
|
|
58460
|
-
const target =
|
|
58871
|
+
const target = path63.isAbsolute(args.path) ? path63.resolve(args.path) : path63.resolve(args.cwd, args.path);
|
|
58461
58872
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
58462
58873
|
const res = workspace.read(args);
|
|
58463
58874
|
return { response: { type: "workspace:read", ...res } };
|
|
58464
58875
|
};
|
|
58465
58876
|
const skillsList = async (frame, _client, ctx) => {
|
|
58466
58877
|
const args = SkillsListArgs.parse(frame);
|
|
58467
|
-
const cwdAbs =
|
|
58878
|
+
const cwdAbs = path63.resolve(args.cwd);
|
|
58468
58879
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
58469
58880
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
58470
58881
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -58476,7 +58887,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
58476
58887
|
};
|
|
58477
58888
|
const agentsList = async (frame, _client, ctx) => {
|
|
58478
58889
|
const args = AgentsListArgs.parse(frame);
|
|
58479
|
-
const cwdAbs =
|
|
58890
|
+
const cwdAbs = path63.resolve(args.cwd);
|
|
58480
58891
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
58481
58892
|
if (args.tool === "codex") {
|
|
58482
58893
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -58498,20 +58909,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
58498
58909
|
}
|
|
58499
58910
|
|
|
58500
58911
|
// src/handlers/git.ts
|
|
58501
|
-
var
|
|
58912
|
+
var path65 = __toESM(require("path"), 1);
|
|
58502
58913
|
init_protocol();
|
|
58503
58914
|
init_protocol();
|
|
58504
58915
|
|
|
58505
58916
|
// src/workspace/git.ts
|
|
58506
|
-
var
|
|
58507
|
-
var
|
|
58508
|
-
var
|
|
58917
|
+
var import_node_child_process12 = require("child_process");
|
|
58918
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
58919
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
58509
58920
|
var import_node_util = require("util");
|
|
58510
|
-
var pexec = (0, import_node_util.promisify)(
|
|
58921
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
|
|
58511
58922
|
function normalizePath(p2) {
|
|
58512
|
-
const resolved =
|
|
58923
|
+
const resolved = import_node_path52.default.resolve(p2);
|
|
58513
58924
|
try {
|
|
58514
|
-
return
|
|
58925
|
+
return import_node_fs47.default.realpathSync(resolved);
|
|
58515
58926
|
} catch {
|
|
58516
58927
|
return resolved;
|
|
58517
58928
|
}
|
|
@@ -58585,7 +58996,7 @@ async function listGitBranches(cwd) {
|
|
|
58585
58996
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
58586
58997
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
58587
58998
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
58588
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
58999
|
+
if (!isGuestPathAllowed(ctx.grants, path65.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
58589
59000
|
throw new ClawdError(
|
|
58590
59001
|
ERROR_CODES.UNAUTHORIZED,
|
|
58591
59002
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -59207,7 +59618,7 @@ function buildDeviceHandlers(deps) {
|
|
|
59207
59618
|
}
|
|
59208
59619
|
|
|
59209
59620
|
// src/handlers/meta.ts
|
|
59210
|
-
var
|
|
59621
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
59211
59622
|
init_protocol();
|
|
59212
59623
|
|
|
59213
59624
|
// src/handlers/method-grants.ts
|
|
@@ -59331,6 +59742,11 @@ var METHOD_GRANT_MAP = {
|
|
|
59331
59742
|
"larkBot:bindManual": ADMIN_ANY,
|
|
59332
59743
|
"larkBot:unbind": ADMIN_ANY,
|
|
59333
59744
|
"larkBot:status": ADMIN_ANY,
|
|
59745
|
+
// ---- onboarding:* / tools:probe / session:externalScan(首启 wizard,owner-only)----
|
|
59746
|
+
"onboarding:complete": ADMIN_ANY,
|
|
59747
|
+
"onboarding:iosInterest": ADMIN_ANY,
|
|
59748
|
+
"tools:probe": ADMIN_ANY,
|
|
59749
|
+
"session:externalScan": ADMIN_ANY,
|
|
59334
59750
|
"inbox:sendDm": ADMIN_ANY,
|
|
59335
59751
|
"personaDispatch:complete": ADMIN_ANY,
|
|
59336
59752
|
"personaDispatch:list": ADMIN_ANY,
|
|
@@ -59462,21 +59878,21 @@ function computeMethodAccess(args) {
|
|
|
59462
59878
|
}
|
|
59463
59879
|
|
|
59464
59880
|
// src/version.ts
|
|
59465
|
-
var version = "0.2.
|
|
59881
|
+
var version = "0.2.322".length > 0 ? "0.2.322" : "dev";
|
|
59466
59882
|
|
|
59467
59883
|
// src/cli-probe/probe.ts
|
|
59468
|
-
var
|
|
59469
|
-
var
|
|
59884
|
+
var fs58 = __toESM(require("fs"), 1);
|
|
59885
|
+
var path66 = __toESM(require("path"), 1);
|
|
59470
59886
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
59471
59887
|
var BIN_NAME = "clawd";
|
|
59472
59888
|
var MAX_PARENT_HOPS = 5;
|
|
59473
59889
|
function probeGlobalCli(pathEnv) {
|
|
59474
59890
|
if (!pathEnv) return null;
|
|
59475
|
-
for (const dir of pathEnv.split(
|
|
59891
|
+
for (const dir of pathEnv.split(path66.delimiter)) {
|
|
59476
59892
|
if (!dir) continue;
|
|
59477
59893
|
let real;
|
|
59478
59894
|
try {
|
|
59479
|
-
real =
|
|
59895
|
+
real = fs58.realpathSync(path66.join(dir, BIN_NAME));
|
|
59480
59896
|
} catch {
|
|
59481
59897
|
continue;
|
|
59482
59898
|
}
|
|
@@ -59486,15 +59902,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
59486
59902
|
return null;
|
|
59487
59903
|
}
|
|
59488
59904
|
function readOwnPackageVersion(entryPath) {
|
|
59489
|
-
let dir =
|
|
59905
|
+
let dir = path66.dirname(entryPath);
|
|
59490
59906
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
59491
59907
|
try {
|
|
59492
|
-
const raw =
|
|
59908
|
+
const raw = fs58.readFileSync(path66.join(dir, "package.json"), "utf8");
|
|
59493
59909
|
const pkg = JSON.parse(raw);
|
|
59494
59910
|
if (pkg.name !== PKG_NAME) return null;
|
|
59495
59911
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
59496
59912
|
} catch {
|
|
59497
|
-
const parent =
|
|
59913
|
+
const parent = path66.dirname(dir);
|
|
59498
59914
|
if (parent === dir) return null;
|
|
59499
59915
|
dir = parent;
|
|
59500
59916
|
}
|
|
@@ -59526,10 +59942,11 @@ function buildReadyFrame(deps, client) {
|
|
|
59526
59942
|
const daemonSource = process.env.CLAWD_DAEMON_SOURCE === "ota" ? "ota" : "packaged";
|
|
59527
59943
|
const globalCliVersion = probeGlobalCli(process.env.PATH);
|
|
59528
59944
|
const logShipping = deps.getLogShipping ? deps.getLogShipping() : null;
|
|
59945
|
+
const onboardingCompletedAt = deps.dataDir && client?.principalKind !== "guest" ? loadOwnerProfile(deps.dataDir).onboardingCompletedAt ?? null : void 0;
|
|
59529
59946
|
return {
|
|
59530
59947
|
version,
|
|
59531
59948
|
protocolVersion: PROTOCOL_VERSION,
|
|
59532
|
-
hostname:
|
|
59949
|
+
hostname: import_node_os18.default.hostname(),
|
|
59533
59950
|
os: process.platform,
|
|
59534
59951
|
tools,
|
|
59535
59952
|
runningSessions: info.runningSessions,
|
|
@@ -59538,7 +59955,8 @@ function buildReadyFrame(deps, client) {
|
|
|
59538
59955
|
daemonSource,
|
|
59539
59956
|
globalCliVersion,
|
|
59540
59957
|
...fileSharing,
|
|
59541
|
-
...logShipping ? { logShipping } : {}
|
|
59958
|
+
...logShipping ? { logShipping } : {},
|
|
59959
|
+
...onboardingCompletedAt !== void 0 ? { onboardingCompletedAt } : {}
|
|
59542
59960
|
};
|
|
59543
59961
|
}
|
|
59544
59962
|
function buildMetaHandlers(deps) {
|
|
@@ -59652,7 +60070,7 @@ function buildPersonaHandlers(deps) {
|
|
|
59652
60070
|
}
|
|
59653
60071
|
|
|
59654
60072
|
// src/handlers/attachment.ts
|
|
59655
|
-
var
|
|
60073
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
59656
60074
|
init_protocol();
|
|
59657
60075
|
init_protocol();
|
|
59658
60076
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -59732,12 +60150,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
59732
60150
|
`session ${args.sessionId} scope unresolved`
|
|
59733
60151
|
);
|
|
59734
60152
|
}
|
|
59735
|
-
const cwdAbs =
|
|
59736
|
-
const candidateAbs =
|
|
60153
|
+
const cwdAbs = import_node_path53.default.resolve(sessionFile.cwd);
|
|
60154
|
+
const candidateAbs = import_node_path53.default.isAbsolute(args.relPath) ? import_node_path53.default.resolve(args.relPath) : import_node_path53.default.resolve(cwdAbs, args.relPath);
|
|
59737
60155
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
59738
60156
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
59739
60157
|
const entry = entries.find((e) => {
|
|
59740
|
-
const storedAbs =
|
|
60158
|
+
const storedAbs = import_node_path53.default.isAbsolute(e.relPath) ? import_node_path53.default.resolve(e.relPath) : import_node_path53.default.resolve(cwdAbs, e.relPath);
|
|
59741
60159
|
return storedAbs === candidateAbs && !e.stale;
|
|
59742
60160
|
});
|
|
59743
60161
|
if (!entry) {
|
|
@@ -59762,7 +60180,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
59762
60180
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
59763
60181
|
const f = deps.sessionStore.read(sessionId);
|
|
59764
60182
|
if (!f) return;
|
|
59765
|
-
assertGuestAttachmentPath(ctx,
|
|
60183
|
+
assertGuestAttachmentPath(ctx, import_node_path53.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
59766
60184
|
}
|
|
59767
60185
|
const groupAdd = async (frame, _client, ctx) => {
|
|
59768
60186
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -59777,8 +60195,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
59777
60195
|
if (!scope) {
|
|
59778
60196
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
59779
60197
|
}
|
|
59780
|
-
const cwdAbs =
|
|
59781
|
-
const candidateAbs =
|
|
60198
|
+
const cwdAbs = import_node_path53.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
60199
|
+
const candidateAbs = import_node_path53.default.isAbsolute(args.relPath) ? import_node_path53.default.resolve(args.relPath) : import_node_path53.default.resolve(cwdAbs, args.relPath);
|
|
59782
60200
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
59783
60201
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
59784
60202
|
const size = 0;
|
|
@@ -59836,21 +60254,21 @@ function buildAttachmentHandlers(deps) {
|
|
|
59836
60254
|
}
|
|
59837
60255
|
|
|
59838
60256
|
// src/handlers/extension.ts
|
|
59839
|
-
var
|
|
59840
|
-
var
|
|
60257
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
60258
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
59841
60259
|
init_protocol();
|
|
59842
60260
|
|
|
59843
60261
|
// src/extension/bundle-zip.ts
|
|
59844
|
-
var
|
|
59845
|
-
var
|
|
60262
|
+
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
60263
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
59846
60264
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
59847
60265
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
59848
60266
|
async function bundleExtensionDir(dir) {
|
|
59849
60267
|
const entries = await listFilesSorted(dir);
|
|
59850
60268
|
const zip = new import_jszip2.default();
|
|
59851
60269
|
for (const rel of entries) {
|
|
59852
|
-
const abs =
|
|
59853
|
-
const content = await
|
|
60270
|
+
const abs = import_node_path54.default.join(dir, rel);
|
|
60271
|
+
const content = await import_promises7.default.readFile(abs);
|
|
59854
60272
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
59855
60273
|
}
|
|
59856
60274
|
const buffer = await zip.generateAsync({
|
|
@@ -59870,8 +60288,8 @@ async function listFilesSorted(rootDir) {
|
|
|
59870
60288
|
return out;
|
|
59871
60289
|
}
|
|
59872
60290
|
async function walk(absRoot, relPrefix, out) {
|
|
59873
|
-
const dirAbs =
|
|
59874
|
-
const entries = await
|
|
60291
|
+
const dirAbs = import_node_path54.default.join(absRoot, relPrefix);
|
|
60292
|
+
const entries = await import_promises7.default.readdir(dirAbs, { withFileTypes: true });
|
|
59875
60293
|
for (const e of entries) {
|
|
59876
60294
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
59877
60295
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
@@ -59923,26 +60341,26 @@ function computePublishCheck(args) {
|
|
|
59923
60341
|
}
|
|
59924
60342
|
|
|
59925
60343
|
// src/extension/install-flow.ts
|
|
59926
|
-
var
|
|
59927
|
-
var
|
|
59928
|
-
var
|
|
60344
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
60345
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
60346
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
59929
60347
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
59930
60348
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
59931
60349
|
|
|
59932
60350
|
// src/extension/paths.ts
|
|
59933
|
-
var
|
|
59934
|
-
var
|
|
60351
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
60352
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
59935
60353
|
function clawdHomeRoot(override) {
|
|
59936
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
60354
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path55.default.join(import_node_os19.default.homedir(), ".clawd");
|
|
59937
60355
|
}
|
|
59938
60356
|
function extensionsRoot(override) {
|
|
59939
|
-
return
|
|
60357
|
+
return import_node_path55.default.join(clawdHomeRoot(override), "extensions");
|
|
59940
60358
|
}
|
|
59941
60359
|
function publishedChannelsFile(override) {
|
|
59942
|
-
return
|
|
60360
|
+
return import_node_path55.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
59943
60361
|
}
|
|
59944
60362
|
function bundleCacheRoot(override) {
|
|
59945
|
-
return
|
|
60363
|
+
return import_node_path55.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
59946
60364
|
}
|
|
59947
60365
|
|
|
59948
60366
|
// src/extension/install-flow.ts
|
|
@@ -59969,7 +60387,7 @@ async function installFromChannel(args, deps) {
|
|
|
59969
60387
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
59970
60388
|
}
|
|
59971
60389
|
for (const name of Object.keys(zip.files)) {
|
|
59972
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
60390
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path56.default.isAbsolute(name)) {
|
|
59973
60391
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
59974
60392
|
}
|
|
59975
60393
|
}
|
|
@@ -60001,10 +60419,10 @@ async function installFromChannel(args, deps) {
|
|
|
60001
60419
|
);
|
|
60002
60420
|
}
|
|
60003
60421
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
60004
|
-
const destDir =
|
|
60422
|
+
const destDir = import_node_path56.default.join(deps.extensionsRoot, localExtId);
|
|
60005
60423
|
let destExists = false;
|
|
60006
60424
|
try {
|
|
60007
|
-
await
|
|
60425
|
+
await import_promises8.default.access(destDir);
|
|
60008
60426
|
destExists = true;
|
|
60009
60427
|
} catch {
|
|
60010
60428
|
}
|
|
@@ -60014,28 +60432,28 @@ async function installFromChannel(args, deps) {
|
|
|
60014
60432
|
`extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
|
|
60015
60433
|
);
|
|
60016
60434
|
}
|
|
60017
|
-
const stage = await
|
|
60018
|
-
|
|
60435
|
+
const stage = await import_promises8.default.mkdtemp(
|
|
60436
|
+
import_node_path56.default.join(import_node_os20.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
60019
60437
|
);
|
|
60020
60438
|
try {
|
|
60021
60439
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60022
|
-
const dest =
|
|
60440
|
+
const dest = import_node_path56.default.join(stage, name);
|
|
60023
60441
|
if (entry.dir) {
|
|
60024
|
-
await
|
|
60442
|
+
await import_promises8.default.mkdir(dest, { recursive: true });
|
|
60025
60443
|
continue;
|
|
60026
60444
|
}
|
|
60027
|
-
await
|
|
60445
|
+
await import_promises8.default.mkdir(import_node_path56.default.dirname(dest), { recursive: true });
|
|
60028
60446
|
if (name === "manifest.json") {
|
|
60029
60447
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60030
|
-
await
|
|
60448
|
+
await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
60031
60449
|
} else {
|
|
60032
|
-
await
|
|
60450
|
+
await import_promises8.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
60033
60451
|
}
|
|
60034
60452
|
}
|
|
60035
|
-
await
|
|
60036
|
-
await
|
|
60453
|
+
await import_promises8.default.mkdir(deps.extensionsRoot, { recursive: true });
|
|
60454
|
+
await import_promises8.default.rename(stage, destDir);
|
|
60037
60455
|
} catch (e) {
|
|
60038
|
-
await
|
|
60456
|
+
await import_promises8.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
60039
60457
|
});
|
|
60040
60458
|
throw e;
|
|
60041
60459
|
}
|
|
@@ -60044,9 +60462,9 @@ async function installFromChannel(args, deps) {
|
|
|
60044
60462
|
}
|
|
60045
60463
|
|
|
60046
60464
|
// src/extension/update-flow.ts
|
|
60047
|
-
var
|
|
60048
|
-
var
|
|
60049
|
-
var
|
|
60465
|
+
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
60466
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
60467
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
60050
60468
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
60051
60469
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
60052
60470
|
var UpdateError = class extends Error {
|
|
@@ -60062,11 +60480,11 @@ async function updateFromChannel(args, deps) {
|
|
|
60062
60480
|
channelRef.extId,
|
|
60063
60481
|
channelRef.ownerPrincipalId
|
|
60064
60482
|
);
|
|
60065
|
-
const liveDir =
|
|
60483
|
+
const liveDir = import_node_path57.default.join(deps.extensionsRoot, localExtId);
|
|
60066
60484
|
const prevDir = `${liveDir}.prev`;
|
|
60067
60485
|
let existingVersion;
|
|
60068
60486
|
try {
|
|
60069
|
-
const raw = await
|
|
60487
|
+
const raw = await import_promises9.default.readFile(import_node_path57.default.join(liveDir, "manifest.json"), "utf8");
|
|
60070
60488
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
60071
60489
|
if (!parsed2.success) {
|
|
60072
60490
|
throw new UpdateError(
|
|
@@ -60099,7 +60517,7 @@ async function updateFromChannel(args, deps) {
|
|
|
60099
60517
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60100
60518
|
}
|
|
60101
60519
|
for (const name of Object.keys(zip.files)) {
|
|
60102
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
60520
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path57.default.isAbsolute(name)) {
|
|
60103
60521
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
60104
60522
|
}
|
|
60105
60523
|
}
|
|
@@ -60131,31 +60549,31 @@ async function updateFromChannel(args, deps) {
|
|
|
60131
60549
|
);
|
|
60132
60550
|
}
|
|
60133
60551
|
await deps.runtime.close(localExtId);
|
|
60134
|
-
await
|
|
60135
|
-
await
|
|
60136
|
-
const stage = await
|
|
60137
|
-
|
|
60552
|
+
await import_promises9.default.rm(prevDir, { recursive: true, force: true });
|
|
60553
|
+
await import_promises9.default.rename(liveDir, prevDir);
|
|
60554
|
+
const stage = await import_promises9.default.mkdtemp(
|
|
60555
|
+
import_node_path57.default.join(import_node_os21.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
60138
60556
|
);
|
|
60139
60557
|
try {
|
|
60140
60558
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60141
|
-
const dest =
|
|
60559
|
+
const dest = import_node_path57.default.join(stage, name);
|
|
60142
60560
|
if (entry.dir) {
|
|
60143
|
-
await
|
|
60561
|
+
await import_promises9.default.mkdir(dest, { recursive: true });
|
|
60144
60562
|
continue;
|
|
60145
60563
|
}
|
|
60146
|
-
await
|
|
60564
|
+
await import_promises9.default.mkdir(import_node_path57.default.dirname(dest), { recursive: true });
|
|
60147
60565
|
if (name === "manifest.json") {
|
|
60148
60566
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60149
|
-
await
|
|
60567
|
+
await import_promises9.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
60150
60568
|
} else {
|
|
60151
|
-
await
|
|
60569
|
+
await import_promises9.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
60152
60570
|
}
|
|
60153
60571
|
}
|
|
60154
|
-
await
|
|
60572
|
+
await import_promises9.default.rename(stage, liveDir);
|
|
60155
60573
|
} catch (e) {
|
|
60156
|
-
await
|
|
60574
|
+
await import_promises9.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
60157
60575
|
});
|
|
60158
|
-
await
|
|
60576
|
+
await import_promises9.default.rename(prevDir, liveDir).catch(() => {
|
|
60159
60577
|
});
|
|
60160
60578
|
await deps.runtime.open(localExtId).catch(() => {
|
|
60161
60579
|
});
|
|
@@ -60177,7 +60595,7 @@ async function updateFromChannel(args, deps) {
|
|
|
60177
60595
|
reason: e.message
|
|
60178
60596
|
};
|
|
60179
60597
|
}
|
|
60180
|
-
await
|
|
60598
|
+
await import_promises9.default.rm(prevDir, { recursive: true, force: true });
|
|
60181
60599
|
return {
|
|
60182
60600
|
kind: "updated",
|
|
60183
60601
|
extId: localExtId,
|
|
@@ -60185,9 +60603,9 @@ async function updateFromChannel(args, deps) {
|
|
|
60185
60603
|
};
|
|
60186
60604
|
}
|
|
60187
60605
|
async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
60188
|
-
await
|
|
60606
|
+
await import_promises9.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
|
|
60189
60607
|
});
|
|
60190
|
-
await
|
|
60608
|
+
await import_promises9.default.rename(prevDir, liveDir).catch(() => {
|
|
60191
60609
|
});
|
|
60192
60610
|
await deps.runtime.open(localExtId).catch(() => {
|
|
60193
60611
|
});
|
|
@@ -60210,18 +60628,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
60210
60628
|
);
|
|
60211
60629
|
}
|
|
60212
60630
|
}
|
|
60213
|
-
const manifestPath =
|
|
60631
|
+
const manifestPath = import_node_path58.default.join(root, extId, "manifest.json");
|
|
60214
60632
|
const manifest = await readManifest(root, extId);
|
|
60215
60633
|
const next = { ...manifest, version: newVersion };
|
|
60216
60634
|
const tmp = `${manifestPath}.tmp`;
|
|
60217
|
-
await
|
|
60218
|
-
await
|
|
60635
|
+
await import_promises10.default.writeFile(tmp, JSON.stringify(next, null, 2));
|
|
60636
|
+
await import_promises10.default.rename(tmp, manifestPath);
|
|
60219
60637
|
}
|
|
60220
60638
|
async function readManifest(root, extId) {
|
|
60221
|
-
const file =
|
|
60639
|
+
const file = import_node_path58.default.join(root, extId, "manifest.json");
|
|
60222
60640
|
let raw;
|
|
60223
60641
|
try {
|
|
60224
|
-
raw = await
|
|
60642
|
+
raw = await import_promises10.default.readFile(file, "utf8");
|
|
60225
60643
|
} catch (e) {
|
|
60226
60644
|
if (e.code === "ENOENT") {
|
|
60227
60645
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
|
|
@@ -60302,7 +60720,7 @@ function buildExtensionHandlers(deps) {
|
|
|
60302
60720
|
};
|
|
60303
60721
|
async function buildSnapshotMeta(extId) {
|
|
60304
60722
|
const manifest = await readManifest(deps.root, extId);
|
|
60305
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
60723
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path58.default.join(deps.root, extId));
|
|
60306
60724
|
return { manifest, contentHash: sha256, buffer };
|
|
60307
60725
|
}
|
|
60308
60726
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -60477,9 +60895,9 @@ function buildExtensionHandlers(deps) {
|
|
|
60477
60895
|
}
|
|
60478
60896
|
|
|
60479
60897
|
// src/app-builder/project-store.ts
|
|
60480
|
-
var
|
|
60481
|
-
var
|
|
60482
|
-
var
|
|
60898
|
+
var import_node_fs48 = require("fs");
|
|
60899
|
+
var import_node_child_process13 = require("child_process");
|
|
60900
|
+
var import_node_path59 = require("path");
|
|
60483
60901
|
init_protocol();
|
|
60484
60902
|
var PROJECTS_DIR = "projects";
|
|
60485
60903
|
var META_FILE = ".clawd-project.json";
|
|
@@ -60493,19 +60911,19 @@ var ProjectStore = class {
|
|
|
60493
60911
|
root;
|
|
60494
60912
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
60495
60913
|
metaPath(name) {
|
|
60496
|
-
return (0,
|
|
60914
|
+
return (0, import_node_path59.join)(this.projectsRoot(), name, META_FILE);
|
|
60497
60915
|
}
|
|
60498
60916
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
60499
60917
|
projectDir(name) {
|
|
60500
|
-
return (0,
|
|
60918
|
+
return (0, import_node_path59.join)(this.projectsRoot(), name);
|
|
60501
60919
|
}
|
|
60502
60920
|
projectsRoot() {
|
|
60503
|
-
return (0,
|
|
60921
|
+
return (0, import_node_path59.join)(this.root, PROJECTS_DIR);
|
|
60504
60922
|
}
|
|
60505
60923
|
async list() {
|
|
60506
60924
|
let entries;
|
|
60507
60925
|
try {
|
|
60508
|
-
entries = await
|
|
60926
|
+
entries = await import_node_fs48.promises.readdir(this.projectsRoot());
|
|
60509
60927
|
} catch (err) {
|
|
60510
60928
|
if (err.code === "ENOENT") return [];
|
|
60511
60929
|
throw err;
|
|
@@ -60513,7 +60931,7 @@ var ProjectStore = class {
|
|
|
60513
60931
|
const out = [];
|
|
60514
60932
|
for (const name of entries) {
|
|
60515
60933
|
try {
|
|
60516
|
-
const raw = await
|
|
60934
|
+
const raw = await import_node_fs48.promises.readFile(this.metaPath(name), "utf8");
|
|
60517
60935
|
const json = JSON.parse(raw);
|
|
60518
60936
|
let migrated = false;
|
|
60519
60937
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -60524,7 +60942,7 @@ var ProjectStore = class {
|
|
|
60524
60942
|
if (parsed.success) {
|
|
60525
60943
|
out.push(parsed.data);
|
|
60526
60944
|
if (migrated) {
|
|
60527
|
-
void
|
|
60945
|
+
void import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
60528
60946
|
});
|
|
60529
60947
|
}
|
|
60530
60948
|
}
|
|
@@ -60568,8 +60986,8 @@ var ProjectStore = class {
|
|
|
60568
60986
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
60569
60987
|
}
|
|
60570
60988
|
const dir = this.projectDir(name);
|
|
60571
|
-
await
|
|
60572
|
-
await
|
|
60989
|
+
await import_node_fs48.promises.mkdir(dir, { recursive: true });
|
|
60990
|
+
await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
60573
60991
|
return meta;
|
|
60574
60992
|
}
|
|
60575
60993
|
/**
|
|
@@ -60583,7 +61001,7 @@ var ProjectStore = class {
|
|
|
60583
61001
|
async scaffold(name, templateSrcDir, scaffoldScriptPath) {
|
|
60584
61002
|
const destDir = this.projectDir(name);
|
|
60585
61003
|
return await new Promise((resolve6, reject) => {
|
|
60586
|
-
const child = (0,
|
|
61004
|
+
const child = (0, import_node_child_process13.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
60587
61005
|
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
60588
61006
|
stdio: ["ignore", "pipe", "pipe"]
|
|
60589
61007
|
});
|
|
@@ -60612,7 +61030,7 @@ var ProjectStore = class {
|
|
|
60612
61030
|
}
|
|
60613
61031
|
async delete(name) {
|
|
60614
61032
|
const dir = this.projectDir(name);
|
|
60615
|
-
await
|
|
61033
|
+
await import_node_fs48.promises.rm(dir, { recursive: true, force: true });
|
|
60616
61034
|
}
|
|
60617
61035
|
async updatePort(name, newPort) {
|
|
60618
61036
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -60628,7 +61046,7 @@ var ProjectStore = class {
|
|
|
60628
61046
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
60629
61047
|
}
|
|
60630
61048
|
const updated = { ...target, port: newPort };
|
|
60631
|
-
await
|
|
61049
|
+
await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
60632
61050
|
return updated;
|
|
60633
61051
|
}
|
|
60634
61052
|
/**
|
|
@@ -60645,7 +61063,7 @@ var ProjectStore = class {
|
|
|
60645
61063
|
if (!validated.success) {
|
|
60646
61064
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
60647
61065
|
}
|
|
60648
|
-
await
|
|
61066
|
+
await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
60649
61067
|
return validated.data;
|
|
60650
61068
|
}
|
|
60651
61069
|
/**
|
|
@@ -60666,7 +61084,7 @@ var ProjectStore = class {
|
|
|
60666
61084
|
if (!validated.success) {
|
|
60667
61085
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
60668
61086
|
}
|
|
60669
|
-
await
|
|
61087
|
+
await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
60670
61088
|
return validated.data;
|
|
60671
61089
|
}
|
|
60672
61090
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -60681,13 +61099,13 @@ var ProjectStore = class {
|
|
|
60681
61099
|
if (!validated.success) {
|
|
60682
61100
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
60683
61101
|
}
|
|
60684
|
-
await
|
|
61102
|
+
await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
60685
61103
|
return validated.data;
|
|
60686
61104
|
}
|
|
60687
61105
|
};
|
|
60688
61106
|
|
|
60689
61107
|
// src/app-builder/kill-port.ts
|
|
60690
|
-
var
|
|
61108
|
+
var import_node_child_process14 = require("child_process");
|
|
60691
61109
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
60692
61110
|
let pids;
|
|
60693
61111
|
try {
|
|
@@ -60729,7 +61147,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
60729
61147
|
}
|
|
60730
61148
|
function listPidsOnPort(port) {
|
|
60731
61149
|
return new Promise((resolve6, reject) => {
|
|
60732
|
-
(0,
|
|
61150
|
+
(0, import_node_child_process14.execFile)(
|
|
60733
61151
|
"lsof",
|
|
60734
61152
|
["-ti", `:${port}`],
|
|
60735
61153
|
{ timeout: 3e3 },
|
|
@@ -60801,9 +61219,9 @@ var PublishJobRegistry = class {
|
|
|
60801
61219
|
};
|
|
60802
61220
|
|
|
60803
61221
|
// src/app-builder/publish-job-runner.ts
|
|
60804
|
-
var
|
|
60805
|
-
var
|
|
60806
|
-
var
|
|
61222
|
+
var import_node_child_process15 = require("child_process");
|
|
61223
|
+
var import_node_fs49 = require("fs");
|
|
61224
|
+
var import_node_path60 = require("path");
|
|
60807
61225
|
|
|
60808
61226
|
// src/app-builder/publish-stage-parser.ts
|
|
60809
61227
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -60830,15 +61248,15 @@ function tailStderrLines(buf, n) {
|
|
|
60830
61248
|
// src/app-builder/publish-job-runner.ts
|
|
60831
61249
|
async function startPublishJob(deps, args) {
|
|
60832
61250
|
const { registry: registry2, projectDir } = deps;
|
|
60833
|
-
const spawn12 = deps.spawnImpl ??
|
|
61251
|
+
const spawn12 = deps.spawnImpl ?? import_node_child_process15.spawn;
|
|
60834
61252
|
if (registry2.has(args.name)) {
|
|
60835
61253
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
60836
61254
|
}
|
|
60837
61255
|
const projDir = projectDir(args.name);
|
|
60838
|
-
const logPath = (0,
|
|
61256
|
+
const logPath = (0, import_node_path60.join)(projDir, ".publish.log");
|
|
60839
61257
|
let logStream = null;
|
|
60840
61258
|
try {
|
|
60841
|
-
logStream = (0,
|
|
61259
|
+
logStream = (0, import_node_fs49.createWriteStream)(logPath, { flags: "w" });
|
|
60842
61260
|
} catch {
|
|
60843
61261
|
logStream = null;
|
|
60844
61262
|
}
|
|
@@ -61095,8 +61513,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
61095
61513
|
|
|
61096
61514
|
// src/handlers/app-builder.ts
|
|
61097
61515
|
init_protocol();
|
|
61098
|
-
var
|
|
61099
|
-
var
|
|
61516
|
+
var import_node_path61 = require("path");
|
|
61517
|
+
var import_node_fs50 = require("fs");
|
|
61100
61518
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
61101
61519
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
61102
61520
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -61177,7 +61595,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
61177
61595
|
async function listAllUsersProjects() {
|
|
61178
61596
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
61179
61597
|
const getStore = deps.getStore;
|
|
61180
|
-
const userIds = await
|
|
61598
|
+
const userIds = await import_node_fs50.promises.readdir(deps.usersRoot).catch(() => []);
|
|
61181
61599
|
const perUser = await Promise.all(
|
|
61182
61600
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
61183
61601
|
);
|
|
@@ -61246,8 +61664,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
61246
61664
|
const project = await userStore.create(f.name, reservedPorts);
|
|
61247
61665
|
try {
|
|
61248
61666
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
61249
|
-
const templateSrcDir = (0,
|
|
61250
|
-
const scaffoldScript = (0,
|
|
61667
|
+
const templateSrcDir = (0, import_node_path61.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
61668
|
+
const scaffoldScript = (0, import_node_path61.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
61251
61669
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
61252
61670
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
61253
61671
|
name: project.name,
|
|
@@ -61451,7 +61869,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
61451
61869
|
await userStore.clearPublishJob(args.name);
|
|
61452
61870
|
}
|
|
61453
61871
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
61454
|
-
const scriptPath = (0,
|
|
61872
|
+
const scriptPath = (0, import_node_path61.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
61455
61873
|
deps.logger?.info("app-builder.publish.start", {
|
|
61456
61874
|
name: args.name,
|
|
61457
61875
|
sessionId: boundSession.sessionId,
|
|
@@ -61870,12 +62288,12 @@ function buildVisitorHandlers(deps) {
|
|
|
61870
62288
|
}
|
|
61871
62289
|
|
|
61872
62290
|
// src/extension/registry.ts
|
|
61873
|
-
var
|
|
61874
|
-
var
|
|
62291
|
+
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
62292
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
61875
62293
|
async function loadAll(root) {
|
|
61876
62294
|
let entries;
|
|
61877
62295
|
try {
|
|
61878
|
-
entries = await
|
|
62296
|
+
entries = await import_promises11.default.readdir(root, { withFileTypes: true });
|
|
61879
62297
|
} catch (e) {
|
|
61880
62298
|
if (e.code === "ENOENT") return [];
|
|
61881
62299
|
throw e;
|
|
@@ -61884,16 +62302,16 @@ async function loadAll(root) {
|
|
|
61884
62302
|
for (const ent of entries) {
|
|
61885
62303
|
if (!ent.isDirectory()) continue;
|
|
61886
62304
|
if (ent.name.startsWith(".")) continue;
|
|
61887
|
-
records.push(await loadOne(
|
|
62305
|
+
records.push(await loadOne(import_node_path62.default.join(root, ent.name), ent.name));
|
|
61888
62306
|
}
|
|
61889
62307
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
61890
62308
|
return records;
|
|
61891
62309
|
}
|
|
61892
62310
|
async function loadOne(dir, dirName) {
|
|
61893
|
-
const manifestPath =
|
|
62311
|
+
const manifestPath = import_node_path62.default.join(dir, "manifest.json");
|
|
61894
62312
|
let raw;
|
|
61895
62313
|
try {
|
|
61896
|
-
raw = await
|
|
62314
|
+
raw = await import_promises11.default.readFile(manifestPath, "utf8");
|
|
61897
62315
|
} catch {
|
|
61898
62316
|
return {
|
|
61899
62317
|
extId: dirName,
|
|
@@ -61934,8 +62352,8 @@ async function loadOne(dir, dirName) {
|
|
|
61934
62352
|
}
|
|
61935
62353
|
|
|
61936
62354
|
// src/extension/uninstall.ts
|
|
61937
|
-
var
|
|
61938
|
-
var
|
|
62355
|
+
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62356
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
61939
62357
|
var UninstallError = class extends Error {
|
|
61940
62358
|
constructor(code, message) {
|
|
61941
62359
|
super(message);
|
|
@@ -61944,14 +62362,14 @@ var UninstallError = class extends Error {
|
|
|
61944
62362
|
code;
|
|
61945
62363
|
};
|
|
61946
62364
|
async function uninstall(deps) {
|
|
61947
|
-
const dir =
|
|
62365
|
+
const dir = import_node_path63.default.join(deps.root, deps.extId);
|
|
61948
62366
|
try {
|
|
61949
|
-
await
|
|
62367
|
+
await import_promises12.default.access(dir);
|
|
61950
62368
|
} catch {
|
|
61951
62369
|
throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
|
|
61952
62370
|
}
|
|
61953
62371
|
await deps.runtime.close(deps.extId);
|
|
61954
|
-
await
|
|
62372
|
+
await import_promises12.default.rm(dir, { recursive: true, force: true });
|
|
61955
62373
|
}
|
|
61956
62374
|
|
|
61957
62375
|
// src/handlers/index.ts
|
|
@@ -61961,15 +62379,15 @@ var import_node_crypto18 = require("crypto");
|
|
|
61961
62379
|
init_protocol();
|
|
61962
62380
|
|
|
61963
62381
|
// src/peer-ops/run-command.ts
|
|
61964
|
-
var
|
|
61965
|
-
var
|
|
62382
|
+
var import_node_child_process16 = require("child_process");
|
|
62383
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
61966
62384
|
var DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
61967
62385
|
var MAX_TIMEOUT_MS = 3e5;
|
|
61968
62386
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
61969
62387
|
function runCommand(command, opts = {}) {
|
|
61970
62388
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4, MAX_TIMEOUT_MS);
|
|
61971
62389
|
return new Promise((resolve6) => {
|
|
61972
|
-
const child = (0,
|
|
62390
|
+
const child = (0, import_node_child_process16.spawn)("bash", ["-c", command], { cwd: import_node_os22.default.homedir() });
|
|
61973
62391
|
const out = [];
|
|
61974
62392
|
const err = [];
|
|
61975
62393
|
let outBytes = 0;
|
|
@@ -62184,8 +62602,129 @@ function buildMethodHandlers(deps) {
|
|
|
62184
62602
|
return handlers;
|
|
62185
62603
|
}
|
|
62186
62604
|
|
|
62605
|
+
// src/handlers/onboarding.ts
|
|
62606
|
+
init_protocol();
|
|
62607
|
+
|
|
62608
|
+
// src/tools/version-probe.ts
|
|
62609
|
+
var import_node_child_process17 = require("child_process");
|
|
62610
|
+
init_claude();
|
|
62611
|
+
function parseVersionOutput(out) {
|
|
62612
|
+
return /(\d+\.\d+\.\d+)/.exec(out)?.[1];
|
|
62613
|
+
}
|
|
62614
|
+
function execVersion(bin) {
|
|
62615
|
+
return new Promise((resolve6, reject) => {
|
|
62616
|
+
(0, import_node_child_process17.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
|
|
62617
|
+
if (err) reject(err);
|
|
62618
|
+
else resolve6(String(stdout));
|
|
62619
|
+
});
|
|
62620
|
+
});
|
|
62621
|
+
}
|
|
62622
|
+
var cache = null;
|
|
62623
|
+
async function probeToolVersions(opts = {}) {
|
|
62624
|
+
if (cache) return cache;
|
|
62625
|
+
const probes = opts.probes ?? { claude: () => probeClaude(), codex: () => probeCodex() };
|
|
62626
|
+
const runVersion = opts.runVersion ?? execVersion;
|
|
62627
|
+
const out = [];
|
|
62628
|
+
for (const id of ["claude", "codex"]) {
|
|
62629
|
+
const p2 = await probes[id]();
|
|
62630
|
+
if (!p2.available) {
|
|
62631
|
+
out.push({ id, available: false });
|
|
62632
|
+
continue;
|
|
62633
|
+
}
|
|
62634
|
+
let version2;
|
|
62635
|
+
try {
|
|
62636
|
+
version2 = parseVersionOutput(await runVersion(p2.path ?? id));
|
|
62637
|
+
} catch {
|
|
62638
|
+
version2 = void 0;
|
|
62639
|
+
}
|
|
62640
|
+
out.push({ id, available: true, ...version2 ? { version: version2 } : {}, ...p2.path ? { path: p2.path } : {} });
|
|
62641
|
+
}
|
|
62642
|
+
if (out.some((t) => t.available)) cache = out;
|
|
62643
|
+
return out;
|
|
62644
|
+
}
|
|
62645
|
+
|
|
62646
|
+
// src/feishu-auth/ios-interest-client.ts
|
|
62647
|
+
var IosInterestClientError = class extends Error {
|
|
62648
|
+
constructor(code, message, cause) {
|
|
62649
|
+
super(message);
|
|
62650
|
+
this.code = code;
|
|
62651
|
+
this.cause = cause;
|
|
62652
|
+
this.name = "IosInterestClientError";
|
|
62653
|
+
}
|
|
62654
|
+
code;
|
|
62655
|
+
cause;
|
|
62656
|
+
};
|
|
62657
|
+
var DEFAULT_TIMEOUT_MS5 = 8e3;
|
|
62658
|
+
async function submitIosInterest(opts) {
|
|
62659
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
62660
|
+
const ac = new AbortController();
|
|
62661
|
+
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5);
|
|
62662
|
+
let res;
|
|
62663
|
+
try {
|
|
62664
|
+
res = await doFetch(`${opts.apiUrl}/api/ios-interest`, {
|
|
62665
|
+
method: "POST",
|
|
62666
|
+
signal: ac.signal,
|
|
62667
|
+
headers: {
|
|
62668
|
+
authorization: `Bearer ${opts.apiKey}`,
|
|
62669
|
+
"x-did": encodeURIComponent(opts.deviceId),
|
|
62670
|
+
"x-name": encodeURIComponent(opts.displayName),
|
|
62671
|
+
"x-scene": "daemon",
|
|
62672
|
+
"content-type": "application/json"
|
|
62673
|
+
},
|
|
62674
|
+
body: JSON.stringify({ unionId: opts.unionId, displayName: opts.displayName })
|
|
62675
|
+
});
|
|
62676
|
+
} catch (err) {
|
|
62677
|
+
clearTimeout(timer);
|
|
62678
|
+
throw new IosInterestClientError("NETWORK", `network error: ${err.message}`, err);
|
|
62679
|
+
} finally {
|
|
62680
|
+
clearTimeout(timer);
|
|
62681
|
+
}
|
|
62682
|
+
if (!res.ok) {
|
|
62683
|
+
let detail = "";
|
|
62684
|
+
try {
|
|
62685
|
+
detail = JSON.stringify(await res.json());
|
|
62686
|
+
} catch {
|
|
62687
|
+
}
|
|
62688
|
+
throw new IosInterestClientError("API_ERROR", `HTTP ${res.status}: ${detail}`);
|
|
62689
|
+
}
|
|
62690
|
+
}
|
|
62691
|
+
|
|
62692
|
+
// src/handlers/onboarding.ts
|
|
62693
|
+
function buildOnboardingHandlers(deps) {
|
|
62694
|
+
const complete = async (frame) => {
|
|
62695
|
+
parseArgs2(OnboardingCompleteArgs, frame, "onboarding:complete args");
|
|
62696
|
+
const existing = loadOwnerProfile(deps.dataDir).onboardingCompletedAt;
|
|
62697
|
+
const ts = typeof existing === "number" ? existing : Date.now();
|
|
62698
|
+
if (typeof existing !== "number") {
|
|
62699
|
+
patchOwnerProfile(deps.dataDir, { onboardingCompletedAt: ts });
|
|
62700
|
+
}
|
|
62701
|
+
return { response: { onboardingCompletedAt: ts } };
|
|
62702
|
+
};
|
|
62703
|
+
const toolsProbe = async (frame) => {
|
|
62704
|
+
parseArgs2(ToolsProbeArgs, frame, "tools:probe args");
|
|
62705
|
+
return { response: { tools: await probeToolVersions() } };
|
|
62706
|
+
};
|
|
62707
|
+
const iosInterest = async (frame) => {
|
|
62708
|
+
parseArgs2(OnboardingIosInterestArgs, frame, "onboarding:iosInterest args");
|
|
62709
|
+
const identity = deps.getOwnerIdentity();
|
|
62710
|
+
if (!identity) {
|
|
62711
|
+
throw new ClawdError(ERROR_CODES.FEISHU_LOGIN_REQUIRED, "onboarding:iosInterest \u9700\u8981\u98DE\u4E66\u767B\u5F55");
|
|
62712
|
+
}
|
|
62713
|
+
await submitIosInterest({
|
|
62714
|
+
apiUrl: deps.apiUrl,
|
|
62715
|
+
apiKey: deps.apiKey,
|
|
62716
|
+
deviceId: deps.deviceId,
|
|
62717
|
+
unionId: identity.unionId,
|
|
62718
|
+
displayName: identity.displayName,
|
|
62719
|
+
...deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}
|
|
62720
|
+
});
|
|
62721
|
+
return { response: { registered: true } };
|
|
62722
|
+
};
|
|
62723
|
+
return { "onboarding:complete": complete, "tools:probe": toolsProbe, "onboarding:iosInterest": iosInterest };
|
|
62724
|
+
}
|
|
62725
|
+
|
|
62187
62726
|
// src/app-builder/dev-server-supervisor.ts
|
|
62188
|
-
var
|
|
62727
|
+
var import_node_child_process18 = require("child_process");
|
|
62189
62728
|
var import_node_events2 = require("events");
|
|
62190
62729
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
62191
62730
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -62222,7 +62761,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
62222
62761
|
tunnelHost: args.tunnelHost,
|
|
62223
62762
|
devCommand: cmd
|
|
62224
62763
|
});
|
|
62225
|
-
const child = (0,
|
|
62764
|
+
const child = (0, import_node_child_process18.spawn)("sh", ["-c", cmd], {
|
|
62226
62765
|
cwd: args.cwd,
|
|
62227
62766
|
env,
|
|
62228
62767
|
stdio: "pipe",
|
|
@@ -62474,9 +63013,9 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
62474
63013
|
}
|
|
62475
63014
|
|
|
62476
63015
|
// src/extension/runtime.ts
|
|
62477
|
-
var
|
|
62478
|
-
var
|
|
62479
|
-
var
|
|
63016
|
+
var import_node_child_process19 = require("child_process");
|
|
63017
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
63018
|
+
var import_promises13 = require("timers/promises");
|
|
62480
63019
|
|
|
62481
63020
|
// src/extension/port-allocator.ts
|
|
62482
63021
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
@@ -62576,13 +63115,13 @@ var Runtime = class {
|
|
|
62576
63115
|
/\$CLAWOS_EXT_PORT/g,
|
|
62577
63116
|
String(port)
|
|
62578
63117
|
);
|
|
62579
|
-
const dir =
|
|
63118
|
+
const dir = import_node_path64.default.join(this.root, extId);
|
|
62580
63119
|
const env = {
|
|
62581
63120
|
...process.env,
|
|
62582
63121
|
CLAWOS_EXT_PORT: String(port),
|
|
62583
63122
|
CLAWOS_EXT_ID: extId
|
|
62584
63123
|
};
|
|
62585
|
-
const child = (0,
|
|
63124
|
+
const child = (0, import_node_child_process19.spawn)("sh", ["-c", cmd], {
|
|
62586
63125
|
cwd: dir,
|
|
62587
63126
|
env,
|
|
62588
63127
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -62652,7 +63191,7 @@ ${handle.stderrTail}`
|
|
|
62652
63191
|
if (res.ok) return;
|
|
62653
63192
|
} catch {
|
|
62654
63193
|
}
|
|
62655
|
-
await (0,
|
|
63194
|
+
await (0, import_promises13.setTimeout)(this.healthzIntervalMs);
|
|
62656
63195
|
}
|
|
62657
63196
|
throw new RuntimeError(
|
|
62658
63197
|
"HEALTHZ_FAILED",
|
|
@@ -62677,7 +63216,7 @@ ${handle.stderrTail}`
|
|
|
62677
63216
|
};
|
|
62678
63217
|
killGroup("SIGTERM");
|
|
62679
63218
|
const exited = new Promise((resolve6) => child.once("exit", () => resolve6()));
|
|
62680
|
-
const timed = (0,
|
|
63219
|
+
const timed = (0, import_promises13.setTimeout)(5e3).then(() => "timeout");
|
|
62681
63220
|
const winner = await Promise.race([exited.then(() => "exited"), timed]);
|
|
62682
63221
|
if (winner === "timeout" && child.exitCode === null) {
|
|
62683
63222
|
killGroup("SIGKILL");
|
|
@@ -62687,8 +63226,8 @@ ${handle.stderrTail}`
|
|
|
62687
63226
|
};
|
|
62688
63227
|
|
|
62689
63228
|
// src/extension/published-channels.ts
|
|
62690
|
-
var
|
|
62691
|
-
var
|
|
63229
|
+
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
63230
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
62692
63231
|
init_zod();
|
|
62693
63232
|
var PublishedChannelsError = class extends Error {
|
|
62694
63233
|
constructor(code, message) {
|
|
@@ -62718,7 +63257,7 @@ var PublishedChannelStore = class {
|
|
|
62718
63257
|
this.channels.clear();
|
|
62719
63258
|
let raw;
|
|
62720
63259
|
try {
|
|
62721
|
-
raw = await
|
|
63260
|
+
raw = await import_promises14.default.readFile(this.filePath, "utf8");
|
|
62722
63261
|
} catch (e) {
|
|
62723
63262
|
if (e.code === "ENOENT") {
|
|
62724
63263
|
this.loaded = true;
|
|
@@ -62787,15 +63326,15 @@ var PublishedChannelStore = class {
|
|
|
62787
63326
|
)
|
|
62788
63327
|
};
|
|
62789
63328
|
const tmp = `${this.filePath}.tmp`;
|
|
62790
|
-
await
|
|
62791
|
-
await
|
|
62792
|
-
await
|
|
63329
|
+
await import_promises14.default.mkdir(import_node_path65.default.dirname(this.filePath), { recursive: true });
|
|
63330
|
+
await import_promises14.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
63331
|
+
await import_promises14.default.rename(tmp, this.filePath);
|
|
62793
63332
|
}
|
|
62794
63333
|
};
|
|
62795
63334
|
|
|
62796
63335
|
// src/extension/bundle-cache.ts
|
|
62797
|
-
var
|
|
62798
|
-
var
|
|
63336
|
+
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
63337
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
62799
63338
|
var BundleCache = class {
|
|
62800
63339
|
constructor(rootDir) {
|
|
62801
63340
|
this.rootDir = rootDir;
|
|
@@ -62803,17 +63342,17 @@ var BundleCache = class {
|
|
|
62803
63342
|
rootDir;
|
|
62804
63343
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
62805
63344
|
async write(snapshotHash, buffer) {
|
|
62806
|
-
await
|
|
62807
|
-
const file =
|
|
63345
|
+
await import_promises15.default.mkdir(this.rootDir, { recursive: true });
|
|
63346
|
+
const file = import_node_path66.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
62808
63347
|
const tmp = `${file}.tmp`;
|
|
62809
|
-
await
|
|
62810
|
-
await
|
|
63348
|
+
await import_promises15.default.writeFile(tmp, buffer, { mode: 384 });
|
|
63349
|
+
await import_promises15.default.rename(tmp, file);
|
|
62811
63350
|
}
|
|
62812
63351
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
62813
63352
|
async read(snapshotHash) {
|
|
62814
|
-
const file =
|
|
63353
|
+
const file = import_node_path66.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
62815
63354
|
try {
|
|
62816
|
-
return await
|
|
63355
|
+
return await import_promises15.default.readFile(file);
|
|
62817
63356
|
} catch (e) {
|
|
62818
63357
|
if (e.code === "ENOENT") return null;
|
|
62819
63358
|
throw e;
|
|
@@ -62821,13 +63360,13 @@ var BundleCache = class {
|
|
|
62821
63360
|
}
|
|
62822
63361
|
/** Idempotent — missing file is not an error. */
|
|
62823
63362
|
async delete(snapshotHash) {
|
|
62824
|
-
const file =
|
|
62825
|
-
await
|
|
63363
|
+
const file = import_node_path66.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63364
|
+
await import_promises15.default.rm(file, { force: true });
|
|
62826
63365
|
}
|
|
62827
63366
|
};
|
|
62828
63367
|
|
|
62829
63368
|
// src/index.ts
|
|
62830
|
-
var
|
|
63369
|
+
var import_meta7 = {};
|
|
62831
63370
|
async function startDaemon(config) {
|
|
62832
63371
|
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
62833
63372
|
const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
|
|
@@ -62842,26 +63381,26 @@ async function startDaemon(config) {
|
|
|
62842
63381
|
},
|
|
62843
63382
|
source: "daemon",
|
|
62844
63383
|
sampling: logShippingCfg.sampling,
|
|
62845
|
-
homeDir:
|
|
63384
|
+
homeDir: import_node_os23.default.homedir()
|
|
62846
63385
|
});
|
|
62847
|
-
const logDir =
|
|
62848
|
-
|
|
63386
|
+
const logDir = import_node_path67.default.join(config.dataDir, "log");
|
|
63387
|
+
import_node_fs51.default.mkdirSync(logDir, { recursive: true });
|
|
62849
63388
|
const logger = createLogger({
|
|
62850
63389
|
level: config.logLevel,
|
|
62851
|
-
file:
|
|
63390
|
+
file: import_node_path67.default.join(logDir, "clawd.log"),
|
|
62852
63391
|
logClient
|
|
62853
63392
|
});
|
|
62854
63393
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
62855
63394
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
62856
|
-
file:
|
|
63395
|
+
file: import_node_path67.default.join(logDir, "screen-idle-probe.log"),
|
|
62857
63396
|
level: "debug"
|
|
62858
63397
|
});
|
|
62859
63398
|
logger.info("screen-idle probe logger enabled", {
|
|
62860
|
-
file:
|
|
63399
|
+
file: import_node_path67.default.join(logDir, "screen-idle-probe.log")
|
|
62861
63400
|
});
|
|
62862
63401
|
const CAP_TARGETS = [
|
|
62863
|
-
|
|
62864
|
-
|
|
63402
|
+
import_node_path67.default.join(logDir, "clawd.log"),
|
|
63403
|
+
import_node_path67.default.join(logDir, "screen-idle-probe.log")
|
|
62865
63404
|
];
|
|
62866
63405
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
62867
63406
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -62957,8 +63496,8 @@ async function startDaemon(config) {
|
|
|
62957
63496
|
const agents = new AgentsScanner();
|
|
62958
63497
|
const history = new ClaudeHistoryReader();
|
|
62959
63498
|
let transport = null;
|
|
62960
|
-
const personaStore = new PersonaStore(
|
|
62961
|
-
const usersRoot =
|
|
63499
|
+
const personaStore = new PersonaStore(import_node_path67.default.join(config.dataDir, "personas"));
|
|
63500
|
+
const usersRoot = import_node_path67.default.join(config.dataDir, "users");
|
|
62962
63501
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
62963
63502
|
if (defaultsRoot) {
|
|
62964
63503
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -62980,7 +63519,7 @@ async function startDaemon(config) {
|
|
|
62980
63519
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
62981
63520
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
62982
63521
|
const dispatchStore = createDispatchStore({
|
|
62983
|
-
filePath:
|
|
63522
|
+
filePath: import_node_path67.default.join(config.dataDir, "dispatch.json"),
|
|
62984
63523
|
now: () => Date.now(),
|
|
62985
63524
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
62986
63525
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -62995,18 +63534,18 @@ async function startDaemon(config) {
|
|
|
62995
63534
|
now: () => Date.now(),
|
|
62996
63535
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
62997
63536
|
});
|
|
62998
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
63537
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path67.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
62999
63538
|
const mcpConfigs = [];
|
|
63000
63539
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
63001
63540
|
const dispatchServerCandidates = [
|
|
63002
|
-
|
|
63541
|
+
import_node_path67.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
63003
63542
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
63004
|
-
|
|
63543
|
+
import_node_path67.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
63005
63544
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
63006
63545
|
];
|
|
63007
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
63546
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63008
63547
|
if (dispatchServerScriptPath) {
|
|
63009
|
-
const dispatchLogPath =
|
|
63548
|
+
const dispatchLogPath = import_node_path67.default.join(logDir, "dispatch-mcp-server.log");
|
|
63010
63549
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
63011
63550
|
dataDir: config.dataDir,
|
|
63012
63551
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -63026,12 +63565,12 @@ async function startDaemon(config) {
|
|
|
63026
63565
|
});
|
|
63027
63566
|
}
|
|
63028
63567
|
const ticketServerCandidates = [
|
|
63029
|
-
|
|
63030
|
-
|
|
63568
|
+
import_node_path67.default.join(here, "ticket", "mcp-server.cjs"),
|
|
63569
|
+
import_node_path67.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
63031
63570
|
];
|
|
63032
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
63571
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63033
63572
|
if (ticketServerScriptPath) {
|
|
63034
|
-
const ticketLogPath =
|
|
63573
|
+
const ticketLogPath = import_node_path67.default.join(logDir, "ticket-mcp-server.log");
|
|
63035
63574
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
63036
63575
|
dataDir: config.dataDir,
|
|
63037
63576
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -63053,12 +63592,12 @@ async function startDaemon(config) {
|
|
|
63053
63592
|
});
|
|
63054
63593
|
}
|
|
63055
63594
|
const shiftServerCandidates = [
|
|
63056
|
-
|
|
63057
|
-
|
|
63595
|
+
import_node_path67.default.join(here, "shift", "mcp-server.cjs"),
|
|
63596
|
+
import_node_path67.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
63058
63597
|
];
|
|
63059
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
63598
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63060
63599
|
if (shiftServerScriptPath) {
|
|
63061
|
-
const shiftLogPath =
|
|
63600
|
+
const shiftLogPath = import_node_path67.default.join(logDir, "shift-mcp-server.log");
|
|
63062
63601
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
63063
63602
|
dataDir: config.dataDir,
|
|
63064
63603
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -63079,12 +63618,12 @@ async function startDaemon(config) {
|
|
|
63079
63618
|
);
|
|
63080
63619
|
}
|
|
63081
63620
|
const inboxServerCandidates = [
|
|
63082
|
-
|
|
63083
|
-
|
|
63621
|
+
import_node_path67.default.join(here, "inbox", "mcp-server.cjs"),
|
|
63622
|
+
import_node_path67.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
63084
63623
|
];
|
|
63085
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
63624
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63086
63625
|
if (inboxServerScriptPath) {
|
|
63087
|
-
const inboxLogPath =
|
|
63626
|
+
const inboxLogPath = import_node_path67.default.join(logDir, "inbox-mcp-server.log");
|
|
63088
63627
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
63089
63628
|
dataDir: config.dataDir,
|
|
63090
63629
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -63105,10 +63644,10 @@ async function startDaemon(config) {
|
|
|
63105
63644
|
);
|
|
63106
63645
|
}
|
|
63107
63646
|
const peerOpsServerCandidates = [
|
|
63108
|
-
|
|
63109
|
-
|
|
63647
|
+
import_node_path67.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
63648
|
+
import_node_path67.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
63110
63649
|
];
|
|
63111
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
63650
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63112
63651
|
if (peerOpsServerScriptPath) {
|
|
63113
63652
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
63114
63653
|
dataDir: config.dataDir,
|
|
@@ -63128,12 +63667,12 @@ async function startDaemon(config) {
|
|
|
63128
63667
|
);
|
|
63129
63668
|
}
|
|
63130
63669
|
const rpcToolServerCandidates = [
|
|
63131
|
-
|
|
63132
|
-
|
|
63670
|
+
import_node_path67.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
63671
|
+
import_node_path67.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
63133
63672
|
];
|
|
63134
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
63673
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
|
|
63135
63674
|
if (rpcToolServerScriptPath) {
|
|
63136
|
-
const rpcToolLogPath =
|
|
63675
|
+
const rpcToolLogPath = import_node_path67.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
63137
63676
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
63138
63677
|
dataDir: config.dataDir,
|
|
63139
63678
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -63154,7 +63693,7 @@ async function startDaemon(config) {
|
|
|
63154
63693
|
);
|
|
63155
63694
|
}
|
|
63156
63695
|
const shiftStore = createShiftStore({
|
|
63157
|
-
filePath:
|
|
63696
|
+
filePath: import_node_path67.default.join(config.dataDir, "shift.json"),
|
|
63158
63697
|
ownerIdProvider: () => ownerPrincipalId,
|
|
63159
63698
|
now: () => Date.now()
|
|
63160
63699
|
});
|
|
@@ -63176,7 +63715,7 @@ async function startDaemon(config) {
|
|
|
63176
63715
|
getAdapter,
|
|
63177
63716
|
historyReader: history,
|
|
63178
63717
|
dataDir: config.dataDir,
|
|
63179
|
-
personaRoot:
|
|
63718
|
+
personaRoot: import_node_path67.default.join(config.dataDir, "personas"),
|
|
63180
63719
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
63181
63720
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
63182
63721
|
getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
|
|
@@ -63227,10 +63766,10 @@ async function startDaemon(config) {
|
|
|
63227
63766
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
63228
63767
|
attachmentGroup: {
|
|
63229
63768
|
onFileEdit: (input) => {
|
|
63230
|
-
const absPath =
|
|
63769
|
+
const absPath = import_node_path67.default.isAbsolute(input.relPath) ? input.relPath : import_node_path67.default.join(input.cwd, input.relPath);
|
|
63231
63770
|
let size = 0;
|
|
63232
63771
|
try {
|
|
63233
|
-
size =
|
|
63772
|
+
size = import_node_fs51.default.statSync(absPath).size;
|
|
63234
63773
|
} catch (err) {
|
|
63235
63774
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
63236
63775
|
sessionId: input.sessionId,
|
|
@@ -63436,6 +63975,8 @@ async function startDaemon(config) {
|
|
|
63436
63975
|
// dispatch / shift-internal 两组,只看 buildMethodHandlers 内部表会误报死方法)
|
|
63437
63976
|
feishuActive: () => feishuActive,
|
|
63438
63977
|
getAllHandlers: () => handlers,
|
|
63978
|
+
// onboarding 判定(info 帧字段)+ importExternal 台账落点
|
|
63979
|
+
dataDir: config.dataDir,
|
|
63439
63980
|
manager,
|
|
63440
63981
|
workspace,
|
|
63441
63982
|
skills,
|
|
@@ -63477,11 +64018,11 @@ async function startDaemon(config) {
|
|
|
63477
64018
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
63478
64019
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
63479
64020
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
63480
|
-
personaRoot:
|
|
64021
|
+
personaRoot: import_node_path67.default.join(config.dataDir, "personas"),
|
|
63481
64022
|
usersRoot
|
|
63482
64023
|
},
|
|
63483
64024
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
63484
|
-
personaRoot:
|
|
64025
|
+
personaRoot: import_node_path67.default.join(config.dataDir, "personas"),
|
|
63485
64026
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
63486
64027
|
usersRoot,
|
|
63487
64028
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -63607,11 +64148,11 @@ async function startDaemon(config) {
|
|
|
63607
64148
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
63608
64149
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
63609
64150
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
63610
|
-
appBuilderPersonaRoot:
|
|
64151
|
+
appBuilderPersonaRoot: import_node_path67.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
63611
64152
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
63612
|
-
deployKitRoot:
|
|
64153
|
+
deployKitRoot: import_node_path67.default.join(config.dataDir, "deploy-kit"),
|
|
63613
64154
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
63614
|
-
resolvePersonaRoot: (personaId2) =>
|
|
64155
|
+
resolvePersonaRoot: (personaId2) => import_node_path67.default.join(config.dataDir, "personas", personaId2),
|
|
63615
64156
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
63616
64157
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
63617
64158
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -63654,7 +64195,7 @@ async function startDaemon(config) {
|
|
|
63654
64195
|
sourceSessionId: args.sourceSessionId
|
|
63655
64196
|
});
|
|
63656
64197
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
63657
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
64198
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os23.default.homedir());
|
|
63658
64199
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
63659
64200
|
dispatchId: args.dispatchId,
|
|
63660
64201
|
sourceJsonlPath,
|
|
@@ -63716,7 +64257,7 @@ async function startDaemon(config) {
|
|
|
63716
64257
|
});
|
|
63717
64258
|
shiftScheduler.start();
|
|
63718
64259
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
63719
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
64260
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path67.default.join(config.dataDir, "personas"));
|
|
63720
64261
|
const larkBotCloud = createLarkBotCloudClient({
|
|
63721
64262
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
63722
64263
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -63730,7 +64271,7 @@ async function startDaemon(config) {
|
|
|
63730
64271
|
store: larkBotStore,
|
|
63731
64272
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
63732
64273
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
63733
|
-
mediaRootFor: (chatId) =>
|
|
64274
|
+
mediaRootFor: (chatId) => import_node_path67.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
63734
64275
|
isShuttingDown: () => larkDraining,
|
|
63735
64276
|
logger: {
|
|
63736
64277
|
warn: (msg) => logger.warn(msg),
|
|
@@ -63756,6 +64297,24 @@ async function startDaemon(config) {
|
|
|
63756
64297
|
logger: { warn: (msg) => logger.warn(msg) }
|
|
63757
64298
|
};
|
|
63758
64299
|
Object.assign(handlers, buildLarkBotHandlers(larkBotDeps));
|
|
64300
|
+
Object.assign(
|
|
64301
|
+
handlers,
|
|
64302
|
+
buildOnboardingHandlers({
|
|
64303
|
+
dataDir: config.dataDir,
|
|
64304
|
+
// 现读(登录/登出热切换);unionId 缺失时回落 ownerId(老登录记录无 unionId)
|
|
64305
|
+
getOwnerIdentity: () => {
|
|
64306
|
+
const rec3 = ownerIdentityStore.read();
|
|
64307
|
+
if (!rec3) return null;
|
|
64308
|
+
return {
|
|
64309
|
+
unionId: rec3.identity.unionId ?? rec3.identity.ownerId,
|
|
64310
|
+
displayName: rec3.identity.displayName
|
|
64311
|
+
};
|
|
64312
|
+
},
|
|
64313
|
+
apiUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
64314
|
+
apiKey: resolveClawdTicketsApiKey(),
|
|
64315
|
+
deviceId: authFile.deviceId
|
|
64316
|
+
})
|
|
64317
|
+
);
|
|
63759
64318
|
const authResolver = new AuthContextResolver({
|
|
63760
64319
|
ownerToken: resolvedAuthToken
|
|
63761
64320
|
});
|
|
@@ -63874,6 +64433,8 @@ async function startDaemon(config) {
|
|
|
63874
64433
|
{
|
|
63875
64434
|
manager,
|
|
63876
64435
|
getAdapter,
|
|
64436
|
+
// onboarding 判定:ready 帧携带 profile.json 的 onboardingCompletedAt
|
|
64437
|
+
dataDir: config.dataDir,
|
|
63877
64438
|
getTunnelUrl: () => currentTunnelUrl,
|
|
63878
64439
|
getLogShipping: () => config.logShipping ? {
|
|
63879
64440
|
endpoint: config.logShipping.endpoint,
|
|
@@ -64014,11 +64575,11 @@ async function startDaemon(config) {
|
|
|
64014
64575
|
const lines = [
|
|
64015
64576
|
`Tunnel: ${r.url}`,
|
|
64016
64577
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
64017
|
-
`Frpc config: ${
|
|
64018
|
-
`Frpc log: ${
|
|
64578
|
+
`Frpc config: ${import_node_path67.default.join(config.dataDir, "frpc.toml")}`,
|
|
64579
|
+
`Frpc log: ${import_node_path67.default.join(logDir, "frpc.log")}`
|
|
64019
64580
|
];
|
|
64020
|
-
const
|
|
64021
|
-
const bar = "\u2550".repeat(
|
|
64581
|
+
const width2 = Math.max(...lines.map((l) => l.length));
|
|
64582
|
+
const bar = "\u2550".repeat(width2 + 4);
|
|
64022
64583
|
process.stdout.write(`
|
|
64023
64584
|
${bar}
|
|
64024
64585
|
`);
|
|
@@ -64028,8 +64589,8 @@ ${bar}
|
|
|
64028
64589
|
|
|
64029
64590
|
`);
|
|
64030
64591
|
try {
|
|
64031
|
-
const connectPath =
|
|
64032
|
-
|
|
64592
|
+
const connectPath = import_node_path67.default.join(config.dataDir, "connect.txt");
|
|
64593
|
+
import_node_fs51.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
64033
64594
|
} catch {
|
|
64034
64595
|
}
|
|
64035
64596
|
} catch (err) {
|
|
@@ -64104,9 +64665,9 @@ ${bar}
|
|
|
64104
64665
|
};
|
|
64105
64666
|
}
|
|
64106
64667
|
function migrateDropPersonsDir(dataDir) {
|
|
64107
|
-
const dir =
|
|
64668
|
+
const dir = import_node_path67.default.join(dataDir, "persons");
|
|
64108
64669
|
try {
|
|
64109
|
-
|
|
64670
|
+
import_node_fs51.default.rmSync(dir, { recursive: true, force: true });
|
|
64110
64671
|
} catch {
|
|
64111
64672
|
}
|
|
64112
64673
|
}
|