@clawos-dev/clawd 0.2.142 → 0.2.143-beta.300.c2a3792
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 +664 -1367
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +0 -3
- package/dist/persona-defaults/persona-bug-fixer/CLAUDE.md +0 -2
- package/dist/persona-defaults/persona-dataclaw-builder/.mcp.json +4 -0
- package/dist/persona-defaults/persona-dataclaw-builder/.secrets/dataclaw.env.example +3 -0
- package/dist/persona-defaults/persona-dataclaw-builder/CLAUDE.md +20 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/README.md +96 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/config.env +20 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/contract/bootstrap +22 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/contract/s.yaml.tmpl +59 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/.env.example +15 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/.fcignore +7 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/nest-cli.json +8 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/package.json +29 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/app.module.ts +13 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/gate.ts +70 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/session.ts +52 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/ttc-user-info.ts +23 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.client.ts +83 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.config.ts +18 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.controller.ts +30 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.module.ts +9 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/main.ts +116 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/polyfill.ts +6 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/tsconfig.json +14 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/index.html +12 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/package.json +18 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/App.jsx +9 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/api.js +19 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/auth.js +7 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/BarChart.jsx +38 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/FilterRow.jsx +79 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/ResultCards.jsx +17 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/ResultTable.jsx +21 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/SchemaFilters.jsx +93 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/enums.js +22 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/main.jsx +6 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/pages/PerformanceQueryPage.jsx +102 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/styles.css +83 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/vite.config.js +30 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/scripts/ensure-toolchain.sh +62 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/scripts/new-extension.sh +66 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/scripts/publish.sh +129 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/scripts/remove-extension.sh +70 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/scripts/verify.sh +38 -0
- package/dist/persona-defaults/persona-developer/CLAUDE.md +0 -2
- package/package.json +2 -5
- package/dist/dispatch/mcp-server.cjs +0 -39756
package/dist/cli.cjs
CHANGED
|
@@ -720,8 +720,8 @@ var init_parseUtil = __esm({
|
|
|
720
720
|
init_errors2();
|
|
721
721
|
init_en();
|
|
722
722
|
makeIssue = (params) => {
|
|
723
|
-
const { data, path:
|
|
724
|
-
const fullPath = [...
|
|
723
|
+
const { data, path: path58, errorMaps, issueData } = params;
|
|
724
|
+
const fullPath = [...path58, ...issueData.path || []];
|
|
725
725
|
const fullIssue = {
|
|
726
726
|
...issueData,
|
|
727
727
|
path: fullPath
|
|
@@ -1032,11 +1032,11 @@ var init_types = __esm({
|
|
|
1032
1032
|
init_parseUtil();
|
|
1033
1033
|
init_util();
|
|
1034
1034
|
ParseInputLazyPath = class {
|
|
1035
|
-
constructor(parent, value,
|
|
1035
|
+
constructor(parent, value, path58, key) {
|
|
1036
1036
|
this._cachedPath = [];
|
|
1037
1037
|
this.parent = parent;
|
|
1038
1038
|
this.data = value;
|
|
1039
|
-
this._path =
|
|
1039
|
+
this._path = path58;
|
|
1040
1040
|
this._key = key;
|
|
1041
1041
|
}
|
|
1042
1042
|
get path() {
|
|
@@ -4752,13 +4752,6 @@ var init_schemas = __esm({
|
|
|
4752
4752
|
* - native `session:*` handler 完全不感知 mirror(UI 操作 mirror 不走 native 路径)
|
|
4753
4753
|
*/
|
|
4754
4754
|
originOwnerPrincipalId: external_exports.string().min(1).optional(),
|
|
4755
|
-
/**
|
|
4756
|
-
* Dispatch 派生的 session 在 create 时记录源 session 的 sessionId(稳定 key);
|
|
4757
|
-
* sidebar 据此把 dispatch 出来的 sub-session 折叠在源 session 下。非 dispatch session 缺省。
|
|
4758
|
-
* mirror SessionFile 上必须 strip(朋友 daemon 上的 sessionId 在本机无意义,会让本机
|
|
4759
|
-
* 反查路径走错;按 #750 一族防线处理,跟 ownerPersonaId 同地点 strip)。
|
|
4760
|
-
*/
|
|
4761
|
-
dispatchedFromSessionId: external_exports.string().min(1).optional(),
|
|
4762
4755
|
createdAt: external_exports.string().min(1),
|
|
4763
4756
|
updatedAt: external_exports.string().min(1)
|
|
4764
4757
|
});
|
|
@@ -5899,7 +5892,9 @@ var init_feishu_auth = __esm({
|
|
|
5899
5892
|
/** 显示名。TTC user_info 接口 data.name */
|
|
5900
5893
|
displayName: external_exports.string().min(1),
|
|
5901
5894
|
/** TTC user_info 接口 data.avatar_url,可缺省 */
|
|
5902
|
-
avatarUrl: external_exports.string().optional()
|
|
5895
|
+
avatarUrl: external_exports.string().optional(),
|
|
5896
|
+
/** TTC user_info 接口 data.union_id(飞书 union_id;dataclaw 可信入口 X-User-UnionId 用),可缺省 */
|
|
5897
|
+
unionId: external_exports.string().optional()
|
|
5903
5898
|
});
|
|
5904
5899
|
AuthLoginStartResponseSchema = external_exports.object({
|
|
5905
5900
|
type: external_exports.literal("auth:login:start:ok"),
|
|
@@ -5933,60 +5928,6 @@ var init_feishu_auth = __esm({
|
|
|
5933
5928
|
}
|
|
5934
5929
|
});
|
|
5935
5930
|
|
|
5936
|
-
// ../protocol/src/dispatch.ts
|
|
5937
|
-
var DispatchOutcomeSchema, DispatchRunArgsSchema, DispatchCompleteArgsSchema;
|
|
5938
|
-
var init_dispatch = __esm({
|
|
5939
|
-
"../protocol/src/dispatch.ts"() {
|
|
5940
|
-
"use strict";
|
|
5941
|
-
init_zod();
|
|
5942
|
-
DispatchOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
5943
|
-
external_exports.object({
|
|
5944
|
-
kind: external_exports.literal("success"),
|
|
5945
|
-
text: external_exports.string(),
|
|
5946
|
-
filePaths: external_exports.array(external_exports.string()).optional()
|
|
5947
|
-
}),
|
|
5948
|
-
external_exports.object({
|
|
5949
|
-
kind: external_exports.literal("failure"),
|
|
5950
|
-
reason: external_exports.string()
|
|
5951
|
-
})
|
|
5952
|
-
]);
|
|
5953
|
-
DispatchRunArgsSchema = external_exports.object({
|
|
5954
|
-
targetPersona: external_exports.string().min(1),
|
|
5955
|
-
prompt: external_exports.string()
|
|
5956
|
-
});
|
|
5957
|
-
DispatchCompleteArgsSchema = external_exports.object({
|
|
5958
|
-
dispatchId: external_exports.string().min(1),
|
|
5959
|
-
outcome: DispatchOutcomeSchema
|
|
5960
|
-
});
|
|
5961
|
-
}
|
|
5962
|
-
});
|
|
5963
|
-
|
|
5964
|
-
// ../protocol/src/log.ts
|
|
5965
|
-
var LOG_SOURCES, LogSourceSchema, LOG_LEVELS, LogLevelSchema, LogRecordSchema;
|
|
5966
|
-
var init_log = __esm({
|
|
5967
|
-
"../protocol/src/log.ts"() {
|
|
5968
|
-
"use strict";
|
|
5969
|
-
init_zod();
|
|
5970
|
-
LOG_SOURCES = ["daemon", "main", "renderer"];
|
|
5971
|
-
LogSourceSchema = external_exports.enum(LOG_SOURCES);
|
|
5972
|
-
LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
5973
|
-
LogLevelSchema = external_exports.enum(LOG_LEVELS);
|
|
5974
|
-
LogRecordSchema = external_exports.object({
|
|
5975
|
-
ts: external_exports.number().int(),
|
|
5976
|
-
source: LogSourceSchema,
|
|
5977
|
-
level: LogLevelSchema,
|
|
5978
|
-
msg: external_exports.string(),
|
|
5979
|
-
ownerPrincipalId: external_exports.string(),
|
|
5980
|
-
deviceId: external_exports.string(),
|
|
5981
|
-
appVersion: external_exports.string(),
|
|
5982
|
-
daemonVersion: external_exports.string().optional(),
|
|
5983
|
-
os: external_exports.string(),
|
|
5984
|
-
meta_json: external_exports.string().optional(),
|
|
5985
|
-
sessionId: external_exports.string().optional()
|
|
5986
|
-
});
|
|
5987
|
-
}
|
|
5988
|
-
});
|
|
5989
|
-
|
|
5990
5931
|
// ../protocol/src/runtime.ts
|
|
5991
5932
|
var init_runtime = __esm({
|
|
5992
5933
|
"../protocol/src/runtime.ts"() {
|
|
@@ -6005,8 +5946,6 @@ var init_runtime = __esm({
|
|
|
6005
5946
|
init_contact();
|
|
6006
5947
|
init_extension();
|
|
6007
5948
|
init_feishu_auth();
|
|
6008
|
-
init_dispatch();
|
|
6009
|
-
init_log();
|
|
6010
5949
|
}
|
|
6011
5950
|
});
|
|
6012
5951
|
|
|
@@ -6281,8 +6220,8 @@ var require_req = __commonJS({
|
|
|
6281
6220
|
if (req.originalUrl) {
|
|
6282
6221
|
_req.url = req.originalUrl;
|
|
6283
6222
|
} else {
|
|
6284
|
-
const
|
|
6285
|
-
_req.url = typeof
|
|
6223
|
+
const path58 = req.path;
|
|
6224
|
+
_req.url = typeof path58 === "string" ? path58 : req.url ? req.url.path || req.url : void 0;
|
|
6286
6225
|
}
|
|
6287
6226
|
if (req.query) {
|
|
6288
6227
|
_req.query = req.query;
|
|
@@ -6447,14 +6386,14 @@ var require_redact = __commonJS({
|
|
|
6447
6386
|
}
|
|
6448
6387
|
return obj;
|
|
6449
6388
|
}
|
|
6450
|
-
function parsePath(
|
|
6389
|
+
function parsePath(path58) {
|
|
6451
6390
|
const parts = [];
|
|
6452
6391
|
let current = "";
|
|
6453
6392
|
let inBrackets = false;
|
|
6454
6393
|
let inQuotes = false;
|
|
6455
6394
|
let quoteChar = "";
|
|
6456
|
-
for (let i = 0; i <
|
|
6457
|
-
const char =
|
|
6395
|
+
for (let i = 0; i < path58.length; i++) {
|
|
6396
|
+
const char = path58[i];
|
|
6458
6397
|
if (!inBrackets && char === ".") {
|
|
6459
6398
|
if (current) {
|
|
6460
6399
|
parts.push(current);
|
|
@@ -6585,10 +6524,10 @@ var require_redact = __commonJS({
|
|
|
6585
6524
|
return current;
|
|
6586
6525
|
}
|
|
6587
6526
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6588
|
-
for (const
|
|
6589
|
-
const parts = parsePath(
|
|
6527
|
+
for (const path58 of paths) {
|
|
6528
|
+
const parts = parsePath(path58);
|
|
6590
6529
|
if (parts.includes("*")) {
|
|
6591
|
-
redactWildcardPath(obj, parts, censor,
|
|
6530
|
+
redactWildcardPath(obj, parts, censor, path58, remove);
|
|
6592
6531
|
} else {
|
|
6593
6532
|
if (remove) {
|
|
6594
6533
|
removeKey(obj, parts);
|
|
@@ -6673,8 +6612,8 @@ var require_redact = __commonJS({
|
|
|
6673
6612
|
}
|
|
6674
6613
|
} else {
|
|
6675
6614
|
if (afterWildcard.includes("*")) {
|
|
6676
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6677
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6615
|
+
const wrappedCensor = typeof censor === "function" ? (value, path58) => {
|
|
6616
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path58];
|
|
6678
6617
|
return censor(value, fullPath);
|
|
6679
6618
|
} : censor;
|
|
6680
6619
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6709,8 +6648,8 @@ var require_redact = __commonJS({
|
|
|
6709
6648
|
return null;
|
|
6710
6649
|
}
|
|
6711
6650
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6712
|
-
for (const
|
|
6713
|
-
const parts = parsePath(
|
|
6651
|
+
for (const path58 of pathsToClone) {
|
|
6652
|
+
const parts = parsePath(path58);
|
|
6714
6653
|
let current = pathStructure;
|
|
6715
6654
|
for (let i = 0; i < parts.length; i++) {
|
|
6716
6655
|
const part = parts[i];
|
|
@@ -6762,24 +6701,24 @@ var require_redact = __commonJS({
|
|
|
6762
6701
|
}
|
|
6763
6702
|
return cloneSelectively(obj, pathStructure);
|
|
6764
6703
|
}
|
|
6765
|
-
function validatePath(
|
|
6766
|
-
if (typeof
|
|
6704
|
+
function validatePath(path58) {
|
|
6705
|
+
if (typeof path58 !== "string") {
|
|
6767
6706
|
throw new Error("Paths must be (non-empty) strings");
|
|
6768
6707
|
}
|
|
6769
|
-
if (
|
|
6708
|
+
if (path58 === "") {
|
|
6770
6709
|
throw new Error("Invalid redaction path ()");
|
|
6771
6710
|
}
|
|
6772
|
-
if (
|
|
6773
|
-
throw new Error(`Invalid redaction path (${
|
|
6711
|
+
if (path58.includes("..")) {
|
|
6712
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6774
6713
|
}
|
|
6775
|
-
if (
|
|
6776
|
-
throw new Error(`Invalid redaction path (${
|
|
6714
|
+
if (path58.includes(",")) {
|
|
6715
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6777
6716
|
}
|
|
6778
6717
|
let bracketCount = 0;
|
|
6779
6718
|
let inQuotes = false;
|
|
6780
6719
|
let quoteChar = "";
|
|
6781
|
-
for (let i = 0; i <
|
|
6782
|
-
const char =
|
|
6720
|
+
for (let i = 0; i < path58.length; i++) {
|
|
6721
|
+
const char = path58[i];
|
|
6783
6722
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6784
6723
|
if (!inQuotes) {
|
|
6785
6724
|
inQuotes = true;
|
|
@@ -6793,20 +6732,20 @@ var require_redact = __commonJS({
|
|
|
6793
6732
|
} else if (char === "]" && !inQuotes) {
|
|
6794
6733
|
bracketCount--;
|
|
6795
6734
|
if (bracketCount < 0) {
|
|
6796
|
-
throw new Error(`Invalid redaction path (${
|
|
6735
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6797
6736
|
}
|
|
6798
6737
|
}
|
|
6799
6738
|
}
|
|
6800
6739
|
if (bracketCount !== 0) {
|
|
6801
|
-
throw new Error(`Invalid redaction path (${
|
|
6740
|
+
throw new Error(`Invalid redaction path (${path58})`);
|
|
6802
6741
|
}
|
|
6803
6742
|
}
|
|
6804
6743
|
function validatePaths(paths) {
|
|
6805
6744
|
if (!Array.isArray(paths)) {
|
|
6806
6745
|
throw new TypeError("paths must be an array");
|
|
6807
6746
|
}
|
|
6808
|
-
for (const
|
|
6809
|
-
validatePath(
|
|
6747
|
+
for (const path58 of paths) {
|
|
6748
|
+
validatePath(path58);
|
|
6810
6749
|
}
|
|
6811
6750
|
}
|
|
6812
6751
|
function slowRedact(options = {}) {
|
|
@@ -6974,8 +6913,8 @@ var require_redaction = __commonJS({
|
|
|
6974
6913
|
if (shape[k2] === null) {
|
|
6975
6914
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6976
6915
|
} else {
|
|
6977
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6978
|
-
return censor(value, [k2, ...
|
|
6916
|
+
const wrappedCensor = typeof censor === "function" ? (value, path58) => {
|
|
6917
|
+
return censor(value, [k2, ...path58]);
|
|
6979
6918
|
} : censor;
|
|
6980
6919
|
o[k2] = Redact({
|
|
6981
6920
|
paths: shape[k2],
|
|
@@ -7159,7 +7098,7 @@ var require_atomic_sleep = __commonJS({
|
|
|
7159
7098
|
"../node_modules/.pnpm/atomic-sleep@1.0.0/node_modules/atomic-sleep/index.js"(exports2, module2) {
|
|
7160
7099
|
"use strict";
|
|
7161
7100
|
if (typeof SharedArrayBuffer !== "undefined" && typeof Atomics !== "undefined") {
|
|
7162
|
-
let
|
|
7101
|
+
let sleep = function(ms) {
|
|
7163
7102
|
const valid = ms > 0 && ms < Infinity;
|
|
7164
7103
|
if (valid === false) {
|
|
7165
7104
|
if (typeof ms !== "number" && typeof ms !== "bigint") {
|
|
@@ -7170,9 +7109,9 @@ var require_atomic_sleep = __commonJS({
|
|
|
7170
7109
|
Atomics.wait(nil, 0, 0, Number(ms));
|
|
7171
7110
|
};
|
|
7172
7111
|
const nil = new Int32Array(new SharedArrayBuffer(4));
|
|
7173
|
-
module2.exports =
|
|
7112
|
+
module2.exports = sleep;
|
|
7174
7113
|
} else {
|
|
7175
|
-
let
|
|
7114
|
+
let sleep = function(ms) {
|
|
7176
7115
|
const valid = ms > 0 && ms < Infinity;
|
|
7177
7116
|
if (valid === false) {
|
|
7178
7117
|
if (typeof ms !== "number" && typeof ms !== "bigint") {
|
|
@@ -7184,7 +7123,7 @@ var require_atomic_sleep = __commonJS({
|
|
|
7184
7123
|
while (target > Date.now()) {
|
|
7185
7124
|
}
|
|
7186
7125
|
};
|
|
7187
|
-
module2.exports =
|
|
7126
|
+
module2.exports = sleep;
|
|
7188
7127
|
}
|
|
7189
7128
|
}
|
|
7190
7129
|
});
|
|
@@ -7193,11 +7132,11 @@ var require_atomic_sleep = __commonJS({
|
|
|
7193
7132
|
var require_sonic_boom = __commonJS({
|
|
7194
7133
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7195
7134
|
"use strict";
|
|
7196
|
-
var
|
|
7135
|
+
var fs51 = require("fs");
|
|
7197
7136
|
var EventEmitter3 = require("events");
|
|
7198
7137
|
var inherits = require("util").inherits;
|
|
7199
|
-
var
|
|
7200
|
-
var
|
|
7138
|
+
var path58 = require("path");
|
|
7139
|
+
var sleep = require_atomic_sleep();
|
|
7201
7140
|
var assert = require("assert");
|
|
7202
7141
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
7203
7142
|
var kEmptyBuffer = Buffer.allocUnsafe(0);
|
|
@@ -7250,20 +7189,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7250
7189
|
const mode = sonic.mode;
|
|
7251
7190
|
if (sonic.sync) {
|
|
7252
7191
|
try {
|
|
7253
|
-
if (sonic.mkdir)
|
|
7254
|
-
const fd =
|
|
7192
|
+
if (sonic.mkdir) fs51.mkdirSync(path58.dirname(file), { recursive: true });
|
|
7193
|
+
const fd = fs51.openSync(file, flags, mode);
|
|
7255
7194
|
fileOpened(null, fd);
|
|
7256
7195
|
} catch (err) {
|
|
7257
7196
|
fileOpened(err);
|
|
7258
7197
|
throw err;
|
|
7259
7198
|
}
|
|
7260
7199
|
} else if (sonic.mkdir) {
|
|
7261
|
-
|
|
7200
|
+
fs51.mkdir(path58.dirname(file), { recursive: true }, (err) => {
|
|
7262
7201
|
if (err) return fileOpened(err);
|
|
7263
|
-
|
|
7202
|
+
fs51.open(file, flags, mode, fileOpened);
|
|
7264
7203
|
});
|
|
7265
7204
|
} else {
|
|
7266
|
-
|
|
7205
|
+
fs51.open(file, flags, mode, fileOpened);
|
|
7267
7206
|
}
|
|
7268
7207
|
}
|
|
7269
7208
|
function SonicBoom(opts) {
|
|
@@ -7304,8 +7243,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7304
7243
|
this.flush = flushBuffer;
|
|
7305
7244
|
this.flushSync = flushBufferSync;
|
|
7306
7245
|
this._actualWrite = actualWriteBuffer;
|
|
7307
|
-
fsWriteSync = () =>
|
|
7308
|
-
fsWrite = () =>
|
|
7246
|
+
fsWriteSync = () => fs51.writeSync(this.fd, this._writingBuf);
|
|
7247
|
+
fsWrite = () => fs51.write(this.fd, this._writingBuf, this.release);
|
|
7309
7248
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7310
7249
|
this._writingBuf = "";
|
|
7311
7250
|
this.write = write;
|
|
@@ -7314,15 +7253,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7314
7253
|
this._actualWrite = actualWrite;
|
|
7315
7254
|
fsWriteSync = () => {
|
|
7316
7255
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7317
|
-
return
|
|
7256
|
+
return fs51.writeSync(this.fd, this._writingBuf);
|
|
7318
7257
|
}
|
|
7319
|
-
return
|
|
7258
|
+
return fs51.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7320
7259
|
};
|
|
7321
7260
|
fsWrite = () => {
|
|
7322
7261
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7323
|
-
return
|
|
7262
|
+
return fs51.write(this.fd, this._writingBuf, this.release);
|
|
7324
7263
|
}
|
|
7325
|
-
return
|
|
7264
|
+
return fs51.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7326
7265
|
};
|
|
7327
7266
|
} else {
|
|
7328
7267
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7343,7 +7282,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7343
7282
|
if ((err.code === "EAGAIN" || err.code === "EBUSY") && this.retryEAGAIN(err, this._writingBuf.length, this._len - this._writingBuf.length)) {
|
|
7344
7283
|
if (this.sync) {
|
|
7345
7284
|
try {
|
|
7346
|
-
|
|
7285
|
+
sleep(BUSY_WRITE_TIMEOUT);
|
|
7347
7286
|
this.release(void 0, 0);
|
|
7348
7287
|
} catch (err2) {
|
|
7349
7288
|
this.release(err2);
|
|
@@ -7379,7 +7318,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7379
7318
|
}
|
|
7380
7319
|
}
|
|
7381
7320
|
if (this._fsync) {
|
|
7382
|
-
|
|
7321
|
+
fs51.fsyncSync(this.fd);
|
|
7383
7322
|
}
|
|
7384
7323
|
const len = this._len;
|
|
7385
7324
|
if (this._reopening) {
|
|
@@ -7493,7 +7432,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7493
7432
|
const onDrain = () => {
|
|
7494
7433
|
if (!this._fsync) {
|
|
7495
7434
|
try {
|
|
7496
|
-
|
|
7435
|
+
fs51.fsync(this.fd, (err) => {
|
|
7497
7436
|
this._flushPending = false;
|
|
7498
7437
|
cb(err);
|
|
7499
7438
|
});
|
|
@@ -7595,7 +7534,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7595
7534
|
const fd = this.fd;
|
|
7596
7535
|
this.once("ready", () => {
|
|
7597
7536
|
if (fd !== this.fd) {
|
|
7598
|
-
|
|
7537
|
+
fs51.close(fd, (err) => {
|
|
7599
7538
|
if (err) {
|
|
7600
7539
|
return this.emit("error", err);
|
|
7601
7540
|
}
|
|
@@ -7644,7 +7583,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7644
7583
|
buf = this._bufs[0];
|
|
7645
7584
|
}
|
|
7646
7585
|
try {
|
|
7647
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7586
|
+
const n = Buffer.isBuffer(buf) ? fs51.writeSync(this.fd, buf) : fs51.writeSync(this.fd, buf, "utf8");
|
|
7648
7587
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7649
7588
|
buf = releasedBufObj.writingBuf;
|
|
7650
7589
|
this._len = releasedBufObj.len;
|
|
@@ -7656,11 +7595,11 @@ var require_sonic_boom = __commonJS({
|
|
|
7656
7595
|
if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
|
|
7657
7596
|
throw err;
|
|
7658
7597
|
}
|
|
7659
|
-
|
|
7598
|
+
sleep(BUSY_WRITE_TIMEOUT);
|
|
7660
7599
|
}
|
|
7661
7600
|
}
|
|
7662
7601
|
try {
|
|
7663
|
-
|
|
7602
|
+
fs51.fsyncSync(this.fd);
|
|
7664
7603
|
} catch {
|
|
7665
7604
|
}
|
|
7666
7605
|
}
|
|
@@ -7681,7 +7620,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7681
7620
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7682
7621
|
}
|
|
7683
7622
|
try {
|
|
7684
|
-
const n =
|
|
7623
|
+
const n = fs51.writeSync(this.fd, buf);
|
|
7685
7624
|
buf = buf.subarray(n);
|
|
7686
7625
|
this._len = Math.max(this._len - n, 0);
|
|
7687
7626
|
if (buf.length <= 0) {
|
|
@@ -7693,7 +7632,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7693
7632
|
if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
|
|
7694
7633
|
throw err;
|
|
7695
7634
|
}
|
|
7696
|
-
|
|
7635
|
+
sleep(BUSY_WRITE_TIMEOUT);
|
|
7697
7636
|
}
|
|
7698
7637
|
}
|
|
7699
7638
|
}
|
|
@@ -7709,13 +7648,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7709
7648
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7710
7649
|
if (this.sync) {
|
|
7711
7650
|
try {
|
|
7712
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7651
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs51.writeSync(this.fd, this._writingBuf) : fs51.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7713
7652
|
release(null, written);
|
|
7714
7653
|
} catch (err) {
|
|
7715
7654
|
release(err);
|
|
7716
7655
|
}
|
|
7717
7656
|
} else {
|
|
7718
|
-
|
|
7657
|
+
fs51.write(this.fd, this._writingBuf, release);
|
|
7719
7658
|
}
|
|
7720
7659
|
}
|
|
7721
7660
|
function actualWriteBuffer() {
|
|
@@ -7724,7 +7663,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7724
7663
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7725
7664
|
if (this.sync) {
|
|
7726
7665
|
try {
|
|
7727
|
-
const written =
|
|
7666
|
+
const written = fs51.writeSync(this.fd, this._writingBuf);
|
|
7728
7667
|
release(null, written);
|
|
7729
7668
|
} catch (err) {
|
|
7730
7669
|
release(err);
|
|
@@ -7733,7 +7672,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7733
7672
|
if (kCopyBuffer) {
|
|
7734
7673
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7735
7674
|
}
|
|
7736
|
-
|
|
7675
|
+
fs51.write(this.fd, this._writingBuf, release);
|
|
7737
7676
|
}
|
|
7738
7677
|
}
|
|
7739
7678
|
function actualClose(sonic) {
|
|
@@ -7749,12 +7688,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7749
7688
|
sonic._lens = [];
|
|
7750
7689
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7751
7690
|
try {
|
|
7752
|
-
|
|
7691
|
+
fs51.fsync(sonic.fd, closeWrapped);
|
|
7753
7692
|
} catch {
|
|
7754
7693
|
}
|
|
7755
7694
|
function closeWrapped() {
|
|
7756
7695
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7757
|
-
|
|
7696
|
+
fs51.close(sonic.fd, done);
|
|
7758
7697
|
} else {
|
|
7759
7698
|
done();
|
|
7760
7699
|
}
|
|
@@ -8434,7 +8373,7 @@ var require_transport = __commonJS({
|
|
|
8434
8373
|
var { createRequire } = require("module");
|
|
8435
8374
|
var getCallers = require_caller();
|
|
8436
8375
|
var { join: join15, isAbsolute: isAbsolute2, sep: sep2 } = require("path");
|
|
8437
|
-
var
|
|
8376
|
+
var sleep = require_atomic_sleep();
|
|
8438
8377
|
var onExit = require_on_exit_leak_free();
|
|
8439
8378
|
var ThreadStream = require_thread_stream();
|
|
8440
8379
|
function setupOnExit(stream) {
|
|
@@ -8468,7 +8407,7 @@ var require_transport = __commonJS({
|
|
|
8468
8407
|
return;
|
|
8469
8408
|
}
|
|
8470
8409
|
stream.flushSync();
|
|
8471
|
-
|
|
8410
|
+
sleep(100);
|
|
8472
8411
|
stream.end();
|
|
8473
8412
|
}
|
|
8474
8413
|
return stream;
|
|
@@ -10118,7 +10057,7 @@ var require_multistream = __commonJS({
|
|
|
10118
10057
|
var require_pino = __commonJS({
|
|
10119
10058
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
10120
10059
|
"use strict";
|
|
10121
|
-
var
|
|
10060
|
+
var os21 = require("os");
|
|
10122
10061
|
var stdSerializers = require_pino_std_serializers();
|
|
10123
10062
|
var caller = require_caller();
|
|
10124
10063
|
var redaction = require_redaction();
|
|
@@ -10165,7 +10104,7 @@ var require_pino = __commonJS({
|
|
|
10165
10104
|
} = symbols;
|
|
10166
10105
|
var { epochTime, nullTime } = time;
|
|
10167
10106
|
var { pid } = process;
|
|
10168
|
-
var hostname =
|
|
10107
|
+
var hostname = os21.hostname();
|
|
10169
10108
|
var defaultErrorSerializer = stdSerializers.err;
|
|
10170
10109
|
var defaultOptions = {
|
|
10171
10110
|
level: "info",
|
|
@@ -10889,11 +10828,11 @@ var init_lib = __esm({
|
|
|
10889
10828
|
}
|
|
10890
10829
|
}
|
|
10891
10830
|
},
|
|
10892
|
-
addToPath: function addToPath(
|
|
10893
|
-
var last =
|
|
10831
|
+
addToPath: function addToPath(path58, added, removed, oldPosInc, options) {
|
|
10832
|
+
var last = path58.lastComponent;
|
|
10894
10833
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10895
10834
|
return {
|
|
10896
|
-
oldPos:
|
|
10835
|
+
oldPos: path58.oldPos + oldPosInc,
|
|
10897
10836
|
lastComponent: {
|
|
10898
10837
|
count: last.count + 1,
|
|
10899
10838
|
added,
|
|
@@ -10903,7 +10842,7 @@ var init_lib = __esm({
|
|
|
10903
10842
|
};
|
|
10904
10843
|
} else {
|
|
10905
10844
|
return {
|
|
10906
|
-
oldPos:
|
|
10845
|
+
oldPos: path58.oldPos + oldPosInc,
|
|
10907
10846
|
lastComponent: {
|
|
10908
10847
|
count: 1,
|
|
10909
10848
|
added,
|
|
@@ -11349,10 +11288,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11349
11288
|
const memories = raw.map((m2) => {
|
|
11350
11289
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11351
11290
|
const rec3 = m2;
|
|
11352
|
-
const
|
|
11291
|
+
const path58 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11353
11292
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11354
|
-
if (!
|
|
11355
|
-
const entry = { path:
|
|
11293
|
+
if (!path58 || content == null) return null;
|
|
11294
|
+
const entry = { path: path58, content };
|
|
11356
11295
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11357
11296
|
return entry;
|
|
11358
11297
|
}).filter((m2) => m2 !== null);
|
|
@@ -11872,9 +11811,6 @@ function buildSpawnArgs(ctx) {
|
|
|
11872
11811
|
if (ctx.addDirs) {
|
|
11873
11812
|
for (const dir of ctx.addDirs) args.push("--add-dir", dir);
|
|
11874
11813
|
}
|
|
11875
|
-
if (ctx.dispatchMcpConfigPath) {
|
|
11876
|
-
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
11877
|
-
}
|
|
11878
11814
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
11879
11815
|
if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
|
|
11880
11816
|
return args;
|
|
@@ -12154,10 +12090,10 @@ function parseAttachment(obj) {
|
|
|
12154
12090
|
const memories = raw.map((m2) => {
|
|
12155
12091
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12156
12092
|
const rec3 = m2;
|
|
12157
|
-
const
|
|
12093
|
+
const path58 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12158
12094
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12159
|
-
if (!
|
|
12160
|
-
const out = { path:
|
|
12095
|
+
if (!path58 || content == null) return null;
|
|
12096
|
+
const out = { path: path58, content };
|
|
12161
12097
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12162
12098
|
return out;
|
|
12163
12099
|
}).filter((m2) => m2 !== null);
|
|
@@ -18187,7 +18123,7 @@ var require_validation = __commonJS({
|
|
|
18187
18123
|
var require_receiver = __commonJS({
|
|
18188
18124
|
"../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/receiver.js"(exports2, module2) {
|
|
18189
18125
|
"use strict";
|
|
18190
|
-
var { Writable:
|
|
18126
|
+
var { Writable: Writable2 } = require("stream");
|
|
18191
18127
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
18192
18128
|
var {
|
|
18193
18129
|
BINARY_TYPES,
|
|
@@ -18205,7 +18141,7 @@ var require_receiver = __commonJS({
|
|
|
18205
18141
|
var GET_DATA = 4;
|
|
18206
18142
|
var INFLATING = 5;
|
|
18207
18143
|
var DEFER_EVENT = 6;
|
|
18208
|
-
var Receiver2 = class extends
|
|
18144
|
+
var Receiver2 = class extends Writable2 {
|
|
18209
18145
|
/**
|
|
18210
18146
|
* Creates a Receiver instance.
|
|
18211
18147
|
*
|
|
@@ -21468,7 +21404,7 @@ var require_stream_writable = __commonJS({
|
|
|
21468
21404
|
"../node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/lib/_stream_writable.js"(exports2, module2) {
|
|
21469
21405
|
"use strict";
|
|
21470
21406
|
var pna = require_process_nextick_args();
|
|
21471
|
-
module2.exports =
|
|
21407
|
+
module2.exports = Writable2;
|
|
21472
21408
|
function CorkedRequest(state) {
|
|
21473
21409
|
var _this = this;
|
|
21474
21410
|
this.next = null;
|
|
@@ -21479,7 +21415,7 @@ var require_stream_writable = __commonJS({
|
|
|
21479
21415
|
}
|
|
21480
21416
|
var asyncWrite = !process.browser && ["v0.10", "v0.9."].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
|
|
21481
21417
|
var Duplex;
|
|
21482
|
-
|
|
21418
|
+
Writable2.WritableState = WritableState;
|
|
21483
21419
|
var util2 = Object.create(require_util());
|
|
21484
21420
|
util2.inherits = require_inherits();
|
|
21485
21421
|
var internalUtil = {
|
|
@@ -21496,7 +21432,7 @@ var require_stream_writable = __commonJS({
|
|
|
21496
21432
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
21497
21433
|
}
|
|
21498
21434
|
var destroyImpl = require_destroy();
|
|
21499
|
-
util2.inherits(
|
|
21435
|
+
util2.inherits(Writable2, Stream);
|
|
21500
21436
|
function nop() {
|
|
21501
21437
|
}
|
|
21502
21438
|
function WritableState(options, stream) {
|
|
@@ -21561,10 +21497,10 @@ var require_stream_writable = __commonJS({
|
|
|
21561
21497
|
var realHasInstance;
|
|
21562
21498
|
if (typeof Symbol === "function" && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === "function") {
|
|
21563
21499
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
21564
|
-
Object.defineProperty(
|
|
21500
|
+
Object.defineProperty(Writable2, Symbol.hasInstance, {
|
|
21565
21501
|
value: function(object) {
|
|
21566
21502
|
if (realHasInstance.call(this, object)) return true;
|
|
21567
|
-
if (this !==
|
|
21503
|
+
if (this !== Writable2) return false;
|
|
21568
21504
|
return object && object._writableState instanceof WritableState;
|
|
21569
21505
|
}
|
|
21570
21506
|
});
|
|
@@ -21573,10 +21509,10 @@ var require_stream_writable = __commonJS({
|
|
|
21573
21509
|
return object instanceof this;
|
|
21574
21510
|
};
|
|
21575
21511
|
}
|
|
21576
|
-
function
|
|
21512
|
+
function Writable2(options) {
|
|
21577
21513
|
Duplex = Duplex || require_stream_duplex();
|
|
21578
|
-
if (!realHasInstance.call(
|
|
21579
|
-
return new
|
|
21514
|
+
if (!realHasInstance.call(Writable2, this) && !(this instanceof Duplex)) {
|
|
21515
|
+
return new Writable2(options);
|
|
21580
21516
|
}
|
|
21581
21517
|
this._writableState = new WritableState(options, this);
|
|
21582
21518
|
this.writable = true;
|
|
@@ -21588,7 +21524,7 @@ var require_stream_writable = __commonJS({
|
|
|
21588
21524
|
}
|
|
21589
21525
|
Stream.call(this);
|
|
21590
21526
|
}
|
|
21591
|
-
|
|
21527
|
+
Writable2.prototype.pipe = function() {
|
|
21592
21528
|
this.emit("error", new Error("Cannot pipe, not readable"));
|
|
21593
21529
|
};
|
|
21594
21530
|
function writeAfterEnd(stream, cb) {
|
|
@@ -21611,7 +21547,7 @@ var require_stream_writable = __commonJS({
|
|
|
21611
21547
|
}
|
|
21612
21548
|
return valid;
|
|
21613
21549
|
}
|
|
21614
|
-
|
|
21550
|
+
Writable2.prototype.write = function(chunk, encoding, cb) {
|
|
21615
21551
|
var state = this._writableState;
|
|
21616
21552
|
var ret = false;
|
|
21617
21553
|
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
|
@@ -21632,18 +21568,18 @@ var require_stream_writable = __commonJS({
|
|
|
21632
21568
|
}
|
|
21633
21569
|
return ret;
|
|
21634
21570
|
};
|
|
21635
|
-
|
|
21571
|
+
Writable2.prototype.cork = function() {
|
|
21636
21572
|
var state = this._writableState;
|
|
21637
21573
|
state.corked++;
|
|
21638
21574
|
};
|
|
21639
|
-
|
|
21575
|
+
Writable2.prototype.uncork = function() {
|
|
21640
21576
|
var state = this._writableState;
|
|
21641
21577
|
if (state.corked) {
|
|
21642
21578
|
state.corked--;
|
|
21643
21579
|
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
|
21644
21580
|
}
|
|
21645
21581
|
};
|
|
21646
|
-
|
|
21582
|
+
Writable2.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
21647
21583
|
if (typeof encoding === "string") encoding = encoding.toLowerCase();
|
|
21648
21584
|
if (!(["hex", "utf8", "utf-8", "ascii", "binary", "base64", "ucs2", "ucs-2", "utf16le", "utf-16le", "raw"].indexOf((encoding + "").toLowerCase()) > -1)) throw new TypeError("Unknown encoding: " + encoding);
|
|
21649
21585
|
this._writableState.defaultEncoding = encoding;
|
|
@@ -21655,7 +21591,7 @@ var require_stream_writable = __commonJS({
|
|
|
21655
21591
|
}
|
|
21656
21592
|
return chunk;
|
|
21657
21593
|
}
|
|
21658
|
-
Object.defineProperty(
|
|
21594
|
+
Object.defineProperty(Writable2.prototype, "writableHighWaterMark", {
|
|
21659
21595
|
// making it explicit this property is not enumerable
|
|
21660
21596
|
// because otherwise some prototype manipulation in
|
|
21661
21597
|
// userland will fail
|
|
@@ -21801,11 +21737,11 @@ var require_stream_writable = __commonJS({
|
|
|
21801
21737
|
state.bufferedRequest = entry;
|
|
21802
21738
|
state.bufferProcessing = false;
|
|
21803
21739
|
}
|
|
21804
|
-
|
|
21740
|
+
Writable2.prototype._write = function(chunk, encoding, cb) {
|
|
21805
21741
|
cb(new Error("_write() is not implemented"));
|
|
21806
21742
|
};
|
|
21807
|
-
|
|
21808
|
-
|
|
21743
|
+
Writable2.prototype._writev = null;
|
|
21744
|
+
Writable2.prototype.end = function(chunk, encoding, cb) {
|
|
21809
21745
|
var state = this._writableState;
|
|
21810
21746
|
if (typeof chunk === "function") {
|
|
21811
21747
|
cb = chunk;
|
|
@@ -21880,7 +21816,7 @@ var require_stream_writable = __commonJS({
|
|
|
21880
21816
|
}
|
|
21881
21817
|
state.corkedRequestsFree.next = corkReq;
|
|
21882
21818
|
}
|
|
21883
|
-
Object.defineProperty(
|
|
21819
|
+
Object.defineProperty(Writable2.prototype, "destroyed", {
|
|
21884
21820
|
get: function() {
|
|
21885
21821
|
if (this._writableState === void 0) {
|
|
21886
21822
|
return false;
|
|
@@ -21894,9 +21830,9 @@ var require_stream_writable = __commonJS({
|
|
|
21894
21830
|
this._writableState.destroyed = value;
|
|
21895
21831
|
}
|
|
21896
21832
|
});
|
|
21897
|
-
|
|
21898
|
-
|
|
21899
|
-
|
|
21833
|
+
Writable2.prototype.destroy = destroyImpl.destroy;
|
|
21834
|
+
Writable2.prototype._undestroy = destroyImpl.undestroy;
|
|
21835
|
+
Writable2.prototype._destroy = function(err, cb) {
|
|
21900
21836
|
this.end();
|
|
21901
21837
|
cb(err);
|
|
21902
21838
|
};
|
|
@@ -21919,13 +21855,13 @@ var require_stream_duplex = __commonJS({
|
|
|
21919
21855
|
var util2 = Object.create(require_util());
|
|
21920
21856
|
util2.inherits = require_inherits();
|
|
21921
21857
|
var Readable3 = require_stream_readable();
|
|
21922
|
-
var
|
|
21858
|
+
var Writable2 = require_stream_writable();
|
|
21923
21859
|
util2.inherits(Duplex, Readable3);
|
|
21924
21860
|
{
|
|
21925
|
-
keys = objectKeys(
|
|
21861
|
+
keys = objectKeys(Writable2.prototype);
|
|
21926
21862
|
for (v2 = 0; v2 < keys.length; v2++) {
|
|
21927
21863
|
method = keys[v2];
|
|
21928
|
-
if (!Duplex.prototype[method]) Duplex.prototype[method] =
|
|
21864
|
+
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable2.prototype[method];
|
|
21929
21865
|
}
|
|
21930
21866
|
}
|
|
21931
21867
|
var keys;
|
|
@@ -21934,7 +21870,7 @@ var require_stream_duplex = __commonJS({
|
|
|
21934
21870
|
function Duplex(options) {
|
|
21935
21871
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
21936
21872
|
Readable3.call(this, options);
|
|
21937
|
-
|
|
21873
|
+
Writable2.call(this, options);
|
|
21938
21874
|
if (options && options.readable === false) this.readable = false;
|
|
21939
21875
|
if (options && options.writable === false) this.writable = false;
|
|
21940
21876
|
this.allowHalfOpen = true;
|
|
@@ -23944,8 +23880,8 @@ var require_utils = __commonJS({
|
|
|
23944
23880
|
var result = transform[inputType][outputType](input);
|
|
23945
23881
|
return result;
|
|
23946
23882
|
};
|
|
23947
|
-
exports2.resolve = function(
|
|
23948
|
-
var parts =
|
|
23883
|
+
exports2.resolve = function(path58) {
|
|
23884
|
+
var parts = path58.split("/");
|
|
23949
23885
|
var result = [];
|
|
23950
23886
|
for (var index = 0; index < parts.length; index++) {
|
|
23951
23887
|
var part = parts[index];
|
|
@@ -29798,18 +29734,18 @@ var require_object = __commonJS({
|
|
|
29798
29734
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
29799
29735
|
this.files[name] = object;
|
|
29800
29736
|
};
|
|
29801
|
-
var parentFolder = function(
|
|
29802
|
-
if (
|
|
29803
|
-
|
|
29737
|
+
var parentFolder = function(path58) {
|
|
29738
|
+
if (path58.slice(-1) === "/") {
|
|
29739
|
+
path58 = path58.substring(0, path58.length - 1);
|
|
29804
29740
|
}
|
|
29805
|
-
var lastSlash =
|
|
29806
|
-
return lastSlash > 0 ?
|
|
29741
|
+
var lastSlash = path58.lastIndexOf("/");
|
|
29742
|
+
return lastSlash > 0 ? path58.substring(0, lastSlash) : "";
|
|
29807
29743
|
};
|
|
29808
|
-
var forceTrailingSlash = function(
|
|
29809
|
-
if (
|
|
29810
|
-
|
|
29744
|
+
var forceTrailingSlash = function(path58) {
|
|
29745
|
+
if (path58.slice(-1) !== "/") {
|
|
29746
|
+
path58 += "/";
|
|
29811
29747
|
}
|
|
29812
|
-
return
|
|
29748
|
+
return path58;
|
|
29813
29749
|
};
|
|
29814
29750
|
var folderAdd = function(name, createFolders) {
|
|
29815
29751
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -30811,7 +30747,7 @@ var require_lib3 = __commonJS({
|
|
|
30811
30747
|
// src/run-case/recorder.ts
|
|
30812
30748
|
function startRunCaseRecorder(opts) {
|
|
30813
30749
|
const now = opts.now ?? Date.now;
|
|
30814
|
-
const dir =
|
|
30750
|
+
const dir = import_node_path46.default.dirname(opts.recordPath);
|
|
30815
30751
|
let stream = null;
|
|
30816
30752
|
let closing = false;
|
|
30817
30753
|
let closedSettled = false;
|
|
@@ -30825,8 +30761,8 @@ function startRunCaseRecorder(opts) {
|
|
|
30825
30761
|
});
|
|
30826
30762
|
const ensureStream = () => {
|
|
30827
30763
|
if (stream) return stream;
|
|
30828
|
-
|
|
30829
|
-
stream =
|
|
30764
|
+
import_node_fs34.default.mkdirSync(dir, { recursive: true });
|
|
30765
|
+
stream = import_node_fs34.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
30830
30766
|
stream.on("close", () => closedResolve());
|
|
30831
30767
|
return stream;
|
|
30832
30768
|
};
|
|
@@ -30851,12 +30787,12 @@ function startRunCaseRecorder(opts) {
|
|
|
30851
30787
|
};
|
|
30852
30788
|
return { tap, close, closed };
|
|
30853
30789
|
}
|
|
30854
|
-
var
|
|
30790
|
+
var import_node_fs34, import_node_path46;
|
|
30855
30791
|
var init_recorder = __esm({
|
|
30856
30792
|
"src/run-case/recorder.ts"() {
|
|
30857
30793
|
"use strict";
|
|
30858
|
-
|
|
30859
|
-
|
|
30794
|
+
import_node_fs34 = __toESM(require("fs"), 1);
|
|
30795
|
+
import_node_path46 = __toESM(require("path"), 1);
|
|
30860
30796
|
}
|
|
30861
30797
|
});
|
|
30862
30798
|
|
|
@@ -30899,7 +30835,7 @@ var init_wire = __esm({
|
|
|
30899
30835
|
// src/run-case/controller.ts
|
|
30900
30836
|
async function runController(opts) {
|
|
30901
30837
|
const now = opts.now ?? Date.now;
|
|
30902
|
-
const cwd = opts.cwd ?? (0,
|
|
30838
|
+
const cwd = opts.cwd ?? (0, import_node_fs35.mkdtempSync)(import_node_path47.default.join(import_node_os19.default.tmpdir(), "clawd-runcase-"));
|
|
30903
30839
|
const ownsCwd = opts.cwd === void 0;
|
|
30904
30840
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
30905
30841
|
const spawnCtx = { cwd };
|
|
@@ -31060,19 +30996,19 @@ async function runController(opts) {
|
|
|
31060
30996
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
31061
30997
|
if (ownsCwd) {
|
|
31062
30998
|
try {
|
|
31063
|
-
(0,
|
|
30999
|
+
(0, import_node_fs35.rmSync)(cwd, { recursive: true, force: true });
|
|
31064
31000
|
} catch {
|
|
31065
31001
|
}
|
|
31066
31002
|
}
|
|
31067
31003
|
return exitCode ?? 0;
|
|
31068
31004
|
}
|
|
31069
|
-
var
|
|
31005
|
+
var import_node_fs35, import_node_os19, import_node_path47;
|
|
31070
31006
|
var init_controller = __esm({
|
|
31071
31007
|
"src/run-case/controller.ts"() {
|
|
31072
31008
|
"use strict";
|
|
31073
|
-
|
|
31074
|
-
|
|
31075
|
-
|
|
31009
|
+
import_node_fs35 = require("fs");
|
|
31010
|
+
import_node_os19 = __toESM(require("os"), 1);
|
|
31011
|
+
import_node_path47 = __toESM(require("path"), 1);
|
|
31076
31012
|
init_claude();
|
|
31077
31013
|
init_stdout_splitter();
|
|
31078
31014
|
init_permission_stdio();
|
|
@@ -31176,24 +31112,6 @@ init_protocol();
|
|
|
31176
31112
|
var DEFAULT_PORT = 18790;
|
|
31177
31113
|
var DEFAULT_HOST = "127.0.0.1";
|
|
31178
31114
|
var DEFAULT_CLAWOS_API = "https://api.clawos.chat";
|
|
31179
|
-
var DEFAULT_LOG_ENDPOINT = "https://clawd-prod.cn-hangzhou.log.aliyuncs.com/logstores/app-logs/track";
|
|
31180
|
-
function resolveLogShipping(raw, cliNoShipping) {
|
|
31181
|
-
if (cliNoShipping) {
|
|
31182
|
-
return { mode: "off", endpoint: null, sampling: {} };
|
|
31183
|
-
}
|
|
31184
|
-
const rawMode = raw?.mode;
|
|
31185
|
-
const mode = rawMode === "off" || rawMode === "errors-only" ? rawMode : "on";
|
|
31186
|
-
if (mode === "off") {
|
|
31187
|
-
return { mode, endpoint: null, sampling: {} };
|
|
31188
|
-
}
|
|
31189
|
-
const endpoint = typeof raw?.endpoint === "string" && raw.endpoint ? raw.endpoint : raw?.endpoint === null ? null : DEFAULT_LOG_ENDPOINT;
|
|
31190
|
-
const sampling = mode === "errors-only" ? { debug: 0, info: 0, warn: 1, error: 1 } : isPlainSamplingMap(raw?.sampling) ? raw.sampling : {};
|
|
31191
|
-
return { mode, endpoint, sampling };
|
|
31192
|
-
}
|
|
31193
|
-
function isPlainSamplingMap(v2) {
|
|
31194
|
-
if (!v2 || typeof v2 !== "object") return false;
|
|
31195
|
-
return Object.values(v2).every((n) => typeof n === "number");
|
|
31196
|
-
}
|
|
31197
31115
|
function parseArgs(argv) {
|
|
31198
31116
|
const out = {};
|
|
31199
31117
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -31239,9 +31157,6 @@ function parseArgs(argv) {
|
|
|
31239
31157
|
case "-v":
|
|
31240
31158
|
out.version = true;
|
|
31241
31159
|
break;
|
|
31242
|
-
case "--no-log-shipping":
|
|
31243
|
-
out.noLogShipping = true;
|
|
31244
|
-
break;
|
|
31245
31160
|
default:
|
|
31246
31161
|
if (a.startsWith("--")) throw new Error(`unknown flag: ${a}`);
|
|
31247
31162
|
break;
|
|
@@ -31287,10 +31202,6 @@ function resolveConfig(opts) {
|
|
|
31287
31202
|
const mode = DAEMON_MODE_VALUES.includes(rawMode ?? "") ? rawMode : "sdk";
|
|
31288
31203
|
const filePreviewPorts = Array.isArray(fileCfg.previewPorts) ? fileCfg.previewPorts.map((n) => Number(n)).filter((n) => Number.isInteger(n) && n > 0) : null;
|
|
31289
31204
|
const previewPorts = env.CLAWD_PREVIEW_PORTS ? env.CLAWD_PREVIEW_PORTS.split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n) && n > 0) : filePreviewPorts && filePreviewPorts.length > 0 ? filePreviewPorts : null;
|
|
31290
|
-
const logShipping = resolveLogShipping(
|
|
31291
|
-
fileCfg.logShipping,
|
|
31292
|
-
args.noLogShipping ?? false
|
|
31293
|
-
);
|
|
31294
31205
|
return {
|
|
31295
31206
|
port,
|
|
31296
31207
|
host,
|
|
@@ -31303,8 +31214,7 @@ function resolveConfig(opts) {
|
|
|
31303
31214
|
noTunnelPersist,
|
|
31304
31215
|
frpcBinary,
|
|
31305
31216
|
mode,
|
|
31306
|
-
previewPorts
|
|
31307
|
-
logShipping
|
|
31217
|
+
previewPorts
|
|
31308
31218
|
};
|
|
31309
31219
|
}
|
|
31310
31220
|
var HELP_TEXT = `clawd [options]
|
|
@@ -31315,7 +31225,6 @@ var HELP_TEXT = `clawd [options]
|
|
|
31315
31225
|
--tunnel \u542F\u7528 frp tunnel \u628A\u672C\u5730\u7AEF\u53E3\u66B4\u9732\u5230\u516C\u7F51
|
|
31316
31226
|
--clawos-api <url> tunnel register \u63A5\u53E3\u7684 base url\uFF08\u9ED8\u8BA4 https://api.clawos.chat\uFF09
|
|
31317
31227
|
--auth-token <s> \u6307\u5B9A daemon auth token\uFF1B\u7F3A\u7701\u65F6 tunnel \u6A21\u5F0F\u4ECE ~/.clawd/auth.json \u590D\u7528\uFF0C\u6CA1\u6709\u5C31\u751F\u6210
|
|
31318
|
-
--no-log-shipping \u7981\u7528 SLS \u65E5\u5FD7\u4E0A\u884C\uFF08\u8986\u76D6 config.json logShipping.mode=off\uFF09
|
|
31319
31228
|
--help / -h \u663E\u793A\u5E2E\u52A9
|
|
31320
31229
|
--version / -v \u663E\u793A\u7248\u672C
|
|
31321
31230
|
|
|
@@ -31334,64 +31243,12 @@ Env (advanced):
|
|
|
31334
31243
|
`;
|
|
31335
31244
|
|
|
31336
31245
|
// src/index.ts
|
|
31337
|
-
var
|
|
31338
|
-
var
|
|
31339
|
-
var import_node_os19 = __toESM(require("os"), 1);
|
|
31340
|
-
|
|
31341
|
-
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
31342
|
-
var byteToHex = [];
|
|
31343
|
-
for (let i = 0; i < 256; ++i) {
|
|
31344
|
-
byteToHex.push((i + 256).toString(16).slice(1));
|
|
31345
|
-
}
|
|
31346
|
-
function unsafeStringify(arr, offset = 0) {
|
|
31347
|
-
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
31348
|
-
}
|
|
31349
|
-
|
|
31350
|
-
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/rng.js
|
|
31351
|
-
var import_node_crypto = __toESM(require("crypto"));
|
|
31352
|
-
var rnds8Pool = new Uint8Array(256);
|
|
31353
|
-
var poolPtr = rnds8Pool.length;
|
|
31354
|
-
function rng() {
|
|
31355
|
-
if (poolPtr > rnds8Pool.length - 16) {
|
|
31356
|
-
import_node_crypto.default.randomFillSync(rnds8Pool);
|
|
31357
|
-
poolPtr = 0;
|
|
31358
|
-
}
|
|
31359
|
-
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
31360
|
-
}
|
|
31361
|
-
|
|
31362
|
-
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/native.js
|
|
31363
|
-
var import_node_crypto2 = __toESM(require("crypto"));
|
|
31364
|
-
var native_default = {
|
|
31365
|
-
randomUUID: import_node_crypto2.default.randomUUID
|
|
31366
|
-
};
|
|
31367
|
-
|
|
31368
|
-
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/v4.js
|
|
31369
|
-
function v4(options, buf, offset) {
|
|
31370
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
31371
|
-
return native_default.randomUUID();
|
|
31372
|
-
}
|
|
31373
|
-
options = options || {};
|
|
31374
|
-
const rnds = options.random || (options.rng || rng)();
|
|
31375
|
-
rnds[6] = rnds[6] & 15 | 64;
|
|
31376
|
-
rnds[8] = rnds[8] & 63 | 128;
|
|
31377
|
-
if (buf) {
|
|
31378
|
-
offset = offset || 0;
|
|
31379
|
-
for (let i = 0; i < 16; ++i) {
|
|
31380
|
-
buf[offset + i] = rnds[i];
|
|
31381
|
-
}
|
|
31382
|
-
return buf;
|
|
31383
|
-
}
|
|
31384
|
-
return unsafeStringify(rnds);
|
|
31385
|
-
}
|
|
31386
|
-
var v4_default = v4;
|
|
31387
|
-
|
|
31388
|
-
// src/index.ts
|
|
31389
|
-
var import_node_url2 = require("url");
|
|
31246
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
31247
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
31390
31248
|
|
|
31391
31249
|
// src/logger.ts
|
|
31392
31250
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
31393
31251
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
31394
|
-
var import_node_stream = require("stream");
|
|
31395
31252
|
var import_pino = __toESM(require_pino(), 1);
|
|
31396
31253
|
function wrap(inner) {
|
|
31397
31254
|
return {
|
|
@@ -31417,329 +31274,12 @@ function createLogger(opts = {}) {
|
|
|
31417
31274
|
} catch {
|
|
31418
31275
|
}
|
|
31419
31276
|
}
|
|
31420
|
-
if (opts.logClient) {
|
|
31421
|
-
const client = opts.logClient;
|
|
31422
|
-
const sink = new import_node_stream.Writable({
|
|
31423
|
-
write(chunk, _enc, cb) {
|
|
31424
|
-
try {
|
|
31425
|
-
const line = String(chunk).trim();
|
|
31426
|
-
if (line) {
|
|
31427
|
-
const obj = JSON.parse(line);
|
|
31428
|
-
const lvl = pinoLevelToString(obj.level);
|
|
31429
|
-
if (lvl) {
|
|
31430
|
-
const meta = {};
|
|
31431
|
-
for (const [k2, v2] of Object.entries(obj)) {
|
|
31432
|
-
if (k2 === "level" || k2 === "msg" || k2 === "time" || k2 === "pid" || k2 === "hostname") continue;
|
|
31433
|
-
if (k2 === "sessionId") continue;
|
|
31434
|
-
meta[k2] = v2;
|
|
31435
|
-
}
|
|
31436
|
-
client.push({
|
|
31437
|
-
ts: typeof obj.time === "number" ? obj.time : void 0,
|
|
31438
|
-
level: lvl,
|
|
31439
|
-
msg: typeof obj.msg === "string" ? obj.msg : "",
|
|
31440
|
-
meta: Object.keys(meta).length > 0 ? meta : void 0,
|
|
31441
|
-
sessionId: typeof obj.sessionId === "string" ? obj.sessionId : void 0
|
|
31442
|
-
});
|
|
31443
|
-
}
|
|
31444
|
-
}
|
|
31445
|
-
} catch {
|
|
31446
|
-
}
|
|
31447
|
-
cb();
|
|
31448
|
-
}
|
|
31449
|
-
});
|
|
31450
|
-
streams.push({ stream: sink, level });
|
|
31451
|
-
}
|
|
31452
31277
|
const base = (0, import_pino.default)(
|
|
31453
31278
|
{ level, base: { pid: process.pid } },
|
|
31454
31279
|
import_pino.default.multistream(streams)
|
|
31455
31280
|
);
|
|
31456
31281
|
return wrap(base);
|
|
31457
31282
|
}
|
|
31458
|
-
function pinoLevelToString(n) {
|
|
31459
|
-
if (typeof n !== "number") return null;
|
|
31460
|
-
if (n >= 50) return "error";
|
|
31461
|
-
if (n >= 40) return "warn";
|
|
31462
|
-
if (n >= 30) return "info";
|
|
31463
|
-
if (n >= 20) return "debug";
|
|
31464
|
-
return null;
|
|
31465
|
-
}
|
|
31466
|
-
|
|
31467
|
-
// ../log-client/src/types.ts
|
|
31468
|
-
var DEFAULT_BATCH = {
|
|
31469
|
-
maxRecords: 100,
|
|
31470
|
-
maxBytes: 512 * 1024,
|
|
31471
|
-
maxWaitMs: 5e3
|
|
31472
|
-
};
|
|
31473
|
-
var DEFAULT_BUFFER_CAP = 5e3;
|
|
31474
|
-
var DEFAULT_SAMPLING = {
|
|
31475
|
-
debug: 0,
|
|
31476
|
-
info: 1,
|
|
31477
|
-
warn: 1,
|
|
31478
|
-
error: 1
|
|
31479
|
-
};
|
|
31480
|
-
var MAX_MSG_BYTES = 1024;
|
|
31481
|
-
var MAX_META_JSON_BYTES = 2048;
|
|
31482
|
-
var REDACT_KEY_REGEX = /token|secret|password|auth(?!or)|apikey|signsecret/i;
|
|
31483
|
-
var REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
31484
|
-
|
|
31485
|
-
// ../log-client/src/redactor.ts
|
|
31486
|
-
var TRUNCATE_SUFFIX = "\u2026[truncated]";
|
|
31487
|
-
function redactMeta(meta, homeDir) {
|
|
31488
|
-
const cleaned = cleanValue(meta, homeDir, 0);
|
|
31489
|
-
const json = safeStringify(cleaned);
|
|
31490
|
-
if (json.length <= MAX_META_JSON_BYTES) return cleaned;
|
|
31491
|
-
const truncated = json.slice(0, MAX_META_JSON_BYTES) + TRUNCATE_SUFFIX;
|
|
31492
|
-
return { __truncated__: truncated };
|
|
31493
|
-
}
|
|
31494
|
-
function cleanValue(v2, homeDir, depth) {
|
|
31495
|
-
if (depth > 10) return "[depth-limit]";
|
|
31496
|
-
if (v2 == null) return v2;
|
|
31497
|
-
if (typeof v2 === "string") {
|
|
31498
|
-
return homeDir ? v2.split(homeDir).join("~") : v2;
|
|
31499
|
-
}
|
|
31500
|
-
if (typeof v2 !== "object") return v2;
|
|
31501
|
-
if (Array.isArray(v2)) return v2.map((x) => cleanValue(x, homeDir, depth + 1));
|
|
31502
|
-
const out = {};
|
|
31503
|
-
for (const [k2, val] of Object.entries(v2)) {
|
|
31504
|
-
if (REDACT_KEY_REGEX.test(k2)) {
|
|
31505
|
-
out[k2] = REDACTED_PLACEHOLDER;
|
|
31506
|
-
} else {
|
|
31507
|
-
out[k2] = cleanValue(val, homeDir, depth + 1);
|
|
31508
|
-
}
|
|
31509
|
-
}
|
|
31510
|
-
return out;
|
|
31511
|
-
}
|
|
31512
|
-
function safeStringify(v2) {
|
|
31513
|
-
try {
|
|
31514
|
-
return JSON.stringify(v2) ?? "";
|
|
31515
|
-
} catch {
|
|
31516
|
-
return '"[serialize-failed]"';
|
|
31517
|
-
}
|
|
31518
|
-
}
|
|
31519
|
-
function truncateMsg(msg) {
|
|
31520
|
-
if (msg.length <= MAX_MSG_BYTES) return msg;
|
|
31521
|
-
return msg.slice(0, MAX_MSG_BYTES) + TRUNCATE_SUFFIX;
|
|
31522
|
-
}
|
|
31523
|
-
|
|
31524
|
-
// ../log-client/src/sampling.ts
|
|
31525
|
-
function shouldSample(level, config, rng2) {
|
|
31526
|
-
const rate = config[level] ?? DEFAULT_SAMPLING[level];
|
|
31527
|
-
if (rate <= 0) return false;
|
|
31528
|
-
if (rate >= 1) return true;
|
|
31529
|
-
return rng2() < rate;
|
|
31530
|
-
}
|
|
31531
|
-
|
|
31532
|
-
// ../log-client/src/batcher.ts
|
|
31533
|
-
var Batcher = class {
|
|
31534
|
-
constructor(deps) {
|
|
31535
|
-
this.deps = deps;
|
|
31536
|
-
}
|
|
31537
|
-
deps;
|
|
31538
|
-
queue = [];
|
|
31539
|
-
bytes = 0;
|
|
31540
|
-
droppedSinceFlush = 0;
|
|
31541
|
-
identityReady = false;
|
|
31542
|
-
timer = null;
|
|
31543
|
-
disposed = false;
|
|
31544
|
-
pendingSends = [];
|
|
31545
|
-
enqueue(record) {
|
|
31546
|
-
if (this.disposed) return;
|
|
31547
|
-
const sz = approxSize(record);
|
|
31548
|
-
while (this.queue.length >= this.deps.bufferCap) {
|
|
31549
|
-
this.queue.shift();
|
|
31550
|
-
this.droppedSinceFlush++;
|
|
31551
|
-
}
|
|
31552
|
-
this.queue.push(record);
|
|
31553
|
-
this.bytes += sz;
|
|
31554
|
-
if (!this.identityReady) return;
|
|
31555
|
-
this.maybeTrigger();
|
|
31556
|
-
}
|
|
31557
|
-
setIdentityReady(ready) {
|
|
31558
|
-
this.identityReady = ready;
|
|
31559
|
-
if (ready && this.queue.length > 0) this.maybeTrigger();
|
|
31560
|
-
}
|
|
31561
|
-
async flush() {
|
|
31562
|
-
if (this.queue.length > 0) {
|
|
31563
|
-
this.fire("flush");
|
|
31564
|
-
}
|
|
31565
|
-
await Promise.allSettled(this.pendingSends);
|
|
31566
|
-
}
|
|
31567
|
-
stats() {
|
|
31568
|
-
return { queued: this.queue.length, dropped: this.droppedSinceFlush };
|
|
31569
|
-
}
|
|
31570
|
-
async dispose() {
|
|
31571
|
-
if (this.disposed) return;
|
|
31572
|
-
this.disposed = true;
|
|
31573
|
-
if (this.timer) {
|
|
31574
|
-
clearTimeout(this.timer);
|
|
31575
|
-
this.timer = null;
|
|
31576
|
-
}
|
|
31577
|
-
await this.flush();
|
|
31578
|
-
}
|
|
31579
|
-
maybeTrigger() {
|
|
31580
|
-
const { maxRecords, maxBytes, maxWaitMs } = this.deps.batch;
|
|
31581
|
-
if (this.queue.length >= maxRecords) {
|
|
31582
|
-
this.fire("records");
|
|
31583
|
-
return;
|
|
31584
|
-
}
|
|
31585
|
-
if (this.bytes >= maxBytes) {
|
|
31586
|
-
this.fire("bytes");
|
|
31587
|
-
return;
|
|
31588
|
-
}
|
|
31589
|
-
if (this.timer == null) {
|
|
31590
|
-
this.timer = setTimeout(() => {
|
|
31591
|
-
this.timer = null;
|
|
31592
|
-
if (this.queue.length > 0 && this.identityReady) this.fire("time");
|
|
31593
|
-
}, maxWaitMs);
|
|
31594
|
-
}
|
|
31595
|
-
}
|
|
31596
|
-
fire(reason) {
|
|
31597
|
-
if (this.timer) {
|
|
31598
|
-
clearTimeout(this.timer);
|
|
31599
|
-
this.timer = null;
|
|
31600
|
-
}
|
|
31601
|
-
const records = this.queue;
|
|
31602
|
-
const droppedCarryover = this.droppedSinceFlush;
|
|
31603
|
-
this.queue = [];
|
|
31604
|
-
this.bytes = 0;
|
|
31605
|
-
this.droppedSinceFlush = 0;
|
|
31606
|
-
const p2 = this.deps.onBatch({ reason, records, droppedCarryover }).catch(() => {
|
|
31607
|
-
});
|
|
31608
|
-
this.pendingSends.push(p2);
|
|
31609
|
-
p2.finally(() => {
|
|
31610
|
-
this.pendingSends = this.pendingSends.filter((x) => x !== p2);
|
|
31611
|
-
});
|
|
31612
|
-
}
|
|
31613
|
-
};
|
|
31614
|
-
function approxSize(record) {
|
|
31615
|
-
return (record.msg?.length ?? 0) + (record.meta_json?.length ?? 0) + 200;
|
|
31616
|
-
}
|
|
31617
|
-
|
|
31618
|
-
// ../log-client/src/sender.ts
|
|
31619
|
-
var BACKOFF_MS = [1e3, 2e3, 4e3];
|
|
31620
|
-
async function sendBatch(deps, batch) {
|
|
31621
|
-
const body = JSON.stringify({
|
|
31622
|
-
__topic__: deps.topic ?? "clawd",
|
|
31623
|
-
__source__: deps.source,
|
|
31624
|
-
__logs__: batch.records,
|
|
31625
|
-
__dropped__: batch.droppedCarryover
|
|
31626
|
-
});
|
|
31627
|
-
for (let attempt = 0; attempt < BACKOFF_MS.length; attempt++) {
|
|
31628
|
-
if (attempt > 0) await sleep(BACKOFF_MS[attempt - 1]);
|
|
31629
|
-
try {
|
|
31630
|
-
const res = await deps.fetchImpl(deps.endpoint, {
|
|
31631
|
-
method: "POST",
|
|
31632
|
-
headers: { "Content-Type": "application/json" },
|
|
31633
|
-
body
|
|
31634
|
-
});
|
|
31635
|
-
if (res.status >= 200 && res.status < 300) {
|
|
31636
|
-
return { sent: batch.records.length, failed: 0 };
|
|
31637
|
-
}
|
|
31638
|
-
if (res.status >= 400 && res.status < 500) {
|
|
31639
|
-
return { sent: 0, failed: batch.records.length };
|
|
31640
|
-
}
|
|
31641
|
-
} catch {
|
|
31642
|
-
}
|
|
31643
|
-
}
|
|
31644
|
-
return { sent: 0, failed: batch.records.length };
|
|
31645
|
-
}
|
|
31646
|
-
function sleep(ms) {
|
|
31647
|
-
return new Promise((r) => setTimeout(r, ms));
|
|
31648
|
-
}
|
|
31649
|
-
|
|
31650
|
-
// ../log-client/src/client.ts
|
|
31651
|
-
function createLogClient(opts) {
|
|
31652
|
-
const stats = { sent: 0, dropped: 0, queued: 0, failed: 0 };
|
|
31653
|
-
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
31654
|
-
const now = opts.now ?? Date.now;
|
|
31655
|
-
const sampling = { ...DEFAULT_SAMPLING, ...opts.sampling ?? {} };
|
|
31656
|
-
const homeDir = opts.homeDir === void 0 ? null : opts.homeDir;
|
|
31657
|
-
const batchConfig = { ...DEFAULT_BATCH, ...opts.batch ?? {} };
|
|
31658
|
-
const bufferCap = opts.bufferCap ?? DEFAULT_BUFFER_CAP;
|
|
31659
|
-
let identity = opts.identity;
|
|
31660
|
-
let disposed = false;
|
|
31661
|
-
if (opts.endpoint == null) {
|
|
31662
|
-
return {
|
|
31663
|
-
push: () => {
|
|
31664
|
-
if (disposed) return;
|
|
31665
|
-
stats.dropped++;
|
|
31666
|
-
},
|
|
31667
|
-
flush: async () => {
|
|
31668
|
-
},
|
|
31669
|
-
setIdentity: (next) => {
|
|
31670
|
-
identity = next;
|
|
31671
|
-
},
|
|
31672
|
-
stats: () => ({ ...stats }),
|
|
31673
|
-
dispose: async () => {
|
|
31674
|
-
disposed = true;
|
|
31675
|
-
}
|
|
31676
|
-
};
|
|
31677
|
-
}
|
|
31678
|
-
const endpoint = opts.endpoint;
|
|
31679
|
-
const batcher = new Batcher({
|
|
31680
|
-
batch: batchConfig,
|
|
31681
|
-
bufferCap,
|
|
31682
|
-
now,
|
|
31683
|
-
onBatch: async (b2) => {
|
|
31684
|
-
const res = await sendBatch({ endpoint, source: opts.source, fetchImpl }, b2);
|
|
31685
|
-
stats.sent += res.sent;
|
|
31686
|
-
stats.failed += res.failed;
|
|
31687
|
-
}
|
|
31688
|
-
});
|
|
31689
|
-
batcher.setIdentityReady(identity != null);
|
|
31690
|
-
return {
|
|
31691
|
-
push(input) {
|
|
31692
|
-
if (disposed) return;
|
|
31693
|
-
try {
|
|
31694
|
-
if (!shouldSample(input.level, sampling, Math.random)) {
|
|
31695
|
-
stats.dropped++;
|
|
31696
|
-
return;
|
|
31697
|
-
}
|
|
31698
|
-
const record = buildRecord(input, identity, opts.source, homeDir, now);
|
|
31699
|
-
batcher.enqueue(record);
|
|
31700
|
-
} catch {
|
|
31701
|
-
}
|
|
31702
|
-
},
|
|
31703
|
-
async flush() {
|
|
31704
|
-
try {
|
|
31705
|
-
await batcher.flush();
|
|
31706
|
-
} catch {
|
|
31707
|
-
}
|
|
31708
|
-
},
|
|
31709
|
-
setIdentity(next) {
|
|
31710
|
-
identity = next;
|
|
31711
|
-
batcher.setIdentityReady(next != null);
|
|
31712
|
-
},
|
|
31713
|
-
stats() {
|
|
31714
|
-
const bs = batcher.stats();
|
|
31715
|
-
return { ...stats, queued: bs.queued, dropped: stats.dropped + bs.dropped };
|
|
31716
|
-
},
|
|
31717
|
-
async dispose() {
|
|
31718
|
-
disposed = true;
|
|
31719
|
-
try {
|
|
31720
|
-
await batcher.dispose();
|
|
31721
|
-
} catch {
|
|
31722
|
-
}
|
|
31723
|
-
}
|
|
31724
|
-
};
|
|
31725
|
-
}
|
|
31726
|
-
function buildRecord(input, identity, source, homeDir, now) {
|
|
31727
|
-
const cleanedMeta = input.meta ? redactMeta(input.meta, homeDir) : void 0;
|
|
31728
|
-
const meta_json = cleanedMeta ? JSON.stringify(cleanedMeta) : void 0;
|
|
31729
|
-
return {
|
|
31730
|
-
ts: input.ts ?? now(),
|
|
31731
|
-
source,
|
|
31732
|
-
level: input.level,
|
|
31733
|
-
msg: truncateMsg(input.msg),
|
|
31734
|
-
ownerPrincipalId: identity?.ownerPrincipalId ?? "__pending__",
|
|
31735
|
-
deviceId: identity?.deviceId ?? "__pending__",
|
|
31736
|
-
appVersion: identity?.appVersion ?? "__pending__",
|
|
31737
|
-
daemonVersion: identity?.daemonVersion,
|
|
31738
|
-
os: identity?.os ?? "unknown",
|
|
31739
|
-
meta_json,
|
|
31740
|
-
sessionId: input.sessionId
|
|
31741
|
-
};
|
|
31742
|
-
}
|
|
31743
31283
|
|
|
31744
31284
|
// src/session/store-factory.ts
|
|
31745
31285
|
var path5 = __toESM(require("path"), 1);
|
|
@@ -31946,6 +31486,55 @@ var SessionStoreFactory = class {
|
|
|
31946
31486
|
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
31947
31487
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
31948
31488
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
31489
|
+
|
|
31490
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
31491
|
+
var byteToHex = [];
|
|
31492
|
+
for (let i = 0; i < 256; ++i) {
|
|
31493
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
31494
|
+
}
|
|
31495
|
+
function unsafeStringify(arr, offset = 0) {
|
|
31496
|
+
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
31497
|
+
}
|
|
31498
|
+
|
|
31499
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/rng.js
|
|
31500
|
+
var import_node_crypto = __toESM(require("crypto"));
|
|
31501
|
+
var rnds8Pool = new Uint8Array(256);
|
|
31502
|
+
var poolPtr = rnds8Pool.length;
|
|
31503
|
+
function rng() {
|
|
31504
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
31505
|
+
import_node_crypto.default.randomFillSync(rnds8Pool);
|
|
31506
|
+
poolPtr = 0;
|
|
31507
|
+
}
|
|
31508
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
31509
|
+
}
|
|
31510
|
+
|
|
31511
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/native.js
|
|
31512
|
+
var import_node_crypto2 = __toESM(require("crypto"));
|
|
31513
|
+
var native_default = {
|
|
31514
|
+
randomUUID: import_node_crypto2.default.randomUUID
|
|
31515
|
+
};
|
|
31516
|
+
|
|
31517
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/v4.js
|
|
31518
|
+
function v4(options, buf, offset) {
|
|
31519
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
31520
|
+
return native_default.randomUUID();
|
|
31521
|
+
}
|
|
31522
|
+
options = options || {};
|
|
31523
|
+
const rnds = options.random || (options.rng || rng)();
|
|
31524
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
31525
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
31526
|
+
if (buf) {
|
|
31527
|
+
offset = offset || 0;
|
|
31528
|
+
for (let i = 0; i < 16; ++i) {
|
|
31529
|
+
buf[offset + i] = rnds[i];
|
|
31530
|
+
}
|
|
31531
|
+
return buf;
|
|
31532
|
+
}
|
|
31533
|
+
return unsafeStringify(rnds);
|
|
31534
|
+
}
|
|
31535
|
+
var v4_default = v4;
|
|
31536
|
+
|
|
31537
|
+
// src/session/manager.ts
|
|
31949
31538
|
init_protocol();
|
|
31950
31539
|
|
|
31951
31540
|
// src/tools/guest-settings.ts
|
|
@@ -32070,32 +31659,6 @@ function buildConnectionPrompt(args) {
|
|
|
32070
31659
|
return result;
|
|
32071
31660
|
}
|
|
32072
31661
|
|
|
32073
|
-
// src/dispatch/system-prompt.ts
|
|
32074
|
-
var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
|
|
32075
|
-
|
|
32076
|
-
\u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-bug-fixer\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 MCP tool \`mcp__clawd-dispatch__personaDispatch\` \u59D4\u6D3E\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
|
|
32077
|
-
|
|
32078
|
-
- \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
|
|
32079
|
-
- \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
|
|
32080
|
-
|
|
32081
|
-
tool \u4F1A\u963B\u585E\u6302\u8D77\u7B49\u5BF9\u65B9\u4EBA\u683C\u5E72\u5B8C\uFF0C\u628A outcome\uFF08\u542B text + \u53EF\u9009 filePaths\uFF09\u4F5C\u4E3A tool_result \u56DE\u7ED9\u4F60\uFF0C\u4F60\u518D\u7EFC\u5408\u56DE\u5E94\u7528\u6237\u3002
|
|
32082
|
-
|
|
32083
|
-
- **\u4E0D\u8981**\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF08\u4F60\u4E0D\u662F\u90A3\u4E2A persona\uFF09
|
|
32084
|
-
- **\u4E0D\u8981** in-place \u6A21\u4EFF\u5BF9\u65B9\u4EBA\u683C \u2014\u2014 dispatch \u662F\u771F\u5207\u5230\u53E6\u4E00\u4E2A\u72EC\u7ACB session
|
|
32085
|
-
- \u4E00\u53E5\u8BDD\u91CC\u591A\u4E2A \`@persona/<id>\` \u65F6\u9009\u7B2C\u4E00\u4E2A\uFF08tool \u4E00\u6B21\u53EA\u5904\u7406\u4E00\u4E2A target\uFF09
|
|
32086
|
-
- \u59D4\u6D3E\u5931\u8D25\uFF08tool_result.is_error=true\uFF09\u65F6\u5982\u5B9E\u544A\u8BC9\u7528\u6237\u539F\u56E0\uFF0C**\u4E0D\u8981\u91CD\u8BD5**
|
|
32087
|
-
|
|
32088
|
-
## \u88AB dispatch \u63A5\u5230\u4EFB\u52A1
|
|
32089
|
-
|
|
32090
|
-
\u5982\u679C\u4F60\u7684 session \u7B2C\u4E00\u6761 user message \u662F\u4EE5 \`[Dispatched from owner \u2014 another persona session\u59D4\u6D3E\u7ED9\u4F60\u6267\u884C\u4EFB\u52A1]\` \u8D77\u5934\u7684 plain text \u4EFB\u52A1\u5305\uFF0C\u4F60\u662F\u88AB\u53E6\u4E00\u4E2A persona \u59D4\u6D3E\u6765\u5E72\u6D3B\u7684\uFF08\u4EFB\u52A1\u5305\u4E0D\u7528 \`<system-reminder>\` \u5305\u662F\u4E3A\u4E86 reducer dedup \u5DE5\u4F5C\u6B63\u5E38\uFF0C\u89C1 manager.ts buildDispatchTaskPack \u6CE8\u91CA\uFF09\uFF1A
|
|
32091
|
-
|
|
32092
|
-
- \u4EFB\u52A1\u5728 \`Task:\` \u6BB5
|
|
32093
|
-
- \u539F\u4F1A\u8BDD\u7684\u5BF9\u8BDD\u5386\u53F2\u5728 \`Source conversation\` \u6BB5\u7ED9\u7684 jsonl \u8DEF\u5F84\u4E0B\uFF1B\u6309\u9700 Read \u5B83\u4E86\u89E3\u4E0A\u4E0B\u6587\uFF08\u4E0D\u5FC5\u8BFB\u5B8C\uFF09
|
|
32094
|
-
- \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`mcp__clawd-dispatch__personaDispatchComplete\` \u62A5\u544A\u7ED3\u679C\uFF1A
|
|
32095
|
-
- \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
|
|
32096
|
-
- \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "..." }\`
|
|
32097
|
-
- \u62A5\u544A\u5B8C\u540E\u4F60\u7684 session \u5C31\u7ED3\u675F\u4E86\uFF0C\u4E0D\u8981\u7EE7\u7EED\u8F93\u51FA`;
|
|
32098
|
-
|
|
32099
31662
|
// src/session/reducer.ts
|
|
32100
31663
|
function cloneState(s) {
|
|
32101
31664
|
return {
|
|
@@ -32174,9 +31737,6 @@ function buildSpawnContext(state, deps) {
|
|
|
32174
31737
|
env.CLAWD_SESSION_ID = file.sessionId;
|
|
32175
31738
|
const daemonUrl = deps.getDaemonUrl?.() ?? null;
|
|
32176
31739
|
if (daemonUrl) env.CLAWD_DAEMON_URL = daemonUrl;
|
|
32177
|
-
const dispatchId = deps.lookupDispatchByBSessionId?.(file.sessionId);
|
|
32178
|
-
if (dispatchId) env.CLAWD_DISPATCH_ID = dispatchId;
|
|
32179
|
-
const dispatchMcpConfigPath2 = deps.getDispatchMcpConfigPath?.() ?? null;
|
|
32180
31740
|
const ctx = {
|
|
32181
31741
|
cwd: file.cwd,
|
|
32182
31742
|
toolSessionId: file.toolSessionId,
|
|
@@ -32186,10 +31746,7 @@ function buildSpawnContext(state, deps) {
|
|
|
32186
31746
|
env,
|
|
32187
31747
|
// Phase 2 capability platform (plan §3): personaRoot 透传给 buildSpawnArgs;
|
|
32188
31748
|
// 内部 shouldSandbox(cwd, personaRoot) 决定是否注入 --settings sandbox-settings.
|
|
32189
|
-
personaRoot: deps.personaRoot
|
|
32190
|
-
// Persona dispatch:所有 session(A 和 B)都挂同一份 dispatch.mcp.json,让两边的 cc
|
|
32191
|
-
// 都能看到 personaDispatch / personaDispatchComplete tool;按 env 区分实际行为。
|
|
32192
|
-
dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0
|
|
31749
|
+
personaRoot: deps.personaRoot
|
|
32193
31750
|
};
|
|
32194
31751
|
const meta = state.subSessionMeta;
|
|
32195
31752
|
if (meta?.personaMode) {
|
|
@@ -32200,9 +31757,6 @@ function buildSpawnContext(state, deps) {
|
|
|
32200
31757
|
workDir: meta.userWorkDir
|
|
32201
31758
|
});
|
|
32202
31759
|
}
|
|
32203
|
-
if (dispatchMcpConfigPath2) {
|
|
32204
|
-
ctx.extraSystemPrompt = (ctx.extraSystemPrompt ? ctx.extraSystemPrompt + "\n\n" : "") + DISPATCH_SYSTEM_PROMPT_HINT;
|
|
32205
|
-
}
|
|
32206
31760
|
if (meta?.extraSettings) {
|
|
32207
31761
|
ctx.extraSettings = meta.extraSettings;
|
|
32208
31762
|
}
|
|
@@ -32868,6 +32422,35 @@ function startRecorder(opts) {
|
|
|
32868
32422
|
};
|
|
32869
32423
|
}
|
|
32870
32424
|
|
|
32425
|
+
// src/persona/mention-injection.ts
|
|
32426
|
+
var MENTION_RE = /@persona\/([A-Za-z0-9_-]+)(?=\s|$|[^A-Za-z0-9_-])/g;
|
|
32427
|
+
function injectPersonaMentions(rawText, store) {
|
|
32428
|
+
const resolved = [];
|
|
32429
|
+
const body = rawText.replace(MENTION_RE, (match, id) => {
|
|
32430
|
+
const meta = store.read(id);
|
|
32431
|
+
const personality = store.readPersonality(id);
|
|
32432
|
+
if (meta && personality !== null) {
|
|
32433
|
+
resolved.push({ label: meta.label, personality });
|
|
32434
|
+
return "";
|
|
32435
|
+
}
|
|
32436
|
+
return match;
|
|
32437
|
+
});
|
|
32438
|
+
if (resolved.length === 0) {
|
|
32439
|
+
return { systemReminder: null, userText: rawText };
|
|
32440
|
+
}
|
|
32441
|
+
const blocks = resolved.map((r) => {
|
|
32442
|
+
const safe = r.personality.replace(/<\/system-reminder>/gi, "</ system-reminder>");
|
|
32443
|
+
return `[Acting as persona "${r.label}" for this message]
|
|
32444
|
+
${safe}`;
|
|
32445
|
+
});
|
|
32446
|
+
return {
|
|
32447
|
+
systemReminder: `<system-reminder>
|
|
32448
|
+
${blocks.join("\n\n")}
|
|
32449
|
+
</system-reminder>`,
|
|
32450
|
+
userText: body.trim()
|
|
32451
|
+
};
|
|
32452
|
+
}
|
|
32453
|
+
|
|
32871
32454
|
// src/session/runner.ts
|
|
32872
32455
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
32873
32456
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -32916,6 +32499,7 @@ var SessionRunner = class {
|
|
|
32916
32499
|
}
|
|
32917
32500
|
// 外部推送 input 到 reducer,然后执行产出的 effects
|
|
32918
32501
|
input(inputMsg) {
|
|
32502
|
+
const personaStore = this.hooks.personaStore;
|
|
32919
32503
|
const adapter = this.hooks.adapter;
|
|
32920
32504
|
const deps = {
|
|
32921
32505
|
// file-sharing (spec §6 PR 3):在 stdout-line 解析时同步观察 file-edit 工具事件,
|
|
@@ -32925,10 +32509,20 @@ var SessionRunner = class {
|
|
|
32925
32509
|
if (this.hooks.onFileEdit) this.observeForFileEdit(events);
|
|
32926
32510
|
return events;
|
|
32927
32511
|
},
|
|
32928
|
-
//
|
|
32929
|
-
//
|
|
32930
|
-
//
|
|
32931
|
-
|
|
32512
|
+
// persona mention injection 在 deps 装配处包一层,对 reducer 完全透明。
|
|
32513
|
+
// 命中 mention 时拆成两条 stdin 帧(先 system-reminder 块、后 user 原文):
|
|
32514
|
+
// - CC stream-json 按行处理,落盘是两条独立 user message;
|
|
32515
|
+
// - 第一条文本起头 `<system-reminder>` → classifyUserMessage 命中 → UI 折叠;
|
|
32516
|
+
// - 第二条正常用户气泡,刷新页面不再暴露 personality 文本。
|
|
32517
|
+
encodeStdin: (t, ctx) => {
|
|
32518
|
+
if (!personaStore) return adapter.encodeStdin(t, ctx) ?? "";
|
|
32519
|
+
const { systemReminder, userText } = injectPersonaMentions(t, personaStore);
|
|
32520
|
+
if (systemReminder === null) return adapter.encodeStdin(userText, ctx) ?? "";
|
|
32521
|
+
const metaFrame = adapter.encodeStdin(systemReminder, ctx) ?? "";
|
|
32522
|
+
if (userText === "") return metaFrame;
|
|
32523
|
+
const userFrame = adapter.encodeStdin(userText, ctx) ?? "";
|
|
32524
|
+
return metaFrame + userFrame;
|
|
32525
|
+
},
|
|
32932
32526
|
bufferCap: this.hooks.bufferCap ?? 500,
|
|
32933
32527
|
now: this.hooks.now ?? Date.now,
|
|
32934
32528
|
resolveContextWindow: this.hooks.resolveContextWindow,
|
|
@@ -32938,10 +32532,6 @@ var SessionRunner = class {
|
|
|
32938
32532
|
// 单栏 refactor (spec 2026-06-02 §5.1): cc 子进程 env 注入 CLAWD_DAEMON_URL,让 assistant
|
|
32939
32533
|
// curl daemon HTTP RPC adapter (/api/rpc/<method>) 触发管理操作。null = HTTP adapter 未启。
|
|
32940
32534
|
getDaemonUrl: this.hooks.getDaemonUrl,
|
|
32941
|
-
// Persona dispatch:透传 dispatch.mcp.json 路径闭包 + B→dispatchId 反查闭包。
|
|
32942
|
-
// 见 reducer.buildSpawnContext 注 CLAWD_DISPATCH_ID env / 派生 SpawnContext.dispatchMcpConfigPath
|
|
32943
|
-
getDispatchMcpConfigPath: this.hooks.getDispatchMcpConfigPath,
|
|
32944
|
-
lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
|
|
32945
32535
|
// ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
|
|
32946
32536
|
mode: this.hooks.mode,
|
|
32947
32537
|
// [RG-DBG] 注入 logger 让 reducer rgDbg 走 pino 进 clawd.log;定位完跟 rgDbg 一起删
|
|
@@ -33401,22 +32991,6 @@ function nowIso2(deps) {
|
|
|
33401
32991
|
function newSessionId() {
|
|
33402
32992
|
return v4_default().replace(/-/g, "").slice(0, 16);
|
|
33403
32993
|
}
|
|
33404
|
-
function buildDispatchTaskPack(args) {
|
|
33405
|
-
return `[Dispatched from owner \u2014 another persona session\u59D4\u6D3E\u7ED9\u4F60\u6267\u884C\u4EFB\u52A1]
|
|
33406
|
-
|
|
33407
|
-
Task:
|
|
33408
|
-
${args.prompt}
|
|
33409
|
-
|
|
33410
|
-
Source conversation (jsonl, CC stream-json format, one message per line):
|
|
33411
|
-
${args.sourceJsonlPath}
|
|
33412
|
-
You may read this file with your Read tool to understand context. You do not have to read it all.
|
|
33413
|
-
|
|
33414
|
-
When done, call the MCP tool \`mcp__clawd-dispatch__personaDispatchComplete\` with your result:
|
|
33415
|
-
- Success: { text: "...", filePaths?: ["abs/path", ...] }
|
|
33416
|
-
- Failure: { isFailure: true, reason: "..." }
|
|
33417
|
-
|
|
33418
|
-
dispatchId for this task: ${args.dispatchId}`;
|
|
33419
|
-
}
|
|
33420
32994
|
function derivePersonaSpawnCwd(file, personaRoot) {
|
|
33421
32995
|
const personaId = file.ownerPersonaId;
|
|
33422
32996
|
if (!personaId) return file.cwd;
|
|
@@ -33714,8 +33288,7 @@ var SessionManager = class {
|
|
|
33714
33288
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
33715
33289
|
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
33716
33290
|
dataDir: this.deps.dataDir,
|
|
33717
|
-
|
|
33718
|
-
// manager 自身的 sandbox 派生仍直接读 this.deps.personaStore。
|
|
33291
|
+
personaStore: this.deps.personaStore,
|
|
33719
33292
|
ownerDisplayName: this.deps.ownerDisplayName,
|
|
33720
33293
|
// Phase 2 capability platform (plan §3): 透传 personaRoot, buildSpawnArgs 据
|
|
33721
33294
|
// cwd 是否在 personaRoot 下自动决定是否注入 --settings sandbox-settings.json.
|
|
@@ -33723,10 +33296,6 @@ var SessionManager = class {
|
|
|
33723
33296
|
// 单栏 refactor (spec 2026-06-02 §5.1): 透传 daemon HTTP RPC base URL 闭包,
|
|
33724
33297
|
// reducer 把它注入 cc 子进程 env CLAWD_DAEMON_URL.
|
|
33725
33298
|
getDaemonUrl: this.deps.getDaemonUrl,
|
|
33726
|
-
// Persona dispatch (Task 7): dispatch.mcp.json 路径 + B sessionId → dispatchId 反查
|
|
33727
|
-
// 闭包透传给 reducer,让 cc spawn 加 --mcp-config flag + B session 注 CLAWD_DISPATCH_ID env.
|
|
33728
|
-
getDispatchMcpConfigPath: this.deps.dispatchMcpConfigPath ? () => this.deps.dispatchMcpConfigPath ?? null : void 0,
|
|
33729
|
-
lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
|
|
33730
33299
|
// file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
|
|
33731
33300
|
onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
|
|
33732
33301
|
scope,
|
|
@@ -33942,20 +33511,15 @@ var SessionManager = class {
|
|
|
33942
33511
|
// 强制走 deps.store(即 default scope),不走 scopeForFile:mirror 物理落 default 即可。
|
|
33943
33512
|
// 远端 creator / origin 字段原值保留(不被本机 ctx 派生覆写)。
|
|
33944
33513
|
//
|
|
33945
|
-
// strip 远端 personaId
|
|
33946
|
-
//
|
|
33947
|
-
//
|
|
33948
|
-
// dispatchedFromSessionId 折叠 sub-session)走错分支。写入前清掉。#750 一族防线。
|
|
33514
|
+
// strip 远端 personaId:mirror SessionFile 上的 ownerPersonaId 是朋友 daemon 的 persona
|
|
33515
|
+
// 目录 id,本机不持有对应 persona。留着会让按 ownerPersonaId 反查的本机消费者
|
|
33516
|
+
// (MyPersonasSection 等)把 mirror 误聚到同 id persona 下。写入前清掉。
|
|
33949
33517
|
//
|
|
33950
33518
|
// 与 manager.create / manager.update 区别:
|
|
33951
33519
|
// - 不走 newRunner / attachObserver / cwd 校验(mirror 是纯 metadata 层)
|
|
33952
33520
|
// - 不发 session:info 帧(manager.create / .update 通过 reducer/wireCollector 发 push)
|
|
33953
33521
|
mirrorUpsert(file) {
|
|
33954
|
-
const {
|
|
33955
|
-
ownerPersonaId: _strippedPid,
|
|
33956
|
-
dispatchedFromSessionId: _strippedDsp,
|
|
33957
|
-
...rest
|
|
33958
|
-
} = file;
|
|
33522
|
+
const { ownerPersonaId: _stripped, ...rest } = file;
|
|
33959
33523
|
return this.deps.store.write(rest);
|
|
33960
33524
|
}
|
|
33961
33525
|
// mirror peer sessions:删本机 mirror SessionFile。mirror 一律落 default(mirrorUpsert
|
|
@@ -34540,66 +34104,6 @@ var SessionManager = class {
|
|
|
34540
34104
|
this.runners.set(file.sessionId, runner);
|
|
34541
34105
|
return runner;
|
|
34542
34106
|
}
|
|
34543
|
-
/**
|
|
34544
|
-
* Persona dispatch: 启动 B session 并投递任务包当第一条 user message。
|
|
34545
|
-
*
|
|
34546
|
-
* - 复用 persona-owner 创建路径(cwd=personaDir、scope=persona-owner、不沙箱)
|
|
34547
|
-
* - SessionFile 上写 dispatchedFromSessionId 关联回 A(UI 折叠用;mirror 一侧 strip)
|
|
34548
|
-
* - 跟 PersonaDispatchManager 双向登记 dispatchId ↔ B sessionId,让后续 reducer
|
|
34549
|
-
* buildSpawnContext 能反查到 dispatchId 注 CLAWD_DISPATCH_ID env
|
|
34550
|
-
* - 投 inject-owner-text 任务包;包尾教 B 用 personaDispatchComplete tool 回传
|
|
34551
|
-
*
|
|
34552
|
-
* cwd 派生与 SessionManager.create 的 owner persona 路径一致(derivePersonaSpawnCwd)。
|
|
34553
|
-
*/
|
|
34554
|
-
createDispatchedSession(args) {
|
|
34555
|
-
if (!this.deps.personaRoot) {
|
|
34556
|
-
throw new Error("createDispatchedSession: personaRoot missing in ManagerDeps");
|
|
34557
|
-
}
|
|
34558
|
-
if (!this.deps.personaDispatchManager) {
|
|
34559
|
-
throw new Error("createDispatchedSession: personaDispatchManager missing in ManagerDeps");
|
|
34560
|
-
}
|
|
34561
|
-
const sessionId = newSessionId();
|
|
34562
|
-
const scope = {
|
|
34563
|
-
kind: "persona",
|
|
34564
|
-
personaId: args.targetPersona,
|
|
34565
|
-
mode: "owner"
|
|
34566
|
-
};
|
|
34567
|
-
const cwd = import_node_path6.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
|
|
34568
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34569
|
-
const file = {
|
|
34570
|
-
sessionId,
|
|
34571
|
-
cwd,
|
|
34572
|
-
tool: "claude",
|
|
34573
|
-
ownerPersonaId: args.targetPersona,
|
|
34574
|
-
dispatchedFromSessionId: args.sourceSessionId,
|
|
34575
|
-
createdAt: now,
|
|
34576
|
-
updatedAt: now
|
|
34577
|
-
};
|
|
34578
|
-
this.storeFor(scope).write(file);
|
|
34579
|
-
this.deps.personaDispatchManager.registerBSession(args.dispatchId, sessionId);
|
|
34580
|
-
this.deps.logger?.info("dispatch.createDispatchedSession.file-written", {
|
|
34581
|
-
dispatchId: args.dispatchId,
|
|
34582
|
-
bSessionId: sessionId,
|
|
34583
|
-
targetPersona: args.targetPersona,
|
|
34584
|
-
cwd
|
|
34585
|
-
});
|
|
34586
|
-
const runner = this.ensureRunnerForScope(file, scope);
|
|
34587
|
-
this.deps.logger?.info("dispatch.createDispatchedSession.runner-ready", {
|
|
34588
|
-
dispatchId: args.dispatchId,
|
|
34589
|
-
bSessionId: sessionId
|
|
34590
|
-
});
|
|
34591
|
-
const taskPack = buildDispatchTaskPack({
|
|
34592
|
-
prompt: args.prompt,
|
|
34593
|
-
sourceJsonlPath: args.sourceJsonlPath,
|
|
34594
|
-
dispatchId: args.dispatchId
|
|
34595
|
-
});
|
|
34596
|
-
runner.input({ kind: "command", command: { kind: "send", text: taskPack } });
|
|
34597
|
-
this.deps.logger?.info("dispatch.createDispatchedSession.task-pack-sent", {
|
|
34598
|
-
dispatchId: args.dispatchId,
|
|
34599
|
-
bSessionId: sessionId
|
|
34600
|
-
});
|
|
34601
|
-
return { sessionId };
|
|
34602
|
-
}
|
|
34603
34107
|
/**
|
|
34604
34108
|
* 老板插话:把 'inject-owner-text' input 喂给对应 runner,
|
|
34605
34109
|
* runner 不存在时按 scope 懒创建。
|
|
@@ -35621,6 +35125,39 @@ var DEFAULT_PERSONAS = [
|
|
|
35621
35125
|
network: true
|
|
35622
35126
|
}
|
|
35623
35127
|
},
|
|
35128
|
+
{
|
|
35129
|
+
// 数据查询搭建师:复用 app-builder 流水线生成 dataclaw 只读查询页
|
|
35130
|
+
// spec: clawd/superpowers/specs/2026-06-14-dataclaw-builder-design.md
|
|
35131
|
+
personaId: "persona-dataclaw-builder",
|
|
35132
|
+
label: "\u6570\u636E\u67E5\u8BE2\u642D\u5EFA\u5E08",
|
|
35133
|
+
model: "opus",
|
|
35134
|
+
iconKey: "assist",
|
|
35135
|
+
public: false,
|
|
35136
|
+
// 同 app-builder 的开发型 profile(逐字段照抄):web 工具 + node/pnpm 工具链精确路径
|
|
35137
|
+
// + 出站 TLD 通配白名单 + .secrets deny。复用同一条流水线 → 同一套沙箱授权。
|
|
35138
|
+
sandboxProfile: {
|
|
35139
|
+
permissions: {
|
|
35140
|
+
defaultMode: "bypassPermissions",
|
|
35141
|
+
allow: ["Read", "Edit", "Write", "Glob", "Grep", "WebFetch", "WebSearch"],
|
|
35142
|
+
deny: ["Read(./.secrets/**)"]
|
|
35143
|
+
},
|
|
35144
|
+
sandbox: {
|
|
35145
|
+
filesystem: {
|
|
35146
|
+
allowRead: ["~/.npmrc", "~/Library/Preferences/pnpm", "~/.nvm", "~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
|
|
35147
|
+
allowWrite: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"]
|
|
35148
|
+
},
|
|
35149
|
+
network: {
|
|
35150
|
+
allowedDomains: ["*.com", "*.org", "*.io", "*.net", "*.dev", "*.app", "*.cn", "*.co", "*.chat", "*.ai"],
|
|
35151
|
+
allowLocalBinding: true
|
|
35152
|
+
}
|
|
35153
|
+
}
|
|
35154
|
+
},
|
|
35155
|
+
codexSandbox: {
|
|
35156
|
+
writableRoots: ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"],
|
|
35157
|
+
denyRead: [".secrets/**"],
|
|
35158
|
+
network: true
|
|
35159
|
+
}
|
|
35160
|
+
},
|
|
35624
35161
|
{
|
|
35625
35162
|
personaId: "persona-developer",
|
|
35626
35163
|
label: "\u5F00\u53D1\u8005",
|
|
@@ -36033,8 +35570,8 @@ function turnStartInput(text) {
|
|
|
36033
35570
|
const items = [];
|
|
36034
35571
|
let leftover = text;
|
|
36035
35572
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
36036
|
-
const [marker, name,
|
|
36037
|
-
items.push({ type: "skill", name, path:
|
|
35573
|
+
const [marker, name, path58] = m2;
|
|
35574
|
+
items.push({ type: "skill", name, path: path58 });
|
|
36038
35575
|
leftover = leftover.replace(marker, "");
|
|
36039
35576
|
}
|
|
36040
35577
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -36685,7 +36222,7 @@ init_claude_history();
|
|
|
36685
36222
|
|
|
36686
36223
|
// src/pty/pty-child-process.ts
|
|
36687
36224
|
var import_node_events = require("events");
|
|
36688
|
-
var
|
|
36225
|
+
var import_node_stream = require("stream");
|
|
36689
36226
|
var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
36690
36227
|
constructor(pty, opts = {}) {
|
|
36691
36228
|
super();
|
|
@@ -36714,7 +36251,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36714
36251
|
pty.write(data);
|
|
36715
36252
|
}
|
|
36716
36253
|
};
|
|
36717
|
-
this.stdin = new
|
|
36254
|
+
this.stdin = new import_node_stream.Writable({
|
|
36718
36255
|
decodeStrings: false,
|
|
36719
36256
|
write: (chunk, _enc, cb) => {
|
|
36720
36257
|
const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
@@ -36733,7 +36270,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36733
36270
|
}
|
|
36734
36271
|
}
|
|
36735
36272
|
});
|
|
36736
|
-
this.stdout = new
|
|
36273
|
+
this.stdout = new import_node_stream.Readable({ read() {
|
|
36737
36274
|
} });
|
|
36738
36275
|
pty.onData((data) => {
|
|
36739
36276
|
if (!this.firstDataLogged) {
|
|
@@ -36746,7 +36283,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36746
36283
|
}
|
|
36747
36284
|
this.stdout.push(Buffer.from(data, "utf8"));
|
|
36748
36285
|
});
|
|
36749
|
-
this.stderr = new
|
|
36286
|
+
this.stderr = new import_node_stream.Readable({ read() {
|
|
36750
36287
|
} });
|
|
36751
36288
|
pty.onExit(({ exitCode, signal }) => {
|
|
36752
36289
|
this.exitCode = exitCode;
|
|
@@ -37261,9 +36798,6 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
37261
36798
|
if (ctx.addDirs) {
|
|
37262
36799
|
for (const dir of ctx.addDirs) args.push("--add-dir", dir);
|
|
37263
36800
|
}
|
|
37264
|
-
if (ctx.dispatchMcpConfigPath) {
|
|
37265
|
-
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
37266
|
-
}
|
|
37267
36801
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
37268
36802
|
return args;
|
|
37269
36803
|
}
|
|
@@ -37281,155 +36815,6 @@ function jsonlExistsForCtx(ctx) {
|
|
|
37281
36815
|
// src/index.ts
|
|
37282
36816
|
init_claude_history();
|
|
37283
36817
|
|
|
37284
|
-
// src/dispatch/manager.ts
|
|
37285
|
-
function defer() {
|
|
37286
|
-
let resolve6;
|
|
37287
|
-
const promise = new Promise((r) => {
|
|
37288
|
-
resolve6 = r;
|
|
37289
|
-
});
|
|
37290
|
-
return { promise, resolve: resolve6 };
|
|
37291
|
-
}
|
|
37292
|
-
var PersonaDispatchManager = class {
|
|
37293
|
-
constructor(deps) {
|
|
37294
|
-
this.deps = deps;
|
|
37295
|
-
}
|
|
37296
|
-
deps;
|
|
37297
|
-
map = /* @__PURE__ */ new Map();
|
|
37298
|
-
start(args) {
|
|
37299
|
-
const dispatchId = this.deps.genId();
|
|
37300
|
-
this.map.set(dispatchId, {
|
|
37301
|
-
dispatchId,
|
|
37302
|
-
sourceSessionId: args.sourceSessionId,
|
|
37303
|
-
targetPersona: args.targetPersona,
|
|
37304
|
-
waiters: [],
|
|
37305
|
-
outcome: null
|
|
37306
|
-
});
|
|
37307
|
-
return { dispatchId };
|
|
37308
|
-
}
|
|
37309
|
-
get(dispatchId) {
|
|
37310
|
-
return this.map.get(dispatchId);
|
|
37311
|
-
}
|
|
37312
|
-
async wait(dispatchId) {
|
|
37313
|
-
const state = this.map.get(dispatchId);
|
|
37314
|
-
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37315
|
-
if (state.outcome) return state.outcome;
|
|
37316
|
-
const d = defer();
|
|
37317
|
-
state.waiters.push(d);
|
|
37318
|
-
return d.promise;
|
|
37319
|
-
}
|
|
37320
|
-
complete(dispatchId, outcome) {
|
|
37321
|
-
const state = this.map.get(dispatchId);
|
|
37322
|
-
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37323
|
-
state.outcome = outcome;
|
|
37324
|
-
const waiters = state.waiters;
|
|
37325
|
-
state.waiters = [];
|
|
37326
|
-
for (const w2 of waiters) w2.resolve(outcome);
|
|
37327
|
-
}
|
|
37328
|
-
/** SessionManager 在 createDispatchedSession 时调,建立 dispatchId → B sessionId 映射 */
|
|
37329
|
-
registerBSession(dispatchId, bSessionId) {
|
|
37330
|
-
const state = this.map.get(dispatchId);
|
|
37331
|
-
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37332
|
-
state.bSessionId = bSessionId;
|
|
37333
|
-
}
|
|
37334
|
-
/** reducer buildSpawnContext 调,按 B 的 sessionId 反查 dispatchId(用于注 CLAWD_DISPATCH_ID env) */
|
|
37335
|
-
lookupDispatchByBSessionId(bSessionId) {
|
|
37336
|
-
for (const state of this.map.values()) {
|
|
37337
|
-
if (state.bSessionId === bSessionId) return state.dispatchId;
|
|
37338
|
-
}
|
|
37339
|
-
return void 0;
|
|
37340
|
-
}
|
|
37341
|
-
};
|
|
37342
|
-
|
|
37343
|
-
// src/dispatch/mcp-config.ts
|
|
37344
|
-
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
37345
|
-
var import_node_path10 = __toESM(require("path"), 1);
|
|
37346
|
-
function dispatchMcpConfigPath(dataDir) {
|
|
37347
|
-
return import_node_path10.default.join(dataDir, "dispatch.mcp.json");
|
|
37348
|
-
}
|
|
37349
|
-
function writeDispatchMcpConfig(args) {
|
|
37350
|
-
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
37351
|
-
const content = {
|
|
37352
|
-
_comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002dispatch-mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\u3002env.CLAWD_DISPATCH_LOG \u6307 server \u5199\u65E5\u5FD7\u7684 append \u6587\u4EF6\u8DEF\u5F84\uFF08dispatch \u6D41\u7A0B\u8282\u70B9 + fetch \u9519\u8BEF\u7EC6\u8282\uFF09\u3002",
|
|
37353
|
-
mcpServers: {
|
|
37354
|
-
"clawd-dispatch": {
|
|
37355
|
-
type: "stdio",
|
|
37356
|
-
command: "node",
|
|
37357
|
-
args: [args.serverScriptPath],
|
|
37358
|
-
...args.logPath ? { env: { CLAWD_DISPATCH_LOG: args.logPath } } : {}
|
|
37359
|
-
}
|
|
37360
|
-
}
|
|
37361
|
-
};
|
|
37362
|
-
import_node_fs12.default.mkdirSync(args.dataDir, { recursive: true });
|
|
37363
|
-
import_node_fs12.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
37364
|
-
return cfgPath;
|
|
37365
|
-
}
|
|
37366
|
-
|
|
37367
|
-
// src/handlers/persona-dispatch.ts
|
|
37368
|
-
init_protocol();
|
|
37369
|
-
function buildPersonaDispatchHandlers(deps) {
|
|
37370
|
-
const { personaDispatchManager: mgr, spawnB, logger } = deps;
|
|
37371
|
-
const run = async (frame) => {
|
|
37372
|
-
const { type: _t, requestId: _r, ...rest } = frame;
|
|
37373
|
-
const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
|
|
37374
|
-
const args = DispatchRunArgsSchema.parse(rest);
|
|
37375
|
-
if (!sourceSessionId) {
|
|
37376
|
-
throw new Error(
|
|
37377
|
-
"personaDispatch:run requires sessionId (caller must pass x-clawd-session-id header)"
|
|
37378
|
-
);
|
|
37379
|
-
}
|
|
37380
|
-
const { dispatchId } = mgr.start({
|
|
37381
|
-
sourceSessionId,
|
|
37382
|
-
targetPersona: args.targetPersona
|
|
37383
|
-
});
|
|
37384
|
-
logger?.info("dispatch.run.received", {
|
|
37385
|
-
dispatchId,
|
|
37386
|
-
sourceSessionId,
|
|
37387
|
-
targetPersona: args.targetPersona,
|
|
37388
|
-
promptLen: args.prompt.length
|
|
37389
|
-
});
|
|
37390
|
-
void spawnB({
|
|
37391
|
-
dispatchId,
|
|
37392
|
-
sourceSessionId,
|
|
37393
|
-
targetPersona: args.targetPersona,
|
|
37394
|
-
prompt: args.prompt
|
|
37395
|
-
}).then(() => {
|
|
37396
|
-
logger?.info("dispatch.spawnB.ok", { dispatchId });
|
|
37397
|
-
}).catch((err) => {
|
|
37398
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
37399
|
-
logger?.warn("dispatch.spawnB.failed", { dispatchId, reason });
|
|
37400
|
-
mgr.complete(dispatchId, {
|
|
37401
|
-
kind: "failure",
|
|
37402
|
-
reason: `failed to spawn B: ${reason}`
|
|
37403
|
-
});
|
|
37404
|
-
});
|
|
37405
|
-
logger?.info("dispatch.run.waiting", { dispatchId });
|
|
37406
|
-
const outcome = await mgr.wait(dispatchId);
|
|
37407
|
-
logger?.info("dispatch.run.resolved", {
|
|
37408
|
-
dispatchId,
|
|
37409
|
-
outcomeKind: outcome.kind
|
|
37410
|
-
});
|
|
37411
|
-
return {
|
|
37412
|
-
response: { type: "personaDispatch:run:ok", outcome }
|
|
37413
|
-
};
|
|
37414
|
-
};
|
|
37415
|
-
const complete = async (frame) => {
|
|
37416
|
-
const { type: _t, requestId: _r, ...rest } = frame;
|
|
37417
|
-
const args = DispatchCompleteArgsSchema.parse(rest);
|
|
37418
|
-
logger?.info("dispatch.complete.received", {
|
|
37419
|
-
dispatchId: args.dispatchId,
|
|
37420
|
-
outcomeKind: args.outcome.kind
|
|
37421
|
-
});
|
|
37422
|
-
mgr.complete(args.dispatchId, args.outcome);
|
|
37423
|
-
return {
|
|
37424
|
-
response: { type: "personaDispatch:complete:ok" }
|
|
37425
|
-
};
|
|
37426
|
-
};
|
|
37427
|
-
return {
|
|
37428
|
-
"personaDispatch:run": run,
|
|
37429
|
-
"personaDispatch:complete": complete
|
|
37430
|
-
};
|
|
37431
|
-
}
|
|
37432
|
-
|
|
37433
36818
|
// src/tools/codex-history.ts
|
|
37434
36819
|
var import_node_child_process5 = require("child_process");
|
|
37435
36820
|
var DEFAULT_TIMEOUT_MS = 8e3;
|
|
@@ -37616,13 +37001,13 @@ function mapSkillsListResponse(res) {
|
|
|
37616
37001
|
const r = s ?? {};
|
|
37617
37002
|
const name = str3(r.name);
|
|
37618
37003
|
if (!name) continue;
|
|
37619
|
-
const
|
|
37004
|
+
const path58 = str3(r.path);
|
|
37620
37005
|
const description = str3(r.description);
|
|
37621
37006
|
const isPlugin = name.includes(":");
|
|
37622
37007
|
out.push({
|
|
37623
37008
|
name,
|
|
37624
37009
|
source: isPlugin ? "plugin" : "project",
|
|
37625
|
-
...
|
|
37010
|
+
...path58 ? { path: path58 } : {},
|
|
37626
37011
|
...description ? { description } : {},
|
|
37627
37012
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
37628
37013
|
});
|
|
@@ -37661,23 +37046,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
37661
37046
|
}
|
|
37662
37047
|
|
|
37663
37048
|
// src/workspace/browser.ts
|
|
37664
|
-
var
|
|
37049
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
37665
37050
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
37666
|
-
var
|
|
37051
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
37667
37052
|
init_protocol();
|
|
37668
37053
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
37669
37054
|
function resolveInsideCwd(cwd, subpath) {
|
|
37670
|
-
const absCwd =
|
|
37671
|
-
const joined =
|
|
37672
|
-
const rel =
|
|
37673
|
-
if (rel.startsWith("..") ||
|
|
37055
|
+
const absCwd = import_node_path10.default.resolve(cwd);
|
|
37056
|
+
const joined = import_node_path10.default.resolve(absCwd, subpath ?? ".");
|
|
37057
|
+
const rel = import_node_path10.default.relative(absCwd, joined);
|
|
37058
|
+
if (rel.startsWith("..") || import_node_path10.default.isAbsolute(rel)) {
|
|
37674
37059
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
37675
37060
|
}
|
|
37676
37061
|
return joined;
|
|
37677
37062
|
}
|
|
37678
37063
|
function ensureCwd(cwd) {
|
|
37679
37064
|
try {
|
|
37680
|
-
const stat =
|
|
37065
|
+
const stat = import_node_fs12.default.statSync(cwd);
|
|
37681
37066
|
if (!stat.isDirectory()) {
|
|
37682
37067
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
37683
37068
|
}
|
|
@@ -37691,7 +37076,7 @@ var WorkspaceBrowser = class {
|
|
|
37691
37076
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
|
|
37692
37077
|
ensureCwd(cwd);
|
|
37693
37078
|
const full = resolveInsideCwd(cwd, args.path);
|
|
37694
|
-
const dirents =
|
|
37079
|
+
const dirents = import_node_fs12.default.readdirSync(full, { withFileTypes: true });
|
|
37695
37080
|
const entries = [];
|
|
37696
37081
|
for (const d of dirents) {
|
|
37697
37082
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -37701,7 +37086,7 @@ var WorkspaceBrowser = class {
|
|
|
37701
37086
|
mtime: ""
|
|
37702
37087
|
};
|
|
37703
37088
|
try {
|
|
37704
|
-
const st =
|
|
37089
|
+
const st = import_node_fs12.default.statSync(import_node_path10.default.join(full, d.name));
|
|
37705
37090
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
37706
37091
|
if (d.isFile()) entry.size = st.size;
|
|
37707
37092
|
} catch {
|
|
@@ -37717,14 +37102,14 @@ var WorkspaceBrowser = class {
|
|
|
37717
37102
|
read(args) {
|
|
37718
37103
|
ensureCwd(args.cwd);
|
|
37719
37104
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
37720
|
-
const st =
|
|
37105
|
+
const st = import_node_fs12.default.statSync(full);
|
|
37721
37106
|
if (!st.isFile()) {
|
|
37722
37107
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
37723
37108
|
}
|
|
37724
37109
|
if (st.size > MAX_FILE_BYTES) {
|
|
37725
37110
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
37726
37111
|
}
|
|
37727
|
-
const buf =
|
|
37112
|
+
const buf = import_node_fs12.default.readFileSync(full);
|
|
37728
37113
|
const isBinary = buf.includes(0);
|
|
37729
37114
|
if (isBinary) {
|
|
37730
37115
|
return {
|
|
@@ -37746,20 +37131,20 @@ var WorkspaceBrowser = class {
|
|
|
37746
37131
|
};
|
|
37747
37132
|
|
|
37748
37133
|
// src/skills/agents-scanner.ts
|
|
37749
|
-
var
|
|
37134
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
37750
37135
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
37751
|
-
var
|
|
37136
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
37752
37137
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
37753
37138
|
function isDirLikeSync2(p2) {
|
|
37754
37139
|
try {
|
|
37755
|
-
return
|
|
37140
|
+
return import_node_fs13.default.statSync(p2).isDirectory();
|
|
37756
37141
|
} catch {
|
|
37757
37142
|
return false;
|
|
37758
37143
|
}
|
|
37759
37144
|
}
|
|
37760
37145
|
function fileExistsSync(p2) {
|
|
37761
37146
|
try {
|
|
37762
|
-
return
|
|
37147
|
+
return import_node_fs13.default.statSync(p2).isFile();
|
|
37763
37148
|
} catch {
|
|
37764
37149
|
return false;
|
|
37765
37150
|
}
|
|
@@ -37767,7 +37152,7 @@ function fileExistsSync(p2) {
|
|
|
37767
37152
|
function parseAgentFile(filePath) {
|
|
37768
37153
|
let content;
|
|
37769
37154
|
try {
|
|
37770
|
-
content =
|
|
37155
|
+
content = import_node_fs13.default.readFileSync(filePath, "utf8");
|
|
37771
37156
|
} catch {
|
|
37772
37157
|
return {};
|
|
37773
37158
|
}
|
|
@@ -37780,16 +37165,16 @@ function parseAgentFile(filePath) {
|
|
|
37780
37165
|
function scanAgentsDir(dir, source, seen, out) {
|
|
37781
37166
|
let entries;
|
|
37782
37167
|
try {
|
|
37783
|
-
entries =
|
|
37168
|
+
entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
37784
37169
|
} catch {
|
|
37785
37170
|
return;
|
|
37786
37171
|
}
|
|
37787
37172
|
for (const ent of entries) {
|
|
37788
37173
|
if (!ent.name.endsWith(".md")) continue;
|
|
37789
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
37174
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path11.default.join(dir, ent.name)))) {
|
|
37790
37175
|
continue;
|
|
37791
37176
|
}
|
|
37792
|
-
const filePath =
|
|
37177
|
+
const filePath = import_node_path11.default.join(dir, ent.name);
|
|
37793
37178
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
37794
37179
|
if (seen.has(baseName)) continue;
|
|
37795
37180
|
seen.add(baseName);
|
|
@@ -37807,12 +37192,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37807
37192
|
function walk2(dir, namespaces) {
|
|
37808
37193
|
let entries;
|
|
37809
37194
|
try {
|
|
37810
|
-
entries =
|
|
37195
|
+
entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
37811
37196
|
} catch {
|
|
37812
37197
|
return;
|
|
37813
37198
|
}
|
|
37814
37199
|
for (const ent of entries) {
|
|
37815
|
-
const childPath =
|
|
37200
|
+
const childPath = import_node_path11.default.join(dir, ent.name);
|
|
37816
37201
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
37817
37202
|
walk2(childPath, [...namespaces, ent.name]);
|
|
37818
37203
|
continue;
|
|
@@ -37837,13 +37222,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37837
37222
|
walk2(root, []);
|
|
37838
37223
|
}
|
|
37839
37224
|
function readInstalledPlugins2(home) {
|
|
37840
|
-
const pluginsDir =
|
|
37841
|
-
const v2 =
|
|
37842
|
-
const v1 =
|
|
37225
|
+
const pluginsDir = import_node_path11.default.join(home, ".claude", "plugins");
|
|
37226
|
+
const v2 = import_node_path11.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
37227
|
+
const v1 = import_node_path11.default.join(pluginsDir, "installed_plugins.json");
|
|
37843
37228
|
let raw = null;
|
|
37844
37229
|
for (const candidate of [v2, v1]) {
|
|
37845
37230
|
try {
|
|
37846
|
-
raw =
|
|
37231
|
+
raw = import_node_fs13.default.readFileSync(candidate, "utf8");
|
|
37847
37232
|
break;
|
|
37848
37233
|
} catch {
|
|
37849
37234
|
}
|
|
@@ -37868,19 +37253,19 @@ function readInstalledPlugins2(home) {
|
|
|
37868
37253
|
return out;
|
|
37869
37254
|
}
|
|
37870
37255
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
37871
|
-
let cur =
|
|
37872
|
-
const fsRoot =
|
|
37256
|
+
let cur = import_node_path11.default.resolve(startCwd);
|
|
37257
|
+
const fsRoot = import_node_path11.default.parse(cur).root;
|
|
37873
37258
|
while (true) {
|
|
37874
|
-
scanAgentsDir(
|
|
37259
|
+
scanAgentsDir(import_node_path11.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
37875
37260
|
let hasGit = false;
|
|
37876
37261
|
try {
|
|
37877
|
-
hasGit =
|
|
37262
|
+
hasGit = import_node_fs13.default.existsSync(import_node_path11.default.join(cur, ".git"));
|
|
37878
37263
|
} catch {
|
|
37879
37264
|
}
|
|
37880
37265
|
if (hasGit) return;
|
|
37881
37266
|
if (cur === home) return;
|
|
37882
37267
|
if (cur === fsRoot) return;
|
|
37883
|
-
const parent =
|
|
37268
|
+
const parent = import_node_path11.default.dirname(cur);
|
|
37884
37269
|
if (parent === cur) return;
|
|
37885
37270
|
cur = parent;
|
|
37886
37271
|
}
|
|
@@ -37915,7 +37300,7 @@ var AgentsScanner = class {
|
|
|
37915
37300
|
}
|
|
37916
37301
|
const fsBlock = [];
|
|
37917
37302
|
scanAgentsDir(
|
|
37918
|
-
|
|
37303
|
+
import_node_path11.default.join(this.home, ".claude", "agents"),
|
|
37919
37304
|
"global",
|
|
37920
37305
|
seen,
|
|
37921
37306
|
fsBlock
|
|
@@ -37929,7 +37314,7 @@ var AgentsScanner = class {
|
|
|
37929
37314
|
...this.extraPluginRoots
|
|
37930
37315
|
];
|
|
37931
37316
|
for (const { name, root } of plugins) {
|
|
37932
|
-
const agentsRoot =
|
|
37317
|
+
const agentsRoot = import_node_path11.default.join(root, "agents");
|
|
37933
37318
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
37934
37319
|
}
|
|
37935
37320
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -37937,15 +37322,15 @@ var AgentsScanner = class {
|
|
|
37937
37322
|
};
|
|
37938
37323
|
|
|
37939
37324
|
// src/observer/session-observer.ts
|
|
37940
|
-
var
|
|
37325
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37941
37326
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
37942
|
-
var
|
|
37327
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
37943
37328
|
init_claude_history();
|
|
37944
37329
|
|
|
37945
37330
|
// src/observer/subagent-meta-observer.ts
|
|
37946
|
-
var
|
|
37331
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
37947
37332
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
37948
|
-
var
|
|
37333
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37949
37334
|
init_claude_history();
|
|
37950
37335
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
37951
37336
|
var SubagentMetaObserver = class {
|
|
@@ -37958,7 +37343,7 @@ var SubagentMetaObserver = class {
|
|
|
37958
37343
|
watches = /* @__PURE__ */ new Map();
|
|
37959
37344
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
37960
37345
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
37961
|
-
return
|
|
37346
|
+
return import_node_path12.default.join(
|
|
37962
37347
|
this.home,
|
|
37963
37348
|
".claude",
|
|
37964
37349
|
"projects",
|
|
@@ -37988,7 +37373,7 @@ var SubagentMetaObserver = class {
|
|
|
37988
37373
|
attachWatcher(w2) {
|
|
37989
37374
|
if (w2.watcher) return;
|
|
37990
37375
|
try {
|
|
37991
|
-
w2.watcher =
|
|
37376
|
+
w2.watcher = import_node_fs14.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
37992
37377
|
if (!name) return;
|
|
37993
37378
|
const m2 = META_RE.exec(String(name));
|
|
37994
37379
|
if (!m2) return;
|
|
@@ -38000,7 +37385,7 @@ var SubagentMetaObserver = class {
|
|
|
38000
37385
|
scan(w2) {
|
|
38001
37386
|
let entries;
|
|
38002
37387
|
try {
|
|
38003
|
-
entries =
|
|
37388
|
+
entries = import_node_fs14.default.readdirSync(w2.dirPath);
|
|
38004
37389
|
} catch {
|
|
38005
37390
|
return;
|
|
38006
37391
|
}
|
|
@@ -38014,10 +37399,10 @@ var SubagentMetaObserver = class {
|
|
|
38014
37399
|
if (!m2) return;
|
|
38015
37400
|
const agentId = m2[1];
|
|
38016
37401
|
if (w2.emitted.has(agentId)) return;
|
|
38017
|
-
const file =
|
|
37402
|
+
const file = import_node_path12.default.join(w2.dirPath, name);
|
|
38018
37403
|
let raw;
|
|
38019
37404
|
try {
|
|
38020
|
-
raw =
|
|
37405
|
+
raw = import_node_fs14.default.readFileSync(file, "utf8");
|
|
38021
37406
|
} catch {
|
|
38022
37407
|
return;
|
|
38023
37408
|
}
|
|
@@ -38074,14 +37459,14 @@ var SessionObserver = class {
|
|
|
38074
37459
|
metaObserver;
|
|
38075
37460
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
38076
37461
|
if (override) return override;
|
|
38077
|
-
return
|
|
37462
|
+
return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
38078
37463
|
}
|
|
38079
37464
|
start(args) {
|
|
38080
37465
|
this.stop(args.sessionId);
|
|
38081
37466
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
38082
37467
|
let size = 0;
|
|
38083
37468
|
try {
|
|
38084
|
-
size =
|
|
37469
|
+
size = import_node_fs15.default.statSync(filePath).size;
|
|
38085
37470
|
} catch {
|
|
38086
37471
|
}
|
|
38087
37472
|
const w2 = {
|
|
@@ -38095,10 +37480,10 @@ var SessionObserver = class {
|
|
|
38095
37480
|
prevIsRejectSentinel: false
|
|
38096
37481
|
};
|
|
38097
37482
|
try {
|
|
38098
|
-
|
|
37483
|
+
import_node_fs15.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
|
|
38099
37484
|
} catch {
|
|
38100
37485
|
}
|
|
38101
|
-
w2.watcher =
|
|
37486
|
+
w2.watcher = import_node_fs15.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
38102
37487
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
38103
37488
|
this.poll(w2);
|
|
38104
37489
|
});
|
|
@@ -38121,7 +37506,7 @@ var SessionObserver = class {
|
|
|
38121
37506
|
// 异常静默吞,不阻塞 watcher 启动
|
|
38122
37507
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
38123
37508
|
try {
|
|
38124
|
-
const raw =
|
|
37509
|
+
const raw = import_node_fs15.default.readFileSync(w2.filePath, "utf8");
|
|
38125
37510
|
if (!raw) return;
|
|
38126
37511
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
38127
37512
|
if (allLines.length === 0) return;
|
|
@@ -38145,7 +37530,7 @@ var SessionObserver = class {
|
|
|
38145
37530
|
poll(w2) {
|
|
38146
37531
|
let size = 0;
|
|
38147
37532
|
try {
|
|
38148
|
-
size =
|
|
37533
|
+
size = import_node_fs15.default.statSync(w2.filePath).size;
|
|
38149
37534
|
} catch {
|
|
38150
37535
|
return;
|
|
38151
37536
|
}
|
|
@@ -38154,11 +37539,11 @@ var SessionObserver = class {
|
|
|
38154
37539
|
w2.buf = "";
|
|
38155
37540
|
}
|
|
38156
37541
|
if (size === w2.lastSize) return;
|
|
38157
|
-
const fd =
|
|
37542
|
+
const fd = import_node_fs15.default.openSync(w2.filePath, "r");
|
|
38158
37543
|
try {
|
|
38159
37544
|
const len = size - w2.lastSize;
|
|
38160
37545
|
const buf = Buffer.alloc(len);
|
|
38161
|
-
|
|
37546
|
+
import_node_fs15.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
38162
37547
|
w2.lastSize = size;
|
|
38163
37548
|
w2.buf += buf.toString("utf8");
|
|
38164
37549
|
let newlineIndex;
|
|
@@ -38181,7 +37566,7 @@ var SessionObserver = class {
|
|
|
38181
37566
|
}
|
|
38182
37567
|
}
|
|
38183
37568
|
} finally {
|
|
38184
|
-
|
|
37569
|
+
import_node_fs15.default.closeSync(fd);
|
|
38185
37570
|
}
|
|
38186
37571
|
}
|
|
38187
37572
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -38276,7 +37661,7 @@ var import_stream = __toESM(require_stream(), 1);
|
|
|
38276
37661
|
var import_extension = __toESM(require_extension(), 1);
|
|
38277
37662
|
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
38278
37663
|
var import_receiver = __toESM(require_receiver(), 1);
|
|
38279
|
-
var
|
|
37664
|
+
var import_sender = __toESM(require_sender(), 1);
|
|
38280
37665
|
var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
38281
37666
|
var import_websocket = __toESM(require_websocket(), 1);
|
|
38282
37667
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
@@ -38904,14 +38289,14 @@ async function authenticate(token, deps) {
|
|
|
38904
38289
|
}
|
|
38905
38290
|
|
|
38906
38291
|
// src/permission/capability-store.ts
|
|
38907
|
-
var
|
|
38908
|
-
var
|
|
38292
|
+
var fs18 = __toESM(require("fs"), 1);
|
|
38293
|
+
var path18 = __toESM(require("path"), 1);
|
|
38909
38294
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
38910
38295
|
var FILE_VERSION = 1;
|
|
38911
38296
|
var CapabilityStore = class {
|
|
38912
38297
|
constructor(dataDir) {
|
|
38913
38298
|
this.dataDir = dataDir;
|
|
38914
|
-
|
|
38299
|
+
fs18.mkdirSync(dataDir, { recursive: true });
|
|
38915
38300
|
this.cache = this.readFromDisk();
|
|
38916
38301
|
}
|
|
38917
38302
|
dataDir;
|
|
@@ -38935,13 +38320,13 @@ var CapabilityStore = class {
|
|
|
38935
38320
|
this.flush();
|
|
38936
38321
|
}
|
|
38937
38322
|
filePath() {
|
|
38938
|
-
return
|
|
38323
|
+
return path18.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
38939
38324
|
}
|
|
38940
38325
|
readFromDisk() {
|
|
38941
38326
|
const file = this.filePath();
|
|
38942
38327
|
let raw;
|
|
38943
38328
|
try {
|
|
38944
|
-
raw =
|
|
38329
|
+
raw = fs18.readFileSync(file, "utf8");
|
|
38945
38330
|
} catch (err) {
|
|
38946
38331
|
if (err?.code === "ENOENT") return [];
|
|
38947
38332
|
return [];
|
|
@@ -38969,10 +38354,10 @@ var CapabilityStore = class {
|
|
|
38969
38354
|
}
|
|
38970
38355
|
atomicWrite(file, content) {
|
|
38971
38356
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
38972
|
-
|
|
38973
|
-
|
|
38357
|
+
fs18.writeFileSync(tmp, content, { mode: 384 });
|
|
38358
|
+
fs18.renameSync(tmp, file);
|
|
38974
38359
|
try {
|
|
38975
|
-
|
|
38360
|
+
fs18.chmodSync(file, 384);
|
|
38976
38361
|
} catch {
|
|
38977
38362
|
}
|
|
38978
38363
|
}
|
|
@@ -39065,14 +38450,14 @@ var CapabilityManager = class {
|
|
|
39065
38450
|
};
|
|
39066
38451
|
|
|
39067
38452
|
// src/permission/cleanup.ts
|
|
39068
|
-
var
|
|
38453
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
39069
38454
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
39070
38455
|
const removed = [];
|
|
39071
38456
|
for (const g2 of cap.grants) {
|
|
39072
38457
|
if (g2.resource.type !== "persona") continue;
|
|
39073
38458
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
39074
38459
|
try {
|
|
39075
|
-
|
|
38460
|
+
fs19.rmSync(dir, { recursive: true, force: true });
|
|
39076
38461
|
removed.push(dir);
|
|
39077
38462
|
} catch {
|
|
39078
38463
|
}
|
|
@@ -39081,13 +38466,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
39081
38466
|
}
|
|
39082
38467
|
|
|
39083
38468
|
// src/inbox/inbox-store.ts
|
|
39084
|
-
var
|
|
39085
|
-
var
|
|
38469
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
38470
|
+
var path19 = __toESM(require("path"), 1);
|
|
39086
38471
|
var INBOX_SUBDIR = "inbox";
|
|
39087
38472
|
var InboxStore = class {
|
|
39088
38473
|
constructor(dataDir) {
|
|
39089
38474
|
this.dataDir = dataDir;
|
|
39090
|
-
|
|
38475
|
+
fs20.mkdirSync(this.dirPath(), { recursive: true });
|
|
39091
38476
|
}
|
|
39092
38477
|
dataDir;
|
|
39093
38478
|
/**
|
|
@@ -39099,7 +38484,7 @@ var InboxStore = class {
|
|
|
39099
38484
|
const file = this.filePath(peerDeviceId);
|
|
39100
38485
|
let raw;
|
|
39101
38486
|
try {
|
|
39102
|
-
raw =
|
|
38487
|
+
raw = fs20.readFileSync(file, "utf8");
|
|
39103
38488
|
} catch (err) {
|
|
39104
38489
|
if (err?.code === "ENOENT") return [];
|
|
39105
38490
|
return [];
|
|
@@ -39115,7 +38500,7 @@ var InboxStore = class {
|
|
|
39115
38500
|
const dir = this.dirPath();
|
|
39116
38501
|
let entries;
|
|
39117
38502
|
try {
|
|
39118
|
-
entries =
|
|
38503
|
+
entries = fs20.readdirSync(dir);
|
|
39119
38504
|
} catch (err) {
|
|
39120
38505
|
if (err?.code === "ENOENT") return [];
|
|
39121
38506
|
return [];
|
|
@@ -39131,9 +38516,9 @@ var InboxStore = class {
|
|
|
39131
38516
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
39132
38517
|
const file = this.filePath(message.peerDeviceId);
|
|
39133
38518
|
const line = JSON.stringify(message) + "\n";
|
|
39134
|
-
|
|
38519
|
+
fs20.appendFileSync(file, line, { mode: 384 });
|
|
39135
38520
|
try {
|
|
39136
|
-
|
|
38521
|
+
fs20.chmodSync(file, 384);
|
|
39137
38522
|
} catch {
|
|
39138
38523
|
}
|
|
39139
38524
|
}
|
|
@@ -39163,7 +38548,7 @@ var InboxStore = class {
|
|
|
39163
38548
|
removeByPeerDeviceId(peerDeviceId) {
|
|
39164
38549
|
const file = this.filePath(peerDeviceId);
|
|
39165
38550
|
try {
|
|
39166
|
-
|
|
38551
|
+
fs20.unlinkSync(file);
|
|
39167
38552
|
} catch (err) {
|
|
39168
38553
|
if (err?.code === "ENOENT") return;
|
|
39169
38554
|
}
|
|
@@ -39172,18 +38557,18 @@ var InboxStore = class {
|
|
|
39172
38557
|
const file = this.filePath(peerDeviceId);
|
|
39173
38558
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39174
38559
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
39175
|
-
|
|
39176
|
-
|
|
38560
|
+
fs20.writeFileSync(tmp, content, { mode: 384 });
|
|
38561
|
+
fs20.renameSync(tmp, file);
|
|
39177
38562
|
try {
|
|
39178
|
-
|
|
38563
|
+
fs20.chmodSync(file, 384);
|
|
39179
38564
|
} catch {
|
|
39180
38565
|
}
|
|
39181
38566
|
}
|
|
39182
38567
|
dirPath() {
|
|
39183
|
-
return
|
|
38568
|
+
return path19.join(this.dataDir, INBOX_SUBDIR);
|
|
39184
38569
|
}
|
|
39185
38570
|
filePath(peerDeviceId) {
|
|
39186
|
-
return
|
|
38571
|
+
return path19.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
39187
38572
|
}
|
|
39188
38573
|
};
|
|
39189
38574
|
function parseAllLines(raw) {
|
|
@@ -39270,8 +38655,8 @@ var InboxManager = class {
|
|
|
39270
38655
|
};
|
|
39271
38656
|
|
|
39272
38657
|
// src/state/contact-store.ts
|
|
39273
|
-
var
|
|
39274
|
-
var
|
|
38658
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
38659
|
+
var path20 = __toESM(require("path"), 1);
|
|
39275
38660
|
var FILE_NAME = "contacts.json";
|
|
39276
38661
|
var ContactStore = class {
|
|
39277
38662
|
constructor(dataDir) {
|
|
@@ -39281,10 +38666,10 @@ var ContactStore = class {
|
|
|
39281
38666
|
contacts = /* @__PURE__ */ new Map();
|
|
39282
38667
|
load() {
|
|
39283
38668
|
this.contacts.clear();
|
|
39284
|
-
const file =
|
|
38669
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
39285
38670
|
let raw;
|
|
39286
38671
|
try {
|
|
39287
|
-
raw =
|
|
38672
|
+
raw = fs21.readFileSync(file, "utf8");
|
|
39288
38673
|
} catch (err) {
|
|
39289
38674
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
39290
38675
|
return;
|
|
@@ -39327,20 +38712,20 @@ var ContactStore = class {
|
|
|
39327
38712
|
return existed;
|
|
39328
38713
|
}
|
|
39329
38714
|
flush() {
|
|
39330
|
-
const file =
|
|
38715
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
39331
38716
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39332
38717
|
const content = JSON.stringify(
|
|
39333
38718
|
{ contacts: Array.from(this.contacts.values()) },
|
|
39334
38719
|
null,
|
|
39335
38720
|
2
|
|
39336
38721
|
);
|
|
39337
|
-
|
|
39338
|
-
|
|
39339
|
-
|
|
38722
|
+
fs21.mkdirSync(this.dataDir, { recursive: true });
|
|
38723
|
+
fs21.writeFileSync(tmp, content, { mode: 384 });
|
|
38724
|
+
fs21.renameSync(tmp, file);
|
|
39340
38725
|
}
|
|
39341
38726
|
renameBak(file) {
|
|
39342
38727
|
try {
|
|
39343
|
-
|
|
38728
|
+
fs21.renameSync(file, `${file}.bak`);
|
|
39344
38729
|
} catch {
|
|
39345
38730
|
}
|
|
39346
38731
|
}
|
|
@@ -39490,61 +38875,61 @@ async function autoReverseContact(args) {
|
|
|
39490
38875
|
}
|
|
39491
38876
|
|
|
39492
38877
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
39493
|
-
var
|
|
39494
|
-
var
|
|
38878
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
38879
|
+
var path21 = __toESM(require("path"), 1);
|
|
39495
38880
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
39496
38881
|
function migrateFlattenSessions(opts) {
|
|
39497
38882
|
const dataDir = opts.dataDir;
|
|
39498
38883
|
const now = opts.now ?? Date.now;
|
|
39499
|
-
const sessionsDir =
|
|
39500
|
-
const flagPath =
|
|
38884
|
+
const sessionsDir = path21.join(dataDir, "sessions");
|
|
38885
|
+
const flagPath = path21.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
39501
38886
|
if (existsSync3(flagPath)) {
|
|
39502
38887
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
39503
38888
|
}
|
|
39504
38889
|
let movedBare = 0;
|
|
39505
38890
|
let movedVmOwner = 0;
|
|
39506
38891
|
let archivedListener = 0;
|
|
39507
|
-
const defaultDir =
|
|
38892
|
+
const defaultDir = path21.join(sessionsDir, "default");
|
|
39508
38893
|
if (existsSync3(defaultDir)) {
|
|
39509
38894
|
for (const entry of readdirSafe(defaultDir)) {
|
|
39510
38895
|
if (!entry.endsWith(".json")) continue;
|
|
39511
|
-
const src =
|
|
39512
|
-
const dst =
|
|
39513
|
-
|
|
38896
|
+
const src = path21.join(defaultDir, entry);
|
|
38897
|
+
const dst = path21.join(sessionsDir, entry);
|
|
38898
|
+
fs22.renameSync(src, dst);
|
|
39514
38899
|
movedBare += 1;
|
|
39515
38900
|
}
|
|
39516
38901
|
rmdirIfEmpty(defaultDir);
|
|
39517
38902
|
}
|
|
39518
38903
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
39519
|
-
const personaDir =
|
|
38904
|
+
const personaDir = path21.join(sessionsDir, pid);
|
|
39520
38905
|
if (!isDir(personaDir)) continue;
|
|
39521
38906
|
if (pid === "default") continue;
|
|
39522
|
-
const ownerSrc =
|
|
38907
|
+
const ownerSrc = path21.join(personaDir, "owner");
|
|
39523
38908
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
39524
|
-
const ownerDst =
|
|
39525
|
-
|
|
38909
|
+
const ownerDst = path21.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
38910
|
+
fs22.mkdirSync(ownerDst, { recursive: true });
|
|
39526
38911
|
for (const file of readdirSafe(ownerSrc)) {
|
|
39527
38912
|
if (!file.endsWith(".json")) continue;
|
|
39528
|
-
|
|
38913
|
+
fs22.renameSync(path21.join(ownerSrc, file), path21.join(ownerDst, file));
|
|
39529
38914
|
movedVmOwner += 1;
|
|
39530
38915
|
}
|
|
39531
38916
|
rmdirIfEmpty(ownerSrc);
|
|
39532
38917
|
}
|
|
39533
|
-
const listenerSrc =
|
|
38918
|
+
const listenerSrc = path21.join(personaDir, "listener");
|
|
39534
38919
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
39535
|
-
const archiveDst =
|
|
39536
|
-
|
|
38920
|
+
const archiveDst = path21.join(dataDir, ".legacy", `listener-${pid}`);
|
|
38921
|
+
fs22.mkdirSync(archiveDst, { recursive: true });
|
|
39537
38922
|
for (const file of readdirSafe(listenerSrc)) {
|
|
39538
38923
|
if (!file.endsWith(".json")) continue;
|
|
39539
|
-
|
|
38924
|
+
fs22.renameSync(path21.join(listenerSrc, file), path21.join(archiveDst, file));
|
|
39540
38925
|
archivedListener += 1;
|
|
39541
38926
|
}
|
|
39542
38927
|
rmdirIfEmpty(listenerSrc);
|
|
39543
38928
|
}
|
|
39544
38929
|
rmdirIfEmpty(personaDir);
|
|
39545
38930
|
}
|
|
39546
|
-
|
|
39547
|
-
|
|
38931
|
+
fs22.mkdirSync(sessionsDir, { recursive: true });
|
|
38932
|
+
fs22.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
39548
38933
|
return {
|
|
39549
38934
|
skipped: false,
|
|
39550
38935
|
flagWritten: true,
|
|
@@ -39555,7 +38940,7 @@ function migrateFlattenSessions(opts) {
|
|
|
39555
38940
|
}
|
|
39556
38941
|
function existsSync3(p2) {
|
|
39557
38942
|
try {
|
|
39558
|
-
|
|
38943
|
+
fs22.statSync(p2);
|
|
39559
38944
|
return true;
|
|
39560
38945
|
} catch {
|
|
39561
38946
|
return false;
|
|
@@ -39563,31 +38948,31 @@ function existsSync3(p2) {
|
|
|
39563
38948
|
}
|
|
39564
38949
|
function isDir(p2) {
|
|
39565
38950
|
try {
|
|
39566
|
-
return
|
|
38951
|
+
return fs22.statSync(p2).isDirectory();
|
|
39567
38952
|
} catch {
|
|
39568
38953
|
return false;
|
|
39569
38954
|
}
|
|
39570
38955
|
}
|
|
39571
38956
|
function readdirSafe(p2) {
|
|
39572
38957
|
try {
|
|
39573
|
-
return
|
|
38958
|
+
return fs22.readdirSync(p2);
|
|
39574
38959
|
} catch {
|
|
39575
38960
|
return [];
|
|
39576
38961
|
}
|
|
39577
38962
|
}
|
|
39578
38963
|
function rmdirIfEmpty(p2) {
|
|
39579
38964
|
try {
|
|
39580
|
-
|
|
38965
|
+
fs22.rmdirSync(p2);
|
|
39581
38966
|
} catch {
|
|
39582
38967
|
}
|
|
39583
38968
|
}
|
|
39584
38969
|
|
|
39585
38970
|
// src/transport/http-router.ts
|
|
39586
|
-
var
|
|
39587
|
-
var
|
|
38971
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
38972
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
39588
38973
|
|
|
39589
38974
|
// src/attachment/mime.ts
|
|
39590
|
-
var
|
|
38975
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
39591
38976
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
39592
38977
|
var EXT_TO_NATIVE_MIME = {
|
|
39593
38978
|
// 图片
|
|
@@ -39694,7 +39079,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
39694
39079
|
".mk"
|
|
39695
39080
|
]);
|
|
39696
39081
|
function lookupMime(filePathOrName) {
|
|
39697
|
-
const ext =
|
|
39082
|
+
const ext = import_node_path14.default.extname(filePathOrName).toLowerCase();
|
|
39698
39083
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
39699
39084
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
39700
39085
|
return "application/octet-stream";
|
|
@@ -39763,8 +39148,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
39763
39148
|
}
|
|
39764
39149
|
|
|
39765
39150
|
// src/attachment/upload.ts
|
|
39766
|
-
var
|
|
39767
|
-
var
|
|
39151
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
39152
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
39768
39153
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
39769
39154
|
var import_promises = require("stream/promises");
|
|
39770
39155
|
var UploadError = class extends Error {
|
|
@@ -39776,22 +39161,22 @@ var UploadError = class extends Error {
|
|
|
39776
39161
|
code;
|
|
39777
39162
|
};
|
|
39778
39163
|
function assertValidFileName(fileName) {
|
|
39779
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
39164
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path15.default.basename(fileName)) {
|
|
39780
39165
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
39781
39166
|
}
|
|
39782
39167
|
}
|
|
39783
39168
|
var HASH_PREFIX_LEN = 16;
|
|
39784
39169
|
async function writeUploadedAttachment(args) {
|
|
39785
39170
|
assertValidFileName(args.fileName);
|
|
39786
|
-
const attachmentsRoot =
|
|
39171
|
+
const attachmentsRoot = import_node_path15.default.join(args.sessionDir, ".attachments");
|
|
39787
39172
|
try {
|
|
39788
|
-
|
|
39173
|
+
import_node_fs16.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
39789
39174
|
} catch (err) {
|
|
39790
39175
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
39791
39176
|
}
|
|
39792
39177
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
39793
39178
|
let actualSize = 0;
|
|
39794
|
-
const tmpPath =
|
|
39179
|
+
const tmpPath = import_node_path15.default.join(
|
|
39795
39180
|
attachmentsRoot,
|
|
39796
39181
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
39797
39182
|
);
|
|
@@ -39806,18 +39191,18 @@ async function writeUploadedAttachment(args) {
|
|
|
39806
39191
|
yield buf;
|
|
39807
39192
|
}
|
|
39808
39193
|
},
|
|
39809
|
-
|
|
39194
|
+
import_node_fs16.default.createWriteStream(tmpPath, { mode: 384 })
|
|
39810
39195
|
);
|
|
39811
39196
|
} catch (err) {
|
|
39812
39197
|
try {
|
|
39813
|
-
|
|
39198
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39814
39199
|
} catch {
|
|
39815
39200
|
}
|
|
39816
39201
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
39817
39202
|
}
|
|
39818
39203
|
if (actualSize !== args.contentLength) {
|
|
39819
39204
|
try {
|
|
39820
|
-
|
|
39205
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39821
39206
|
} catch {
|
|
39822
39207
|
}
|
|
39823
39208
|
throw new UploadError(
|
|
@@ -39826,35 +39211,35 @@ async function writeUploadedAttachment(args) {
|
|
|
39826
39211
|
);
|
|
39827
39212
|
}
|
|
39828
39213
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
39829
|
-
const hashDir =
|
|
39214
|
+
const hashDir = import_node_path15.default.join(attachmentsRoot, attachmentId);
|
|
39830
39215
|
let finalFileName;
|
|
39831
39216
|
let hashDirExists = false;
|
|
39832
39217
|
try {
|
|
39833
|
-
hashDirExists =
|
|
39218
|
+
hashDirExists = import_node_fs16.default.statSync(hashDir).isDirectory();
|
|
39834
39219
|
} catch {
|
|
39835
39220
|
}
|
|
39836
39221
|
if (hashDirExists) {
|
|
39837
|
-
const existing =
|
|
39222
|
+
const existing = import_node_fs16.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
39838
39223
|
finalFileName = existing[0] ?? args.fileName;
|
|
39839
39224
|
try {
|
|
39840
|
-
|
|
39225
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39841
39226
|
} catch {
|
|
39842
39227
|
}
|
|
39843
39228
|
} else {
|
|
39844
39229
|
try {
|
|
39845
|
-
|
|
39230
|
+
import_node_fs16.default.mkdirSync(hashDir, { recursive: true });
|
|
39846
39231
|
finalFileName = args.fileName;
|
|
39847
|
-
|
|
39232
|
+
import_node_fs16.default.renameSync(tmpPath, import_node_path15.default.join(hashDir, finalFileName));
|
|
39848
39233
|
} catch (err) {
|
|
39849
39234
|
try {
|
|
39850
|
-
|
|
39235
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39851
39236
|
} catch {
|
|
39852
39237
|
}
|
|
39853
39238
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
39854
39239
|
}
|
|
39855
39240
|
}
|
|
39856
|
-
const absPath =
|
|
39857
|
-
const relPath =
|
|
39241
|
+
const absPath = import_node_path15.default.join(hashDir, finalFileName);
|
|
39242
|
+
const relPath = import_node_path15.default.relative(args.sessionDir, absPath);
|
|
39858
39243
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
39859
39244
|
relPath: absPath,
|
|
39860
39245
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -39868,7 +39253,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39868
39253
|
|
|
39869
39254
|
// src/extension/import.ts
|
|
39870
39255
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
39871
|
-
var
|
|
39256
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
39872
39257
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
39873
39258
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
39874
39259
|
var ImportError = class extends Error {
|
|
@@ -39886,7 +39271,7 @@ async function importZip(buf, root) {
|
|
|
39886
39271
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
39887
39272
|
}
|
|
39888
39273
|
for (const name of Object.keys(zip.files)) {
|
|
39889
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
39274
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path16.default.isAbsolute(name)) {
|
|
39890
39275
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
39891
39276
|
}
|
|
39892
39277
|
}
|
|
@@ -39919,7 +39304,7 @@ async function importZip(buf, root) {
|
|
|
39919
39304
|
);
|
|
39920
39305
|
}
|
|
39921
39306
|
}
|
|
39922
|
-
const destDir =
|
|
39307
|
+
const destDir = import_node_path16.default.join(root, manifest.id);
|
|
39923
39308
|
let destExists = false;
|
|
39924
39309
|
try {
|
|
39925
39310
|
await import_promises2.default.access(destDir);
|
|
@@ -39929,15 +39314,15 @@ async function importZip(buf, root) {
|
|
|
39929
39314
|
if (destExists) {
|
|
39930
39315
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
39931
39316
|
}
|
|
39932
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
39317
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path16.default.join(import_node_os10.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
39933
39318
|
try {
|
|
39934
39319
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
39935
|
-
const dest =
|
|
39320
|
+
const dest = import_node_path16.default.join(stage, name);
|
|
39936
39321
|
if (entry.dir) {
|
|
39937
39322
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
39938
39323
|
continue;
|
|
39939
39324
|
}
|
|
39940
|
-
await import_promises2.default.mkdir(
|
|
39325
|
+
await import_promises2.default.mkdir(import_node_path16.default.dirname(dest), { recursive: true });
|
|
39941
39326
|
const content = await entry.async("nodebuffer");
|
|
39942
39327
|
await import_promises2.default.writeFile(dest, content);
|
|
39943
39328
|
}
|
|
@@ -39963,11 +39348,9 @@ var EXPOSED_RPC_METHODS = [
|
|
|
39963
39348
|
"appBuilder.reportStage",
|
|
39964
39349
|
// 单栏 §5.6.5 fix: UI 切 session 时调(assistant 不需要主动调,但暴露白名单避免误猜成 forbidden)
|
|
39965
39350
|
"appBuilder.setActiveSession",
|
|
39966
|
-
//
|
|
39967
|
-
//
|
|
39968
|
-
|
|
39969
|
-
"personaDispatch.run",
|
|
39970
|
-
"personaDispatch.complete"
|
|
39351
|
+
// dataclaw-builder:persona 建页时取建页人身份(含 union_id)写进生成 app 的配置。
|
|
39352
|
+
// 路由到 handlers['auth:getIdentity'],只返 identity、绝不带 ttcToken(见 handlers/feishu-auth.ts)。
|
|
39353
|
+
"auth.getIdentity"
|
|
39971
39354
|
];
|
|
39972
39355
|
async function handleRpcRequest(input) {
|
|
39973
39356
|
const { method, body, sessionId, dispatcher } = input;
|
|
@@ -40056,7 +39439,7 @@ function isValidUploadFileName(fileName) {
|
|
|
40056
39439
|
if (fileName === "." || fileName === "..") return false;
|
|
40057
39440
|
if (fileName.startsWith(".")) return false;
|
|
40058
39441
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
40059
|
-
return fileName ===
|
|
39442
|
+
return fileName === import_node_path17.default.basename(fileName);
|
|
40060
39443
|
}
|
|
40061
39444
|
function createHttpRouter(deps) {
|
|
40062
39445
|
return async (req, res) => {
|
|
@@ -40103,8 +39486,6 @@ function createHttpRouter(deps) {
|
|
|
40103
39486
|
sendJson(res, 403, { code: "NOT_LOOPBACK", message: "RPC adapter only accepts loopback connections" });
|
|
40104
39487
|
return true;
|
|
40105
39488
|
}
|
|
40106
|
-
req.socket.setTimeout(0);
|
|
40107
|
-
res.socket?.setTimeout(0);
|
|
40108
39489
|
const method = url.pathname.slice(RPC_ROUTE_PREFIX.length).split("?")[0] ?? "";
|
|
40109
39490
|
const sessionId = req.headers["x-clawd-session-id"] ?? void 0;
|
|
40110
39491
|
let body;
|
|
@@ -40287,7 +39668,7 @@ function createHttpRouter(deps) {
|
|
|
40287
39668
|
return true;
|
|
40288
39669
|
}
|
|
40289
39670
|
let absPath;
|
|
40290
|
-
if (
|
|
39671
|
+
if (import_node_path17.default.isAbsolute(pathParam)) {
|
|
40291
39672
|
absPath = pathParam;
|
|
40292
39673
|
} else if (deps.sessionStore) {
|
|
40293
39674
|
const file = deps.sessionStore.read(sid);
|
|
@@ -40295,7 +39676,7 @@ function createHttpRouter(deps) {
|
|
|
40295
39676
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
40296
39677
|
return true;
|
|
40297
39678
|
}
|
|
40298
|
-
absPath =
|
|
39679
|
+
absPath = import_node_path17.default.join(file.cwd, pathParam);
|
|
40299
39680
|
} else {
|
|
40300
39681
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
40301
39682
|
return true;
|
|
@@ -40378,7 +39759,7 @@ function withCtx(ctx, body) {
|
|
|
40378
39759
|
function streamFile(res, absPath, logger) {
|
|
40379
39760
|
let stat;
|
|
40380
39761
|
try {
|
|
40381
|
-
stat =
|
|
39762
|
+
stat = import_node_fs17.default.statSync(absPath);
|
|
40382
39763
|
} catch (err) {
|
|
40383
39764
|
const code = err?.code;
|
|
40384
39765
|
if (code === "ENOENT") {
|
|
@@ -40393,7 +39774,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40393
39774
|
return;
|
|
40394
39775
|
}
|
|
40395
39776
|
const mime = lookupMime(absPath);
|
|
40396
|
-
const basename =
|
|
39777
|
+
const basename = import_node_path17.default.basename(absPath);
|
|
40397
39778
|
res.writeHead(200, {
|
|
40398
39779
|
"Content-Type": mime,
|
|
40399
39780
|
"Content-Length": String(stat.size),
|
|
@@ -40401,7 +39782,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40401
39782
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
40402
39783
|
"X-Content-Type-Options": "nosniff"
|
|
40403
39784
|
});
|
|
40404
|
-
const stream =
|
|
39785
|
+
const stream = import_node_fs17.default.createReadStream(absPath);
|
|
40405
39786
|
stream.on("error", (err) => {
|
|
40406
39787
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
40407
39788
|
res.destroy();
|
|
@@ -40410,8 +39791,8 @@ function streamFile(res, absPath, logger) {
|
|
|
40410
39791
|
}
|
|
40411
39792
|
|
|
40412
39793
|
// src/attachment/gc.ts
|
|
40413
|
-
var
|
|
40414
|
-
var
|
|
39794
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
39795
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
40415
39796
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
40416
39797
|
function runAttachmentGc(args) {
|
|
40417
39798
|
const now = (args.now ?? Date.now)();
|
|
@@ -40420,38 +39801,38 @@ function runAttachmentGc(args) {
|
|
|
40420
39801
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40421
39802
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
40422
39803
|
if (entry.stale) continue;
|
|
40423
|
-
if (
|
|
39804
|
+
if (import_node_path18.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
40424
39805
|
}
|
|
40425
39806
|
}
|
|
40426
39807
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40427
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
39808
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path18.default.join(
|
|
40428
39809
|
args.dataDir,
|
|
40429
39810
|
"sessions",
|
|
40430
39811
|
...scopeSubPath(scope).map(safeFileName),
|
|
40431
39812
|
safeFileName(sessionId)
|
|
40432
39813
|
);
|
|
40433
|
-
const attRoot =
|
|
39814
|
+
const attRoot = import_node_path18.default.join(sessionDir, ".attachments");
|
|
40434
39815
|
let hashDirs;
|
|
40435
39816
|
try {
|
|
40436
|
-
hashDirs =
|
|
39817
|
+
hashDirs = import_node_fs18.default.readdirSync(attRoot);
|
|
40437
39818
|
} catch (err) {
|
|
40438
39819
|
if (err.code === "ENOENT") continue;
|
|
40439
39820
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
40440
39821
|
continue;
|
|
40441
39822
|
}
|
|
40442
39823
|
for (const hashDir of hashDirs) {
|
|
40443
|
-
const hashDirAbs =
|
|
39824
|
+
const hashDirAbs = import_node_path18.default.join(attRoot, hashDir);
|
|
40444
39825
|
let files;
|
|
40445
39826
|
try {
|
|
40446
|
-
files =
|
|
39827
|
+
files = import_node_fs18.default.readdirSync(hashDirAbs);
|
|
40447
39828
|
} catch {
|
|
40448
39829
|
continue;
|
|
40449
39830
|
}
|
|
40450
39831
|
for (const name of files) {
|
|
40451
|
-
const file =
|
|
39832
|
+
const file = import_node_path18.default.join(hashDirAbs, name);
|
|
40452
39833
|
let stat;
|
|
40453
39834
|
try {
|
|
40454
|
-
stat =
|
|
39835
|
+
stat = import_node_fs18.default.statSync(file);
|
|
40455
39836
|
} catch {
|
|
40456
39837
|
continue;
|
|
40457
39838
|
}
|
|
@@ -40460,26 +39841,26 @@ function runAttachmentGc(args) {
|
|
|
40460
39841
|
if (age < ttlMs) continue;
|
|
40461
39842
|
if (liveAbs.has(file)) continue;
|
|
40462
39843
|
try {
|
|
40463
|
-
|
|
39844
|
+
import_node_fs18.default.unlinkSync(file);
|
|
40464
39845
|
} catch (err) {
|
|
40465
39846
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
40466
39847
|
}
|
|
40467
39848
|
}
|
|
40468
39849
|
try {
|
|
40469
|
-
if (
|
|
39850
|
+
if (import_node_fs18.default.readdirSync(hashDirAbs).length === 0) import_node_fs18.default.rmdirSync(hashDirAbs);
|
|
40470
39851
|
} catch {
|
|
40471
39852
|
}
|
|
40472
39853
|
}
|
|
40473
39854
|
try {
|
|
40474
|
-
if (
|
|
39855
|
+
if (import_node_fs18.default.readdirSync(attRoot).length === 0) import_node_fs18.default.rmdirSync(attRoot);
|
|
40475
39856
|
} catch {
|
|
40476
39857
|
}
|
|
40477
39858
|
}
|
|
40478
39859
|
}
|
|
40479
39860
|
|
|
40480
39861
|
// src/attachment/group.ts
|
|
40481
|
-
var
|
|
40482
|
-
var
|
|
39862
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
39863
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
40483
39864
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
40484
39865
|
init_protocol();
|
|
40485
39866
|
var GroupFileStore = class {
|
|
@@ -40491,11 +39872,11 @@ var GroupFileStore = class {
|
|
|
40491
39872
|
this.logger = opts.logger;
|
|
40492
39873
|
}
|
|
40493
39874
|
rootForScope(scope) {
|
|
40494
|
-
return
|
|
39875
|
+
return import_node_path19.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
40495
39876
|
}
|
|
40496
39877
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
40497
39878
|
filePath(scope, sessionId) {
|
|
40498
|
-
return
|
|
39879
|
+
return import_node_path19.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
40499
39880
|
}
|
|
40500
39881
|
cacheKey(scope, sessionId) {
|
|
40501
39882
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -40504,7 +39885,7 @@ var GroupFileStore = class {
|
|
|
40504
39885
|
readFile(scope, sessionId) {
|
|
40505
39886
|
const file = this.filePath(scope, sessionId);
|
|
40506
39887
|
try {
|
|
40507
|
-
const raw =
|
|
39888
|
+
const raw = import_node_fs19.default.readFileSync(file, "utf8");
|
|
40508
39889
|
const parsed = JSON.parse(raw);
|
|
40509
39890
|
if (!Array.isArray(parsed)) {
|
|
40510
39891
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -40530,10 +39911,10 @@ var GroupFileStore = class {
|
|
|
40530
39911
|
}
|
|
40531
39912
|
writeFile(scope, sessionId, entries) {
|
|
40532
39913
|
const file = this.filePath(scope, sessionId);
|
|
40533
|
-
|
|
39914
|
+
import_node_fs19.default.mkdirSync(import_node_path19.default.dirname(file), { recursive: true });
|
|
40534
39915
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
40535
|
-
|
|
40536
|
-
|
|
39916
|
+
import_node_fs19.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
39917
|
+
import_node_fs19.default.renameSync(tmp, file);
|
|
40537
39918
|
}
|
|
40538
39919
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
40539
39920
|
list(scope, sessionId) {
|
|
@@ -40619,10 +40000,10 @@ var GroupFileStore = class {
|
|
|
40619
40000
|
};
|
|
40620
40001
|
|
|
40621
40002
|
// src/discovery/state-file.ts
|
|
40622
|
-
var
|
|
40623
|
-
var
|
|
40003
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
40004
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
40624
40005
|
function defaultStateFilePath(dataDir) {
|
|
40625
|
-
return
|
|
40006
|
+
return import_node_path20.default.join(dataDir, "state.json");
|
|
40626
40007
|
}
|
|
40627
40008
|
function isPidAlive(pid) {
|
|
40628
40009
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -40644,7 +40025,7 @@ var StateFileManager = class {
|
|
|
40644
40025
|
}
|
|
40645
40026
|
read() {
|
|
40646
40027
|
try {
|
|
40647
|
-
const raw =
|
|
40028
|
+
const raw = import_node_fs20.default.readFileSync(this.file, "utf8");
|
|
40648
40029
|
const parsed = JSON.parse(raw);
|
|
40649
40030
|
return parsed;
|
|
40650
40031
|
} catch {
|
|
@@ -40658,20 +40039,20 @@ var StateFileManager = class {
|
|
|
40658
40039
|
return { status: "stale", existing };
|
|
40659
40040
|
}
|
|
40660
40041
|
write(state) {
|
|
40661
|
-
|
|
40042
|
+
import_node_fs20.default.mkdirSync(import_node_path20.default.dirname(this.file), { recursive: true });
|
|
40662
40043
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
40663
|
-
|
|
40664
|
-
|
|
40044
|
+
import_node_fs20.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
40045
|
+
import_node_fs20.default.renameSync(tmp, this.file);
|
|
40665
40046
|
if (process.platform !== "win32") {
|
|
40666
40047
|
try {
|
|
40667
|
-
|
|
40048
|
+
import_node_fs20.default.chmodSync(this.file, 384);
|
|
40668
40049
|
} catch {
|
|
40669
40050
|
}
|
|
40670
40051
|
}
|
|
40671
40052
|
}
|
|
40672
40053
|
delete() {
|
|
40673
40054
|
try {
|
|
40674
|
-
|
|
40055
|
+
import_node_fs20.default.unlinkSync(this.file);
|
|
40675
40056
|
} catch {
|
|
40676
40057
|
}
|
|
40677
40058
|
}
|
|
@@ -40686,14 +40067,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
40686
40067
|
}
|
|
40687
40068
|
|
|
40688
40069
|
// src/tunnel/tunnel-manager.ts
|
|
40689
|
-
var
|
|
40690
|
-
var
|
|
40070
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
40071
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
40691
40072
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
40692
40073
|
var import_node_child_process9 = require("child_process");
|
|
40693
40074
|
|
|
40694
40075
|
// src/tunnel/tunnel-store.ts
|
|
40695
|
-
var
|
|
40696
|
-
var
|
|
40076
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
40077
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40697
40078
|
var TunnelStore = class {
|
|
40698
40079
|
constructor(filePath) {
|
|
40699
40080
|
this.filePath = filePath;
|
|
@@ -40701,7 +40082,7 @@ var TunnelStore = class {
|
|
|
40701
40082
|
filePath;
|
|
40702
40083
|
async get() {
|
|
40703
40084
|
try {
|
|
40704
|
-
const raw = await
|
|
40085
|
+
const raw = await import_node_fs21.default.promises.readFile(this.filePath, "utf8");
|
|
40705
40086
|
const obj = JSON.parse(raw);
|
|
40706
40087
|
if (!isPersistedTunnel(obj)) return null;
|
|
40707
40088
|
return obj;
|
|
@@ -40712,22 +40093,22 @@ var TunnelStore = class {
|
|
|
40712
40093
|
}
|
|
40713
40094
|
}
|
|
40714
40095
|
async set(v2) {
|
|
40715
|
-
const dir =
|
|
40716
|
-
await
|
|
40096
|
+
const dir = import_node_path21.default.dirname(this.filePath);
|
|
40097
|
+
await import_node_fs21.default.promises.mkdir(dir, { recursive: true });
|
|
40717
40098
|
const data = JSON.stringify(v2, null, 2);
|
|
40718
40099
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
40719
|
-
await
|
|
40100
|
+
await import_node_fs21.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
40720
40101
|
if (process.platform !== "win32") {
|
|
40721
40102
|
try {
|
|
40722
|
-
await
|
|
40103
|
+
await import_node_fs21.default.promises.chmod(tmp, 384);
|
|
40723
40104
|
} catch {
|
|
40724
40105
|
}
|
|
40725
40106
|
}
|
|
40726
|
-
await
|
|
40107
|
+
await import_node_fs21.default.promises.rename(tmp, this.filePath);
|
|
40727
40108
|
}
|
|
40728
40109
|
async clear() {
|
|
40729
40110
|
try {
|
|
40730
|
-
await
|
|
40111
|
+
await import_node_fs21.default.promises.unlink(this.filePath);
|
|
40731
40112
|
} catch (err) {
|
|
40732
40113
|
const code = err?.code;
|
|
40733
40114
|
if (code !== "ENOENT") throw err;
|
|
@@ -40822,11 +40203,11 @@ function escape(v2) {
|
|
|
40822
40203
|
}
|
|
40823
40204
|
|
|
40824
40205
|
// src/tunnel/frpc-binary.ts
|
|
40825
|
-
var
|
|
40206
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40826
40207
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
40827
|
-
var
|
|
40208
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40828
40209
|
var import_node_child_process7 = require("child_process");
|
|
40829
|
-
var
|
|
40210
|
+
var import_node_stream2 = require("stream");
|
|
40830
40211
|
var import_promises3 = require("stream/promises");
|
|
40831
40212
|
var FRPC_VERSION = "0.68.0";
|
|
40832
40213
|
var UnsupportedPlatformError = class extends Error {
|
|
@@ -40856,20 +40237,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
40856
40237
|
}
|
|
40857
40238
|
async function ensureFrpcBinary(opts) {
|
|
40858
40239
|
if (opts.override) {
|
|
40859
|
-
if (!
|
|
40240
|
+
if (!import_node_fs22.default.existsSync(opts.override)) {
|
|
40860
40241
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
40861
40242
|
}
|
|
40862
40243
|
return opts.override;
|
|
40863
40244
|
}
|
|
40864
40245
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
40865
40246
|
const platform = opts.platform ?? detectPlatform();
|
|
40866
|
-
const binDir =
|
|
40867
|
-
|
|
40247
|
+
const binDir = import_node_path22.default.join(opts.dataDir, "bin");
|
|
40248
|
+
import_node_fs22.default.mkdirSync(binDir, { recursive: true });
|
|
40868
40249
|
cleanupStaleArtifacts(binDir);
|
|
40869
|
-
const stableBin =
|
|
40870
|
-
if (
|
|
40250
|
+
const stableBin = import_node_path22.default.join(binDir, "frpc");
|
|
40251
|
+
if (import_node_fs22.default.existsSync(stableBin)) return stableBin;
|
|
40871
40252
|
const partialBin = `${stableBin}.partial`;
|
|
40872
|
-
const tarballPath =
|
|
40253
|
+
const tarballPath = import_node_path22.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
40873
40254
|
try {
|
|
40874
40255
|
const url = frpcDownloadUrl(version2, platform);
|
|
40875
40256
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -40878,8 +40259,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
40878
40259
|
} else {
|
|
40879
40260
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
40880
40261
|
}
|
|
40881
|
-
|
|
40882
|
-
|
|
40262
|
+
import_node_fs22.default.chmodSync(partialBin, 493);
|
|
40263
|
+
import_node_fs22.default.renameSync(partialBin, stableBin);
|
|
40883
40264
|
} finally {
|
|
40884
40265
|
safeUnlink(tarballPath);
|
|
40885
40266
|
safeUnlink(partialBin);
|
|
@@ -40889,15 +40270,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
40889
40270
|
function cleanupStaleArtifacts(binDir) {
|
|
40890
40271
|
let entries;
|
|
40891
40272
|
try {
|
|
40892
|
-
entries =
|
|
40273
|
+
entries = import_node_fs22.default.readdirSync(binDir);
|
|
40893
40274
|
} catch {
|
|
40894
40275
|
return;
|
|
40895
40276
|
}
|
|
40896
40277
|
for (const name of entries) {
|
|
40897
40278
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
40898
|
-
const full =
|
|
40279
|
+
const full = import_node_path22.default.join(binDir, name);
|
|
40899
40280
|
try {
|
|
40900
|
-
|
|
40281
|
+
import_node_fs22.default.rmSync(full, { recursive: true, force: true });
|
|
40901
40282
|
} catch {
|
|
40902
40283
|
}
|
|
40903
40284
|
}
|
|
@@ -40905,7 +40286,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
40905
40286
|
}
|
|
40906
40287
|
function safeUnlink(p2) {
|
|
40907
40288
|
try {
|
|
40908
|
-
|
|
40289
|
+
import_node_fs22.default.unlinkSync(p2);
|
|
40909
40290
|
} catch {
|
|
40910
40291
|
}
|
|
40911
40292
|
}
|
|
@@ -40916,13 +40297,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
40916
40297
|
if (!res.ok || !res.body) {
|
|
40917
40298
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
40918
40299
|
}
|
|
40919
|
-
const out =
|
|
40920
|
-
const nodeStream =
|
|
40300
|
+
const out = import_node_fs22.default.createWriteStream(dest);
|
|
40301
|
+
const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
|
|
40921
40302
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
40922
40303
|
}
|
|
40923
40304
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
40924
|
-
const work =
|
|
40925
|
-
|
|
40305
|
+
const work = import_node_path22.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
40306
|
+
import_node_fs22.default.mkdirSync(work, { recursive: true });
|
|
40926
40307
|
try {
|
|
40927
40308
|
await new Promise((resolve6, reject) => {
|
|
40928
40309
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -40930,32 +40311,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
40930
40311
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
40931
40312
|
});
|
|
40932
40313
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
40933
|
-
const src =
|
|
40934
|
-
if (!
|
|
40314
|
+
const src = import_node_path22.default.join(work, dirName, "frpc");
|
|
40315
|
+
if (!import_node_fs22.default.existsSync(src)) {
|
|
40935
40316
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
40936
40317
|
}
|
|
40937
|
-
|
|
40318
|
+
import_node_fs22.default.copyFileSync(src, destBin);
|
|
40938
40319
|
} finally {
|
|
40939
|
-
|
|
40320
|
+
import_node_fs22.default.rmSync(work, { recursive: true, force: true });
|
|
40940
40321
|
}
|
|
40941
40322
|
}
|
|
40942
40323
|
|
|
40943
40324
|
// src/tunnel/frpc-process.ts
|
|
40944
|
-
var
|
|
40945
|
-
var
|
|
40325
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40326
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
40946
40327
|
var import_node_child_process8 = require("child_process");
|
|
40947
40328
|
function frpcPidFilePath(dataDir) {
|
|
40948
|
-
return
|
|
40329
|
+
return import_node_path23.default.join(dataDir, "frpc.pid");
|
|
40949
40330
|
}
|
|
40950
40331
|
function writeFrpcPid(dataDir, pid) {
|
|
40951
40332
|
try {
|
|
40952
|
-
|
|
40333
|
+
import_node_fs23.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
40953
40334
|
} catch {
|
|
40954
40335
|
}
|
|
40955
40336
|
}
|
|
40956
40337
|
function clearFrpcPid(dataDir) {
|
|
40957
40338
|
try {
|
|
40958
|
-
|
|
40339
|
+
import_node_fs23.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
40959
40340
|
} catch {
|
|
40960
40341
|
}
|
|
40961
40342
|
}
|
|
@@ -40971,7 +40352,7 @@ function defaultIsPidAlive(pid) {
|
|
|
40971
40352
|
}
|
|
40972
40353
|
function defaultReadPidFile(file) {
|
|
40973
40354
|
try {
|
|
40974
|
-
return
|
|
40355
|
+
return import_node_fs23.default.readFileSync(file, "utf8");
|
|
40975
40356
|
} catch {
|
|
40976
40357
|
return null;
|
|
40977
40358
|
}
|
|
@@ -40987,12 +40368,12 @@ function defaultSleep(ms) {
|
|
|
40987
40368
|
}
|
|
40988
40369
|
async function killStaleFrpc(deps) {
|
|
40989
40370
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
40990
|
-
const tomlPath =
|
|
40371
|
+
const tomlPath = import_node_path23.default.join(deps.dataDir, "frpc.toml");
|
|
40991
40372
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
40992
40373
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
40993
40374
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
40994
40375
|
const scanPids = deps.scanFrpcPidsImpl ?? ((tp) => defaultScanFrpcPidsByCmdline(tp, deps.logger));
|
|
40995
|
-
const
|
|
40376
|
+
const sleep = deps.sleepImpl ?? defaultSleep;
|
|
40996
40377
|
const victims = /* @__PURE__ */ new Set();
|
|
40997
40378
|
const raw = readPidFile(pidFile);
|
|
40998
40379
|
if (raw) {
|
|
@@ -41011,7 +40392,7 @@ async function killStaleFrpc(deps) {
|
|
|
41011
40392
|
}
|
|
41012
40393
|
if (victims.size === 0) {
|
|
41013
40394
|
try {
|
|
41014
|
-
|
|
40395
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
41015
40396
|
} catch {
|
|
41016
40397
|
}
|
|
41017
40398
|
return;
|
|
@@ -41020,9 +40401,9 @@ async function killStaleFrpc(deps) {
|
|
|
41020
40401
|
deps.logger?.warn("tunnel: killing stale frpc before respawn", { pid });
|
|
41021
40402
|
killPid(pid, "SIGKILL");
|
|
41022
40403
|
}
|
|
41023
|
-
await
|
|
40404
|
+
await sleep(deps.reapWaitMs ?? 300);
|
|
41024
40405
|
try {
|
|
41025
|
-
|
|
40406
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
41026
40407
|
} catch {
|
|
41027
40408
|
}
|
|
41028
40409
|
}
|
|
@@ -41059,7 +40440,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
41059
40440
|
var TunnelManager = class {
|
|
41060
40441
|
constructor(deps) {
|
|
41061
40442
|
this.deps = deps;
|
|
41062
|
-
this.store = deps.store ?? new TunnelStore(
|
|
40443
|
+
this.store = deps.store ?? new TunnelStore(import_node_path24.default.join(deps.dataDir, "tunnel.json"));
|
|
41063
40444
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
41064
40445
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
41065
40446
|
}
|
|
@@ -41186,7 +40567,7 @@ var TunnelManager = class {
|
|
|
41186
40567
|
dataDir: this.deps.dataDir,
|
|
41187
40568
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
41188
40569
|
});
|
|
41189
|
-
const tomlPath =
|
|
40570
|
+
const tomlPath = import_node_path24.default.join(this.deps.dataDir, "frpc.toml");
|
|
41190
40571
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
41191
40572
|
const toml = buildFrpcToml({
|
|
41192
40573
|
serverAddr: t.frpsHost,
|
|
@@ -41197,12 +40578,12 @@ var TunnelManager = class {
|
|
|
41197
40578
|
localPort,
|
|
41198
40579
|
logLevel: "info"
|
|
41199
40580
|
});
|
|
41200
|
-
await
|
|
40581
|
+
await import_node_fs24.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
41201
40582
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
41202
40583
|
stdio: ["ignore", "pipe", "pipe"]
|
|
41203
40584
|
});
|
|
41204
|
-
const logFilePath =
|
|
41205
|
-
const logStream =
|
|
40585
|
+
const logFilePath = import_node_path24.default.join(this.deps.dataDir, "frpc.log");
|
|
40586
|
+
const logStream = import_node_fs24.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
41206
40587
|
logStream.on("error", () => {
|
|
41207
40588
|
});
|
|
41208
40589
|
const tee = (chunk) => {
|
|
@@ -41285,27 +40666,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
41285
40666
|
|
|
41286
40667
|
// src/tunnel/device-key.ts
|
|
41287
40668
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
41288
|
-
var
|
|
40669
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
41289
40670
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
41290
40671
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
41291
40672
|
function deriveStableDeviceKey(opts = {}) {
|
|
41292
40673
|
const hostname = opts.hostname ?? import_node_os12.default.hostname();
|
|
41293
40674
|
const uid = opts.uid ?? (typeof import_node_os12.default.userInfo === "function" ? import_node_os12.default.userInfo().uid : 0);
|
|
41294
40675
|
const home = opts.home ?? import_node_os12.default.homedir();
|
|
41295
|
-
const defaultDataDir =
|
|
41296
|
-
const normalizedDataDir = opts.dataDir ?
|
|
40676
|
+
const defaultDataDir = import_node_path25.default.resolve(import_node_path25.default.join(home, ".clawd"));
|
|
40677
|
+
const normalizedDataDir = opts.dataDir ? import_node_path25.default.resolve(opts.dataDir) : null;
|
|
41297
40678
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
41298
40679
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
41299
40680
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
41300
40681
|
}
|
|
41301
40682
|
|
|
41302
40683
|
// src/auth-store.ts
|
|
41303
|
-
var
|
|
41304
|
-
var
|
|
40684
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
40685
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
41305
40686
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
41306
40687
|
var AUTH_FILE_NAME = "auth.json";
|
|
41307
40688
|
function authFilePath(dataDir) {
|
|
41308
|
-
return
|
|
40689
|
+
return import_node_path26.default.join(dataDir, AUTH_FILE_NAME);
|
|
41309
40690
|
}
|
|
41310
40691
|
function loadOrCreateAuthFile(opts) {
|
|
41311
40692
|
const file = authFilePath(opts.dataDir);
|
|
@@ -41339,7 +40720,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
41339
40720
|
}
|
|
41340
40721
|
function readAuthFile(file) {
|
|
41341
40722
|
try {
|
|
41342
|
-
const raw =
|
|
40723
|
+
const raw = import_node_fs25.default.readFileSync(file, "utf8");
|
|
41343
40724
|
const parsed = JSON.parse(raw);
|
|
41344
40725
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
41345
40726
|
return null;
|
|
@@ -41358,25 +40739,25 @@ function readAuthFile(file) {
|
|
|
41358
40739
|
}
|
|
41359
40740
|
}
|
|
41360
40741
|
function writeAuthFile(file, content) {
|
|
41361
|
-
|
|
41362
|
-
|
|
40742
|
+
import_node_fs25.default.mkdirSync(import_node_path26.default.dirname(file), { recursive: true });
|
|
40743
|
+
import_node_fs25.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
41363
40744
|
try {
|
|
41364
|
-
|
|
40745
|
+
import_node_fs25.default.chmodSync(file, 384);
|
|
41365
40746
|
} catch {
|
|
41366
40747
|
}
|
|
41367
40748
|
}
|
|
41368
40749
|
|
|
41369
40750
|
// src/owner-profile.ts
|
|
41370
|
-
var
|
|
40751
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
41371
40752
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
41372
|
-
var
|
|
40753
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
41373
40754
|
var PROFILE_FILENAME = "profile.json";
|
|
41374
40755
|
function loadOwnerDisplayName(dataDir) {
|
|
41375
40756
|
const fallback = import_node_os13.default.userInfo().username;
|
|
41376
|
-
const profilePath =
|
|
40757
|
+
const profilePath = import_node_path27.default.join(dataDir, PROFILE_FILENAME);
|
|
41377
40758
|
let raw;
|
|
41378
40759
|
try {
|
|
41379
|
-
raw =
|
|
40760
|
+
raw = import_node_fs26.default.readFileSync(profilePath, "utf8");
|
|
41380
40761
|
} catch {
|
|
41381
40762
|
return fallback;
|
|
41382
40763
|
}
|
|
@@ -41399,18 +40780,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
41399
40780
|
}
|
|
41400
40781
|
|
|
41401
40782
|
// src/feishu-auth/owner-identity-store.ts
|
|
41402
|
-
var
|
|
41403
|
-
var
|
|
40783
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
40784
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
41404
40785
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
41405
40786
|
var OwnerIdentityStore = class {
|
|
41406
40787
|
file;
|
|
41407
40788
|
constructor(dataDir) {
|
|
41408
|
-
this.file =
|
|
40789
|
+
this.file = import_node_path28.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
41409
40790
|
}
|
|
41410
40791
|
read() {
|
|
41411
40792
|
let raw;
|
|
41412
40793
|
try {
|
|
41413
|
-
raw =
|
|
40794
|
+
raw = import_node_fs27.default.readFileSync(this.file, "utf8");
|
|
41414
40795
|
} catch {
|
|
41415
40796
|
return null;
|
|
41416
40797
|
}
|
|
@@ -41429,7 +40810,8 @@ var OwnerIdentityStore = class {
|
|
|
41429
40810
|
ownerId: r.identity.ownerId,
|
|
41430
40811
|
provider: r.identity.provider,
|
|
41431
40812
|
displayName: r.identity.displayName,
|
|
41432
|
-
...typeof r.identity.avatarUrl === "string" ? { avatarUrl: r.identity.avatarUrl } : {}
|
|
40813
|
+
...typeof r.identity.avatarUrl === "string" ? { avatarUrl: r.identity.avatarUrl } : {},
|
|
40814
|
+
...typeof r.identity.unionId === "string" ? { unionId: r.identity.unionId } : {}
|
|
41433
40815
|
},
|
|
41434
40816
|
ttcToken: r.ttcToken,
|
|
41435
40817
|
ttcTokenExpiresAt: typeof r.ttcTokenExpiresAt === "number" ? r.ttcTokenExpiresAt : null,
|
|
@@ -41437,16 +40819,16 @@ var OwnerIdentityStore = class {
|
|
|
41437
40819
|
};
|
|
41438
40820
|
}
|
|
41439
40821
|
write(record) {
|
|
41440
|
-
|
|
41441
|
-
|
|
40822
|
+
import_node_fs27.default.mkdirSync(import_node_path28.default.dirname(this.file), { recursive: true });
|
|
40823
|
+
import_node_fs27.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
41442
40824
|
try {
|
|
41443
|
-
|
|
40825
|
+
import_node_fs27.default.chmodSync(this.file, 384);
|
|
41444
40826
|
} catch {
|
|
41445
40827
|
}
|
|
41446
40828
|
}
|
|
41447
40829
|
clear() {
|
|
41448
40830
|
try {
|
|
41449
|
-
|
|
40831
|
+
import_node_fs27.default.unlinkSync(this.file);
|
|
41450
40832
|
} catch (err) {
|
|
41451
40833
|
const code = err?.code;
|
|
41452
40834
|
if (code !== "ENOENT") throw err;
|
|
@@ -41550,7 +40932,9 @@ async function fetchTtcUserInfo(opts) {
|
|
|
41550
40932
|
ownerId: d.unique_id,
|
|
41551
40933
|
provider: "ttc",
|
|
41552
40934
|
displayName: d.name,
|
|
41553
|
-
...typeof d.avatar_url === "string" && d.avatar_url.length > 0 ? { avatarUrl: d.avatar_url } : {}
|
|
40935
|
+
...typeof d.avatar_url === "string" && d.avatar_url.length > 0 ? { avatarUrl: d.avatar_url } : {},
|
|
40936
|
+
// union_id 捕获:dataclaw 可信入口用 X-User-UnionId(ownerId 仍是 unique_id,跨登录方式稳定)
|
|
40937
|
+
...typeof d.union_id === "string" && d.union_id.length > 0 ? { unionId: d.union_id } : {}
|
|
41554
40938
|
};
|
|
41555
40939
|
}
|
|
41556
40940
|
|
|
@@ -41565,9 +40949,9 @@ var CentralClientError = class extends Error {
|
|
|
41565
40949
|
code;
|
|
41566
40950
|
cause;
|
|
41567
40951
|
};
|
|
41568
|
-
async function centralRequest(opts,
|
|
40952
|
+
async function centralRequest(opts, path58, init) {
|
|
41569
40953
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
41570
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
40954
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path58}`;
|
|
41571
40955
|
const ctrl = new AbortController();
|
|
41572
40956
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
41573
40957
|
let res;
|
|
@@ -41709,8 +41093,8 @@ function verifyConnectToken(args) {
|
|
|
41709
41093
|
}
|
|
41710
41094
|
|
|
41711
41095
|
// src/feishu-auth/server-key.ts
|
|
41712
|
-
var
|
|
41713
|
-
var
|
|
41096
|
+
var fs36 = __toESM(require("fs"), 1);
|
|
41097
|
+
var path37 = __toESM(require("path"), 1);
|
|
41714
41098
|
var FILE_NAME2 = "server-signing-key.json";
|
|
41715
41099
|
var ServerKeyStore = class {
|
|
41716
41100
|
constructor(dataDir) {
|
|
@@ -41718,12 +41102,12 @@ var ServerKeyStore = class {
|
|
|
41718
41102
|
}
|
|
41719
41103
|
dataDir;
|
|
41720
41104
|
filePath() {
|
|
41721
|
-
return
|
|
41105
|
+
return path37.join(this.dataDir, FILE_NAME2);
|
|
41722
41106
|
}
|
|
41723
41107
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
41724
41108
|
read() {
|
|
41725
41109
|
try {
|
|
41726
|
-
const raw =
|
|
41110
|
+
const raw = fs36.readFileSync(this.filePath(), "utf8");
|
|
41727
41111
|
const parsed = JSON.parse(raw);
|
|
41728
41112
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
41729
41113
|
return parsed.publicKeyPem;
|
|
@@ -41738,12 +41122,12 @@ var ServerKeyStore = class {
|
|
|
41738
41122
|
publicKeyPem,
|
|
41739
41123
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41740
41124
|
};
|
|
41741
|
-
|
|
41742
|
-
|
|
41125
|
+
fs36.mkdirSync(this.dataDir, { recursive: true });
|
|
41126
|
+
fs36.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
41743
41127
|
}
|
|
41744
41128
|
clear() {
|
|
41745
41129
|
try {
|
|
41746
|
-
|
|
41130
|
+
fs36.unlinkSync(this.filePath());
|
|
41747
41131
|
} catch {
|
|
41748
41132
|
}
|
|
41749
41133
|
}
|
|
@@ -41756,12 +41140,12 @@ init_protocol();
|
|
|
41756
41140
|
init_protocol();
|
|
41757
41141
|
|
|
41758
41142
|
// src/session/fork.ts
|
|
41759
|
-
var
|
|
41143
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41760
41144
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
41761
|
-
var
|
|
41145
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
41762
41146
|
init_claude_history();
|
|
41763
41147
|
function readJsonlEntries(file) {
|
|
41764
|
-
const raw =
|
|
41148
|
+
const raw = import_node_fs28.default.readFileSync(file, "utf8");
|
|
41765
41149
|
const out = [];
|
|
41766
41150
|
for (const line of raw.split("\n")) {
|
|
41767
41151
|
const t = line.trim();
|
|
@@ -41774,10 +41158,10 @@ function readJsonlEntries(file) {
|
|
|
41774
41158
|
return out;
|
|
41775
41159
|
}
|
|
41776
41160
|
function forkSession(input) {
|
|
41777
|
-
const baseDir = input.baseDir ??
|
|
41778
|
-
const projectDir =
|
|
41779
|
-
const sourceFile =
|
|
41780
|
-
if (!
|
|
41161
|
+
const baseDir = input.baseDir ?? import_node_path29.default.join(import_node_os14.default.homedir(), ".claude");
|
|
41162
|
+
const projectDir = import_node_path29.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
41163
|
+
const sourceFile = import_node_path29.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
41164
|
+
if (!import_node_fs28.default.existsSync(sourceFile)) {
|
|
41781
41165
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
41782
41166
|
}
|
|
41783
41167
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -41807,9 +41191,9 @@ function forkSession(input) {
|
|
|
41807
41191
|
}
|
|
41808
41192
|
forkedLines.push(JSON.stringify(forked));
|
|
41809
41193
|
}
|
|
41810
|
-
const forkedFilePath =
|
|
41811
|
-
|
|
41812
|
-
|
|
41194
|
+
const forkedFilePath = import_node_path29.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
41195
|
+
import_node_fs28.default.mkdirSync(projectDir, { recursive: true });
|
|
41196
|
+
import_node_fs28.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
41813
41197
|
return { forkedToolSessionId, forkedFilePath };
|
|
41814
41198
|
}
|
|
41815
41199
|
|
|
@@ -42185,7 +41569,7 @@ function buildPermissionHandlers(deps) {
|
|
|
42185
41569
|
}
|
|
42186
41570
|
|
|
42187
41571
|
// src/handlers/history.ts
|
|
42188
|
-
var
|
|
41572
|
+
var path40 = __toESM(require("path"), 1);
|
|
42189
41573
|
init_protocol();
|
|
42190
41574
|
|
|
42191
41575
|
// src/session/recent-dirs.ts
|
|
@@ -42203,7 +41587,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
42203
41587
|
}
|
|
42204
41588
|
|
|
42205
41589
|
// src/permission/persona-paths.ts
|
|
42206
|
-
var
|
|
41590
|
+
var path39 = __toESM(require("path"), 1);
|
|
42207
41591
|
function getAllowedPersonaIds(grants, action) {
|
|
42208
41592
|
const ids = /* @__PURE__ */ new Set();
|
|
42209
41593
|
for (const g2 of grants) {
|
|
@@ -42216,31 +41600,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
42216
41600
|
return ids;
|
|
42217
41601
|
}
|
|
42218
41602
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
42219
|
-
const target =
|
|
41603
|
+
const target = path39.resolve(absPath);
|
|
42220
41604
|
if (userWorkDir) {
|
|
42221
|
-
const u =
|
|
42222
|
-
const usep = u.endsWith(
|
|
41605
|
+
const u = path39.resolve(userWorkDir);
|
|
41606
|
+
const usep = u.endsWith(path39.sep) ? "" : path39.sep;
|
|
42223
41607
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
42224
41608
|
}
|
|
42225
|
-
const root =
|
|
42226
|
-
const sep2 = root.endsWith(
|
|
41609
|
+
const root = path39.resolve(personaRoot);
|
|
41610
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
42227
41611
|
if (!target.startsWith(root + sep2)) return false;
|
|
42228
|
-
const rel =
|
|
41612
|
+
const rel = path39.relative(root, target);
|
|
42229
41613
|
if (!rel || rel.startsWith("..")) return false;
|
|
42230
|
-
const personaId = rel.split(
|
|
41614
|
+
const personaId = rel.split(path39.sep)[0];
|
|
42231
41615
|
if (!personaId) return false;
|
|
42232
41616
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
42233
41617
|
if (allowed === "*") return true;
|
|
42234
41618
|
return allowed.has(personaId);
|
|
42235
41619
|
}
|
|
42236
41620
|
function personaIdFromPath(absPath, personaRoot) {
|
|
42237
|
-
const root =
|
|
42238
|
-
const target =
|
|
42239
|
-
const sep2 = root.endsWith(
|
|
41621
|
+
const root = path39.resolve(personaRoot);
|
|
41622
|
+
const target = path39.resolve(absPath);
|
|
41623
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
42240
41624
|
if (!target.startsWith(root + sep2)) return null;
|
|
42241
|
-
const rel =
|
|
41625
|
+
const rel = path39.relative(root, target);
|
|
42242
41626
|
if (!rel || rel.startsWith("..")) return null;
|
|
42243
|
-
const id = rel.split(
|
|
41627
|
+
const id = rel.split(path39.sep)[0];
|
|
42244
41628
|
return id || null;
|
|
42245
41629
|
}
|
|
42246
41630
|
|
|
@@ -42267,7 +41651,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42267
41651
|
if (!pid) return false;
|
|
42268
41652
|
return isGuestPathAllowed(
|
|
42269
41653
|
ctx.grants,
|
|
42270
|
-
|
|
41654
|
+
path40.join(personaRoot, pid),
|
|
42271
41655
|
personaRoot,
|
|
42272
41656
|
"read",
|
|
42273
41657
|
userWorkDir
|
|
@@ -42279,7 +41663,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42279
41663
|
};
|
|
42280
41664
|
const list = async (frame, _client, ctx) => {
|
|
42281
41665
|
const args = HistoryListArgs.parse(frame);
|
|
42282
|
-
assertGuestPath(ctx,
|
|
41666
|
+
assertGuestPath(ctx, path40.resolve(args.projectPath), personaRoot, "history:list");
|
|
42283
41667
|
const sessions = await history.listSessions(args);
|
|
42284
41668
|
return { response: { type: "history:list", sessions } };
|
|
42285
41669
|
};
|
|
@@ -42311,13 +41695,13 @@ function buildHistoryHandlers(deps) {
|
|
|
42311
41695
|
};
|
|
42312
41696
|
const subagents = async (frame, _client, ctx) => {
|
|
42313
41697
|
const args = HistorySubagentsArgs.parse(frame);
|
|
42314
|
-
assertGuestPath(ctx,
|
|
41698
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
42315
41699
|
const subs = await history.listSubagents(args);
|
|
42316
41700
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
42317
41701
|
};
|
|
42318
41702
|
const subagentRead = async (frame, _client, ctx) => {
|
|
42319
41703
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
42320
|
-
assertGuestPath(ctx,
|
|
41704
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
42321
41705
|
const res = await history.readSubagent(args);
|
|
42322
41706
|
return { response: { type: "history:subagent-read", ...res } };
|
|
42323
41707
|
};
|
|
@@ -42326,7 +41710,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42326
41710
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
42327
41711
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42328
41712
|
const filtered = dirs.filter(
|
|
42329
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
41713
|
+
(d) => isGuestPathAllowed(ctx.grants, path40.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
42330
41714
|
);
|
|
42331
41715
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
42332
41716
|
}
|
|
@@ -42343,7 +41727,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42343
41727
|
}
|
|
42344
41728
|
|
|
42345
41729
|
// src/handlers/workspace.ts
|
|
42346
|
-
var
|
|
41730
|
+
var path41 = __toESM(require("path"), 1);
|
|
42347
41731
|
var os15 = __toESM(require("os"), 1);
|
|
42348
41732
|
init_protocol();
|
|
42349
41733
|
init_protocol();
|
|
@@ -42385,22 +41769,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42385
41769
|
const args = WorkspaceListArgs.parse(frame);
|
|
42386
41770
|
const isGuest = ctx?.principal.kind === "guest";
|
|
42387
41771
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
42388
|
-
const resolvedCwd =
|
|
42389
|
-
const target = args.path ?
|
|
41772
|
+
const resolvedCwd = path41.resolve(args.cwd ?? fallbackCwd);
|
|
41773
|
+
const target = args.path ? path41.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
42390
41774
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
42391
41775
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
42392
41776
|
return { response: { type: "workspace:list", ...res } };
|
|
42393
41777
|
};
|
|
42394
41778
|
const read = async (frame, _client, ctx) => {
|
|
42395
41779
|
const args = WorkspaceReadArgs.parse(frame);
|
|
42396
|
-
const target =
|
|
41780
|
+
const target = path41.isAbsolute(args.path) ? path41.resolve(args.path) : path41.resolve(args.cwd, args.path);
|
|
42397
41781
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
42398
41782
|
const res = workspace.read(args);
|
|
42399
41783
|
return { response: { type: "workspace:read", ...res } };
|
|
42400
41784
|
};
|
|
42401
41785
|
const skillsList = async (frame, _client, ctx) => {
|
|
42402
41786
|
const args = SkillsListArgs.parse(frame);
|
|
42403
|
-
const cwdAbs =
|
|
41787
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
42404
41788
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
42405
41789
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
42406
41790
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -42412,7 +41796,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42412
41796
|
};
|
|
42413
41797
|
const agentsList = async (frame, _client, ctx) => {
|
|
42414
41798
|
const args = AgentsListArgs.parse(frame);
|
|
42415
|
-
const cwdAbs =
|
|
41799
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
42416
41800
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
42417
41801
|
if (args.tool === "codex") {
|
|
42418
41802
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -42434,20 +41818,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42434
41818
|
}
|
|
42435
41819
|
|
|
42436
41820
|
// src/handlers/git.ts
|
|
42437
|
-
var
|
|
41821
|
+
var path43 = __toESM(require("path"), 1);
|
|
42438
41822
|
init_protocol();
|
|
42439
41823
|
init_protocol();
|
|
42440
41824
|
|
|
42441
41825
|
// src/workspace/git.ts
|
|
42442
41826
|
var import_node_child_process10 = require("child_process");
|
|
42443
|
-
var
|
|
42444
|
-
var
|
|
41827
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41828
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
42445
41829
|
var import_node_util = require("util");
|
|
42446
41830
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
42447
41831
|
function normalizePath(p2) {
|
|
42448
|
-
const resolved =
|
|
41832
|
+
const resolved = import_node_path30.default.resolve(p2);
|
|
42449
41833
|
try {
|
|
42450
|
-
return
|
|
41834
|
+
return import_node_fs29.default.realpathSync(resolved);
|
|
42451
41835
|
} catch {
|
|
42452
41836
|
return resolved;
|
|
42453
41837
|
}
|
|
@@ -42521,7 +41905,7 @@ async function listGitBranches(cwd) {
|
|
|
42521
41905
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
42522
41906
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
42523
41907
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42524
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
41908
|
+
if (!isGuestPathAllowed(ctx.grants, path43.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
42525
41909
|
throw new ClawdError(
|
|
42526
41910
|
ERROR_CODES.UNAUTHORIZED,
|
|
42527
41911
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -42937,7 +42321,6 @@ function buildReadyFrame(deps, client) {
|
|
|
42937
42321
|
if (deps.httpToken) fileSharing.httpToken = deps.httpToken;
|
|
42938
42322
|
}
|
|
42939
42323
|
const daemonSource = process.env.CLAWD_DAEMON_SOURCE === "ota" ? "ota" : "packaged";
|
|
42940
|
-
const logShipping = deps.getLogShipping ? deps.getLogShipping() : null;
|
|
42941
42324
|
return {
|
|
42942
42325
|
version,
|
|
42943
42326
|
protocolVersion: PROTOCOL_VERSION,
|
|
@@ -42948,8 +42331,7 @@ function buildReadyFrame(deps, client) {
|
|
|
42948
42331
|
tunnelUrl,
|
|
42949
42332
|
mode: deps.mode,
|
|
42950
42333
|
daemonSource,
|
|
42951
|
-
...fileSharing
|
|
42952
|
-
...logShipping ? { logShipping } : {}
|
|
42334
|
+
...fileSharing
|
|
42953
42335
|
};
|
|
42954
42336
|
}
|
|
42955
42337
|
function buildMetaHandlers(deps) {
|
|
@@ -43037,7 +42419,7 @@ function buildPersonaHandlers(deps) {
|
|
|
43037
42419
|
}
|
|
43038
42420
|
|
|
43039
42421
|
// src/handlers/attachment.ts
|
|
43040
|
-
var
|
|
42422
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
43041
42423
|
init_protocol();
|
|
43042
42424
|
init_protocol();
|
|
43043
42425
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -43092,12 +42474,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
43092
42474
|
`session ${args.sessionId} scope unresolved`
|
|
43093
42475
|
);
|
|
43094
42476
|
}
|
|
43095
|
-
const cwdAbs =
|
|
43096
|
-
const candidateAbs =
|
|
42477
|
+
const cwdAbs = import_node_path31.default.resolve(sessionFile.cwd);
|
|
42478
|
+
const candidateAbs = import_node_path31.default.isAbsolute(args.relPath) ? import_node_path31.default.resolve(args.relPath) : import_node_path31.default.resolve(cwdAbs, args.relPath);
|
|
43097
42479
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
43098
42480
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
43099
42481
|
const entry = entries.find((e) => {
|
|
43100
|
-
const storedAbs =
|
|
42482
|
+
const storedAbs = import_node_path31.default.isAbsolute(e.relPath) ? import_node_path31.default.resolve(e.relPath) : import_node_path31.default.resolve(cwdAbs, e.relPath);
|
|
43101
42483
|
return storedAbs === candidateAbs && !e.stale;
|
|
43102
42484
|
});
|
|
43103
42485
|
if (!entry) {
|
|
@@ -43121,7 +42503,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
43121
42503
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
43122
42504
|
const f = deps.sessionStore.read(sessionId);
|
|
43123
42505
|
if (!f) return;
|
|
43124
|
-
assertGuestAttachmentPath(ctx,
|
|
42506
|
+
assertGuestAttachmentPath(ctx, import_node_path31.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
43125
42507
|
}
|
|
43126
42508
|
const groupAdd = async (frame, _client, ctx) => {
|
|
43127
42509
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -43193,19 +42575,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
43193
42575
|
|
|
43194
42576
|
// src/handlers/extension.ts
|
|
43195
42577
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
43196
|
-
var
|
|
42578
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
43197
42579
|
init_protocol();
|
|
43198
42580
|
|
|
43199
42581
|
// src/extension/bundle-zip.ts
|
|
43200
42582
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
43201
|
-
var
|
|
42583
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
43202
42584
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
43203
42585
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
43204
42586
|
async function bundleExtensionDir(dir) {
|
|
43205
42587
|
const entries = await listFilesSorted(dir);
|
|
43206
42588
|
const zip = new import_jszip2.default();
|
|
43207
42589
|
for (const rel of entries) {
|
|
43208
|
-
const abs =
|
|
42590
|
+
const abs = import_node_path32.default.join(dir, rel);
|
|
43209
42591
|
const content = await import_promises4.default.readFile(abs);
|
|
43210
42592
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
43211
42593
|
}
|
|
@@ -43226,7 +42608,7 @@ async function listFilesSorted(rootDir) {
|
|
|
43226
42608
|
return out;
|
|
43227
42609
|
}
|
|
43228
42610
|
async function walk(absRoot, relPrefix, out) {
|
|
43229
|
-
const dirAbs =
|
|
42611
|
+
const dirAbs = import_node_path32.default.join(absRoot, relPrefix);
|
|
43230
42612
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
43231
42613
|
for (const e of entries) {
|
|
43232
42614
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -43280,25 +42662,25 @@ function computePublishCheck(args) {
|
|
|
43280
42662
|
|
|
43281
42663
|
// src/extension/install-flow.ts
|
|
43282
42664
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
43283
|
-
var
|
|
42665
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
43284
42666
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
43285
42667
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
43286
42668
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
43287
42669
|
|
|
43288
42670
|
// src/extension/paths.ts
|
|
43289
42671
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
43290
|
-
var
|
|
42672
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
43291
42673
|
function clawdHomeRoot(override) {
|
|
43292
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
42674
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path33.default.join(import_node_os16.default.homedir(), ".clawd");
|
|
43293
42675
|
}
|
|
43294
42676
|
function extensionsRoot(override) {
|
|
43295
|
-
return
|
|
42677
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions");
|
|
43296
42678
|
}
|
|
43297
42679
|
function publishedChannelsFile(override) {
|
|
43298
|
-
return
|
|
42680
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
43299
42681
|
}
|
|
43300
42682
|
function bundleCacheRoot(override) {
|
|
43301
|
-
return
|
|
42683
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
43302
42684
|
}
|
|
43303
42685
|
|
|
43304
42686
|
// src/extension/install-flow.ts
|
|
@@ -43325,7 +42707,7 @@ async function installFromChannel(args, deps) {
|
|
|
43325
42707
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43326
42708
|
}
|
|
43327
42709
|
for (const name of Object.keys(zip.files)) {
|
|
43328
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42710
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path34.default.isAbsolute(name)) {
|
|
43329
42711
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43330
42712
|
}
|
|
43331
42713
|
}
|
|
@@ -43357,7 +42739,7 @@ async function installFromChannel(args, deps) {
|
|
|
43357
42739
|
);
|
|
43358
42740
|
}
|
|
43359
42741
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
43360
|
-
const destDir =
|
|
42742
|
+
const destDir = import_node_path34.default.join(deps.extensionsRoot, localExtId);
|
|
43361
42743
|
let destExists = false;
|
|
43362
42744
|
try {
|
|
43363
42745
|
await import_promises5.default.access(destDir);
|
|
@@ -43371,16 +42753,16 @@ async function installFromChannel(args, deps) {
|
|
|
43371
42753
|
);
|
|
43372
42754
|
}
|
|
43373
42755
|
const stage = await import_promises5.default.mkdtemp(
|
|
43374
|
-
|
|
42756
|
+
import_node_path34.default.join(import_node_os17.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
43375
42757
|
);
|
|
43376
42758
|
try {
|
|
43377
42759
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43378
|
-
const dest =
|
|
42760
|
+
const dest = import_node_path34.default.join(stage, name);
|
|
43379
42761
|
if (entry.dir) {
|
|
43380
42762
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
43381
42763
|
continue;
|
|
43382
42764
|
}
|
|
43383
|
-
await import_promises5.default.mkdir(
|
|
42765
|
+
await import_promises5.default.mkdir(import_node_path34.default.dirname(dest), { recursive: true });
|
|
43384
42766
|
if (name === "manifest.json") {
|
|
43385
42767
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43386
42768
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43401,7 +42783,7 @@ async function installFromChannel(args, deps) {
|
|
|
43401
42783
|
|
|
43402
42784
|
// src/extension/update-flow.ts
|
|
43403
42785
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
43404
|
-
var
|
|
42786
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
43405
42787
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
43406
42788
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
43407
42789
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -43418,11 +42800,11 @@ async function updateFromChannel(args, deps) {
|
|
|
43418
42800
|
channelRef.extId,
|
|
43419
42801
|
channelRef.ownerPrincipalId
|
|
43420
42802
|
);
|
|
43421
|
-
const liveDir =
|
|
42803
|
+
const liveDir = import_node_path35.default.join(deps.extensionsRoot, localExtId);
|
|
43422
42804
|
const prevDir = `${liveDir}.prev`;
|
|
43423
42805
|
let existingVersion;
|
|
43424
42806
|
try {
|
|
43425
|
-
const raw = await import_promises6.default.readFile(
|
|
42807
|
+
const raw = await import_promises6.default.readFile(import_node_path35.default.join(liveDir, "manifest.json"), "utf8");
|
|
43426
42808
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
43427
42809
|
if (!parsed2.success) {
|
|
43428
42810
|
throw new UpdateError(
|
|
@@ -43455,7 +42837,7 @@ async function updateFromChannel(args, deps) {
|
|
|
43455
42837
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43456
42838
|
}
|
|
43457
42839
|
for (const name of Object.keys(zip.files)) {
|
|
43458
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42840
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
|
|
43459
42841
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43460
42842
|
}
|
|
43461
42843
|
}
|
|
@@ -43490,16 +42872,16 @@ async function updateFromChannel(args, deps) {
|
|
|
43490
42872
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
43491
42873
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
43492
42874
|
const stage = await import_promises6.default.mkdtemp(
|
|
43493
|
-
|
|
42875
|
+
import_node_path35.default.join(import_node_os18.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
43494
42876
|
);
|
|
43495
42877
|
try {
|
|
43496
42878
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43497
|
-
const dest =
|
|
42879
|
+
const dest = import_node_path35.default.join(stage, name);
|
|
43498
42880
|
if (entry.dir) {
|
|
43499
42881
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
43500
42882
|
continue;
|
|
43501
42883
|
}
|
|
43502
|
-
await import_promises6.default.mkdir(
|
|
42884
|
+
await import_promises6.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
|
|
43503
42885
|
if (name === "manifest.json") {
|
|
43504
42886
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43505
42887
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43592,7 +42974,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43592
42974
|
);
|
|
43593
42975
|
}
|
|
43594
42976
|
}
|
|
43595
|
-
const manifestPath =
|
|
42977
|
+
const manifestPath = import_node_path36.default.join(root, extId, "manifest.json");
|
|
43596
42978
|
const manifest = await readManifest(root, extId);
|
|
43597
42979
|
const next = { ...manifest, version: newVersion };
|
|
43598
42980
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -43600,7 +42982,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43600
42982
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
43601
42983
|
}
|
|
43602
42984
|
async function readManifest(root, extId) {
|
|
43603
|
-
const file =
|
|
42985
|
+
const file = import_node_path36.default.join(root, extId, "manifest.json");
|
|
43604
42986
|
let raw;
|
|
43605
42987
|
try {
|
|
43606
42988
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -43691,7 +43073,7 @@ function buildExtensionHandlers(deps) {
|
|
|
43691
43073
|
};
|
|
43692
43074
|
async function buildSnapshotMeta(extId) {
|
|
43693
43075
|
const manifest = await readManifest(deps.root, extId);
|
|
43694
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
43076
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path36.default.join(deps.root, extId));
|
|
43695
43077
|
return { manifest, contentHash: sha256, buffer };
|
|
43696
43078
|
}
|
|
43697
43079
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -43987,8 +43369,8 @@ var PublishJobRegistry = class {
|
|
|
43987
43369
|
|
|
43988
43370
|
// src/app-builder/publish-job-runner.ts
|
|
43989
43371
|
var import_node_child_process12 = require("child_process");
|
|
43990
|
-
var
|
|
43991
|
-
var
|
|
43372
|
+
var import_node_fs30 = require("fs");
|
|
43373
|
+
var import_node_path37 = require("path");
|
|
43992
43374
|
|
|
43993
43375
|
// src/app-builder/publish-stage-parser.ts
|
|
43994
43376
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -44020,10 +43402,10 @@ async function startPublishJob(deps, args) {
|
|
|
44020
43402
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
44021
43403
|
}
|
|
44022
43404
|
const projDir = projectDir(args.name);
|
|
44023
|
-
const logPath = (0,
|
|
43405
|
+
const logPath = (0, import_node_path37.join)(projDir, ".publish.log");
|
|
44024
43406
|
let logStream = null;
|
|
44025
43407
|
try {
|
|
44026
|
-
logStream = (0,
|
|
43408
|
+
logStream = (0, import_node_fs30.createWriteStream)(logPath, { flags: "w" });
|
|
44027
43409
|
} catch {
|
|
44028
43410
|
logStream = null;
|
|
44029
43411
|
}
|
|
@@ -44280,9 +43662,9 @@ async function recoverInterruptedJobs(deps) {
|
|
|
44280
43662
|
|
|
44281
43663
|
// src/handlers/app-builder.ts
|
|
44282
43664
|
init_protocol();
|
|
44283
|
-
var
|
|
44284
|
-
var
|
|
44285
|
-
var APP_BUILDER_PERSONAS = ["persona-app-builder"];
|
|
43665
|
+
var import_node_path38 = require("path");
|
|
43666
|
+
var import_node_fs31 = require("fs");
|
|
43667
|
+
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
44286
43668
|
var PUBLISH_SCRIPT_REL = "extension-kit/scripts/publish.sh";
|
|
44287
43669
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
44288
43670
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -44363,7 +43745,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44363
43745
|
async function listAllUsersProjects() {
|
|
44364
43746
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
44365
43747
|
const getStore = deps.getStore;
|
|
44366
|
-
const userIds = await
|
|
43748
|
+
const userIds = await import_node_fs31.promises.readdir(deps.usersRoot).catch(() => []);
|
|
44367
43749
|
const perUser = await Promise.all(
|
|
44368
43750
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
44369
43751
|
);
|
|
@@ -44438,7 +43820,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44438
43820
|
const reservedPorts = new Set((await listAllUsersProjects()).map((p2) => p2.port));
|
|
44439
43821
|
const project = await userStore.create(f.name, reservedPorts);
|
|
44440
43822
|
try {
|
|
44441
|
-
const
|
|
43823
|
+
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
43824
|
+
const scaffoldResult = await userStore.scaffold(project.name, void 0, personaRoot);
|
|
44442
43825
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
44443
43826
|
name: project.name,
|
|
44444
43827
|
stdout: scaffoldResult.stdout.slice(0, 200)
|
|
@@ -44657,7 +44040,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44657
44040
|
});
|
|
44658
44041
|
await userStore.clearPublishJob(args.name);
|
|
44659
44042
|
}
|
|
44660
|
-
const scriptPath = (0,
|
|
44043
|
+
const scriptPath = (0, import_node_path38.join)(deps.personaRoot, PUBLISH_SCRIPT_REL);
|
|
44661
44044
|
deps.logger?.info("app-builder.publish.start", {
|
|
44662
44045
|
name: args.name,
|
|
44663
44046
|
sessionId: boundSession.sessionId,
|
|
@@ -44751,7 +44134,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44751
44134
|
|
|
44752
44135
|
// src/extension/registry.ts
|
|
44753
44136
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
44754
|
-
var
|
|
44137
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
44755
44138
|
async function loadAll(root) {
|
|
44756
44139
|
let entries;
|
|
44757
44140
|
try {
|
|
@@ -44764,13 +44147,13 @@ async function loadAll(root) {
|
|
|
44764
44147
|
for (const ent of entries) {
|
|
44765
44148
|
if (!ent.isDirectory()) continue;
|
|
44766
44149
|
if (ent.name.startsWith(".")) continue;
|
|
44767
|
-
records.push(await loadOne(
|
|
44150
|
+
records.push(await loadOne(import_node_path39.default.join(root, ent.name), ent.name));
|
|
44768
44151
|
}
|
|
44769
44152
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
44770
44153
|
return records;
|
|
44771
44154
|
}
|
|
44772
44155
|
async function loadOne(dir, dirName) {
|
|
44773
|
-
const manifestPath =
|
|
44156
|
+
const manifestPath = import_node_path39.default.join(dir, "manifest.json");
|
|
44774
44157
|
let raw;
|
|
44775
44158
|
try {
|
|
44776
44159
|
raw = await import_promises8.default.readFile(manifestPath, "utf8");
|
|
@@ -44815,7 +44198,7 @@ async function loadOne(dir, dirName) {
|
|
|
44815
44198
|
|
|
44816
44199
|
// src/extension/uninstall.ts
|
|
44817
44200
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
44818
|
-
var
|
|
44201
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
44819
44202
|
var UninstallError = class extends Error {
|
|
44820
44203
|
constructor(code, message) {
|
|
44821
44204
|
super(message);
|
|
@@ -44824,7 +44207,7 @@ var UninstallError = class extends Error {
|
|
|
44824
44207
|
code;
|
|
44825
44208
|
};
|
|
44826
44209
|
async function uninstall(deps) {
|
|
44827
|
-
const dir =
|
|
44210
|
+
const dir = import_node_path40.default.join(deps.root, deps.extId);
|
|
44828
44211
|
try {
|
|
44829
44212
|
await import_promises9.default.access(dir);
|
|
44830
44213
|
} catch {
|
|
@@ -44897,15 +44280,16 @@ function buildMethodHandlers(deps) {
|
|
|
44897
44280
|
// personaRoot 用于拼 publish.sh 绝对路径;broadcastSessionFrame 用于失败回灌路径
|
|
44898
44281
|
// (runner 调 manager.send 后逐帧 dispatch 到 transport)。
|
|
44899
44282
|
personaRoot: deps.appBuilderPersonaRoot,
|
|
44283
|
+
resolvePersonaRoot: deps.resolvePersonaRoot,
|
|
44900
44284
|
broadcastSessionFrame: deps.broadcastSessionFrame
|
|
44901
44285
|
})
|
|
44902
44286
|
};
|
|
44903
44287
|
}
|
|
44904
44288
|
|
|
44905
44289
|
// src/app-builder/project-store.ts
|
|
44906
|
-
var
|
|
44290
|
+
var import_node_fs32 = require("fs");
|
|
44907
44291
|
var import_node_child_process13 = require("child_process");
|
|
44908
|
-
var
|
|
44292
|
+
var import_node_path41 = require("path");
|
|
44909
44293
|
init_protocol();
|
|
44910
44294
|
var PROJECTS_DIR = "projects";
|
|
44911
44295
|
var META_FILE = ".clawd-project.json";
|
|
@@ -44920,19 +44304,19 @@ var ProjectStore = class {
|
|
|
44920
44304
|
root;
|
|
44921
44305
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
44922
44306
|
metaPath(name) {
|
|
44923
|
-
return (0,
|
|
44307
|
+
return (0, import_node_path41.join)(this.projectsRoot(), name, META_FILE);
|
|
44924
44308
|
}
|
|
44925
44309
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
44926
44310
|
projectDir(name) {
|
|
44927
|
-
return (0,
|
|
44311
|
+
return (0, import_node_path41.join)(this.projectsRoot(), name);
|
|
44928
44312
|
}
|
|
44929
44313
|
projectsRoot() {
|
|
44930
|
-
return (0,
|
|
44314
|
+
return (0, import_node_path41.join)(this.root, PROJECTS_DIR);
|
|
44931
44315
|
}
|
|
44932
44316
|
async list() {
|
|
44933
44317
|
let entries;
|
|
44934
44318
|
try {
|
|
44935
|
-
entries = await
|
|
44319
|
+
entries = await import_node_fs32.promises.readdir(this.projectsRoot());
|
|
44936
44320
|
} catch (err) {
|
|
44937
44321
|
if (err.code === "ENOENT") return [];
|
|
44938
44322
|
throw err;
|
|
@@ -44940,7 +44324,7 @@ var ProjectStore = class {
|
|
|
44940
44324
|
const out = [];
|
|
44941
44325
|
for (const name of entries) {
|
|
44942
44326
|
try {
|
|
44943
|
-
const raw = await
|
|
44327
|
+
const raw = await import_node_fs32.promises.readFile(this.metaPath(name), "utf8");
|
|
44944
44328
|
const json = JSON.parse(raw);
|
|
44945
44329
|
let migrated = false;
|
|
44946
44330
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -44951,7 +44335,7 @@ var ProjectStore = class {
|
|
|
44951
44335
|
if (parsed.success) {
|
|
44952
44336
|
out.push(parsed.data);
|
|
44953
44337
|
if (migrated) {
|
|
44954
|
-
void
|
|
44338
|
+
void import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
44955
44339
|
});
|
|
44956
44340
|
}
|
|
44957
44341
|
}
|
|
@@ -44995,8 +44379,8 @@ var ProjectStore = class {
|
|
|
44995
44379
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
44996
44380
|
}
|
|
44997
44381
|
const dir = this.projectDir(name);
|
|
44998
|
-
await
|
|
44999
|
-
await
|
|
44382
|
+
await import_node_fs32.promises.mkdir(dir, { recursive: true });
|
|
44383
|
+
await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
45000
44384
|
return meta;
|
|
45001
44385
|
}
|
|
45002
44386
|
/**
|
|
@@ -45008,7 +44392,7 @@ var ProjectStore = class {
|
|
|
45008
44392
|
* 代码再参考"。assistant 进 project 时目录已是完整模板,直接 pnpm install 即可。
|
|
45009
44393
|
*/
|
|
45010
44394
|
async scaffold(name, template = DEFAULT_TEMPLATE, personaRoot = this.root) {
|
|
45011
|
-
const scriptPath = (0,
|
|
44395
|
+
const scriptPath = (0, import_node_path41.join)(personaRoot, SCAFFOLD_SCRIPT_REL);
|
|
45012
44396
|
const destDir = this.projectDir(name);
|
|
45013
44397
|
return await new Promise((resolve6, reject) => {
|
|
45014
44398
|
const child = (0, import_node_child_process13.spawn)("bash", [scriptPath, name, template, destDir], {
|
|
@@ -45041,7 +44425,7 @@ var ProjectStore = class {
|
|
|
45041
44425
|
}
|
|
45042
44426
|
async delete(name) {
|
|
45043
44427
|
const dir = this.projectDir(name);
|
|
45044
|
-
await
|
|
44428
|
+
await import_node_fs32.promises.rm(dir, { recursive: true, force: true });
|
|
45045
44429
|
}
|
|
45046
44430
|
async updatePort(name, newPort) {
|
|
45047
44431
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -45057,7 +44441,7 @@ var ProjectStore = class {
|
|
|
45057
44441
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
45058
44442
|
}
|
|
45059
44443
|
const updated = { ...target, port: newPort };
|
|
45060
|
-
await
|
|
44444
|
+
await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
45061
44445
|
return updated;
|
|
45062
44446
|
}
|
|
45063
44447
|
/**
|
|
@@ -45074,7 +44458,7 @@ var ProjectStore = class {
|
|
|
45074
44458
|
if (!validated.success) {
|
|
45075
44459
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
45076
44460
|
}
|
|
45077
|
-
await
|
|
44461
|
+
await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45078
44462
|
return validated.data;
|
|
45079
44463
|
}
|
|
45080
44464
|
/**
|
|
@@ -45095,7 +44479,7 @@ var ProjectStore = class {
|
|
|
45095
44479
|
if (!validated.success) {
|
|
45096
44480
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
45097
44481
|
}
|
|
45098
|
-
await
|
|
44482
|
+
await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45099
44483
|
return validated.data;
|
|
45100
44484
|
}
|
|
45101
44485
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -45110,7 +44494,7 @@ var ProjectStore = class {
|
|
|
45110
44494
|
if (!validated.success) {
|
|
45111
44495
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
45112
44496
|
}
|
|
45113
|
-
await
|
|
44497
|
+
await import_node_fs32.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45114
44498
|
return validated.data;
|
|
45115
44499
|
}
|
|
45116
44500
|
};
|
|
@@ -45546,7 +44930,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
45546
44930
|
|
|
45547
44931
|
// src/extension/runtime.ts
|
|
45548
44932
|
var import_node_child_process15 = require("child_process");
|
|
45549
|
-
var
|
|
44933
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
45550
44934
|
var import_promises10 = require("timers/promises");
|
|
45551
44935
|
|
|
45552
44936
|
// src/extension/port-allocator.ts
|
|
@@ -45647,7 +45031,7 @@ var Runtime = class {
|
|
|
45647
45031
|
/\$CLAWOS_EXT_PORT/g,
|
|
45648
45032
|
String(port)
|
|
45649
45033
|
);
|
|
45650
|
-
const dir =
|
|
45034
|
+
const dir = import_node_path42.default.join(this.root, extId);
|
|
45651
45035
|
const env = {
|
|
45652
45036
|
...process.env,
|
|
45653
45037
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -45759,7 +45143,7 @@ ${handle.stderrTail}`
|
|
|
45759
45143
|
|
|
45760
45144
|
// src/extension/published-channels.ts
|
|
45761
45145
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
45762
|
-
var
|
|
45146
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
45763
45147
|
init_zod();
|
|
45764
45148
|
var PublishedChannelsError = class extends Error {
|
|
45765
45149
|
constructor(code, message) {
|
|
@@ -45858,7 +45242,7 @@ var PublishedChannelStore = class {
|
|
|
45858
45242
|
)
|
|
45859
45243
|
};
|
|
45860
45244
|
const tmp = `${this.filePath}.tmp`;
|
|
45861
|
-
await import_promises11.default.mkdir(
|
|
45245
|
+
await import_promises11.default.mkdir(import_node_path43.default.dirname(this.filePath), { recursive: true });
|
|
45862
45246
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
45863
45247
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
45864
45248
|
}
|
|
@@ -45866,7 +45250,7 @@ var PublishedChannelStore = class {
|
|
|
45866
45250
|
|
|
45867
45251
|
// src/extension/bundle-cache.ts
|
|
45868
45252
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
45869
|
-
var
|
|
45253
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45870
45254
|
var BundleCache = class {
|
|
45871
45255
|
constructor(rootDir) {
|
|
45872
45256
|
this.rootDir = rootDir;
|
|
@@ -45875,14 +45259,14 @@ var BundleCache = class {
|
|
|
45875
45259
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
45876
45260
|
async write(snapshotHash, buffer) {
|
|
45877
45261
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
45878
|
-
const file =
|
|
45262
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45879
45263
|
const tmp = `${file}.tmp`;
|
|
45880
45264
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
45881
45265
|
await import_promises12.default.rename(tmp, file);
|
|
45882
45266
|
}
|
|
45883
45267
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
45884
45268
|
async read(snapshotHash) {
|
|
45885
|
-
const file =
|
|
45269
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45886
45270
|
try {
|
|
45887
45271
|
return await import_promises12.default.readFile(file);
|
|
45888
45272
|
} catch (e) {
|
|
@@ -45892,33 +45276,16 @@ var BundleCache = class {
|
|
|
45892
45276
|
}
|
|
45893
45277
|
/** Idempotent — missing file is not an error. */
|
|
45894
45278
|
async delete(snapshotHash) {
|
|
45895
|
-
const file =
|
|
45279
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45896
45280
|
await import_promises12.default.rm(file, { force: true });
|
|
45897
45281
|
}
|
|
45898
45282
|
};
|
|
45899
45283
|
|
|
45900
45284
|
// src/index.ts
|
|
45901
|
-
var import_meta4 = {};
|
|
45902
45285
|
async function startDaemon(config) {
|
|
45903
|
-
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
45904
|
-
const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
|
|
45905
|
-
const logClient = createLogClient({
|
|
45906
|
-
endpoint: logShippingCfg.endpoint,
|
|
45907
|
-
identity: {
|
|
45908
|
-
ownerPrincipalId: authFile.ownerPrincipalId,
|
|
45909
|
-
deviceId: authFile.deviceId,
|
|
45910
|
-
appVersion: version,
|
|
45911
|
-
daemonVersion: version,
|
|
45912
|
-
os: `${process.platform}-${process.arch}`
|
|
45913
|
-
},
|
|
45914
|
-
source: "daemon",
|
|
45915
|
-
sampling: logShippingCfg.sampling,
|
|
45916
|
-
homeDir: import_node_os19.default.homedir()
|
|
45917
|
-
});
|
|
45918
45286
|
const logger = createLogger({
|
|
45919
45287
|
level: config.logLevel,
|
|
45920
|
-
file:
|
|
45921
|
-
logClient
|
|
45288
|
+
file: import_node_path45.default.join(config.dataDir, "clawd.log")
|
|
45922
45289
|
});
|
|
45923
45290
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
45924
45291
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -45929,6 +45296,7 @@ async function startDaemon(config) {
|
|
|
45929
45296
|
if (pre.status === "stale") {
|
|
45930
45297
|
logger.warn("stale state file detected, overwriting", { pid: pre.existing.pid });
|
|
45931
45298
|
}
|
|
45299
|
+
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
45932
45300
|
let resolvedAuthToken = null;
|
|
45933
45301
|
if (config.authToken && config.authToken.trim()) {
|
|
45934
45302
|
resolvedAuthToken = config.authToken.trim();
|
|
@@ -46053,8 +45421,8 @@ async function startDaemon(config) {
|
|
|
46053
45421
|
const agents = new AgentsScanner();
|
|
46054
45422
|
const history = new ClaudeHistoryReader();
|
|
46055
45423
|
let transport = null;
|
|
46056
|
-
const personaStore = new PersonaStore(
|
|
46057
|
-
const usersRoot =
|
|
45424
|
+
const personaStore = new PersonaStore(import_node_path45.default.join(config.dataDir, "personas"));
|
|
45425
|
+
const usersRoot = import_node_path45.default.join(config.dataDir, "users");
|
|
46058
45426
|
const defaultsRoot = findDefaultsRoot();
|
|
46059
45427
|
if (defaultsRoot) {
|
|
46060
45428
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -46065,33 +45433,6 @@ async function startDaemon(config) {
|
|
|
46065
45433
|
migrateAgentsMirror({ store: personaStore, logger });
|
|
46066
45434
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
46067
45435
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
46068
|
-
const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
|
|
46069
|
-
const here = typeof __dirname === "string" ? __dirname : import_node_path46.default.dirname((0, import_node_url2.fileURLToPath)(import_meta4.url));
|
|
46070
|
-
const dispatchServerCandidates = [
|
|
46071
|
-
import_node_path46.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
46072
|
-
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
46073
|
-
import_node_path46.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
46074
|
-
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
46075
|
-
];
|
|
46076
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs34.default.existsSync(p2));
|
|
46077
|
-
let dispatchMcpConfigPath2;
|
|
46078
|
-
if (dispatchServerScriptPath) {
|
|
46079
|
-
const dispatchLogPath = import_node_path46.default.join(config.dataDir, "dispatch-mcp-server.log");
|
|
46080
|
-
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
46081
|
-
dataDir: config.dataDir,
|
|
46082
|
-
serverScriptPath: dispatchServerScriptPath,
|
|
46083
|
-
logPath: dispatchLogPath
|
|
46084
|
-
});
|
|
46085
|
-
logger.info("dispatch.mcp.json written", {
|
|
46086
|
-
path: dispatchMcpConfigPath2,
|
|
46087
|
-
server: dispatchServerScriptPath,
|
|
46088
|
-
serverLog: dispatchLogPath
|
|
46089
|
-
});
|
|
46090
|
-
} else {
|
|
46091
|
-
logger.warn("dispatch-mcp-server.cjs not found; persona dispatch disabled (dev tsx \u6A21\u5F0F\u4E0B\u9700\u5148\u8DD1\u8FC7 build)", {
|
|
46092
|
-
tried: dispatchServerCandidates
|
|
46093
|
-
});
|
|
46094
|
-
}
|
|
46095
45436
|
const manager = new SessionManager({
|
|
46096
45437
|
store,
|
|
46097
45438
|
// Phase 2 (capability platform plan §1): factory 注入后 manager.storeFor 走
|
|
@@ -46101,7 +45442,7 @@ async function startDaemon(config) {
|
|
|
46101
45442
|
getAdapter,
|
|
46102
45443
|
historyReader: history,
|
|
46103
45444
|
dataDir: config.dataDir,
|
|
46104
|
-
personaRoot:
|
|
45445
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46105
45446
|
usersRoot,
|
|
46106
45447
|
personaStore,
|
|
46107
45448
|
ownerDisplayName,
|
|
@@ -46112,12 +45453,6 @@ async function startDaemon(config) {
|
|
|
46112
45453
|
// 127.0.0.1(不是 config.host)—— cc 跑在本机,loopback 最稳;外部访问限制 + http-router
|
|
46113
45454
|
// 的 isLoopback 兜底已确保安全。
|
|
46114
45455
|
getDaemonUrl: () => `http://127.0.0.1:${config.port}`,
|
|
46115
|
-
// Persona dispatch (Task 8): manager 通过这两个 deps 跟 PersonaDispatchManager 协作。
|
|
46116
|
-
// - personaDispatchManager: manager.createDispatchedSession 用它 registerBSession;
|
|
46117
|
-
// reducer 通过闭包反查 dispatchId 注 CLAWD_DISPATCH_ID env。
|
|
46118
|
-
// - dispatchMcpConfigPath: reducer 透传到 SpawnContext,cc spawn 加 --mcp-config flag。
|
|
46119
|
-
personaDispatchManager,
|
|
46120
|
-
dispatchMcpConfigPath: dispatchMcpConfigPath2,
|
|
46121
45456
|
broadcastFrame: (frame, target) => {
|
|
46122
45457
|
if (target === "all") {
|
|
46123
45458
|
transport?.broadcastAll(frame);
|
|
@@ -46137,10 +45472,10 @@ async function startDaemon(config) {
|
|
|
46137
45472
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
46138
45473
|
attachmentGroup: {
|
|
46139
45474
|
onFileEdit: (input) => {
|
|
46140
|
-
const absPath =
|
|
45475
|
+
const absPath = import_node_path45.default.isAbsolute(input.relPath) ? input.relPath : import_node_path45.default.join(input.cwd, input.relPath);
|
|
46141
45476
|
let size = 0;
|
|
46142
45477
|
try {
|
|
46143
|
-
size =
|
|
45478
|
+
size = import_node_fs33.default.statSync(absPath).size;
|
|
46144
45479
|
} catch (err) {
|
|
46145
45480
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
46146
45481
|
sessionId: input.sessionId,
|
|
@@ -46326,11 +45661,11 @@ async function startDaemon(config) {
|
|
|
46326
45661
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
46327
45662
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
46328
45663
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
46329
|
-
personaRoot:
|
|
45664
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46330
45665
|
usersRoot
|
|
46331
45666
|
},
|
|
46332
45667
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
46333
|
-
personaRoot:
|
|
45668
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46334
45669
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
46335
45670
|
usersRoot,
|
|
46336
45671
|
// capability:list / delete handler 依赖
|
|
@@ -46419,7 +45754,9 @@ async function startDaemon(config) {
|
|
|
46419
45754
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
46420
45755
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
46421
45756
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
46422
|
-
appBuilderPersonaRoot:
|
|
45757
|
+
appBuilderPersonaRoot: import_node_path45.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
45758
|
+
// scaffold 按当前 session 的 persona 解析其安装根,让新 persona 复用流水线用自己的模板。
|
|
45759
|
+
resolvePersonaRoot: (personaId) => import_node_path45.default.join(config.dataDir, "personas", personaId),
|
|
46423
45760
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
46424
45761
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
46425
45762
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -46440,41 +45777,6 @@ async function startDaemon(config) {
|
|
|
46440
45777
|
logger
|
|
46441
45778
|
});
|
|
46442
45779
|
let handlers = makeHandlers();
|
|
46443
|
-
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
46444
|
-
personaDispatchManager,
|
|
46445
|
-
logger,
|
|
46446
|
-
spawnB: async (args) => {
|
|
46447
|
-
logger.info("dispatch.spawnB.start", {
|
|
46448
|
-
dispatchId: args.dispatchId,
|
|
46449
|
-
targetPersona: args.targetPersona,
|
|
46450
|
-
sourceSessionId: args.sourceSessionId
|
|
46451
|
-
});
|
|
46452
|
-
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
46453
|
-
if (!sourceFile) {
|
|
46454
|
-
throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
|
|
46455
|
-
}
|
|
46456
|
-
const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path46.default.join(
|
|
46457
|
-
import_node_os19.default.homedir(),
|
|
46458
|
-
".claude",
|
|
46459
|
-
"projects",
|
|
46460
|
-
cwdToHashDir(sourceFile.cwd),
|
|
46461
|
-
`${sourceFile.toolSessionId}.jsonl`
|
|
46462
|
-
) : "(no transcript yet \u2014 operate from the task description alone)";
|
|
46463
|
-
logger.info("dispatch.spawnB.source-resolved", {
|
|
46464
|
-
dispatchId: args.dispatchId,
|
|
46465
|
-
sourceJsonlPath,
|
|
46466
|
-
hasToolSessionId: Boolean(sourceFile.toolSessionId)
|
|
46467
|
-
});
|
|
46468
|
-
manager.createDispatchedSession({
|
|
46469
|
-
dispatchId: args.dispatchId,
|
|
46470
|
-
sourceSessionId: args.sourceSessionId,
|
|
46471
|
-
targetPersona: args.targetPersona,
|
|
46472
|
-
prompt: args.prompt,
|
|
46473
|
-
sourceJsonlPath
|
|
46474
|
-
});
|
|
46475
|
-
}
|
|
46476
|
-
});
|
|
46477
|
-
handlers = { ...handlers, ...dispatchHandlers };
|
|
46478
45780
|
const authResolver = new AuthContextResolver({
|
|
46479
45781
|
ownerToken: resolvedAuthToken
|
|
46480
45782
|
});
|
|
@@ -46549,10 +45851,6 @@ async function startDaemon(config) {
|
|
|
46549
45851
|
manager,
|
|
46550
45852
|
getAdapter,
|
|
46551
45853
|
getTunnelUrl: () => currentTunnelUrl,
|
|
46552
|
-
getLogShipping: () => config.logShipping ? {
|
|
46553
|
-
endpoint: config.logShipping.endpoint,
|
|
46554
|
-
sampling: config.logShipping.sampling
|
|
46555
|
-
} : null,
|
|
46556
45854
|
// ready 帧 mode = daemon CC spawn 模式('sdk' | 'tui');UI 用它挂 XtermPanel
|
|
46557
45855
|
mode: config.mode,
|
|
46558
45856
|
// file-sharing 字段:httpBaseUrl 跟 tunnel 状态走;httpToken 复用 owner WS token
|
|
@@ -46707,8 +46005,8 @@ async function startDaemon(config) {
|
|
|
46707
46005
|
const lines = [
|
|
46708
46006
|
`Tunnel: ${r.url}`,
|
|
46709
46007
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
46710
|
-
`Frpc config: ${
|
|
46711
|
-
`Frpc log: ${
|
|
46008
|
+
`Frpc config: ${import_node_path45.default.join(config.dataDir, "frpc.toml")}`,
|
|
46009
|
+
`Frpc log: ${import_node_path45.default.join(config.dataDir, "frpc.log")}`
|
|
46712
46010
|
];
|
|
46713
46011
|
const width = Math.max(...lines.map((l) => l.length));
|
|
46714
46012
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -46721,8 +46019,8 @@ ${bar}
|
|
|
46721
46019
|
|
|
46722
46020
|
`);
|
|
46723
46021
|
try {
|
|
46724
|
-
const connectPath =
|
|
46725
|
-
|
|
46022
|
+
const connectPath = import_node_path45.default.join(config.dataDir, "connect.txt");
|
|
46023
|
+
import_node_fs33.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
46726
46024
|
} catch {
|
|
46727
46025
|
}
|
|
46728
46026
|
} catch (err) {
|
|
@@ -46783,7 +46081,6 @@ ${bar}
|
|
|
46783
46081
|
}
|
|
46784
46082
|
await wss.stop();
|
|
46785
46083
|
stateMgr.delete();
|
|
46786
|
-
if (logClient) await logClient.dispose();
|
|
46787
46084
|
};
|
|
46788
46085
|
return {
|
|
46789
46086
|
stop: shutdown,
|
|
@@ -46794,9 +46091,9 @@ ${bar}
|
|
|
46794
46091
|
};
|
|
46795
46092
|
}
|
|
46796
46093
|
function migrateDropPersonsDir(dataDir) {
|
|
46797
|
-
const dir =
|
|
46094
|
+
const dir = import_node_path45.default.join(dataDir, "persons");
|
|
46798
46095
|
try {
|
|
46799
|
-
|
|
46096
|
+
import_node_fs33.default.rmSync(dir, { recursive: true, force: true });
|
|
46800
46097
|
} catch {
|
|
46801
46098
|
}
|
|
46802
46099
|
}
|