@clawos-dev/clawd 0.2.142 → 0.2.143-beta.301.814d293
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +920 -1562
- package/dist/deploy-kit/.secrets/aliyun.env.example +4 -0
- package/dist/deploy-kit/scripts/new-extension.sh +22 -0
- package/dist/deploy-kit/scripts/publish.sh +100 -0
- package/dist/deploy-kit/scripts/publish.spec.ts +69 -0
- package/dist/{persona-defaults/persona-app-builder/extension-kit → deploy-kit}/scripts/remove-extension.sh +15 -26
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +13 -16
- package/dist/persona-defaults/persona-app-builder/extension-kit/README.md +24 -18
- package/dist/persona-defaults/persona-app-builder/extension-kit/examples/nestjs-react/ext.conf +5 -0
- 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 +66 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/README.md +99 -0
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/config.env +20 -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/ext.conf +5 -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/hooks/pre-deploy.sh +25 -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/persona-defaults/persona-app-builder/extension-kit/scripts/new-extension.sh +0 -66
- package/dist/persona-defaults/persona-app-builder/extension-kit/scripts/publish.sh +0 -110
- /package/dist/{persona-defaults/persona-app-builder → deploy-kit}/.secrets/aliyun.env +0 -0
- /package/dist/{persona-defaults/persona-app-builder/extension-kit → deploy-kit}/contract/bootstrap +0 -0
- /package/dist/{persona-defaults/persona-app-builder/extension-kit → deploy-kit}/scripts/ensure-toolchain.sh +0 -0
- /package/dist/{persona-defaults/persona-app-builder/extension-kit → deploy-kit}/scripts/verify.sh +0 -0
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",
|
|
@@ -35779,6 +35316,56 @@ function migrateCodexSandbox(args) {
|
|
|
35779
35316
|
}
|
|
35780
35317
|
if (n > 0) args.logger.info("persona.codex-sandbox.done", { migrated: n });
|
|
35781
35318
|
}
|
|
35319
|
+
function findDeployKitRoot() {
|
|
35320
|
+
const candidates = [];
|
|
35321
|
+
try {
|
|
35322
|
+
const here = path11.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
35323
|
+
candidates.push(path11.resolve(here, "..", "deploy-kit"));
|
|
35324
|
+
} catch {
|
|
35325
|
+
}
|
|
35326
|
+
if (process.argv[1]) {
|
|
35327
|
+
candidates.push(path11.resolve(path11.dirname(process.argv[1]), "deploy-kit"));
|
|
35328
|
+
}
|
|
35329
|
+
for (const c of candidates) {
|
|
35330
|
+
try {
|
|
35331
|
+
if (fs9.statSync(c).isDirectory()) return c;
|
|
35332
|
+
} catch {
|
|
35333
|
+
}
|
|
35334
|
+
}
|
|
35335
|
+
return null;
|
|
35336
|
+
}
|
|
35337
|
+
function seedDeployKit(args) {
|
|
35338
|
+
const dst = path11.join(args.dataDir, "deploy-kit");
|
|
35339
|
+
fs9.cpSync(args.deployKitBundleRoot, dst, {
|
|
35340
|
+
recursive: true,
|
|
35341
|
+
dereference: true,
|
|
35342
|
+
force: false,
|
|
35343
|
+
errorOnExist: false
|
|
35344
|
+
});
|
|
35345
|
+
args.logger.info("deploy-kit.seed.done", { dst });
|
|
35346
|
+
}
|
|
35347
|
+
function refreshDeployKit(args) {
|
|
35348
|
+
const dst = path11.join(args.dataDir, "deploy-kit");
|
|
35349
|
+
if (!fs9.existsSync(dst)) {
|
|
35350
|
+
seedDeployKit(args);
|
|
35351
|
+
return;
|
|
35352
|
+
}
|
|
35353
|
+
for (const sub of ["scripts", "contract"]) {
|
|
35354
|
+
const s = path11.join(args.deployKitBundleRoot, sub);
|
|
35355
|
+
if (fs9.existsSync(s)) {
|
|
35356
|
+
fs9.cpSync(s, path11.join(dst, sub), { recursive: true, force: true, dereference: true });
|
|
35357
|
+
}
|
|
35358
|
+
}
|
|
35359
|
+
const secretsSrc = path11.join(args.deployKitBundleRoot, ".secrets");
|
|
35360
|
+
if (fs9.existsSync(secretsSrc)) {
|
|
35361
|
+
fs9.mkdirSync(path11.join(dst, ".secrets"), { recursive: true });
|
|
35362
|
+
for (const f of fs9.readdirSync(secretsSrc)) {
|
|
35363
|
+
if (!f.endsWith(".example")) continue;
|
|
35364
|
+
fs9.copyFileSync(path11.join(secretsSrc, f), path11.join(dst, ".secrets", f));
|
|
35365
|
+
}
|
|
35366
|
+
}
|
|
35367
|
+
args.logger.info("deploy-kit.refresh.done", { dst });
|
|
35368
|
+
}
|
|
35782
35369
|
|
|
35783
35370
|
// src/index.ts
|
|
35784
35371
|
init_claude();
|
|
@@ -36033,8 +35620,8 @@ function turnStartInput(text) {
|
|
|
36033
35620
|
const items = [];
|
|
36034
35621
|
let leftover = text;
|
|
36035
35622
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
36036
|
-
const [marker, name,
|
|
36037
|
-
items.push({ type: "skill", name, path:
|
|
35623
|
+
const [marker, name, path58] = m2;
|
|
35624
|
+
items.push({ type: "skill", name, path: path58 });
|
|
36038
35625
|
leftover = leftover.replace(marker, "");
|
|
36039
35626
|
}
|
|
36040
35627
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -36685,7 +36272,7 @@ init_claude_history();
|
|
|
36685
36272
|
|
|
36686
36273
|
// src/pty/pty-child-process.ts
|
|
36687
36274
|
var import_node_events = require("events");
|
|
36688
|
-
var
|
|
36275
|
+
var import_node_stream = require("stream");
|
|
36689
36276
|
var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
36690
36277
|
constructor(pty, opts = {}) {
|
|
36691
36278
|
super();
|
|
@@ -36714,7 +36301,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36714
36301
|
pty.write(data);
|
|
36715
36302
|
}
|
|
36716
36303
|
};
|
|
36717
|
-
this.stdin = new
|
|
36304
|
+
this.stdin = new import_node_stream.Writable({
|
|
36718
36305
|
decodeStrings: false,
|
|
36719
36306
|
write: (chunk, _enc, cb) => {
|
|
36720
36307
|
const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
@@ -36733,7 +36320,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36733
36320
|
}
|
|
36734
36321
|
}
|
|
36735
36322
|
});
|
|
36736
|
-
this.stdout = new
|
|
36323
|
+
this.stdout = new import_node_stream.Readable({ read() {
|
|
36737
36324
|
} });
|
|
36738
36325
|
pty.onData((data) => {
|
|
36739
36326
|
if (!this.firstDataLogged) {
|
|
@@ -36746,7 +36333,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36746
36333
|
}
|
|
36747
36334
|
this.stdout.push(Buffer.from(data, "utf8"));
|
|
36748
36335
|
});
|
|
36749
|
-
this.stderr = new
|
|
36336
|
+
this.stderr = new import_node_stream.Readable({ read() {
|
|
36750
36337
|
} });
|
|
36751
36338
|
pty.onExit(({ exitCode, signal }) => {
|
|
36752
36339
|
this.exitCode = exitCode;
|
|
@@ -37261,9 +36848,6 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
37261
36848
|
if (ctx.addDirs) {
|
|
37262
36849
|
for (const dir of ctx.addDirs) args.push("--add-dir", dir);
|
|
37263
36850
|
}
|
|
37264
|
-
if (ctx.dispatchMcpConfigPath) {
|
|
37265
|
-
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
37266
|
-
}
|
|
37267
36851
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
37268
36852
|
return args;
|
|
37269
36853
|
}
|
|
@@ -37281,155 +36865,6 @@ function jsonlExistsForCtx(ctx) {
|
|
|
37281
36865
|
// src/index.ts
|
|
37282
36866
|
init_claude_history();
|
|
37283
36867
|
|
|
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
36868
|
// src/tools/codex-history.ts
|
|
37434
36869
|
var import_node_child_process5 = require("child_process");
|
|
37435
36870
|
var DEFAULT_TIMEOUT_MS = 8e3;
|
|
@@ -37616,13 +37051,13 @@ function mapSkillsListResponse(res) {
|
|
|
37616
37051
|
const r = s ?? {};
|
|
37617
37052
|
const name = str3(r.name);
|
|
37618
37053
|
if (!name) continue;
|
|
37619
|
-
const
|
|
37054
|
+
const path58 = str3(r.path);
|
|
37620
37055
|
const description = str3(r.description);
|
|
37621
37056
|
const isPlugin = name.includes(":");
|
|
37622
37057
|
out.push({
|
|
37623
37058
|
name,
|
|
37624
37059
|
source: isPlugin ? "plugin" : "project",
|
|
37625
|
-
...
|
|
37060
|
+
...path58 ? { path: path58 } : {},
|
|
37626
37061
|
...description ? { description } : {},
|
|
37627
37062
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
37628
37063
|
});
|
|
@@ -37661,23 +37096,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
37661
37096
|
}
|
|
37662
37097
|
|
|
37663
37098
|
// src/workspace/browser.ts
|
|
37664
|
-
var
|
|
37099
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
37665
37100
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
37666
|
-
var
|
|
37101
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
37667
37102
|
init_protocol();
|
|
37668
37103
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
37669
37104
|
function resolveInsideCwd(cwd, subpath) {
|
|
37670
|
-
const absCwd =
|
|
37671
|
-
const joined =
|
|
37672
|
-
const rel =
|
|
37673
|
-
if (rel.startsWith("..") ||
|
|
37105
|
+
const absCwd = import_node_path10.default.resolve(cwd);
|
|
37106
|
+
const joined = import_node_path10.default.resolve(absCwd, subpath ?? ".");
|
|
37107
|
+
const rel = import_node_path10.default.relative(absCwd, joined);
|
|
37108
|
+
if (rel.startsWith("..") || import_node_path10.default.isAbsolute(rel)) {
|
|
37674
37109
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
37675
37110
|
}
|
|
37676
37111
|
return joined;
|
|
37677
37112
|
}
|
|
37678
37113
|
function ensureCwd(cwd) {
|
|
37679
37114
|
try {
|
|
37680
|
-
const stat =
|
|
37115
|
+
const stat = import_node_fs12.default.statSync(cwd);
|
|
37681
37116
|
if (!stat.isDirectory()) {
|
|
37682
37117
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
37683
37118
|
}
|
|
@@ -37691,7 +37126,7 @@ var WorkspaceBrowser = class {
|
|
|
37691
37126
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
|
|
37692
37127
|
ensureCwd(cwd);
|
|
37693
37128
|
const full = resolveInsideCwd(cwd, args.path);
|
|
37694
|
-
const dirents =
|
|
37129
|
+
const dirents = import_node_fs12.default.readdirSync(full, { withFileTypes: true });
|
|
37695
37130
|
const entries = [];
|
|
37696
37131
|
for (const d of dirents) {
|
|
37697
37132
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -37701,7 +37136,7 @@ var WorkspaceBrowser = class {
|
|
|
37701
37136
|
mtime: ""
|
|
37702
37137
|
};
|
|
37703
37138
|
try {
|
|
37704
|
-
const st =
|
|
37139
|
+
const st = import_node_fs12.default.statSync(import_node_path10.default.join(full, d.name));
|
|
37705
37140
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
37706
37141
|
if (d.isFile()) entry.size = st.size;
|
|
37707
37142
|
} catch {
|
|
@@ -37717,14 +37152,14 @@ var WorkspaceBrowser = class {
|
|
|
37717
37152
|
read(args) {
|
|
37718
37153
|
ensureCwd(args.cwd);
|
|
37719
37154
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
37720
|
-
const st =
|
|
37155
|
+
const st = import_node_fs12.default.statSync(full);
|
|
37721
37156
|
if (!st.isFile()) {
|
|
37722
37157
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
37723
37158
|
}
|
|
37724
37159
|
if (st.size > MAX_FILE_BYTES) {
|
|
37725
37160
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
37726
37161
|
}
|
|
37727
|
-
const buf =
|
|
37162
|
+
const buf = import_node_fs12.default.readFileSync(full);
|
|
37728
37163
|
const isBinary = buf.includes(0);
|
|
37729
37164
|
if (isBinary) {
|
|
37730
37165
|
return {
|
|
@@ -37746,20 +37181,20 @@ var WorkspaceBrowser = class {
|
|
|
37746
37181
|
};
|
|
37747
37182
|
|
|
37748
37183
|
// src/skills/agents-scanner.ts
|
|
37749
|
-
var
|
|
37184
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
37750
37185
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
37751
|
-
var
|
|
37186
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
37752
37187
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
37753
37188
|
function isDirLikeSync2(p2) {
|
|
37754
37189
|
try {
|
|
37755
|
-
return
|
|
37190
|
+
return import_node_fs13.default.statSync(p2).isDirectory();
|
|
37756
37191
|
} catch {
|
|
37757
37192
|
return false;
|
|
37758
37193
|
}
|
|
37759
37194
|
}
|
|
37760
37195
|
function fileExistsSync(p2) {
|
|
37761
37196
|
try {
|
|
37762
|
-
return
|
|
37197
|
+
return import_node_fs13.default.statSync(p2).isFile();
|
|
37763
37198
|
} catch {
|
|
37764
37199
|
return false;
|
|
37765
37200
|
}
|
|
@@ -37767,7 +37202,7 @@ function fileExistsSync(p2) {
|
|
|
37767
37202
|
function parseAgentFile(filePath) {
|
|
37768
37203
|
let content;
|
|
37769
37204
|
try {
|
|
37770
|
-
content =
|
|
37205
|
+
content = import_node_fs13.default.readFileSync(filePath, "utf8");
|
|
37771
37206
|
} catch {
|
|
37772
37207
|
return {};
|
|
37773
37208
|
}
|
|
@@ -37780,16 +37215,16 @@ function parseAgentFile(filePath) {
|
|
|
37780
37215
|
function scanAgentsDir(dir, source, seen, out) {
|
|
37781
37216
|
let entries;
|
|
37782
37217
|
try {
|
|
37783
|
-
entries =
|
|
37218
|
+
entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
37784
37219
|
} catch {
|
|
37785
37220
|
return;
|
|
37786
37221
|
}
|
|
37787
37222
|
for (const ent of entries) {
|
|
37788
37223
|
if (!ent.name.endsWith(".md")) continue;
|
|
37789
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
37224
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path11.default.join(dir, ent.name)))) {
|
|
37790
37225
|
continue;
|
|
37791
37226
|
}
|
|
37792
|
-
const filePath =
|
|
37227
|
+
const filePath = import_node_path11.default.join(dir, ent.name);
|
|
37793
37228
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
37794
37229
|
if (seen.has(baseName)) continue;
|
|
37795
37230
|
seen.add(baseName);
|
|
@@ -37807,12 +37242,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37807
37242
|
function walk2(dir, namespaces) {
|
|
37808
37243
|
let entries;
|
|
37809
37244
|
try {
|
|
37810
|
-
entries =
|
|
37245
|
+
entries = import_node_fs13.default.readdirSync(dir, { withFileTypes: true });
|
|
37811
37246
|
} catch {
|
|
37812
37247
|
return;
|
|
37813
37248
|
}
|
|
37814
37249
|
for (const ent of entries) {
|
|
37815
|
-
const childPath =
|
|
37250
|
+
const childPath = import_node_path11.default.join(dir, ent.name);
|
|
37816
37251
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
37817
37252
|
walk2(childPath, [...namespaces, ent.name]);
|
|
37818
37253
|
continue;
|
|
@@ -37837,13 +37272,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37837
37272
|
walk2(root, []);
|
|
37838
37273
|
}
|
|
37839
37274
|
function readInstalledPlugins2(home) {
|
|
37840
|
-
const pluginsDir =
|
|
37841
|
-
const v2 =
|
|
37842
|
-
const v1 =
|
|
37275
|
+
const pluginsDir = import_node_path11.default.join(home, ".claude", "plugins");
|
|
37276
|
+
const v2 = import_node_path11.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
37277
|
+
const v1 = import_node_path11.default.join(pluginsDir, "installed_plugins.json");
|
|
37843
37278
|
let raw = null;
|
|
37844
37279
|
for (const candidate of [v2, v1]) {
|
|
37845
37280
|
try {
|
|
37846
|
-
raw =
|
|
37281
|
+
raw = import_node_fs13.default.readFileSync(candidate, "utf8");
|
|
37847
37282
|
break;
|
|
37848
37283
|
} catch {
|
|
37849
37284
|
}
|
|
@@ -37868,19 +37303,19 @@ function readInstalledPlugins2(home) {
|
|
|
37868
37303
|
return out;
|
|
37869
37304
|
}
|
|
37870
37305
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
37871
|
-
let cur =
|
|
37872
|
-
const fsRoot =
|
|
37306
|
+
let cur = import_node_path11.default.resolve(startCwd);
|
|
37307
|
+
const fsRoot = import_node_path11.default.parse(cur).root;
|
|
37873
37308
|
while (true) {
|
|
37874
|
-
scanAgentsDir(
|
|
37309
|
+
scanAgentsDir(import_node_path11.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
37875
37310
|
let hasGit = false;
|
|
37876
37311
|
try {
|
|
37877
|
-
hasGit =
|
|
37312
|
+
hasGit = import_node_fs13.default.existsSync(import_node_path11.default.join(cur, ".git"));
|
|
37878
37313
|
} catch {
|
|
37879
37314
|
}
|
|
37880
37315
|
if (hasGit) return;
|
|
37881
37316
|
if (cur === home) return;
|
|
37882
37317
|
if (cur === fsRoot) return;
|
|
37883
|
-
const parent =
|
|
37318
|
+
const parent = import_node_path11.default.dirname(cur);
|
|
37884
37319
|
if (parent === cur) return;
|
|
37885
37320
|
cur = parent;
|
|
37886
37321
|
}
|
|
@@ -37915,7 +37350,7 @@ var AgentsScanner = class {
|
|
|
37915
37350
|
}
|
|
37916
37351
|
const fsBlock = [];
|
|
37917
37352
|
scanAgentsDir(
|
|
37918
|
-
|
|
37353
|
+
import_node_path11.default.join(this.home, ".claude", "agents"),
|
|
37919
37354
|
"global",
|
|
37920
37355
|
seen,
|
|
37921
37356
|
fsBlock
|
|
@@ -37929,7 +37364,7 @@ var AgentsScanner = class {
|
|
|
37929
37364
|
...this.extraPluginRoots
|
|
37930
37365
|
];
|
|
37931
37366
|
for (const { name, root } of plugins) {
|
|
37932
|
-
const agentsRoot =
|
|
37367
|
+
const agentsRoot = import_node_path11.default.join(root, "agents");
|
|
37933
37368
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
37934
37369
|
}
|
|
37935
37370
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -37937,15 +37372,15 @@ var AgentsScanner = class {
|
|
|
37937
37372
|
};
|
|
37938
37373
|
|
|
37939
37374
|
// src/observer/session-observer.ts
|
|
37940
|
-
var
|
|
37375
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37941
37376
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
37942
|
-
var
|
|
37377
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
37943
37378
|
init_claude_history();
|
|
37944
37379
|
|
|
37945
37380
|
// src/observer/subagent-meta-observer.ts
|
|
37946
|
-
var
|
|
37381
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
37947
37382
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
37948
|
-
var
|
|
37383
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37949
37384
|
init_claude_history();
|
|
37950
37385
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
37951
37386
|
var SubagentMetaObserver = class {
|
|
@@ -37958,7 +37393,7 @@ var SubagentMetaObserver = class {
|
|
|
37958
37393
|
watches = /* @__PURE__ */ new Map();
|
|
37959
37394
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
37960
37395
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
37961
|
-
return
|
|
37396
|
+
return import_node_path12.default.join(
|
|
37962
37397
|
this.home,
|
|
37963
37398
|
".claude",
|
|
37964
37399
|
"projects",
|
|
@@ -37988,7 +37423,7 @@ var SubagentMetaObserver = class {
|
|
|
37988
37423
|
attachWatcher(w2) {
|
|
37989
37424
|
if (w2.watcher) return;
|
|
37990
37425
|
try {
|
|
37991
|
-
w2.watcher =
|
|
37426
|
+
w2.watcher = import_node_fs14.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
37992
37427
|
if (!name) return;
|
|
37993
37428
|
const m2 = META_RE.exec(String(name));
|
|
37994
37429
|
if (!m2) return;
|
|
@@ -38000,7 +37435,7 @@ var SubagentMetaObserver = class {
|
|
|
38000
37435
|
scan(w2) {
|
|
38001
37436
|
let entries;
|
|
38002
37437
|
try {
|
|
38003
|
-
entries =
|
|
37438
|
+
entries = import_node_fs14.default.readdirSync(w2.dirPath);
|
|
38004
37439
|
} catch {
|
|
38005
37440
|
return;
|
|
38006
37441
|
}
|
|
@@ -38014,10 +37449,10 @@ var SubagentMetaObserver = class {
|
|
|
38014
37449
|
if (!m2) return;
|
|
38015
37450
|
const agentId = m2[1];
|
|
38016
37451
|
if (w2.emitted.has(agentId)) return;
|
|
38017
|
-
const file =
|
|
37452
|
+
const file = import_node_path12.default.join(w2.dirPath, name);
|
|
38018
37453
|
let raw;
|
|
38019
37454
|
try {
|
|
38020
|
-
raw =
|
|
37455
|
+
raw = import_node_fs14.default.readFileSync(file, "utf8");
|
|
38021
37456
|
} catch {
|
|
38022
37457
|
return;
|
|
38023
37458
|
}
|
|
@@ -38074,14 +37509,14 @@ var SessionObserver = class {
|
|
|
38074
37509
|
metaObserver;
|
|
38075
37510
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
38076
37511
|
if (override) return override;
|
|
38077
|
-
return
|
|
37512
|
+
return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
38078
37513
|
}
|
|
38079
37514
|
start(args) {
|
|
38080
37515
|
this.stop(args.sessionId);
|
|
38081
37516
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
38082
37517
|
let size = 0;
|
|
38083
37518
|
try {
|
|
38084
|
-
size =
|
|
37519
|
+
size = import_node_fs15.default.statSync(filePath).size;
|
|
38085
37520
|
} catch {
|
|
38086
37521
|
}
|
|
38087
37522
|
const w2 = {
|
|
@@ -38095,10 +37530,10 @@ var SessionObserver = class {
|
|
|
38095
37530
|
prevIsRejectSentinel: false
|
|
38096
37531
|
};
|
|
38097
37532
|
try {
|
|
38098
|
-
|
|
37533
|
+
import_node_fs15.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
|
|
38099
37534
|
} catch {
|
|
38100
37535
|
}
|
|
38101
|
-
w2.watcher =
|
|
37536
|
+
w2.watcher = import_node_fs15.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
38102
37537
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
38103
37538
|
this.poll(w2);
|
|
38104
37539
|
});
|
|
@@ -38121,7 +37556,7 @@ var SessionObserver = class {
|
|
|
38121
37556
|
// 异常静默吞,不阻塞 watcher 启动
|
|
38122
37557
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
38123
37558
|
try {
|
|
38124
|
-
const raw =
|
|
37559
|
+
const raw = import_node_fs15.default.readFileSync(w2.filePath, "utf8");
|
|
38125
37560
|
if (!raw) return;
|
|
38126
37561
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
38127
37562
|
if (allLines.length === 0) return;
|
|
@@ -38145,7 +37580,7 @@ var SessionObserver = class {
|
|
|
38145
37580
|
poll(w2) {
|
|
38146
37581
|
let size = 0;
|
|
38147
37582
|
try {
|
|
38148
|
-
size =
|
|
37583
|
+
size = import_node_fs15.default.statSync(w2.filePath).size;
|
|
38149
37584
|
} catch {
|
|
38150
37585
|
return;
|
|
38151
37586
|
}
|
|
@@ -38154,11 +37589,11 @@ var SessionObserver = class {
|
|
|
38154
37589
|
w2.buf = "";
|
|
38155
37590
|
}
|
|
38156
37591
|
if (size === w2.lastSize) return;
|
|
38157
|
-
const fd =
|
|
37592
|
+
const fd = import_node_fs15.default.openSync(w2.filePath, "r");
|
|
38158
37593
|
try {
|
|
38159
37594
|
const len = size - w2.lastSize;
|
|
38160
37595
|
const buf = Buffer.alloc(len);
|
|
38161
|
-
|
|
37596
|
+
import_node_fs15.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
38162
37597
|
w2.lastSize = size;
|
|
38163
37598
|
w2.buf += buf.toString("utf8");
|
|
38164
37599
|
let newlineIndex;
|
|
@@ -38181,7 +37616,7 @@ var SessionObserver = class {
|
|
|
38181
37616
|
}
|
|
38182
37617
|
}
|
|
38183
37618
|
} finally {
|
|
38184
|
-
|
|
37619
|
+
import_node_fs15.default.closeSync(fd);
|
|
38185
37620
|
}
|
|
38186
37621
|
}
|
|
38187
37622
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -38276,7 +37711,7 @@ var import_stream = __toESM(require_stream(), 1);
|
|
|
38276
37711
|
var import_extension = __toESM(require_extension(), 1);
|
|
38277
37712
|
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
38278
37713
|
var import_receiver = __toESM(require_receiver(), 1);
|
|
38279
|
-
var
|
|
37714
|
+
var import_sender = __toESM(require_sender(), 1);
|
|
38280
37715
|
var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
38281
37716
|
var import_websocket = __toESM(require_websocket(), 1);
|
|
38282
37717
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
@@ -38904,14 +38339,14 @@ async function authenticate(token, deps) {
|
|
|
38904
38339
|
}
|
|
38905
38340
|
|
|
38906
38341
|
// src/permission/capability-store.ts
|
|
38907
|
-
var
|
|
38908
|
-
var
|
|
38342
|
+
var fs18 = __toESM(require("fs"), 1);
|
|
38343
|
+
var path18 = __toESM(require("path"), 1);
|
|
38909
38344
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
38910
38345
|
var FILE_VERSION = 1;
|
|
38911
38346
|
var CapabilityStore = class {
|
|
38912
38347
|
constructor(dataDir) {
|
|
38913
38348
|
this.dataDir = dataDir;
|
|
38914
|
-
|
|
38349
|
+
fs18.mkdirSync(dataDir, { recursive: true });
|
|
38915
38350
|
this.cache = this.readFromDisk();
|
|
38916
38351
|
}
|
|
38917
38352
|
dataDir;
|
|
@@ -38935,13 +38370,13 @@ var CapabilityStore = class {
|
|
|
38935
38370
|
this.flush();
|
|
38936
38371
|
}
|
|
38937
38372
|
filePath() {
|
|
38938
|
-
return
|
|
38373
|
+
return path18.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
38939
38374
|
}
|
|
38940
38375
|
readFromDisk() {
|
|
38941
38376
|
const file = this.filePath();
|
|
38942
38377
|
let raw;
|
|
38943
38378
|
try {
|
|
38944
|
-
raw =
|
|
38379
|
+
raw = fs18.readFileSync(file, "utf8");
|
|
38945
38380
|
} catch (err) {
|
|
38946
38381
|
if (err?.code === "ENOENT") return [];
|
|
38947
38382
|
return [];
|
|
@@ -38969,10 +38404,10 @@ var CapabilityStore = class {
|
|
|
38969
38404
|
}
|
|
38970
38405
|
atomicWrite(file, content) {
|
|
38971
38406
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
38972
|
-
|
|
38973
|
-
|
|
38407
|
+
fs18.writeFileSync(tmp, content, { mode: 384 });
|
|
38408
|
+
fs18.renameSync(tmp, file);
|
|
38974
38409
|
try {
|
|
38975
|
-
|
|
38410
|
+
fs18.chmodSync(file, 384);
|
|
38976
38411
|
} catch {
|
|
38977
38412
|
}
|
|
38978
38413
|
}
|
|
@@ -39065,14 +38500,14 @@ var CapabilityManager = class {
|
|
|
39065
38500
|
};
|
|
39066
38501
|
|
|
39067
38502
|
// src/permission/cleanup.ts
|
|
39068
|
-
var
|
|
38503
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
39069
38504
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
39070
38505
|
const removed = [];
|
|
39071
38506
|
for (const g2 of cap.grants) {
|
|
39072
38507
|
if (g2.resource.type !== "persona") continue;
|
|
39073
38508
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
39074
38509
|
try {
|
|
39075
|
-
|
|
38510
|
+
fs19.rmSync(dir, { recursive: true, force: true });
|
|
39076
38511
|
removed.push(dir);
|
|
39077
38512
|
} catch {
|
|
39078
38513
|
}
|
|
@@ -39081,13 +38516,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
39081
38516
|
}
|
|
39082
38517
|
|
|
39083
38518
|
// src/inbox/inbox-store.ts
|
|
39084
|
-
var
|
|
39085
|
-
var
|
|
38519
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
38520
|
+
var path19 = __toESM(require("path"), 1);
|
|
39086
38521
|
var INBOX_SUBDIR = "inbox";
|
|
39087
38522
|
var InboxStore = class {
|
|
39088
38523
|
constructor(dataDir) {
|
|
39089
38524
|
this.dataDir = dataDir;
|
|
39090
|
-
|
|
38525
|
+
fs20.mkdirSync(this.dirPath(), { recursive: true });
|
|
39091
38526
|
}
|
|
39092
38527
|
dataDir;
|
|
39093
38528
|
/**
|
|
@@ -39099,7 +38534,7 @@ var InboxStore = class {
|
|
|
39099
38534
|
const file = this.filePath(peerDeviceId);
|
|
39100
38535
|
let raw;
|
|
39101
38536
|
try {
|
|
39102
|
-
raw =
|
|
38537
|
+
raw = fs20.readFileSync(file, "utf8");
|
|
39103
38538
|
} catch (err) {
|
|
39104
38539
|
if (err?.code === "ENOENT") return [];
|
|
39105
38540
|
return [];
|
|
@@ -39115,7 +38550,7 @@ var InboxStore = class {
|
|
|
39115
38550
|
const dir = this.dirPath();
|
|
39116
38551
|
let entries;
|
|
39117
38552
|
try {
|
|
39118
|
-
entries =
|
|
38553
|
+
entries = fs20.readdirSync(dir);
|
|
39119
38554
|
} catch (err) {
|
|
39120
38555
|
if (err?.code === "ENOENT") return [];
|
|
39121
38556
|
return [];
|
|
@@ -39131,9 +38566,9 @@ var InboxStore = class {
|
|
|
39131
38566
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
39132
38567
|
const file = this.filePath(message.peerDeviceId);
|
|
39133
38568
|
const line = JSON.stringify(message) + "\n";
|
|
39134
|
-
|
|
38569
|
+
fs20.appendFileSync(file, line, { mode: 384 });
|
|
39135
38570
|
try {
|
|
39136
|
-
|
|
38571
|
+
fs20.chmodSync(file, 384);
|
|
39137
38572
|
} catch {
|
|
39138
38573
|
}
|
|
39139
38574
|
}
|
|
@@ -39163,7 +38598,7 @@ var InboxStore = class {
|
|
|
39163
38598
|
removeByPeerDeviceId(peerDeviceId) {
|
|
39164
38599
|
const file = this.filePath(peerDeviceId);
|
|
39165
38600
|
try {
|
|
39166
|
-
|
|
38601
|
+
fs20.unlinkSync(file);
|
|
39167
38602
|
} catch (err) {
|
|
39168
38603
|
if (err?.code === "ENOENT") return;
|
|
39169
38604
|
}
|
|
@@ -39172,18 +38607,18 @@ var InboxStore = class {
|
|
|
39172
38607
|
const file = this.filePath(peerDeviceId);
|
|
39173
38608
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39174
38609
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
39175
|
-
|
|
39176
|
-
|
|
38610
|
+
fs20.writeFileSync(tmp, content, { mode: 384 });
|
|
38611
|
+
fs20.renameSync(tmp, file);
|
|
39177
38612
|
try {
|
|
39178
|
-
|
|
38613
|
+
fs20.chmodSync(file, 384);
|
|
39179
38614
|
} catch {
|
|
39180
38615
|
}
|
|
39181
38616
|
}
|
|
39182
38617
|
dirPath() {
|
|
39183
|
-
return
|
|
38618
|
+
return path19.join(this.dataDir, INBOX_SUBDIR);
|
|
39184
38619
|
}
|
|
39185
38620
|
filePath(peerDeviceId) {
|
|
39186
|
-
return
|
|
38621
|
+
return path19.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
39187
38622
|
}
|
|
39188
38623
|
};
|
|
39189
38624
|
function parseAllLines(raw) {
|
|
@@ -39270,8 +38705,8 @@ var InboxManager = class {
|
|
|
39270
38705
|
};
|
|
39271
38706
|
|
|
39272
38707
|
// src/state/contact-store.ts
|
|
39273
|
-
var
|
|
39274
|
-
var
|
|
38708
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
38709
|
+
var path20 = __toESM(require("path"), 1);
|
|
39275
38710
|
var FILE_NAME = "contacts.json";
|
|
39276
38711
|
var ContactStore = class {
|
|
39277
38712
|
constructor(dataDir) {
|
|
@@ -39281,10 +38716,10 @@ var ContactStore = class {
|
|
|
39281
38716
|
contacts = /* @__PURE__ */ new Map();
|
|
39282
38717
|
load() {
|
|
39283
38718
|
this.contacts.clear();
|
|
39284
|
-
const file =
|
|
38719
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
39285
38720
|
let raw;
|
|
39286
38721
|
try {
|
|
39287
|
-
raw =
|
|
38722
|
+
raw = fs21.readFileSync(file, "utf8");
|
|
39288
38723
|
} catch (err) {
|
|
39289
38724
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
39290
38725
|
return;
|
|
@@ -39327,20 +38762,20 @@ var ContactStore = class {
|
|
|
39327
38762
|
return existed;
|
|
39328
38763
|
}
|
|
39329
38764
|
flush() {
|
|
39330
|
-
const file =
|
|
38765
|
+
const file = path20.join(this.dataDir, FILE_NAME);
|
|
39331
38766
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39332
38767
|
const content = JSON.stringify(
|
|
39333
38768
|
{ contacts: Array.from(this.contacts.values()) },
|
|
39334
38769
|
null,
|
|
39335
38770
|
2
|
|
39336
38771
|
);
|
|
39337
|
-
|
|
39338
|
-
|
|
39339
|
-
|
|
38772
|
+
fs21.mkdirSync(this.dataDir, { recursive: true });
|
|
38773
|
+
fs21.writeFileSync(tmp, content, { mode: 384 });
|
|
38774
|
+
fs21.renameSync(tmp, file);
|
|
39340
38775
|
}
|
|
39341
38776
|
renameBak(file) {
|
|
39342
38777
|
try {
|
|
39343
|
-
|
|
38778
|
+
fs21.renameSync(file, `${file}.bak`);
|
|
39344
38779
|
} catch {
|
|
39345
38780
|
}
|
|
39346
38781
|
}
|
|
@@ -39490,61 +38925,61 @@ async function autoReverseContact(args) {
|
|
|
39490
38925
|
}
|
|
39491
38926
|
|
|
39492
38927
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
39493
|
-
var
|
|
39494
|
-
var
|
|
38928
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
38929
|
+
var path21 = __toESM(require("path"), 1);
|
|
39495
38930
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
39496
38931
|
function migrateFlattenSessions(opts) {
|
|
39497
38932
|
const dataDir = opts.dataDir;
|
|
39498
38933
|
const now = opts.now ?? Date.now;
|
|
39499
|
-
const sessionsDir =
|
|
39500
|
-
const flagPath =
|
|
38934
|
+
const sessionsDir = path21.join(dataDir, "sessions");
|
|
38935
|
+
const flagPath = path21.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
39501
38936
|
if (existsSync3(flagPath)) {
|
|
39502
38937
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
39503
38938
|
}
|
|
39504
38939
|
let movedBare = 0;
|
|
39505
38940
|
let movedVmOwner = 0;
|
|
39506
38941
|
let archivedListener = 0;
|
|
39507
|
-
const defaultDir =
|
|
38942
|
+
const defaultDir = path21.join(sessionsDir, "default");
|
|
39508
38943
|
if (existsSync3(defaultDir)) {
|
|
39509
38944
|
for (const entry of readdirSafe(defaultDir)) {
|
|
39510
38945
|
if (!entry.endsWith(".json")) continue;
|
|
39511
|
-
const src =
|
|
39512
|
-
const dst =
|
|
39513
|
-
|
|
38946
|
+
const src = path21.join(defaultDir, entry);
|
|
38947
|
+
const dst = path21.join(sessionsDir, entry);
|
|
38948
|
+
fs22.renameSync(src, dst);
|
|
39514
38949
|
movedBare += 1;
|
|
39515
38950
|
}
|
|
39516
38951
|
rmdirIfEmpty(defaultDir);
|
|
39517
38952
|
}
|
|
39518
38953
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
39519
|
-
const personaDir =
|
|
38954
|
+
const personaDir = path21.join(sessionsDir, pid);
|
|
39520
38955
|
if (!isDir(personaDir)) continue;
|
|
39521
38956
|
if (pid === "default") continue;
|
|
39522
|
-
const ownerSrc =
|
|
38957
|
+
const ownerSrc = path21.join(personaDir, "owner");
|
|
39523
38958
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
39524
|
-
const ownerDst =
|
|
39525
|
-
|
|
38959
|
+
const ownerDst = path21.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
38960
|
+
fs22.mkdirSync(ownerDst, { recursive: true });
|
|
39526
38961
|
for (const file of readdirSafe(ownerSrc)) {
|
|
39527
38962
|
if (!file.endsWith(".json")) continue;
|
|
39528
|
-
|
|
38963
|
+
fs22.renameSync(path21.join(ownerSrc, file), path21.join(ownerDst, file));
|
|
39529
38964
|
movedVmOwner += 1;
|
|
39530
38965
|
}
|
|
39531
38966
|
rmdirIfEmpty(ownerSrc);
|
|
39532
38967
|
}
|
|
39533
|
-
const listenerSrc =
|
|
38968
|
+
const listenerSrc = path21.join(personaDir, "listener");
|
|
39534
38969
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
39535
|
-
const archiveDst =
|
|
39536
|
-
|
|
38970
|
+
const archiveDst = path21.join(dataDir, ".legacy", `listener-${pid}`);
|
|
38971
|
+
fs22.mkdirSync(archiveDst, { recursive: true });
|
|
39537
38972
|
for (const file of readdirSafe(listenerSrc)) {
|
|
39538
38973
|
if (!file.endsWith(".json")) continue;
|
|
39539
|
-
|
|
38974
|
+
fs22.renameSync(path21.join(listenerSrc, file), path21.join(archiveDst, file));
|
|
39540
38975
|
archivedListener += 1;
|
|
39541
38976
|
}
|
|
39542
38977
|
rmdirIfEmpty(listenerSrc);
|
|
39543
38978
|
}
|
|
39544
38979
|
rmdirIfEmpty(personaDir);
|
|
39545
38980
|
}
|
|
39546
|
-
|
|
39547
|
-
|
|
38981
|
+
fs22.mkdirSync(sessionsDir, { recursive: true });
|
|
38982
|
+
fs22.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
39548
38983
|
return {
|
|
39549
38984
|
skipped: false,
|
|
39550
38985
|
flagWritten: true,
|
|
@@ -39555,7 +38990,7 @@ function migrateFlattenSessions(opts) {
|
|
|
39555
38990
|
}
|
|
39556
38991
|
function existsSync3(p2) {
|
|
39557
38992
|
try {
|
|
39558
|
-
|
|
38993
|
+
fs22.statSync(p2);
|
|
39559
38994
|
return true;
|
|
39560
38995
|
} catch {
|
|
39561
38996
|
return false;
|
|
@@ -39563,31 +38998,31 @@ function existsSync3(p2) {
|
|
|
39563
38998
|
}
|
|
39564
38999
|
function isDir(p2) {
|
|
39565
39000
|
try {
|
|
39566
|
-
return
|
|
39001
|
+
return fs22.statSync(p2).isDirectory();
|
|
39567
39002
|
} catch {
|
|
39568
39003
|
return false;
|
|
39569
39004
|
}
|
|
39570
39005
|
}
|
|
39571
39006
|
function readdirSafe(p2) {
|
|
39572
39007
|
try {
|
|
39573
|
-
return
|
|
39008
|
+
return fs22.readdirSync(p2);
|
|
39574
39009
|
} catch {
|
|
39575
39010
|
return [];
|
|
39576
39011
|
}
|
|
39577
39012
|
}
|
|
39578
39013
|
function rmdirIfEmpty(p2) {
|
|
39579
39014
|
try {
|
|
39580
|
-
|
|
39015
|
+
fs22.rmdirSync(p2);
|
|
39581
39016
|
} catch {
|
|
39582
39017
|
}
|
|
39583
39018
|
}
|
|
39584
39019
|
|
|
39585
39020
|
// src/transport/http-router.ts
|
|
39586
|
-
var
|
|
39587
|
-
var
|
|
39021
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
39022
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
39588
39023
|
|
|
39589
39024
|
// src/attachment/mime.ts
|
|
39590
|
-
var
|
|
39025
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
39591
39026
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
39592
39027
|
var EXT_TO_NATIVE_MIME = {
|
|
39593
39028
|
// 图片
|
|
@@ -39694,7 +39129,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
39694
39129
|
".mk"
|
|
39695
39130
|
]);
|
|
39696
39131
|
function lookupMime(filePathOrName) {
|
|
39697
|
-
const ext =
|
|
39132
|
+
const ext = import_node_path14.default.extname(filePathOrName).toLowerCase();
|
|
39698
39133
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
39699
39134
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
39700
39135
|
return "application/octet-stream";
|
|
@@ -39763,8 +39198,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
39763
39198
|
}
|
|
39764
39199
|
|
|
39765
39200
|
// src/attachment/upload.ts
|
|
39766
|
-
var
|
|
39767
|
-
var
|
|
39201
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
39202
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
39768
39203
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
39769
39204
|
var import_promises = require("stream/promises");
|
|
39770
39205
|
var UploadError = class extends Error {
|
|
@@ -39776,22 +39211,22 @@ var UploadError = class extends Error {
|
|
|
39776
39211
|
code;
|
|
39777
39212
|
};
|
|
39778
39213
|
function assertValidFileName(fileName) {
|
|
39779
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
39214
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path15.default.basename(fileName)) {
|
|
39780
39215
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
39781
39216
|
}
|
|
39782
39217
|
}
|
|
39783
39218
|
var HASH_PREFIX_LEN = 16;
|
|
39784
39219
|
async function writeUploadedAttachment(args) {
|
|
39785
39220
|
assertValidFileName(args.fileName);
|
|
39786
|
-
const attachmentsRoot =
|
|
39221
|
+
const attachmentsRoot = import_node_path15.default.join(args.sessionDir, ".attachments");
|
|
39787
39222
|
try {
|
|
39788
|
-
|
|
39223
|
+
import_node_fs16.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
39789
39224
|
} catch (err) {
|
|
39790
39225
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
39791
39226
|
}
|
|
39792
39227
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
39793
39228
|
let actualSize = 0;
|
|
39794
|
-
const tmpPath =
|
|
39229
|
+
const tmpPath = import_node_path15.default.join(
|
|
39795
39230
|
attachmentsRoot,
|
|
39796
39231
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
39797
39232
|
);
|
|
@@ -39806,18 +39241,18 @@ async function writeUploadedAttachment(args) {
|
|
|
39806
39241
|
yield buf;
|
|
39807
39242
|
}
|
|
39808
39243
|
},
|
|
39809
|
-
|
|
39244
|
+
import_node_fs16.default.createWriteStream(tmpPath, { mode: 384 })
|
|
39810
39245
|
);
|
|
39811
39246
|
} catch (err) {
|
|
39812
39247
|
try {
|
|
39813
|
-
|
|
39248
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39814
39249
|
} catch {
|
|
39815
39250
|
}
|
|
39816
39251
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
39817
39252
|
}
|
|
39818
39253
|
if (actualSize !== args.contentLength) {
|
|
39819
39254
|
try {
|
|
39820
|
-
|
|
39255
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39821
39256
|
} catch {
|
|
39822
39257
|
}
|
|
39823
39258
|
throw new UploadError(
|
|
@@ -39826,35 +39261,35 @@ async function writeUploadedAttachment(args) {
|
|
|
39826
39261
|
);
|
|
39827
39262
|
}
|
|
39828
39263
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
39829
|
-
const hashDir =
|
|
39264
|
+
const hashDir = import_node_path15.default.join(attachmentsRoot, attachmentId);
|
|
39830
39265
|
let finalFileName;
|
|
39831
39266
|
let hashDirExists = false;
|
|
39832
39267
|
try {
|
|
39833
|
-
hashDirExists =
|
|
39268
|
+
hashDirExists = import_node_fs16.default.statSync(hashDir).isDirectory();
|
|
39834
39269
|
} catch {
|
|
39835
39270
|
}
|
|
39836
39271
|
if (hashDirExists) {
|
|
39837
|
-
const existing =
|
|
39272
|
+
const existing = import_node_fs16.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
39838
39273
|
finalFileName = existing[0] ?? args.fileName;
|
|
39839
39274
|
try {
|
|
39840
|
-
|
|
39275
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39841
39276
|
} catch {
|
|
39842
39277
|
}
|
|
39843
39278
|
} else {
|
|
39844
39279
|
try {
|
|
39845
|
-
|
|
39280
|
+
import_node_fs16.default.mkdirSync(hashDir, { recursive: true });
|
|
39846
39281
|
finalFileName = args.fileName;
|
|
39847
|
-
|
|
39282
|
+
import_node_fs16.default.renameSync(tmpPath, import_node_path15.default.join(hashDir, finalFileName));
|
|
39848
39283
|
} catch (err) {
|
|
39849
39284
|
try {
|
|
39850
|
-
|
|
39285
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
39851
39286
|
} catch {
|
|
39852
39287
|
}
|
|
39853
39288
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
39854
39289
|
}
|
|
39855
39290
|
}
|
|
39856
|
-
const absPath =
|
|
39857
|
-
const relPath =
|
|
39291
|
+
const absPath = import_node_path15.default.join(hashDir, finalFileName);
|
|
39292
|
+
const relPath = import_node_path15.default.relative(args.sessionDir, absPath);
|
|
39858
39293
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
39859
39294
|
relPath: absPath,
|
|
39860
39295
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -39868,7 +39303,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39868
39303
|
|
|
39869
39304
|
// src/extension/import.ts
|
|
39870
39305
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
39871
|
-
var
|
|
39306
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
39872
39307
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
39873
39308
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
39874
39309
|
var ImportError = class extends Error {
|
|
@@ -39886,7 +39321,7 @@ async function importZip(buf, root) {
|
|
|
39886
39321
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
39887
39322
|
}
|
|
39888
39323
|
for (const name of Object.keys(zip.files)) {
|
|
39889
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
39324
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path16.default.isAbsolute(name)) {
|
|
39890
39325
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
39891
39326
|
}
|
|
39892
39327
|
}
|
|
@@ -39919,7 +39354,7 @@ async function importZip(buf, root) {
|
|
|
39919
39354
|
);
|
|
39920
39355
|
}
|
|
39921
39356
|
}
|
|
39922
|
-
const destDir =
|
|
39357
|
+
const destDir = import_node_path16.default.join(root, manifest.id);
|
|
39923
39358
|
let destExists = false;
|
|
39924
39359
|
try {
|
|
39925
39360
|
await import_promises2.default.access(destDir);
|
|
@@ -39929,15 +39364,15 @@ async function importZip(buf, root) {
|
|
|
39929
39364
|
if (destExists) {
|
|
39930
39365
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
39931
39366
|
}
|
|
39932
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
39367
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path16.default.join(import_node_os10.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
39933
39368
|
try {
|
|
39934
39369
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
39935
|
-
const dest =
|
|
39370
|
+
const dest = import_node_path16.default.join(stage, name);
|
|
39936
39371
|
if (entry.dir) {
|
|
39937
39372
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
39938
39373
|
continue;
|
|
39939
39374
|
}
|
|
39940
|
-
await import_promises2.default.mkdir(
|
|
39375
|
+
await import_promises2.default.mkdir(import_node_path16.default.dirname(dest), { recursive: true });
|
|
39941
39376
|
const content = await entry.async("nodebuffer");
|
|
39942
39377
|
await import_promises2.default.writeFile(dest, content);
|
|
39943
39378
|
}
|
|
@@ -39963,11 +39398,9 @@ var EXPOSED_RPC_METHODS = [
|
|
|
39963
39398
|
"appBuilder.reportStage",
|
|
39964
39399
|
// 单栏 §5.6.5 fix: UI 切 session 时调(assistant 不需要主动调,但暴露白名单避免误猜成 forbidden)
|
|
39965
39400
|
"appBuilder.setActiveSession",
|
|
39966
|
-
//
|
|
39967
|
-
//
|
|
39968
|
-
|
|
39969
|
-
"personaDispatch.run",
|
|
39970
|
-
"personaDispatch.complete"
|
|
39401
|
+
// dataclaw-builder:persona 建页时取建页人身份(含 union_id)写进生成 app 的配置。
|
|
39402
|
+
// 路由到 handlers['auth:getIdentity'],只返 identity、绝不带 ttcToken(见 handlers/feishu-auth.ts)。
|
|
39403
|
+
"auth.getIdentity"
|
|
39971
39404
|
];
|
|
39972
39405
|
async function handleRpcRequest(input) {
|
|
39973
39406
|
const { method, body, sessionId, dispatcher } = input;
|
|
@@ -40056,7 +39489,7 @@ function isValidUploadFileName(fileName) {
|
|
|
40056
39489
|
if (fileName === "." || fileName === "..") return false;
|
|
40057
39490
|
if (fileName.startsWith(".")) return false;
|
|
40058
39491
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
40059
|
-
return fileName ===
|
|
39492
|
+
return fileName === import_node_path17.default.basename(fileName);
|
|
40060
39493
|
}
|
|
40061
39494
|
function createHttpRouter(deps) {
|
|
40062
39495
|
return async (req, res) => {
|
|
@@ -40103,8 +39536,6 @@ function createHttpRouter(deps) {
|
|
|
40103
39536
|
sendJson(res, 403, { code: "NOT_LOOPBACK", message: "RPC adapter only accepts loopback connections" });
|
|
40104
39537
|
return true;
|
|
40105
39538
|
}
|
|
40106
|
-
req.socket.setTimeout(0);
|
|
40107
|
-
res.socket?.setTimeout(0);
|
|
40108
39539
|
const method = url.pathname.slice(RPC_ROUTE_PREFIX.length).split("?")[0] ?? "";
|
|
40109
39540
|
const sessionId = req.headers["x-clawd-session-id"] ?? void 0;
|
|
40110
39541
|
let body;
|
|
@@ -40287,7 +39718,7 @@ function createHttpRouter(deps) {
|
|
|
40287
39718
|
return true;
|
|
40288
39719
|
}
|
|
40289
39720
|
let absPath;
|
|
40290
|
-
if (
|
|
39721
|
+
if (import_node_path17.default.isAbsolute(pathParam)) {
|
|
40291
39722
|
absPath = pathParam;
|
|
40292
39723
|
} else if (deps.sessionStore) {
|
|
40293
39724
|
const file = deps.sessionStore.read(sid);
|
|
@@ -40295,7 +39726,7 @@ function createHttpRouter(deps) {
|
|
|
40295
39726
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
40296
39727
|
return true;
|
|
40297
39728
|
}
|
|
40298
|
-
absPath =
|
|
39729
|
+
absPath = import_node_path17.default.join(file.cwd, pathParam);
|
|
40299
39730
|
} else {
|
|
40300
39731
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
40301
39732
|
return true;
|
|
@@ -40378,7 +39809,7 @@ function withCtx(ctx, body) {
|
|
|
40378
39809
|
function streamFile(res, absPath, logger) {
|
|
40379
39810
|
let stat;
|
|
40380
39811
|
try {
|
|
40381
|
-
stat =
|
|
39812
|
+
stat = import_node_fs17.default.statSync(absPath);
|
|
40382
39813
|
} catch (err) {
|
|
40383
39814
|
const code = err?.code;
|
|
40384
39815
|
if (code === "ENOENT") {
|
|
@@ -40393,7 +39824,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40393
39824
|
return;
|
|
40394
39825
|
}
|
|
40395
39826
|
const mime = lookupMime(absPath);
|
|
40396
|
-
const basename =
|
|
39827
|
+
const basename = import_node_path17.default.basename(absPath);
|
|
40397
39828
|
res.writeHead(200, {
|
|
40398
39829
|
"Content-Type": mime,
|
|
40399
39830
|
"Content-Length": String(stat.size),
|
|
@@ -40401,7 +39832,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40401
39832
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
40402
39833
|
"X-Content-Type-Options": "nosniff"
|
|
40403
39834
|
});
|
|
40404
|
-
const stream =
|
|
39835
|
+
const stream = import_node_fs17.default.createReadStream(absPath);
|
|
40405
39836
|
stream.on("error", (err) => {
|
|
40406
39837
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
40407
39838
|
res.destroy();
|
|
@@ -40410,8 +39841,8 @@ function streamFile(res, absPath, logger) {
|
|
|
40410
39841
|
}
|
|
40411
39842
|
|
|
40412
39843
|
// src/attachment/gc.ts
|
|
40413
|
-
var
|
|
40414
|
-
var
|
|
39844
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
39845
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
40415
39846
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
40416
39847
|
function runAttachmentGc(args) {
|
|
40417
39848
|
const now = (args.now ?? Date.now)();
|
|
@@ -40420,38 +39851,38 @@ function runAttachmentGc(args) {
|
|
|
40420
39851
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40421
39852
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
40422
39853
|
if (entry.stale) continue;
|
|
40423
|
-
if (
|
|
39854
|
+
if (import_node_path18.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
40424
39855
|
}
|
|
40425
39856
|
}
|
|
40426
39857
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40427
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
39858
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path18.default.join(
|
|
40428
39859
|
args.dataDir,
|
|
40429
39860
|
"sessions",
|
|
40430
39861
|
...scopeSubPath(scope).map(safeFileName),
|
|
40431
39862
|
safeFileName(sessionId)
|
|
40432
39863
|
);
|
|
40433
|
-
const attRoot =
|
|
39864
|
+
const attRoot = import_node_path18.default.join(sessionDir, ".attachments");
|
|
40434
39865
|
let hashDirs;
|
|
40435
39866
|
try {
|
|
40436
|
-
hashDirs =
|
|
39867
|
+
hashDirs = import_node_fs18.default.readdirSync(attRoot);
|
|
40437
39868
|
} catch (err) {
|
|
40438
39869
|
if (err.code === "ENOENT") continue;
|
|
40439
39870
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
40440
39871
|
continue;
|
|
40441
39872
|
}
|
|
40442
39873
|
for (const hashDir of hashDirs) {
|
|
40443
|
-
const hashDirAbs =
|
|
39874
|
+
const hashDirAbs = import_node_path18.default.join(attRoot, hashDir);
|
|
40444
39875
|
let files;
|
|
40445
39876
|
try {
|
|
40446
|
-
files =
|
|
39877
|
+
files = import_node_fs18.default.readdirSync(hashDirAbs);
|
|
40447
39878
|
} catch {
|
|
40448
39879
|
continue;
|
|
40449
39880
|
}
|
|
40450
39881
|
for (const name of files) {
|
|
40451
|
-
const file =
|
|
39882
|
+
const file = import_node_path18.default.join(hashDirAbs, name);
|
|
40452
39883
|
let stat;
|
|
40453
39884
|
try {
|
|
40454
|
-
stat =
|
|
39885
|
+
stat = import_node_fs18.default.statSync(file);
|
|
40455
39886
|
} catch {
|
|
40456
39887
|
continue;
|
|
40457
39888
|
}
|
|
@@ -40460,26 +39891,26 @@ function runAttachmentGc(args) {
|
|
|
40460
39891
|
if (age < ttlMs) continue;
|
|
40461
39892
|
if (liveAbs.has(file)) continue;
|
|
40462
39893
|
try {
|
|
40463
|
-
|
|
39894
|
+
import_node_fs18.default.unlinkSync(file);
|
|
40464
39895
|
} catch (err) {
|
|
40465
39896
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
40466
39897
|
}
|
|
40467
39898
|
}
|
|
40468
39899
|
try {
|
|
40469
|
-
if (
|
|
39900
|
+
if (import_node_fs18.default.readdirSync(hashDirAbs).length === 0) import_node_fs18.default.rmdirSync(hashDirAbs);
|
|
40470
39901
|
} catch {
|
|
40471
39902
|
}
|
|
40472
39903
|
}
|
|
40473
39904
|
try {
|
|
40474
|
-
if (
|
|
39905
|
+
if (import_node_fs18.default.readdirSync(attRoot).length === 0) import_node_fs18.default.rmdirSync(attRoot);
|
|
40475
39906
|
} catch {
|
|
40476
39907
|
}
|
|
40477
39908
|
}
|
|
40478
39909
|
}
|
|
40479
39910
|
|
|
40480
39911
|
// src/attachment/group.ts
|
|
40481
|
-
var
|
|
40482
|
-
var
|
|
39912
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
39913
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
40483
39914
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
40484
39915
|
init_protocol();
|
|
40485
39916
|
var GroupFileStore = class {
|
|
@@ -40491,11 +39922,11 @@ var GroupFileStore = class {
|
|
|
40491
39922
|
this.logger = opts.logger;
|
|
40492
39923
|
}
|
|
40493
39924
|
rootForScope(scope) {
|
|
40494
|
-
return
|
|
39925
|
+
return import_node_path19.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
40495
39926
|
}
|
|
40496
39927
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
40497
39928
|
filePath(scope, sessionId) {
|
|
40498
|
-
return
|
|
39929
|
+
return import_node_path19.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
40499
39930
|
}
|
|
40500
39931
|
cacheKey(scope, sessionId) {
|
|
40501
39932
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -40504,7 +39935,7 @@ var GroupFileStore = class {
|
|
|
40504
39935
|
readFile(scope, sessionId) {
|
|
40505
39936
|
const file = this.filePath(scope, sessionId);
|
|
40506
39937
|
try {
|
|
40507
|
-
const raw =
|
|
39938
|
+
const raw = import_node_fs19.default.readFileSync(file, "utf8");
|
|
40508
39939
|
const parsed = JSON.parse(raw);
|
|
40509
39940
|
if (!Array.isArray(parsed)) {
|
|
40510
39941
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -40530,10 +39961,10 @@ var GroupFileStore = class {
|
|
|
40530
39961
|
}
|
|
40531
39962
|
writeFile(scope, sessionId, entries) {
|
|
40532
39963
|
const file = this.filePath(scope, sessionId);
|
|
40533
|
-
|
|
39964
|
+
import_node_fs19.default.mkdirSync(import_node_path19.default.dirname(file), { recursive: true });
|
|
40534
39965
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
40535
|
-
|
|
40536
|
-
|
|
39966
|
+
import_node_fs19.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
39967
|
+
import_node_fs19.default.renameSync(tmp, file);
|
|
40537
39968
|
}
|
|
40538
39969
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
40539
39970
|
list(scope, sessionId) {
|
|
@@ -40619,10 +40050,10 @@ var GroupFileStore = class {
|
|
|
40619
40050
|
};
|
|
40620
40051
|
|
|
40621
40052
|
// src/discovery/state-file.ts
|
|
40622
|
-
var
|
|
40623
|
-
var
|
|
40053
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
40054
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
40624
40055
|
function defaultStateFilePath(dataDir) {
|
|
40625
|
-
return
|
|
40056
|
+
return import_node_path20.default.join(dataDir, "state.json");
|
|
40626
40057
|
}
|
|
40627
40058
|
function isPidAlive(pid) {
|
|
40628
40059
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -40644,7 +40075,7 @@ var StateFileManager = class {
|
|
|
40644
40075
|
}
|
|
40645
40076
|
read() {
|
|
40646
40077
|
try {
|
|
40647
|
-
const raw =
|
|
40078
|
+
const raw = import_node_fs20.default.readFileSync(this.file, "utf8");
|
|
40648
40079
|
const parsed = JSON.parse(raw);
|
|
40649
40080
|
return parsed;
|
|
40650
40081
|
} catch {
|
|
@@ -40658,20 +40089,20 @@ var StateFileManager = class {
|
|
|
40658
40089
|
return { status: "stale", existing };
|
|
40659
40090
|
}
|
|
40660
40091
|
write(state) {
|
|
40661
|
-
|
|
40092
|
+
import_node_fs20.default.mkdirSync(import_node_path20.default.dirname(this.file), { recursive: true });
|
|
40662
40093
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
40663
|
-
|
|
40664
|
-
|
|
40094
|
+
import_node_fs20.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
40095
|
+
import_node_fs20.default.renameSync(tmp, this.file);
|
|
40665
40096
|
if (process.platform !== "win32") {
|
|
40666
40097
|
try {
|
|
40667
|
-
|
|
40098
|
+
import_node_fs20.default.chmodSync(this.file, 384);
|
|
40668
40099
|
} catch {
|
|
40669
40100
|
}
|
|
40670
40101
|
}
|
|
40671
40102
|
}
|
|
40672
40103
|
delete() {
|
|
40673
40104
|
try {
|
|
40674
|
-
|
|
40105
|
+
import_node_fs20.default.unlinkSync(this.file);
|
|
40675
40106
|
} catch {
|
|
40676
40107
|
}
|
|
40677
40108
|
}
|
|
@@ -40686,14 +40117,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
40686
40117
|
}
|
|
40687
40118
|
|
|
40688
40119
|
// src/tunnel/tunnel-manager.ts
|
|
40689
|
-
var
|
|
40690
|
-
var
|
|
40120
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
40121
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
40691
40122
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
40692
40123
|
var import_node_child_process9 = require("child_process");
|
|
40693
40124
|
|
|
40694
40125
|
// src/tunnel/tunnel-store.ts
|
|
40695
|
-
var
|
|
40696
|
-
var
|
|
40126
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
40127
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40697
40128
|
var TunnelStore = class {
|
|
40698
40129
|
constructor(filePath) {
|
|
40699
40130
|
this.filePath = filePath;
|
|
@@ -40701,7 +40132,7 @@ var TunnelStore = class {
|
|
|
40701
40132
|
filePath;
|
|
40702
40133
|
async get() {
|
|
40703
40134
|
try {
|
|
40704
|
-
const raw = await
|
|
40135
|
+
const raw = await import_node_fs21.default.promises.readFile(this.filePath, "utf8");
|
|
40705
40136
|
const obj = JSON.parse(raw);
|
|
40706
40137
|
if (!isPersistedTunnel(obj)) return null;
|
|
40707
40138
|
return obj;
|
|
@@ -40712,22 +40143,22 @@ var TunnelStore = class {
|
|
|
40712
40143
|
}
|
|
40713
40144
|
}
|
|
40714
40145
|
async set(v2) {
|
|
40715
|
-
const dir =
|
|
40716
|
-
await
|
|
40146
|
+
const dir = import_node_path21.default.dirname(this.filePath);
|
|
40147
|
+
await import_node_fs21.default.promises.mkdir(dir, { recursive: true });
|
|
40717
40148
|
const data = JSON.stringify(v2, null, 2);
|
|
40718
40149
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
40719
|
-
await
|
|
40150
|
+
await import_node_fs21.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
40720
40151
|
if (process.platform !== "win32") {
|
|
40721
40152
|
try {
|
|
40722
|
-
await
|
|
40153
|
+
await import_node_fs21.default.promises.chmod(tmp, 384);
|
|
40723
40154
|
} catch {
|
|
40724
40155
|
}
|
|
40725
40156
|
}
|
|
40726
|
-
await
|
|
40157
|
+
await import_node_fs21.default.promises.rename(tmp, this.filePath);
|
|
40727
40158
|
}
|
|
40728
40159
|
async clear() {
|
|
40729
40160
|
try {
|
|
40730
|
-
await
|
|
40161
|
+
await import_node_fs21.default.promises.unlink(this.filePath);
|
|
40731
40162
|
} catch (err) {
|
|
40732
40163
|
const code = err?.code;
|
|
40733
40164
|
if (code !== "ENOENT") throw err;
|
|
@@ -40822,11 +40253,11 @@ function escape(v2) {
|
|
|
40822
40253
|
}
|
|
40823
40254
|
|
|
40824
40255
|
// src/tunnel/frpc-binary.ts
|
|
40825
|
-
var
|
|
40256
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40826
40257
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
40827
|
-
var
|
|
40258
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40828
40259
|
var import_node_child_process7 = require("child_process");
|
|
40829
|
-
var
|
|
40260
|
+
var import_node_stream2 = require("stream");
|
|
40830
40261
|
var import_promises3 = require("stream/promises");
|
|
40831
40262
|
var FRPC_VERSION = "0.68.0";
|
|
40832
40263
|
var UnsupportedPlatformError = class extends Error {
|
|
@@ -40856,20 +40287,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
40856
40287
|
}
|
|
40857
40288
|
async function ensureFrpcBinary(opts) {
|
|
40858
40289
|
if (opts.override) {
|
|
40859
|
-
if (!
|
|
40290
|
+
if (!import_node_fs22.default.existsSync(opts.override)) {
|
|
40860
40291
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
40861
40292
|
}
|
|
40862
40293
|
return opts.override;
|
|
40863
40294
|
}
|
|
40864
40295
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
40865
40296
|
const platform = opts.platform ?? detectPlatform();
|
|
40866
|
-
const binDir =
|
|
40867
|
-
|
|
40297
|
+
const binDir = import_node_path22.default.join(opts.dataDir, "bin");
|
|
40298
|
+
import_node_fs22.default.mkdirSync(binDir, { recursive: true });
|
|
40868
40299
|
cleanupStaleArtifacts(binDir);
|
|
40869
|
-
const stableBin =
|
|
40870
|
-
if (
|
|
40300
|
+
const stableBin = import_node_path22.default.join(binDir, "frpc");
|
|
40301
|
+
if (import_node_fs22.default.existsSync(stableBin)) return stableBin;
|
|
40871
40302
|
const partialBin = `${stableBin}.partial`;
|
|
40872
|
-
const tarballPath =
|
|
40303
|
+
const tarballPath = import_node_path22.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
40873
40304
|
try {
|
|
40874
40305
|
const url = frpcDownloadUrl(version2, platform);
|
|
40875
40306
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -40878,8 +40309,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
40878
40309
|
} else {
|
|
40879
40310
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
40880
40311
|
}
|
|
40881
|
-
|
|
40882
|
-
|
|
40312
|
+
import_node_fs22.default.chmodSync(partialBin, 493);
|
|
40313
|
+
import_node_fs22.default.renameSync(partialBin, stableBin);
|
|
40883
40314
|
} finally {
|
|
40884
40315
|
safeUnlink(tarballPath);
|
|
40885
40316
|
safeUnlink(partialBin);
|
|
@@ -40889,15 +40320,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
40889
40320
|
function cleanupStaleArtifacts(binDir) {
|
|
40890
40321
|
let entries;
|
|
40891
40322
|
try {
|
|
40892
|
-
entries =
|
|
40323
|
+
entries = import_node_fs22.default.readdirSync(binDir);
|
|
40893
40324
|
} catch {
|
|
40894
40325
|
return;
|
|
40895
40326
|
}
|
|
40896
40327
|
for (const name of entries) {
|
|
40897
40328
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
40898
|
-
const full =
|
|
40329
|
+
const full = import_node_path22.default.join(binDir, name);
|
|
40899
40330
|
try {
|
|
40900
|
-
|
|
40331
|
+
import_node_fs22.default.rmSync(full, { recursive: true, force: true });
|
|
40901
40332
|
} catch {
|
|
40902
40333
|
}
|
|
40903
40334
|
}
|
|
@@ -40905,7 +40336,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
40905
40336
|
}
|
|
40906
40337
|
function safeUnlink(p2) {
|
|
40907
40338
|
try {
|
|
40908
|
-
|
|
40339
|
+
import_node_fs22.default.unlinkSync(p2);
|
|
40909
40340
|
} catch {
|
|
40910
40341
|
}
|
|
40911
40342
|
}
|
|
@@ -40916,13 +40347,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
40916
40347
|
if (!res.ok || !res.body) {
|
|
40917
40348
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
40918
40349
|
}
|
|
40919
|
-
const out =
|
|
40920
|
-
const nodeStream =
|
|
40350
|
+
const out = import_node_fs22.default.createWriteStream(dest);
|
|
40351
|
+
const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
|
|
40921
40352
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
40922
40353
|
}
|
|
40923
40354
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
40924
|
-
const work =
|
|
40925
|
-
|
|
40355
|
+
const work = import_node_path22.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
40356
|
+
import_node_fs22.default.mkdirSync(work, { recursive: true });
|
|
40926
40357
|
try {
|
|
40927
40358
|
await new Promise((resolve6, reject) => {
|
|
40928
40359
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -40930,32 +40361,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
40930
40361
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
40931
40362
|
});
|
|
40932
40363
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
40933
|
-
const src =
|
|
40934
|
-
if (!
|
|
40364
|
+
const src = import_node_path22.default.join(work, dirName, "frpc");
|
|
40365
|
+
if (!import_node_fs22.default.existsSync(src)) {
|
|
40935
40366
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
40936
40367
|
}
|
|
40937
|
-
|
|
40368
|
+
import_node_fs22.default.copyFileSync(src, destBin);
|
|
40938
40369
|
} finally {
|
|
40939
|
-
|
|
40370
|
+
import_node_fs22.default.rmSync(work, { recursive: true, force: true });
|
|
40940
40371
|
}
|
|
40941
40372
|
}
|
|
40942
40373
|
|
|
40943
40374
|
// src/tunnel/frpc-process.ts
|
|
40944
|
-
var
|
|
40945
|
-
var
|
|
40375
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40376
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
40946
40377
|
var import_node_child_process8 = require("child_process");
|
|
40947
40378
|
function frpcPidFilePath(dataDir) {
|
|
40948
|
-
return
|
|
40379
|
+
return import_node_path23.default.join(dataDir, "frpc.pid");
|
|
40949
40380
|
}
|
|
40950
40381
|
function writeFrpcPid(dataDir, pid) {
|
|
40951
40382
|
try {
|
|
40952
|
-
|
|
40383
|
+
import_node_fs23.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
40953
40384
|
} catch {
|
|
40954
40385
|
}
|
|
40955
40386
|
}
|
|
40956
40387
|
function clearFrpcPid(dataDir) {
|
|
40957
40388
|
try {
|
|
40958
|
-
|
|
40389
|
+
import_node_fs23.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
40959
40390
|
} catch {
|
|
40960
40391
|
}
|
|
40961
40392
|
}
|
|
@@ -40971,7 +40402,7 @@ function defaultIsPidAlive(pid) {
|
|
|
40971
40402
|
}
|
|
40972
40403
|
function defaultReadPidFile(file) {
|
|
40973
40404
|
try {
|
|
40974
|
-
return
|
|
40405
|
+
return import_node_fs23.default.readFileSync(file, "utf8");
|
|
40975
40406
|
} catch {
|
|
40976
40407
|
return null;
|
|
40977
40408
|
}
|
|
@@ -40987,12 +40418,12 @@ function defaultSleep(ms) {
|
|
|
40987
40418
|
}
|
|
40988
40419
|
async function killStaleFrpc(deps) {
|
|
40989
40420
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
40990
|
-
const tomlPath =
|
|
40421
|
+
const tomlPath = import_node_path23.default.join(deps.dataDir, "frpc.toml");
|
|
40991
40422
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
40992
40423
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
40993
40424
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
40994
40425
|
const scanPids = deps.scanFrpcPidsImpl ?? ((tp) => defaultScanFrpcPidsByCmdline(tp, deps.logger));
|
|
40995
|
-
const
|
|
40426
|
+
const sleep = deps.sleepImpl ?? defaultSleep;
|
|
40996
40427
|
const victims = /* @__PURE__ */ new Set();
|
|
40997
40428
|
const raw = readPidFile(pidFile);
|
|
40998
40429
|
if (raw) {
|
|
@@ -41011,7 +40442,7 @@ async function killStaleFrpc(deps) {
|
|
|
41011
40442
|
}
|
|
41012
40443
|
if (victims.size === 0) {
|
|
41013
40444
|
try {
|
|
41014
|
-
|
|
40445
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
41015
40446
|
} catch {
|
|
41016
40447
|
}
|
|
41017
40448
|
return;
|
|
@@ -41020,9 +40451,9 @@ async function killStaleFrpc(deps) {
|
|
|
41020
40451
|
deps.logger?.warn("tunnel: killing stale frpc before respawn", { pid });
|
|
41021
40452
|
killPid(pid, "SIGKILL");
|
|
41022
40453
|
}
|
|
41023
|
-
await
|
|
40454
|
+
await sleep(deps.reapWaitMs ?? 300);
|
|
41024
40455
|
try {
|
|
41025
|
-
|
|
40456
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
41026
40457
|
} catch {
|
|
41027
40458
|
}
|
|
41028
40459
|
}
|
|
@@ -41059,7 +40490,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
41059
40490
|
var TunnelManager = class {
|
|
41060
40491
|
constructor(deps) {
|
|
41061
40492
|
this.deps = deps;
|
|
41062
|
-
this.store = deps.store ?? new TunnelStore(
|
|
40493
|
+
this.store = deps.store ?? new TunnelStore(import_node_path24.default.join(deps.dataDir, "tunnel.json"));
|
|
41063
40494
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
41064
40495
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
41065
40496
|
}
|
|
@@ -41186,7 +40617,7 @@ var TunnelManager = class {
|
|
|
41186
40617
|
dataDir: this.deps.dataDir,
|
|
41187
40618
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
41188
40619
|
});
|
|
41189
|
-
const tomlPath =
|
|
40620
|
+
const tomlPath = import_node_path24.default.join(this.deps.dataDir, "frpc.toml");
|
|
41190
40621
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
41191
40622
|
const toml = buildFrpcToml({
|
|
41192
40623
|
serverAddr: t.frpsHost,
|
|
@@ -41197,12 +40628,12 @@ var TunnelManager = class {
|
|
|
41197
40628
|
localPort,
|
|
41198
40629
|
logLevel: "info"
|
|
41199
40630
|
});
|
|
41200
|
-
await
|
|
40631
|
+
await import_node_fs24.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
41201
40632
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
41202
40633
|
stdio: ["ignore", "pipe", "pipe"]
|
|
41203
40634
|
});
|
|
41204
|
-
const logFilePath =
|
|
41205
|
-
const logStream =
|
|
40635
|
+
const logFilePath = import_node_path24.default.join(this.deps.dataDir, "frpc.log");
|
|
40636
|
+
const logStream = import_node_fs24.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
41206
40637
|
logStream.on("error", () => {
|
|
41207
40638
|
});
|
|
41208
40639
|
const tee = (chunk) => {
|
|
@@ -41285,27 +40716,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
41285
40716
|
|
|
41286
40717
|
// src/tunnel/device-key.ts
|
|
41287
40718
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
41288
|
-
var
|
|
40719
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
41289
40720
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
41290
40721
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
41291
40722
|
function deriveStableDeviceKey(opts = {}) {
|
|
41292
40723
|
const hostname = opts.hostname ?? import_node_os12.default.hostname();
|
|
41293
40724
|
const uid = opts.uid ?? (typeof import_node_os12.default.userInfo === "function" ? import_node_os12.default.userInfo().uid : 0);
|
|
41294
40725
|
const home = opts.home ?? import_node_os12.default.homedir();
|
|
41295
|
-
const defaultDataDir =
|
|
41296
|
-
const normalizedDataDir = opts.dataDir ?
|
|
40726
|
+
const defaultDataDir = import_node_path25.default.resolve(import_node_path25.default.join(home, ".clawd"));
|
|
40727
|
+
const normalizedDataDir = opts.dataDir ? import_node_path25.default.resolve(opts.dataDir) : null;
|
|
41297
40728
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
41298
40729
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
41299
40730
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
41300
40731
|
}
|
|
41301
40732
|
|
|
41302
40733
|
// src/auth-store.ts
|
|
41303
|
-
var
|
|
41304
|
-
var
|
|
40734
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
40735
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
41305
40736
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
41306
40737
|
var AUTH_FILE_NAME = "auth.json";
|
|
41307
40738
|
function authFilePath(dataDir) {
|
|
41308
|
-
return
|
|
40739
|
+
return import_node_path26.default.join(dataDir, AUTH_FILE_NAME);
|
|
41309
40740
|
}
|
|
41310
40741
|
function loadOrCreateAuthFile(opts) {
|
|
41311
40742
|
const file = authFilePath(opts.dataDir);
|
|
@@ -41339,7 +40770,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
41339
40770
|
}
|
|
41340
40771
|
function readAuthFile(file) {
|
|
41341
40772
|
try {
|
|
41342
|
-
const raw =
|
|
40773
|
+
const raw = import_node_fs25.default.readFileSync(file, "utf8");
|
|
41343
40774
|
const parsed = JSON.parse(raw);
|
|
41344
40775
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
41345
40776
|
return null;
|
|
@@ -41358,25 +40789,25 @@ function readAuthFile(file) {
|
|
|
41358
40789
|
}
|
|
41359
40790
|
}
|
|
41360
40791
|
function writeAuthFile(file, content) {
|
|
41361
|
-
|
|
41362
|
-
|
|
40792
|
+
import_node_fs25.default.mkdirSync(import_node_path26.default.dirname(file), { recursive: true });
|
|
40793
|
+
import_node_fs25.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
41363
40794
|
try {
|
|
41364
|
-
|
|
40795
|
+
import_node_fs25.default.chmodSync(file, 384);
|
|
41365
40796
|
} catch {
|
|
41366
40797
|
}
|
|
41367
40798
|
}
|
|
41368
40799
|
|
|
41369
40800
|
// src/owner-profile.ts
|
|
41370
|
-
var
|
|
40801
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
41371
40802
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
41372
|
-
var
|
|
40803
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
41373
40804
|
var PROFILE_FILENAME = "profile.json";
|
|
41374
40805
|
function loadOwnerDisplayName(dataDir) {
|
|
41375
40806
|
const fallback = import_node_os13.default.userInfo().username;
|
|
41376
|
-
const profilePath =
|
|
40807
|
+
const profilePath = import_node_path27.default.join(dataDir, PROFILE_FILENAME);
|
|
41377
40808
|
let raw;
|
|
41378
40809
|
try {
|
|
41379
|
-
raw =
|
|
40810
|
+
raw = import_node_fs26.default.readFileSync(profilePath, "utf8");
|
|
41380
40811
|
} catch {
|
|
41381
40812
|
return fallback;
|
|
41382
40813
|
}
|
|
@@ -41399,18 +40830,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
41399
40830
|
}
|
|
41400
40831
|
|
|
41401
40832
|
// src/feishu-auth/owner-identity-store.ts
|
|
41402
|
-
var
|
|
41403
|
-
var
|
|
40833
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
40834
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
41404
40835
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
41405
40836
|
var OwnerIdentityStore = class {
|
|
41406
40837
|
file;
|
|
41407
40838
|
constructor(dataDir) {
|
|
41408
|
-
this.file =
|
|
40839
|
+
this.file = import_node_path28.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
41409
40840
|
}
|
|
41410
40841
|
read() {
|
|
41411
40842
|
let raw;
|
|
41412
40843
|
try {
|
|
41413
|
-
raw =
|
|
40844
|
+
raw = import_node_fs27.default.readFileSync(this.file, "utf8");
|
|
41414
40845
|
} catch {
|
|
41415
40846
|
return null;
|
|
41416
40847
|
}
|
|
@@ -41429,7 +40860,8 @@ var OwnerIdentityStore = class {
|
|
|
41429
40860
|
ownerId: r.identity.ownerId,
|
|
41430
40861
|
provider: r.identity.provider,
|
|
41431
40862
|
displayName: r.identity.displayName,
|
|
41432
|
-
...typeof r.identity.avatarUrl === "string" ? { avatarUrl: r.identity.avatarUrl } : {}
|
|
40863
|
+
...typeof r.identity.avatarUrl === "string" ? { avatarUrl: r.identity.avatarUrl } : {},
|
|
40864
|
+
...typeof r.identity.unionId === "string" ? { unionId: r.identity.unionId } : {}
|
|
41433
40865
|
},
|
|
41434
40866
|
ttcToken: r.ttcToken,
|
|
41435
40867
|
ttcTokenExpiresAt: typeof r.ttcTokenExpiresAt === "number" ? r.ttcTokenExpiresAt : null,
|
|
@@ -41437,16 +40869,16 @@ var OwnerIdentityStore = class {
|
|
|
41437
40869
|
};
|
|
41438
40870
|
}
|
|
41439
40871
|
write(record) {
|
|
41440
|
-
|
|
41441
|
-
|
|
40872
|
+
import_node_fs27.default.mkdirSync(import_node_path28.default.dirname(this.file), { recursive: true });
|
|
40873
|
+
import_node_fs27.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
41442
40874
|
try {
|
|
41443
|
-
|
|
40875
|
+
import_node_fs27.default.chmodSync(this.file, 384);
|
|
41444
40876
|
} catch {
|
|
41445
40877
|
}
|
|
41446
40878
|
}
|
|
41447
40879
|
clear() {
|
|
41448
40880
|
try {
|
|
41449
|
-
|
|
40881
|
+
import_node_fs27.default.unlinkSync(this.file);
|
|
41450
40882
|
} catch (err) {
|
|
41451
40883
|
const code = err?.code;
|
|
41452
40884
|
if (code !== "ENOENT") throw err;
|
|
@@ -41550,7 +40982,9 @@ async function fetchTtcUserInfo(opts) {
|
|
|
41550
40982
|
ownerId: d.unique_id,
|
|
41551
40983
|
provider: "ttc",
|
|
41552
40984
|
displayName: d.name,
|
|
41553
|
-
...typeof d.avatar_url === "string" && d.avatar_url.length > 0 ? { avatarUrl: d.avatar_url } : {}
|
|
40985
|
+
...typeof d.avatar_url === "string" && d.avatar_url.length > 0 ? { avatarUrl: d.avatar_url } : {},
|
|
40986
|
+
// union_id 捕获:dataclaw 可信入口用 X-User-UnionId(ownerId 仍是 unique_id,跨登录方式稳定)
|
|
40987
|
+
...typeof d.union_id === "string" && d.union_id.length > 0 ? { unionId: d.union_id } : {}
|
|
41554
40988
|
};
|
|
41555
40989
|
}
|
|
41556
40990
|
|
|
@@ -41565,9 +40999,9 @@ var CentralClientError = class extends Error {
|
|
|
41565
40999
|
code;
|
|
41566
41000
|
cause;
|
|
41567
41001
|
};
|
|
41568
|
-
async function centralRequest(opts,
|
|
41002
|
+
async function centralRequest(opts, path58, init) {
|
|
41569
41003
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
41570
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
41004
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path58}`;
|
|
41571
41005
|
const ctrl = new AbortController();
|
|
41572
41006
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
41573
41007
|
let res;
|
|
@@ -41709,8 +41143,8 @@ function verifyConnectToken(args) {
|
|
|
41709
41143
|
}
|
|
41710
41144
|
|
|
41711
41145
|
// src/feishu-auth/server-key.ts
|
|
41712
|
-
var
|
|
41713
|
-
var
|
|
41146
|
+
var fs36 = __toESM(require("fs"), 1);
|
|
41147
|
+
var path37 = __toESM(require("path"), 1);
|
|
41714
41148
|
var FILE_NAME2 = "server-signing-key.json";
|
|
41715
41149
|
var ServerKeyStore = class {
|
|
41716
41150
|
constructor(dataDir) {
|
|
@@ -41718,12 +41152,12 @@ var ServerKeyStore = class {
|
|
|
41718
41152
|
}
|
|
41719
41153
|
dataDir;
|
|
41720
41154
|
filePath() {
|
|
41721
|
-
return
|
|
41155
|
+
return path37.join(this.dataDir, FILE_NAME2);
|
|
41722
41156
|
}
|
|
41723
41157
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
41724
41158
|
read() {
|
|
41725
41159
|
try {
|
|
41726
|
-
const raw =
|
|
41160
|
+
const raw = fs36.readFileSync(this.filePath(), "utf8");
|
|
41727
41161
|
const parsed = JSON.parse(raw);
|
|
41728
41162
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
41729
41163
|
return parsed.publicKeyPem;
|
|
@@ -41738,12 +41172,12 @@ var ServerKeyStore = class {
|
|
|
41738
41172
|
publicKeyPem,
|
|
41739
41173
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41740
41174
|
};
|
|
41741
|
-
|
|
41742
|
-
|
|
41175
|
+
fs36.mkdirSync(this.dataDir, { recursive: true });
|
|
41176
|
+
fs36.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
41743
41177
|
}
|
|
41744
41178
|
clear() {
|
|
41745
41179
|
try {
|
|
41746
|
-
|
|
41180
|
+
fs36.unlinkSync(this.filePath());
|
|
41747
41181
|
} catch {
|
|
41748
41182
|
}
|
|
41749
41183
|
}
|
|
@@ -41756,12 +41190,12 @@ init_protocol();
|
|
|
41756
41190
|
init_protocol();
|
|
41757
41191
|
|
|
41758
41192
|
// src/session/fork.ts
|
|
41759
|
-
var
|
|
41193
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41760
41194
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
41761
|
-
var
|
|
41195
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
41762
41196
|
init_claude_history();
|
|
41763
41197
|
function readJsonlEntries(file) {
|
|
41764
|
-
const raw =
|
|
41198
|
+
const raw = import_node_fs28.default.readFileSync(file, "utf8");
|
|
41765
41199
|
const out = [];
|
|
41766
41200
|
for (const line of raw.split("\n")) {
|
|
41767
41201
|
const t = line.trim();
|
|
@@ -41774,10 +41208,10 @@ function readJsonlEntries(file) {
|
|
|
41774
41208
|
return out;
|
|
41775
41209
|
}
|
|
41776
41210
|
function forkSession(input) {
|
|
41777
|
-
const baseDir = input.baseDir ??
|
|
41778
|
-
const projectDir =
|
|
41779
|
-
const sourceFile =
|
|
41780
|
-
if (!
|
|
41211
|
+
const baseDir = input.baseDir ?? import_node_path29.default.join(import_node_os14.default.homedir(), ".claude");
|
|
41212
|
+
const projectDir = import_node_path29.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
41213
|
+
const sourceFile = import_node_path29.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
41214
|
+
if (!import_node_fs28.default.existsSync(sourceFile)) {
|
|
41781
41215
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
41782
41216
|
}
|
|
41783
41217
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -41807,9 +41241,9 @@ function forkSession(input) {
|
|
|
41807
41241
|
}
|
|
41808
41242
|
forkedLines.push(JSON.stringify(forked));
|
|
41809
41243
|
}
|
|
41810
|
-
const forkedFilePath =
|
|
41811
|
-
|
|
41812
|
-
|
|
41244
|
+
const forkedFilePath = import_node_path29.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
41245
|
+
import_node_fs28.default.mkdirSync(projectDir, { recursive: true });
|
|
41246
|
+
import_node_fs28.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
41813
41247
|
return { forkedToolSessionId, forkedFilePath };
|
|
41814
41248
|
}
|
|
41815
41249
|
|
|
@@ -42185,7 +41619,7 @@ function buildPermissionHandlers(deps) {
|
|
|
42185
41619
|
}
|
|
42186
41620
|
|
|
42187
41621
|
// src/handlers/history.ts
|
|
42188
|
-
var
|
|
41622
|
+
var path40 = __toESM(require("path"), 1);
|
|
42189
41623
|
init_protocol();
|
|
42190
41624
|
|
|
42191
41625
|
// src/session/recent-dirs.ts
|
|
@@ -42203,7 +41637,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
42203
41637
|
}
|
|
42204
41638
|
|
|
42205
41639
|
// src/permission/persona-paths.ts
|
|
42206
|
-
var
|
|
41640
|
+
var path39 = __toESM(require("path"), 1);
|
|
42207
41641
|
function getAllowedPersonaIds(grants, action) {
|
|
42208
41642
|
const ids = /* @__PURE__ */ new Set();
|
|
42209
41643
|
for (const g2 of grants) {
|
|
@@ -42216,31 +41650,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
42216
41650
|
return ids;
|
|
42217
41651
|
}
|
|
42218
41652
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
42219
|
-
const target =
|
|
41653
|
+
const target = path39.resolve(absPath);
|
|
42220
41654
|
if (userWorkDir) {
|
|
42221
|
-
const u =
|
|
42222
|
-
const usep = u.endsWith(
|
|
41655
|
+
const u = path39.resolve(userWorkDir);
|
|
41656
|
+
const usep = u.endsWith(path39.sep) ? "" : path39.sep;
|
|
42223
41657
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
42224
41658
|
}
|
|
42225
|
-
const root =
|
|
42226
|
-
const sep2 = root.endsWith(
|
|
41659
|
+
const root = path39.resolve(personaRoot);
|
|
41660
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
42227
41661
|
if (!target.startsWith(root + sep2)) return false;
|
|
42228
|
-
const rel =
|
|
41662
|
+
const rel = path39.relative(root, target);
|
|
42229
41663
|
if (!rel || rel.startsWith("..")) return false;
|
|
42230
|
-
const personaId = rel.split(
|
|
41664
|
+
const personaId = rel.split(path39.sep)[0];
|
|
42231
41665
|
if (!personaId) return false;
|
|
42232
41666
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
42233
41667
|
if (allowed === "*") return true;
|
|
42234
41668
|
return allowed.has(personaId);
|
|
42235
41669
|
}
|
|
42236
41670
|
function personaIdFromPath(absPath, personaRoot) {
|
|
42237
|
-
const root =
|
|
42238
|
-
const target =
|
|
42239
|
-
const sep2 = root.endsWith(
|
|
41671
|
+
const root = path39.resolve(personaRoot);
|
|
41672
|
+
const target = path39.resolve(absPath);
|
|
41673
|
+
const sep2 = root.endsWith(path39.sep) ? "" : path39.sep;
|
|
42240
41674
|
if (!target.startsWith(root + sep2)) return null;
|
|
42241
|
-
const rel =
|
|
41675
|
+
const rel = path39.relative(root, target);
|
|
42242
41676
|
if (!rel || rel.startsWith("..")) return null;
|
|
42243
|
-
const id = rel.split(
|
|
41677
|
+
const id = rel.split(path39.sep)[0];
|
|
42244
41678
|
return id || null;
|
|
42245
41679
|
}
|
|
42246
41680
|
|
|
@@ -42267,7 +41701,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42267
41701
|
if (!pid) return false;
|
|
42268
41702
|
return isGuestPathAllowed(
|
|
42269
41703
|
ctx.grants,
|
|
42270
|
-
|
|
41704
|
+
path40.join(personaRoot, pid),
|
|
42271
41705
|
personaRoot,
|
|
42272
41706
|
"read",
|
|
42273
41707
|
userWorkDir
|
|
@@ -42279,7 +41713,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42279
41713
|
};
|
|
42280
41714
|
const list = async (frame, _client, ctx) => {
|
|
42281
41715
|
const args = HistoryListArgs.parse(frame);
|
|
42282
|
-
assertGuestPath(ctx,
|
|
41716
|
+
assertGuestPath(ctx, path40.resolve(args.projectPath), personaRoot, "history:list");
|
|
42283
41717
|
const sessions = await history.listSessions(args);
|
|
42284
41718
|
return { response: { type: "history:list", sessions } };
|
|
42285
41719
|
};
|
|
@@ -42311,13 +41745,13 @@ function buildHistoryHandlers(deps) {
|
|
|
42311
41745
|
};
|
|
42312
41746
|
const subagents = async (frame, _client, ctx) => {
|
|
42313
41747
|
const args = HistorySubagentsArgs.parse(frame);
|
|
42314
|
-
assertGuestPath(ctx,
|
|
41748
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
42315
41749
|
const subs = await history.listSubagents(args);
|
|
42316
41750
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
42317
41751
|
};
|
|
42318
41752
|
const subagentRead = async (frame, _client, ctx) => {
|
|
42319
41753
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
42320
|
-
assertGuestPath(ctx,
|
|
41754
|
+
assertGuestPath(ctx, path40.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
42321
41755
|
const res = await history.readSubagent(args);
|
|
42322
41756
|
return { response: { type: "history:subagent-read", ...res } };
|
|
42323
41757
|
};
|
|
@@ -42326,7 +41760,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42326
41760
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
42327
41761
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42328
41762
|
const filtered = dirs.filter(
|
|
42329
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
41763
|
+
(d) => isGuestPathAllowed(ctx.grants, path40.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
42330
41764
|
);
|
|
42331
41765
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
42332
41766
|
}
|
|
@@ -42343,7 +41777,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42343
41777
|
}
|
|
42344
41778
|
|
|
42345
41779
|
// src/handlers/workspace.ts
|
|
42346
|
-
var
|
|
41780
|
+
var path41 = __toESM(require("path"), 1);
|
|
42347
41781
|
var os15 = __toESM(require("os"), 1);
|
|
42348
41782
|
init_protocol();
|
|
42349
41783
|
init_protocol();
|
|
@@ -42385,22 +41819,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42385
41819
|
const args = WorkspaceListArgs.parse(frame);
|
|
42386
41820
|
const isGuest = ctx?.principal.kind === "guest";
|
|
42387
41821
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
42388
|
-
const resolvedCwd =
|
|
42389
|
-
const target = args.path ?
|
|
41822
|
+
const resolvedCwd = path41.resolve(args.cwd ?? fallbackCwd);
|
|
41823
|
+
const target = args.path ? path41.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
42390
41824
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
42391
41825
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
42392
41826
|
return { response: { type: "workspace:list", ...res } };
|
|
42393
41827
|
};
|
|
42394
41828
|
const read = async (frame, _client, ctx) => {
|
|
42395
41829
|
const args = WorkspaceReadArgs.parse(frame);
|
|
42396
|
-
const target =
|
|
41830
|
+
const target = path41.isAbsolute(args.path) ? path41.resolve(args.path) : path41.resolve(args.cwd, args.path);
|
|
42397
41831
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
42398
41832
|
const res = workspace.read(args);
|
|
42399
41833
|
return { response: { type: "workspace:read", ...res } };
|
|
42400
41834
|
};
|
|
42401
41835
|
const skillsList = async (frame, _client, ctx) => {
|
|
42402
41836
|
const args = SkillsListArgs.parse(frame);
|
|
42403
|
-
const cwdAbs =
|
|
41837
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
42404
41838
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
42405
41839
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
42406
41840
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -42412,7 +41846,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42412
41846
|
};
|
|
42413
41847
|
const agentsList = async (frame, _client, ctx) => {
|
|
42414
41848
|
const args = AgentsListArgs.parse(frame);
|
|
42415
|
-
const cwdAbs =
|
|
41849
|
+
const cwdAbs = path41.resolve(args.cwd);
|
|
42416
41850
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
42417
41851
|
if (args.tool === "codex") {
|
|
42418
41852
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -42434,20 +41868,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42434
41868
|
}
|
|
42435
41869
|
|
|
42436
41870
|
// src/handlers/git.ts
|
|
42437
|
-
var
|
|
41871
|
+
var path43 = __toESM(require("path"), 1);
|
|
42438
41872
|
init_protocol();
|
|
42439
41873
|
init_protocol();
|
|
42440
41874
|
|
|
42441
41875
|
// src/workspace/git.ts
|
|
42442
41876
|
var import_node_child_process10 = require("child_process");
|
|
42443
|
-
var
|
|
42444
|
-
var
|
|
41877
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41878
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
42445
41879
|
var import_node_util = require("util");
|
|
42446
41880
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
42447
41881
|
function normalizePath(p2) {
|
|
42448
|
-
const resolved =
|
|
41882
|
+
const resolved = import_node_path30.default.resolve(p2);
|
|
42449
41883
|
try {
|
|
42450
|
-
return
|
|
41884
|
+
return import_node_fs29.default.realpathSync(resolved);
|
|
42451
41885
|
} catch {
|
|
42452
41886
|
return resolved;
|
|
42453
41887
|
}
|
|
@@ -42521,7 +41955,7 @@ async function listGitBranches(cwd) {
|
|
|
42521
41955
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
42522
41956
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
42523
41957
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42524
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
41958
|
+
if (!isGuestPathAllowed(ctx.grants, path43.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
42525
41959
|
throw new ClawdError(
|
|
42526
41960
|
ERROR_CODES.UNAUTHORIZED,
|
|
42527
41961
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -42937,7 +42371,6 @@ function buildReadyFrame(deps, client) {
|
|
|
42937
42371
|
if (deps.httpToken) fileSharing.httpToken = deps.httpToken;
|
|
42938
42372
|
}
|
|
42939
42373
|
const daemonSource = process.env.CLAWD_DAEMON_SOURCE === "ota" ? "ota" : "packaged";
|
|
42940
|
-
const logShipping = deps.getLogShipping ? deps.getLogShipping() : null;
|
|
42941
42374
|
return {
|
|
42942
42375
|
version,
|
|
42943
42376
|
protocolVersion: PROTOCOL_VERSION,
|
|
@@ -42948,8 +42381,7 @@ function buildReadyFrame(deps, client) {
|
|
|
42948
42381
|
tunnelUrl,
|
|
42949
42382
|
mode: deps.mode,
|
|
42950
42383
|
daemonSource,
|
|
42951
|
-
...fileSharing
|
|
42952
|
-
...logShipping ? { logShipping } : {}
|
|
42384
|
+
...fileSharing
|
|
42953
42385
|
};
|
|
42954
42386
|
}
|
|
42955
42387
|
function buildMetaHandlers(deps) {
|
|
@@ -43037,7 +42469,7 @@ function buildPersonaHandlers(deps) {
|
|
|
43037
42469
|
}
|
|
43038
42470
|
|
|
43039
42471
|
// src/handlers/attachment.ts
|
|
43040
|
-
var
|
|
42472
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
43041
42473
|
init_protocol();
|
|
43042
42474
|
init_protocol();
|
|
43043
42475
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -43092,12 +42524,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
43092
42524
|
`session ${args.sessionId} scope unresolved`
|
|
43093
42525
|
);
|
|
43094
42526
|
}
|
|
43095
|
-
const cwdAbs =
|
|
43096
|
-
const candidateAbs =
|
|
42527
|
+
const cwdAbs = import_node_path31.default.resolve(sessionFile.cwd);
|
|
42528
|
+
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
42529
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
43098
42530
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
43099
42531
|
const entry = entries.find((e) => {
|
|
43100
|
-
const storedAbs =
|
|
42532
|
+
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
42533
|
return storedAbs === candidateAbs && !e.stale;
|
|
43102
42534
|
});
|
|
43103
42535
|
if (!entry) {
|
|
@@ -43121,7 +42553,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
43121
42553
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
43122
42554
|
const f = deps.sessionStore.read(sessionId);
|
|
43123
42555
|
if (!f) return;
|
|
43124
|
-
assertGuestAttachmentPath(ctx,
|
|
42556
|
+
assertGuestAttachmentPath(ctx, import_node_path31.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
43125
42557
|
}
|
|
43126
42558
|
const groupAdd = async (frame, _client, ctx) => {
|
|
43127
42559
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -43193,19 +42625,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
43193
42625
|
|
|
43194
42626
|
// src/handlers/extension.ts
|
|
43195
42627
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
43196
|
-
var
|
|
42628
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
43197
42629
|
init_protocol();
|
|
43198
42630
|
|
|
43199
42631
|
// src/extension/bundle-zip.ts
|
|
43200
42632
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
43201
|
-
var
|
|
42633
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
43202
42634
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
43203
42635
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
43204
42636
|
async function bundleExtensionDir(dir) {
|
|
43205
42637
|
const entries = await listFilesSorted(dir);
|
|
43206
42638
|
const zip = new import_jszip2.default();
|
|
43207
42639
|
for (const rel of entries) {
|
|
43208
|
-
const abs =
|
|
42640
|
+
const abs = import_node_path32.default.join(dir, rel);
|
|
43209
42641
|
const content = await import_promises4.default.readFile(abs);
|
|
43210
42642
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
43211
42643
|
}
|
|
@@ -43226,7 +42658,7 @@ async function listFilesSorted(rootDir) {
|
|
|
43226
42658
|
return out;
|
|
43227
42659
|
}
|
|
43228
42660
|
async function walk(absRoot, relPrefix, out) {
|
|
43229
|
-
const dirAbs =
|
|
42661
|
+
const dirAbs = import_node_path32.default.join(absRoot, relPrefix);
|
|
43230
42662
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
43231
42663
|
for (const e of entries) {
|
|
43232
42664
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -43280,25 +42712,25 @@ function computePublishCheck(args) {
|
|
|
43280
42712
|
|
|
43281
42713
|
// src/extension/install-flow.ts
|
|
43282
42714
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
43283
|
-
var
|
|
42715
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
43284
42716
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
43285
42717
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
43286
42718
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
43287
42719
|
|
|
43288
42720
|
// src/extension/paths.ts
|
|
43289
42721
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
43290
|
-
var
|
|
42722
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
43291
42723
|
function clawdHomeRoot(override) {
|
|
43292
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
42724
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path33.default.join(import_node_os16.default.homedir(), ".clawd");
|
|
43293
42725
|
}
|
|
43294
42726
|
function extensionsRoot(override) {
|
|
43295
|
-
return
|
|
42727
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions");
|
|
43296
42728
|
}
|
|
43297
42729
|
function publishedChannelsFile(override) {
|
|
43298
|
-
return
|
|
42730
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
43299
42731
|
}
|
|
43300
42732
|
function bundleCacheRoot(override) {
|
|
43301
|
-
return
|
|
42733
|
+
return import_node_path33.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
43302
42734
|
}
|
|
43303
42735
|
|
|
43304
42736
|
// src/extension/install-flow.ts
|
|
@@ -43325,7 +42757,7 @@ async function installFromChannel(args, deps) {
|
|
|
43325
42757
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43326
42758
|
}
|
|
43327
42759
|
for (const name of Object.keys(zip.files)) {
|
|
43328
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42760
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path34.default.isAbsolute(name)) {
|
|
43329
42761
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43330
42762
|
}
|
|
43331
42763
|
}
|
|
@@ -43357,7 +42789,7 @@ async function installFromChannel(args, deps) {
|
|
|
43357
42789
|
);
|
|
43358
42790
|
}
|
|
43359
42791
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
43360
|
-
const destDir =
|
|
42792
|
+
const destDir = import_node_path34.default.join(deps.extensionsRoot, localExtId);
|
|
43361
42793
|
let destExists = false;
|
|
43362
42794
|
try {
|
|
43363
42795
|
await import_promises5.default.access(destDir);
|
|
@@ -43371,16 +42803,16 @@ async function installFromChannel(args, deps) {
|
|
|
43371
42803
|
);
|
|
43372
42804
|
}
|
|
43373
42805
|
const stage = await import_promises5.default.mkdtemp(
|
|
43374
|
-
|
|
42806
|
+
import_node_path34.default.join(import_node_os17.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
43375
42807
|
);
|
|
43376
42808
|
try {
|
|
43377
42809
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43378
|
-
const dest =
|
|
42810
|
+
const dest = import_node_path34.default.join(stage, name);
|
|
43379
42811
|
if (entry.dir) {
|
|
43380
42812
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
43381
42813
|
continue;
|
|
43382
42814
|
}
|
|
43383
|
-
await import_promises5.default.mkdir(
|
|
42815
|
+
await import_promises5.default.mkdir(import_node_path34.default.dirname(dest), { recursive: true });
|
|
43384
42816
|
if (name === "manifest.json") {
|
|
43385
42817
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43386
42818
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43401,7 +42833,7 @@ async function installFromChannel(args, deps) {
|
|
|
43401
42833
|
|
|
43402
42834
|
// src/extension/update-flow.ts
|
|
43403
42835
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
43404
|
-
var
|
|
42836
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
43405
42837
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
43406
42838
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
43407
42839
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -43418,11 +42850,11 @@ async function updateFromChannel(args, deps) {
|
|
|
43418
42850
|
channelRef.extId,
|
|
43419
42851
|
channelRef.ownerPrincipalId
|
|
43420
42852
|
);
|
|
43421
|
-
const liveDir =
|
|
42853
|
+
const liveDir = import_node_path35.default.join(deps.extensionsRoot, localExtId);
|
|
43422
42854
|
const prevDir = `${liveDir}.prev`;
|
|
43423
42855
|
let existingVersion;
|
|
43424
42856
|
try {
|
|
43425
|
-
const raw = await import_promises6.default.readFile(
|
|
42857
|
+
const raw = await import_promises6.default.readFile(import_node_path35.default.join(liveDir, "manifest.json"), "utf8");
|
|
43426
42858
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
43427
42859
|
if (!parsed2.success) {
|
|
43428
42860
|
throw new UpdateError(
|
|
@@ -43455,7 +42887,7 @@ async function updateFromChannel(args, deps) {
|
|
|
43455
42887
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43456
42888
|
}
|
|
43457
42889
|
for (const name of Object.keys(zip.files)) {
|
|
43458
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
42890
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
|
|
43459
42891
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43460
42892
|
}
|
|
43461
42893
|
}
|
|
@@ -43490,16 +42922,16 @@ async function updateFromChannel(args, deps) {
|
|
|
43490
42922
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
43491
42923
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
43492
42924
|
const stage = await import_promises6.default.mkdtemp(
|
|
43493
|
-
|
|
42925
|
+
import_node_path35.default.join(import_node_os18.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
43494
42926
|
);
|
|
43495
42927
|
try {
|
|
43496
42928
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43497
|
-
const dest =
|
|
42929
|
+
const dest = import_node_path35.default.join(stage, name);
|
|
43498
42930
|
if (entry.dir) {
|
|
43499
42931
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
43500
42932
|
continue;
|
|
43501
42933
|
}
|
|
43502
|
-
await import_promises6.default.mkdir(
|
|
42934
|
+
await import_promises6.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
|
|
43503
42935
|
if (name === "manifest.json") {
|
|
43504
42936
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43505
42937
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43592,7 +43024,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43592
43024
|
);
|
|
43593
43025
|
}
|
|
43594
43026
|
}
|
|
43595
|
-
const manifestPath =
|
|
43027
|
+
const manifestPath = import_node_path36.default.join(root, extId, "manifest.json");
|
|
43596
43028
|
const manifest = await readManifest(root, extId);
|
|
43597
43029
|
const next = { ...manifest, version: newVersion };
|
|
43598
43030
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -43600,7 +43032,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43600
43032
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
43601
43033
|
}
|
|
43602
43034
|
async function readManifest(root, extId) {
|
|
43603
|
-
const file =
|
|
43035
|
+
const file = import_node_path36.default.join(root, extId, "manifest.json");
|
|
43604
43036
|
let raw;
|
|
43605
43037
|
try {
|
|
43606
43038
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -43691,7 +43123,7 @@ function buildExtensionHandlers(deps) {
|
|
|
43691
43123
|
};
|
|
43692
43124
|
async function buildSnapshotMeta(extId) {
|
|
43693
43125
|
const manifest = await readManifest(deps.root, extId);
|
|
43694
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
43126
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path36.default.join(deps.root, extId));
|
|
43695
43127
|
return { manifest, contentHash: sha256, buffer };
|
|
43696
43128
|
}
|
|
43697
43129
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -43871,8 +43303,218 @@ function buildExtensionHandlers(deps) {
|
|
|
43871
43303
|
};
|
|
43872
43304
|
}
|
|
43873
43305
|
|
|
43874
|
-
// src/app-builder/
|
|
43306
|
+
// src/app-builder/project-store.ts
|
|
43307
|
+
var import_node_fs30 = require("fs");
|
|
43875
43308
|
var import_node_child_process11 = require("child_process");
|
|
43309
|
+
var import_node_path37 = require("path");
|
|
43310
|
+
init_protocol();
|
|
43311
|
+
var PROJECTS_DIR = "projects";
|
|
43312
|
+
var META_FILE = ".clawd-project.json";
|
|
43313
|
+
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
43314
|
+
var SCAFFOLD_TIMEOUT_MS = 3e4;
|
|
43315
|
+
var ProjectStore = class {
|
|
43316
|
+
/** @param root projects 父目录,例如 `~/.clawd/users/<userId>/`(v2 per-user) */
|
|
43317
|
+
constructor(root) {
|
|
43318
|
+
this.root = root;
|
|
43319
|
+
}
|
|
43320
|
+
root;
|
|
43321
|
+
/** projects/<name>/.clawd-project.json 路径 */
|
|
43322
|
+
metaPath(name) {
|
|
43323
|
+
return (0, import_node_path37.join)(this.projectsRoot(), name, META_FILE);
|
|
43324
|
+
}
|
|
43325
|
+
/** projects/<name>/ 目录路径(cwd 用) */
|
|
43326
|
+
projectDir(name) {
|
|
43327
|
+
return (0, import_node_path37.join)(this.projectsRoot(), name);
|
|
43328
|
+
}
|
|
43329
|
+
projectsRoot() {
|
|
43330
|
+
return (0, import_node_path37.join)(this.root, PROJECTS_DIR);
|
|
43331
|
+
}
|
|
43332
|
+
async list() {
|
|
43333
|
+
let entries;
|
|
43334
|
+
try {
|
|
43335
|
+
entries = await import_node_fs30.promises.readdir(this.projectsRoot());
|
|
43336
|
+
} catch (err) {
|
|
43337
|
+
if (err.code === "ENOENT") return [];
|
|
43338
|
+
throw err;
|
|
43339
|
+
}
|
|
43340
|
+
const out = [];
|
|
43341
|
+
for (const name of entries) {
|
|
43342
|
+
try {
|
|
43343
|
+
const raw = await import_node_fs30.promises.readFile(this.metaPath(name), "utf8");
|
|
43344
|
+
const json = JSON.parse(raw);
|
|
43345
|
+
let migrated = false;
|
|
43346
|
+
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
43347
|
+
json.devCommand = DEFAULT_DEV_COMMAND;
|
|
43348
|
+
migrated = true;
|
|
43349
|
+
}
|
|
43350
|
+
const parsed = ProjectMetadataSchema.safeParse(json);
|
|
43351
|
+
if (parsed.success) {
|
|
43352
|
+
out.push(parsed.data);
|
|
43353
|
+
if (migrated) {
|
|
43354
|
+
void import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
43355
|
+
});
|
|
43356
|
+
}
|
|
43357
|
+
}
|
|
43358
|
+
} catch {
|
|
43359
|
+
}
|
|
43360
|
+
}
|
|
43361
|
+
return out.sort((a, b2) => a.name.localeCompare(b2.name));
|
|
43362
|
+
}
|
|
43363
|
+
/**
|
|
43364
|
+
* @param reservedPorts 其它 user 已占端口(v2 per-user:端口必须全局唯一,所有 user 的
|
|
43365
|
+
* dev server 同机跑;per-user store 各自只 list 自己,靠 handler 收集全局端口传进来,
|
|
43366
|
+
* 否则不同 user 的首个项目都从 PROJECT_PORT_MIN 起 → 全撞 6173)。
|
|
43367
|
+
*/
|
|
43368
|
+
async create(name, reservedPorts) {
|
|
43369
|
+
const existing = await this.list();
|
|
43370
|
+
if (existing.some((p2) => p2.name === name)) {
|
|
43371
|
+
throw new Error(`project "${name}" already exists / \u5DF2\u5B58\u5728`);
|
|
43372
|
+
}
|
|
43373
|
+
const usedPorts = new Set(existing.map((p2) => p2.port));
|
|
43374
|
+
if (reservedPorts) for (const p2 of reservedPorts) usedPorts.add(p2);
|
|
43375
|
+
let port = -1;
|
|
43376
|
+
for (let p2 = PROJECT_PORT_MIN; p2 <= PROJECT_PORT_MAX; p2++) {
|
|
43377
|
+
if (!usedPorts.has(p2)) {
|
|
43378
|
+
port = p2;
|
|
43379
|
+
break;
|
|
43380
|
+
}
|
|
43381
|
+
}
|
|
43382
|
+
if (port < 0) {
|
|
43383
|
+
throw new Error(
|
|
43384
|
+
`port pool exhausted / \u7AEF\u53E3\u6C60\u5DF2\u6EE1\uFF08${PROJECT_PORT_MIN}-${PROJECT_PORT_MAX}\uFF09\uFF0C\u5148\u5220\u4E00\u4E2A project \u91CA\u653E\u7AEF\u53E3`
|
|
43385
|
+
);
|
|
43386
|
+
}
|
|
43387
|
+
const meta = {
|
|
43388
|
+
name,
|
|
43389
|
+
port,
|
|
43390
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43391
|
+
devCommand: DEFAULT_DEV_COMMAND
|
|
43392
|
+
};
|
|
43393
|
+
const validated = ProjectMetadataSchema.safeParse(meta);
|
|
43394
|
+
if (!validated.success) {
|
|
43395
|
+
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
43396
|
+
}
|
|
43397
|
+
const dir = this.projectDir(name);
|
|
43398
|
+
await import_node_fs30.promises.mkdir(dir, { recursive: true });
|
|
43399
|
+
await import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
43400
|
+
return meta;
|
|
43401
|
+
}
|
|
43402
|
+
/**
|
|
43403
|
+
* 同步内联 scaffold:spawn `extension-kit/scripts/new-extension.sh <name>` 等 exit。
|
|
43404
|
+
* 必须在 `create()` 之后调(脚本期望 projects/<name>/.clawd-project.json 已就位 = picker 模式)。
|
|
43405
|
+
* 失败抛错;上层(handler)应当 catch 后回滚(删 dir + 不 mutate session)。
|
|
43406
|
+
*
|
|
43407
|
+
* spec 2026-06-02 §5.6.3:scaffold 对 assistant 不可见,避免 assistant 被诱导去"读 example
|
|
43408
|
+
* 代码再参考"。assistant 进 project 时目录已是完整模板,直接 pnpm install 即可。
|
|
43409
|
+
*/
|
|
43410
|
+
async scaffold(name, templateSrcDir, scaffoldScriptPath) {
|
|
43411
|
+
const destDir = this.projectDir(name);
|
|
43412
|
+
return await new Promise((resolve6, reject) => {
|
|
43413
|
+
const child = (0, import_node_child_process11.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
43414
|
+
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
43415
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
43416
|
+
});
|
|
43417
|
+
let stdout = "";
|
|
43418
|
+
let stderr = "";
|
|
43419
|
+
child.stdout.on("data", (d) => {
|
|
43420
|
+
stdout += d.toString("utf8");
|
|
43421
|
+
});
|
|
43422
|
+
child.stderr.on("data", (d) => {
|
|
43423
|
+
stderr += d.toString("utf8");
|
|
43424
|
+
});
|
|
43425
|
+
const timer = setTimeout(() => {
|
|
43426
|
+
child.kill("SIGKILL");
|
|
43427
|
+
reject(new Error(`scaffold timeout (>${SCAFFOLD_TIMEOUT_MS}ms): ${scaffoldScriptPath} ${name}`));
|
|
43428
|
+
}, SCAFFOLD_TIMEOUT_MS);
|
|
43429
|
+
child.on("error", (err) => {
|
|
43430
|
+
clearTimeout(timer);
|
|
43431
|
+
reject(new Error(`scaffold spawn failed: ${err.message}`));
|
|
43432
|
+
});
|
|
43433
|
+
child.on("exit", (code, signal) => {
|
|
43434
|
+
clearTimeout(timer);
|
|
43435
|
+
if (code === 0) resolve6({ stdout, stderr });
|
|
43436
|
+
else reject(new Error(`scaffold exit ${code ?? signal}: ${stderr.slice(0, 500)}`));
|
|
43437
|
+
});
|
|
43438
|
+
});
|
|
43439
|
+
}
|
|
43440
|
+
async delete(name) {
|
|
43441
|
+
const dir = this.projectDir(name);
|
|
43442
|
+
await import_node_fs30.promises.rm(dir, { recursive: true, force: true });
|
|
43443
|
+
}
|
|
43444
|
+
async updatePort(name, newPort) {
|
|
43445
|
+
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
43446
|
+
throw new Error(
|
|
43447
|
+
`port range invalid: must be ${PROJECT_PORT_MIN}-${PROJECT_PORT_MAX}, got ${newPort}`
|
|
43448
|
+
);
|
|
43449
|
+
}
|
|
43450
|
+
const list = await this.list();
|
|
43451
|
+
const target = list.find((p2) => p2.name === name);
|
|
43452
|
+
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
43453
|
+
const conflict = list.find((p2) => p2.name !== name && p2.port === newPort);
|
|
43454
|
+
if (conflict) {
|
|
43455
|
+
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
43456
|
+
}
|
|
43457
|
+
const updated = { ...target, port: newPort };
|
|
43458
|
+
await import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
43459
|
+
return updated;
|
|
43460
|
+
}
|
|
43461
|
+
/**
|
|
43462
|
+
* 单栏 refactor (spec 2026-06-02 §5.6.1):发布上线后写公网 URL 到 .clawd-project.json.prodUrl。
|
|
43463
|
+
* UI 通过 listProjects 读到 prodUrl 后切预览栏到线上 URL,取代旧 prod marker 机制。
|
|
43464
|
+
* 重复调用幂等(覆盖旧 URL)。url 由 ProjectMetadataSchema 校验 url() 格式。
|
|
43465
|
+
*/
|
|
43466
|
+
async setProdUrl(name, url) {
|
|
43467
|
+
const list = await this.list();
|
|
43468
|
+
const target = list.find((p2) => p2.name === name);
|
|
43469
|
+
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
43470
|
+
const updated = { ...target, prodUrl: url };
|
|
43471
|
+
const validated = ProjectMetadataSchema.safeParse(updated);
|
|
43472
|
+
if (!validated.success) {
|
|
43473
|
+
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
43474
|
+
}
|
|
43475
|
+
await import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43476
|
+
return validated.data;
|
|
43477
|
+
}
|
|
43478
|
+
/**
|
|
43479
|
+
* 发布上线脚手架化 (spec 2026-06-03-app-builder-publish-scaffold-design §5.1.4):
|
|
43480
|
+
* 写 publishJob 字段到 .clawd-project.json。仅承载 in-flight 状态 ——
|
|
43481
|
+
* - daemon 收到第一个 ::stage::build marker 时写入
|
|
43482
|
+
* - 每次 stage 切换更新 stage 字段(jobId / startedAt 不变)
|
|
43483
|
+
* - 成功 / 失败 / dismiss 时调 clearPublishJob 清掉
|
|
43484
|
+
* - 只有 daemon 崩才会留残骸
|
|
43485
|
+
* 写入时保留所有其他字段(prodUrl 等不受影响)。
|
|
43486
|
+
*/
|
|
43487
|
+
async setPublishJob(name, job) {
|
|
43488
|
+
const list = await this.list();
|
|
43489
|
+
const target = list.find((p2) => p2.name === name);
|
|
43490
|
+
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
43491
|
+
const updated = { ...target, publishJob: job };
|
|
43492
|
+
const validated = ProjectMetadataSchema.safeParse(updated);
|
|
43493
|
+
if (!validated.success) {
|
|
43494
|
+
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
43495
|
+
}
|
|
43496
|
+
await import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43497
|
+
return validated.data;
|
|
43498
|
+
}
|
|
43499
|
+
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
43500
|
+
async clearPublishJob(name) {
|
|
43501
|
+
const list = await this.list();
|
|
43502
|
+
const target = list.find((p2) => p2.name === name);
|
|
43503
|
+
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
43504
|
+
if (!target.publishJob) return target;
|
|
43505
|
+
const { publishJob: _drop, ...rest } = target;
|
|
43506
|
+
void _drop;
|
|
43507
|
+
const validated = ProjectMetadataSchema.safeParse(rest);
|
|
43508
|
+
if (!validated.success) {
|
|
43509
|
+
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
43510
|
+
}
|
|
43511
|
+
await import_node_fs30.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43512
|
+
return validated.data;
|
|
43513
|
+
}
|
|
43514
|
+
};
|
|
43515
|
+
|
|
43516
|
+
// src/app-builder/kill-port.ts
|
|
43517
|
+
var import_node_child_process12 = require("child_process");
|
|
43876
43518
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
43877
43519
|
let pids;
|
|
43878
43520
|
try {
|
|
@@ -43914,7 +43556,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
43914
43556
|
}
|
|
43915
43557
|
function listPidsOnPort(port) {
|
|
43916
43558
|
return new Promise((resolve6, reject) => {
|
|
43917
|
-
(0,
|
|
43559
|
+
(0, import_node_child_process12.execFile)(
|
|
43918
43560
|
"lsof",
|
|
43919
43561
|
["-ti", `:${port}`],
|
|
43920
43562
|
{ timeout: 3e3 },
|
|
@@ -43986,7 +43628,7 @@ var PublishJobRegistry = class {
|
|
|
43986
43628
|
};
|
|
43987
43629
|
|
|
43988
43630
|
// src/app-builder/publish-job-runner.ts
|
|
43989
|
-
var
|
|
43631
|
+
var import_node_child_process13 = require("child_process");
|
|
43990
43632
|
var import_node_fs31 = require("fs");
|
|
43991
43633
|
var import_node_path38 = require("path");
|
|
43992
43634
|
|
|
@@ -44015,7 +43657,7 @@ function tailStderrLines(buf, n) {
|
|
|
44015
43657
|
// src/app-builder/publish-job-runner.ts
|
|
44016
43658
|
async function startPublishJob(deps, args) {
|
|
44017
43659
|
const { registry: registry2, projectDir } = deps;
|
|
44018
|
-
const spawn12 = deps.spawnImpl ??
|
|
43660
|
+
const spawn12 = deps.spawnImpl ?? import_node_child_process13.spawn;
|
|
44019
43661
|
if (registry2.has(args.name)) {
|
|
44020
43662
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
44021
43663
|
}
|
|
@@ -44027,7 +43669,7 @@ async function startPublishJob(deps, args) {
|
|
|
44027
43669
|
} catch {
|
|
44028
43670
|
logStream = null;
|
|
44029
43671
|
}
|
|
44030
|
-
const child = spawn12("bash", [args.scriptPath, projDir], {
|
|
43672
|
+
const child = spawn12("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
|
|
44031
43673
|
cwd: projDir,
|
|
44032
43674
|
env: process.env,
|
|
44033
43675
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -44282,8 +43924,7 @@ async function recoverInterruptedJobs(deps) {
|
|
|
44282
43924
|
init_protocol();
|
|
44283
43925
|
var import_node_path39 = require("path");
|
|
44284
43926
|
var import_node_fs32 = require("fs");
|
|
44285
|
-
var APP_BUILDER_PERSONAS = ["persona-app-builder"];
|
|
44286
|
-
var PUBLISH_SCRIPT_REL = "extension-kit/scripts/publish.sh";
|
|
43927
|
+
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
44287
43928
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
44288
43929
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
44289
43930
|
await recoverInterruptedJobs({
|
|
@@ -44438,7 +44079,10 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44438
44079
|
const reservedPorts = new Set((await listAllUsersProjects()).map((p2) => p2.port));
|
|
44439
44080
|
const project = await userStore.create(f.name, reservedPorts);
|
|
44440
44081
|
try {
|
|
44441
|
-
const
|
|
44082
|
+
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
44083
|
+
const templateSrcDir = (0, import_node_path39.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
44084
|
+
const scaffoldScript = (0, import_node_path39.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
44085
|
+
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
44442
44086
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
44443
44087
|
name: project.name,
|
|
44444
44088
|
stdout: scaffoldResult.stdout.slice(0, 200)
|
|
@@ -44657,11 +44301,13 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44657
44301
|
});
|
|
44658
44302
|
await userStore.clearPublishJob(args.name);
|
|
44659
44303
|
}
|
|
44660
|
-
const
|
|
44304
|
+
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
44305
|
+
const scriptPath = (0, import_node_path39.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
44661
44306
|
deps.logger?.info("app-builder.publish.start", {
|
|
44662
44307
|
name: args.name,
|
|
44663
44308
|
sessionId: boundSession.sessionId,
|
|
44664
|
-
scriptPath
|
|
44309
|
+
scriptPath,
|
|
44310
|
+
personaRoot
|
|
44665
44311
|
});
|
|
44666
44312
|
const result = await startPublishJob(
|
|
44667
44313
|
{
|
|
@@ -44696,7 +44342,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44696
44342
|
{
|
|
44697
44343
|
name: args.name,
|
|
44698
44344
|
sessionId: boundSession.sessionId,
|
|
44699
|
-
scriptPath
|
|
44345
|
+
scriptPath,
|
|
44346
|
+
personaRoot
|
|
44700
44347
|
}
|
|
44701
44348
|
);
|
|
44702
44349
|
return { response: { ...result } };
|
|
@@ -44894,227 +44541,16 @@ function buildMethodHandlers(deps) {
|
|
|
44894
44541
|
broadcastProjectUpdated: deps.broadcastProjectUpdated,
|
|
44895
44542
|
logger: deps.logger,
|
|
44896
44543
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
44897
|
-
// personaRoot
|
|
44898
|
-
//
|
|
44544
|
+
// personaRoot 仅作 resolvePersonaRoot 未注入时的兜底;deployKitRoot 为共享脚本根。
|
|
44545
|
+
// broadcastSessionFrame 用于失败回灌路径(runner 调 manager.send 后逐帧 dispatch 到 transport)。
|
|
44899
44546
|
personaRoot: deps.appBuilderPersonaRoot,
|
|
44547
|
+
deployKitRoot: deps.deployKitRoot,
|
|
44548
|
+
resolvePersonaRoot: deps.resolvePersonaRoot,
|
|
44900
44549
|
broadcastSessionFrame: deps.broadcastSessionFrame
|
|
44901
44550
|
})
|
|
44902
44551
|
};
|
|
44903
44552
|
}
|
|
44904
44553
|
|
|
44905
|
-
// src/app-builder/project-store.ts
|
|
44906
|
-
var import_node_fs33 = require("fs");
|
|
44907
|
-
var import_node_child_process13 = require("child_process");
|
|
44908
|
-
var import_node_path42 = require("path");
|
|
44909
|
-
init_protocol();
|
|
44910
|
-
var PROJECTS_DIR = "projects";
|
|
44911
|
-
var META_FILE = ".clawd-project.json";
|
|
44912
|
-
var SCAFFOLD_SCRIPT_REL = "extension-kit/scripts/new-extension.sh";
|
|
44913
|
-
var DEFAULT_TEMPLATE = "nestjs-react";
|
|
44914
|
-
var SCAFFOLD_TIMEOUT_MS = 3e4;
|
|
44915
|
-
var ProjectStore = class {
|
|
44916
|
-
/** @param root projects 父目录,例如 `~/.clawd/users/<userId>/`(v2 per-user) */
|
|
44917
|
-
constructor(root) {
|
|
44918
|
-
this.root = root;
|
|
44919
|
-
}
|
|
44920
|
-
root;
|
|
44921
|
-
/** projects/<name>/.clawd-project.json 路径 */
|
|
44922
|
-
metaPath(name) {
|
|
44923
|
-
return (0, import_node_path42.join)(this.projectsRoot(), name, META_FILE);
|
|
44924
|
-
}
|
|
44925
|
-
/** projects/<name>/ 目录路径(cwd 用) */
|
|
44926
|
-
projectDir(name) {
|
|
44927
|
-
return (0, import_node_path42.join)(this.projectsRoot(), name);
|
|
44928
|
-
}
|
|
44929
|
-
projectsRoot() {
|
|
44930
|
-
return (0, import_node_path42.join)(this.root, PROJECTS_DIR);
|
|
44931
|
-
}
|
|
44932
|
-
async list() {
|
|
44933
|
-
let entries;
|
|
44934
|
-
try {
|
|
44935
|
-
entries = await import_node_fs33.promises.readdir(this.projectsRoot());
|
|
44936
|
-
} catch (err) {
|
|
44937
|
-
if (err.code === "ENOENT") return [];
|
|
44938
|
-
throw err;
|
|
44939
|
-
}
|
|
44940
|
-
const out = [];
|
|
44941
|
-
for (const name of entries) {
|
|
44942
|
-
try {
|
|
44943
|
-
const raw = await import_node_fs33.promises.readFile(this.metaPath(name), "utf8");
|
|
44944
|
-
const json = JSON.parse(raw);
|
|
44945
|
-
let migrated = false;
|
|
44946
|
-
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
44947
|
-
json.devCommand = DEFAULT_DEV_COMMAND;
|
|
44948
|
-
migrated = true;
|
|
44949
|
-
}
|
|
44950
|
-
const parsed = ProjectMetadataSchema.safeParse(json);
|
|
44951
|
-
if (parsed.success) {
|
|
44952
|
-
out.push(parsed.data);
|
|
44953
|
-
if (migrated) {
|
|
44954
|
-
void import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
44955
|
-
});
|
|
44956
|
-
}
|
|
44957
|
-
}
|
|
44958
|
-
} catch {
|
|
44959
|
-
}
|
|
44960
|
-
}
|
|
44961
|
-
return out.sort((a, b2) => a.name.localeCompare(b2.name));
|
|
44962
|
-
}
|
|
44963
|
-
/**
|
|
44964
|
-
* @param reservedPorts 其它 user 已占端口(v2 per-user:端口必须全局唯一,所有 user 的
|
|
44965
|
-
* dev server 同机跑;per-user store 各自只 list 自己,靠 handler 收集全局端口传进来,
|
|
44966
|
-
* 否则不同 user 的首个项目都从 PROJECT_PORT_MIN 起 → 全撞 6173)。
|
|
44967
|
-
*/
|
|
44968
|
-
async create(name, reservedPorts) {
|
|
44969
|
-
const existing = await this.list();
|
|
44970
|
-
if (existing.some((p2) => p2.name === name)) {
|
|
44971
|
-
throw new Error(`project "${name}" already exists / \u5DF2\u5B58\u5728`);
|
|
44972
|
-
}
|
|
44973
|
-
const usedPorts = new Set(existing.map((p2) => p2.port));
|
|
44974
|
-
if (reservedPorts) for (const p2 of reservedPorts) usedPorts.add(p2);
|
|
44975
|
-
let port = -1;
|
|
44976
|
-
for (let p2 = PROJECT_PORT_MIN; p2 <= PROJECT_PORT_MAX; p2++) {
|
|
44977
|
-
if (!usedPorts.has(p2)) {
|
|
44978
|
-
port = p2;
|
|
44979
|
-
break;
|
|
44980
|
-
}
|
|
44981
|
-
}
|
|
44982
|
-
if (port < 0) {
|
|
44983
|
-
throw new Error(
|
|
44984
|
-
`port pool exhausted / \u7AEF\u53E3\u6C60\u5DF2\u6EE1\uFF08${PROJECT_PORT_MIN}-${PROJECT_PORT_MAX}\uFF09\uFF0C\u5148\u5220\u4E00\u4E2A project \u91CA\u653E\u7AEF\u53E3`
|
|
44985
|
-
);
|
|
44986
|
-
}
|
|
44987
|
-
const meta = {
|
|
44988
|
-
name,
|
|
44989
|
-
port,
|
|
44990
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44991
|
-
devCommand: DEFAULT_DEV_COMMAND
|
|
44992
|
-
};
|
|
44993
|
-
const validated = ProjectMetadataSchema.safeParse(meta);
|
|
44994
|
-
if (!validated.success) {
|
|
44995
|
-
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
44996
|
-
}
|
|
44997
|
-
const dir = this.projectDir(name);
|
|
44998
|
-
await import_node_fs33.promises.mkdir(dir, { recursive: true });
|
|
44999
|
-
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
45000
|
-
return meta;
|
|
45001
|
-
}
|
|
45002
|
-
/**
|
|
45003
|
-
* 同步内联 scaffold:spawn `extension-kit/scripts/new-extension.sh <name>` 等 exit。
|
|
45004
|
-
* 必须在 `create()` 之后调(脚本期望 projects/<name>/.clawd-project.json 已就位 = picker 模式)。
|
|
45005
|
-
* 失败抛错;上层(handler)应当 catch 后回滚(删 dir + 不 mutate session)。
|
|
45006
|
-
*
|
|
45007
|
-
* spec 2026-06-02 §5.6.3:scaffold 对 assistant 不可见,避免 assistant 被诱导去"读 example
|
|
45008
|
-
* 代码再参考"。assistant 进 project 时目录已是完整模板,直接 pnpm install 即可。
|
|
45009
|
-
*/
|
|
45010
|
-
async scaffold(name, template = DEFAULT_TEMPLATE, personaRoot = this.root) {
|
|
45011
|
-
const scriptPath = (0, import_node_path42.join)(personaRoot, SCAFFOLD_SCRIPT_REL);
|
|
45012
|
-
const destDir = this.projectDir(name);
|
|
45013
|
-
return await new Promise((resolve6, reject) => {
|
|
45014
|
-
const child = (0, import_node_child_process13.spawn)("bash", [scriptPath, name, template, destDir], {
|
|
45015
|
-
cwd: personaRoot,
|
|
45016
|
-
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
45017
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
45018
|
-
});
|
|
45019
|
-
let stdout = "";
|
|
45020
|
-
let stderr = "";
|
|
45021
|
-
child.stdout.on("data", (d) => {
|
|
45022
|
-
stdout += d.toString("utf8");
|
|
45023
|
-
});
|
|
45024
|
-
child.stderr.on("data", (d) => {
|
|
45025
|
-
stderr += d.toString("utf8");
|
|
45026
|
-
});
|
|
45027
|
-
const timer = setTimeout(() => {
|
|
45028
|
-
child.kill("SIGKILL");
|
|
45029
|
-
reject(new Error(`scaffold timeout (>${SCAFFOLD_TIMEOUT_MS}ms): ${scriptPath} ${name} ${template}`));
|
|
45030
|
-
}, SCAFFOLD_TIMEOUT_MS);
|
|
45031
|
-
child.on("error", (err) => {
|
|
45032
|
-
clearTimeout(timer);
|
|
45033
|
-
reject(new Error(`scaffold spawn failed: ${err.message}`));
|
|
45034
|
-
});
|
|
45035
|
-
child.on("exit", (code, signal) => {
|
|
45036
|
-
clearTimeout(timer);
|
|
45037
|
-
if (code === 0) resolve6({ stdout, stderr });
|
|
45038
|
-
else reject(new Error(`scaffold exit ${code ?? signal}: ${stderr.slice(0, 500)}`));
|
|
45039
|
-
});
|
|
45040
|
-
});
|
|
45041
|
-
}
|
|
45042
|
-
async delete(name) {
|
|
45043
|
-
const dir = this.projectDir(name);
|
|
45044
|
-
await import_node_fs33.promises.rm(dir, { recursive: true, force: true });
|
|
45045
|
-
}
|
|
45046
|
-
async updatePort(name, newPort) {
|
|
45047
|
-
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
45048
|
-
throw new Error(
|
|
45049
|
-
`port range invalid: must be ${PROJECT_PORT_MIN}-${PROJECT_PORT_MAX}, got ${newPort}`
|
|
45050
|
-
);
|
|
45051
|
-
}
|
|
45052
|
-
const list = await this.list();
|
|
45053
|
-
const target = list.find((p2) => p2.name === name);
|
|
45054
|
-
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
45055
|
-
const conflict = list.find((p2) => p2.name !== name && p2.port === newPort);
|
|
45056
|
-
if (conflict) {
|
|
45057
|
-
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
45058
|
-
}
|
|
45059
|
-
const updated = { ...target, port: newPort };
|
|
45060
|
-
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
45061
|
-
return updated;
|
|
45062
|
-
}
|
|
45063
|
-
/**
|
|
45064
|
-
* 单栏 refactor (spec 2026-06-02 §5.6.1):发布上线后写公网 URL 到 .clawd-project.json.prodUrl。
|
|
45065
|
-
* UI 通过 listProjects 读到 prodUrl 后切预览栏到线上 URL,取代旧 prod marker 机制。
|
|
45066
|
-
* 重复调用幂等(覆盖旧 URL)。url 由 ProjectMetadataSchema 校验 url() 格式。
|
|
45067
|
-
*/
|
|
45068
|
-
async setProdUrl(name, url) {
|
|
45069
|
-
const list = await this.list();
|
|
45070
|
-
const target = list.find((p2) => p2.name === name);
|
|
45071
|
-
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
45072
|
-
const updated = { ...target, prodUrl: url };
|
|
45073
|
-
const validated = ProjectMetadataSchema.safeParse(updated);
|
|
45074
|
-
if (!validated.success) {
|
|
45075
|
-
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
45076
|
-
}
|
|
45077
|
-
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45078
|
-
return validated.data;
|
|
45079
|
-
}
|
|
45080
|
-
/**
|
|
45081
|
-
* 发布上线脚手架化 (spec 2026-06-03-app-builder-publish-scaffold-design §5.1.4):
|
|
45082
|
-
* 写 publishJob 字段到 .clawd-project.json。仅承载 in-flight 状态 ——
|
|
45083
|
-
* - daemon 收到第一个 ::stage::build marker 时写入
|
|
45084
|
-
* - 每次 stage 切换更新 stage 字段(jobId / startedAt 不变)
|
|
45085
|
-
* - 成功 / 失败 / dismiss 时调 clearPublishJob 清掉
|
|
45086
|
-
* - 只有 daemon 崩才会留残骸
|
|
45087
|
-
* 写入时保留所有其他字段(prodUrl 等不受影响)。
|
|
45088
|
-
*/
|
|
45089
|
-
async setPublishJob(name, job) {
|
|
45090
|
-
const list = await this.list();
|
|
45091
|
-
const target = list.find((p2) => p2.name === name);
|
|
45092
|
-
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
45093
|
-
const updated = { ...target, publishJob: job };
|
|
45094
|
-
const validated = ProjectMetadataSchema.safeParse(updated);
|
|
45095
|
-
if (!validated.success) {
|
|
45096
|
-
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
45097
|
-
}
|
|
45098
|
-
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45099
|
-
return validated.data;
|
|
45100
|
-
}
|
|
45101
|
-
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
45102
|
-
async clearPublishJob(name) {
|
|
45103
|
-
const list = await this.list();
|
|
45104
|
-
const target = list.find((p2) => p2.name === name);
|
|
45105
|
-
if (!target) throw new Error(`project "${name}" not found / \u4E0D\u5B58\u5728`);
|
|
45106
|
-
if (!target.publishJob) return target;
|
|
45107
|
-
const { publishJob: _drop, ...rest } = target;
|
|
45108
|
-
void _drop;
|
|
45109
|
-
const validated = ProjectMetadataSchema.safeParse(rest);
|
|
45110
|
-
if (!validated.success) {
|
|
45111
|
-
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
45112
|
-
}
|
|
45113
|
-
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
45114
|
-
return validated.data;
|
|
45115
|
-
}
|
|
45116
|
-
};
|
|
45117
|
-
|
|
45118
44554
|
// src/app-builder/dev-server-supervisor.ts
|
|
45119
44555
|
var import_node_child_process14 = require("child_process");
|
|
45120
44556
|
var import_node_events2 = require("events");
|
|
@@ -45546,7 +44982,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
45546
44982
|
|
|
45547
44983
|
// src/extension/runtime.ts
|
|
45548
44984
|
var import_node_child_process15 = require("child_process");
|
|
45549
|
-
var
|
|
44985
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
45550
44986
|
var import_promises10 = require("timers/promises");
|
|
45551
44987
|
|
|
45552
44988
|
// src/extension/port-allocator.ts
|
|
@@ -45647,7 +45083,7 @@ var Runtime = class {
|
|
|
45647
45083
|
/\$CLAWOS_EXT_PORT/g,
|
|
45648
45084
|
String(port)
|
|
45649
45085
|
);
|
|
45650
|
-
const dir =
|
|
45086
|
+
const dir = import_node_path42.default.join(this.root, extId);
|
|
45651
45087
|
const env = {
|
|
45652
45088
|
...process.env,
|
|
45653
45089
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -45759,7 +45195,7 @@ ${handle.stderrTail}`
|
|
|
45759
45195
|
|
|
45760
45196
|
// src/extension/published-channels.ts
|
|
45761
45197
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
45762
|
-
var
|
|
45198
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
45763
45199
|
init_zod();
|
|
45764
45200
|
var PublishedChannelsError = class extends Error {
|
|
45765
45201
|
constructor(code, message) {
|
|
@@ -45858,7 +45294,7 @@ var PublishedChannelStore = class {
|
|
|
45858
45294
|
)
|
|
45859
45295
|
};
|
|
45860
45296
|
const tmp = `${this.filePath}.tmp`;
|
|
45861
|
-
await import_promises11.default.mkdir(
|
|
45297
|
+
await import_promises11.default.mkdir(import_node_path43.default.dirname(this.filePath), { recursive: true });
|
|
45862
45298
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
45863
45299
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
45864
45300
|
}
|
|
@@ -45866,7 +45302,7 @@ var PublishedChannelStore = class {
|
|
|
45866
45302
|
|
|
45867
45303
|
// src/extension/bundle-cache.ts
|
|
45868
45304
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
45869
|
-
var
|
|
45305
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45870
45306
|
var BundleCache = class {
|
|
45871
45307
|
constructor(rootDir) {
|
|
45872
45308
|
this.rootDir = rootDir;
|
|
@@ -45875,14 +45311,14 @@ var BundleCache = class {
|
|
|
45875
45311
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
45876
45312
|
async write(snapshotHash, buffer) {
|
|
45877
45313
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
45878
|
-
const file =
|
|
45314
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45879
45315
|
const tmp = `${file}.tmp`;
|
|
45880
45316
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
45881
45317
|
await import_promises12.default.rename(tmp, file);
|
|
45882
45318
|
}
|
|
45883
45319
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
45884
45320
|
async read(snapshotHash) {
|
|
45885
|
-
const file =
|
|
45321
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45886
45322
|
try {
|
|
45887
45323
|
return await import_promises12.default.readFile(file);
|
|
45888
45324
|
} catch (e) {
|
|
@@ -45892,33 +45328,16 @@ var BundleCache = class {
|
|
|
45892
45328
|
}
|
|
45893
45329
|
/** Idempotent — missing file is not an error. */
|
|
45894
45330
|
async delete(snapshotHash) {
|
|
45895
|
-
const file =
|
|
45331
|
+
const file = import_node_path44.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45896
45332
|
await import_promises12.default.rm(file, { force: true });
|
|
45897
45333
|
}
|
|
45898
45334
|
};
|
|
45899
45335
|
|
|
45900
45336
|
// src/index.ts
|
|
45901
|
-
var import_meta4 = {};
|
|
45902
45337
|
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
45338
|
const logger = createLogger({
|
|
45919
45339
|
level: config.logLevel,
|
|
45920
|
-
file:
|
|
45921
|
-
logClient
|
|
45340
|
+
file: import_node_path45.default.join(config.dataDir, "clawd.log")
|
|
45922
45341
|
});
|
|
45923
45342
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
45924
45343
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -45929,6 +45348,7 @@ async function startDaemon(config) {
|
|
|
45929
45348
|
if (pre.status === "stale") {
|
|
45930
45349
|
logger.warn("stale state file detected, overwriting", { pid: pre.existing.pid });
|
|
45931
45350
|
}
|
|
45351
|
+
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
45932
45352
|
let resolvedAuthToken = null;
|
|
45933
45353
|
if (config.authToken && config.authToken.trim()) {
|
|
45934
45354
|
resolvedAuthToken = config.authToken.trim();
|
|
@@ -46053,8 +45473,8 @@ async function startDaemon(config) {
|
|
|
46053
45473
|
const agents = new AgentsScanner();
|
|
46054
45474
|
const history = new ClaudeHistoryReader();
|
|
46055
45475
|
let transport = null;
|
|
46056
|
-
const personaStore = new PersonaStore(
|
|
46057
|
-
const usersRoot =
|
|
45476
|
+
const personaStore = new PersonaStore(import_node_path45.default.join(config.dataDir, "personas"));
|
|
45477
|
+
const usersRoot = import_node_path45.default.join(config.dataDir, "users");
|
|
46058
45478
|
const defaultsRoot = findDefaultsRoot();
|
|
46059
45479
|
if (defaultsRoot) {
|
|
46060
45480
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -46062,36 +45482,16 @@ async function startDaemon(config) {
|
|
|
46062
45482
|
} else {
|
|
46063
45483
|
logger.warn("persona.seed.skip", { reason: "defaults-root-not-found" });
|
|
46064
45484
|
}
|
|
45485
|
+
const deployKitBundleRoot = findDeployKitRoot();
|
|
45486
|
+
if (deployKitBundleRoot) {
|
|
45487
|
+
seedDeployKit({ deployKitBundleRoot, dataDir: config.dataDir, logger });
|
|
45488
|
+
refreshDeployKit({ deployKitBundleRoot, dataDir: config.dataDir, logger });
|
|
45489
|
+
} else {
|
|
45490
|
+
logger.warn("deploy-kit.bundle-missing", {});
|
|
45491
|
+
}
|
|
46065
45492
|
migrateAgentsMirror({ store: personaStore, logger });
|
|
46066
45493
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
46067
45494
|
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
45495
|
const manager = new SessionManager({
|
|
46096
45496
|
store,
|
|
46097
45497
|
// Phase 2 (capability platform plan §1): factory 注入后 manager.storeFor 走
|
|
@@ -46101,7 +45501,7 @@ async function startDaemon(config) {
|
|
|
46101
45501
|
getAdapter,
|
|
46102
45502
|
historyReader: history,
|
|
46103
45503
|
dataDir: config.dataDir,
|
|
46104
|
-
personaRoot:
|
|
45504
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46105
45505
|
usersRoot,
|
|
46106
45506
|
personaStore,
|
|
46107
45507
|
ownerDisplayName,
|
|
@@ -46112,12 +45512,6 @@ async function startDaemon(config) {
|
|
|
46112
45512
|
// 127.0.0.1(不是 config.host)—— cc 跑在本机,loopback 最稳;外部访问限制 + http-router
|
|
46113
45513
|
// 的 isLoopback 兜底已确保安全。
|
|
46114
45514
|
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
45515
|
broadcastFrame: (frame, target) => {
|
|
46122
45516
|
if (target === "all") {
|
|
46123
45517
|
transport?.broadcastAll(frame);
|
|
@@ -46137,10 +45531,10 @@ async function startDaemon(config) {
|
|
|
46137
45531
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
46138
45532
|
attachmentGroup: {
|
|
46139
45533
|
onFileEdit: (input) => {
|
|
46140
|
-
const absPath =
|
|
45534
|
+
const absPath = import_node_path45.default.isAbsolute(input.relPath) ? input.relPath : import_node_path45.default.join(input.cwd, input.relPath);
|
|
46141
45535
|
let size = 0;
|
|
46142
45536
|
try {
|
|
46143
|
-
size =
|
|
45537
|
+
size = import_node_fs33.default.statSync(absPath).size;
|
|
46144
45538
|
} catch (err) {
|
|
46145
45539
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
46146
45540
|
sessionId: input.sessionId,
|
|
@@ -46326,11 +45720,11 @@ async function startDaemon(config) {
|
|
|
46326
45720
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
46327
45721
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
46328
45722
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
46329
|
-
personaRoot:
|
|
45723
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46330
45724
|
usersRoot
|
|
46331
45725
|
},
|
|
46332
45726
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
46333
|
-
personaRoot:
|
|
45727
|
+
personaRoot: import_node_path45.default.join(config.dataDir, "personas"),
|
|
46334
45728
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
46335
45729
|
usersRoot,
|
|
46336
45730
|
// capability:list / delete handler 依赖
|
|
@@ -46419,7 +45813,11 @@ async function startDaemon(config) {
|
|
|
46419
45813
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
46420
45814
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
46421
45815
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
46422
|
-
appBuilderPersonaRoot:
|
|
45816
|
+
appBuilderPersonaRoot: import_node_path45.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
45817
|
+
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
45818
|
+
deployKitRoot: import_node_path45.default.join(config.dataDir, "deploy-kit"),
|
|
45819
|
+
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
45820
|
+
resolvePersonaRoot: (personaId) => import_node_path45.default.join(config.dataDir, "personas", personaId),
|
|
46423
45821
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
46424
45822
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
46425
45823
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -46440,41 +45838,6 @@ async function startDaemon(config) {
|
|
|
46440
45838
|
logger
|
|
46441
45839
|
});
|
|
46442
45840
|
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
45841
|
const authResolver = new AuthContextResolver({
|
|
46479
45842
|
ownerToken: resolvedAuthToken
|
|
46480
45843
|
});
|
|
@@ -46549,10 +45912,6 @@ async function startDaemon(config) {
|
|
|
46549
45912
|
manager,
|
|
46550
45913
|
getAdapter,
|
|
46551
45914
|
getTunnelUrl: () => currentTunnelUrl,
|
|
46552
|
-
getLogShipping: () => config.logShipping ? {
|
|
46553
|
-
endpoint: config.logShipping.endpoint,
|
|
46554
|
-
sampling: config.logShipping.sampling
|
|
46555
|
-
} : null,
|
|
46556
45915
|
// ready 帧 mode = daemon CC spawn 模式('sdk' | 'tui');UI 用它挂 XtermPanel
|
|
46557
45916
|
mode: config.mode,
|
|
46558
45917
|
// file-sharing 字段:httpBaseUrl 跟 tunnel 状态走;httpToken 复用 owner WS token
|
|
@@ -46707,8 +46066,8 @@ async function startDaemon(config) {
|
|
|
46707
46066
|
const lines = [
|
|
46708
46067
|
`Tunnel: ${r.url}`,
|
|
46709
46068
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
46710
|
-
`Frpc config: ${
|
|
46711
|
-
`Frpc log: ${
|
|
46069
|
+
`Frpc config: ${import_node_path45.default.join(config.dataDir, "frpc.toml")}`,
|
|
46070
|
+
`Frpc log: ${import_node_path45.default.join(config.dataDir, "frpc.log")}`
|
|
46712
46071
|
];
|
|
46713
46072
|
const width = Math.max(...lines.map((l) => l.length));
|
|
46714
46073
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -46721,8 +46080,8 @@ ${bar}
|
|
|
46721
46080
|
|
|
46722
46081
|
`);
|
|
46723
46082
|
try {
|
|
46724
|
-
const connectPath =
|
|
46725
|
-
|
|
46083
|
+
const connectPath = import_node_path45.default.join(config.dataDir, "connect.txt");
|
|
46084
|
+
import_node_fs33.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
46726
46085
|
} catch {
|
|
46727
46086
|
}
|
|
46728
46087
|
} catch (err) {
|
|
@@ -46783,7 +46142,6 @@ ${bar}
|
|
|
46783
46142
|
}
|
|
46784
46143
|
await wss.stop();
|
|
46785
46144
|
stateMgr.delete();
|
|
46786
|
-
if (logClient) await logClient.dispose();
|
|
46787
46145
|
};
|
|
46788
46146
|
return {
|
|
46789
46147
|
stop: shutdown,
|
|
@@ -46794,9 +46152,9 @@ ${bar}
|
|
|
46794
46152
|
};
|
|
46795
46153
|
}
|
|
46796
46154
|
function migrateDropPersonsDir(dataDir) {
|
|
46797
|
-
const dir =
|
|
46155
|
+
const dir = import_node_path45.default.join(dataDir, "persons");
|
|
46798
46156
|
try {
|
|
46799
|
-
|
|
46157
|
+
import_node_fs33.default.rmSync(dir, { recursive: true, force: true });
|
|
46800
46158
|
} catch {
|
|
46801
46159
|
}
|
|
46802
46160
|
}
|