@clawos-dev/clawd 0.2.143-beta.301.814d293 → 0.2.143-beta.303.ab28945
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 +1364 -617
- package/dist/dispatch/mcp-server.cjs +39756 -0
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +3 -0
- package/dist/persona-defaults/persona-bug-fixer/CLAUDE.md +2 -0
- package/dist/persona-defaults/persona-dataclaw-builder/CLAUDE.md +29 -9
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/README.md +10 -18
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/config.env +2 -5
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/contract/s.yaml.tmpl +1 -6
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/ext.conf +3 -2
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/.env.example +5 -14
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/package.json +1 -3
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/app.module.ts +2 -2
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.client.ts +18 -8
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.config.ts +9 -12
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/dataclaw/dataclaw.controller.ts +12 -8
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/main.ts +3 -16
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/App.jsx +1 -4
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/api.js +4 -2
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/ResultTable.jsx +4 -2
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/enums.js +3 -18
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/pages/PerformanceQueryPage.jsx +35 -57
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/hooks/pre-deploy.sh +16 -20
- package/dist/persona-defaults/persona-developer/CLAUDE.md +2 -0
- package/package.json +5 -2
- package/dist/persona-defaults/persona-dataclaw-builder/.secrets/dataclaw.env.example +0 -3
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/gate.ts +0 -70
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/session.ts +0 -52
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/server/src/auth/ttc-user-info.ts +0 -23
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/auth.js +0 -7
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/FilterRow.jsx +0 -79
- package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/examples/nestjs-react/web/src/components/SchemaFilters.jsx +0 -93
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: path59, errorMaps, issueData } = params;
|
|
724
|
+
const fullPath = [...path59, ...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, path59, key) {
|
|
1036
1036
|
this._cachedPath = [];
|
|
1037
1037
|
this.parent = parent;
|
|
1038
1038
|
this.data = value;
|
|
1039
|
-
this._path =
|
|
1039
|
+
this._path = path59;
|
|
1040
1040
|
this._key = key;
|
|
1041
1041
|
}
|
|
1042
1042
|
get path() {
|
|
@@ -4752,6 +4752,13 @@ 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(),
|
|
4755
4762
|
createdAt: external_exports.string().min(1),
|
|
4756
4763
|
updatedAt: external_exports.string().min(1)
|
|
4757
4764
|
});
|
|
@@ -5928,6 +5935,60 @@ var init_feishu_auth = __esm({
|
|
|
5928
5935
|
}
|
|
5929
5936
|
});
|
|
5930
5937
|
|
|
5938
|
+
// ../protocol/src/dispatch.ts
|
|
5939
|
+
var DispatchOutcomeSchema, DispatchRunArgsSchema, DispatchCompleteArgsSchema;
|
|
5940
|
+
var init_dispatch = __esm({
|
|
5941
|
+
"../protocol/src/dispatch.ts"() {
|
|
5942
|
+
"use strict";
|
|
5943
|
+
init_zod();
|
|
5944
|
+
DispatchOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
5945
|
+
external_exports.object({
|
|
5946
|
+
kind: external_exports.literal("success"),
|
|
5947
|
+
text: external_exports.string(),
|
|
5948
|
+
filePaths: external_exports.array(external_exports.string()).optional()
|
|
5949
|
+
}),
|
|
5950
|
+
external_exports.object({
|
|
5951
|
+
kind: external_exports.literal("failure"),
|
|
5952
|
+
reason: external_exports.string()
|
|
5953
|
+
})
|
|
5954
|
+
]);
|
|
5955
|
+
DispatchRunArgsSchema = external_exports.object({
|
|
5956
|
+
targetPersona: external_exports.string().min(1),
|
|
5957
|
+
prompt: external_exports.string()
|
|
5958
|
+
});
|
|
5959
|
+
DispatchCompleteArgsSchema = external_exports.object({
|
|
5960
|
+
dispatchId: external_exports.string().min(1),
|
|
5961
|
+
outcome: DispatchOutcomeSchema
|
|
5962
|
+
});
|
|
5963
|
+
}
|
|
5964
|
+
});
|
|
5965
|
+
|
|
5966
|
+
// ../protocol/src/log.ts
|
|
5967
|
+
var LOG_SOURCES, LogSourceSchema, LOG_LEVELS, LogLevelSchema, LogRecordSchema;
|
|
5968
|
+
var init_log = __esm({
|
|
5969
|
+
"../protocol/src/log.ts"() {
|
|
5970
|
+
"use strict";
|
|
5971
|
+
init_zod();
|
|
5972
|
+
LOG_SOURCES = ["daemon", "main", "renderer"];
|
|
5973
|
+
LogSourceSchema = external_exports.enum(LOG_SOURCES);
|
|
5974
|
+
LOG_LEVELS = ["debug", "info", "warn", "error"];
|
|
5975
|
+
LogLevelSchema = external_exports.enum(LOG_LEVELS);
|
|
5976
|
+
LogRecordSchema = external_exports.object({
|
|
5977
|
+
ts: external_exports.number().int(),
|
|
5978
|
+
source: LogSourceSchema,
|
|
5979
|
+
level: LogLevelSchema,
|
|
5980
|
+
msg: external_exports.string(),
|
|
5981
|
+
ownerPrincipalId: external_exports.string(),
|
|
5982
|
+
deviceId: external_exports.string(),
|
|
5983
|
+
appVersion: external_exports.string(),
|
|
5984
|
+
daemonVersion: external_exports.string().optional(),
|
|
5985
|
+
os: external_exports.string(),
|
|
5986
|
+
meta_json: external_exports.string().optional(),
|
|
5987
|
+
sessionId: external_exports.string().optional()
|
|
5988
|
+
});
|
|
5989
|
+
}
|
|
5990
|
+
});
|
|
5991
|
+
|
|
5931
5992
|
// ../protocol/src/runtime.ts
|
|
5932
5993
|
var init_runtime = __esm({
|
|
5933
5994
|
"../protocol/src/runtime.ts"() {
|
|
@@ -5946,6 +6007,8 @@ var init_runtime = __esm({
|
|
|
5946
6007
|
init_contact();
|
|
5947
6008
|
init_extension();
|
|
5948
6009
|
init_feishu_auth();
|
|
6010
|
+
init_dispatch();
|
|
6011
|
+
init_log();
|
|
5949
6012
|
}
|
|
5950
6013
|
});
|
|
5951
6014
|
|
|
@@ -6220,8 +6283,8 @@ var require_req = __commonJS({
|
|
|
6220
6283
|
if (req.originalUrl) {
|
|
6221
6284
|
_req.url = req.originalUrl;
|
|
6222
6285
|
} else {
|
|
6223
|
-
const
|
|
6224
|
-
_req.url = typeof
|
|
6286
|
+
const path59 = req.path;
|
|
6287
|
+
_req.url = typeof path59 === "string" ? path59 : req.url ? req.url.path || req.url : void 0;
|
|
6225
6288
|
}
|
|
6226
6289
|
if (req.query) {
|
|
6227
6290
|
_req.query = req.query;
|
|
@@ -6386,14 +6449,14 @@ var require_redact = __commonJS({
|
|
|
6386
6449
|
}
|
|
6387
6450
|
return obj;
|
|
6388
6451
|
}
|
|
6389
|
-
function parsePath(
|
|
6452
|
+
function parsePath(path59) {
|
|
6390
6453
|
const parts = [];
|
|
6391
6454
|
let current = "";
|
|
6392
6455
|
let inBrackets = false;
|
|
6393
6456
|
let inQuotes = false;
|
|
6394
6457
|
let quoteChar = "";
|
|
6395
|
-
for (let i = 0; i <
|
|
6396
|
-
const char =
|
|
6458
|
+
for (let i = 0; i < path59.length; i++) {
|
|
6459
|
+
const char = path59[i];
|
|
6397
6460
|
if (!inBrackets && char === ".") {
|
|
6398
6461
|
if (current) {
|
|
6399
6462
|
parts.push(current);
|
|
@@ -6524,10 +6587,10 @@ var require_redact = __commonJS({
|
|
|
6524
6587
|
return current;
|
|
6525
6588
|
}
|
|
6526
6589
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6527
|
-
for (const
|
|
6528
|
-
const parts = parsePath(
|
|
6590
|
+
for (const path59 of paths) {
|
|
6591
|
+
const parts = parsePath(path59);
|
|
6529
6592
|
if (parts.includes("*")) {
|
|
6530
|
-
redactWildcardPath(obj, parts, censor,
|
|
6593
|
+
redactWildcardPath(obj, parts, censor, path59, remove);
|
|
6531
6594
|
} else {
|
|
6532
6595
|
if (remove) {
|
|
6533
6596
|
removeKey(obj, parts);
|
|
@@ -6612,8 +6675,8 @@ var require_redact = __commonJS({
|
|
|
6612
6675
|
}
|
|
6613
6676
|
} else {
|
|
6614
6677
|
if (afterWildcard.includes("*")) {
|
|
6615
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6616
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6678
|
+
const wrappedCensor = typeof censor === "function" ? (value, path59) => {
|
|
6679
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path59];
|
|
6617
6680
|
return censor(value, fullPath);
|
|
6618
6681
|
} : censor;
|
|
6619
6682
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6648,8 +6711,8 @@ var require_redact = __commonJS({
|
|
|
6648
6711
|
return null;
|
|
6649
6712
|
}
|
|
6650
6713
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6651
|
-
for (const
|
|
6652
|
-
const parts = parsePath(
|
|
6714
|
+
for (const path59 of pathsToClone) {
|
|
6715
|
+
const parts = parsePath(path59);
|
|
6653
6716
|
let current = pathStructure;
|
|
6654
6717
|
for (let i = 0; i < parts.length; i++) {
|
|
6655
6718
|
const part = parts[i];
|
|
@@ -6701,24 +6764,24 @@ var require_redact = __commonJS({
|
|
|
6701
6764
|
}
|
|
6702
6765
|
return cloneSelectively(obj, pathStructure);
|
|
6703
6766
|
}
|
|
6704
|
-
function validatePath(
|
|
6705
|
-
if (typeof
|
|
6767
|
+
function validatePath(path59) {
|
|
6768
|
+
if (typeof path59 !== "string") {
|
|
6706
6769
|
throw new Error("Paths must be (non-empty) strings");
|
|
6707
6770
|
}
|
|
6708
|
-
if (
|
|
6771
|
+
if (path59 === "") {
|
|
6709
6772
|
throw new Error("Invalid redaction path ()");
|
|
6710
6773
|
}
|
|
6711
|
-
if (
|
|
6712
|
-
throw new Error(`Invalid redaction path (${
|
|
6774
|
+
if (path59.includes("..")) {
|
|
6775
|
+
throw new Error(`Invalid redaction path (${path59})`);
|
|
6713
6776
|
}
|
|
6714
|
-
if (
|
|
6715
|
-
throw new Error(`Invalid redaction path (${
|
|
6777
|
+
if (path59.includes(",")) {
|
|
6778
|
+
throw new Error(`Invalid redaction path (${path59})`);
|
|
6716
6779
|
}
|
|
6717
6780
|
let bracketCount = 0;
|
|
6718
6781
|
let inQuotes = false;
|
|
6719
6782
|
let quoteChar = "";
|
|
6720
|
-
for (let i = 0; i <
|
|
6721
|
-
const char =
|
|
6783
|
+
for (let i = 0; i < path59.length; i++) {
|
|
6784
|
+
const char = path59[i];
|
|
6722
6785
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6723
6786
|
if (!inQuotes) {
|
|
6724
6787
|
inQuotes = true;
|
|
@@ -6732,20 +6795,20 @@ var require_redact = __commonJS({
|
|
|
6732
6795
|
} else if (char === "]" && !inQuotes) {
|
|
6733
6796
|
bracketCount--;
|
|
6734
6797
|
if (bracketCount < 0) {
|
|
6735
|
-
throw new Error(`Invalid redaction path (${
|
|
6798
|
+
throw new Error(`Invalid redaction path (${path59})`);
|
|
6736
6799
|
}
|
|
6737
6800
|
}
|
|
6738
6801
|
}
|
|
6739
6802
|
if (bracketCount !== 0) {
|
|
6740
|
-
throw new Error(`Invalid redaction path (${
|
|
6803
|
+
throw new Error(`Invalid redaction path (${path59})`);
|
|
6741
6804
|
}
|
|
6742
6805
|
}
|
|
6743
6806
|
function validatePaths(paths) {
|
|
6744
6807
|
if (!Array.isArray(paths)) {
|
|
6745
6808
|
throw new TypeError("paths must be an array");
|
|
6746
6809
|
}
|
|
6747
|
-
for (const
|
|
6748
|
-
validatePath(
|
|
6810
|
+
for (const path59 of paths) {
|
|
6811
|
+
validatePath(path59);
|
|
6749
6812
|
}
|
|
6750
6813
|
}
|
|
6751
6814
|
function slowRedact(options = {}) {
|
|
@@ -6913,8 +6976,8 @@ var require_redaction = __commonJS({
|
|
|
6913
6976
|
if (shape[k2] === null) {
|
|
6914
6977
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6915
6978
|
} else {
|
|
6916
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6917
|
-
return censor(value, [k2, ...
|
|
6979
|
+
const wrappedCensor = typeof censor === "function" ? (value, path59) => {
|
|
6980
|
+
return censor(value, [k2, ...path59]);
|
|
6918
6981
|
} : censor;
|
|
6919
6982
|
o[k2] = Redact({
|
|
6920
6983
|
paths: shape[k2],
|
|
@@ -7098,7 +7161,7 @@ var require_atomic_sleep = __commonJS({
|
|
|
7098
7161
|
"../node_modules/.pnpm/atomic-sleep@1.0.0/node_modules/atomic-sleep/index.js"(exports2, module2) {
|
|
7099
7162
|
"use strict";
|
|
7100
7163
|
if (typeof SharedArrayBuffer !== "undefined" && typeof Atomics !== "undefined") {
|
|
7101
|
-
let
|
|
7164
|
+
let sleep2 = function(ms) {
|
|
7102
7165
|
const valid = ms > 0 && ms < Infinity;
|
|
7103
7166
|
if (valid === false) {
|
|
7104
7167
|
if (typeof ms !== "number" && typeof ms !== "bigint") {
|
|
@@ -7109,9 +7172,9 @@ var require_atomic_sleep = __commonJS({
|
|
|
7109
7172
|
Atomics.wait(nil, 0, 0, Number(ms));
|
|
7110
7173
|
};
|
|
7111
7174
|
const nil = new Int32Array(new SharedArrayBuffer(4));
|
|
7112
|
-
module2.exports =
|
|
7175
|
+
module2.exports = sleep2;
|
|
7113
7176
|
} else {
|
|
7114
|
-
let
|
|
7177
|
+
let sleep2 = function(ms) {
|
|
7115
7178
|
const valid = ms > 0 && ms < Infinity;
|
|
7116
7179
|
if (valid === false) {
|
|
7117
7180
|
if (typeof ms !== "number" && typeof ms !== "bigint") {
|
|
@@ -7123,7 +7186,7 @@ var require_atomic_sleep = __commonJS({
|
|
|
7123
7186
|
while (target > Date.now()) {
|
|
7124
7187
|
}
|
|
7125
7188
|
};
|
|
7126
|
-
module2.exports =
|
|
7189
|
+
module2.exports = sleep2;
|
|
7127
7190
|
}
|
|
7128
7191
|
}
|
|
7129
7192
|
});
|
|
@@ -7132,11 +7195,11 @@ var require_atomic_sleep = __commonJS({
|
|
|
7132
7195
|
var require_sonic_boom = __commonJS({
|
|
7133
7196
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7134
7197
|
"use strict";
|
|
7135
|
-
var
|
|
7198
|
+
var fs52 = require("fs");
|
|
7136
7199
|
var EventEmitter3 = require("events");
|
|
7137
7200
|
var inherits = require("util").inherits;
|
|
7138
|
-
var
|
|
7139
|
-
var
|
|
7201
|
+
var path59 = require("path");
|
|
7202
|
+
var sleep2 = require_atomic_sleep();
|
|
7140
7203
|
var assert = require("assert");
|
|
7141
7204
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
7142
7205
|
var kEmptyBuffer = Buffer.allocUnsafe(0);
|
|
@@ -7189,20 +7252,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7189
7252
|
const mode = sonic.mode;
|
|
7190
7253
|
if (sonic.sync) {
|
|
7191
7254
|
try {
|
|
7192
|
-
if (sonic.mkdir)
|
|
7193
|
-
const fd =
|
|
7255
|
+
if (sonic.mkdir) fs52.mkdirSync(path59.dirname(file), { recursive: true });
|
|
7256
|
+
const fd = fs52.openSync(file, flags, mode);
|
|
7194
7257
|
fileOpened(null, fd);
|
|
7195
7258
|
} catch (err) {
|
|
7196
7259
|
fileOpened(err);
|
|
7197
7260
|
throw err;
|
|
7198
7261
|
}
|
|
7199
7262
|
} else if (sonic.mkdir) {
|
|
7200
|
-
|
|
7263
|
+
fs52.mkdir(path59.dirname(file), { recursive: true }, (err) => {
|
|
7201
7264
|
if (err) return fileOpened(err);
|
|
7202
|
-
|
|
7265
|
+
fs52.open(file, flags, mode, fileOpened);
|
|
7203
7266
|
});
|
|
7204
7267
|
} else {
|
|
7205
|
-
|
|
7268
|
+
fs52.open(file, flags, mode, fileOpened);
|
|
7206
7269
|
}
|
|
7207
7270
|
}
|
|
7208
7271
|
function SonicBoom(opts) {
|
|
@@ -7243,8 +7306,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7243
7306
|
this.flush = flushBuffer;
|
|
7244
7307
|
this.flushSync = flushBufferSync;
|
|
7245
7308
|
this._actualWrite = actualWriteBuffer;
|
|
7246
|
-
fsWriteSync = () =>
|
|
7247
|
-
fsWrite = () =>
|
|
7309
|
+
fsWriteSync = () => fs52.writeSync(this.fd, this._writingBuf);
|
|
7310
|
+
fsWrite = () => fs52.write(this.fd, this._writingBuf, this.release);
|
|
7248
7311
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7249
7312
|
this._writingBuf = "";
|
|
7250
7313
|
this.write = write;
|
|
@@ -7253,15 +7316,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7253
7316
|
this._actualWrite = actualWrite;
|
|
7254
7317
|
fsWriteSync = () => {
|
|
7255
7318
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7256
|
-
return
|
|
7319
|
+
return fs52.writeSync(this.fd, this._writingBuf);
|
|
7257
7320
|
}
|
|
7258
|
-
return
|
|
7321
|
+
return fs52.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7259
7322
|
};
|
|
7260
7323
|
fsWrite = () => {
|
|
7261
7324
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7262
|
-
return
|
|
7325
|
+
return fs52.write(this.fd, this._writingBuf, this.release);
|
|
7263
7326
|
}
|
|
7264
|
-
return
|
|
7327
|
+
return fs52.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7265
7328
|
};
|
|
7266
7329
|
} else {
|
|
7267
7330
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7282,7 +7345,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7282
7345
|
if ((err.code === "EAGAIN" || err.code === "EBUSY") && this.retryEAGAIN(err, this._writingBuf.length, this._len - this._writingBuf.length)) {
|
|
7283
7346
|
if (this.sync) {
|
|
7284
7347
|
try {
|
|
7285
|
-
|
|
7348
|
+
sleep2(BUSY_WRITE_TIMEOUT);
|
|
7286
7349
|
this.release(void 0, 0);
|
|
7287
7350
|
} catch (err2) {
|
|
7288
7351
|
this.release(err2);
|
|
@@ -7318,7 +7381,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7318
7381
|
}
|
|
7319
7382
|
}
|
|
7320
7383
|
if (this._fsync) {
|
|
7321
|
-
|
|
7384
|
+
fs52.fsyncSync(this.fd);
|
|
7322
7385
|
}
|
|
7323
7386
|
const len = this._len;
|
|
7324
7387
|
if (this._reopening) {
|
|
@@ -7432,7 +7495,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7432
7495
|
const onDrain = () => {
|
|
7433
7496
|
if (!this._fsync) {
|
|
7434
7497
|
try {
|
|
7435
|
-
|
|
7498
|
+
fs52.fsync(this.fd, (err) => {
|
|
7436
7499
|
this._flushPending = false;
|
|
7437
7500
|
cb(err);
|
|
7438
7501
|
});
|
|
@@ -7534,7 +7597,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7534
7597
|
const fd = this.fd;
|
|
7535
7598
|
this.once("ready", () => {
|
|
7536
7599
|
if (fd !== this.fd) {
|
|
7537
|
-
|
|
7600
|
+
fs52.close(fd, (err) => {
|
|
7538
7601
|
if (err) {
|
|
7539
7602
|
return this.emit("error", err);
|
|
7540
7603
|
}
|
|
@@ -7583,7 +7646,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7583
7646
|
buf = this._bufs[0];
|
|
7584
7647
|
}
|
|
7585
7648
|
try {
|
|
7586
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7649
|
+
const n = Buffer.isBuffer(buf) ? fs52.writeSync(this.fd, buf) : fs52.writeSync(this.fd, buf, "utf8");
|
|
7587
7650
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7588
7651
|
buf = releasedBufObj.writingBuf;
|
|
7589
7652
|
this._len = releasedBufObj.len;
|
|
@@ -7595,11 +7658,11 @@ var require_sonic_boom = __commonJS({
|
|
|
7595
7658
|
if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
|
|
7596
7659
|
throw err;
|
|
7597
7660
|
}
|
|
7598
|
-
|
|
7661
|
+
sleep2(BUSY_WRITE_TIMEOUT);
|
|
7599
7662
|
}
|
|
7600
7663
|
}
|
|
7601
7664
|
try {
|
|
7602
|
-
|
|
7665
|
+
fs52.fsyncSync(this.fd);
|
|
7603
7666
|
} catch {
|
|
7604
7667
|
}
|
|
7605
7668
|
}
|
|
@@ -7620,7 +7683,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7620
7683
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7621
7684
|
}
|
|
7622
7685
|
try {
|
|
7623
|
-
const n =
|
|
7686
|
+
const n = fs52.writeSync(this.fd, buf);
|
|
7624
7687
|
buf = buf.subarray(n);
|
|
7625
7688
|
this._len = Math.max(this._len - n, 0);
|
|
7626
7689
|
if (buf.length <= 0) {
|
|
@@ -7632,7 +7695,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7632
7695
|
if (shouldRetry && !this.retryEAGAIN(err, buf.length, this._len - buf.length)) {
|
|
7633
7696
|
throw err;
|
|
7634
7697
|
}
|
|
7635
|
-
|
|
7698
|
+
sleep2(BUSY_WRITE_TIMEOUT);
|
|
7636
7699
|
}
|
|
7637
7700
|
}
|
|
7638
7701
|
}
|
|
@@ -7648,13 +7711,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7648
7711
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7649
7712
|
if (this.sync) {
|
|
7650
7713
|
try {
|
|
7651
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7714
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs52.writeSync(this.fd, this._writingBuf) : fs52.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7652
7715
|
release(null, written);
|
|
7653
7716
|
} catch (err) {
|
|
7654
7717
|
release(err);
|
|
7655
7718
|
}
|
|
7656
7719
|
} else {
|
|
7657
|
-
|
|
7720
|
+
fs52.write(this.fd, this._writingBuf, release);
|
|
7658
7721
|
}
|
|
7659
7722
|
}
|
|
7660
7723
|
function actualWriteBuffer() {
|
|
@@ -7663,7 +7726,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7663
7726
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7664
7727
|
if (this.sync) {
|
|
7665
7728
|
try {
|
|
7666
|
-
const written =
|
|
7729
|
+
const written = fs52.writeSync(this.fd, this._writingBuf);
|
|
7667
7730
|
release(null, written);
|
|
7668
7731
|
} catch (err) {
|
|
7669
7732
|
release(err);
|
|
@@ -7672,7 +7735,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7672
7735
|
if (kCopyBuffer) {
|
|
7673
7736
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7674
7737
|
}
|
|
7675
|
-
|
|
7738
|
+
fs52.write(this.fd, this._writingBuf, release);
|
|
7676
7739
|
}
|
|
7677
7740
|
}
|
|
7678
7741
|
function actualClose(sonic) {
|
|
@@ -7688,12 +7751,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7688
7751
|
sonic._lens = [];
|
|
7689
7752
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7690
7753
|
try {
|
|
7691
|
-
|
|
7754
|
+
fs52.fsync(sonic.fd, closeWrapped);
|
|
7692
7755
|
} catch {
|
|
7693
7756
|
}
|
|
7694
7757
|
function closeWrapped() {
|
|
7695
7758
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7696
|
-
|
|
7759
|
+
fs52.close(sonic.fd, done);
|
|
7697
7760
|
} else {
|
|
7698
7761
|
done();
|
|
7699
7762
|
}
|
|
@@ -8373,7 +8436,7 @@ var require_transport = __commonJS({
|
|
|
8373
8436
|
var { createRequire } = require("module");
|
|
8374
8437
|
var getCallers = require_caller();
|
|
8375
8438
|
var { join: join15, isAbsolute: isAbsolute2, sep: sep2 } = require("path");
|
|
8376
|
-
var
|
|
8439
|
+
var sleep2 = require_atomic_sleep();
|
|
8377
8440
|
var onExit = require_on_exit_leak_free();
|
|
8378
8441
|
var ThreadStream = require_thread_stream();
|
|
8379
8442
|
function setupOnExit(stream) {
|
|
@@ -8407,7 +8470,7 @@ var require_transport = __commonJS({
|
|
|
8407
8470
|
return;
|
|
8408
8471
|
}
|
|
8409
8472
|
stream.flushSync();
|
|
8410
|
-
|
|
8473
|
+
sleep2(100);
|
|
8411
8474
|
stream.end();
|
|
8412
8475
|
}
|
|
8413
8476
|
return stream;
|
|
@@ -10057,7 +10120,7 @@ var require_multistream = __commonJS({
|
|
|
10057
10120
|
var require_pino = __commonJS({
|
|
10058
10121
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
10059
10122
|
"use strict";
|
|
10060
|
-
var
|
|
10123
|
+
var os22 = require("os");
|
|
10061
10124
|
var stdSerializers = require_pino_std_serializers();
|
|
10062
10125
|
var caller = require_caller();
|
|
10063
10126
|
var redaction = require_redaction();
|
|
@@ -10104,7 +10167,7 @@ var require_pino = __commonJS({
|
|
|
10104
10167
|
} = symbols;
|
|
10105
10168
|
var { epochTime, nullTime } = time;
|
|
10106
10169
|
var { pid } = process;
|
|
10107
|
-
var hostname =
|
|
10170
|
+
var hostname = os22.hostname();
|
|
10108
10171
|
var defaultErrorSerializer = stdSerializers.err;
|
|
10109
10172
|
var defaultOptions = {
|
|
10110
10173
|
level: "info",
|
|
@@ -10828,11 +10891,11 @@ var init_lib = __esm({
|
|
|
10828
10891
|
}
|
|
10829
10892
|
}
|
|
10830
10893
|
},
|
|
10831
|
-
addToPath: function addToPath(
|
|
10832
|
-
var last =
|
|
10894
|
+
addToPath: function addToPath(path59, added, removed, oldPosInc, options) {
|
|
10895
|
+
var last = path59.lastComponent;
|
|
10833
10896
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10834
10897
|
return {
|
|
10835
|
-
oldPos:
|
|
10898
|
+
oldPos: path59.oldPos + oldPosInc,
|
|
10836
10899
|
lastComponent: {
|
|
10837
10900
|
count: last.count + 1,
|
|
10838
10901
|
added,
|
|
@@ -10842,7 +10905,7 @@ var init_lib = __esm({
|
|
|
10842
10905
|
};
|
|
10843
10906
|
} else {
|
|
10844
10907
|
return {
|
|
10845
|
-
oldPos:
|
|
10908
|
+
oldPos: path59.oldPos + oldPosInc,
|
|
10846
10909
|
lastComponent: {
|
|
10847
10910
|
count: 1,
|
|
10848
10911
|
added,
|
|
@@ -11288,10 +11351,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11288
11351
|
const memories = raw.map((m2) => {
|
|
11289
11352
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11290
11353
|
const rec3 = m2;
|
|
11291
|
-
const
|
|
11354
|
+
const path59 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11292
11355
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11293
|
-
if (!
|
|
11294
|
-
const entry = { path:
|
|
11356
|
+
if (!path59 || content == null) return null;
|
|
11357
|
+
const entry = { path: path59, content };
|
|
11295
11358
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11296
11359
|
return entry;
|
|
11297
11360
|
}).filter((m2) => m2 !== null);
|
|
@@ -11811,6 +11874,9 @@ function buildSpawnArgs(ctx) {
|
|
|
11811
11874
|
if (ctx.addDirs) {
|
|
11812
11875
|
for (const dir of ctx.addDirs) args.push("--add-dir", dir);
|
|
11813
11876
|
}
|
|
11877
|
+
if (ctx.dispatchMcpConfigPath) {
|
|
11878
|
+
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
11879
|
+
}
|
|
11814
11880
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
11815
11881
|
if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
|
|
11816
11882
|
return args;
|
|
@@ -12090,10 +12156,10 @@ function parseAttachment(obj) {
|
|
|
12090
12156
|
const memories = raw.map((m2) => {
|
|
12091
12157
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12092
12158
|
const rec3 = m2;
|
|
12093
|
-
const
|
|
12159
|
+
const path59 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12094
12160
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12095
|
-
if (!
|
|
12096
|
-
const out = { path:
|
|
12161
|
+
if (!path59 || content == null) return null;
|
|
12162
|
+
const out = { path: path59, content };
|
|
12097
12163
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12098
12164
|
return out;
|
|
12099
12165
|
}).filter((m2) => m2 !== null);
|
|
@@ -18123,7 +18189,7 @@ var require_validation = __commonJS({
|
|
|
18123
18189
|
var require_receiver = __commonJS({
|
|
18124
18190
|
"../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/receiver.js"(exports2, module2) {
|
|
18125
18191
|
"use strict";
|
|
18126
|
-
var { Writable:
|
|
18192
|
+
var { Writable: Writable3 } = require("stream");
|
|
18127
18193
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
18128
18194
|
var {
|
|
18129
18195
|
BINARY_TYPES,
|
|
@@ -18141,7 +18207,7 @@ var require_receiver = __commonJS({
|
|
|
18141
18207
|
var GET_DATA = 4;
|
|
18142
18208
|
var INFLATING = 5;
|
|
18143
18209
|
var DEFER_EVENT = 6;
|
|
18144
|
-
var Receiver2 = class extends
|
|
18210
|
+
var Receiver2 = class extends Writable3 {
|
|
18145
18211
|
/**
|
|
18146
18212
|
* Creates a Receiver instance.
|
|
18147
18213
|
*
|
|
@@ -21404,7 +21470,7 @@ var require_stream_writable = __commonJS({
|
|
|
21404
21470
|
"../node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/lib/_stream_writable.js"(exports2, module2) {
|
|
21405
21471
|
"use strict";
|
|
21406
21472
|
var pna = require_process_nextick_args();
|
|
21407
|
-
module2.exports =
|
|
21473
|
+
module2.exports = Writable3;
|
|
21408
21474
|
function CorkedRequest(state) {
|
|
21409
21475
|
var _this = this;
|
|
21410
21476
|
this.next = null;
|
|
@@ -21415,7 +21481,7 @@ var require_stream_writable = __commonJS({
|
|
|
21415
21481
|
}
|
|
21416
21482
|
var asyncWrite = !process.browser && ["v0.10", "v0.9."].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
|
|
21417
21483
|
var Duplex;
|
|
21418
|
-
|
|
21484
|
+
Writable3.WritableState = WritableState;
|
|
21419
21485
|
var util2 = Object.create(require_util());
|
|
21420
21486
|
util2.inherits = require_inherits();
|
|
21421
21487
|
var internalUtil = {
|
|
@@ -21432,7 +21498,7 @@ var require_stream_writable = __commonJS({
|
|
|
21432
21498
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
21433
21499
|
}
|
|
21434
21500
|
var destroyImpl = require_destroy();
|
|
21435
|
-
util2.inherits(
|
|
21501
|
+
util2.inherits(Writable3, Stream);
|
|
21436
21502
|
function nop() {
|
|
21437
21503
|
}
|
|
21438
21504
|
function WritableState(options, stream) {
|
|
@@ -21497,10 +21563,10 @@ var require_stream_writable = __commonJS({
|
|
|
21497
21563
|
var realHasInstance;
|
|
21498
21564
|
if (typeof Symbol === "function" && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === "function") {
|
|
21499
21565
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
21500
|
-
Object.defineProperty(
|
|
21566
|
+
Object.defineProperty(Writable3, Symbol.hasInstance, {
|
|
21501
21567
|
value: function(object) {
|
|
21502
21568
|
if (realHasInstance.call(this, object)) return true;
|
|
21503
|
-
if (this !==
|
|
21569
|
+
if (this !== Writable3) return false;
|
|
21504
21570
|
return object && object._writableState instanceof WritableState;
|
|
21505
21571
|
}
|
|
21506
21572
|
});
|
|
@@ -21509,10 +21575,10 @@ var require_stream_writable = __commonJS({
|
|
|
21509
21575
|
return object instanceof this;
|
|
21510
21576
|
};
|
|
21511
21577
|
}
|
|
21512
|
-
function
|
|
21578
|
+
function Writable3(options) {
|
|
21513
21579
|
Duplex = Duplex || require_stream_duplex();
|
|
21514
|
-
if (!realHasInstance.call(
|
|
21515
|
-
return new
|
|
21580
|
+
if (!realHasInstance.call(Writable3, this) && !(this instanceof Duplex)) {
|
|
21581
|
+
return new Writable3(options);
|
|
21516
21582
|
}
|
|
21517
21583
|
this._writableState = new WritableState(options, this);
|
|
21518
21584
|
this.writable = true;
|
|
@@ -21524,7 +21590,7 @@ var require_stream_writable = __commonJS({
|
|
|
21524
21590
|
}
|
|
21525
21591
|
Stream.call(this);
|
|
21526
21592
|
}
|
|
21527
|
-
|
|
21593
|
+
Writable3.prototype.pipe = function() {
|
|
21528
21594
|
this.emit("error", new Error("Cannot pipe, not readable"));
|
|
21529
21595
|
};
|
|
21530
21596
|
function writeAfterEnd(stream, cb) {
|
|
@@ -21547,7 +21613,7 @@ var require_stream_writable = __commonJS({
|
|
|
21547
21613
|
}
|
|
21548
21614
|
return valid;
|
|
21549
21615
|
}
|
|
21550
|
-
|
|
21616
|
+
Writable3.prototype.write = function(chunk, encoding, cb) {
|
|
21551
21617
|
var state = this._writableState;
|
|
21552
21618
|
var ret = false;
|
|
21553
21619
|
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
|
@@ -21568,18 +21634,18 @@ var require_stream_writable = __commonJS({
|
|
|
21568
21634
|
}
|
|
21569
21635
|
return ret;
|
|
21570
21636
|
};
|
|
21571
|
-
|
|
21637
|
+
Writable3.prototype.cork = function() {
|
|
21572
21638
|
var state = this._writableState;
|
|
21573
21639
|
state.corked++;
|
|
21574
21640
|
};
|
|
21575
|
-
|
|
21641
|
+
Writable3.prototype.uncork = function() {
|
|
21576
21642
|
var state = this._writableState;
|
|
21577
21643
|
if (state.corked) {
|
|
21578
21644
|
state.corked--;
|
|
21579
21645
|
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
|
21580
21646
|
}
|
|
21581
21647
|
};
|
|
21582
|
-
|
|
21648
|
+
Writable3.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
21583
21649
|
if (typeof encoding === "string") encoding = encoding.toLowerCase();
|
|
21584
21650
|
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);
|
|
21585
21651
|
this._writableState.defaultEncoding = encoding;
|
|
@@ -21591,7 +21657,7 @@ var require_stream_writable = __commonJS({
|
|
|
21591
21657
|
}
|
|
21592
21658
|
return chunk;
|
|
21593
21659
|
}
|
|
21594
|
-
Object.defineProperty(
|
|
21660
|
+
Object.defineProperty(Writable3.prototype, "writableHighWaterMark", {
|
|
21595
21661
|
// making it explicit this property is not enumerable
|
|
21596
21662
|
// because otherwise some prototype manipulation in
|
|
21597
21663
|
// userland will fail
|
|
@@ -21737,11 +21803,11 @@ var require_stream_writable = __commonJS({
|
|
|
21737
21803
|
state.bufferedRequest = entry;
|
|
21738
21804
|
state.bufferProcessing = false;
|
|
21739
21805
|
}
|
|
21740
|
-
|
|
21806
|
+
Writable3.prototype._write = function(chunk, encoding, cb) {
|
|
21741
21807
|
cb(new Error("_write() is not implemented"));
|
|
21742
21808
|
};
|
|
21743
|
-
|
|
21744
|
-
|
|
21809
|
+
Writable3.prototype._writev = null;
|
|
21810
|
+
Writable3.prototype.end = function(chunk, encoding, cb) {
|
|
21745
21811
|
var state = this._writableState;
|
|
21746
21812
|
if (typeof chunk === "function") {
|
|
21747
21813
|
cb = chunk;
|
|
@@ -21816,7 +21882,7 @@ var require_stream_writable = __commonJS({
|
|
|
21816
21882
|
}
|
|
21817
21883
|
state.corkedRequestsFree.next = corkReq;
|
|
21818
21884
|
}
|
|
21819
|
-
Object.defineProperty(
|
|
21885
|
+
Object.defineProperty(Writable3.prototype, "destroyed", {
|
|
21820
21886
|
get: function() {
|
|
21821
21887
|
if (this._writableState === void 0) {
|
|
21822
21888
|
return false;
|
|
@@ -21830,9 +21896,9 @@ var require_stream_writable = __commonJS({
|
|
|
21830
21896
|
this._writableState.destroyed = value;
|
|
21831
21897
|
}
|
|
21832
21898
|
});
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21899
|
+
Writable3.prototype.destroy = destroyImpl.destroy;
|
|
21900
|
+
Writable3.prototype._undestroy = destroyImpl.undestroy;
|
|
21901
|
+
Writable3.prototype._destroy = function(err, cb) {
|
|
21836
21902
|
this.end();
|
|
21837
21903
|
cb(err);
|
|
21838
21904
|
};
|
|
@@ -21855,13 +21921,13 @@ var require_stream_duplex = __commonJS({
|
|
|
21855
21921
|
var util2 = Object.create(require_util());
|
|
21856
21922
|
util2.inherits = require_inherits();
|
|
21857
21923
|
var Readable3 = require_stream_readable();
|
|
21858
|
-
var
|
|
21924
|
+
var Writable3 = require_stream_writable();
|
|
21859
21925
|
util2.inherits(Duplex, Readable3);
|
|
21860
21926
|
{
|
|
21861
|
-
keys = objectKeys(
|
|
21927
|
+
keys = objectKeys(Writable3.prototype);
|
|
21862
21928
|
for (v2 = 0; v2 < keys.length; v2++) {
|
|
21863
21929
|
method = keys[v2];
|
|
21864
|
-
if (!Duplex.prototype[method]) Duplex.prototype[method] =
|
|
21930
|
+
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable3.prototype[method];
|
|
21865
21931
|
}
|
|
21866
21932
|
}
|
|
21867
21933
|
var keys;
|
|
@@ -21870,7 +21936,7 @@ var require_stream_duplex = __commonJS({
|
|
|
21870
21936
|
function Duplex(options) {
|
|
21871
21937
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
21872
21938
|
Readable3.call(this, options);
|
|
21873
|
-
|
|
21939
|
+
Writable3.call(this, options);
|
|
21874
21940
|
if (options && options.readable === false) this.readable = false;
|
|
21875
21941
|
if (options && options.writable === false) this.writable = false;
|
|
21876
21942
|
this.allowHalfOpen = true;
|
|
@@ -23880,8 +23946,8 @@ var require_utils = __commonJS({
|
|
|
23880
23946
|
var result = transform[inputType][outputType](input);
|
|
23881
23947
|
return result;
|
|
23882
23948
|
};
|
|
23883
|
-
exports2.resolve = function(
|
|
23884
|
-
var parts =
|
|
23949
|
+
exports2.resolve = function(path59) {
|
|
23950
|
+
var parts = path59.split("/");
|
|
23885
23951
|
var result = [];
|
|
23886
23952
|
for (var index = 0; index < parts.length; index++) {
|
|
23887
23953
|
var part = parts[index];
|
|
@@ -29734,18 +29800,18 @@ var require_object = __commonJS({
|
|
|
29734
29800
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
29735
29801
|
this.files[name] = object;
|
|
29736
29802
|
};
|
|
29737
|
-
var parentFolder = function(
|
|
29738
|
-
if (
|
|
29739
|
-
|
|
29803
|
+
var parentFolder = function(path59) {
|
|
29804
|
+
if (path59.slice(-1) === "/") {
|
|
29805
|
+
path59 = path59.substring(0, path59.length - 1);
|
|
29740
29806
|
}
|
|
29741
|
-
var lastSlash =
|
|
29742
|
-
return lastSlash > 0 ?
|
|
29807
|
+
var lastSlash = path59.lastIndexOf("/");
|
|
29808
|
+
return lastSlash > 0 ? path59.substring(0, lastSlash) : "";
|
|
29743
29809
|
};
|
|
29744
|
-
var forceTrailingSlash = function(
|
|
29745
|
-
if (
|
|
29746
|
-
|
|
29810
|
+
var forceTrailingSlash = function(path59) {
|
|
29811
|
+
if (path59.slice(-1) !== "/") {
|
|
29812
|
+
path59 += "/";
|
|
29747
29813
|
}
|
|
29748
|
-
return
|
|
29814
|
+
return path59;
|
|
29749
29815
|
};
|
|
29750
29816
|
var folderAdd = function(name, createFolders) {
|
|
29751
29817
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -30747,7 +30813,7 @@ var require_lib3 = __commonJS({
|
|
|
30747
30813
|
// src/run-case/recorder.ts
|
|
30748
30814
|
function startRunCaseRecorder(opts) {
|
|
30749
30815
|
const now = opts.now ?? Date.now;
|
|
30750
|
-
const dir =
|
|
30816
|
+
const dir = import_node_path47.default.dirname(opts.recordPath);
|
|
30751
30817
|
let stream = null;
|
|
30752
30818
|
let closing = false;
|
|
30753
30819
|
let closedSettled = false;
|
|
@@ -30761,8 +30827,8 @@ function startRunCaseRecorder(opts) {
|
|
|
30761
30827
|
});
|
|
30762
30828
|
const ensureStream = () => {
|
|
30763
30829
|
if (stream) return stream;
|
|
30764
|
-
|
|
30765
|
-
stream =
|
|
30830
|
+
import_node_fs35.default.mkdirSync(dir, { recursive: true });
|
|
30831
|
+
stream = import_node_fs35.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
30766
30832
|
stream.on("close", () => closedResolve());
|
|
30767
30833
|
return stream;
|
|
30768
30834
|
};
|
|
@@ -30787,12 +30853,12 @@ function startRunCaseRecorder(opts) {
|
|
|
30787
30853
|
};
|
|
30788
30854
|
return { tap, close, closed };
|
|
30789
30855
|
}
|
|
30790
|
-
var
|
|
30856
|
+
var import_node_fs35, import_node_path47;
|
|
30791
30857
|
var init_recorder = __esm({
|
|
30792
30858
|
"src/run-case/recorder.ts"() {
|
|
30793
30859
|
"use strict";
|
|
30794
|
-
|
|
30795
|
-
|
|
30860
|
+
import_node_fs35 = __toESM(require("fs"), 1);
|
|
30861
|
+
import_node_path47 = __toESM(require("path"), 1);
|
|
30796
30862
|
}
|
|
30797
30863
|
});
|
|
30798
30864
|
|
|
@@ -30835,7 +30901,7 @@ var init_wire = __esm({
|
|
|
30835
30901
|
// src/run-case/controller.ts
|
|
30836
30902
|
async function runController(opts) {
|
|
30837
30903
|
const now = opts.now ?? Date.now;
|
|
30838
|
-
const cwd = opts.cwd ?? (0,
|
|
30904
|
+
const cwd = opts.cwd ?? (0, import_node_fs36.mkdtempSync)(import_node_path48.default.join(import_node_os20.default.tmpdir(), "clawd-runcase-"));
|
|
30839
30905
|
const ownsCwd = opts.cwd === void 0;
|
|
30840
30906
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
30841
30907
|
const spawnCtx = { cwd };
|
|
@@ -30996,19 +31062,19 @@ async function runController(opts) {
|
|
|
30996
31062
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
30997
31063
|
if (ownsCwd) {
|
|
30998
31064
|
try {
|
|
30999
|
-
(0,
|
|
31065
|
+
(0, import_node_fs36.rmSync)(cwd, { recursive: true, force: true });
|
|
31000
31066
|
} catch {
|
|
31001
31067
|
}
|
|
31002
31068
|
}
|
|
31003
31069
|
return exitCode ?? 0;
|
|
31004
31070
|
}
|
|
31005
|
-
var
|
|
31071
|
+
var import_node_fs36, import_node_os20, import_node_path48;
|
|
31006
31072
|
var init_controller = __esm({
|
|
31007
31073
|
"src/run-case/controller.ts"() {
|
|
31008
31074
|
"use strict";
|
|
31009
|
-
|
|
31010
|
-
|
|
31011
|
-
|
|
31075
|
+
import_node_fs36 = require("fs");
|
|
31076
|
+
import_node_os20 = __toESM(require("os"), 1);
|
|
31077
|
+
import_node_path48 = __toESM(require("path"), 1);
|
|
31012
31078
|
init_claude();
|
|
31013
31079
|
init_stdout_splitter();
|
|
31014
31080
|
init_permission_stdio();
|
|
@@ -31112,6 +31178,24 @@ init_protocol();
|
|
|
31112
31178
|
var DEFAULT_PORT = 18790;
|
|
31113
31179
|
var DEFAULT_HOST = "127.0.0.1";
|
|
31114
31180
|
var DEFAULT_CLAWOS_API = "https://api.clawos.chat";
|
|
31181
|
+
var DEFAULT_LOG_ENDPOINT = "https://clawd-prod.cn-hangzhou.log.aliyuncs.com/logstores/app-logs/track";
|
|
31182
|
+
function resolveLogShipping(raw, cliNoShipping) {
|
|
31183
|
+
if (cliNoShipping) {
|
|
31184
|
+
return { mode: "off", endpoint: null, sampling: {} };
|
|
31185
|
+
}
|
|
31186
|
+
const rawMode = raw?.mode;
|
|
31187
|
+
const mode = rawMode === "off" || rawMode === "errors-only" ? rawMode : "on";
|
|
31188
|
+
if (mode === "off") {
|
|
31189
|
+
return { mode, endpoint: null, sampling: {} };
|
|
31190
|
+
}
|
|
31191
|
+
const endpoint = typeof raw?.endpoint === "string" && raw.endpoint ? raw.endpoint : raw?.endpoint === null ? null : DEFAULT_LOG_ENDPOINT;
|
|
31192
|
+
const sampling = mode === "errors-only" ? { debug: 0, info: 0, warn: 1, error: 1 } : isPlainSamplingMap(raw?.sampling) ? raw.sampling : {};
|
|
31193
|
+
return { mode, endpoint, sampling };
|
|
31194
|
+
}
|
|
31195
|
+
function isPlainSamplingMap(v2) {
|
|
31196
|
+
if (!v2 || typeof v2 !== "object") return false;
|
|
31197
|
+
return Object.values(v2).every((n) => typeof n === "number");
|
|
31198
|
+
}
|
|
31115
31199
|
function parseArgs(argv) {
|
|
31116
31200
|
const out = {};
|
|
31117
31201
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -31157,6 +31241,9 @@ function parseArgs(argv) {
|
|
|
31157
31241
|
case "-v":
|
|
31158
31242
|
out.version = true;
|
|
31159
31243
|
break;
|
|
31244
|
+
case "--no-log-shipping":
|
|
31245
|
+
out.noLogShipping = true;
|
|
31246
|
+
break;
|
|
31160
31247
|
default:
|
|
31161
31248
|
if (a.startsWith("--")) throw new Error(`unknown flag: ${a}`);
|
|
31162
31249
|
break;
|
|
@@ -31202,6 +31289,10 @@ function resolveConfig(opts) {
|
|
|
31202
31289
|
const mode = DAEMON_MODE_VALUES.includes(rawMode ?? "") ? rawMode : "sdk";
|
|
31203
31290
|
const filePreviewPorts = Array.isArray(fileCfg.previewPorts) ? fileCfg.previewPorts.map((n) => Number(n)).filter((n) => Number.isInteger(n) && n > 0) : null;
|
|
31204
31291
|
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;
|
|
31292
|
+
const logShipping = resolveLogShipping(
|
|
31293
|
+
fileCfg.logShipping,
|
|
31294
|
+
args.noLogShipping ?? false
|
|
31295
|
+
);
|
|
31205
31296
|
return {
|
|
31206
31297
|
port,
|
|
31207
31298
|
host,
|
|
@@ -31214,7 +31305,8 @@ function resolveConfig(opts) {
|
|
|
31214
31305
|
noTunnelPersist,
|
|
31215
31306
|
frpcBinary,
|
|
31216
31307
|
mode,
|
|
31217
|
-
previewPorts
|
|
31308
|
+
previewPorts,
|
|
31309
|
+
logShipping
|
|
31218
31310
|
};
|
|
31219
31311
|
}
|
|
31220
31312
|
var HELP_TEXT = `clawd [options]
|
|
@@ -31225,6 +31317,7 @@ var HELP_TEXT = `clawd [options]
|
|
|
31225
31317
|
--tunnel \u542F\u7528 frp tunnel \u628A\u672C\u5730\u7AEF\u53E3\u66B4\u9732\u5230\u516C\u7F51
|
|
31226
31318
|
--clawos-api <url> tunnel register \u63A5\u53E3\u7684 base url\uFF08\u9ED8\u8BA4 https://api.clawos.chat\uFF09
|
|
31227
31319
|
--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
|
|
31320
|
+
--no-log-shipping \u7981\u7528 SLS \u65E5\u5FD7\u4E0A\u884C\uFF08\u8986\u76D6 config.json logShipping.mode=off\uFF09
|
|
31228
31321
|
--help / -h \u663E\u793A\u5E2E\u52A9
|
|
31229
31322
|
--version / -v \u663E\u793A\u7248\u672C
|
|
31230
31323
|
|
|
@@ -31243,12 +31336,64 @@ Env (advanced):
|
|
|
31243
31336
|
`;
|
|
31244
31337
|
|
|
31245
31338
|
// src/index.ts
|
|
31246
|
-
var
|
|
31247
|
-
var
|
|
31339
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
31340
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
31341
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
31342
|
+
|
|
31343
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
31344
|
+
var byteToHex = [];
|
|
31345
|
+
for (let i = 0; i < 256; ++i) {
|
|
31346
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
31347
|
+
}
|
|
31348
|
+
function unsafeStringify(arr, offset = 0) {
|
|
31349
|
+
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();
|
|
31350
|
+
}
|
|
31351
|
+
|
|
31352
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/rng.js
|
|
31353
|
+
var import_node_crypto = __toESM(require("crypto"));
|
|
31354
|
+
var rnds8Pool = new Uint8Array(256);
|
|
31355
|
+
var poolPtr = rnds8Pool.length;
|
|
31356
|
+
function rng() {
|
|
31357
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
31358
|
+
import_node_crypto.default.randomFillSync(rnds8Pool);
|
|
31359
|
+
poolPtr = 0;
|
|
31360
|
+
}
|
|
31361
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
31362
|
+
}
|
|
31363
|
+
|
|
31364
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/native.js
|
|
31365
|
+
var import_node_crypto2 = __toESM(require("crypto"));
|
|
31366
|
+
var native_default = {
|
|
31367
|
+
randomUUID: import_node_crypto2.default.randomUUID
|
|
31368
|
+
};
|
|
31369
|
+
|
|
31370
|
+
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/v4.js
|
|
31371
|
+
function v4(options, buf, offset) {
|
|
31372
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
31373
|
+
return native_default.randomUUID();
|
|
31374
|
+
}
|
|
31375
|
+
options = options || {};
|
|
31376
|
+
const rnds = options.random || (options.rng || rng)();
|
|
31377
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
31378
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
31379
|
+
if (buf) {
|
|
31380
|
+
offset = offset || 0;
|
|
31381
|
+
for (let i = 0; i < 16; ++i) {
|
|
31382
|
+
buf[offset + i] = rnds[i];
|
|
31383
|
+
}
|
|
31384
|
+
return buf;
|
|
31385
|
+
}
|
|
31386
|
+
return unsafeStringify(rnds);
|
|
31387
|
+
}
|
|
31388
|
+
var v4_default = v4;
|
|
31389
|
+
|
|
31390
|
+
// src/index.ts
|
|
31391
|
+
var import_node_url2 = require("url");
|
|
31248
31392
|
|
|
31249
31393
|
// src/logger.ts
|
|
31250
31394
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
31251
31395
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
31396
|
+
var import_node_stream = require("stream");
|
|
31252
31397
|
var import_pino = __toESM(require_pino(), 1);
|
|
31253
31398
|
function wrap(inner) {
|
|
31254
31399
|
return {
|
|
@@ -31274,12 +31419,328 @@ function createLogger(opts = {}) {
|
|
|
31274
31419
|
} catch {
|
|
31275
31420
|
}
|
|
31276
31421
|
}
|
|
31422
|
+
if (opts.logClient) {
|
|
31423
|
+
const client = opts.logClient;
|
|
31424
|
+
const sink = new import_node_stream.Writable({
|
|
31425
|
+
write(chunk, _enc, cb) {
|
|
31426
|
+
try {
|
|
31427
|
+
const line = String(chunk).trim();
|
|
31428
|
+
if (line) {
|
|
31429
|
+
const obj = JSON.parse(line);
|
|
31430
|
+
const lvl = pinoLevelToString(obj.level);
|
|
31431
|
+
if (lvl) {
|
|
31432
|
+
const meta = {};
|
|
31433
|
+
for (const [k2, v2] of Object.entries(obj)) {
|
|
31434
|
+
if (k2 === "level" || k2 === "msg" || k2 === "time" || k2 === "pid" || k2 === "hostname") continue;
|
|
31435
|
+
if (k2 === "sessionId") continue;
|
|
31436
|
+
meta[k2] = v2;
|
|
31437
|
+
}
|
|
31438
|
+
client.push({
|
|
31439
|
+
ts: typeof obj.time === "number" ? obj.time : void 0,
|
|
31440
|
+
level: lvl,
|
|
31441
|
+
msg: typeof obj.msg === "string" ? obj.msg : "",
|
|
31442
|
+
meta: Object.keys(meta).length > 0 ? meta : void 0,
|
|
31443
|
+
sessionId: typeof obj.sessionId === "string" ? obj.sessionId : void 0
|
|
31444
|
+
});
|
|
31445
|
+
}
|
|
31446
|
+
}
|
|
31447
|
+
} catch {
|
|
31448
|
+
}
|
|
31449
|
+
cb();
|
|
31450
|
+
}
|
|
31451
|
+
});
|
|
31452
|
+
streams.push({ stream: sink, level });
|
|
31453
|
+
}
|
|
31277
31454
|
const base = (0, import_pino.default)(
|
|
31278
31455
|
{ level, base: { pid: process.pid } },
|
|
31279
31456
|
import_pino.default.multistream(streams)
|
|
31280
31457
|
);
|
|
31281
31458
|
return wrap(base);
|
|
31282
31459
|
}
|
|
31460
|
+
function pinoLevelToString(n) {
|
|
31461
|
+
if (typeof n !== "number") return null;
|
|
31462
|
+
if (n >= 50) return "error";
|
|
31463
|
+
if (n >= 40) return "warn";
|
|
31464
|
+
if (n >= 30) return "info";
|
|
31465
|
+
if (n >= 20) return "debug";
|
|
31466
|
+
return null;
|
|
31467
|
+
}
|
|
31468
|
+
|
|
31469
|
+
// ../log-client/dist/index.js
|
|
31470
|
+
var DEFAULT_BATCH = {
|
|
31471
|
+
maxRecords: 100,
|
|
31472
|
+
maxBytes: 512 * 1024,
|
|
31473
|
+
maxWaitMs: 5e3
|
|
31474
|
+
};
|
|
31475
|
+
var DEFAULT_BUFFER_CAP = 5e3;
|
|
31476
|
+
var DEFAULT_SAMPLING = {
|
|
31477
|
+
debug: 0,
|
|
31478
|
+
info: 1,
|
|
31479
|
+
warn: 1,
|
|
31480
|
+
error: 1
|
|
31481
|
+
};
|
|
31482
|
+
var MAX_MSG_BYTES = 1024;
|
|
31483
|
+
var MAX_META_JSON_BYTES = 2048;
|
|
31484
|
+
var REDACT_KEY_REGEX = /token|secret|password|auth(?!or)|apikey|signsecret/i;
|
|
31485
|
+
var REDACTED_PLACEHOLDER = "[REDACTED]";
|
|
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
|
+
function shouldSample(level, config, rng2) {
|
|
31524
|
+
const rate = config[level] ?? DEFAULT_SAMPLING[level];
|
|
31525
|
+
if (rate <= 0) return false;
|
|
31526
|
+
if (rate >= 1) return true;
|
|
31527
|
+
return rng2() < rate;
|
|
31528
|
+
}
|
|
31529
|
+
var Batcher = class {
|
|
31530
|
+
constructor(deps) {
|
|
31531
|
+
this.deps = deps;
|
|
31532
|
+
}
|
|
31533
|
+
deps;
|
|
31534
|
+
queue = [];
|
|
31535
|
+
bytes = 0;
|
|
31536
|
+
droppedSinceFlush = 0;
|
|
31537
|
+
identityReady = false;
|
|
31538
|
+
timer = null;
|
|
31539
|
+
disposed = false;
|
|
31540
|
+
pendingSends = [];
|
|
31541
|
+
enqueue(record) {
|
|
31542
|
+
if (this.disposed) return;
|
|
31543
|
+
const sz = approxSize(record);
|
|
31544
|
+
while (this.queue.length >= this.deps.bufferCap) {
|
|
31545
|
+
this.queue.shift();
|
|
31546
|
+
this.droppedSinceFlush++;
|
|
31547
|
+
}
|
|
31548
|
+
this.queue.push(record);
|
|
31549
|
+
this.bytes += sz;
|
|
31550
|
+
if (!this.identityReady) return;
|
|
31551
|
+
this.maybeTrigger();
|
|
31552
|
+
}
|
|
31553
|
+
setIdentityReady(ready) {
|
|
31554
|
+
this.identityReady = ready;
|
|
31555
|
+
if (ready && this.queue.length > 0) this.maybeTrigger();
|
|
31556
|
+
}
|
|
31557
|
+
async flush() {
|
|
31558
|
+
if (this.queue.length > 0) {
|
|
31559
|
+
this.fire("flush");
|
|
31560
|
+
}
|
|
31561
|
+
await Promise.allSettled(this.pendingSends);
|
|
31562
|
+
}
|
|
31563
|
+
stats() {
|
|
31564
|
+
return { queued: this.queue.length, dropped: this.droppedSinceFlush };
|
|
31565
|
+
}
|
|
31566
|
+
async dispose() {
|
|
31567
|
+
if (this.disposed) return;
|
|
31568
|
+
this.disposed = true;
|
|
31569
|
+
if (this.timer) {
|
|
31570
|
+
clearTimeout(this.timer);
|
|
31571
|
+
this.timer = null;
|
|
31572
|
+
}
|
|
31573
|
+
await this.flush();
|
|
31574
|
+
}
|
|
31575
|
+
maybeTrigger() {
|
|
31576
|
+
const { maxRecords, maxBytes, maxWaitMs } = this.deps.batch;
|
|
31577
|
+
if (this.queue.length >= maxRecords) {
|
|
31578
|
+
this.fire("records");
|
|
31579
|
+
return;
|
|
31580
|
+
}
|
|
31581
|
+
if (this.bytes >= maxBytes) {
|
|
31582
|
+
this.fire("bytes");
|
|
31583
|
+
return;
|
|
31584
|
+
}
|
|
31585
|
+
if (this.timer == null) {
|
|
31586
|
+
this.timer = setTimeout(() => {
|
|
31587
|
+
this.timer = null;
|
|
31588
|
+
if (this.queue.length > 0 && this.identityReady) this.fire("time");
|
|
31589
|
+
}, maxWaitMs);
|
|
31590
|
+
}
|
|
31591
|
+
}
|
|
31592
|
+
fire(reason) {
|
|
31593
|
+
if (this.timer) {
|
|
31594
|
+
clearTimeout(this.timer);
|
|
31595
|
+
this.timer = null;
|
|
31596
|
+
}
|
|
31597
|
+
const records = this.queue;
|
|
31598
|
+
const droppedCarryover = this.droppedSinceFlush;
|
|
31599
|
+
this.queue = [];
|
|
31600
|
+
this.bytes = 0;
|
|
31601
|
+
this.droppedSinceFlush = 0;
|
|
31602
|
+
const p2 = this.deps.onBatch({ reason, records, droppedCarryover }).catch(() => {
|
|
31603
|
+
});
|
|
31604
|
+
this.pendingSends.push(p2);
|
|
31605
|
+
p2.finally(() => {
|
|
31606
|
+
this.pendingSends = this.pendingSends.filter((x) => x !== p2);
|
|
31607
|
+
});
|
|
31608
|
+
}
|
|
31609
|
+
};
|
|
31610
|
+
function approxSize(record) {
|
|
31611
|
+
return (record.msg?.length ?? 0) + (record.meta_json?.length ?? 0) + 200;
|
|
31612
|
+
}
|
|
31613
|
+
var BACKOFF_MS = [1e3, 2e3, 4e3];
|
|
31614
|
+
async function sendBatch(deps, batch) {
|
|
31615
|
+
const logsForSls = batch.records.map(stringifyRecord);
|
|
31616
|
+
const body = JSON.stringify({
|
|
31617
|
+
__topic__: deps.topic ?? "clawd",
|
|
31618
|
+
__source__: deps.source,
|
|
31619
|
+
__logs__: logsForSls,
|
|
31620
|
+
...batch.droppedCarryover > 0 ? { __tags__: { dropped: String(batch.droppedCarryover) } } : {}
|
|
31621
|
+
});
|
|
31622
|
+
for (let attempt = 0; attempt < BACKOFF_MS.length; attempt++) {
|
|
31623
|
+
if (attempt > 0) await sleep(BACKOFF_MS[attempt - 1]);
|
|
31624
|
+
try {
|
|
31625
|
+
const res = await deps.fetchImpl(deps.endpoint, {
|
|
31626
|
+
method: "POST",
|
|
31627
|
+
headers: { "Content-Type": "application/json" },
|
|
31628
|
+
body
|
|
31629
|
+
});
|
|
31630
|
+
if (res.status >= 200 && res.status < 300) {
|
|
31631
|
+
return { sent: batch.records.length, failed: 0 };
|
|
31632
|
+
}
|
|
31633
|
+
if (res.status >= 400 && res.status < 500) {
|
|
31634
|
+
return { sent: 0, failed: batch.records.length };
|
|
31635
|
+
}
|
|
31636
|
+
} catch {
|
|
31637
|
+
}
|
|
31638
|
+
}
|
|
31639
|
+
return { sent: 0, failed: batch.records.length };
|
|
31640
|
+
}
|
|
31641
|
+
function stringifyRecord(rec3) {
|
|
31642
|
+
const out = {};
|
|
31643
|
+
for (const [k2, v2] of Object.entries(rec3)) {
|
|
31644
|
+
if (v2 == null) continue;
|
|
31645
|
+
out[k2] = typeof v2 === "string" ? v2 : String(v2);
|
|
31646
|
+
}
|
|
31647
|
+
return out;
|
|
31648
|
+
}
|
|
31649
|
+
function sleep(ms) {
|
|
31650
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
31651
|
+
}
|
|
31652
|
+
function createLogClient(opts) {
|
|
31653
|
+
const stats = { sent: 0, dropped: 0, queued: 0, failed: 0 };
|
|
31654
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
|
|
31655
|
+
const now = opts.now ?? Date.now;
|
|
31656
|
+
const sampling = { ...DEFAULT_SAMPLING, ...opts.sampling ?? {} };
|
|
31657
|
+
const homeDir = opts.homeDir === void 0 ? null : opts.homeDir;
|
|
31658
|
+
const batchConfig = { ...DEFAULT_BATCH, ...opts.batch ?? {} };
|
|
31659
|
+
const bufferCap = opts.bufferCap ?? DEFAULT_BUFFER_CAP;
|
|
31660
|
+
let identity = opts.identity;
|
|
31661
|
+
let disposed = false;
|
|
31662
|
+
if (opts.endpoint == null) {
|
|
31663
|
+
return {
|
|
31664
|
+
push: () => {
|
|
31665
|
+
if (disposed) return;
|
|
31666
|
+
stats.dropped++;
|
|
31667
|
+
},
|
|
31668
|
+
flush: async () => {
|
|
31669
|
+
},
|
|
31670
|
+
setIdentity: (next) => {
|
|
31671
|
+
identity = next;
|
|
31672
|
+
},
|
|
31673
|
+
stats: () => ({ ...stats }),
|
|
31674
|
+
dispose: async () => {
|
|
31675
|
+
disposed = true;
|
|
31676
|
+
}
|
|
31677
|
+
};
|
|
31678
|
+
}
|
|
31679
|
+
const endpoint = opts.endpoint;
|
|
31680
|
+
const batcher = new Batcher({
|
|
31681
|
+
batch: batchConfig,
|
|
31682
|
+
bufferCap,
|
|
31683
|
+
now,
|
|
31684
|
+
onBatch: async (b2) => {
|
|
31685
|
+
const res = await sendBatch({ endpoint, source: opts.source, fetchImpl }, b2);
|
|
31686
|
+
stats.sent += res.sent;
|
|
31687
|
+
stats.failed += res.failed;
|
|
31688
|
+
}
|
|
31689
|
+
});
|
|
31690
|
+
batcher.setIdentityReady(identity != null);
|
|
31691
|
+
return {
|
|
31692
|
+
push(input) {
|
|
31693
|
+
if (disposed) return;
|
|
31694
|
+
try {
|
|
31695
|
+
if (!shouldSample(input.level, sampling, Math.random)) {
|
|
31696
|
+
stats.dropped++;
|
|
31697
|
+
return;
|
|
31698
|
+
}
|
|
31699
|
+
const record = buildRecord(input, identity, opts.source, homeDir, now);
|
|
31700
|
+
batcher.enqueue(record);
|
|
31701
|
+
} catch {
|
|
31702
|
+
}
|
|
31703
|
+
},
|
|
31704
|
+
async flush() {
|
|
31705
|
+
try {
|
|
31706
|
+
await batcher.flush();
|
|
31707
|
+
} catch {
|
|
31708
|
+
}
|
|
31709
|
+
},
|
|
31710
|
+
setIdentity(next) {
|
|
31711
|
+
identity = next;
|
|
31712
|
+
batcher.setIdentityReady(next != null);
|
|
31713
|
+
},
|
|
31714
|
+
stats() {
|
|
31715
|
+
const bs = batcher.stats();
|
|
31716
|
+
return { ...stats, queued: bs.queued, dropped: stats.dropped + bs.dropped };
|
|
31717
|
+
},
|
|
31718
|
+
async dispose() {
|
|
31719
|
+
disposed = true;
|
|
31720
|
+
try {
|
|
31721
|
+
await batcher.dispose();
|
|
31722
|
+
} catch {
|
|
31723
|
+
}
|
|
31724
|
+
}
|
|
31725
|
+
};
|
|
31726
|
+
}
|
|
31727
|
+
function buildRecord(input, identity, source, homeDir, now) {
|
|
31728
|
+
const cleanedMeta = input.meta ? redactMeta(input.meta, homeDir) : void 0;
|
|
31729
|
+
const meta_json = cleanedMeta ? JSON.stringify(cleanedMeta) : void 0;
|
|
31730
|
+
return {
|
|
31731
|
+
ts: input.ts ?? now(),
|
|
31732
|
+
source,
|
|
31733
|
+
level: input.level,
|
|
31734
|
+
msg: truncateMsg(input.msg),
|
|
31735
|
+
ownerPrincipalId: identity?.ownerPrincipalId ?? "__pending__",
|
|
31736
|
+
deviceId: identity?.deviceId ?? "__pending__",
|
|
31737
|
+
appVersion: identity?.appVersion ?? "__pending__",
|
|
31738
|
+
daemonVersion: identity?.daemonVersion,
|
|
31739
|
+
os: identity?.os ?? "unknown",
|
|
31740
|
+
meta_json,
|
|
31741
|
+
sessionId: input.sessionId
|
|
31742
|
+
};
|
|
31743
|
+
}
|
|
31283
31744
|
|
|
31284
31745
|
// src/session/store-factory.ts
|
|
31285
31746
|
var path5 = __toESM(require("path"), 1);
|
|
@@ -31486,55 +31947,6 @@ var SessionStoreFactory = class {
|
|
|
31486
31947
|
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
31487
31948
|
var import_node_path6 = __toESM(require("path"), 1);
|
|
31488
31949
|
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
|
|
31538
31950
|
init_protocol();
|
|
31539
31951
|
|
|
31540
31952
|
// src/tools/guest-settings.ts
|
|
@@ -31659,6 +32071,32 @@ function buildConnectionPrompt(args) {
|
|
|
31659
32071
|
return result;
|
|
31660
32072
|
}
|
|
31661
32073
|
|
|
32074
|
+
// src/dispatch/system-prompt.ts
|
|
32075
|
+
var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
|
|
32076
|
+
|
|
32077
|
+
\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
|
|
32078
|
+
|
|
32079
|
+
- \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
|
|
32080
|
+
- \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
|
|
32081
|
+
|
|
32082
|
+
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
|
|
32083
|
+
|
|
32084
|
+
- **\u4E0D\u8981**\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF08\u4F60\u4E0D\u662F\u90A3\u4E2A persona\uFF09
|
|
32085
|
+
- **\u4E0D\u8981** in-place \u6A21\u4EFF\u5BF9\u65B9\u4EBA\u683C \u2014\u2014 dispatch \u662F\u771F\u5207\u5230\u53E6\u4E00\u4E2A\u72EC\u7ACB session
|
|
32086
|
+
- \u4E00\u53E5\u8BDD\u91CC\u591A\u4E2A \`@persona/<id>\` \u65F6\u9009\u7B2C\u4E00\u4E2A\uFF08tool \u4E00\u6B21\u53EA\u5904\u7406\u4E00\u4E2A target\uFF09
|
|
32087
|
+
- \u59D4\u6D3E\u5931\u8D25\uFF08tool_result.is_error=true\uFF09\u65F6\u5982\u5B9E\u544A\u8BC9\u7528\u6237\u539F\u56E0\uFF0C**\u4E0D\u8981\u91CD\u8BD5**
|
|
32088
|
+
|
|
32089
|
+
## \u88AB dispatch \u63A5\u5230\u4EFB\u52A1
|
|
32090
|
+
|
|
32091
|
+
\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
|
|
32092
|
+
|
|
32093
|
+
- \u4EFB\u52A1\u5728 \`Task:\` \u6BB5
|
|
32094
|
+
- \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
|
|
32095
|
+
- \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`mcp__clawd-dispatch__personaDispatchComplete\` \u62A5\u544A\u7ED3\u679C\uFF1A
|
|
32096
|
+
- \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
|
|
32097
|
+
- \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "..." }\`
|
|
32098
|
+
- \u62A5\u544A\u5B8C\u540E\u4F60\u7684 session \u5C31\u7ED3\u675F\u4E86\uFF0C\u4E0D\u8981\u7EE7\u7EED\u8F93\u51FA`;
|
|
32099
|
+
|
|
31662
32100
|
// src/session/reducer.ts
|
|
31663
32101
|
function cloneState(s) {
|
|
31664
32102
|
return {
|
|
@@ -31737,6 +32175,9 @@ function buildSpawnContext(state, deps) {
|
|
|
31737
32175
|
env.CLAWD_SESSION_ID = file.sessionId;
|
|
31738
32176
|
const daemonUrl = deps.getDaemonUrl?.() ?? null;
|
|
31739
32177
|
if (daemonUrl) env.CLAWD_DAEMON_URL = daemonUrl;
|
|
32178
|
+
const dispatchId = deps.lookupDispatchByBSessionId?.(file.sessionId);
|
|
32179
|
+
if (dispatchId) env.CLAWD_DISPATCH_ID = dispatchId;
|
|
32180
|
+
const dispatchMcpConfigPath2 = deps.getDispatchMcpConfigPath?.() ?? null;
|
|
31740
32181
|
const ctx = {
|
|
31741
32182
|
cwd: file.cwd,
|
|
31742
32183
|
toolSessionId: file.toolSessionId,
|
|
@@ -31746,7 +32187,10 @@ function buildSpawnContext(state, deps) {
|
|
|
31746
32187
|
env,
|
|
31747
32188
|
// Phase 2 capability platform (plan §3): personaRoot 透传给 buildSpawnArgs;
|
|
31748
32189
|
// 内部 shouldSandbox(cwd, personaRoot) 决定是否注入 --settings sandbox-settings.
|
|
31749
|
-
personaRoot: deps.personaRoot
|
|
32190
|
+
personaRoot: deps.personaRoot,
|
|
32191
|
+
// Persona dispatch:所有 session(A 和 B)都挂同一份 dispatch.mcp.json,让两边的 cc
|
|
32192
|
+
// 都能看到 personaDispatch / personaDispatchComplete tool;按 env 区分实际行为。
|
|
32193
|
+
dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0
|
|
31750
32194
|
};
|
|
31751
32195
|
const meta = state.subSessionMeta;
|
|
31752
32196
|
if (meta?.personaMode) {
|
|
@@ -31757,6 +32201,9 @@ function buildSpawnContext(state, deps) {
|
|
|
31757
32201
|
workDir: meta.userWorkDir
|
|
31758
32202
|
});
|
|
31759
32203
|
}
|
|
32204
|
+
if (dispatchMcpConfigPath2) {
|
|
32205
|
+
ctx.extraSystemPrompt = (ctx.extraSystemPrompt ? ctx.extraSystemPrompt + "\n\n" : "") + DISPATCH_SYSTEM_PROMPT_HINT;
|
|
32206
|
+
}
|
|
31760
32207
|
if (meta?.extraSettings) {
|
|
31761
32208
|
ctx.extraSettings = meta.extraSettings;
|
|
31762
32209
|
}
|
|
@@ -32422,35 +32869,6 @@ function startRecorder(opts) {
|
|
|
32422
32869
|
};
|
|
32423
32870
|
}
|
|
32424
32871
|
|
|
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
|
-
|
|
32454
32872
|
// src/session/runner.ts
|
|
32455
32873
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
32456
32874
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -32499,7 +32917,6 @@ var SessionRunner = class {
|
|
|
32499
32917
|
}
|
|
32500
32918
|
// 外部推送 input 到 reducer,然后执行产出的 effects
|
|
32501
32919
|
input(inputMsg) {
|
|
32502
|
-
const personaStore = this.hooks.personaStore;
|
|
32503
32920
|
const adapter = this.hooks.adapter;
|
|
32504
32921
|
const deps = {
|
|
32505
32922
|
// file-sharing (spec §6 PR 3):在 stdout-line 解析时同步观察 file-edit 工具事件,
|
|
@@ -32509,20 +32926,10 @@ var SessionRunner = class {
|
|
|
32509
32926
|
if (this.hooks.onFileEdit) this.observeForFileEdit(events);
|
|
32510
32927
|
return events;
|
|
32511
32928
|
},
|
|
32512
|
-
//
|
|
32513
|
-
//
|
|
32514
|
-
//
|
|
32515
|
-
|
|
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
|
-
},
|
|
32929
|
+
// Persona dispatch (Task 9):原 in-place `@persona/<id>` 注入路径已删,cc 自己看到字面
|
|
32930
|
+
// token 会调 personaDispatch MCP tool 委派(dispatch.mcp.json 通过 cc --mcp-config 加载,
|
|
32931
|
+
// CLAUDE.md 教 cc 触发条件)。encodeStdin 现在是 adapter 的简单 passthrough。
|
|
32932
|
+
encodeStdin: (t, ctx) => adapter.encodeStdin(t, ctx) ?? "",
|
|
32526
32933
|
bufferCap: this.hooks.bufferCap ?? 500,
|
|
32527
32934
|
now: this.hooks.now ?? Date.now,
|
|
32528
32935
|
resolveContextWindow: this.hooks.resolveContextWindow,
|
|
@@ -32532,6 +32939,10 @@ var SessionRunner = class {
|
|
|
32532
32939
|
// 单栏 refactor (spec 2026-06-02 §5.1): cc 子进程 env 注入 CLAWD_DAEMON_URL,让 assistant
|
|
32533
32940
|
// curl daemon HTTP RPC adapter (/api/rpc/<method>) 触发管理操作。null = HTTP adapter 未启。
|
|
32534
32941
|
getDaemonUrl: this.hooks.getDaemonUrl,
|
|
32942
|
+
// Persona dispatch:透传 dispatch.mcp.json 路径闭包 + B→dispatchId 反查闭包。
|
|
32943
|
+
// 见 reducer.buildSpawnContext 注 CLAWD_DISPATCH_ID env / 派生 SpawnContext.dispatchMcpConfigPath
|
|
32944
|
+
getDispatchMcpConfigPath: this.hooks.getDispatchMcpConfigPath,
|
|
32945
|
+
lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
|
|
32535
32946
|
// ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
|
|
32536
32947
|
mode: this.hooks.mode,
|
|
32537
32948
|
// [RG-DBG] 注入 logger 让 reducer rgDbg 走 pino 进 clawd.log;定位完跟 rgDbg 一起删
|
|
@@ -32991,6 +33402,22 @@ function nowIso2(deps) {
|
|
|
32991
33402
|
function newSessionId() {
|
|
32992
33403
|
return v4_default().replace(/-/g, "").slice(0, 16);
|
|
32993
33404
|
}
|
|
33405
|
+
function buildDispatchTaskPack(args) {
|
|
33406
|
+
return `[Dispatched from owner \u2014 another persona session\u59D4\u6D3E\u7ED9\u4F60\u6267\u884C\u4EFB\u52A1]
|
|
33407
|
+
|
|
33408
|
+
Task:
|
|
33409
|
+
${args.prompt}
|
|
33410
|
+
|
|
33411
|
+
Source conversation (jsonl, CC stream-json format, one message per line):
|
|
33412
|
+
${args.sourceJsonlPath}
|
|
33413
|
+
You may read this file with your Read tool to understand context. You do not have to read it all.
|
|
33414
|
+
|
|
33415
|
+
When done, call the MCP tool \`mcp__clawd-dispatch__personaDispatchComplete\` with your result:
|
|
33416
|
+
- Success: { text: "...", filePaths?: ["abs/path", ...] }
|
|
33417
|
+
- Failure: { isFailure: true, reason: "..." }
|
|
33418
|
+
|
|
33419
|
+
dispatchId for this task: ${args.dispatchId}`;
|
|
33420
|
+
}
|
|
32994
33421
|
function derivePersonaSpawnCwd(file, personaRoot) {
|
|
32995
33422
|
const personaId = file.ownerPersonaId;
|
|
32996
33423
|
if (!personaId) return file.cwd;
|
|
@@ -33288,7 +33715,8 @@ var SessionManager = class {
|
|
|
33288
33715
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
33289
33716
|
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
33290
33717
|
dataDir: this.deps.dataDir,
|
|
33291
|
-
personaStore
|
|
33718
|
+
// personaStore 不再透给 runner hooks(in-place mention 注入路径已删,runner 不用);
|
|
33719
|
+
// manager 自身的 sandbox 派生仍直接读 this.deps.personaStore。
|
|
33292
33720
|
ownerDisplayName: this.deps.ownerDisplayName,
|
|
33293
33721
|
// Phase 2 capability platform (plan §3): 透传 personaRoot, buildSpawnArgs 据
|
|
33294
33722
|
// cwd 是否在 personaRoot 下自动决定是否注入 --settings sandbox-settings.json.
|
|
@@ -33296,6 +33724,10 @@ var SessionManager = class {
|
|
|
33296
33724
|
// 单栏 refactor (spec 2026-06-02 §5.1): 透传 daemon HTTP RPC base URL 闭包,
|
|
33297
33725
|
// reducer 把它注入 cc 子进程 env CLAWD_DAEMON_URL.
|
|
33298
33726
|
getDaemonUrl: this.deps.getDaemonUrl,
|
|
33727
|
+
// Persona dispatch (Task 7): dispatch.mcp.json 路径 + B sessionId → dispatchId 反查
|
|
33728
|
+
// 闭包透传给 reducer,让 cc spawn 加 --mcp-config flag + B session 注 CLAWD_DISPATCH_ID env.
|
|
33729
|
+
getDispatchMcpConfigPath: this.deps.dispatchMcpConfigPath ? () => this.deps.dispatchMcpConfigPath ?? null : void 0,
|
|
33730
|
+
lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
|
|
33299
33731
|
// file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
|
|
33300
33732
|
onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
|
|
33301
33733
|
scope,
|
|
@@ -33511,15 +33943,20 @@ var SessionManager = class {
|
|
|
33511
33943
|
// 强制走 deps.store(即 default scope),不走 scopeForFile:mirror 物理落 default 即可。
|
|
33512
33944
|
// 远端 creator / origin 字段原值保留(不被本机 ctx 派生覆写)。
|
|
33513
33945
|
//
|
|
33514
|
-
// strip 远端 personaId:mirror SessionFile
|
|
33515
|
-
//
|
|
33516
|
-
//
|
|
33946
|
+
// strip 远端 personaId / dispatchedFromSessionId:mirror SessionFile 上这两个字段都指向
|
|
33947
|
+
// 朋友 daemon 上的本地 id,本机不持有对应 persona / 源 session。留着会让按这些字段反查的
|
|
33948
|
+
// 本机消费者(MyPersonasSection 按 ownerPersonaId 反查 persona、sidebar 按
|
|
33949
|
+
// dispatchedFromSessionId 折叠 sub-session)走错分支。写入前清掉。#750 一族防线。
|
|
33517
33950
|
//
|
|
33518
33951
|
// 与 manager.create / manager.update 区别:
|
|
33519
33952
|
// - 不走 newRunner / attachObserver / cwd 校验(mirror 是纯 metadata 层)
|
|
33520
33953
|
// - 不发 session:info 帧(manager.create / .update 通过 reducer/wireCollector 发 push)
|
|
33521
33954
|
mirrorUpsert(file) {
|
|
33522
|
-
const {
|
|
33955
|
+
const {
|
|
33956
|
+
ownerPersonaId: _strippedPid,
|
|
33957
|
+
dispatchedFromSessionId: _strippedDsp,
|
|
33958
|
+
...rest
|
|
33959
|
+
} = file;
|
|
33523
33960
|
return this.deps.store.write(rest);
|
|
33524
33961
|
}
|
|
33525
33962
|
// mirror peer sessions:删本机 mirror SessionFile。mirror 一律落 default(mirrorUpsert
|
|
@@ -34104,6 +34541,66 @@ var SessionManager = class {
|
|
|
34104
34541
|
this.runners.set(file.sessionId, runner);
|
|
34105
34542
|
return runner;
|
|
34106
34543
|
}
|
|
34544
|
+
/**
|
|
34545
|
+
* Persona dispatch: 启动 B session 并投递任务包当第一条 user message。
|
|
34546
|
+
*
|
|
34547
|
+
* - 复用 persona-owner 创建路径(cwd=personaDir、scope=persona-owner、不沙箱)
|
|
34548
|
+
* - SessionFile 上写 dispatchedFromSessionId 关联回 A(UI 折叠用;mirror 一侧 strip)
|
|
34549
|
+
* - 跟 PersonaDispatchManager 双向登记 dispatchId ↔ B sessionId,让后续 reducer
|
|
34550
|
+
* buildSpawnContext 能反查到 dispatchId 注 CLAWD_DISPATCH_ID env
|
|
34551
|
+
* - 投 inject-owner-text 任务包;包尾教 B 用 personaDispatchComplete tool 回传
|
|
34552
|
+
*
|
|
34553
|
+
* cwd 派生与 SessionManager.create 的 owner persona 路径一致(derivePersonaSpawnCwd)。
|
|
34554
|
+
*/
|
|
34555
|
+
createDispatchedSession(args) {
|
|
34556
|
+
if (!this.deps.personaRoot) {
|
|
34557
|
+
throw new Error("createDispatchedSession: personaRoot missing in ManagerDeps");
|
|
34558
|
+
}
|
|
34559
|
+
if (!this.deps.personaDispatchManager) {
|
|
34560
|
+
throw new Error("createDispatchedSession: personaDispatchManager missing in ManagerDeps");
|
|
34561
|
+
}
|
|
34562
|
+
const sessionId = newSessionId();
|
|
34563
|
+
const scope = {
|
|
34564
|
+
kind: "persona",
|
|
34565
|
+
personaId: args.targetPersona,
|
|
34566
|
+
mode: "owner"
|
|
34567
|
+
};
|
|
34568
|
+
const cwd = import_node_path6.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
|
|
34569
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34570
|
+
const file = {
|
|
34571
|
+
sessionId,
|
|
34572
|
+
cwd,
|
|
34573
|
+
tool: "claude",
|
|
34574
|
+
ownerPersonaId: args.targetPersona,
|
|
34575
|
+
dispatchedFromSessionId: args.sourceSessionId,
|
|
34576
|
+
createdAt: now,
|
|
34577
|
+
updatedAt: now
|
|
34578
|
+
};
|
|
34579
|
+
this.storeFor(scope).write(file);
|
|
34580
|
+
this.deps.personaDispatchManager.registerBSession(args.dispatchId, sessionId);
|
|
34581
|
+
this.deps.logger?.info("dispatch.createDispatchedSession.file-written", {
|
|
34582
|
+
dispatchId: args.dispatchId,
|
|
34583
|
+
bSessionId: sessionId,
|
|
34584
|
+
targetPersona: args.targetPersona,
|
|
34585
|
+
cwd
|
|
34586
|
+
});
|
|
34587
|
+
const runner = this.ensureRunnerForScope(file, scope);
|
|
34588
|
+
this.deps.logger?.info("dispatch.createDispatchedSession.runner-ready", {
|
|
34589
|
+
dispatchId: args.dispatchId,
|
|
34590
|
+
bSessionId: sessionId
|
|
34591
|
+
});
|
|
34592
|
+
const taskPack = buildDispatchTaskPack({
|
|
34593
|
+
prompt: args.prompt,
|
|
34594
|
+
sourceJsonlPath: args.sourceJsonlPath,
|
|
34595
|
+
dispatchId: args.dispatchId
|
|
34596
|
+
});
|
|
34597
|
+
runner.input({ kind: "command", command: { kind: "send", text: taskPack } });
|
|
34598
|
+
this.deps.logger?.info("dispatch.createDispatchedSession.task-pack-sent", {
|
|
34599
|
+
dispatchId: args.dispatchId,
|
|
34600
|
+
bSessionId: sessionId
|
|
34601
|
+
});
|
|
34602
|
+
return { sessionId };
|
|
34603
|
+
}
|
|
34107
34604
|
/**
|
|
34108
34605
|
* 老板插话:把 'inject-owner-text' input 喂给对应 runner,
|
|
34109
34606
|
* runner 不存在时按 scope 懒创建。
|
|
@@ -35620,8 +36117,8 @@ function turnStartInput(text) {
|
|
|
35620
36117
|
const items = [];
|
|
35621
36118
|
let leftover = text;
|
|
35622
36119
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
35623
|
-
const [marker, name,
|
|
35624
|
-
items.push({ type: "skill", name, path:
|
|
36120
|
+
const [marker, name, path59] = m2;
|
|
36121
|
+
items.push({ type: "skill", name, path: path59 });
|
|
35625
36122
|
leftover = leftover.replace(marker, "");
|
|
35626
36123
|
}
|
|
35627
36124
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -36272,7 +36769,7 @@ init_claude_history();
|
|
|
36272
36769
|
|
|
36273
36770
|
// src/pty/pty-child-process.ts
|
|
36274
36771
|
var import_node_events = require("events");
|
|
36275
|
-
var
|
|
36772
|
+
var import_node_stream2 = require("stream");
|
|
36276
36773
|
var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
36277
36774
|
constructor(pty, opts = {}) {
|
|
36278
36775
|
super();
|
|
@@ -36301,7 +36798,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36301
36798
|
pty.write(data);
|
|
36302
36799
|
}
|
|
36303
36800
|
};
|
|
36304
|
-
this.stdin = new
|
|
36801
|
+
this.stdin = new import_node_stream2.Writable({
|
|
36305
36802
|
decodeStrings: false,
|
|
36306
36803
|
write: (chunk, _enc, cb) => {
|
|
36307
36804
|
const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
@@ -36320,7 +36817,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36320
36817
|
}
|
|
36321
36818
|
}
|
|
36322
36819
|
});
|
|
36323
|
-
this.stdout = new
|
|
36820
|
+
this.stdout = new import_node_stream2.Readable({ read() {
|
|
36324
36821
|
} });
|
|
36325
36822
|
pty.onData((data) => {
|
|
36326
36823
|
if (!this.firstDataLogged) {
|
|
@@ -36333,7 +36830,7 @@ var PtyChildProcess = class extends import_node_events.EventEmitter {
|
|
|
36333
36830
|
}
|
|
36334
36831
|
this.stdout.push(Buffer.from(data, "utf8"));
|
|
36335
36832
|
});
|
|
36336
|
-
this.stderr = new
|
|
36833
|
+
this.stderr = new import_node_stream2.Readable({ read() {
|
|
36337
36834
|
} });
|
|
36338
36835
|
pty.onExit(({ exitCode, signal }) => {
|
|
36339
36836
|
this.exitCode = exitCode;
|
|
@@ -36848,6 +37345,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
36848
37345
|
if (ctx.addDirs) {
|
|
36849
37346
|
for (const dir of ctx.addDirs) args.push("--add-dir", dir);
|
|
36850
37347
|
}
|
|
37348
|
+
if (ctx.dispatchMcpConfigPath) {
|
|
37349
|
+
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
37350
|
+
}
|
|
36851
37351
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
36852
37352
|
return args;
|
|
36853
37353
|
}
|
|
@@ -36865,6 +37365,155 @@ function jsonlExistsForCtx(ctx) {
|
|
|
36865
37365
|
// src/index.ts
|
|
36866
37366
|
init_claude_history();
|
|
36867
37367
|
|
|
37368
|
+
// src/dispatch/manager.ts
|
|
37369
|
+
function defer() {
|
|
37370
|
+
let resolve6;
|
|
37371
|
+
const promise = new Promise((r) => {
|
|
37372
|
+
resolve6 = r;
|
|
37373
|
+
});
|
|
37374
|
+
return { promise, resolve: resolve6 };
|
|
37375
|
+
}
|
|
37376
|
+
var PersonaDispatchManager = class {
|
|
37377
|
+
constructor(deps) {
|
|
37378
|
+
this.deps = deps;
|
|
37379
|
+
}
|
|
37380
|
+
deps;
|
|
37381
|
+
map = /* @__PURE__ */ new Map();
|
|
37382
|
+
start(args) {
|
|
37383
|
+
const dispatchId = this.deps.genId();
|
|
37384
|
+
this.map.set(dispatchId, {
|
|
37385
|
+
dispatchId,
|
|
37386
|
+
sourceSessionId: args.sourceSessionId,
|
|
37387
|
+
targetPersona: args.targetPersona,
|
|
37388
|
+
waiters: [],
|
|
37389
|
+
outcome: null
|
|
37390
|
+
});
|
|
37391
|
+
return { dispatchId };
|
|
37392
|
+
}
|
|
37393
|
+
get(dispatchId) {
|
|
37394
|
+
return this.map.get(dispatchId);
|
|
37395
|
+
}
|
|
37396
|
+
async wait(dispatchId) {
|
|
37397
|
+
const state = this.map.get(dispatchId);
|
|
37398
|
+
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37399
|
+
if (state.outcome) return state.outcome;
|
|
37400
|
+
const d = defer();
|
|
37401
|
+
state.waiters.push(d);
|
|
37402
|
+
return d.promise;
|
|
37403
|
+
}
|
|
37404
|
+
complete(dispatchId, outcome) {
|
|
37405
|
+
const state = this.map.get(dispatchId);
|
|
37406
|
+
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37407
|
+
state.outcome = outcome;
|
|
37408
|
+
const waiters = state.waiters;
|
|
37409
|
+
state.waiters = [];
|
|
37410
|
+
for (const w2 of waiters) w2.resolve(outcome);
|
|
37411
|
+
}
|
|
37412
|
+
/** SessionManager 在 createDispatchedSession 时调,建立 dispatchId → B sessionId 映射 */
|
|
37413
|
+
registerBSession(dispatchId, bSessionId) {
|
|
37414
|
+
const state = this.map.get(dispatchId);
|
|
37415
|
+
if (!state) throw new Error(`unknown dispatchId: ${dispatchId}`);
|
|
37416
|
+
state.bSessionId = bSessionId;
|
|
37417
|
+
}
|
|
37418
|
+
/** reducer buildSpawnContext 调,按 B 的 sessionId 反查 dispatchId(用于注 CLAWD_DISPATCH_ID env) */
|
|
37419
|
+
lookupDispatchByBSessionId(bSessionId) {
|
|
37420
|
+
for (const state of this.map.values()) {
|
|
37421
|
+
if (state.bSessionId === bSessionId) return state.dispatchId;
|
|
37422
|
+
}
|
|
37423
|
+
return void 0;
|
|
37424
|
+
}
|
|
37425
|
+
};
|
|
37426
|
+
|
|
37427
|
+
// src/dispatch/mcp-config.ts
|
|
37428
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
37429
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
37430
|
+
function dispatchMcpConfigPath(dataDir) {
|
|
37431
|
+
return import_node_path10.default.join(dataDir, "dispatch.mcp.json");
|
|
37432
|
+
}
|
|
37433
|
+
function writeDispatchMcpConfig(args) {
|
|
37434
|
+
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
37435
|
+
const content = {
|
|
37436
|
+
_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",
|
|
37437
|
+
mcpServers: {
|
|
37438
|
+
"clawd-dispatch": {
|
|
37439
|
+
type: "stdio",
|
|
37440
|
+
command: "node",
|
|
37441
|
+
args: [args.serverScriptPath],
|
|
37442
|
+
...args.logPath ? { env: { CLAWD_DISPATCH_LOG: args.logPath } } : {}
|
|
37443
|
+
}
|
|
37444
|
+
}
|
|
37445
|
+
};
|
|
37446
|
+
import_node_fs12.default.mkdirSync(args.dataDir, { recursive: true });
|
|
37447
|
+
import_node_fs12.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
37448
|
+
return cfgPath;
|
|
37449
|
+
}
|
|
37450
|
+
|
|
37451
|
+
// src/handlers/persona-dispatch.ts
|
|
37452
|
+
init_protocol();
|
|
37453
|
+
function buildPersonaDispatchHandlers(deps) {
|
|
37454
|
+
const { personaDispatchManager: mgr, spawnB, logger } = deps;
|
|
37455
|
+
const run = async (frame) => {
|
|
37456
|
+
const { type: _t, requestId: _r, ...rest } = frame;
|
|
37457
|
+
const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
|
|
37458
|
+
const args = DispatchRunArgsSchema.parse(rest);
|
|
37459
|
+
if (!sourceSessionId) {
|
|
37460
|
+
throw new Error(
|
|
37461
|
+
"personaDispatch:run requires sessionId (caller must pass x-clawd-session-id header)"
|
|
37462
|
+
);
|
|
37463
|
+
}
|
|
37464
|
+
const { dispatchId } = mgr.start({
|
|
37465
|
+
sourceSessionId,
|
|
37466
|
+
targetPersona: args.targetPersona
|
|
37467
|
+
});
|
|
37468
|
+
logger?.info("dispatch.run.received", {
|
|
37469
|
+
dispatchId,
|
|
37470
|
+
sourceSessionId,
|
|
37471
|
+
targetPersona: args.targetPersona,
|
|
37472
|
+
promptLen: args.prompt.length
|
|
37473
|
+
});
|
|
37474
|
+
void spawnB({
|
|
37475
|
+
dispatchId,
|
|
37476
|
+
sourceSessionId,
|
|
37477
|
+
targetPersona: args.targetPersona,
|
|
37478
|
+
prompt: args.prompt
|
|
37479
|
+
}).then(() => {
|
|
37480
|
+
logger?.info("dispatch.spawnB.ok", { dispatchId });
|
|
37481
|
+
}).catch((err) => {
|
|
37482
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
37483
|
+
logger?.warn("dispatch.spawnB.failed", { dispatchId, reason });
|
|
37484
|
+
mgr.complete(dispatchId, {
|
|
37485
|
+
kind: "failure",
|
|
37486
|
+
reason: `failed to spawn B: ${reason}`
|
|
37487
|
+
});
|
|
37488
|
+
});
|
|
37489
|
+
logger?.info("dispatch.run.waiting", { dispatchId });
|
|
37490
|
+
const outcome = await mgr.wait(dispatchId);
|
|
37491
|
+
logger?.info("dispatch.run.resolved", {
|
|
37492
|
+
dispatchId,
|
|
37493
|
+
outcomeKind: outcome.kind
|
|
37494
|
+
});
|
|
37495
|
+
return {
|
|
37496
|
+
response: { type: "personaDispatch:run:ok", outcome }
|
|
37497
|
+
};
|
|
37498
|
+
};
|
|
37499
|
+
const complete = async (frame) => {
|
|
37500
|
+
const { type: _t, requestId: _r, ...rest } = frame;
|
|
37501
|
+
const args = DispatchCompleteArgsSchema.parse(rest);
|
|
37502
|
+
logger?.info("dispatch.complete.received", {
|
|
37503
|
+
dispatchId: args.dispatchId,
|
|
37504
|
+
outcomeKind: args.outcome.kind
|
|
37505
|
+
});
|
|
37506
|
+
mgr.complete(args.dispatchId, args.outcome);
|
|
37507
|
+
return {
|
|
37508
|
+
response: { type: "personaDispatch:complete:ok" }
|
|
37509
|
+
};
|
|
37510
|
+
};
|
|
37511
|
+
return {
|
|
37512
|
+
"personaDispatch:run": run,
|
|
37513
|
+
"personaDispatch:complete": complete
|
|
37514
|
+
};
|
|
37515
|
+
}
|
|
37516
|
+
|
|
36868
37517
|
// src/tools/codex-history.ts
|
|
36869
37518
|
var import_node_child_process5 = require("child_process");
|
|
36870
37519
|
var DEFAULT_TIMEOUT_MS = 8e3;
|
|
@@ -37051,13 +37700,13 @@ function mapSkillsListResponse(res) {
|
|
|
37051
37700
|
const r = s ?? {};
|
|
37052
37701
|
const name = str3(r.name);
|
|
37053
37702
|
if (!name) continue;
|
|
37054
|
-
const
|
|
37703
|
+
const path59 = str3(r.path);
|
|
37055
37704
|
const description = str3(r.description);
|
|
37056
37705
|
const isPlugin = name.includes(":");
|
|
37057
37706
|
out.push({
|
|
37058
37707
|
name,
|
|
37059
37708
|
source: isPlugin ? "plugin" : "project",
|
|
37060
|
-
...
|
|
37709
|
+
...path59 ? { path: path59 } : {},
|
|
37061
37710
|
...description ? { description } : {},
|
|
37062
37711
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
37063
37712
|
});
|
|
@@ -37096,23 +37745,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
37096
37745
|
}
|
|
37097
37746
|
|
|
37098
37747
|
// src/workspace/browser.ts
|
|
37099
|
-
var
|
|
37748
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
37100
37749
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
37101
|
-
var
|
|
37750
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
37102
37751
|
init_protocol();
|
|
37103
37752
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
37104
37753
|
function resolveInsideCwd(cwd, subpath) {
|
|
37105
|
-
const absCwd =
|
|
37106
|
-
const joined =
|
|
37107
|
-
const rel =
|
|
37108
|
-
if (rel.startsWith("..") ||
|
|
37754
|
+
const absCwd = import_node_path11.default.resolve(cwd);
|
|
37755
|
+
const joined = import_node_path11.default.resolve(absCwd, subpath ?? ".");
|
|
37756
|
+
const rel = import_node_path11.default.relative(absCwd, joined);
|
|
37757
|
+
if (rel.startsWith("..") || import_node_path11.default.isAbsolute(rel)) {
|
|
37109
37758
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
37110
37759
|
}
|
|
37111
37760
|
return joined;
|
|
37112
37761
|
}
|
|
37113
37762
|
function ensureCwd(cwd) {
|
|
37114
37763
|
try {
|
|
37115
|
-
const stat =
|
|
37764
|
+
const stat = import_node_fs13.default.statSync(cwd);
|
|
37116
37765
|
if (!stat.isDirectory()) {
|
|
37117
37766
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
37118
37767
|
}
|
|
@@ -37126,7 +37775,7 @@ var WorkspaceBrowser = class {
|
|
|
37126
37775
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
|
|
37127
37776
|
ensureCwd(cwd);
|
|
37128
37777
|
const full = resolveInsideCwd(cwd, args.path);
|
|
37129
|
-
const dirents =
|
|
37778
|
+
const dirents = import_node_fs13.default.readdirSync(full, { withFileTypes: true });
|
|
37130
37779
|
const entries = [];
|
|
37131
37780
|
for (const d of dirents) {
|
|
37132
37781
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -37136,7 +37785,7 @@ var WorkspaceBrowser = class {
|
|
|
37136
37785
|
mtime: ""
|
|
37137
37786
|
};
|
|
37138
37787
|
try {
|
|
37139
|
-
const st =
|
|
37788
|
+
const st = import_node_fs13.default.statSync(import_node_path11.default.join(full, d.name));
|
|
37140
37789
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
37141
37790
|
if (d.isFile()) entry.size = st.size;
|
|
37142
37791
|
} catch {
|
|
@@ -37152,14 +37801,14 @@ var WorkspaceBrowser = class {
|
|
|
37152
37801
|
read(args) {
|
|
37153
37802
|
ensureCwd(args.cwd);
|
|
37154
37803
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
37155
|
-
const st =
|
|
37804
|
+
const st = import_node_fs13.default.statSync(full);
|
|
37156
37805
|
if (!st.isFile()) {
|
|
37157
37806
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
37158
37807
|
}
|
|
37159
37808
|
if (st.size > MAX_FILE_BYTES) {
|
|
37160
37809
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
37161
37810
|
}
|
|
37162
|
-
const buf =
|
|
37811
|
+
const buf = import_node_fs13.default.readFileSync(full);
|
|
37163
37812
|
const isBinary = buf.includes(0);
|
|
37164
37813
|
if (isBinary) {
|
|
37165
37814
|
return {
|
|
@@ -37181,20 +37830,20 @@ var WorkspaceBrowser = class {
|
|
|
37181
37830
|
};
|
|
37182
37831
|
|
|
37183
37832
|
// src/skills/agents-scanner.ts
|
|
37184
|
-
var
|
|
37833
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
37185
37834
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
37186
|
-
var
|
|
37835
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37187
37836
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
37188
37837
|
function isDirLikeSync2(p2) {
|
|
37189
37838
|
try {
|
|
37190
|
-
return
|
|
37839
|
+
return import_node_fs14.default.statSync(p2).isDirectory();
|
|
37191
37840
|
} catch {
|
|
37192
37841
|
return false;
|
|
37193
37842
|
}
|
|
37194
37843
|
}
|
|
37195
37844
|
function fileExistsSync(p2) {
|
|
37196
37845
|
try {
|
|
37197
|
-
return
|
|
37846
|
+
return import_node_fs14.default.statSync(p2).isFile();
|
|
37198
37847
|
} catch {
|
|
37199
37848
|
return false;
|
|
37200
37849
|
}
|
|
@@ -37202,7 +37851,7 @@ function fileExistsSync(p2) {
|
|
|
37202
37851
|
function parseAgentFile(filePath) {
|
|
37203
37852
|
let content;
|
|
37204
37853
|
try {
|
|
37205
|
-
content =
|
|
37854
|
+
content = import_node_fs14.default.readFileSync(filePath, "utf8");
|
|
37206
37855
|
} catch {
|
|
37207
37856
|
return {};
|
|
37208
37857
|
}
|
|
@@ -37215,16 +37864,16 @@ function parseAgentFile(filePath) {
|
|
|
37215
37864
|
function scanAgentsDir(dir, source, seen, out) {
|
|
37216
37865
|
let entries;
|
|
37217
37866
|
try {
|
|
37218
|
-
entries =
|
|
37867
|
+
entries = import_node_fs14.default.readdirSync(dir, { withFileTypes: true });
|
|
37219
37868
|
} catch {
|
|
37220
37869
|
return;
|
|
37221
37870
|
}
|
|
37222
37871
|
for (const ent of entries) {
|
|
37223
37872
|
if (!ent.name.endsWith(".md")) continue;
|
|
37224
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
37873
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path12.default.join(dir, ent.name)))) {
|
|
37225
37874
|
continue;
|
|
37226
37875
|
}
|
|
37227
|
-
const filePath =
|
|
37876
|
+
const filePath = import_node_path12.default.join(dir, ent.name);
|
|
37228
37877
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
37229
37878
|
if (seen.has(baseName)) continue;
|
|
37230
37879
|
seen.add(baseName);
|
|
@@ -37242,12 +37891,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37242
37891
|
function walk2(dir, namespaces) {
|
|
37243
37892
|
let entries;
|
|
37244
37893
|
try {
|
|
37245
|
-
entries =
|
|
37894
|
+
entries = import_node_fs14.default.readdirSync(dir, { withFileTypes: true });
|
|
37246
37895
|
} catch {
|
|
37247
37896
|
return;
|
|
37248
37897
|
}
|
|
37249
37898
|
for (const ent of entries) {
|
|
37250
|
-
const childPath =
|
|
37899
|
+
const childPath = import_node_path12.default.join(dir, ent.name);
|
|
37251
37900
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
37252
37901
|
walk2(childPath, [...namespaces, ent.name]);
|
|
37253
37902
|
continue;
|
|
@@ -37272,13 +37921,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
37272
37921
|
walk2(root, []);
|
|
37273
37922
|
}
|
|
37274
37923
|
function readInstalledPlugins2(home) {
|
|
37275
|
-
const pluginsDir =
|
|
37276
|
-
const v2 =
|
|
37277
|
-
const v1 =
|
|
37924
|
+
const pluginsDir = import_node_path12.default.join(home, ".claude", "plugins");
|
|
37925
|
+
const v2 = import_node_path12.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
37926
|
+
const v1 = import_node_path12.default.join(pluginsDir, "installed_plugins.json");
|
|
37278
37927
|
let raw = null;
|
|
37279
37928
|
for (const candidate of [v2, v1]) {
|
|
37280
37929
|
try {
|
|
37281
|
-
raw =
|
|
37930
|
+
raw = import_node_fs14.default.readFileSync(candidate, "utf8");
|
|
37282
37931
|
break;
|
|
37283
37932
|
} catch {
|
|
37284
37933
|
}
|
|
@@ -37303,19 +37952,19 @@ function readInstalledPlugins2(home) {
|
|
|
37303
37952
|
return out;
|
|
37304
37953
|
}
|
|
37305
37954
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
37306
|
-
let cur =
|
|
37307
|
-
const fsRoot =
|
|
37955
|
+
let cur = import_node_path12.default.resolve(startCwd);
|
|
37956
|
+
const fsRoot = import_node_path12.default.parse(cur).root;
|
|
37308
37957
|
while (true) {
|
|
37309
|
-
scanAgentsDir(
|
|
37958
|
+
scanAgentsDir(import_node_path12.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
37310
37959
|
let hasGit = false;
|
|
37311
37960
|
try {
|
|
37312
|
-
hasGit =
|
|
37961
|
+
hasGit = import_node_fs14.default.existsSync(import_node_path12.default.join(cur, ".git"));
|
|
37313
37962
|
} catch {
|
|
37314
37963
|
}
|
|
37315
37964
|
if (hasGit) return;
|
|
37316
37965
|
if (cur === home) return;
|
|
37317
37966
|
if (cur === fsRoot) return;
|
|
37318
|
-
const parent =
|
|
37967
|
+
const parent = import_node_path12.default.dirname(cur);
|
|
37319
37968
|
if (parent === cur) return;
|
|
37320
37969
|
cur = parent;
|
|
37321
37970
|
}
|
|
@@ -37350,7 +37999,7 @@ var AgentsScanner = class {
|
|
|
37350
37999
|
}
|
|
37351
38000
|
const fsBlock = [];
|
|
37352
38001
|
scanAgentsDir(
|
|
37353
|
-
|
|
38002
|
+
import_node_path12.default.join(this.home, ".claude", "agents"),
|
|
37354
38003
|
"global",
|
|
37355
38004
|
seen,
|
|
37356
38005
|
fsBlock
|
|
@@ -37364,7 +38013,7 @@ var AgentsScanner = class {
|
|
|
37364
38013
|
...this.extraPluginRoots
|
|
37365
38014
|
];
|
|
37366
38015
|
for (const { name, root } of plugins) {
|
|
37367
|
-
const agentsRoot =
|
|
38016
|
+
const agentsRoot = import_node_path12.default.join(root, "agents");
|
|
37368
38017
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
37369
38018
|
}
|
|
37370
38019
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -37372,15 +38021,15 @@ var AgentsScanner = class {
|
|
|
37372
38021
|
};
|
|
37373
38022
|
|
|
37374
38023
|
// src/observer/session-observer.ts
|
|
37375
|
-
var
|
|
38024
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
37376
38025
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
37377
|
-
var
|
|
38026
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
37378
38027
|
init_claude_history();
|
|
37379
38028
|
|
|
37380
38029
|
// src/observer/subagent-meta-observer.ts
|
|
37381
|
-
var
|
|
38030
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37382
38031
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
37383
|
-
var
|
|
38032
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
37384
38033
|
init_claude_history();
|
|
37385
38034
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
37386
38035
|
var SubagentMetaObserver = class {
|
|
@@ -37393,7 +38042,7 @@ var SubagentMetaObserver = class {
|
|
|
37393
38042
|
watches = /* @__PURE__ */ new Map();
|
|
37394
38043
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
37395
38044
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
37396
|
-
return
|
|
38045
|
+
return import_node_path13.default.join(
|
|
37397
38046
|
this.home,
|
|
37398
38047
|
".claude",
|
|
37399
38048
|
"projects",
|
|
@@ -37423,7 +38072,7 @@ var SubagentMetaObserver = class {
|
|
|
37423
38072
|
attachWatcher(w2) {
|
|
37424
38073
|
if (w2.watcher) return;
|
|
37425
38074
|
try {
|
|
37426
|
-
w2.watcher =
|
|
38075
|
+
w2.watcher = import_node_fs15.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
37427
38076
|
if (!name) return;
|
|
37428
38077
|
const m2 = META_RE.exec(String(name));
|
|
37429
38078
|
if (!m2) return;
|
|
@@ -37435,7 +38084,7 @@ var SubagentMetaObserver = class {
|
|
|
37435
38084
|
scan(w2) {
|
|
37436
38085
|
let entries;
|
|
37437
38086
|
try {
|
|
37438
|
-
entries =
|
|
38087
|
+
entries = import_node_fs15.default.readdirSync(w2.dirPath);
|
|
37439
38088
|
} catch {
|
|
37440
38089
|
return;
|
|
37441
38090
|
}
|
|
@@ -37449,10 +38098,10 @@ var SubagentMetaObserver = class {
|
|
|
37449
38098
|
if (!m2) return;
|
|
37450
38099
|
const agentId = m2[1];
|
|
37451
38100
|
if (w2.emitted.has(agentId)) return;
|
|
37452
|
-
const file =
|
|
38101
|
+
const file = import_node_path13.default.join(w2.dirPath, name);
|
|
37453
38102
|
let raw;
|
|
37454
38103
|
try {
|
|
37455
|
-
raw =
|
|
38104
|
+
raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
37456
38105
|
} catch {
|
|
37457
38106
|
return;
|
|
37458
38107
|
}
|
|
@@ -37509,14 +38158,14 @@ var SessionObserver = class {
|
|
|
37509
38158
|
metaObserver;
|
|
37510
38159
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
37511
38160
|
if (override) return override;
|
|
37512
|
-
return
|
|
38161
|
+
return import_node_path14.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
37513
38162
|
}
|
|
37514
38163
|
start(args) {
|
|
37515
38164
|
this.stop(args.sessionId);
|
|
37516
38165
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
37517
38166
|
let size = 0;
|
|
37518
38167
|
try {
|
|
37519
|
-
size =
|
|
38168
|
+
size = import_node_fs16.default.statSync(filePath).size;
|
|
37520
38169
|
} catch {
|
|
37521
38170
|
}
|
|
37522
38171
|
const w2 = {
|
|
@@ -37530,10 +38179,10 @@ var SessionObserver = class {
|
|
|
37530
38179
|
prevIsRejectSentinel: false
|
|
37531
38180
|
};
|
|
37532
38181
|
try {
|
|
37533
|
-
|
|
38182
|
+
import_node_fs16.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
|
|
37534
38183
|
} catch {
|
|
37535
38184
|
}
|
|
37536
|
-
w2.watcher =
|
|
38185
|
+
w2.watcher = import_node_fs16.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
37537
38186
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
37538
38187
|
this.poll(w2);
|
|
37539
38188
|
});
|
|
@@ -37556,7 +38205,7 @@ var SessionObserver = class {
|
|
|
37556
38205
|
// 异常静默吞,不阻塞 watcher 启动
|
|
37557
38206
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
37558
38207
|
try {
|
|
37559
|
-
const raw =
|
|
38208
|
+
const raw = import_node_fs16.default.readFileSync(w2.filePath, "utf8");
|
|
37560
38209
|
if (!raw) return;
|
|
37561
38210
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
37562
38211
|
if (allLines.length === 0) return;
|
|
@@ -37580,7 +38229,7 @@ var SessionObserver = class {
|
|
|
37580
38229
|
poll(w2) {
|
|
37581
38230
|
let size = 0;
|
|
37582
38231
|
try {
|
|
37583
|
-
size =
|
|
38232
|
+
size = import_node_fs16.default.statSync(w2.filePath).size;
|
|
37584
38233
|
} catch {
|
|
37585
38234
|
return;
|
|
37586
38235
|
}
|
|
@@ -37589,11 +38238,11 @@ var SessionObserver = class {
|
|
|
37589
38238
|
w2.buf = "";
|
|
37590
38239
|
}
|
|
37591
38240
|
if (size === w2.lastSize) return;
|
|
37592
|
-
const fd =
|
|
38241
|
+
const fd = import_node_fs16.default.openSync(w2.filePath, "r");
|
|
37593
38242
|
try {
|
|
37594
38243
|
const len = size - w2.lastSize;
|
|
37595
38244
|
const buf = Buffer.alloc(len);
|
|
37596
|
-
|
|
38245
|
+
import_node_fs16.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
37597
38246
|
w2.lastSize = size;
|
|
37598
38247
|
w2.buf += buf.toString("utf8");
|
|
37599
38248
|
let newlineIndex;
|
|
@@ -37616,7 +38265,7 @@ var SessionObserver = class {
|
|
|
37616
38265
|
}
|
|
37617
38266
|
}
|
|
37618
38267
|
} finally {
|
|
37619
|
-
|
|
38268
|
+
import_node_fs16.default.closeSync(fd);
|
|
37620
38269
|
}
|
|
37621
38270
|
}
|
|
37622
38271
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -38339,14 +38988,14 @@ async function authenticate(token, deps) {
|
|
|
38339
38988
|
}
|
|
38340
38989
|
|
|
38341
38990
|
// src/permission/capability-store.ts
|
|
38342
|
-
var
|
|
38343
|
-
var
|
|
38991
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
38992
|
+
var path19 = __toESM(require("path"), 1);
|
|
38344
38993
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
38345
38994
|
var FILE_VERSION = 1;
|
|
38346
38995
|
var CapabilityStore = class {
|
|
38347
38996
|
constructor(dataDir) {
|
|
38348
38997
|
this.dataDir = dataDir;
|
|
38349
|
-
|
|
38998
|
+
fs19.mkdirSync(dataDir, { recursive: true });
|
|
38350
38999
|
this.cache = this.readFromDisk();
|
|
38351
39000
|
}
|
|
38352
39001
|
dataDir;
|
|
@@ -38370,13 +39019,13 @@ var CapabilityStore = class {
|
|
|
38370
39019
|
this.flush();
|
|
38371
39020
|
}
|
|
38372
39021
|
filePath() {
|
|
38373
|
-
return
|
|
39022
|
+
return path19.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
38374
39023
|
}
|
|
38375
39024
|
readFromDisk() {
|
|
38376
39025
|
const file = this.filePath();
|
|
38377
39026
|
let raw;
|
|
38378
39027
|
try {
|
|
38379
|
-
raw =
|
|
39028
|
+
raw = fs19.readFileSync(file, "utf8");
|
|
38380
39029
|
} catch (err) {
|
|
38381
39030
|
if (err?.code === "ENOENT") return [];
|
|
38382
39031
|
return [];
|
|
@@ -38404,10 +39053,10 @@ var CapabilityStore = class {
|
|
|
38404
39053
|
}
|
|
38405
39054
|
atomicWrite(file, content) {
|
|
38406
39055
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
38407
|
-
|
|
38408
|
-
|
|
39056
|
+
fs19.writeFileSync(tmp, content, { mode: 384 });
|
|
39057
|
+
fs19.renameSync(tmp, file);
|
|
38409
39058
|
try {
|
|
38410
|
-
|
|
39059
|
+
fs19.chmodSync(file, 384);
|
|
38411
39060
|
} catch {
|
|
38412
39061
|
}
|
|
38413
39062
|
}
|
|
@@ -38500,14 +39149,14 @@ var CapabilityManager = class {
|
|
|
38500
39149
|
};
|
|
38501
39150
|
|
|
38502
39151
|
// src/permission/cleanup.ts
|
|
38503
|
-
var
|
|
39152
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
38504
39153
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
38505
39154
|
const removed = [];
|
|
38506
39155
|
for (const g2 of cap.grants) {
|
|
38507
39156
|
if (g2.resource.type !== "persona") continue;
|
|
38508
39157
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
38509
39158
|
try {
|
|
38510
|
-
|
|
39159
|
+
fs20.rmSync(dir, { recursive: true, force: true });
|
|
38511
39160
|
removed.push(dir);
|
|
38512
39161
|
} catch {
|
|
38513
39162
|
}
|
|
@@ -38516,13 +39165,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
38516
39165
|
}
|
|
38517
39166
|
|
|
38518
39167
|
// src/inbox/inbox-store.ts
|
|
38519
|
-
var
|
|
38520
|
-
var
|
|
39168
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
39169
|
+
var path20 = __toESM(require("path"), 1);
|
|
38521
39170
|
var INBOX_SUBDIR = "inbox";
|
|
38522
39171
|
var InboxStore = class {
|
|
38523
39172
|
constructor(dataDir) {
|
|
38524
39173
|
this.dataDir = dataDir;
|
|
38525
|
-
|
|
39174
|
+
fs21.mkdirSync(this.dirPath(), { recursive: true });
|
|
38526
39175
|
}
|
|
38527
39176
|
dataDir;
|
|
38528
39177
|
/**
|
|
@@ -38534,7 +39183,7 @@ var InboxStore = class {
|
|
|
38534
39183
|
const file = this.filePath(peerDeviceId);
|
|
38535
39184
|
let raw;
|
|
38536
39185
|
try {
|
|
38537
|
-
raw =
|
|
39186
|
+
raw = fs21.readFileSync(file, "utf8");
|
|
38538
39187
|
} catch (err) {
|
|
38539
39188
|
if (err?.code === "ENOENT") return [];
|
|
38540
39189
|
return [];
|
|
@@ -38550,7 +39199,7 @@ var InboxStore = class {
|
|
|
38550
39199
|
const dir = this.dirPath();
|
|
38551
39200
|
let entries;
|
|
38552
39201
|
try {
|
|
38553
|
-
entries =
|
|
39202
|
+
entries = fs21.readdirSync(dir);
|
|
38554
39203
|
} catch (err) {
|
|
38555
39204
|
if (err?.code === "ENOENT") return [];
|
|
38556
39205
|
return [];
|
|
@@ -38566,9 +39215,9 @@ var InboxStore = class {
|
|
|
38566
39215
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
38567
39216
|
const file = this.filePath(message.peerDeviceId);
|
|
38568
39217
|
const line = JSON.stringify(message) + "\n";
|
|
38569
|
-
|
|
39218
|
+
fs21.appendFileSync(file, line, { mode: 384 });
|
|
38570
39219
|
try {
|
|
38571
|
-
|
|
39220
|
+
fs21.chmodSync(file, 384);
|
|
38572
39221
|
} catch {
|
|
38573
39222
|
}
|
|
38574
39223
|
}
|
|
@@ -38598,7 +39247,7 @@ var InboxStore = class {
|
|
|
38598
39247
|
removeByPeerDeviceId(peerDeviceId) {
|
|
38599
39248
|
const file = this.filePath(peerDeviceId);
|
|
38600
39249
|
try {
|
|
38601
|
-
|
|
39250
|
+
fs21.unlinkSync(file);
|
|
38602
39251
|
} catch (err) {
|
|
38603
39252
|
if (err?.code === "ENOENT") return;
|
|
38604
39253
|
}
|
|
@@ -38607,18 +39256,18 @@ var InboxStore = class {
|
|
|
38607
39256
|
const file = this.filePath(peerDeviceId);
|
|
38608
39257
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
38609
39258
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
38610
|
-
|
|
38611
|
-
|
|
39259
|
+
fs21.writeFileSync(tmp, content, { mode: 384 });
|
|
39260
|
+
fs21.renameSync(tmp, file);
|
|
38612
39261
|
try {
|
|
38613
|
-
|
|
39262
|
+
fs21.chmodSync(file, 384);
|
|
38614
39263
|
} catch {
|
|
38615
39264
|
}
|
|
38616
39265
|
}
|
|
38617
39266
|
dirPath() {
|
|
38618
|
-
return
|
|
39267
|
+
return path20.join(this.dataDir, INBOX_SUBDIR);
|
|
38619
39268
|
}
|
|
38620
39269
|
filePath(peerDeviceId) {
|
|
38621
|
-
return
|
|
39270
|
+
return path20.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
38622
39271
|
}
|
|
38623
39272
|
};
|
|
38624
39273
|
function parseAllLines(raw) {
|
|
@@ -38705,8 +39354,8 @@ var InboxManager = class {
|
|
|
38705
39354
|
};
|
|
38706
39355
|
|
|
38707
39356
|
// src/state/contact-store.ts
|
|
38708
|
-
var
|
|
38709
|
-
var
|
|
39357
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
39358
|
+
var path21 = __toESM(require("path"), 1);
|
|
38710
39359
|
var FILE_NAME = "contacts.json";
|
|
38711
39360
|
var ContactStore = class {
|
|
38712
39361
|
constructor(dataDir) {
|
|
@@ -38716,10 +39365,10 @@ var ContactStore = class {
|
|
|
38716
39365
|
contacts = /* @__PURE__ */ new Map();
|
|
38717
39366
|
load() {
|
|
38718
39367
|
this.contacts.clear();
|
|
38719
|
-
const file =
|
|
39368
|
+
const file = path21.join(this.dataDir, FILE_NAME);
|
|
38720
39369
|
let raw;
|
|
38721
39370
|
try {
|
|
38722
|
-
raw =
|
|
39371
|
+
raw = fs22.readFileSync(file, "utf8");
|
|
38723
39372
|
} catch (err) {
|
|
38724
39373
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
38725
39374
|
return;
|
|
@@ -38762,20 +39411,20 @@ var ContactStore = class {
|
|
|
38762
39411
|
return existed;
|
|
38763
39412
|
}
|
|
38764
39413
|
flush() {
|
|
38765
|
-
const file =
|
|
39414
|
+
const file = path21.join(this.dataDir, FILE_NAME);
|
|
38766
39415
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
38767
39416
|
const content = JSON.stringify(
|
|
38768
39417
|
{ contacts: Array.from(this.contacts.values()) },
|
|
38769
39418
|
null,
|
|
38770
39419
|
2
|
|
38771
39420
|
);
|
|
38772
|
-
|
|
38773
|
-
|
|
38774
|
-
|
|
39421
|
+
fs22.mkdirSync(this.dataDir, { recursive: true });
|
|
39422
|
+
fs22.writeFileSync(tmp, content, { mode: 384 });
|
|
39423
|
+
fs22.renameSync(tmp, file);
|
|
38775
39424
|
}
|
|
38776
39425
|
renameBak(file) {
|
|
38777
39426
|
try {
|
|
38778
|
-
|
|
39427
|
+
fs22.renameSync(file, `${file}.bak`);
|
|
38779
39428
|
} catch {
|
|
38780
39429
|
}
|
|
38781
39430
|
}
|
|
@@ -38925,61 +39574,61 @@ async function autoReverseContact(args) {
|
|
|
38925
39574
|
}
|
|
38926
39575
|
|
|
38927
39576
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
38928
|
-
var
|
|
38929
|
-
var
|
|
39577
|
+
var fs23 = __toESM(require("fs"), 1);
|
|
39578
|
+
var path22 = __toESM(require("path"), 1);
|
|
38930
39579
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
38931
39580
|
function migrateFlattenSessions(opts) {
|
|
38932
39581
|
const dataDir = opts.dataDir;
|
|
38933
39582
|
const now = opts.now ?? Date.now;
|
|
38934
|
-
const sessionsDir =
|
|
38935
|
-
const flagPath =
|
|
39583
|
+
const sessionsDir = path22.join(dataDir, "sessions");
|
|
39584
|
+
const flagPath = path22.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
38936
39585
|
if (existsSync3(flagPath)) {
|
|
38937
39586
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
38938
39587
|
}
|
|
38939
39588
|
let movedBare = 0;
|
|
38940
39589
|
let movedVmOwner = 0;
|
|
38941
39590
|
let archivedListener = 0;
|
|
38942
|
-
const defaultDir =
|
|
39591
|
+
const defaultDir = path22.join(sessionsDir, "default");
|
|
38943
39592
|
if (existsSync3(defaultDir)) {
|
|
38944
39593
|
for (const entry of readdirSafe(defaultDir)) {
|
|
38945
39594
|
if (!entry.endsWith(".json")) continue;
|
|
38946
|
-
const src =
|
|
38947
|
-
const dst =
|
|
38948
|
-
|
|
39595
|
+
const src = path22.join(defaultDir, entry);
|
|
39596
|
+
const dst = path22.join(sessionsDir, entry);
|
|
39597
|
+
fs23.renameSync(src, dst);
|
|
38949
39598
|
movedBare += 1;
|
|
38950
39599
|
}
|
|
38951
39600
|
rmdirIfEmpty(defaultDir);
|
|
38952
39601
|
}
|
|
38953
39602
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
38954
|
-
const personaDir =
|
|
39603
|
+
const personaDir = path22.join(sessionsDir, pid);
|
|
38955
39604
|
if (!isDir(personaDir)) continue;
|
|
38956
39605
|
if (pid === "default") continue;
|
|
38957
|
-
const ownerSrc =
|
|
39606
|
+
const ownerSrc = path22.join(personaDir, "owner");
|
|
38958
39607
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
38959
|
-
const ownerDst =
|
|
38960
|
-
|
|
39608
|
+
const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
39609
|
+
fs23.mkdirSync(ownerDst, { recursive: true });
|
|
38961
39610
|
for (const file of readdirSafe(ownerSrc)) {
|
|
38962
39611
|
if (!file.endsWith(".json")) continue;
|
|
38963
|
-
|
|
39612
|
+
fs23.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
|
|
38964
39613
|
movedVmOwner += 1;
|
|
38965
39614
|
}
|
|
38966
39615
|
rmdirIfEmpty(ownerSrc);
|
|
38967
39616
|
}
|
|
38968
|
-
const listenerSrc =
|
|
39617
|
+
const listenerSrc = path22.join(personaDir, "listener");
|
|
38969
39618
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
38970
|
-
const archiveDst =
|
|
38971
|
-
|
|
39619
|
+
const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
|
|
39620
|
+
fs23.mkdirSync(archiveDst, { recursive: true });
|
|
38972
39621
|
for (const file of readdirSafe(listenerSrc)) {
|
|
38973
39622
|
if (!file.endsWith(".json")) continue;
|
|
38974
|
-
|
|
39623
|
+
fs23.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
|
|
38975
39624
|
archivedListener += 1;
|
|
38976
39625
|
}
|
|
38977
39626
|
rmdirIfEmpty(listenerSrc);
|
|
38978
39627
|
}
|
|
38979
39628
|
rmdirIfEmpty(personaDir);
|
|
38980
39629
|
}
|
|
38981
|
-
|
|
38982
|
-
|
|
39630
|
+
fs23.mkdirSync(sessionsDir, { recursive: true });
|
|
39631
|
+
fs23.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
38983
39632
|
return {
|
|
38984
39633
|
skipped: false,
|
|
38985
39634
|
flagWritten: true,
|
|
@@ -38990,7 +39639,7 @@ function migrateFlattenSessions(opts) {
|
|
|
38990
39639
|
}
|
|
38991
39640
|
function existsSync3(p2) {
|
|
38992
39641
|
try {
|
|
38993
|
-
|
|
39642
|
+
fs23.statSync(p2);
|
|
38994
39643
|
return true;
|
|
38995
39644
|
} catch {
|
|
38996
39645
|
return false;
|
|
@@ -38998,31 +39647,31 @@ function existsSync3(p2) {
|
|
|
38998
39647
|
}
|
|
38999
39648
|
function isDir(p2) {
|
|
39000
39649
|
try {
|
|
39001
|
-
return
|
|
39650
|
+
return fs23.statSync(p2).isDirectory();
|
|
39002
39651
|
} catch {
|
|
39003
39652
|
return false;
|
|
39004
39653
|
}
|
|
39005
39654
|
}
|
|
39006
39655
|
function readdirSafe(p2) {
|
|
39007
39656
|
try {
|
|
39008
|
-
return
|
|
39657
|
+
return fs23.readdirSync(p2);
|
|
39009
39658
|
} catch {
|
|
39010
39659
|
return [];
|
|
39011
39660
|
}
|
|
39012
39661
|
}
|
|
39013
39662
|
function rmdirIfEmpty(p2) {
|
|
39014
39663
|
try {
|
|
39015
|
-
|
|
39664
|
+
fs23.rmdirSync(p2);
|
|
39016
39665
|
} catch {
|
|
39017
39666
|
}
|
|
39018
39667
|
}
|
|
39019
39668
|
|
|
39020
39669
|
// src/transport/http-router.ts
|
|
39021
|
-
var
|
|
39022
|
-
var
|
|
39670
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
39671
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
39023
39672
|
|
|
39024
39673
|
// src/attachment/mime.ts
|
|
39025
|
-
var
|
|
39674
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
39026
39675
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
39027
39676
|
var EXT_TO_NATIVE_MIME = {
|
|
39028
39677
|
// 图片
|
|
@@ -39129,7 +39778,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
39129
39778
|
".mk"
|
|
39130
39779
|
]);
|
|
39131
39780
|
function lookupMime(filePathOrName) {
|
|
39132
|
-
const ext =
|
|
39781
|
+
const ext = import_node_path15.default.extname(filePathOrName).toLowerCase();
|
|
39133
39782
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
39134
39783
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
39135
39784
|
return "application/octet-stream";
|
|
@@ -39198,8 +39847,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
39198
39847
|
}
|
|
39199
39848
|
|
|
39200
39849
|
// src/attachment/upload.ts
|
|
39201
|
-
var
|
|
39202
|
-
var
|
|
39850
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
39851
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
39203
39852
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
39204
39853
|
var import_promises = require("stream/promises");
|
|
39205
39854
|
var UploadError = class extends Error {
|
|
@@ -39211,22 +39860,22 @@ var UploadError = class extends Error {
|
|
|
39211
39860
|
code;
|
|
39212
39861
|
};
|
|
39213
39862
|
function assertValidFileName(fileName) {
|
|
39214
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
39863
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path16.default.basename(fileName)) {
|
|
39215
39864
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
39216
39865
|
}
|
|
39217
39866
|
}
|
|
39218
39867
|
var HASH_PREFIX_LEN = 16;
|
|
39219
39868
|
async function writeUploadedAttachment(args) {
|
|
39220
39869
|
assertValidFileName(args.fileName);
|
|
39221
|
-
const attachmentsRoot =
|
|
39870
|
+
const attachmentsRoot = import_node_path16.default.join(args.sessionDir, ".attachments");
|
|
39222
39871
|
try {
|
|
39223
|
-
|
|
39872
|
+
import_node_fs17.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
39224
39873
|
} catch (err) {
|
|
39225
39874
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
39226
39875
|
}
|
|
39227
39876
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
39228
39877
|
let actualSize = 0;
|
|
39229
|
-
const tmpPath =
|
|
39878
|
+
const tmpPath = import_node_path16.default.join(
|
|
39230
39879
|
attachmentsRoot,
|
|
39231
39880
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
39232
39881
|
);
|
|
@@ -39241,18 +39890,18 @@ async function writeUploadedAttachment(args) {
|
|
|
39241
39890
|
yield buf;
|
|
39242
39891
|
}
|
|
39243
39892
|
},
|
|
39244
|
-
|
|
39893
|
+
import_node_fs17.default.createWriteStream(tmpPath, { mode: 384 })
|
|
39245
39894
|
);
|
|
39246
39895
|
} catch (err) {
|
|
39247
39896
|
try {
|
|
39248
|
-
|
|
39897
|
+
import_node_fs17.default.unlinkSync(tmpPath);
|
|
39249
39898
|
} catch {
|
|
39250
39899
|
}
|
|
39251
39900
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
39252
39901
|
}
|
|
39253
39902
|
if (actualSize !== args.contentLength) {
|
|
39254
39903
|
try {
|
|
39255
|
-
|
|
39904
|
+
import_node_fs17.default.unlinkSync(tmpPath);
|
|
39256
39905
|
} catch {
|
|
39257
39906
|
}
|
|
39258
39907
|
throw new UploadError(
|
|
@@ -39261,35 +39910,35 @@ async function writeUploadedAttachment(args) {
|
|
|
39261
39910
|
);
|
|
39262
39911
|
}
|
|
39263
39912
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
39264
|
-
const hashDir =
|
|
39913
|
+
const hashDir = import_node_path16.default.join(attachmentsRoot, attachmentId);
|
|
39265
39914
|
let finalFileName;
|
|
39266
39915
|
let hashDirExists = false;
|
|
39267
39916
|
try {
|
|
39268
|
-
hashDirExists =
|
|
39917
|
+
hashDirExists = import_node_fs17.default.statSync(hashDir).isDirectory();
|
|
39269
39918
|
} catch {
|
|
39270
39919
|
}
|
|
39271
39920
|
if (hashDirExists) {
|
|
39272
|
-
const existing =
|
|
39921
|
+
const existing = import_node_fs17.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
39273
39922
|
finalFileName = existing[0] ?? args.fileName;
|
|
39274
39923
|
try {
|
|
39275
|
-
|
|
39924
|
+
import_node_fs17.default.unlinkSync(tmpPath);
|
|
39276
39925
|
} catch {
|
|
39277
39926
|
}
|
|
39278
39927
|
} else {
|
|
39279
39928
|
try {
|
|
39280
|
-
|
|
39929
|
+
import_node_fs17.default.mkdirSync(hashDir, { recursive: true });
|
|
39281
39930
|
finalFileName = args.fileName;
|
|
39282
|
-
|
|
39931
|
+
import_node_fs17.default.renameSync(tmpPath, import_node_path16.default.join(hashDir, finalFileName));
|
|
39283
39932
|
} catch (err) {
|
|
39284
39933
|
try {
|
|
39285
|
-
|
|
39934
|
+
import_node_fs17.default.unlinkSync(tmpPath);
|
|
39286
39935
|
} catch {
|
|
39287
39936
|
}
|
|
39288
39937
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
39289
39938
|
}
|
|
39290
39939
|
}
|
|
39291
|
-
const absPath =
|
|
39292
|
-
const relPath =
|
|
39940
|
+
const absPath = import_node_path16.default.join(hashDir, finalFileName);
|
|
39941
|
+
const relPath = import_node_path16.default.relative(args.sessionDir, absPath);
|
|
39293
39942
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
39294
39943
|
relPath: absPath,
|
|
39295
39944
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -39303,7 +39952,7 @@ async function writeUploadedAttachment(args) {
|
|
|
39303
39952
|
|
|
39304
39953
|
// src/extension/import.ts
|
|
39305
39954
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
39306
|
-
var
|
|
39955
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
39307
39956
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
39308
39957
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
39309
39958
|
var ImportError = class extends Error {
|
|
@@ -39321,7 +39970,7 @@ async function importZip(buf, root) {
|
|
|
39321
39970
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
39322
39971
|
}
|
|
39323
39972
|
for (const name of Object.keys(zip.files)) {
|
|
39324
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
39973
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path17.default.isAbsolute(name)) {
|
|
39325
39974
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
39326
39975
|
}
|
|
39327
39976
|
}
|
|
@@ -39354,7 +40003,7 @@ async function importZip(buf, root) {
|
|
|
39354
40003
|
);
|
|
39355
40004
|
}
|
|
39356
40005
|
}
|
|
39357
|
-
const destDir =
|
|
40006
|
+
const destDir = import_node_path17.default.join(root, manifest.id);
|
|
39358
40007
|
let destExists = false;
|
|
39359
40008
|
try {
|
|
39360
40009
|
await import_promises2.default.access(destDir);
|
|
@@ -39364,15 +40013,15 @@ async function importZip(buf, root) {
|
|
|
39364
40013
|
if (destExists) {
|
|
39365
40014
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
39366
40015
|
}
|
|
39367
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
40016
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path17.default.join(import_node_os10.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
39368
40017
|
try {
|
|
39369
40018
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
39370
|
-
const dest =
|
|
40019
|
+
const dest = import_node_path17.default.join(stage, name);
|
|
39371
40020
|
if (entry.dir) {
|
|
39372
40021
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
39373
40022
|
continue;
|
|
39374
40023
|
}
|
|
39375
|
-
await import_promises2.default.mkdir(
|
|
40024
|
+
await import_promises2.default.mkdir(import_node_path17.default.dirname(dest), { recursive: true });
|
|
39376
40025
|
const content = await entry.async("nodebuffer");
|
|
39377
40026
|
await import_promises2.default.writeFile(dest, content);
|
|
39378
40027
|
}
|
|
@@ -39400,7 +40049,12 @@ var EXPOSED_RPC_METHODS = [
|
|
|
39400
40049
|
"appBuilder.setActiveSession",
|
|
39401
40050
|
// dataclaw-builder:persona 建页时取建页人身份(含 union_id)写进生成 app 的配置。
|
|
39402
40051
|
// 路由到 handlers['auth:getIdentity'],只返 identity、绝不带 ttcToken(见 handlers/feishu-auth.ts)。
|
|
39403
|
-
"auth.getIdentity"
|
|
40052
|
+
"auth.getIdentity",
|
|
40053
|
+
// Persona dispatch (Task 4): A 端 dispatch MCP server 调 run(hold-and-wait 一次);
|
|
40054
|
+
// B 端 dispatch MCP server 调 complete(带 outcome 触发 run 端 resolve)。详见
|
|
40055
|
+
// protocol/src/dispatch.ts。
|
|
40056
|
+
"personaDispatch.run",
|
|
40057
|
+
"personaDispatch.complete"
|
|
39404
40058
|
];
|
|
39405
40059
|
async function handleRpcRequest(input) {
|
|
39406
40060
|
const { method, body, sessionId, dispatcher } = input;
|
|
@@ -39489,7 +40143,7 @@ function isValidUploadFileName(fileName) {
|
|
|
39489
40143
|
if (fileName === "." || fileName === "..") return false;
|
|
39490
40144
|
if (fileName.startsWith(".")) return false;
|
|
39491
40145
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
39492
|
-
return fileName ===
|
|
40146
|
+
return fileName === import_node_path18.default.basename(fileName);
|
|
39493
40147
|
}
|
|
39494
40148
|
function createHttpRouter(deps) {
|
|
39495
40149
|
return async (req, res) => {
|
|
@@ -39536,6 +40190,8 @@ function createHttpRouter(deps) {
|
|
|
39536
40190
|
sendJson(res, 403, { code: "NOT_LOOPBACK", message: "RPC adapter only accepts loopback connections" });
|
|
39537
40191
|
return true;
|
|
39538
40192
|
}
|
|
40193
|
+
req.socket.setTimeout(0);
|
|
40194
|
+
res.socket?.setTimeout(0);
|
|
39539
40195
|
const method = url.pathname.slice(RPC_ROUTE_PREFIX.length).split("?")[0] ?? "";
|
|
39540
40196
|
const sessionId = req.headers["x-clawd-session-id"] ?? void 0;
|
|
39541
40197
|
let body;
|
|
@@ -39718,7 +40374,7 @@ function createHttpRouter(deps) {
|
|
|
39718
40374
|
return true;
|
|
39719
40375
|
}
|
|
39720
40376
|
let absPath;
|
|
39721
|
-
if (
|
|
40377
|
+
if (import_node_path18.default.isAbsolute(pathParam)) {
|
|
39722
40378
|
absPath = pathParam;
|
|
39723
40379
|
} else if (deps.sessionStore) {
|
|
39724
40380
|
const file = deps.sessionStore.read(sid);
|
|
@@ -39726,7 +40382,7 @@ function createHttpRouter(deps) {
|
|
|
39726
40382
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
39727
40383
|
return true;
|
|
39728
40384
|
}
|
|
39729
|
-
absPath =
|
|
40385
|
+
absPath = import_node_path18.default.join(file.cwd, pathParam);
|
|
39730
40386
|
} else {
|
|
39731
40387
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
39732
40388
|
return true;
|
|
@@ -39809,7 +40465,7 @@ function withCtx(ctx, body) {
|
|
|
39809
40465
|
function streamFile(res, absPath, logger) {
|
|
39810
40466
|
let stat;
|
|
39811
40467
|
try {
|
|
39812
|
-
stat =
|
|
40468
|
+
stat = import_node_fs18.default.statSync(absPath);
|
|
39813
40469
|
} catch (err) {
|
|
39814
40470
|
const code = err?.code;
|
|
39815
40471
|
if (code === "ENOENT") {
|
|
@@ -39824,7 +40480,7 @@ function streamFile(res, absPath, logger) {
|
|
|
39824
40480
|
return;
|
|
39825
40481
|
}
|
|
39826
40482
|
const mime = lookupMime(absPath);
|
|
39827
|
-
const basename =
|
|
40483
|
+
const basename = import_node_path18.default.basename(absPath);
|
|
39828
40484
|
res.writeHead(200, {
|
|
39829
40485
|
"Content-Type": mime,
|
|
39830
40486
|
"Content-Length": String(stat.size),
|
|
@@ -39832,7 +40488,7 @@ function streamFile(res, absPath, logger) {
|
|
|
39832
40488
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
39833
40489
|
"X-Content-Type-Options": "nosniff"
|
|
39834
40490
|
});
|
|
39835
|
-
const stream =
|
|
40491
|
+
const stream = import_node_fs18.default.createReadStream(absPath);
|
|
39836
40492
|
stream.on("error", (err) => {
|
|
39837
40493
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
39838
40494
|
res.destroy();
|
|
@@ -39841,8 +40497,8 @@ function streamFile(res, absPath, logger) {
|
|
|
39841
40497
|
}
|
|
39842
40498
|
|
|
39843
40499
|
// src/attachment/gc.ts
|
|
39844
|
-
var
|
|
39845
|
-
var
|
|
40500
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
40501
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
39846
40502
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
39847
40503
|
function runAttachmentGc(args) {
|
|
39848
40504
|
const now = (args.now ?? Date.now)();
|
|
@@ -39851,38 +40507,38 @@ function runAttachmentGc(args) {
|
|
|
39851
40507
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
39852
40508
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
39853
40509
|
if (entry.stale) continue;
|
|
39854
|
-
if (
|
|
40510
|
+
if (import_node_path19.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
39855
40511
|
}
|
|
39856
40512
|
}
|
|
39857
40513
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
39858
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
40514
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path19.default.join(
|
|
39859
40515
|
args.dataDir,
|
|
39860
40516
|
"sessions",
|
|
39861
40517
|
...scopeSubPath(scope).map(safeFileName),
|
|
39862
40518
|
safeFileName(sessionId)
|
|
39863
40519
|
);
|
|
39864
|
-
const attRoot =
|
|
40520
|
+
const attRoot = import_node_path19.default.join(sessionDir, ".attachments");
|
|
39865
40521
|
let hashDirs;
|
|
39866
40522
|
try {
|
|
39867
|
-
hashDirs =
|
|
40523
|
+
hashDirs = import_node_fs19.default.readdirSync(attRoot);
|
|
39868
40524
|
} catch (err) {
|
|
39869
40525
|
if (err.code === "ENOENT") continue;
|
|
39870
40526
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
39871
40527
|
continue;
|
|
39872
40528
|
}
|
|
39873
40529
|
for (const hashDir of hashDirs) {
|
|
39874
|
-
const hashDirAbs =
|
|
40530
|
+
const hashDirAbs = import_node_path19.default.join(attRoot, hashDir);
|
|
39875
40531
|
let files;
|
|
39876
40532
|
try {
|
|
39877
|
-
files =
|
|
40533
|
+
files = import_node_fs19.default.readdirSync(hashDirAbs);
|
|
39878
40534
|
} catch {
|
|
39879
40535
|
continue;
|
|
39880
40536
|
}
|
|
39881
40537
|
for (const name of files) {
|
|
39882
|
-
const file =
|
|
40538
|
+
const file = import_node_path19.default.join(hashDirAbs, name);
|
|
39883
40539
|
let stat;
|
|
39884
40540
|
try {
|
|
39885
|
-
stat =
|
|
40541
|
+
stat = import_node_fs19.default.statSync(file);
|
|
39886
40542
|
} catch {
|
|
39887
40543
|
continue;
|
|
39888
40544
|
}
|
|
@@ -39891,26 +40547,26 @@ function runAttachmentGc(args) {
|
|
|
39891
40547
|
if (age < ttlMs) continue;
|
|
39892
40548
|
if (liveAbs.has(file)) continue;
|
|
39893
40549
|
try {
|
|
39894
|
-
|
|
40550
|
+
import_node_fs19.default.unlinkSync(file);
|
|
39895
40551
|
} catch (err) {
|
|
39896
40552
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
39897
40553
|
}
|
|
39898
40554
|
}
|
|
39899
40555
|
try {
|
|
39900
|
-
if (
|
|
40556
|
+
if (import_node_fs19.default.readdirSync(hashDirAbs).length === 0) import_node_fs19.default.rmdirSync(hashDirAbs);
|
|
39901
40557
|
} catch {
|
|
39902
40558
|
}
|
|
39903
40559
|
}
|
|
39904
40560
|
try {
|
|
39905
|
-
if (
|
|
40561
|
+
if (import_node_fs19.default.readdirSync(attRoot).length === 0) import_node_fs19.default.rmdirSync(attRoot);
|
|
39906
40562
|
} catch {
|
|
39907
40563
|
}
|
|
39908
40564
|
}
|
|
39909
40565
|
}
|
|
39910
40566
|
|
|
39911
40567
|
// src/attachment/group.ts
|
|
39912
|
-
var
|
|
39913
|
-
var
|
|
40568
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
40569
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
39914
40570
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
39915
40571
|
init_protocol();
|
|
39916
40572
|
var GroupFileStore = class {
|
|
@@ -39922,11 +40578,11 @@ var GroupFileStore = class {
|
|
|
39922
40578
|
this.logger = opts.logger;
|
|
39923
40579
|
}
|
|
39924
40580
|
rootForScope(scope) {
|
|
39925
|
-
return
|
|
40581
|
+
return import_node_path20.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
39926
40582
|
}
|
|
39927
40583
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
39928
40584
|
filePath(scope, sessionId) {
|
|
39929
|
-
return
|
|
40585
|
+
return import_node_path20.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
39930
40586
|
}
|
|
39931
40587
|
cacheKey(scope, sessionId) {
|
|
39932
40588
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -39935,7 +40591,7 @@ var GroupFileStore = class {
|
|
|
39935
40591
|
readFile(scope, sessionId) {
|
|
39936
40592
|
const file = this.filePath(scope, sessionId);
|
|
39937
40593
|
try {
|
|
39938
|
-
const raw =
|
|
40594
|
+
const raw = import_node_fs20.default.readFileSync(file, "utf8");
|
|
39939
40595
|
const parsed = JSON.parse(raw);
|
|
39940
40596
|
if (!Array.isArray(parsed)) {
|
|
39941
40597
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -39961,10 +40617,10 @@ var GroupFileStore = class {
|
|
|
39961
40617
|
}
|
|
39962
40618
|
writeFile(scope, sessionId, entries) {
|
|
39963
40619
|
const file = this.filePath(scope, sessionId);
|
|
39964
|
-
|
|
40620
|
+
import_node_fs20.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
|
|
39965
40621
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39966
|
-
|
|
39967
|
-
|
|
40622
|
+
import_node_fs20.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
40623
|
+
import_node_fs20.default.renameSync(tmp, file);
|
|
39968
40624
|
}
|
|
39969
40625
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
39970
40626
|
list(scope, sessionId) {
|
|
@@ -40050,10 +40706,10 @@ var GroupFileStore = class {
|
|
|
40050
40706
|
};
|
|
40051
40707
|
|
|
40052
40708
|
// src/discovery/state-file.ts
|
|
40053
|
-
var
|
|
40054
|
-
var
|
|
40709
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
40710
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40055
40711
|
function defaultStateFilePath(dataDir) {
|
|
40056
|
-
return
|
|
40712
|
+
return import_node_path21.default.join(dataDir, "state.json");
|
|
40057
40713
|
}
|
|
40058
40714
|
function isPidAlive(pid) {
|
|
40059
40715
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -40075,7 +40731,7 @@ var StateFileManager = class {
|
|
|
40075
40731
|
}
|
|
40076
40732
|
read() {
|
|
40077
40733
|
try {
|
|
40078
|
-
const raw =
|
|
40734
|
+
const raw = import_node_fs21.default.readFileSync(this.file, "utf8");
|
|
40079
40735
|
const parsed = JSON.parse(raw);
|
|
40080
40736
|
return parsed;
|
|
40081
40737
|
} catch {
|
|
@@ -40089,20 +40745,20 @@ var StateFileManager = class {
|
|
|
40089
40745
|
return { status: "stale", existing };
|
|
40090
40746
|
}
|
|
40091
40747
|
write(state) {
|
|
40092
|
-
|
|
40748
|
+
import_node_fs21.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
|
|
40093
40749
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
40094
|
-
|
|
40095
|
-
|
|
40750
|
+
import_node_fs21.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
40751
|
+
import_node_fs21.default.renameSync(tmp, this.file);
|
|
40096
40752
|
if (process.platform !== "win32") {
|
|
40097
40753
|
try {
|
|
40098
|
-
|
|
40754
|
+
import_node_fs21.default.chmodSync(this.file, 384);
|
|
40099
40755
|
} catch {
|
|
40100
40756
|
}
|
|
40101
40757
|
}
|
|
40102
40758
|
}
|
|
40103
40759
|
delete() {
|
|
40104
40760
|
try {
|
|
40105
|
-
|
|
40761
|
+
import_node_fs21.default.unlinkSync(this.file);
|
|
40106
40762
|
} catch {
|
|
40107
40763
|
}
|
|
40108
40764
|
}
|
|
@@ -40117,14 +40773,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
40117
40773
|
}
|
|
40118
40774
|
|
|
40119
40775
|
// src/tunnel/tunnel-manager.ts
|
|
40120
|
-
var
|
|
40121
|
-
var
|
|
40776
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
40777
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
40122
40778
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
40123
40779
|
var import_node_child_process9 = require("child_process");
|
|
40124
40780
|
|
|
40125
40781
|
// src/tunnel/tunnel-store.ts
|
|
40126
|
-
var
|
|
40127
|
-
var
|
|
40782
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40783
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40128
40784
|
var TunnelStore = class {
|
|
40129
40785
|
constructor(filePath) {
|
|
40130
40786
|
this.filePath = filePath;
|
|
@@ -40132,7 +40788,7 @@ var TunnelStore = class {
|
|
|
40132
40788
|
filePath;
|
|
40133
40789
|
async get() {
|
|
40134
40790
|
try {
|
|
40135
|
-
const raw = await
|
|
40791
|
+
const raw = await import_node_fs22.default.promises.readFile(this.filePath, "utf8");
|
|
40136
40792
|
const obj = JSON.parse(raw);
|
|
40137
40793
|
if (!isPersistedTunnel(obj)) return null;
|
|
40138
40794
|
return obj;
|
|
@@ -40143,22 +40799,22 @@ var TunnelStore = class {
|
|
|
40143
40799
|
}
|
|
40144
40800
|
}
|
|
40145
40801
|
async set(v2) {
|
|
40146
|
-
const dir =
|
|
40147
|
-
await
|
|
40802
|
+
const dir = import_node_path22.default.dirname(this.filePath);
|
|
40803
|
+
await import_node_fs22.default.promises.mkdir(dir, { recursive: true });
|
|
40148
40804
|
const data = JSON.stringify(v2, null, 2);
|
|
40149
40805
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
40150
|
-
await
|
|
40806
|
+
await import_node_fs22.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
40151
40807
|
if (process.platform !== "win32") {
|
|
40152
40808
|
try {
|
|
40153
|
-
await
|
|
40809
|
+
await import_node_fs22.default.promises.chmod(tmp, 384);
|
|
40154
40810
|
} catch {
|
|
40155
40811
|
}
|
|
40156
40812
|
}
|
|
40157
|
-
await
|
|
40813
|
+
await import_node_fs22.default.promises.rename(tmp, this.filePath);
|
|
40158
40814
|
}
|
|
40159
40815
|
async clear() {
|
|
40160
40816
|
try {
|
|
40161
|
-
await
|
|
40817
|
+
await import_node_fs22.default.promises.unlink(this.filePath);
|
|
40162
40818
|
} catch (err) {
|
|
40163
40819
|
const code = err?.code;
|
|
40164
40820
|
if (code !== "ENOENT") throw err;
|
|
@@ -40253,11 +40909,11 @@ function escape(v2) {
|
|
|
40253
40909
|
}
|
|
40254
40910
|
|
|
40255
40911
|
// src/tunnel/frpc-binary.ts
|
|
40256
|
-
var
|
|
40912
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40257
40913
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
40258
|
-
var
|
|
40914
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
40259
40915
|
var import_node_child_process7 = require("child_process");
|
|
40260
|
-
var
|
|
40916
|
+
var import_node_stream3 = require("stream");
|
|
40261
40917
|
var import_promises3 = require("stream/promises");
|
|
40262
40918
|
var FRPC_VERSION = "0.68.0";
|
|
40263
40919
|
var UnsupportedPlatformError = class extends Error {
|
|
@@ -40287,20 +40943,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
40287
40943
|
}
|
|
40288
40944
|
async function ensureFrpcBinary(opts) {
|
|
40289
40945
|
if (opts.override) {
|
|
40290
|
-
if (!
|
|
40946
|
+
if (!import_node_fs23.default.existsSync(opts.override)) {
|
|
40291
40947
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
40292
40948
|
}
|
|
40293
40949
|
return opts.override;
|
|
40294
40950
|
}
|
|
40295
40951
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
40296
40952
|
const platform = opts.platform ?? detectPlatform();
|
|
40297
|
-
const binDir =
|
|
40298
|
-
|
|
40953
|
+
const binDir = import_node_path23.default.join(opts.dataDir, "bin");
|
|
40954
|
+
import_node_fs23.default.mkdirSync(binDir, { recursive: true });
|
|
40299
40955
|
cleanupStaleArtifacts(binDir);
|
|
40300
|
-
const stableBin =
|
|
40301
|
-
if (
|
|
40956
|
+
const stableBin = import_node_path23.default.join(binDir, "frpc");
|
|
40957
|
+
if (import_node_fs23.default.existsSync(stableBin)) return stableBin;
|
|
40302
40958
|
const partialBin = `${stableBin}.partial`;
|
|
40303
|
-
const tarballPath =
|
|
40959
|
+
const tarballPath = import_node_path23.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
40304
40960
|
try {
|
|
40305
40961
|
const url = frpcDownloadUrl(version2, platform);
|
|
40306
40962
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -40309,8 +40965,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
40309
40965
|
} else {
|
|
40310
40966
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
40311
40967
|
}
|
|
40312
|
-
|
|
40313
|
-
|
|
40968
|
+
import_node_fs23.default.chmodSync(partialBin, 493);
|
|
40969
|
+
import_node_fs23.default.renameSync(partialBin, stableBin);
|
|
40314
40970
|
} finally {
|
|
40315
40971
|
safeUnlink(tarballPath);
|
|
40316
40972
|
safeUnlink(partialBin);
|
|
@@ -40320,15 +40976,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
40320
40976
|
function cleanupStaleArtifacts(binDir) {
|
|
40321
40977
|
let entries;
|
|
40322
40978
|
try {
|
|
40323
|
-
entries =
|
|
40979
|
+
entries = import_node_fs23.default.readdirSync(binDir);
|
|
40324
40980
|
} catch {
|
|
40325
40981
|
return;
|
|
40326
40982
|
}
|
|
40327
40983
|
for (const name of entries) {
|
|
40328
40984
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
40329
|
-
const full =
|
|
40985
|
+
const full = import_node_path23.default.join(binDir, name);
|
|
40330
40986
|
try {
|
|
40331
|
-
|
|
40987
|
+
import_node_fs23.default.rmSync(full, { recursive: true, force: true });
|
|
40332
40988
|
} catch {
|
|
40333
40989
|
}
|
|
40334
40990
|
}
|
|
@@ -40336,7 +40992,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
40336
40992
|
}
|
|
40337
40993
|
function safeUnlink(p2) {
|
|
40338
40994
|
try {
|
|
40339
|
-
|
|
40995
|
+
import_node_fs23.default.unlinkSync(p2);
|
|
40340
40996
|
} catch {
|
|
40341
40997
|
}
|
|
40342
40998
|
}
|
|
@@ -40347,13 +41003,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
40347
41003
|
if (!res.ok || !res.body) {
|
|
40348
41004
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
40349
41005
|
}
|
|
40350
|
-
const out =
|
|
40351
|
-
const nodeStream =
|
|
41006
|
+
const out = import_node_fs23.default.createWriteStream(dest);
|
|
41007
|
+
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
40352
41008
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
40353
41009
|
}
|
|
40354
41010
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
40355
|
-
const work =
|
|
40356
|
-
|
|
41011
|
+
const work = import_node_path23.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
41012
|
+
import_node_fs23.default.mkdirSync(work, { recursive: true });
|
|
40357
41013
|
try {
|
|
40358
41014
|
await new Promise((resolve6, reject) => {
|
|
40359
41015
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -40361,32 +41017,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
40361
41017
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
40362
41018
|
});
|
|
40363
41019
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
40364
|
-
const src =
|
|
40365
|
-
if (!
|
|
41020
|
+
const src = import_node_path23.default.join(work, dirName, "frpc");
|
|
41021
|
+
if (!import_node_fs23.default.existsSync(src)) {
|
|
40366
41022
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
40367
41023
|
}
|
|
40368
|
-
|
|
41024
|
+
import_node_fs23.default.copyFileSync(src, destBin);
|
|
40369
41025
|
} finally {
|
|
40370
|
-
|
|
41026
|
+
import_node_fs23.default.rmSync(work, { recursive: true, force: true });
|
|
40371
41027
|
}
|
|
40372
41028
|
}
|
|
40373
41029
|
|
|
40374
41030
|
// src/tunnel/frpc-process.ts
|
|
40375
|
-
var
|
|
40376
|
-
var
|
|
41031
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
41032
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
40377
41033
|
var import_node_child_process8 = require("child_process");
|
|
40378
41034
|
function frpcPidFilePath(dataDir) {
|
|
40379
|
-
return
|
|
41035
|
+
return import_node_path24.default.join(dataDir, "frpc.pid");
|
|
40380
41036
|
}
|
|
40381
41037
|
function writeFrpcPid(dataDir, pid) {
|
|
40382
41038
|
try {
|
|
40383
|
-
|
|
41039
|
+
import_node_fs24.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
40384
41040
|
} catch {
|
|
40385
41041
|
}
|
|
40386
41042
|
}
|
|
40387
41043
|
function clearFrpcPid(dataDir) {
|
|
40388
41044
|
try {
|
|
40389
|
-
|
|
41045
|
+
import_node_fs24.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
40390
41046
|
} catch {
|
|
40391
41047
|
}
|
|
40392
41048
|
}
|
|
@@ -40402,7 +41058,7 @@ function defaultIsPidAlive(pid) {
|
|
|
40402
41058
|
}
|
|
40403
41059
|
function defaultReadPidFile(file) {
|
|
40404
41060
|
try {
|
|
40405
|
-
return
|
|
41061
|
+
return import_node_fs24.default.readFileSync(file, "utf8");
|
|
40406
41062
|
} catch {
|
|
40407
41063
|
return null;
|
|
40408
41064
|
}
|
|
@@ -40418,12 +41074,12 @@ function defaultSleep(ms) {
|
|
|
40418
41074
|
}
|
|
40419
41075
|
async function killStaleFrpc(deps) {
|
|
40420
41076
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
40421
|
-
const tomlPath =
|
|
41077
|
+
const tomlPath = import_node_path24.default.join(deps.dataDir, "frpc.toml");
|
|
40422
41078
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
40423
41079
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
40424
41080
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
40425
41081
|
const scanPids = deps.scanFrpcPidsImpl ?? ((tp) => defaultScanFrpcPidsByCmdline(tp, deps.logger));
|
|
40426
|
-
const
|
|
41082
|
+
const sleep2 = deps.sleepImpl ?? defaultSleep;
|
|
40427
41083
|
const victims = /* @__PURE__ */ new Set();
|
|
40428
41084
|
const raw = readPidFile(pidFile);
|
|
40429
41085
|
if (raw) {
|
|
@@ -40442,7 +41098,7 @@ async function killStaleFrpc(deps) {
|
|
|
40442
41098
|
}
|
|
40443
41099
|
if (victims.size === 0) {
|
|
40444
41100
|
try {
|
|
40445
|
-
|
|
41101
|
+
import_node_fs24.default.unlinkSync(pidFile);
|
|
40446
41102
|
} catch {
|
|
40447
41103
|
}
|
|
40448
41104
|
return;
|
|
@@ -40451,9 +41107,9 @@ async function killStaleFrpc(deps) {
|
|
|
40451
41107
|
deps.logger?.warn("tunnel: killing stale frpc before respawn", { pid });
|
|
40452
41108
|
killPid(pid, "SIGKILL");
|
|
40453
41109
|
}
|
|
40454
|
-
await
|
|
41110
|
+
await sleep2(deps.reapWaitMs ?? 300);
|
|
40455
41111
|
try {
|
|
40456
|
-
|
|
41112
|
+
import_node_fs24.default.unlinkSync(pidFile);
|
|
40457
41113
|
} catch {
|
|
40458
41114
|
}
|
|
40459
41115
|
}
|
|
@@ -40490,7 +41146,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
40490
41146
|
var TunnelManager = class {
|
|
40491
41147
|
constructor(deps) {
|
|
40492
41148
|
this.deps = deps;
|
|
40493
|
-
this.store = deps.store ?? new TunnelStore(
|
|
41149
|
+
this.store = deps.store ?? new TunnelStore(import_node_path25.default.join(deps.dataDir, "tunnel.json"));
|
|
40494
41150
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
40495
41151
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
40496
41152
|
}
|
|
@@ -40617,7 +41273,7 @@ var TunnelManager = class {
|
|
|
40617
41273
|
dataDir: this.deps.dataDir,
|
|
40618
41274
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
40619
41275
|
});
|
|
40620
|
-
const tomlPath =
|
|
41276
|
+
const tomlPath = import_node_path25.default.join(this.deps.dataDir, "frpc.toml");
|
|
40621
41277
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
40622
41278
|
const toml = buildFrpcToml({
|
|
40623
41279
|
serverAddr: t.frpsHost,
|
|
@@ -40628,12 +41284,12 @@ var TunnelManager = class {
|
|
|
40628
41284
|
localPort,
|
|
40629
41285
|
logLevel: "info"
|
|
40630
41286
|
});
|
|
40631
|
-
await
|
|
41287
|
+
await import_node_fs25.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
40632
41288
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
40633
41289
|
stdio: ["ignore", "pipe", "pipe"]
|
|
40634
41290
|
});
|
|
40635
|
-
const logFilePath =
|
|
40636
|
-
const logStream =
|
|
41291
|
+
const logFilePath = import_node_path25.default.join(this.deps.dataDir, "frpc.log");
|
|
41292
|
+
const logStream = import_node_fs25.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
40637
41293
|
logStream.on("error", () => {
|
|
40638
41294
|
});
|
|
40639
41295
|
const tee = (chunk) => {
|
|
@@ -40716,27 +41372,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
40716
41372
|
|
|
40717
41373
|
// src/tunnel/device-key.ts
|
|
40718
41374
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
40719
|
-
var
|
|
41375
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
40720
41376
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
40721
41377
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
40722
41378
|
function deriveStableDeviceKey(opts = {}) {
|
|
40723
41379
|
const hostname = opts.hostname ?? import_node_os12.default.hostname();
|
|
40724
41380
|
const uid = opts.uid ?? (typeof import_node_os12.default.userInfo === "function" ? import_node_os12.default.userInfo().uid : 0);
|
|
40725
41381
|
const home = opts.home ?? import_node_os12.default.homedir();
|
|
40726
|
-
const defaultDataDir =
|
|
40727
|
-
const normalizedDataDir = opts.dataDir ?
|
|
41382
|
+
const defaultDataDir = import_node_path26.default.resolve(import_node_path26.default.join(home, ".clawd"));
|
|
41383
|
+
const normalizedDataDir = opts.dataDir ? import_node_path26.default.resolve(opts.dataDir) : null;
|
|
40728
41384
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
40729
41385
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
40730
41386
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
40731
41387
|
}
|
|
40732
41388
|
|
|
40733
41389
|
// src/auth-store.ts
|
|
40734
|
-
var
|
|
40735
|
-
var
|
|
41390
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
41391
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
40736
41392
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
40737
41393
|
var AUTH_FILE_NAME = "auth.json";
|
|
40738
41394
|
function authFilePath(dataDir) {
|
|
40739
|
-
return
|
|
41395
|
+
return import_node_path27.default.join(dataDir, AUTH_FILE_NAME);
|
|
40740
41396
|
}
|
|
40741
41397
|
function loadOrCreateAuthFile(opts) {
|
|
40742
41398
|
const file = authFilePath(opts.dataDir);
|
|
@@ -40770,7 +41426,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
40770
41426
|
}
|
|
40771
41427
|
function readAuthFile(file) {
|
|
40772
41428
|
try {
|
|
40773
|
-
const raw =
|
|
41429
|
+
const raw = import_node_fs26.default.readFileSync(file, "utf8");
|
|
40774
41430
|
const parsed = JSON.parse(raw);
|
|
40775
41431
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
40776
41432
|
return null;
|
|
@@ -40789,25 +41445,25 @@ function readAuthFile(file) {
|
|
|
40789
41445
|
}
|
|
40790
41446
|
}
|
|
40791
41447
|
function writeAuthFile(file, content) {
|
|
40792
|
-
|
|
40793
|
-
|
|
41448
|
+
import_node_fs26.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
|
|
41449
|
+
import_node_fs26.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
40794
41450
|
try {
|
|
40795
|
-
|
|
41451
|
+
import_node_fs26.default.chmodSync(file, 384);
|
|
40796
41452
|
} catch {
|
|
40797
41453
|
}
|
|
40798
41454
|
}
|
|
40799
41455
|
|
|
40800
41456
|
// src/owner-profile.ts
|
|
40801
|
-
var
|
|
41457
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
40802
41458
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
40803
|
-
var
|
|
41459
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
40804
41460
|
var PROFILE_FILENAME = "profile.json";
|
|
40805
41461
|
function loadOwnerDisplayName(dataDir) {
|
|
40806
41462
|
const fallback = import_node_os13.default.userInfo().username;
|
|
40807
|
-
const profilePath =
|
|
41463
|
+
const profilePath = import_node_path28.default.join(dataDir, PROFILE_FILENAME);
|
|
40808
41464
|
let raw;
|
|
40809
41465
|
try {
|
|
40810
|
-
raw =
|
|
41466
|
+
raw = import_node_fs27.default.readFileSync(profilePath, "utf8");
|
|
40811
41467
|
} catch {
|
|
40812
41468
|
return fallback;
|
|
40813
41469
|
}
|
|
@@ -40830,18 +41486,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
40830
41486
|
}
|
|
40831
41487
|
|
|
40832
41488
|
// src/feishu-auth/owner-identity-store.ts
|
|
40833
|
-
var
|
|
40834
|
-
var
|
|
41489
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41490
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
40835
41491
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
40836
41492
|
var OwnerIdentityStore = class {
|
|
40837
41493
|
file;
|
|
40838
41494
|
constructor(dataDir) {
|
|
40839
|
-
this.file =
|
|
41495
|
+
this.file = import_node_path29.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
40840
41496
|
}
|
|
40841
41497
|
read() {
|
|
40842
41498
|
let raw;
|
|
40843
41499
|
try {
|
|
40844
|
-
raw =
|
|
41500
|
+
raw = import_node_fs28.default.readFileSync(this.file, "utf8");
|
|
40845
41501
|
} catch {
|
|
40846
41502
|
return null;
|
|
40847
41503
|
}
|
|
@@ -40869,16 +41525,16 @@ var OwnerIdentityStore = class {
|
|
|
40869
41525
|
};
|
|
40870
41526
|
}
|
|
40871
41527
|
write(record) {
|
|
40872
|
-
|
|
40873
|
-
|
|
41528
|
+
import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(this.file), { recursive: true });
|
|
41529
|
+
import_node_fs28.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
40874
41530
|
try {
|
|
40875
|
-
|
|
41531
|
+
import_node_fs28.default.chmodSync(this.file, 384);
|
|
40876
41532
|
} catch {
|
|
40877
41533
|
}
|
|
40878
41534
|
}
|
|
40879
41535
|
clear() {
|
|
40880
41536
|
try {
|
|
40881
|
-
|
|
41537
|
+
import_node_fs28.default.unlinkSync(this.file);
|
|
40882
41538
|
} catch (err) {
|
|
40883
41539
|
const code = err?.code;
|
|
40884
41540
|
if (code !== "ENOENT") throw err;
|
|
@@ -40999,9 +41655,9 @@ var CentralClientError = class extends Error {
|
|
|
40999
41655
|
code;
|
|
41000
41656
|
cause;
|
|
41001
41657
|
};
|
|
41002
|
-
async function centralRequest(opts,
|
|
41658
|
+
async function centralRequest(opts, path59, init) {
|
|
41003
41659
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
41004
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
41660
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path59}`;
|
|
41005
41661
|
const ctrl = new AbortController();
|
|
41006
41662
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
41007
41663
|
let res;
|
|
@@ -41143,8 +41799,8 @@ function verifyConnectToken(args) {
|
|
|
41143
41799
|
}
|
|
41144
41800
|
|
|
41145
41801
|
// src/feishu-auth/server-key.ts
|
|
41146
|
-
var
|
|
41147
|
-
var
|
|
41802
|
+
var fs37 = __toESM(require("fs"), 1);
|
|
41803
|
+
var path38 = __toESM(require("path"), 1);
|
|
41148
41804
|
var FILE_NAME2 = "server-signing-key.json";
|
|
41149
41805
|
var ServerKeyStore = class {
|
|
41150
41806
|
constructor(dataDir) {
|
|
@@ -41152,12 +41808,12 @@ var ServerKeyStore = class {
|
|
|
41152
41808
|
}
|
|
41153
41809
|
dataDir;
|
|
41154
41810
|
filePath() {
|
|
41155
|
-
return
|
|
41811
|
+
return path38.join(this.dataDir, FILE_NAME2);
|
|
41156
41812
|
}
|
|
41157
41813
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
41158
41814
|
read() {
|
|
41159
41815
|
try {
|
|
41160
|
-
const raw =
|
|
41816
|
+
const raw = fs37.readFileSync(this.filePath(), "utf8");
|
|
41161
41817
|
const parsed = JSON.parse(raw);
|
|
41162
41818
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
41163
41819
|
return parsed.publicKeyPem;
|
|
@@ -41172,12 +41828,12 @@ var ServerKeyStore = class {
|
|
|
41172
41828
|
publicKeyPem,
|
|
41173
41829
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41174
41830
|
};
|
|
41175
|
-
|
|
41176
|
-
|
|
41831
|
+
fs37.mkdirSync(this.dataDir, { recursive: true });
|
|
41832
|
+
fs37.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
41177
41833
|
}
|
|
41178
41834
|
clear() {
|
|
41179
41835
|
try {
|
|
41180
|
-
|
|
41836
|
+
fs37.unlinkSync(this.filePath());
|
|
41181
41837
|
} catch {
|
|
41182
41838
|
}
|
|
41183
41839
|
}
|
|
@@ -41190,12 +41846,12 @@ init_protocol();
|
|
|
41190
41846
|
init_protocol();
|
|
41191
41847
|
|
|
41192
41848
|
// src/session/fork.ts
|
|
41193
|
-
var
|
|
41849
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41194
41850
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
41195
|
-
var
|
|
41851
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
41196
41852
|
init_claude_history();
|
|
41197
41853
|
function readJsonlEntries(file) {
|
|
41198
|
-
const raw =
|
|
41854
|
+
const raw = import_node_fs29.default.readFileSync(file, "utf8");
|
|
41199
41855
|
const out = [];
|
|
41200
41856
|
for (const line of raw.split("\n")) {
|
|
41201
41857
|
const t = line.trim();
|
|
@@ -41208,10 +41864,10 @@ function readJsonlEntries(file) {
|
|
|
41208
41864
|
return out;
|
|
41209
41865
|
}
|
|
41210
41866
|
function forkSession(input) {
|
|
41211
|
-
const baseDir = input.baseDir ??
|
|
41212
|
-
const projectDir =
|
|
41213
|
-
const sourceFile =
|
|
41214
|
-
if (!
|
|
41867
|
+
const baseDir = input.baseDir ?? import_node_path30.default.join(import_node_os14.default.homedir(), ".claude");
|
|
41868
|
+
const projectDir = import_node_path30.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
41869
|
+
const sourceFile = import_node_path30.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
41870
|
+
if (!import_node_fs29.default.existsSync(sourceFile)) {
|
|
41215
41871
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
41216
41872
|
}
|
|
41217
41873
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -41241,9 +41897,9 @@ function forkSession(input) {
|
|
|
41241
41897
|
}
|
|
41242
41898
|
forkedLines.push(JSON.stringify(forked));
|
|
41243
41899
|
}
|
|
41244
|
-
const forkedFilePath =
|
|
41245
|
-
|
|
41246
|
-
|
|
41900
|
+
const forkedFilePath = import_node_path30.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
41901
|
+
import_node_fs29.default.mkdirSync(projectDir, { recursive: true });
|
|
41902
|
+
import_node_fs29.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
41247
41903
|
return { forkedToolSessionId, forkedFilePath };
|
|
41248
41904
|
}
|
|
41249
41905
|
|
|
@@ -41619,7 +42275,7 @@ function buildPermissionHandlers(deps) {
|
|
|
41619
42275
|
}
|
|
41620
42276
|
|
|
41621
42277
|
// src/handlers/history.ts
|
|
41622
|
-
var
|
|
42278
|
+
var path41 = __toESM(require("path"), 1);
|
|
41623
42279
|
init_protocol();
|
|
41624
42280
|
|
|
41625
42281
|
// src/session/recent-dirs.ts
|
|
@@ -41637,7 +42293,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
41637
42293
|
}
|
|
41638
42294
|
|
|
41639
42295
|
// src/permission/persona-paths.ts
|
|
41640
|
-
var
|
|
42296
|
+
var path40 = __toESM(require("path"), 1);
|
|
41641
42297
|
function getAllowedPersonaIds(grants, action) {
|
|
41642
42298
|
const ids = /* @__PURE__ */ new Set();
|
|
41643
42299
|
for (const g2 of grants) {
|
|
@@ -41650,31 +42306,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
41650
42306
|
return ids;
|
|
41651
42307
|
}
|
|
41652
42308
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
41653
|
-
const target =
|
|
42309
|
+
const target = path40.resolve(absPath);
|
|
41654
42310
|
if (userWorkDir) {
|
|
41655
|
-
const u =
|
|
41656
|
-
const usep = u.endsWith(
|
|
42311
|
+
const u = path40.resolve(userWorkDir);
|
|
42312
|
+
const usep = u.endsWith(path40.sep) ? "" : path40.sep;
|
|
41657
42313
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
41658
42314
|
}
|
|
41659
|
-
const root =
|
|
41660
|
-
const sep2 = root.endsWith(
|
|
42315
|
+
const root = path40.resolve(personaRoot);
|
|
42316
|
+
const sep2 = root.endsWith(path40.sep) ? "" : path40.sep;
|
|
41661
42317
|
if (!target.startsWith(root + sep2)) return false;
|
|
41662
|
-
const rel =
|
|
42318
|
+
const rel = path40.relative(root, target);
|
|
41663
42319
|
if (!rel || rel.startsWith("..")) return false;
|
|
41664
|
-
const personaId = rel.split(
|
|
42320
|
+
const personaId = rel.split(path40.sep)[0];
|
|
41665
42321
|
if (!personaId) return false;
|
|
41666
42322
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
41667
42323
|
if (allowed === "*") return true;
|
|
41668
42324
|
return allowed.has(personaId);
|
|
41669
42325
|
}
|
|
41670
42326
|
function personaIdFromPath(absPath, personaRoot) {
|
|
41671
|
-
const root =
|
|
41672
|
-
const target =
|
|
41673
|
-
const sep2 = root.endsWith(
|
|
42327
|
+
const root = path40.resolve(personaRoot);
|
|
42328
|
+
const target = path40.resolve(absPath);
|
|
42329
|
+
const sep2 = root.endsWith(path40.sep) ? "" : path40.sep;
|
|
41674
42330
|
if (!target.startsWith(root + sep2)) return null;
|
|
41675
|
-
const rel =
|
|
42331
|
+
const rel = path40.relative(root, target);
|
|
41676
42332
|
if (!rel || rel.startsWith("..")) return null;
|
|
41677
|
-
const id = rel.split(
|
|
42333
|
+
const id = rel.split(path40.sep)[0];
|
|
41678
42334
|
return id || null;
|
|
41679
42335
|
}
|
|
41680
42336
|
|
|
@@ -41701,7 +42357,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41701
42357
|
if (!pid) return false;
|
|
41702
42358
|
return isGuestPathAllowed(
|
|
41703
42359
|
ctx.grants,
|
|
41704
|
-
|
|
42360
|
+
path41.join(personaRoot, pid),
|
|
41705
42361
|
personaRoot,
|
|
41706
42362
|
"read",
|
|
41707
42363
|
userWorkDir
|
|
@@ -41713,7 +42369,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41713
42369
|
};
|
|
41714
42370
|
const list = async (frame, _client, ctx) => {
|
|
41715
42371
|
const args = HistoryListArgs.parse(frame);
|
|
41716
|
-
assertGuestPath(ctx,
|
|
42372
|
+
assertGuestPath(ctx, path41.resolve(args.projectPath), personaRoot, "history:list");
|
|
41717
42373
|
const sessions = await history.listSessions(args);
|
|
41718
42374
|
return { response: { type: "history:list", sessions } };
|
|
41719
42375
|
};
|
|
@@ -41745,13 +42401,13 @@ function buildHistoryHandlers(deps) {
|
|
|
41745
42401
|
};
|
|
41746
42402
|
const subagents = async (frame, _client, ctx) => {
|
|
41747
42403
|
const args = HistorySubagentsArgs.parse(frame);
|
|
41748
|
-
assertGuestPath(ctx,
|
|
42404
|
+
assertGuestPath(ctx, path41.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
41749
42405
|
const subs = await history.listSubagents(args);
|
|
41750
42406
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
41751
42407
|
};
|
|
41752
42408
|
const subagentRead = async (frame, _client, ctx) => {
|
|
41753
42409
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
41754
|
-
assertGuestPath(ctx,
|
|
42410
|
+
assertGuestPath(ctx, path41.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
41755
42411
|
const res = await history.readSubagent(args);
|
|
41756
42412
|
return { response: { type: "history:subagent-read", ...res } };
|
|
41757
42413
|
};
|
|
@@ -41760,7 +42416,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41760
42416
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
41761
42417
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
41762
42418
|
const filtered = dirs.filter(
|
|
41763
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
42419
|
+
(d) => isGuestPathAllowed(ctx.grants, path41.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
41764
42420
|
);
|
|
41765
42421
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
41766
42422
|
}
|
|
@@ -41777,7 +42433,7 @@ function buildHistoryHandlers(deps) {
|
|
|
41777
42433
|
}
|
|
41778
42434
|
|
|
41779
42435
|
// src/handlers/workspace.ts
|
|
41780
|
-
var
|
|
42436
|
+
var path42 = __toESM(require("path"), 1);
|
|
41781
42437
|
var os15 = __toESM(require("os"), 1);
|
|
41782
42438
|
init_protocol();
|
|
41783
42439
|
init_protocol();
|
|
@@ -41819,22 +42475,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41819
42475
|
const args = WorkspaceListArgs.parse(frame);
|
|
41820
42476
|
const isGuest = ctx?.principal.kind === "guest";
|
|
41821
42477
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
41822
|
-
const resolvedCwd =
|
|
41823
|
-
const target = args.path ?
|
|
42478
|
+
const resolvedCwd = path42.resolve(args.cwd ?? fallbackCwd);
|
|
42479
|
+
const target = args.path ? path42.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
41824
42480
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
41825
42481
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
41826
42482
|
return { response: { type: "workspace:list", ...res } };
|
|
41827
42483
|
};
|
|
41828
42484
|
const read = async (frame, _client, ctx) => {
|
|
41829
42485
|
const args = WorkspaceReadArgs.parse(frame);
|
|
41830
|
-
const target =
|
|
42486
|
+
const target = path42.isAbsolute(args.path) ? path42.resolve(args.path) : path42.resolve(args.cwd, args.path);
|
|
41831
42487
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
41832
42488
|
const res = workspace.read(args);
|
|
41833
42489
|
return { response: { type: "workspace:read", ...res } };
|
|
41834
42490
|
};
|
|
41835
42491
|
const skillsList = async (frame, _client, ctx) => {
|
|
41836
42492
|
const args = SkillsListArgs.parse(frame);
|
|
41837
|
-
const cwdAbs =
|
|
42493
|
+
const cwdAbs = path42.resolve(args.cwd);
|
|
41838
42494
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
41839
42495
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
41840
42496
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -41846,7 +42502,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41846
42502
|
};
|
|
41847
42503
|
const agentsList = async (frame, _client, ctx) => {
|
|
41848
42504
|
const args = AgentsListArgs.parse(frame);
|
|
41849
|
-
const cwdAbs =
|
|
42505
|
+
const cwdAbs = path42.resolve(args.cwd);
|
|
41850
42506
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
41851
42507
|
if (args.tool === "codex") {
|
|
41852
42508
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -41868,20 +42524,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
41868
42524
|
}
|
|
41869
42525
|
|
|
41870
42526
|
// src/handlers/git.ts
|
|
41871
|
-
var
|
|
42527
|
+
var path44 = __toESM(require("path"), 1);
|
|
41872
42528
|
init_protocol();
|
|
41873
42529
|
init_protocol();
|
|
41874
42530
|
|
|
41875
42531
|
// src/workspace/git.ts
|
|
41876
42532
|
var import_node_child_process10 = require("child_process");
|
|
41877
|
-
var
|
|
41878
|
-
var
|
|
42533
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
42534
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
41879
42535
|
var import_node_util = require("util");
|
|
41880
42536
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
41881
42537
|
function normalizePath(p2) {
|
|
41882
|
-
const resolved =
|
|
42538
|
+
const resolved = import_node_path31.default.resolve(p2);
|
|
41883
42539
|
try {
|
|
41884
|
-
return
|
|
42540
|
+
return import_node_fs30.default.realpathSync(resolved);
|
|
41885
42541
|
} catch {
|
|
41886
42542
|
return resolved;
|
|
41887
42543
|
}
|
|
@@ -41955,7 +42611,7 @@ async function listGitBranches(cwd) {
|
|
|
41955
42611
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
41956
42612
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
41957
42613
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
41958
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
42614
|
+
if (!isGuestPathAllowed(ctx.grants, path44.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
41959
42615
|
throw new ClawdError(
|
|
41960
42616
|
ERROR_CODES.UNAUTHORIZED,
|
|
41961
42617
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -42371,6 +43027,7 @@ function buildReadyFrame(deps, client) {
|
|
|
42371
43027
|
if (deps.httpToken) fileSharing.httpToken = deps.httpToken;
|
|
42372
43028
|
}
|
|
42373
43029
|
const daemonSource = process.env.CLAWD_DAEMON_SOURCE === "ota" ? "ota" : "packaged";
|
|
43030
|
+
const logShipping = deps.getLogShipping ? deps.getLogShipping() : null;
|
|
42374
43031
|
return {
|
|
42375
43032
|
version,
|
|
42376
43033
|
protocolVersion: PROTOCOL_VERSION,
|
|
@@ -42381,7 +43038,8 @@ function buildReadyFrame(deps, client) {
|
|
|
42381
43038
|
tunnelUrl,
|
|
42382
43039
|
mode: deps.mode,
|
|
42383
43040
|
daemonSource,
|
|
42384
|
-
...fileSharing
|
|
43041
|
+
...fileSharing,
|
|
43042
|
+
...logShipping ? { logShipping } : {}
|
|
42385
43043
|
};
|
|
42386
43044
|
}
|
|
42387
43045
|
function buildMetaHandlers(deps) {
|
|
@@ -42469,7 +43127,7 @@ function buildPersonaHandlers(deps) {
|
|
|
42469
43127
|
}
|
|
42470
43128
|
|
|
42471
43129
|
// src/handlers/attachment.ts
|
|
42472
|
-
var
|
|
43130
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
42473
43131
|
init_protocol();
|
|
42474
43132
|
init_protocol();
|
|
42475
43133
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -42524,12 +43182,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
42524
43182
|
`session ${args.sessionId} scope unresolved`
|
|
42525
43183
|
);
|
|
42526
43184
|
}
|
|
42527
|
-
const cwdAbs =
|
|
42528
|
-
const candidateAbs =
|
|
43185
|
+
const cwdAbs = import_node_path32.default.resolve(sessionFile.cwd);
|
|
43186
|
+
const candidateAbs = import_node_path32.default.isAbsolute(args.relPath) ? import_node_path32.default.resolve(args.relPath) : import_node_path32.default.resolve(cwdAbs, args.relPath);
|
|
42529
43187
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
42530
43188
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
42531
43189
|
const entry = entries.find((e) => {
|
|
42532
|
-
const storedAbs =
|
|
43190
|
+
const storedAbs = import_node_path32.default.isAbsolute(e.relPath) ? import_node_path32.default.resolve(e.relPath) : import_node_path32.default.resolve(cwdAbs, e.relPath);
|
|
42533
43191
|
return storedAbs === candidateAbs && !e.stale;
|
|
42534
43192
|
});
|
|
42535
43193
|
if (!entry) {
|
|
@@ -42553,7 +43211,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
42553
43211
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
42554
43212
|
const f = deps.sessionStore.read(sessionId);
|
|
42555
43213
|
if (!f) return;
|
|
42556
|
-
assertGuestAttachmentPath(ctx,
|
|
43214
|
+
assertGuestAttachmentPath(ctx, import_node_path32.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
42557
43215
|
}
|
|
42558
43216
|
const groupAdd = async (frame, _client, ctx) => {
|
|
42559
43217
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -42625,19 +43283,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
42625
43283
|
|
|
42626
43284
|
// src/handlers/extension.ts
|
|
42627
43285
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
42628
|
-
var
|
|
43286
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
42629
43287
|
init_protocol();
|
|
42630
43288
|
|
|
42631
43289
|
// src/extension/bundle-zip.ts
|
|
42632
43290
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
42633
|
-
var
|
|
43291
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
42634
43292
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
42635
43293
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
42636
43294
|
async function bundleExtensionDir(dir) {
|
|
42637
43295
|
const entries = await listFilesSorted(dir);
|
|
42638
43296
|
const zip = new import_jszip2.default();
|
|
42639
43297
|
for (const rel of entries) {
|
|
42640
|
-
const abs =
|
|
43298
|
+
const abs = import_node_path33.default.join(dir, rel);
|
|
42641
43299
|
const content = await import_promises4.default.readFile(abs);
|
|
42642
43300
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
42643
43301
|
}
|
|
@@ -42658,7 +43316,7 @@ async function listFilesSorted(rootDir) {
|
|
|
42658
43316
|
return out;
|
|
42659
43317
|
}
|
|
42660
43318
|
async function walk(absRoot, relPrefix, out) {
|
|
42661
|
-
const dirAbs =
|
|
43319
|
+
const dirAbs = import_node_path33.default.join(absRoot, relPrefix);
|
|
42662
43320
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
42663
43321
|
for (const e of entries) {
|
|
42664
43322
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -42712,25 +43370,25 @@ function computePublishCheck(args) {
|
|
|
42712
43370
|
|
|
42713
43371
|
// src/extension/install-flow.ts
|
|
42714
43372
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
42715
|
-
var
|
|
43373
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
42716
43374
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
42717
43375
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
42718
43376
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
42719
43377
|
|
|
42720
43378
|
// src/extension/paths.ts
|
|
42721
43379
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
42722
|
-
var
|
|
43380
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
42723
43381
|
function clawdHomeRoot(override) {
|
|
42724
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
43382
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path34.default.join(import_node_os16.default.homedir(), ".clawd");
|
|
42725
43383
|
}
|
|
42726
43384
|
function extensionsRoot(override) {
|
|
42727
|
-
return
|
|
43385
|
+
return import_node_path34.default.join(clawdHomeRoot(override), "extensions");
|
|
42728
43386
|
}
|
|
42729
43387
|
function publishedChannelsFile(override) {
|
|
42730
|
-
return
|
|
43388
|
+
return import_node_path34.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
42731
43389
|
}
|
|
42732
43390
|
function bundleCacheRoot(override) {
|
|
42733
|
-
return
|
|
43391
|
+
return import_node_path34.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
42734
43392
|
}
|
|
42735
43393
|
|
|
42736
43394
|
// src/extension/install-flow.ts
|
|
@@ -42757,7 +43415,7 @@ async function installFromChannel(args, deps) {
|
|
|
42757
43415
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
42758
43416
|
}
|
|
42759
43417
|
for (const name of Object.keys(zip.files)) {
|
|
42760
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43418
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path35.default.isAbsolute(name)) {
|
|
42761
43419
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
42762
43420
|
}
|
|
42763
43421
|
}
|
|
@@ -42789,7 +43447,7 @@ async function installFromChannel(args, deps) {
|
|
|
42789
43447
|
);
|
|
42790
43448
|
}
|
|
42791
43449
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
42792
|
-
const destDir =
|
|
43450
|
+
const destDir = import_node_path35.default.join(deps.extensionsRoot, localExtId);
|
|
42793
43451
|
let destExists = false;
|
|
42794
43452
|
try {
|
|
42795
43453
|
await import_promises5.default.access(destDir);
|
|
@@ -42803,16 +43461,16 @@ async function installFromChannel(args, deps) {
|
|
|
42803
43461
|
);
|
|
42804
43462
|
}
|
|
42805
43463
|
const stage = await import_promises5.default.mkdtemp(
|
|
42806
|
-
|
|
43464
|
+
import_node_path35.default.join(import_node_os17.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
42807
43465
|
);
|
|
42808
43466
|
try {
|
|
42809
43467
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
42810
|
-
const dest =
|
|
43468
|
+
const dest = import_node_path35.default.join(stage, name);
|
|
42811
43469
|
if (entry.dir) {
|
|
42812
43470
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
42813
43471
|
continue;
|
|
42814
43472
|
}
|
|
42815
|
-
await import_promises5.default.mkdir(
|
|
43473
|
+
await import_promises5.default.mkdir(import_node_path35.default.dirname(dest), { recursive: true });
|
|
42816
43474
|
if (name === "manifest.json") {
|
|
42817
43475
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
42818
43476
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -42833,7 +43491,7 @@ async function installFromChannel(args, deps) {
|
|
|
42833
43491
|
|
|
42834
43492
|
// src/extension/update-flow.ts
|
|
42835
43493
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
42836
|
-
var
|
|
43494
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
42837
43495
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
42838
43496
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
42839
43497
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -42850,11 +43508,11 @@ async function updateFromChannel(args, deps) {
|
|
|
42850
43508
|
channelRef.extId,
|
|
42851
43509
|
channelRef.ownerPrincipalId
|
|
42852
43510
|
);
|
|
42853
|
-
const liveDir =
|
|
43511
|
+
const liveDir = import_node_path36.default.join(deps.extensionsRoot, localExtId);
|
|
42854
43512
|
const prevDir = `${liveDir}.prev`;
|
|
42855
43513
|
let existingVersion;
|
|
42856
43514
|
try {
|
|
42857
|
-
const raw = await import_promises6.default.readFile(
|
|
43515
|
+
const raw = await import_promises6.default.readFile(import_node_path36.default.join(liveDir, "manifest.json"), "utf8");
|
|
42858
43516
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
42859
43517
|
if (!parsed2.success) {
|
|
42860
43518
|
throw new UpdateError(
|
|
@@ -42887,7 +43545,7 @@ async function updateFromChannel(args, deps) {
|
|
|
42887
43545
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
42888
43546
|
}
|
|
42889
43547
|
for (const name of Object.keys(zip.files)) {
|
|
42890
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43548
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
|
|
42891
43549
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
42892
43550
|
}
|
|
42893
43551
|
}
|
|
@@ -42922,16 +43580,16 @@ async function updateFromChannel(args, deps) {
|
|
|
42922
43580
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
42923
43581
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
42924
43582
|
const stage = await import_promises6.default.mkdtemp(
|
|
42925
|
-
|
|
43583
|
+
import_node_path36.default.join(import_node_os18.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
42926
43584
|
);
|
|
42927
43585
|
try {
|
|
42928
43586
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
42929
|
-
const dest =
|
|
43587
|
+
const dest = import_node_path36.default.join(stage, name);
|
|
42930
43588
|
if (entry.dir) {
|
|
42931
43589
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
42932
43590
|
continue;
|
|
42933
43591
|
}
|
|
42934
|
-
await import_promises6.default.mkdir(
|
|
43592
|
+
await import_promises6.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
|
|
42935
43593
|
if (name === "manifest.json") {
|
|
42936
43594
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
42937
43595
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43024,7 +43682,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43024
43682
|
);
|
|
43025
43683
|
}
|
|
43026
43684
|
}
|
|
43027
|
-
const manifestPath =
|
|
43685
|
+
const manifestPath = import_node_path37.default.join(root, extId, "manifest.json");
|
|
43028
43686
|
const manifest = await readManifest(root, extId);
|
|
43029
43687
|
const next = { ...manifest, version: newVersion };
|
|
43030
43688
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -43032,7 +43690,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43032
43690
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
43033
43691
|
}
|
|
43034
43692
|
async function readManifest(root, extId) {
|
|
43035
|
-
const file =
|
|
43693
|
+
const file = import_node_path37.default.join(root, extId, "manifest.json");
|
|
43036
43694
|
let raw;
|
|
43037
43695
|
try {
|
|
43038
43696
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -43123,7 +43781,7 @@ function buildExtensionHandlers(deps) {
|
|
|
43123
43781
|
};
|
|
43124
43782
|
async function buildSnapshotMeta(extId) {
|
|
43125
43783
|
const manifest = await readManifest(deps.root, extId);
|
|
43126
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
43784
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path37.default.join(deps.root, extId));
|
|
43127
43785
|
return { manifest, contentHash: sha256, buffer };
|
|
43128
43786
|
}
|
|
43129
43787
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -43304,9 +43962,9 @@ function buildExtensionHandlers(deps) {
|
|
|
43304
43962
|
}
|
|
43305
43963
|
|
|
43306
43964
|
// src/app-builder/project-store.ts
|
|
43307
|
-
var
|
|
43965
|
+
var import_node_fs31 = require("fs");
|
|
43308
43966
|
var import_node_child_process11 = require("child_process");
|
|
43309
|
-
var
|
|
43967
|
+
var import_node_path38 = require("path");
|
|
43310
43968
|
init_protocol();
|
|
43311
43969
|
var PROJECTS_DIR = "projects";
|
|
43312
43970
|
var META_FILE = ".clawd-project.json";
|
|
@@ -43320,19 +43978,19 @@ var ProjectStore = class {
|
|
|
43320
43978
|
root;
|
|
43321
43979
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
43322
43980
|
metaPath(name) {
|
|
43323
|
-
return (0,
|
|
43981
|
+
return (0, import_node_path38.join)(this.projectsRoot(), name, META_FILE);
|
|
43324
43982
|
}
|
|
43325
43983
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
43326
43984
|
projectDir(name) {
|
|
43327
|
-
return (0,
|
|
43985
|
+
return (0, import_node_path38.join)(this.projectsRoot(), name);
|
|
43328
43986
|
}
|
|
43329
43987
|
projectsRoot() {
|
|
43330
|
-
return (0,
|
|
43988
|
+
return (0, import_node_path38.join)(this.root, PROJECTS_DIR);
|
|
43331
43989
|
}
|
|
43332
43990
|
async list() {
|
|
43333
43991
|
let entries;
|
|
43334
43992
|
try {
|
|
43335
|
-
entries = await
|
|
43993
|
+
entries = await import_node_fs31.promises.readdir(this.projectsRoot());
|
|
43336
43994
|
} catch (err) {
|
|
43337
43995
|
if (err.code === "ENOENT") return [];
|
|
43338
43996
|
throw err;
|
|
@@ -43340,7 +43998,7 @@ var ProjectStore = class {
|
|
|
43340
43998
|
const out = [];
|
|
43341
43999
|
for (const name of entries) {
|
|
43342
44000
|
try {
|
|
43343
|
-
const raw = await
|
|
44001
|
+
const raw = await import_node_fs31.promises.readFile(this.metaPath(name), "utf8");
|
|
43344
44002
|
const json = JSON.parse(raw);
|
|
43345
44003
|
let migrated = false;
|
|
43346
44004
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -43351,7 +44009,7 @@ var ProjectStore = class {
|
|
|
43351
44009
|
if (parsed.success) {
|
|
43352
44010
|
out.push(parsed.data);
|
|
43353
44011
|
if (migrated) {
|
|
43354
|
-
void
|
|
44012
|
+
void import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
43355
44013
|
});
|
|
43356
44014
|
}
|
|
43357
44015
|
}
|
|
@@ -43395,8 +44053,8 @@ var ProjectStore = class {
|
|
|
43395
44053
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
43396
44054
|
}
|
|
43397
44055
|
const dir = this.projectDir(name);
|
|
43398
|
-
await
|
|
43399
|
-
await
|
|
44056
|
+
await import_node_fs31.promises.mkdir(dir, { recursive: true });
|
|
44057
|
+
await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
43400
44058
|
return meta;
|
|
43401
44059
|
}
|
|
43402
44060
|
/**
|
|
@@ -43439,7 +44097,7 @@ var ProjectStore = class {
|
|
|
43439
44097
|
}
|
|
43440
44098
|
async delete(name) {
|
|
43441
44099
|
const dir = this.projectDir(name);
|
|
43442
|
-
await
|
|
44100
|
+
await import_node_fs31.promises.rm(dir, { recursive: true, force: true });
|
|
43443
44101
|
}
|
|
43444
44102
|
async updatePort(name, newPort) {
|
|
43445
44103
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -43455,7 +44113,7 @@ var ProjectStore = class {
|
|
|
43455
44113
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
43456
44114
|
}
|
|
43457
44115
|
const updated = { ...target, port: newPort };
|
|
43458
|
-
await
|
|
44116
|
+
await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
43459
44117
|
return updated;
|
|
43460
44118
|
}
|
|
43461
44119
|
/**
|
|
@@ -43472,7 +44130,7 @@ var ProjectStore = class {
|
|
|
43472
44130
|
if (!validated.success) {
|
|
43473
44131
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
43474
44132
|
}
|
|
43475
|
-
await
|
|
44133
|
+
await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43476
44134
|
return validated.data;
|
|
43477
44135
|
}
|
|
43478
44136
|
/**
|
|
@@ -43493,7 +44151,7 @@ var ProjectStore = class {
|
|
|
43493
44151
|
if (!validated.success) {
|
|
43494
44152
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
43495
44153
|
}
|
|
43496
|
-
await
|
|
44154
|
+
await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43497
44155
|
return validated.data;
|
|
43498
44156
|
}
|
|
43499
44157
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -43508,7 +44166,7 @@ var ProjectStore = class {
|
|
|
43508
44166
|
if (!validated.success) {
|
|
43509
44167
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
43510
44168
|
}
|
|
43511
|
-
await
|
|
44169
|
+
await import_node_fs31.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
43512
44170
|
return validated.data;
|
|
43513
44171
|
}
|
|
43514
44172
|
};
|
|
@@ -43629,8 +44287,8 @@ var PublishJobRegistry = class {
|
|
|
43629
44287
|
|
|
43630
44288
|
// src/app-builder/publish-job-runner.ts
|
|
43631
44289
|
var import_node_child_process13 = require("child_process");
|
|
43632
|
-
var
|
|
43633
|
-
var
|
|
44290
|
+
var import_node_fs32 = require("fs");
|
|
44291
|
+
var import_node_path39 = require("path");
|
|
43634
44292
|
|
|
43635
44293
|
// src/app-builder/publish-stage-parser.ts
|
|
43636
44294
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -43662,10 +44320,10 @@ async function startPublishJob(deps, args) {
|
|
|
43662
44320
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
43663
44321
|
}
|
|
43664
44322
|
const projDir = projectDir(args.name);
|
|
43665
|
-
const logPath = (0,
|
|
44323
|
+
const logPath = (0, import_node_path39.join)(projDir, ".publish.log");
|
|
43666
44324
|
let logStream = null;
|
|
43667
44325
|
try {
|
|
43668
|
-
logStream = (0,
|
|
44326
|
+
logStream = (0, import_node_fs32.createWriteStream)(logPath, { flags: "w" });
|
|
43669
44327
|
} catch {
|
|
43670
44328
|
logStream = null;
|
|
43671
44329
|
}
|
|
@@ -43922,8 +44580,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
43922
44580
|
|
|
43923
44581
|
// src/handlers/app-builder.ts
|
|
43924
44582
|
init_protocol();
|
|
43925
|
-
var
|
|
43926
|
-
var
|
|
44583
|
+
var import_node_path40 = require("path");
|
|
44584
|
+
var import_node_fs33 = require("fs");
|
|
43927
44585
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
43928
44586
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
43929
44587
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -44004,7 +44662,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44004
44662
|
async function listAllUsersProjects() {
|
|
44005
44663
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
44006
44664
|
const getStore = deps.getStore;
|
|
44007
|
-
const userIds = await
|
|
44665
|
+
const userIds = await import_node_fs33.promises.readdir(deps.usersRoot).catch(() => []);
|
|
44008
44666
|
const perUser = await Promise.all(
|
|
44009
44667
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
44010
44668
|
);
|
|
@@ -44080,8 +44738,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44080
44738
|
const project = await userStore.create(f.name, reservedPorts);
|
|
44081
44739
|
try {
|
|
44082
44740
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
44083
|
-
const templateSrcDir = (0,
|
|
44084
|
-
const scaffoldScript = (0,
|
|
44741
|
+
const templateSrcDir = (0, import_node_path40.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
44742
|
+
const scaffoldScript = (0, import_node_path40.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
44085
44743
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
44086
44744
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
44087
44745
|
name: project.name,
|
|
@@ -44302,7 +44960,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44302
44960
|
await userStore.clearPublishJob(args.name);
|
|
44303
44961
|
}
|
|
44304
44962
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
44305
|
-
const scriptPath = (0,
|
|
44963
|
+
const scriptPath = (0, import_node_path40.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
44306
44964
|
deps.logger?.info("app-builder.publish.start", {
|
|
44307
44965
|
name: args.name,
|
|
44308
44966
|
sessionId: boundSession.sessionId,
|
|
@@ -44398,7 +45056,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44398
45056
|
|
|
44399
45057
|
// src/extension/registry.ts
|
|
44400
45058
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
44401
|
-
var
|
|
45059
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
44402
45060
|
async function loadAll(root) {
|
|
44403
45061
|
let entries;
|
|
44404
45062
|
try {
|
|
@@ -44411,13 +45069,13 @@ async function loadAll(root) {
|
|
|
44411
45069
|
for (const ent of entries) {
|
|
44412
45070
|
if (!ent.isDirectory()) continue;
|
|
44413
45071
|
if (ent.name.startsWith(".")) continue;
|
|
44414
|
-
records.push(await loadOne(
|
|
45072
|
+
records.push(await loadOne(import_node_path41.default.join(root, ent.name), ent.name));
|
|
44415
45073
|
}
|
|
44416
45074
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
44417
45075
|
return records;
|
|
44418
45076
|
}
|
|
44419
45077
|
async function loadOne(dir, dirName) {
|
|
44420
|
-
const manifestPath =
|
|
45078
|
+
const manifestPath = import_node_path41.default.join(dir, "manifest.json");
|
|
44421
45079
|
let raw;
|
|
44422
45080
|
try {
|
|
44423
45081
|
raw = await import_promises8.default.readFile(manifestPath, "utf8");
|
|
@@ -44462,7 +45120,7 @@ async function loadOne(dir, dirName) {
|
|
|
44462
45120
|
|
|
44463
45121
|
// src/extension/uninstall.ts
|
|
44464
45122
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
44465
|
-
var
|
|
45123
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
44466
45124
|
var UninstallError = class extends Error {
|
|
44467
45125
|
constructor(code, message) {
|
|
44468
45126
|
super(message);
|
|
@@ -44471,7 +45129,7 @@ var UninstallError = class extends Error {
|
|
|
44471
45129
|
code;
|
|
44472
45130
|
};
|
|
44473
45131
|
async function uninstall(deps) {
|
|
44474
|
-
const dir =
|
|
45132
|
+
const dir = import_node_path42.default.join(deps.root, deps.extId);
|
|
44475
45133
|
try {
|
|
44476
45134
|
await import_promises9.default.access(dir);
|
|
44477
45135
|
} catch {
|
|
@@ -44982,7 +45640,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
44982
45640
|
|
|
44983
45641
|
// src/extension/runtime.ts
|
|
44984
45642
|
var import_node_child_process15 = require("child_process");
|
|
44985
|
-
var
|
|
45643
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
44986
45644
|
var import_promises10 = require("timers/promises");
|
|
44987
45645
|
|
|
44988
45646
|
// src/extension/port-allocator.ts
|
|
@@ -45083,7 +45741,7 @@ var Runtime = class {
|
|
|
45083
45741
|
/\$CLAWOS_EXT_PORT/g,
|
|
45084
45742
|
String(port)
|
|
45085
45743
|
);
|
|
45086
|
-
const dir =
|
|
45744
|
+
const dir = import_node_path43.default.join(this.root, extId);
|
|
45087
45745
|
const env = {
|
|
45088
45746
|
...process.env,
|
|
45089
45747
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -45195,7 +45853,7 @@ ${handle.stderrTail}`
|
|
|
45195
45853
|
|
|
45196
45854
|
// src/extension/published-channels.ts
|
|
45197
45855
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
45198
|
-
var
|
|
45856
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45199
45857
|
init_zod();
|
|
45200
45858
|
var PublishedChannelsError = class extends Error {
|
|
45201
45859
|
constructor(code, message) {
|
|
@@ -45294,7 +45952,7 @@ var PublishedChannelStore = class {
|
|
|
45294
45952
|
)
|
|
45295
45953
|
};
|
|
45296
45954
|
const tmp = `${this.filePath}.tmp`;
|
|
45297
|
-
await import_promises11.default.mkdir(
|
|
45955
|
+
await import_promises11.default.mkdir(import_node_path44.default.dirname(this.filePath), { recursive: true });
|
|
45298
45956
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
45299
45957
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
45300
45958
|
}
|
|
@@ -45302,7 +45960,7 @@ var PublishedChannelStore = class {
|
|
|
45302
45960
|
|
|
45303
45961
|
// src/extension/bundle-cache.ts
|
|
45304
45962
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
45305
|
-
var
|
|
45963
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
45306
45964
|
var BundleCache = class {
|
|
45307
45965
|
constructor(rootDir) {
|
|
45308
45966
|
this.rootDir = rootDir;
|
|
@@ -45311,14 +45969,14 @@ var BundleCache = class {
|
|
|
45311
45969
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
45312
45970
|
async write(snapshotHash, buffer) {
|
|
45313
45971
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
45314
|
-
const file =
|
|
45972
|
+
const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45315
45973
|
const tmp = `${file}.tmp`;
|
|
45316
45974
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
45317
45975
|
await import_promises12.default.rename(tmp, file);
|
|
45318
45976
|
}
|
|
45319
45977
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
45320
45978
|
async read(snapshotHash) {
|
|
45321
|
-
const file =
|
|
45979
|
+
const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45322
45980
|
try {
|
|
45323
45981
|
return await import_promises12.default.readFile(file);
|
|
45324
45982
|
} catch (e) {
|
|
@@ -45328,16 +45986,33 @@ var BundleCache = class {
|
|
|
45328
45986
|
}
|
|
45329
45987
|
/** Idempotent — missing file is not an error. */
|
|
45330
45988
|
async delete(snapshotHash) {
|
|
45331
|
-
const file =
|
|
45989
|
+
const file = import_node_path45.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
45332
45990
|
await import_promises12.default.rm(file, { force: true });
|
|
45333
45991
|
}
|
|
45334
45992
|
};
|
|
45335
45993
|
|
|
45336
45994
|
// src/index.ts
|
|
45995
|
+
var import_meta4 = {};
|
|
45337
45996
|
async function startDaemon(config) {
|
|
45997
|
+
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
45998
|
+
const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
|
|
45999
|
+
const logClient = createLogClient({
|
|
46000
|
+
endpoint: logShippingCfg.endpoint,
|
|
46001
|
+
identity: {
|
|
46002
|
+
ownerPrincipalId: authFile.ownerPrincipalId,
|
|
46003
|
+
deviceId: authFile.deviceId,
|
|
46004
|
+
appVersion: version,
|
|
46005
|
+
daemonVersion: version,
|
|
46006
|
+
os: `${process.platform}-${process.arch}`
|
|
46007
|
+
},
|
|
46008
|
+
source: "daemon",
|
|
46009
|
+
sampling: logShippingCfg.sampling,
|
|
46010
|
+
homeDir: import_node_os19.default.homedir()
|
|
46011
|
+
});
|
|
45338
46012
|
const logger = createLogger({
|
|
45339
46013
|
level: config.logLevel,
|
|
45340
|
-
file:
|
|
46014
|
+
file: import_node_path46.default.join(config.dataDir, "clawd.log"),
|
|
46015
|
+
logClient
|
|
45341
46016
|
});
|
|
45342
46017
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
45343
46018
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -45348,7 +46023,6 @@ async function startDaemon(config) {
|
|
|
45348
46023
|
if (pre.status === "stale") {
|
|
45349
46024
|
logger.warn("stale state file detected, overwriting", { pid: pre.existing.pid });
|
|
45350
46025
|
}
|
|
45351
|
-
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
45352
46026
|
let resolvedAuthToken = null;
|
|
45353
46027
|
if (config.authToken && config.authToken.trim()) {
|
|
45354
46028
|
resolvedAuthToken = config.authToken.trim();
|
|
@@ -45473,8 +46147,8 @@ async function startDaemon(config) {
|
|
|
45473
46147
|
const agents = new AgentsScanner();
|
|
45474
46148
|
const history = new ClaudeHistoryReader();
|
|
45475
46149
|
let transport = null;
|
|
45476
|
-
const personaStore = new PersonaStore(
|
|
45477
|
-
const usersRoot =
|
|
46150
|
+
const personaStore = new PersonaStore(import_node_path46.default.join(config.dataDir, "personas"));
|
|
46151
|
+
const usersRoot = import_node_path46.default.join(config.dataDir, "users");
|
|
45478
46152
|
const defaultsRoot = findDefaultsRoot();
|
|
45479
46153
|
if (defaultsRoot) {
|
|
45480
46154
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -45492,6 +46166,33 @@ async function startDaemon(config) {
|
|
|
45492
46166
|
migrateAgentsMirror({ store: personaStore, logger });
|
|
45493
46167
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
45494
46168
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
46169
|
+
const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
|
|
46170
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path46.default.dirname((0, import_node_url2.fileURLToPath)(import_meta4.url));
|
|
46171
|
+
const dispatchServerCandidates = [
|
|
46172
|
+
import_node_path46.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
46173
|
+
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
46174
|
+
import_node_path46.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
46175
|
+
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
46176
|
+
];
|
|
46177
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs34.default.existsSync(p2));
|
|
46178
|
+
let dispatchMcpConfigPath2;
|
|
46179
|
+
if (dispatchServerScriptPath) {
|
|
46180
|
+
const dispatchLogPath = import_node_path46.default.join(config.dataDir, "dispatch-mcp-server.log");
|
|
46181
|
+
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
46182
|
+
dataDir: config.dataDir,
|
|
46183
|
+
serverScriptPath: dispatchServerScriptPath,
|
|
46184
|
+
logPath: dispatchLogPath
|
|
46185
|
+
});
|
|
46186
|
+
logger.info("dispatch.mcp.json written", {
|
|
46187
|
+
path: dispatchMcpConfigPath2,
|
|
46188
|
+
server: dispatchServerScriptPath,
|
|
46189
|
+
serverLog: dispatchLogPath
|
|
46190
|
+
});
|
|
46191
|
+
} else {
|
|
46192
|
+
logger.warn("dispatch-mcp-server.cjs not found; persona dispatch disabled (dev tsx \u6A21\u5F0F\u4E0B\u9700\u5148\u8DD1\u8FC7 build)", {
|
|
46193
|
+
tried: dispatchServerCandidates
|
|
46194
|
+
});
|
|
46195
|
+
}
|
|
45495
46196
|
const manager = new SessionManager({
|
|
45496
46197
|
store,
|
|
45497
46198
|
// Phase 2 (capability platform plan §1): factory 注入后 manager.storeFor 走
|
|
@@ -45501,7 +46202,7 @@ async function startDaemon(config) {
|
|
|
45501
46202
|
getAdapter,
|
|
45502
46203
|
historyReader: history,
|
|
45503
46204
|
dataDir: config.dataDir,
|
|
45504
|
-
personaRoot:
|
|
46205
|
+
personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
|
|
45505
46206
|
usersRoot,
|
|
45506
46207
|
personaStore,
|
|
45507
46208
|
ownerDisplayName,
|
|
@@ -45512,6 +46213,12 @@ async function startDaemon(config) {
|
|
|
45512
46213
|
// 127.0.0.1(不是 config.host)—— cc 跑在本机,loopback 最稳;外部访问限制 + http-router
|
|
45513
46214
|
// 的 isLoopback 兜底已确保安全。
|
|
45514
46215
|
getDaemonUrl: () => `http://127.0.0.1:${config.port}`,
|
|
46216
|
+
// Persona dispatch (Task 8): manager 通过这两个 deps 跟 PersonaDispatchManager 协作。
|
|
46217
|
+
// - personaDispatchManager: manager.createDispatchedSession 用它 registerBSession;
|
|
46218
|
+
// reducer 通过闭包反查 dispatchId 注 CLAWD_DISPATCH_ID env。
|
|
46219
|
+
// - dispatchMcpConfigPath: reducer 透传到 SpawnContext,cc spawn 加 --mcp-config flag。
|
|
46220
|
+
personaDispatchManager,
|
|
46221
|
+
dispatchMcpConfigPath: dispatchMcpConfigPath2,
|
|
45515
46222
|
broadcastFrame: (frame, target) => {
|
|
45516
46223
|
if (target === "all") {
|
|
45517
46224
|
transport?.broadcastAll(frame);
|
|
@@ -45531,10 +46238,10 @@ async function startDaemon(config) {
|
|
|
45531
46238
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
45532
46239
|
attachmentGroup: {
|
|
45533
46240
|
onFileEdit: (input) => {
|
|
45534
|
-
const absPath =
|
|
46241
|
+
const absPath = import_node_path46.default.isAbsolute(input.relPath) ? input.relPath : import_node_path46.default.join(input.cwd, input.relPath);
|
|
45535
46242
|
let size = 0;
|
|
45536
46243
|
try {
|
|
45537
|
-
size =
|
|
46244
|
+
size = import_node_fs34.default.statSync(absPath).size;
|
|
45538
46245
|
} catch (err) {
|
|
45539
46246
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
45540
46247
|
sessionId: input.sessionId,
|
|
@@ -45720,11 +46427,11 @@ async function startDaemon(config) {
|
|
|
45720
46427
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
45721
46428
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
45722
46429
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
45723
|
-
personaRoot:
|
|
46430
|
+
personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
|
|
45724
46431
|
usersRoot
|
|
45725
46432
|
},
|
|
45726
46433
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
45727
|
-
personaRoot:
|
|
46434
|
+
personaRoot: import_node_path46.default.join(config.dataDir, "personas"),
|
|
45728
46435
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
45729
46436
|
usersRoot,
|
|
45730
46437
|
// capability:list / delete handler 依赖
|
|
@@ -45813,11 +46520,11 @@ async function startDaemon(config) {
|
|
|
45813
46520
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
45814
46521
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
45815
46522
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
45816
|
-
appBuilderPersonaRoot:
|
|
46523
|
+
appBuilderPersonaRoot: import_node_path46.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
45817
46524
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
45818
|
-
deployKitRoot:
|
|
46525
|
+
deployKitRoot: import_node_path46.default.join(config.dataDir, "deploy-kit"),
|
|
45819
46526
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
45820
|
-
resolvePersonaRoot: (personaId) =>
|
|
46527
|
+
resolvePersonaRoot: (personaId) => import_node_path46.default.join(config.dataDir, "personas", personaId),
|
|
45821
46528
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
45822
46529
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
45823
46530
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -45838,6 +46545,41 @@ async function startDaemon(config) {
|
|
|
45838
46545
|
logger
|
|
45839
46546
|
});
|
|
45840
46547
|
let handlers = makeHandlers();
|
|
46548
|
+
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
46549
|
+
personaDispatchManager,
|
|
46550
|
+
logger,
|
|
46551
|
+
spawnB: async (args) => {
|
|
46552
|
+
logger.info("dispatch.spawnB.start", {
|
|
46553
|
+
dispatchId: args.dispatchId,
|
|
46554
|
+
targetPersona: args.targetPersona,
|
|
46555
|
+
sourceSessionId: args.sourceSessionId
|
|
46556
|
+
});
|
|
46557
|
+
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
46558
|
+
if (!sourceFile) {
|
|
46559
|
+
throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
|
|
46560
|
+
}
|
|
46561
|
+
const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path46.default.join(
|
|
46562
|
+
import_node_os19.default.homedir(),
|
|
46563
|
+
".claude",
|
|
46564
|
+
"projects",
|
|
46565
|
+
cwdToHashDir(sourceFile.cwd),
|
|
46566
|
+
`${sourceFile.toolSessionId}.jsonl`
|
|
46567
|
+
) : "(no transcript yet \u2014 operate from the task description alone)";
|
|
46568
|
+
logger.info("dispatch.spawnB.source-resolved", {
|
|
46569
|
+
dispatchId: args.dispatchId,
|
|
46570
|
+
sourceJsonlPath,
|
|
46571
|
+
hasToolSessionId: Boolean(sourceFile.toolSessionId)
|
|
46572
|
+
});
|
|
46573
|
+
manager.createDispatchedSession({
|
|
46574
|
+
dispatchId: args.dispatchId,
|
|
46575
|
+
sourceSessionId: args.sourceSessionId,
|
|
46576
|
+
targetPersona: args.targetPersona,
|
|
46577
|
+
prompt: args.prompt,
|
|
46578
|
+
sourceJsonlPath
|
|
46579
|
+
});
|
|
46580
|
+
}
|
|
46581
|
+
});
|
|
46582
|
+
handlers = { ...handlers, ...dispatchHandlers };
|
|
45841
46583
|
const authResolver = new AuthContextResolver({
|
|
45842
46584
|
ownerToken: resolvedAuthToken
|
|
45843
46585
|
});
|
|
@@ -45912,6 +46654,10 @@ async function startDaemon(config) {
|
|
|
45912
46654
|
manager,
|
|
45913
46655
|
getAdapter,
|
|
45914
46656
|
getTunnelUrl: () => currentTunnelUrl,
|
|
46657
|
+
getLogShipping: () => config.logShipping ? {
|
|
46658
|
+
endpoint: config.logShipping.endpoint,
|
|
46659
|
+
sampling: config.logShipping.sampling
|
|
46660
|
+
} : null,
|
|
45915
46661
|
// ready 帧 mode = daemon CC spawn 模式('sdk' | 'tui');UI 用它挂 XtermPanel
|
|
45916
46662
|
mode: config.mode,
|
|
45917
46663
|
// file-sharing 字段:httpBaseUrl 跟 tunnel 状态走;httpToken 复用 owner WS token
|
|
@@ -46066,8 +46812,8 @@ async function startDaemon(config) {
|
|
|
46066
46812
|
const lines = [
|
|
46067
46813
|
`Tunnel: ${r.url}`,
|
|
46068
46814
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
46069
|
-
`Frpc config: ${
|
|
46070
|
-
`Frpc log: ${
|
|
46815
|
+
`Frpc config: ${import_node_path46.default.join(config.dataDir, "frpc.toml")}`,
|
|
46816
|
+
`Frpc log: ${import_node_path46.default.join(config.dataDir, "frpc.log")}`
|
|
46071
46817
|
];
|
|
46072
46818
|
const width = Math.max(...lines.map((l) => l.length));
|
|
46073
46819
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -46080,8 +46826,8 @@ ${bar}
|
|
|
46080
46826
|
|
|
46081
46827
|
`);
|
|
46082
46828
|
try {
|
|
46083
|
-
const connectPath =
|
|
46084
|
-
|
|
46829
|
+
const connectPath = import_node_path46.default.join(config.dataDir, "connect.txt");
|
|
46830
|
+
import_node_fs34.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
46085
46831
|
} catch {
|
|
46086
46832
|
}
|
|
46087
46833
|
} catch (err) {
|
|
@@ -46142,6 +46888,7 @@ ${bar}
|
|
|
46142
46888
|
}
|
|
46143
46889
|
await wss.stop();
|
|
46144
46890
|
stateMgr.delete();
|
|
46891
|
+
if (logClient) await logClient.dispose();
|
|
46145
46892
|
};
|
|
46146
46893
|
return {
|
|
46147
46894
|
stop: shutdown,
|
|
@@ -46152,9 +46899,9 @@ ${bar}
|
|
|
46152
46899
|
};
|
|
46153
46900
|
}
|
|
46154
46901
|
function migrateDropPersonsDir(dataDir) {
|
|
46155
|
-
const dir =
|
|
46902
|
+
const dir = import_node_path46.default.join(dataDir, "persons");
|
|
46156
46903
|
try {
|
|
46157
|
-
|
|
46904
|
+
import_node_fs34.default.rmSync(dir, { recursive: true, force: true });
|
|
46158
46905
|
} catch {
|
|
46159
46906
|
}
|
|
46160
46907
|
}
|