@clawos-dev/clawd 0.2.439 → 0.2.441
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 +971 -798
- package/dist/dispatch/mcp-server.cjs +23 -4
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/{guest-CaPkO7XV.js → guest-Cn0m2N_c.js} +114 -114
- package/dist/share-ui/assets/guest-DISx208T.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-DO5eviOK.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
|
|
|
450
450
|
init_errors();
|
|
451
451
|
init_en();
|
|
452
452
|
makeIssue = (params) => {
|
|
453
|
-
const { data, path:
|
|
454
|
-
const fullPath = [...
|
|
453
|
+
const { data, path: path91, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path91, ...issueData.path || []];
|
|
455
455
|
const fullIssue = {
|
|
456
456
|
...issueData,
|
|
457
457
|
path: fullPath
|
|
@@ -762,11 +762,11 @@ var init_types = __esm({
|
|
|
762
762
|
init_parseUtil();
|
|
763
763
|
init_util();
|
|
764
764
|
ParseInputLazyPath = class {
|
|
765
|
-
constructor(parent, value,
|
|
765
|
+
constructor(parent, value, path91, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path91;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -7089,10 +7089,9 @@ var init_persona_schemas = __esm({
|
|
|
7089
7089
|
writableRoots: external_exports.array(external_exports.string()).optional(),
|
|
7090
7090
|
// 禁读 glob(相对 workspace root 或绝对),如 ".secrets/**"、"**/*.env"。
|
|
7091
7091
|
denyRead: external_exports.array(external_exports.string()).optional(),
|
|
7092
|
-
// true → 网络全放(*);false
|
|
7093
|
-
//
|
|
7094
|
-
//
|
|
7095
|
-
// 「卡片显示开、实际断网」的幽灵态。
|
|
7092
|
+
// true → 网络全放(*);false / 缺省 → 断网(fail-closed)。**「新建默认联网」不靠这里的缺省**,
|
|
7093
|
+
// 靠 persona 创建时就把 CODEX_SANDBOX_DEFAULT 物化进文件(见 PersonaManager.create)——
|
|
7094
|
+
// 缺省只在文件损坏这种异常路径上出现,那时断网是更安全的一侧。
|
|
7096
7095
|
network: external_exports.boolean().optional()
|
|
7097
7096
|
}).strict();
|
|
7098
7097
|
PersonaSandboxSettingsSchema = external_exports.object({
|
|
@@ -7285,7 +7284,7 @@ var init_principal = __esm({
|
|
|
7285
7284
|
});
|
|
7286
7285
|
|
|
7287
7286
|
// ../protocol/src/schemas.ts
|
|
7288
|
-
var SessionStatusSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, SelectOptionSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, TURN_END_REASONS, ParsedEventSchema, SessionCreateArgs, ProjectEntry, ProjectPatchArgs, ProjectRevealArgs, ProjectCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, QueuedMessage, SessionSendArgs, SessionDequeueArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, SessionArchiveArgs, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
|
|
7287
|
+
var SessionStatusSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, SelectOptionSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, ToolFeaturesSchema, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, TURN_END_REASONS, ParsedEventSchema, SessionCreateArgs, ProjectEntry, ProjectPatchArgs, ProjectRevealArgs, ProjectCreateArgs, SessionImportExternalArgs, SessionListArgs, SessionIdArgs, SessionUpdateArgs, QueuedMessage, SessionSendArgs, SessionDequeueArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SkillEntrySchema, AgentEntrySchema, AgentsListArgs, AgentsListResponseSchema, SessionCurrentTurnSenderArgs, SessionSubscribeArgs, SessionPinArgs, SessionArchiveArgs, SessionSearchContentArgs, SessionSearchMatchSchema, SessionSearchContentResponseSchema, PeerSessionUpsertArgs, PeerSessionUpsertResponseSchema, PeerSessionRemoveArgs, PeerSessionRemoveResponseSchema, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, CancelQuestionArgs, CancelQuestionResponseSchema, ClientInfoSchema, AuthRequestFrameSchema, AuthOkFrameSchema, DeviceConnectionEntrySchema, DeviceConnectionsResponseSchema, TunnelReadyEventSchema, TunnelExitedEventSchema, TunnelUnavailableEventSchema, InfoRunningSessionSchema, InfoResponseSchema, PROJECT_PORT_MIN, PROJECT_PORT_MAX, projectNameRegex, DEFAULT_DEV_COMMAND, ProjectMetadataSchema, PROJECT_STAGE_VALUES, ProjectStageSchema, ProjectWithStatusSchema, ListProjectsArgsSchema, ListProjectsResultSchema, GetProjectArgsSchema, GetProjectResultSchema, CreateProjectArgsSchema, CreateProjectResultSchema, DeleteProjectArgsSchema, DeleteProjectResultSchema, UpdateProjectPortArgsSchema, UpdateProjectPortResultSchema, SetProdUrlArgsSchema, SetProdUrlResultSchema, StartDevServerArgsSchema, StartDevServerResultSchema, ASSISTANT_REPORTABLE_STAGES, ReportStageArgsSchema, ReportStageResultSchema, StopDevServerArgsSchema, StopDevServerResultSchema, AppBuilderProjectUpdatedEventSchema, PublishArgsSchema, PublishResultSchema, DismissPublishJobArgsSchema, DismissPublishJobResultSchema, AppBuilderPublishProgressEventSchema, AppBuilderPublishFailedEventSchema;
|
|
7289
7288
|
var init_schemas = __esm({
|
|
7290
7289
|
"../protocol/src/schemas.ts"() {
|
|
7291
7290
|
"use strict";
|
|
@@ -8029,6 +8028,22 @@ var init_schemas = __esm({
|
|
|
8029
8028
|
sessionId: external_exports.string().min(1),
|
|
8030
8029
|
archived: external_exports.boolean()
|
|
8031
8030
|
});
|
|
8031
|
+
SessionSearchContentArgs = external_exports.object({
|
|
8032
|
+
query: external_exports.string().min(1),
|
|
8033
|
+
// 扫描顺序 = 数组顺序(调用方按 updatedAt 倒序传),攒够 limit 即停
|
|
8034
|
+
sessionIds: external_exports.array(external_exports.string().min(1)),
|
|
8035
|
+
limit: external_exports.number().int().positive().max(50).optional()
|
|
8036
|
+
});
|
|
8037
|
+
SessionSearchMatchSchema = external_exports.object({
|
|
8038
|
+
sessionId: external_exports.string().min(1),
|
|
8039
|
+
// 命中处上下文片段,已单行化。**不回高亮 offset**:调用方手里有 query,
|
|
8040
|
+
// 自己在 snippet 里 indexOf 就能高亮,wire 上少一组坐标少一处漂
|
|
8041
|
+
snippet: external_exports.string()
|
|
8042
|
+
});
|
|
8043
|
+
SessionSearchContentResponseSchema = external_exports.object({
|
|
8044
|
+
type: external_exports.literal("session:searchContent"),
|
|
8045
|
+
matches: external_exports.array(SessionSearchMatchSchema)
|
|
8046
|
+
});
|
|
8032
8047
|
PeerSessionUpsertArgs = SessionFileSchema;
|
|
8033
8048
|
PeerSessionUpsertResponseSchema = external_exports.object({
|
|
8034
8049
|
type: external_exports.literal("peerSession:upsert:ok")
|
|
@@ -8515,6 +8530,10 @@ var init_methods = __esm({
|
|
|
8515
8530
|
summary: "\u5F52\u6863 / \u53D6\u6D88\u5F52\u6863\u4F1A\u8BDD\uFF08\u5F52\u6863 = \u5168\u5C40\u6536\u7EB3\u6001\uFF1A\u9000\u51FA sidebar\u3001\u539F\u5B50\u6E05 pinnedAt\uFF09",
|
|
8516
8531
|
args: SessionArchiveArgs
|
|
8517
8532
|
},
|
|
8533
|
+
"session:searchContent": {
|
|
8534
|
+
summary: '\u5728 sessionIds \u7ED9\u5B9A\u7684\u8FD9\u6279\u4F1A\u8BDD\u91CC\u641C\u6B63\u6587\u5185\u5BB9\uFF08user / assistant \u7684\u6587\u672C\u6D88\u606F\uFF1B\u5DE5\u5177\u5165\u53C2\u51FA\u53C2\u4E0E\u7CFB\u7EDF\u6CE8\u5165\u4E0D\u7B97\uFF09\uFF0C\u547D\u4E2D\u8FD4\u56DE\u4E0A\u4E0B\u6587\u7247\u6BB5\u3002**\u626B\u63CF\u987A\u5E8F = sessionIds \u6570\u7EC4\u987A\u5E8F\uFF0C\u6512\u591F limit \u5C31\u505C**\uFF08\u8C03\u7528\u65B9\u6309 updatedAt \u5012\u5E8F\u4F20 \u2192 \u65E9\u505C\u7ED3\u679C\u5373"\u6700\u8FD1 N \u6761"\uFF09\uFF1Blimit \u7F3A\u7701 9\u3002\u5019\u9009\u7531\u8C03\u7528\u65B9\u7ED9\u5B9A\uFF0Cdaemon \u4E0D\u81EA\u5DF1\u6309 archivedAt \u7B5B\uFF08\u8BDD\u9898\u5F52\u6863\u53EA\u6253\u5728 Master \u4F1A\u8BDD\u4E0A\uFF0Cworker \u4F1A\u8BDD\u6CA1\u6807\u8BB0\uFF09\uFF1B\u65E0\u6743\u8BFB / \u5B9A\u4F4D\u4E0D\u5230 transcript / transcript \u5DF2\u88AB CC \u6E05\u7406\u7684\u4F1A\u8BDD\u9759\u9ED8\u8DF3\u8FC7\uFF0C\u4E0D\u62A5\u9519',
|
|
8535
|
+
args: SessionSearchContentArgs
|
|
8536
|
+
},
|
|
8518
8537
|
"session:markRead": {
|
|
8519
8538
|
summary: "\u6E05\u6389\u4F1A\u8BDD\u7684\u5171\u4EAB\u672A\u8BFB\u6807\u8BB0\u5E76\u5E7F\u64AD session:info\uFF1B\u5E42\u7B49",
|
|
8520
8539
|
args: SessionIdArgs
|
|
@@ -9574,8 +9593,8 @@ var require_req = __commonJS({
|
|
|
9574
9593
|
if (req.originalUrl) {
|
|
9575
9594
|
_req.url = req.originalUrl;
|
|
9576
9595
|
} else {
|
|
9577
|
-
const
|
|
9578
|
-
_req.url = typeof
|
|
9596
|
+
const path91 = req.path;
|
|
9597
|
+
_req.url = typeof path91 === "string" ? path91 : req.url ? req.url.path || req.url : void 0;
|
|
9579
9598
|
}
|
|
9580
9599
|
if (req.query) {
|
|
9581
9600
|
_req.query = req.query;
|
|
@@ -9740,14 +9759,14 @@ var require_redact = __commonJS({
|
|
|
9740
9759
|
}
|
|
9741
9760
|
return obj;
|
|
9742
9761
|
}
|
|
9743
|
-
function parsePath(
|
|
9762
|
+
function parsePath(path91) {
|
|
9744
9763
|
const parts = [];
|
|
9745
9764
|
let current = "";
|
|
9746
9765
|
let inBrackets = false;
|
|
9747
9766
|
let inQuotes = false;
|
|
9748
9767
|
let quoteChar = "";
|
|
9749
|
-
for (let i = 0; i <
|
|
9750
|
-
const char =
|
|
9768
|
+
for (let i = 0; i < path91.length; i++) {
|
|
9769
|
+
const char = path91[i];
|
|
9751
9770
|
if (!inBrackets && char === ".") {
|
|
9752
9771
|
if (current) {
|
|
9753
9772
|
parts.push(current);
|
|
@@ -9878,10 +9897,10 @@ var require_redact = __commonJS({
|
|
|
9878
9897
|
return current;
|
|
9879
9898
|
}
|
|
9880
9899
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9881
|
-
for (const
|
|
9882
|
-
const parts = parsePath(
|
|
9900
|
+
for (const path91 of paths) {
|
|
9901
|
+
const parts = parsePath(path91);
|
|
9883
9902
|
if (parts.includes("*")) {
|
|
9884
|
-
redactWildcardPath(obj, parts, censor,
|
|
9903
|
+
redactWildcardPath(obj, parts, censor, path91, remove);
|
|
9885
9904
|
} else {
|
|
9886
9905
|
if (remove) {
|
|
9887
9906
|
removeKey(obj, parts);
|
|
@@ -9966,8 +9985,8 @@ var require_redact = __commonJS({
|
|
|
9966
9985
|
}
|
|
9967
9986
|
} else {
|
|
9968
9987
|
if (afterWildcard.includes("*")) {
|
|
9969
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9970
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9988
|
+
const wrappedCensor = typeof censor === "function" ? (value, path91) => {
|
|
9989
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path91];
|
|
9971
9990
|
return censor(value, fullPath);
|
|
9972
9991
|
} : censor;
|
|
9973
9992
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10002,8 +10021,8 @@ var require_redact = __commonJS({
|
|
|
10002
10021
|
return null;
|
|
10003
10022
|
}
|
|
10004
10023
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10005
|
-
for (const
|
|
10006
|
-
const parts = parsePath(
|
|
10024
|
+
for (const path91 of pathsToClone) {
|
|
10025
|
+
const parts = parsePath(path91);
|
|
10007
10026
|
let current = pathStructure;
|
|
10008
10027
|
for (let i = 0; i < parts.length; i++) {
|
|
10009
10028
|
const part = parts[i];
|
|
@@ -10055,24 +10074,24 @@ var require_redact = __commonJS({
|
|
|
10055
10074
|
}
|
|
10056
10075
|
return cloneSelectively(obj, pathStructure);
|
|
10057
10076
|
}
|
|
10058
|
-
function validatePath(
|
|
10059
|
-
if (typeof
|
|
10077
|
+
function validatePath(path91) {
|
|
10078
|
+
if (typeof path91 !== "string") {
|
|
10060
10079
|
throw new Error("Paths must be (non-empty) strings");
|
|
10061
10080
|
}
|
|
10062
|
-
if (
|
|
10081
|
+
if (path91 === "") {
|
|
10063
10082
|
throw new Error("Invalid redaction path ()");
|
|
10064
10083
|
}
|
|
10065
|
-
if (
|
|
10066
|
-
throw new Error(`Invalid redaction path (${
|
|
10084
|
+
if (path91.includes("..")) {
|
|
10085
|
+
throw new Error(`Invalid redaction path (${path91})`);
|
|
10067
10086
|
}
|
|
10068
|
-
if (
|
|
10069
|
-
throw new Error(`Invalid redaction path (${
|
|
10087
|
+
if (path91.includes(",")) {
|
|
10088
|
+
throw new Error(`Invalid redaction path (${path91})`);
|
|
10070
10089
|
}
|
|
10071
10090
|
let bracketCount = 0;
|
|
10072
10091
|
let inQuotes = false;
|
|
10073
10092
|
let quoteChar = "";
|
|
10074
|
-
for (let i = 0; i <
|
|
10075
|
-
const char =
|
|
10093
|
+
for (let i = 0; i < path91.length; i++) {
|
|
10094
|
+
const char = path91[i];
|
|
10076
10095
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10077
10096
|
if (!inQuotes) {
|
|
10078
10097
|
inQuotes = true;
|
|
@@ -10086,20 +10105,20 @@ var require_redact = __commonJS({
|
|
|
10086
10105
|
} else if (char === "]" && !inQuotes) {
|
|
10087
10106
|
bracketCount--;
|
|
10088
10107
|
if (bracketCount < 0) {
|
|
10089
|
-
throw new Error(`Invalid redaction path (${
|
|
10108
|
+
throw new Error(`Invalid redaction path (${path91})`);
|
|
10090
10109
|
}
|
|
10091
10110
|
}
|
|
10092
10111
|
}
|
|
10093
10112
|
if (bracketCount !== 0) {
|
|
10094
|
-
throw new Error(`Invalid redaction path (${
|
|
10113
|
+
throw new Error(`Invalid redaction path (${path91})`);
|
|
10095
10114
|
}
|
|
10096
10115
|
}
|
|
10097
10116
|
function validatePaths(paths) {
|
|
10098
10117
|
if (!Array.isArray(paths)) {
|
|
10099
10118
|
throw new TypeError("paths must be an array");
|
|
10100
10119
|
}
|
|
10101
|
-
for (const
|
|
10102
|
-
validatePath(
|
|
10120
|
+
for (const path91 of paths) {
|
|
10121
|
+
validatePath(path91);
|
|
10103
10122
|
}
|
|
10104
10123
|
}
|
|
10105
10124
|
function slowRedact(options = {}) {
|
|
@@ -10267,8 +10286,8 @@ var require_redaction = __commonJS({
|
|
|
10267
10286
|
if (shape[k2] === null) {
|
|
10268
10287
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
10269
10288
|
} else {
|
|
10270
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10271
|
-
return censor(value, [k2, ...
|
|
10289
|
+
const wrappedCensor = typeof censor === "function" ? (value, path91) => {
|
|
10290
|
+
return censor(value, [k2, ...path91]);
|
|
10272
10291
|
} : censor;
|
|
10273
10292
|
o[k2] = Redact({
|
|
10274
10293
|
paths: shape[k2],
|
|
@@ -10486,10 +10505,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10486
10505
|
var require_sonic_boom = __commonJS({
|
|
10487
10506
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10488
10507
|
"use strict";
|
|
10489
|
-
var
|
|
10508
|
+
var fs80 = require("fs");
|
|
10490
10509
|
var EventEmitter3 = require("events");
|
|
10491
10510
|
var inherits = require("util").inherits;
|
|
10492
|
-
var
|
|
10511
|
+
var path91 = require("path");
|
|
10493
10512
|
var sleep2 = require_atomic_sleep();
|
|
10494
10513
|
var assert = require("assert");
|
|
10495
10514
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10543,20 +10562,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10543
10562
|
const mode = sonic.mode;
|
|
10544
10563
|
if (sonic.sync) {
|
|
10545
10564
|
try {
|
|
10546
|
-
if (sonic.mkdir)
|
|
10547
|
-
const fd =
|
|
10565
|
+
if (sonic.mkdir) fs80.mkdirSync(path91.dirname(file), { recursive: true });
|
|
10566
|
+
const fd = fs80.openSync(file, flags, mode);
|
|
10548
10567
|
fileOpened(null, fd);
|
|
10549
10568
|
} catch (err) {
|
|
10550
10569
|
fileOpened(err);
|
|
10551
10570
|
throw err;
|
|
10552
10571
|
}
|
|
10553
10572
|
} else if (sonic.mkdir) {
|
|
10554
|
-
|
|
10573
|
+
fs80.mkdir(path91.dirname(file), { recursive: true }, (err) => {
|
|
10555
10574
|
if (err) return fileOpened(err);
|
|
10556
|
-
|
|
10575
|
+
fs80.open(file, flags, mode, fileOpened);
|
|
10557
10576
|
});
|
|
10558
10577
|
} else {
|
|
10559
|
-
|
|
10578
|
+
fs80.open(file, flags, mode, fileOpened);
|
|
10560
10579
|
}
|
|
10561
10580
|
}
|
|
10562
10581
|
function SonicBoom(opts) {
|
|
@@ -10597,8 +10616,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10597
10616
|
this.flush = flushBuffer;
|
|
10598
10617
|
this.flushSync = flushBufferSync;
|
|
10599
10618
|
this._actualWrite = actualWriteBuffer;
|
|
10600
|
-
fsWriteSync = () =>
|
|
10601
|
-
fsWrite = () =>
|
|
10619
|
+
fsWriteSync = () => fs80.writeSync(this.fd, this._writingBuf);
|
|
10620
|
+
fsWrite = () => fs80.write(this.fd, this._writingBuf, this.release);
|
|
10602
10621
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10603
10622
|
this._writingBuf = "";
|
|
10604
10623
|
this.write = write;
|
|
@@ -10607,15 +10626,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10607
10626
|
this._actualWrite = actualWrite;
|
|
10608
10627
|
fsWriteSync = () => {
|
|
10609
10628
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10610
|
-
return
|
|
10629
|
+
return fs80.writeSync(this.fd, this._writingBuf);
|
|
10611
10630
|
}
|
|
10612
|
-
return
|
|
10631
|
+
return fs80.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10613
10632
|
};
|
|
10614
10633
|
fsWrite = () => {
|
|
10615
10634
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10616
|
-
return
|
|
10635
|
+
return fs80.write(this.fd, this._writingBuf, this.release);
|
|
10617
10636
|
}
|
|
10618
|
-
return
|
|
10637
|
+
return fs80.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10619
10638
|
};
|
|
10620
10639
|
} else {
|
|
10621
10640
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10672,7 +10691,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10672
10691
|
}
|
|
10673
10692
|
}
|
|
10674
10693
|
if (this._fsync) {
|
|
10675
|
-
|
|
10694
|
+
fs80.fsyncSync(this.fd);
|
|
10676
10695
|
}
|
|
10677
10696
|
const len = this._len;
|
|
10678
10697
|
if (this._reopening) {
|
|
@@ -10786,7 +10805,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10786
10805
|
const onDrain = () => {
|
|
10787
10806
|
if (!this._fsync) {
|
|
10788
10807
|
try {
|
|
10789
|
-
|
|
10808
|
+
fs80.fsync(this.fd, (err) => {
|
|
10790
10809
|
this._flushPending = false;
|
|
10791
10810
|
cb(err);
|
|
10792
10811
|
});
|
|
@@ -10888,7 +10907,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10888
10907
|
const fd = this.fd;
|
|
10889
10908
|
this.once("ready", () => {
|
|
10890
10909
|
if (fd !== this.fd) {
|
|
10891
|
-
|
|
10910
|
+
fs80.close(fd, (err) => {
|
|
10892
10911
|
if (err) {
|
|
10893
10912
|
return this.emit("error", err);
|
|
10894
10913
|
}
|
|
@@ -10937,7 +10956,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10937
10956
|
buf = this._bufs[0];
|
|
10938
10957
|
}
|
|
10939
10958
|
try {
|
|
10940
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10959
|
+
const n = Buffer.isBuffer(buf) ? fs80.writeSync(this.fd, buf) : fs80.writeSync(this.fd, buf, "utf8");
|
|
10941
10960
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10942
10961
|
buf = releasedBufObj.writingBuf;
|
|
10943
10962
|
this._len = releasedBufObj.len;
|
|
@@ -10953,7 +10972,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10953
10972
|
}
|
|
10954
10973
|
}
|
|
10955
10974
|
try {
|
|
10956
|
-
|
|
10975
|
+
fs80.fsyncSync(this.fd);
|
|
10957
10976
|
} catch {
|
|
10958
10977
|
}
|
|
10959
10978
|
}
|
|
@@ -10974,7 +10993,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10974
10993
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10975
10994
|
}
|
|
10976
10995
|
try {
|
|
10977
|
-
const n =
|
|
10996
|
+
const n = fs80.writeSync(this.fd, buf);
|
|
10978
10997
|
buf = buf.subarray(n);
|
|
10979
10998
|
this._len = Math.max(this._len - n, 0);
|
|
10980
10999
|
if (buf.length <= 0) {
|
|
@@ -11002,13 +11021,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11002
11021
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11003
11022
|
if (this.sync) {
|
|
11004
11023
|
try {
|
|
11005
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
11024
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs80.writeSync(this.fd, this._writingBuf) : fs80.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11006
11025
|
release(null, written);
|
|
11007
11026
|
} catch (err) {
|
|
11008
11027
|
release(err);
|
|
11009
11028
|
}
|
|
11010
11029
|
} else {
|
|
11011
|
-
|
|
11030
|
+
fs80.write(this.fd, this._writingBuf, release);
|
|
11012
11031
|
}
|
|
11013
11032
|
}
|
|
11014
11033
|
function actualWriteBuffer() {
|
|
@@ -11017,7 +11036,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11017
11036
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11018
11037
|
if (this.sync) {
|
|
11019
11038
|
try {
|
|
11020
|
-
const written =
|
|
11039
|
+
const written = fs80.writeSync(this.fd, this._writingBuf);
|
|
11021
11040
|
release(null, written);
|
|
11022
11041
|
} catch (err) {
|
|
11023
11042
|
release(err);
|
|
@@ -11026,7 +11045,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11026
11045
|
if (kCopyBuffer) {
|
|
11027
11046
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11028
11047
|
}
|
|
11029
|
-
|
|
11048
|
+
fs80.write(this.fd, this._writingBuf, release);
|
|
11030
11049
|
}
|
|
11031
11050
|
}
|
|
11032
11051
|
function actualClose(sonic) {
|
|
@@ -11042,12 +11061,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11042
11061
|
sonic._lens = [];
|
|
11043
11062
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11044
11063
|
try {
|
|
11045
|
-
|
|
11064
|
+
fs80.fsync(sonic.fd, closeWrapped);
|
|
11046
11065
|
} catch {
|
|
11047
11066
|
}
|
|
11048
11067
|
function closeWrapped() {
|
|
11049
11068
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11050
|
-
|
|
11069
|
+
fs80.close(sonic.fd, done);
|
|
11051
11070
|
} else {
|
|
11052
11071
|
done();
|
|
11053
11072
|
}
|
|
@@ -13411,7 +13430,7 @@ var require_multistream = __commonJS({
|
|
|
13411
13430
|
var require_pino = __commonJS({
|
|
13412
13431
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
13413
13432
|
"use strict";
|
|
13414
|
-
var
|
|
13433
|
+
var os31 = require("os");
|
|
13415
13434
|
var stdSerializers = require_pino_std_serializers();
|
|
13416
13435
|
var caller = require_caller();
|
|
13417
13436
|
var redaction = require_redaction();
|
|
@@ -13458,7 +13477,7 @@ var require_pino = __commonJS({
|
|
|
13458
13477
|
} = symbols;
|
|
13459
13478
|
var { epochTime, nullTime } = time;
|
|
13460
13479
|
var { pid } = process;
|
|
13461
|
-
var hostname =
|
|
13480
|
+
var hostname = os31.hostname();
|
|
13462
13481
|
var defaultErrorSerializer = stdSerializers.err;
|
|
13463
13482
|
var defaultOptions2 = {
|
|
13464
13483
|
level: "info",
|
|
@@ -14182,11 +14201,11 @@ var init_lib = __esm({
|
|
|
14182
14201
|
}
|
|
14183
14202
|
}
|
|
14184
14203
|
},
|
|
14185
|
-
addToPath: function addToPath(
|
|
14186
|
-
var last =
|
|
14204
|
+
addToPath: function addToPath(path91, added, removed, oldPosInc, options) {
|
|
14205
|
+
var last = path91.lastComponent;
|
|
14187
14206
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14188
14207
|
return {
|
|
14189
|
-
oldPos:
|
|
14208
|
+
oldPos: path91.oldPos + oldPosInc,
|
|
14190
14209
|
lastComponent: {
|
|
14191
14210
|
count: last.count + 1,
|
|
14192
14211
|
added,
|
|
@@ -14196,7 +14215,7 @@ var init_lib = __esm({
|
|
|
14196
14215
|
};
|
|
14197
14216
|
} else {
|
|
14198
14217
|
return {
|
|
14199
|
-
oldPos:
|
|
14218
|
+
oldPos: path91.oldPos + oldPosInc,
|
|
14200
14219
|
lastComponent: {
|
|
14201
14220
|
count: 1,
|
|
14202
14221
|
added,
|
|
@@ -14778,10 +14797,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14778
14797
|
const memories = raw.map((m2) => {
|
|
14779
14798
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14780
14799
|
const rec4 = m2;
|
|
14781
|
-
const
|
|
14800
|
+
const path91 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14782
14801
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14783
|
-
if (!
|
|
14784
|
-
const entry = { path:
|
|
14802
|
+
if (!path91 || content == null) return null;
|
|
14803
|
+
const entry = { path: path91, content };
|
|
14785
14804
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14786
14805
|
return entry;
|
|
14787
14806
|
}).filter((m2) => m2 !== null);
|
|
@@ -15647,10 +15666,10 @@ function parseAttachment(obj) {
|
|
|
15647
15666
|
const memories = raw.map((m2) => {
|
|
15648
15667
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15649
15668
|
const rec4 = m2;
|
|
15650
|
-
const
|
|
15669
|
+
const path91 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15651
15670
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15652
|
-
if (!
|
|
15653
|
-
const out = { path:
|
|
15671
|
+
if (!path91 || content == null) return null;
|
|
15672
|
+
const out = { path: path91, content };
|
|
15654
15673
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15655
15674
|
return out;
|
|
15656
15675
|
}).filter((m2) => m2 !== null);
|
|
@@ -36624,8 +36643,8 @@ var require_utils = __commonJS({
|
|
|
36624
36643
|
var result = transform[inputType][outputType](input);
|
|
36625
36644
|
return result;
|
|
36626
36645
|
};
|
|
36627
|
-
exports2.resolve = function(
|
|
36628
|
-
var parts =
|
|
36646
|
+
exports2.resolve = function(path91) {
|
|
36647
|
+
var parts = path91.split("/");
|
|
36629
36648
|
var result = [];
|
|
36630
36649
|
for (var index = 0; index < parts.length; index++) {
|
|
36631
36650
|
var part = parts[index];
|
|
@@ -42478,18 +42497,18 @@ var require_object = __commonJS({
|
|
|
42478
42497
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42479
42498
|
this.files[name] = object;
|
|
42480
42499
|
};
|
|
42481
|
-
var parentFolder = function(
|
|
42482
|
-
if (
|
|
42483
|
-
|
|
42500
|
+
var parentFolder = function(path91) {
|
|
42501
|
+
if (path91.slice(-1) === "/") {
|
|
42502
|
+
path91 = path91.substring(0, path91.length - 1);
|
|
42484
42503
|
}
|
|
42485
|
-
var lastSlash =
|
|
42486
|
-
return lastSlash > 0 ?
|
|
42504
|
+
var lastSlash = path91.lastIndexOf("/");
|
|
42505
|
+
return lastSlash > 0 ? path91.substring(0, lastSlash) : "";
|
|
42487
42506
|
};
|
|
42488
|
-
var forceTrailingSlash = function(
|
|
42489
|
-
if (
|
|
42490
|
-
|
|
42507
|
+
var forceTrailingSlash = function(path91) {
|
|
42508
|
+
if (path91.slice(-1) !== "/") {
|
|
42509
|
+
path91 += "/";
|
|
42491
42510
|
}
|
|
42492
|
-
return
|
|
42511
|
+
return path91;
|
|
42493
42512
|
};
|
|
42494
42513
|
var folderAdd = function(name, createFolders) {
|
|
42495
42514
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43491,7 +43510,7 @@ var require_lib3 = __commonJS({
|
|
|
43491
43510
|
// src/run-case/recorder.ts
|
|
43492
43511
|
function startRunCaseRecorder(opts) {
|
|
43493
43512
|
const now = opts.now ?? Date.now;
|
|
43494
|
-
const dir =
|
|
43513
|
+
const dir = import_node_path73.default.dirname(opts.recordPath);
|
|
43495
43514
|
let stream = null;
|
|
43496
43515
|
let closing = false;
|
|
43497
43516
|
let closedSettled = false;
|
|
@@ -43505,8 +43524,8 @@ function startRunCaseRecorder(opts) {
|
|
|
43505
43524
|
});
|
|
43506
43525
|
const ensureStream = () => {
|
|
43507
43526
|
if (stream) return stream;
|
|
43508
|
-
|
|
43509
|
-
stream =
|
|
43527
|
+
import_node_fs54.default.mkdirSync(dir, { recursive: true });
|
|
43528
|
+
stream = import_node_fs54.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
43510
43529
|
stream.on("close", () => closedResolve());
|
|
43511
43530
|
return stream;
|
|
43512
43531
|
};
|
|
@@ -43531,12 +43550,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43531
43550
|
};
|
|
43532
43551
|
return { tap, close, closed };
|
|
43533
43552
|
}
|
|
43534
|
-
var
|
|
43553
|
+
var import_node_fs54, import_node_path73;
|
|
43535
43554
|
var init_recorder = __esm({
|
|
43536
43555
|
"src/run-case/recorder.ts"() {
|
|
43537
43556
|
"use strict";
|
|
43538
|
-
|
|
43539
|
-
|
|
43557
|
+
import_node_fs54 = __toESM(require("fs"), 1);
|
|
43558
|
+
import_node_path73 = __toESM(require("path"), 1);
|
|
43540
43559
|
}
|
|
43541
43560
|
});
|
|
43542
43561
|
|
|
@@ -43579,7 +43598,7 @@ var init_wire = __esm({
|
|
|
43579
43598
|
// src/run-case/controller.ts
|
|
43580
43599
|
async function runController(opts) {
|
|
43581
43600
|
const now = opts.now ?? Date.now;
|
|
43582
|
-
const cwd = opts.cwd ?? (0,
|
|
43601
|
+
const cwd = opts.cwd ?? (0, import_node_fs55.mkdtempSync)(import_node_path74.default.join(import_node_os27.default.tmpdir(), "clawd-runcase-"));
|
|
43583
43602
|
const ownsCwd = opts.cwd === void 0;
|
|
43584
43603
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43585
43604
|
const spawnCtx = { cwd };
|
|
@@ -43740,19 +43759,19 @@ async function runController(opts) {
|
|
|
43740
43759
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
43741
43760
|
if (ownsCwd) {
|
|
43742
43761
|
try {
|
|
43743
|
-
(0,
|
|
43762
|
+
(0, import_node_fs55.rmSync)(cwd, { recursive: true, force: true });
|
|
43744
43763
|
} catch {
|
|
43745
43764
|
}
|
|
43746
43765
|
}
|
|
43747
43766
|
return exitCode ?? 0;
|
|
43748
43767
|
}
|
|
43749
|
-
var
|
|
43768
|
+
var import_node_fs55, import_node_os27, import_node_path74;
|
|
43750
43769
|
var init_controller = __esm({
|
|
43751
43770
|
"src/run-case/controller.ts"() {
|
|
43752
43771
|
"use strict";
|
|
43753
|
-
|
|
43754
|
-
|
|
43755
|
-
|
|
43772
|
+
import_node_fs55 = require("fs");
|
|
43773
|
+
import_node_os27 = __toESM(require("os"), 1);
|
|
43774
|
+
import_node_path74 = __toESM(require("path"), 1);
|
|
43756
43775
|
init_claude();
|
|
43757
43776
|
init_stdout_splitter();
|
|
43758
43777
|
init_permission_stdio();
|
|
@@ -44027,9 +44046,9 @@ Env (advanced):
|
|
|
44027
44046
|
`;
|
|
44028
44047
|
|
|
44029
44048
|
// src/index.ts
|
|
44030
|
-
var
|
|
44031
|
-
var
|
|
44032
|
-
var
|
|
44049
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
44050
|
+
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
44051
|
+
var import_node_os26 = __toESM(require("os"), 1);
|
|
44033
44052
|
var import_node_crypto22 = require("crypto");
|
|
44034
44053
|
var import_node_url4 = require("url");
|
|
44035
44054
|
|
|
@@ -47069,7 +47088,7 @@ var SessionManager = class {
|
|
|
47069
47088
|
subSessionMeta.codexSandbox = {
|
|
47070
47089
|
writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
|
|
47071
47090
|
denyRead: codexCfg?.denyRead ?? [],
|
|
47072
|
-
network: codexCfg?.network ??
|
|
47091
|
+
network: codexCfg?.network ?? false
|
|
47073
47092
|
};
|
|
47074
47093
|
}
|
|
47075
47094
|
if (subSessionMeta?.personaMode === "owner" && file.projectPath) {
|
|
@@ -49446,408 +49465,20 @@ var PersonaRegistry = class {
|
|
|
49446
49465
|
}
|
|
49447
49466
|
};
|
|
49448
49467
|
|
|
49449
|
-
// src/skills/scanner.ts
|
|
49450
|
-
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
49451
|
-
var import_node_os6 = __toESM(require("os"), 1);
|
|
49452
|
-
var import_node_path9 = __toESM(require("path"), 1);
|
|
49453
|
-
|
|
49454
|
-
// src/skills/frontmatter.ts
|
|
49455
|
-
var STRIP_QUOTES = /^["']|["']$/g;
|
|
49456
|
-
function strip(s) {
|
|
49457
|
-
return s.trim().replace(STRIP_QUOTES, "");
|
|
49458
|
-
}
|
|
49459
|
-
function parseFrontmatter(content, keys) {
|
|
49460
|
-
const out = {};
|
|
49461
|
-
if (!content.startsWith("---")) return out;
|
|
49462
|
-
const end = content.indexOf("---", 3);
|
|
49463
|
-
if (end === -1) return out;
|
|
49464
|
-
const lines = content.slice(3, end).split("\n");
|
|
49465
|
-
for (let i = 0; i < lines.length; i++) {
|
|
49466
|
-
const trimmed = lines[i].trim();
|
|
49467
|
-
for (const key of keys) {
|
|
49468
|
-
const prefix = `${key}:`;
|
|
49469
|
-
if (!trimmed.startsWith(prefix)) continue;
|
|
49470
|
-
const rest = trimmed.slice(prefix.length).trim();
|
|
49471
|
-
if (rest === "|" || rest === ">" || rest === "|-" || rest === ">-") {
|
|
49472
|
-
const parts = [];
|
|
49473
|
-
for (let j = i + 1; j < lines.length; j++) {
|
|
49474
|
-
const next = lines[j];
|
|
49475
|
-
if (next.length === 0) {
|
|
49476
|
-
parts.push("");
|
|
49477
|
-
continue;
|
|
49478
|
-
}
|
|
49479
|
-
if (!/^\s/.test(next)) break;
|
|
49480
|
-
parts.push(next.replace(/^\s+/, ""));
|
|
49481
|
-
}
|
|
49482
|
-
const value = parts.filter(Boolean).join(" ").trim();
|
|
49483
|
-
if (value) out[key] = value;
|
|
49484
|
-
} else {
|
|
49485
|
-
const value = strip(rest);
|
|
49486
|
-
if (value) out[key] = value;
|
|
49487
|
-
}
|
|
49488
|
-
break;
|
|
49489
|
-
}
|
|
49490
|
-
}
|
|
49491
|
-
return out;
|
|
49492
|
-
}
|
|
49493
|
-
|
|
49494
|
-
// src/skills/builtin-cc-resources.ts
|
|
49495
|
-
var BUILTIN_SKILLS = [
|
|
49496
|
-
{ name: "update-config", source: "builtin", description: "Update Claude Code configuration." },
|
|
49497
|
-
{ name: "keybindings-help", source: "builtin", description: "Show available keybindings." },
|
|
49498
|
-
{ name: "verify", source: "builtin", description: "Verify the implementation." },
|
|
49499
|
-
{ name: "debug", source: "builtin", description: "Debug current issue." },
|
|
49500
|
-
{ name: "lorem-ipsum", source: "builtin", description: "Generate lorem ipsum placeholder text." },
|
|
49501
|
-
{ name: "skillify", source: "builtin", description: "Convert a process into a reusable skill." },
|
|
49502
|
-
{ name: "remember", source: "builtin", description: "Remember context for later use." },
|
|
49503
|
-
{ name: "simplify", source: "builtin", description: "Simplify the code or message." },
|
|
49504
|
-
{ name: "batch", source: "builtin", description: "Run a batch of similar operations." },
|
|
49505
|
-
{ name: "stuck", source: "builtin", description: "Help unstick a stalled task." },
|
|
49506
|
-
{ name: "loop", source: "builtin", description: "Loop a task until a condition is met." },
|
|
49507
|
-
{ name: "cron-list", source: "builtin", description: "List scheduled cron tasks." },
|
|
49508
|
-
{ name: "cron-delete", source: "builtin", description: "Delete a scheduled cron task." },
|
|
49509
|
-
{ name: "dream", source: "builtin", description: "Brainstorm freely without constraints." },
|
|
49510
|
-
{ name: "hunter", source: "builtin", description: "Hunt down a bug or root cause." },
|
|
49511
|
-
{ name: "schedule", source: "builtin", description: "Schedule a task to run later." },
|
|
49512
|
-
{ name: "claude-api", source: "builtin", description: "Use the Claude API directly." },
|
|
49513
|
-
{ name: "claude-in-chrome", source: "builtin", description: "Drive Claude inside Chrome via the Chrome extension." }
|
|
49514
|
-
];
|
|
49515
|
-
var BUILTIN_AGENTS = [
|
|
49516
|
-
{
|
|
49517
|
-
name: "general-purpose",
|
|
49518
|
-
source: "builtin",
|
|
49519
|
-
description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
|
|
49520
|
-
whenToUse: "When you are searching for a keyword or file and are not confident you will find the right match in the first few tries."
|
|
49521
|
-
},
|
|
49522
|
-
{
|
|
49523
|
-
name: "statusline-setup",
|
|
49524
|
-
source: "builtin",
|
|
49525
|
-
description: "Configure the user's Claude Code status line setting.",
|
|
49526
|
-
whenToUse: "When the user is setting up or changing their status line configuration."
|
|
49527
|
-
},
|
|
49528
|
-
{
|
|
49529
|
-
name: "Explore",
|
|
49530
|
-
source: "builtin",
|
|
49531
|
-
description: "Explore the codebase to gather context.",
|
|
49532
|
-
whenToUse: "Before making changes that require understanding the surrounding code."
|
|
49533
|
-
},
|
|
49534
|
-
{
|
|
49535
|
-
name: "Plan",
|
|
49536
|
-
source: "builtin",
|
|
49537
|
-
description: "Produce an implementation plan before writing code.",
|
|
49538
|
-
whenToUse: "When the task is non-trivial and would benefit from an explicit plan."
|
|
49539
|
-
},
|
|
49540
|
-
{
|
|
49541
|
-
name: "claude-code-guide",
|
|
49542
|
-
source: "builtin",
|
|
49543
|
-
description: "Guide the user through Claude Code features.",
|
|
49544
|
-
whenToUse: "When the user needs help understanding what Claude Code can do."
|
|
49545
|
-
},
|
|
49546
|
-
{
|
|
49547
|
-
name: "verification",
|
|
49548
|
-
source: "builtin",
|
|
49549
|
-
description: "Verify that a change works as intended.",
|
|
49550
|
-
whenToUse: "After implementing a change, before declaring it done."
|
|
49551
|
-
}
|
|
49552
|
-
];
|
|
49553
|
-
|
|
49554
|
-
// src/skills/scanner.ts
|
|
49555
|
-
function parseDescription(content) {
|
|
49556
|
-
const fields = parseFrontmatter(content, ["description"]);
|
|
49557
|
-
return { description: fields.description ?? "" };
|
|
49558
|
-
}
|
|
49559
|
-
function isDirLikeSync(p2) {
|
|
49560
|
-
try {
|
|
49561
|
-
return import_node_fs9.default.statSync(p2).isDirectory();
|
|
49562
|
-
} catch {
|
|
49563
|
-
return false;
|
|
49564
|
-
}
|
|
49565
|
-
}
|
|
49566
|
-
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
49567
|
-
let entries;
|
|
49568
|
-
try {
|
|
49569
|
-
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
49570
|
-
} catch {
|
|
49571
|
-
return;
|
|
49572
|
-
}
|
|
49573
|
-
for (const ent of entries) {
|
|
49574
|
-
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
49575
|
-
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
49576
|
-
let content;
|
|
49577
|
-
try {
|
|
49578
|
-
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
|
|
49579
|
-
} catch {
|
|
49580
|
-
try {
|
|
49581
|
-
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
|
|
49582
|
-
} catch {
|
|
49583
|
-
continue;
|
|
49584
|
-
}
|
|
49585
|
-
}
|
|
49586
|
-
const { description } = parseDescription(content);
|
|
49587
|
-
const baseName = ent.name;
|
|
49588
|
-
const name = pluginName ? `${pluginName}:${baseName}` : baseName;
|
|
49589
|
-
if (seen.has(name)) continue;
|
|
49590
|
-
seen.add(name);
|
|
49591
|
-
const info = { name, source, path: entryPath, description: description || void 0 };
|
|
49592
|
-
if (pluginName) info.plugin = pluginName;
|
|
49593
|
-
out.push(info);
|
|
49594
|
-
}
|
|
49595
|
-
}
|
|
49596
|
-
function listSkillsForDir(dir, source) {
|
|
49597
|
-
const seen = /* @__PURE__ */ new Set();
|
|
49598
|
-
const out = [];
|
|
49599
|
-
scanSkillDir(dir, source, seen, out);
|
|
49600
|
-
return out;
|
|
49601
|
-
}
|
|
49602
|
-
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
49603
|
-
let entries;
|
|
49604
|
-
try {
|
|
49605
|
-
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
49606
|
-
} catch {
|
|
49607
|
-
return;
|
|
49608
|
-
}
|
|
49609
|
-
for (const ent of entries) {
|
|
49610
|
-
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
49611
|
-
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
49612
|
-
const ns = ent.name;
|
|
49613
|
-
let subEntries;
|
|
49614
|
-
try {
|
|
49615
|
-
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
49616
|
-
} catch {
|
|
49617
|
-
continue;
|
|
49618
|
-
}
|
|
49619
|
-
for (const se of subEntries) {
|
|
49620
|
-
if (!se.name.endsWith(".md")) continue;
|
|
49621
|
-
const sePath = import_node_path9.default.join(entryPath, se.name);
|
|
49622
|
-
let content;
|
|
49623
|
-
try {
|
|
49624
|
-
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
49625
|
-
} catch {
|
|
49626
|
-
continue;
|
|
49627
|
-
}
|
|
49628
|
-
const cmd = se.name.replace(/\.md$/, "");
|
|
49629
|
-
const { description } = parseDescription(content);
|
|
49630
|
-
const qualified = `${ns}:${cmd}`;
|
|
49631
|
-
const name = pluginName ? `${pluginName}:${qualified}` : qualified;
|
|
49632
|
-
if (seen.has(name)) continue;
|
|
49633
|
-
seen.add(name);
|
|
49634
|
-
const info = { name, source, path: sePath, description: description || void 0 };
|
|
49635
|
-
if (pluginName) info.plugin = pluginName;
|
|
49636
|
-
out.push(info);
|
|
49637
|
-
}
|
|
49638
|
-
} else if (ent.name.endsWith(".md")) {
|
|
49639
|
-
let content;
|
|
49640
|
-
try {
|
|
49641
|
-
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
49642
|
-
} catch {
|
|
49643
|
-
continue;
|
|
49644
|
-
}
|
|
49645
|
-
const cmd = ent.name.replace(/\.md$/, "");
|
|
49646
|
-
const { description } = parseDescription(content);
|
|
49647
|
-
const name = pluginName ? `${pluginName}:${cmd}` : cmd;
|
|
49648
|
-
if (seen.has(name)) continue;
|
|
49649
|
-
seen.add(name);
|
|
49650
|
-
const info = { name, source, path: entryPath, description: description || void 0 };
|
|
49651
|
-
if (pluginName) info.plugin = pluginName;
|
|
49652
|
-
out.push(info);
|
|
49653
|
-
}
|
|
49654
|
-
}
|
|
49655
|
-
}
|
|
49656
|
-
function readInstalledPlugins(home) {
|
|
49657
|
-
const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
49658
|
-
let raw;
|
|
49659
|
-
try {
|
|
49660
|
-
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
49661
|
-
} catch {
|
|
49662
|
-
return [];
|
|
49663
|
-
}
|
|
49664
|
-
let parsed;
|
|
49665
|
-
try {
|
|
49666
|
-
parsed = JSON.parse(raw);
|
|
49667
|
-
} catch {
|
|
49668
|
-
return [];
|
|
49669
|
-
}
|
|
49670
|
-
const out = [];
|
|
49671
|
-
for (const [key, entries] of Object.entries(parsed.plugins ?? {})) {
|
|
49672
|
-
if (!Array.isArray(entries) || entries.length === 0) continue;
|
|
49673
|
-
const entry = entries[0];
|
|
49674
|
-
if (!entry?.installPath) continue;
|
|
49675
|
-
const pluginName = key.includes("@") ? key.slice(0, key.indexOf("@")) : key;
|
|
49676
|
-
if (!pluginName) continue;
|
|
49677
|
-
out.push({ name: pluginName, root: entry.installPath });
|
|
49678
|
-
}
|
|
49679
|
-
return out;
|
|
49680
|
-
}
|
|
49681
|
-
var SkillsScanner = class {
|
|
49682
|
-
home;
|
|
49683
|
-
extraPluginRoots;
|
|
49684
|
-
constructor(opts = {}) {
|
|
49685
|
-
this.home = opts.home ?? import_node_os6.default.homedir();
|
|
49686
|
-
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
49687
|
-
}
|
|
49688
|
-
/**
|
|
49689
|
-
* 对齐 cc-direct(openclaw-plugin-clawos/src/claude-code/skills-scanner.ts):
|
|
49690
|
-
* 1. global: ~/.claude/skills + ~/.claude/commands
|
|
49691
|
-
* 2. project: <cwd>/.claude/skills + <cwd>/.claude/commands
|
|
49692
|
-
* 3. plugin: installed_plugins.json 里每个 plugin 的 skills + commands
|
|
49693
|
-
* 顺序 global → project → plugin,同名去重(先到先得)
|
|
49694
|
-
*/
|
|
49695
|
-
list(args) {
|
|
49696
|
-
const seen = /* @__PURE__ */ new Set();
|
|
49697
|
-
const builtinBlock = [];
|
|
49698
|
-
for (const b2 of BUILTIN_SKILLS) {
|
|
49699
|
-
if (seen.has(b2.name)) continue;
|
|
49700
|
-
seen.add(b2.name);
|
|
49701
|
-
builtinBlock.push({
|
|
49702
|
-
name: b2.name,
|
|
49703
|
-
source: "builtin",
|
|
49704
|
-
description: b2.description
|
|
49705
|
-
});
|
|
49706
|
-
}
|
|
49707
|
-
const fsBlock = [];
|
|
49708
|
-
scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
|
|
49709
|
-
scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
|
|
49710
|
-
scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
|
|
49711
|
-
scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
|
|
49712
|
-
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
49713
|
-
for (const { name, root } of plugins) {
|
|
49714
|
-
scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
|
|
49715
|
-
scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
|
|
49716
|
-
}
|
|
49717
|
-
fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
|
|
49718
|
-
return [...builtinBlock, ...fsBlock];
|
|
49719
|
-
}
|
|
49720
|
-
};
|
|
49721
|
-
|
|
49722
|
-
// src/persona/manager.ts
|
|
49723
|
-
var PersonaManager = class {
|
|
49724
|
-
constructor(deps) {
|
|
49725
|
-
this.deps = deps;
|
|
49726
|
-
}
|
|
49727
|
-
deps;
|
|
49728
|
-
/**
|
|
49729
|
-
* slug 是 persona 的身份,label 只是显示名——两者刻意分开:id 落进文件路径 /
|
|
49730
|
-
* 分享链接且创建后不可改,label 可中文、可随时改。此前 id 从 label 推导,
|
|
49731
|
-
* 非 ascii 被剥空后一律 fallback 成 `persona-persona`。
|
|
49732
|
-
*
|
|
49733
|
-
* 撞名直接抛错而非改名:id 由调用方显式指定,静默换成带后缀的 id 等于把
|
|
49734
|
-
* 用户的选择偷偷改掉。字符集校验在 PersonaCreateArgsSchema(路径穿越边界)。
|
|
49735
|
-
*/
|
|
49736
|
-
create(args) {
|
|
49737
|
-
const personaId2 = `persona-${args.slug}`;
|
|
49738
|
-
if (this.deps.store.has(personaId2)) {
|
|
49739
|
-
throw new Error(`personaId already exists: ${personaId2}`);
|
|
49740
|
-
}
|
|
49741
|
-
const now = Date.now();
|
|
49742
|
-
const persona = {
|
|
49743
|
-
personaId: personaId2,
|
|
49744
|
-
label: args.label,
|
|
49745
|
-
model: args.model,
|
|
49746
|
-
// effort 兜底 high:persona 一律持有具体档位(spec 2026-08-12),UI 会带界面上高亮的
|
|
49747
|
-
// 那一档,但 persona:create 也可能来自 butler 的 persona-authoring skill 这类不带该
|
|
49748
|
-
// 字段的调用方——不兜的话要等下次 daemon 启动 backfill 才补上,中间建的 session 就漏了。
|
|
49749
|
-
// 取值理由与 backfillPersonaSessionDefaults 一致(见那里的注释)。
|
|
49750
|
-
effort: args.effort ?? "high",
|
|
49751
|
-
tool: args.tool,
|
|
49752
|
-
public: args.public ?? false,
|
|
49753
|
-
iconKey: args.iconKey,
|
|
49754
|
-
createdAt: now,
|
|
49755
|
-
updatedAt: now
|
|
49756
|
-
};
|
|
49757
|
-
this.deps.store.write(persona, args.personality);
|
|
49758
|
-
this.deps.registry.set(persona);
|
|
49759
|
-
return persona;
|
|
49760
|
-
}
|
|
49761
|
-
update(personaId2, patch, texts) {
|
|
49762
|
-
const existing = this.deps.registry.get(personaId2);
|
|
49763
|
-
if (!existing) throw new Error(`persona not found: ${personaId2}`);
|
|
49764
|
-
const { iconKey: iconKeyPatch, ...restPatch } = patch;
|
|
49765
|
-
const updated = {
|
|
49766
|
-
...existing,
|
|
49767
|
-
...restPatch,
|
|
49768
|
-
updatedAt: Date.now()
|
|
49769
|
-
};
|
|
49770
|
-
const toolChanged = patch.tool !== void 0 && (patch.tool ?? "claude") !== (existing.tool ?? "claude");
|
|
49771
|
-
if (toolChanged) {
|
|
49772
|
-
if (patch.model === void 0) delete updated.model;
|
|
49773
|
-
if (patch.effort === void 0) delete updated.effort;
|
|
49774
|
-
}
|
|
49775
|
-
if (iconKeyPatch === null) {
|
|
49776
|
-
delete updated.iconKey;
|
|
49777
|
-
} else if (iconKeyPatch !== void 0) {
|
|
49778
|
-
updated.iconKey = iconKeyPatch;
|
|
49779
|
-
}
|
|
49780
|
-
if (texts?.personality !== void 0) {
|
|
49781
|
-
this.deps.store.writePersonality(personaId2, texts.personality);
|
|
49782
|
-
}
|
|
49783
|
-
if (texts?.personalityLocal !== void 0) {
|
|
49784
|
-
this.deps.store.writePersonalityLocal(personaId2, texts.personalityLocal);
|
|
49785
|
-
}
|
|
49786
|
-
this.deps.store.writeMeta(updated);
|
|
49787
|
-
this.deps.registry.set(updated);
|
|
49788
|
-
return updated;
|
|
49789
|
-
}
|
|
49790
|
-
/** 读取 CLAUDE.md 内容;persona 目录或文件不存在时返回 null。透传给 handler 拼响应。 */
|
|
49791
|
-
readPersonality(personaId2) {
|
|
49792
|
-
return this.deps.store.readPersonality(personaId2);
|
|
49793
|
-
}
|
|
49794
|
-
/** 读人格补充层(`.clawd/personality.local.md`);没写过返回 null。供 persona:get 拼响应。 */
|
|
49795
|
-
readPersonalityLocal(personaId2) {
|
|
49796
|
-
return this.deps.store.readPersonalityLocal(personaId2);
|
|
49797
|
-
}
|
|
49798
|
-
/** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
|
|
49799
|
-
listSkills(personaId2) {
|
|
49800
|
-
return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
|
|
49801
|
-
}
|
|
49802
|
-
/**
|
|
49803
|
-
* 读取 persona `.claude/settings.json` 中已启用的插件列表(value === true 的 key)。
|
|
49804
|
-
* 文件不存在 / 解析失败 / 字段缺失 → 空数组。供 persona:get handler 拼响应。
|
|
49805
|
-
*/
|
|
49806
|
-
listEnabledPlugins(personaId2) {
|
|
49807
|
-
return this.deps.store.readEnabledPlugins(personaId2);
|
|
49808
|
-
}
|
|
49809
|
-
/** 读 sandbox-settings.json;不存在 / 损坏返回 null。供 persona:get handler 拼响应。 */
|
|
49810
|
-
/** 读 codex guest 沙箱配置(`.clawd/codex-sandbox.json`);缺失 / 坏 → null。透传给 handler 拼响应。 */
|
|
49811
|
-
readCodexSandboxSettings(personaId2) {
|
|
49812
|
-
return this.deps.store.readCodexSandboxSettings(personaId2);
|
|
49813
|
-
}
|
|
49814
|
-
/**
|
|
49815
|
-
* 局部合并写 codex guest 沙箱配置,返回合并后的全量。
|
|
49816
|
-
*
|
|
49817
|
-
* **必须是合并不是覆盖**:UI 的「访客联网」开关只发 `{network}`,整体覆盖会静默抹掉 owner
|
|
49818
|
-
* 手配的 writableRoots / denyRead(丢的是安全边界,且用户不会立刻发现)。
|
|
49819
|
-
* 不走 PersonaManager.update 是因为它管的是 PersonaFile meta + 人格两层文本,
|
|
49820
|
-
* 而这份配置是另一个文件、另一套 schema。
|
|
49821
|
-
*/
|
|
49822
|
-
mergeCodexSandbox(personaId2, patch) {
|
|
49823
|
-
if (!this.deps.registry.get(personaId2)) throw new Error(`persona not found: ${personaId2}`);
|
|
49824
|
-
const merged = { ...this.deps.store.readCodexSandboxSettings(personaId2) ?? {}, ...patch };
|
|
49825
|
-
this.deps.store.writeCodexSandboxSettings(personaId2, merged);
|
|
49826
|
-
return merged;
|
|
49827
|
-
}
|
|
49828
|
-
readSandboxSettings(personaId2) {
|
|
49829
|
-
return this.deps.store.readSandboxSettings(personaId2);
|
|
49830
|
-
}
|
|
49831
|
-
/**
|
|
49832
|
-
* 删除 persona。
|
|
49833
|
-
* PersonaStore.remove(personaId) 级联删整个 <personaRoot>/<personaId>/ 目录
|
|
49834
|
-
* (含 .clawd/sessions/owner/ 和 .clawd/sessions/guests/<capId>/),rmSync
|
|
49835
|
-
* recursive force 一锅清。
|
|
49836
|
-
*/
|
|
49837
|
-
delete(personaId2) {
|
|
49838
|
-
this.deps.store.remove(personaId2);
|
|
49839
|
-
this.deps.registry.remove(personaId2);
|
|
49840
|
-
}
|
|
49841
|
-
};
|
|
49842
|
-
|
|
49843
49468
|
// src/persona/seed.ts
|
|
49844
|
-
var
|
|
49845
|
-
var
|
|
49469
|
+
var fs12 = __toESM(require("fs"), 1);
|
|
49470
|
+
var path15 = __toESM(require("path"), 1);
|
|
49846
49471
|
var import_node_url = require("url");
|
|
49847
49472
|
var import_meta = {};
|
|
49848
49473
|
var DEFAULT_BYPASS_PROFILE = {
|
|
49849
49474
|
permissions: { defaultMode: "bypassPermissions" }
|
|
49850
49475
|
};
|
|
49476
|
+
var PKG_CACHE_ROOTS = ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"];
|
|
49477
|
+
var CODEX_SANDBOX_DEFAULT = {
|
|
49478
|
+
writableRoots: [...PKG_CACHE_ROOTS],
|
|
49479
|
+
denyRead: [".secrets/**"],
|
|
49480
|
+
network: true
|
|
49481
|
+
};
|
|
49851
49482
|
var DEFAULT_PERSONAS = [
|
|
49852
49483
|
{
|
|
49853
49484
|
personaId: "persona-researcher",
|
|
@@ -49932,7 +49563,7 @@ var DEFAULT_PERSONAS = [
|
|
|
49932
49563
|
}
|
|
49933
49564
|
},
|
|
49934
49565
|
codexSandbox: {
|
|
49935
|
-
writableRoots: [
|
|
49566
|
+
writableRoots: [...PKG_CACHE_ROOTS],
|
|
49936
49567
|
denyRead: [".secrets/**"],
|
|
49937
49568
|
network: true
|
|
49938
49569
|
}
|
|
@@ -49966,7 +49597,7 @@ var DEFAULT_PERSONAS = [
|
|
|
49966
49597
|
}
|
|
49967
49598
|
},
|
|
49968
49599
|
codexSandbox: {
|
|
49969
|
-
writableRoots: [
|
|
49600
|
+
writableRoots: [...PKG_CACHE_ROOTS],
|
|
49970
49601
|
denyRead: [".secrets/**"],
|
|
49971
49602
|
network: true
|
|
49972
49603
|
}
|
|
@@ -50008,7 +49639,7 @@ var DEFAULT_PERSONAS = [
|
|
|
50008
49639
|
}
|
|
50009
49640
|
},
|
|
50010
49641
|
codexSandbox: {
|
|
50011
|
-
writableRoots: [
|
|
49642
|
+
writableRoots: [...PKG_CACHE_ROOTS],
|
|
50012
49643
|
denyRead: [".secrets/**"],
|
|
50013
49644
|
network: true
|
|
50014
49645
|
}
|
|
@@ -50033,24 +49664,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
|
|
|
50033
49664
|
if (!argv1) return null;
|
|
50034
49665
|
let real = argv1;
|
|
50035
49666
|
try {
|
|
50036
|
-
real =
|
|
49667
|
+
real = fs12.realpathSync(argv1);
|
|
50037
49668
|
} catch {
|
|
50038
49669
|
}
|
|
50039
|
-
return
|
|
49670
|
+
return path15.resolve(path15.dirname(real), sibling);
|
|
50040
49671
|
}
|
|
50041
49672
|
function findDefaultsRoot(logger) {
|
|
50042
49673
|
const candidates = [];
|
|
50043
49674
|
try {
|
|
50044
|
-
const here =
|
|
50045
|
-
candidates.push(
|
|
50046
|
-
candidates.push(
|
|
49675
|
+
const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
49676
|
+
candidates.push(path15.resolve(here, "defaults"));
|
|
49677
|
+
candidates.push(path15.resolve(here, "persona-defaults"));
|
|
50047
49678
|
} catch {
|
|
50048
49679
|
}
|
|
50049
49680
|
const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
|
|
50050
49681
|
if (fromArgv) candidates.push(fromArgv);
|
|
50051
49682
|
for (const c of candidates) {
|
|
50052
49683
|
try {
|
|
50053
|
-
if (
|
|
49684
|
+
if (fs12.statSync(c).isDirectory()) {
|
|
50054
49685
|
logger?.info("persona.defaults-root.resolved", { root: c });
|
|
50055
49686
|
return c;
|
|
50056
49687
|
}
|
|
@@ -50067,8 +49698,8 @@ function seedDefaultPersonas(args) {
|
|
|
50067
49698
|
args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
|
|
50068
49699
|
continue;
|
|
50069
49700
|
}
|
|
50070
|
-
const bundleDir =
|
|
50071
|
-
if (!
|
|
49701
|
+
const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
|
|
49702
|
+
if (!fs12.existsSync(bundleDir)) {
|
|
50072
49703
|
args.logger.warn("persona.seed.skip", {
|
|
50073
49704
|
personaId: entry.personaId,
|
|
50074
49705
|
reason: "bundle-missing",
|
|
@@ -50076,8 +49707,8 @@ function seedDefaultPersonas(args) {
|
|
|
50076
49707
|
});
|
|
50077
49708
|
continue;
|
|
50078
49709
|
}
|
|
50079
|
-
const claudeMdPath =
|
|
50080
|
-
if (!
|
|
49710
|
+
const claudeMdPath = path15.join(bundleDir, "CLAUDE.md");
|
|
49711
|
+
if (!fs12.existsSync(claudeMdPath)) {
|
|
50081
49712
|
args.logger.warn("persona.seed.skip", {
|
|
50082
49713
|
personaId: entry.personaId,
|
|
50083
49714
|
reason: "no-CLAUDE.md",
|
|
@@ -50085,7 +49716,7 @@ function seedDefaultPersonas(args) {
|
|
|
50085
49716
|
});
|
|
50086
49717
|
continue;
|
|
50087
49718
|
}
|
|
50088
|
-
const personality =
|
|
49719
|
+
const personality = fs12.readFileSync(claudeMdPath, "utf8");
|
|
50089
49720
|
const now = Date.now();
|
|
50090
49721
|
const persona = {
|
|
50091
49722
|
personaId: entry.personaId,
|
|
@@ -50112,51 +49743,51 @@ function seedDefaultPersonas(args) {
|
|
|
50112
49743
|
}
|
|
50113
49744
|
}
|
|
50114
49745
|
function skipNodeModulesUnder(srcRoot) {
|
|
50115
|
-
return (src) => !
|
|
49746
|
+
return (src) => !path15.relative(srcRoot, src).split(path15.sep).includes("node_modules");
|
|
50116
49747
|
}
|
|
50117
49748
|
function copyBundleExtras(srcDir, dstDir) {
|
|
50118
|
-
for (const entry of
|
|
49749
|
+
for (const entry of fs12.readdirSync(srcDir, { withFileTypes: true })) {
|
|
50119
49750
|
if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
|
|
50120
|
-
const srcPath =
|
|
50121
|
-
const dstPath =
|
|
49751
|
+
const srcPath = path15.join(srcDir, entry.name);
|
|
49752
|
+
const dstPath = path15.join(dstDir, entry.name);
|
|
50122
49753
|
if (entry.isDirectory()) {
|
|
50123
|
-
|
|
49754
|
+
fs12.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
|
|
50124
49755
|
} else if (entry.isFile()) {
|
|
50125
|
-
|
|
49756
|
+
fs12.copyFileSync(srcPath, dstPath);
|
|
50126
49757
|
}
|
|
50127
49758
|
}
|
|
50128
49759
|
}
|
|
50129
49760
|
var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills", ".claude/agents"];
|
|
50130
49761
|
function replaceManagedPath(src, dst) {
|
|
50131
|
-
if (!
|
|
50132
|
-
|
|
50133
|
-
|
|
50134
|
-
|
|
49762
|
+
if (!fs12.statSync(src).isDirectory()) {
|
|
49763
|
+
fs12.mkdirSync(path15.dirname(dst), { recursive: true });
|
|
49764
|
+
fs12.rmSync(dst, { recursive: true, force: true });
|
|
49765
|
+
fs12.cpSync(src, dst, { dereference: true });
|
|
50135
49766
|
return;
|
|
50136
49767
|
}
|
|
50137
|
-
|
|
50138
|
-
for (const e of
|
|
49768
|
+
fs12.mkdirSync(dst, { recursive: true });
|
|
49769
|
+
for (const e of fs12.readdirSync(src, { withFileTypes: true })) {
|
|
50139
49770
|
if (e.name === "node_modules") continue;
|
|
50140
|
-
const child =
|
|
50141
|
-
|
|
50142
|
-
|
|
49771
|
+
const child = path15.join(dst, e.name);
|
|
49772
|
+
fs12.rmSync(child, { recursive: true, force: true });
|
|
49773
|
+
fs12.cpSync(path15.join(src, e.name), child, { recursive: true, dereference: true });
|
|
50143
49774
|
}
|
|
50144
49775
|
}
|
|
50145
49776
|
function refreshDaemonManagedDirs(args) {
|
|
50146
49777
|
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
50147
49778
|
for (const entry of entries) {
|
|
50148
|
-
const bundleDir =
|
|
50149
|
-
if (!
|
|
49779
|
+
const bundleDir = path15.join(args.defaultsRoot, entry.personaId);
|
|
49780
|
+
if (!fs12.existsSync(bundleDir)) continue;
|
|
50150
49781
|
const personaDir = args.store.personaDirPath(entry.personaId);
|
|
50151
|
-
if (!
|
|
49782
|
+
if (!fs12.existsSync(personaDir)) continue;
|
|
50152
49783
|
for (const relPath of DAEMON_MANAGED_PATHS) {
|
|
50153
|
-
const srcPath =
|
|
50154
|
-
if (!
|
|
50155
|
-
const dstPath =
|
|
49784
|
+
const srcPath = path15.join(bundleDir, relPath);
|
|
49785
|
+
if (!fs12.existsSync(srcPath)) continue;
|
|
49786
|
+
const dstPath = path15.join(personaDir, relPath);
|
|
50156
49787
|
try {
|
|
50157
49788
|
replaceManagedPath(srcPath, dstPath);
|
|
50158
49789
|
if (relPath === "CLAUDE.md") {
|
|
50159
|
-
replaceManagedPath(srcPath,
|
|
49790
|
+
replaceManagedPath(srcPath, path15.join(personaDir, "AGENTS.md"));
|
|
50160
49791
|
}
|
|
50161
49792
|
args.logger.info("persona.refresh.synced", {
|
|
50162
49793
|
personaId: entry.personaId,
|
|
@@ -50180,12 +49811,12 @@ function migratePersonalityOverlay(args) {
|
|
|
50180
49811
|
for (const entry of entries) {
|
|
50181
49812
|
const personaId2 = entry.personaId;
|
|
50182
49813
|
try {
|
|
50183
|
-
if (
|
|
50184
|
-
const bundleClaudeMd =
|
|
50185
|
-
if (!
|
|
49814
|
+
if (fs12.existsSync(args.store.personalityLocalPath(personaId2))) continue;
|
|
49815
|
+
const bundleClaudeMd = path15.join(args.defaultsRoot, personaId2, "CLAUDE.md");
|
|
49816
|
+
if (!fs12.existsSync(bundleClaudeMd)) continue;
|
|
50186
49817
|
const current = args.store.readPersonality(personaId2);
|
|
50187
49818
|
if (current === null) continue;
|
|
50188
|
-
const bundle =
|
|
49819
|
+
const bundle = fs12.readFileSync(bundleClaudeMd, "utf8");
|
|
50189
49820
|
if (current === bundle) continue;
|
|
50190
49821
|
if (!current.startsWith(bundle)) continue;
|
|
50191
49822
|
const tail = current.slice(bundle.length).trim();
|
|
@@ -50226,8 +49857,6 @@ function migrateAgentsMirror(args) {
|
|
|
50226
49857
|
}
|
|
50227
49858
|
if (mirrored > 0) args.logger.info("persona.agents-mirror.done", { mirrored });
|
|
50228
49859
|
}
|
|
50229
|
-
var PKG_CACHE_ROOTS = ["~/Library/pnpm", "~/.local/share/pnpm", "~/.local/state/pnpm", "~/.npm", "~/.pnpm-store"];
|
|
50230
|
-
var CODEX_SANDBOX_DEFAULT = { writableRoots: [...PKG_CACHE_ROOTS], denyRead: [], network: true };
|
|
50231
49860
|
function migrateCodexSandbox(args) {
|
|
50232
49861
|
const entries = args.entries ?? DEFAULT_PERSONAS;
|
|
50233
49862
|
let n = 0;
|
|
@@ -50286,7 +49915,7 @@ function migrateSandboxAllowRead(args) {
|
|
|
50286
49915
|
for (const personaId2 of args.store.list()) {
|
|
50287
49916
|
try {
|
|
50288
49917
|
const readPath = tildePath(args.store.personaDirPath(personaId2));
|
|
50289
|
-
if (!
|
|
49918
|
+
if (!fs12.existsSync(args.store.sandboxSettingsPath(personaId2))) {
|
|
50290
49919
|
args.store.writeSandboxSettings(personaId2, buildGuestSettingsV1());
|
|
50291
49920
|
n++;
|
|
50292
49921
|
continue;
|
|
@@ -50329,13 +49958,13 @@ var PERSONA_BUILDER_TOMBSTONE = `${PERSONA_BUILDER_TOMBSTONE_MARKER}
|
|
|
50329
49958
|
function containsAnyFile(dir) {
|
|
50330
49959
|
let entries;
|
|
50331
49960
|
try {
|
|
50332
|
-
entries =
|
|
49961
|
+
entries = fs12.readdirSync(dir, { withFileTypes: true });
|
|
50333
49962
|
} catch {
|
|
50334
49963
|
return false;
|
|
50335
49964
|
}
|
|
50336
49965
|
for (const e of entries) {
|
|
50337
49966
|
if (e.isDirectory()) {
|
|
50338
|
-
if (containsAnyFile(
|
|
49967
|
+
if (containsAnyFile(path15.join(dir, e.name))) return true;
|
|
50339
49968
|
} else {
|
|
50340
49969
|
return true;
|
|
50341
49970
|
}
|
|
@@ -50344,9 +49973,9 @@ function containsAnyFile(dir) {
|
|
|
50344
49973
|
}
|
|
50345
49974
|
function retirePersonaBuilder(args) {
|
|
50346
49975
|
const dir = args.store.personaDirPath(PERSONA_BUILDER_ID);
|
|
50347
|
-
if (!
|
|
49976
|
+
if (!fs12.existsSync(dir)) return;
|
|
50348
49977
|
try {
|
|
50349
|
-
const used = containsAnyFile(
|
|
49978
|
+
const used = containsAnyFile(path15.join(dir, ".clawd", "sessions")) || containsAnyFile(path15.join(dir, ".claude", "skills")) || containsAnyFile(path15.join(dir, "projects"));
|
|
50350
49979
|
if (!used) {
|
|
50351
49980
|
args.store.remove(PERSONA_BUILDER_ID);
|
|
50352
49981
|
args.logger.info("persona.retire-builder.removed", { personaId: PERSONA_BUILDER_ID });
|
|
@@ -50354,10 +49983,10 @@ function retirePersonaBuilder(args) {
|
|
|
50354
49983
|
}
|
|
50355
49984
|
let wrote = false;
|
|
50356
49985
|
for (const name of ["CLAUDE.md", "AGENTS.md"]) {
|
|
50357
|
-
const p2 =
|
|
50358
|
-
const cur =
|
|
49986
|
+
const p2 = path15.join(dir, name);
|
|
49987
|
+
const cur = fs12.existsSync(p2) ? fs12.readFileSync(p2, "utf8") : null;
|
|
50359
49988
|
if (cur?.startsWith(PERSONA_BUILDER_TOMBSTONE_MARKER)) continue;
|
|
50360
|
-
|
|
49989
|
+
fs12.writeFileSync(p2, PERSONA_BUILDER_TOMBSTONE);
|
|
50361
49990
|
wrote = true;
|
|
50362
49991
|
}
|
|
50363
49992
|
if (wrote) args.logger.info("persona.retire-builder.tombstoned", { personaId: PERSONA_BUILDER_ID });
|
|
@@ -50371,15 +50000,15 @@ function retirePersonaBuilder(args) {
|
|
|
50371
50000
|
function findDeployKitRoot(logger) {
|
|
50372
50001
|
const candidates = [];
|
|
50373
50002
|
try {
|
|
50374
|
-
const here =
|
|
50375
|
-
candidates.push(
|
|
50003
|
+
const here = path15.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
50004
|
+
candidates.push(path15.resolve(here, "..", "deploy-kit"));
|
|
50376
50005
|
} catch {
|
|
50377
50006
|
}
|
|
50378
50007
|
const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
|
|
50379
50008
|
if (fromArgv) candidates.push(fromArgv);
|
|
50380
50009
|
for (const c of candidates) {
|
|
50381
50010
|
try {
|
|
50382
|
-
if (
|
|
50011
|
+
if (fs12.statSync(c).isDirectory()) {
|
|
50383
50012
|
logger?.info("persona.deploy-kit-root.resolved", { root: c });
|
|
50384
50013
|
return c;
|
|
50385
50014
|
}
|
|
@@ -50390,8 +50019,8 @@ function findDeployKitRoot(logger) {
|
|
|
50390
50019
|
return null;
|
|
50391
50020
|
}
|
|
50392
50021
|
function seedDeployKit(args) {
|
|
50393
|
-
const dst =
|
|
50394
|
-
|
|
50022
|
+
const dst = path15.join(args.dataDir, "deploy-kit");
|
|
50023
|
+
fs12.cpSync(args.deployKitBundleRoot, dst, {
|
|
50395
50024
|
recursive: true,
|
|
50396
50025
|
dereference: true,
|
|
50397
50026
|
force: false,
|
|
@@ -50400,28 +50029,434 @@ function seedDeployKit(args) {
|
|
|
50400
50029
|
args.logger.info("deploy-kit.seed.done", { dst });
|
|
50401
50030
|
}
|
|
50402
50031
|
function refreshDeployKit(args) {
|
|
50403
|
-
const dst =
|
|
50404
|
-
if (!
|
|
50032
|
+
const dst = path15.join(args.dataDir, "deploy-kit");
|
|
50033
|
+
if (!fs12.existsSync(dst)) {
|
|
50405
50034
|
seedDeployKit(args);
|
|
50406
50035
|
return;
|
|
50407
50036
|
}
|
|
50408
50037
|
for (const sub of ["scripts", "contract"]) {
|
|
50409
|
-
const s =
|
|
50410
|
-
if (
|
|
50411
|
-
|
|
50038
|
+
const s = path15.join(args.deployKitBundleRoot, sub);
|
|
50039
|
+
if (fs12.existsSync(s)) {
|
|
50040
|
+
fs12.cpSync(s, path15.join(dst, sub), { recursive: true, force: true, dereference: true });
|
|
50412
50041
|
}
|
|
50413
50042
|
}
|
|
50414
|
-
const secretsSrc =
|
|
50415
|
-
if (
|
|
50416
|
-
|
|
50417
|
-
for (const f of
|
|
50043
|
+
const secretsSrc = path15.join(args.deployKitBundleRoot, ".secrets");
|
|
50044
|
+
if (fs12.existsSync(secretsSrc)) {
|
|
50045
|
+
fs12.mkdirSync(path15.join(dst, ".secrets"), { recursive: true });
|
|
50046
|
+
for (const f of fs12.readdirSync(secretsSrc)) {
|
|
50418
50047
|
if (f.endsWith(".local")) continue;
|
|
50419
|
-
|
|
50048
|
+
fs12.copyFileSync(path15.join(secretsSrc, f), path15.join(dst, ".secrets", f));
|
|
50420
50049
|
}
|
|
50421
50050
|
}
|
|
50422
50051
|
args.logger.info("deploy-kit.refresh.done", { dst });
|
|
50423
50052
|
}
|
|
50424
50053
|
|
|
50054
|
+
// src/skills/scanner.ts
|
|
50055
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
50056
|
+
var import_node_os6 = __toESM(require("os"), 1);
|
|
50057
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
50058
|
+
|
|
50059
|
+
// src/skills/frontmatter.ts
|
|
50060
|
+
var STRIP_QUOTES = /^["']|["']$/g;
|
|
50061
|
+
function strip(s) {
|
|
50062
|
+
return s.trim().replace(STRIP_QUOTES, "");
|
|
50063
|
+
}
|
|
50064
|
+
function parseFrontmatter(content, keys) {
|
|
50065
|
+
const out = {};
|
|
50066
|
+
if (!content.startsWith("---")) return out;
|
|
50067
|
+
const end = content.indexOf("---", 3);
|
|
50068
|
+
if (end === -1) return out;
|
|
50069
|
+
const lines = content.slice(3, end).split("\n");
|
|
50070
|
+
for (let i = 0; i < lines.length; i++) {
|
|
50071
|
+
const trimmed = lines[i].trim();
|
|
50072
|
+
for (const key of keys) {
|
|
50073
|
+
const prefix = `${key}:`;
|
|
50074
|
+
if (!trimmed.startsWith(prefix)) continue;
|
|
50075
|
+
const rest = trimmed.slice(prefix.length).trim();
|
|
50076
|
+
if (rest === "|" || rest === ">" || rest === "|-" || rest === ">-") {
|
|
50077
|
+
const parts = [];
|
|
50078
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
50079
|
+
const next = lines[j];
|
|
50080
|
+
if (next.length === 0) {
|
|
50081
|
+
parts.push("");
|
|
50082
|
+
continue;
|
|
50083
|
+
}
|
|
50084
|
+
if (!/^\s/.test(next)) break;
|
|
50085
|
+
parts.push(next.replace(/^\s+/, ""));
|
|
50086
|
+
}
|
|
50087
|
+
const value = parts.filter(Boolean).join(" ").trim();
|
|
50088
|
+
if (value) out[key] = value;
|
|
50089
|
+
} else {
|
|
50090
|
+
const value = strip(rest);
|
|
50091
|
+
if (value) out[key] = value;
|
|
50092
|
+
}
|
|
50093
|
+
break;
|
|
50094
|
+
}
|
|
50095
|
+
}
|
|
50096
|
+
return out;
|
|
50097
|
+
}
|
|
50098
|
+
|
|
50099
|
+
// src/skills/builtin-cc-resources.ts
|
|
50100
|
+
var BUILTIN_SKILLS = [
|
|
50101
|
+
{ name: "update-config", source: "builtin", description: "Update Claude Code configuration." },
|
|
50102
|
+
{ name: "keybindings-help", source: "builtin", description: "Show available keybindings." },
|
|
50103
|
+
{ name: "verify", source: "builtin", description: "Verify the implementation." },
|
|
50104
|
+
{ name: "debug", source: "builtin", description: "Debug current issue." },
|
|
50105
|
+
{ name: "lorem-ipsum", source: "builtin", description: "Generate lorem ipsum placeholder text." },
|
|
50106
|
+
{ name: "skillify", source: "builtin", description: "Convert a process into a reusable skill." },
|
|
50107
|
+
{ name: "remember", source: "builtin", description: "Remember context for later use." },
|
|
50108
|
+
{ name: "simplify", source: "builtin", description: "Simplify the code or message." },
|
|
50109
|
+
{ name: "batch", source: "builtin", description: "Run a batch of similar operations." },
|
|
50110
|
+
{ name: "stuck", source: "builtin", description: "Help unstick a stalled task." },
|
|
50111
|
+
{ name: "loop", source: "builtin", description: "Loop a task until a condition is met." },
|
|
50112
|
+
{ name: "cron-list", source: "builtin", description: "List scheduled cron tasks." },
|
|
50113
|
+
{ name: "cron-delete", source: "builtin", description: "Delete a scheduled cron task." },
|
|
50114
|
+
{ name: "dream", source: "builtin", description: "Brainstorm freely without constraints." },
|
|
50115
|
+
{ name: "hunter", source: "builtin", description: "Hunt down a bug or root cause." },
|
|
50116
|
+
{ name: "schedule", source: "builtin", description: "Schedule a task to run later." },
|
|
50117
|
+
{ name: "claude-api", source: "builtin", description: "Use the Claude API directly." },
|
|
50118
|
+
{ name: "claude-in-chrome", source: "builtin", description: "Drive Claude inside Chrome via the Chrome extension." }
|
|
50119
|
+
];
|
|
50120
|
+
var BUILTIN_AGENTS = [
|
|
50121
|
+
{
|
|
50122
|
+
name: "general-purpose",
|
|
50123
|
+
source: "builtin",
|
|
50124
|
+
description: "General-purpose agent for researching complex questions and executing multi-step tasks.",
|
|
50125
|
+
whenToUse: "When you are searching for a keyword or file and are not confident you will find the right match in the first few tries."
|
|
50126
|
+
},
|
|
50127
|
+
{
|
|
50128
|
+
name: "statusline-setup",
|
|
50129
|
+
source: "builtin",
|
|
50130
|
+
description: "Configure the user's Claude Code status line setting.",
|
|
50131
|
+
whenToUse: "When the user is setting up or changing their status line configuration."
|
|
50132
|
+
},
|
|
50133
|
+
{
|
|
50134
|
+
name: "Explore",
|
|
50135
|
+
source: "builtin",
|
|
50136
|
+
description: "Explore the codebase to gather context.",
|
|
50137
|
+
whenToUse: "Before making changes that require understanding the surrounding code."
|
|
50138
|
+
},
|
|
50139
|
+
{
|
|
50140
|
+
name: "Plan",
|
|
50141
|
+
source: "builtin",
|
|
50142
|
+
description: "Produce an implementation plan before writing code.",
|
|
50143
|
+
whenToUse: "When the task is non-trivial and would benefit from an explicit plan."
|
|
50144
|
+
},
|
|
50145
|
+
{
|
|
50146
|
+
name: "claude-code-guide",
|
|
50147
|
+
source: "builtin",
|
|
50148
|
+
description: "Guide the user through Claude Code features.",
|
|
50149
|
+
whenToUse: "When the user needs help understanding what Claude Code can do."
|
|
50150
|
+
},
|
|
50151
|
+
{
|
|
50152
|
+
name: "verification",
|
|
50153
|
+
source: "builtin",
|
|
50154
|
+
description: "Verify that a change works as intended.",
|
|
50155
|
+
whenToUse: "After implementing a change, before declaring it done."
|
|
50156
|
+
}
|
|
50157
|
+
];
|
|
50158
|
+
|
|
50159
|
+
// src/skills/scanner.ts
|
|
50160
|
+
function parseDescription(content) {
|
|
50161
|
+
const fields = parseFrontmatter(content, ["description"]);
|
|
50162
|
+
return { description: fields.description ?? "" };
|
|
50163
|
+
}
|
|
50164
|
+
function isDirLikeSync(p2) {
|
|
50165
|
+
try {
|
|
50166
|
+
return import_node_fs9.default.statSync(p2).isDirectory();
|
|
50167
|
+
} catch {
|
|
50168
|
+
return false;
|
|
50169
|
+
}
|
|
50170
|
+
}
|
|
50171
|
+
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
50172
|
+
let entries;
|
|
50173
|
+
try {
|
|
50174
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
50175
|
+
} catch {
|
|
50176
|
+
return;
|
|
50177
|
+
}
|
|
50178
|
+
for (const ent of entries) {
|
|
50179
|
+
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
50180
|
+
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
50181
|
+
let content;
|
|
50182
|
+
try {
|
|
50183
|
+
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
|
|
50184
|
+
} catch {
|
|
50185
|
+
try {
|
|
50186
|
+
content = import_node_fs9.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
|
|
50187
|
+
} catch {
|
|
50188
|
+
continue;
|
|
50189
|
+
}
|
|
50190
|
+
}
|
|
50191
|
+
const { description } = parseDescription(content);
|
|
50192
|
+
const baseName = ent.name;
|
|
50193
|
+
const name = pluginName ? `${pluginName}:${baseName}` : baseName;
|
|
50194
|
+
if (seen.has(name)) continue;
|
|
50195
|
+
seen.add(name);
|
|
50196
|
+
const info = { name, source, path: entryPath, description: description || void 0 };
|
|
50197
|
+
if (pluginName) info.plugin = pluginName;
|
|
50198
|
+
out.push(info);
|
|
50199
|
+
}
|
|
50200
|
+
}
|
|
50201
|
+
function listSkillsForDir(dir, source) {
|
|
50202
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50203
|
+
const out = [];
|
|
50204
|
+
scanSkillDir(dir, source, seen, out);
|
|
50205
|
+
return out;
|
|
50206
|
+
}
|
|
50207
|
+
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
50208
|
+
let entries;
|
|
50209
|
+
try {
|
|
50210
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
50211
|
+
} catch {
|
|
50212
|
+
return;
|
|
50213
|
+
}
|
|
50214
|
+
for (const ent of entries) {
|
|
50215
|
+
const entryPath = import_node_path9.default.join(dir, ent.name);
|
|
50216
|
+
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
50217
|
+
const ns = ent.name;
|
|
50218
|
+
let subEntries;
|
|
50219
|
+
try {
|
|
50220
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
50221
|
+
} catch {
|
|
50222
|
+
continue;
|
|
50223
|
+
}
|
|
50224
|
+
for (const se of subEntries) {
|
|
50225
|
+
if (!se.name.endsWith(".md")) continue;
|
|
50226
|
+
const sePath = import_node_path9.default.join(entryPath, se.name);
|
|
50227
|
+
let content;
|
|
50228
|
+
try {
|
|
50229
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
50230
|
+
} catch {
|
|
50231
|
+
continue;
|
|
50232
|
+
}
|
|
50233
|
+
const cmd = se.name.replace(/\.md$/, "");
|
|
50234
|
+
const { description } = parseDescription(content);
|
|
50235
|
+
const qualified = `${ns}:${cmd}`;
|
|
50236
|
+
const name = pluginName ? `${pluginName}:${qualified}` : qualified;
|
|
50237
|
+
if (seen.has(name)) continue;
|
|
50238
|
+
seen.add(name);
|
|
50239
|
+
const info = { name, source, path: sePath, description: description || void 0 };
|
|
50240
|
+
if (pluginName) info.plugin = pluginName;
|
|
50241
|
+
out.push(info);
|
|
50242
|
+
}
|
|
50243
|
+
} else if (ent.name.endsWith(".md")) {
|
|
50244
|
+
let content;
|
|
50245
|
+
try {
|
|
50246
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
50247
|
+
} catch {
|
|
50248
|
+
continue;
|
|
50249
|
+
}
|
|
50250
|
+
const cmd = ent.name.replace(/\.md$/, "");
|
|
50251
|
+
const { description } = parseDescription(content);
|
|
50252
|
+
const name = pluginName ? `${pluginName}:${cmd}` : cmd;
|
|
50253
|
+
if (seen.has(name)) continue;
|
|
50254
|
+
seen.add(name);
|
|
50255
|
+
const info = { name, source, path: entryPath, description: description || void 0 };
|
|
50256
|
+
if (pluginName) info.plugin = pluginName;
|
|
50257
|
+
out.push(info);
|
|
50258
|
+
}
|
|
50259
|
+
}
|
|
50260
|
+
}
|
|
50261
|
+
function readInstalledPlugins(home) {
|
|
50262
|
+
const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
50263
|
+
let raw;
|
|
50264
|
+
try {
|
|
50265
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
50266
|
+
} catch {
|
|
50267
|
+
return [];
|
|
50268
|
+
}
|
|
50269
|
+
let parsed;
|
|
50270
|
+
try {
|
|
50271
|
+
parsed = JSON.parse(raw);
|
|
50272
|
+
} catch {
|
|
50273
|
+
return [];
|
|
50274
|
+
}
|
|
50275
|
+
const out = [];
|
|
50276
|
+
for (const [key, entries] of Object.entries(parsed.plugins ?? {})) {
|
|
50277
|
+
if (!Array.isArray(entries) || entries.length === 0) continue;
|
|
50278
|
+
const entry = entries[0];
|
|
50279
|
+
if (!entry?.installPath) continue;
|
|
50280
|
+
const pluginName = key.includes("@") ? key.slice(0, key.indexOf("@")) : key;
|
|
50281
|
+
if (!pluginName) continue;
|
|
50282
|
+
out.push({ name: pluginName, root: entry.installPath });
|
|
50283
|
+
}
|
|
50284
|
+
return out;
|
|
50285
|
+
}
|
|
50286
|
+
var SkillsScanner = class {
|
|
50287
|
+
home;
|
|
50288
|
+
extraPluginRoots;
|
|
50289
|
+
constructor(opts = {}) {
|
|
50290
|
+
this.home = opts.home ?? import_node_os6.default.homedir();
|
|
50291
|
+
this.extraPluginRoots = opts.extraPluginRoots ?? [];
|
|
50292
|
+
}
|
|
50293
|
+
/**
|
|
50294
|
+
* 对齐 cc-direct(openclaw-plugin-clawos/src/claude-code/skills-scanner.ts):
|
|
50295
|
+
* 1. global: ~/.claude/skills + ~/.claude/commands
|
|
50296
|
+
* 2. project: <cwd>/.claude/skills + <cwd>/.claude/commands
|
|
50297
|
+
* 3. plugin: installed_plugins.json 里每个 plugin 的 skills + commands
|
|
50298
|
+
* 顺序 global → project → plugin,同名去重(先到先得)
|
|
50299
|
+
*/
|
|
50300
|
+
list(args) {
|
|
50301
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50302
|
+
const builtinBlock = [];
|
|
50303
|
+
for (const b2 of BUILTIN_SKILLS) {
|
|
50304
|
+
if (seen.has(b2.name)) continue;
|
|
50305
|
+
seen.add(b2.name);
|
|
50306
|
+
builtinBlock.push({
|
|
50307
|
+
name: b2.name,
|
|
50308
|
+
source: "builtin",
|
|
50309
|
+
description: b2.description
|
|
50310
|
+
});
|
|
50311
|
+
}
|
|
50312
|
+
const fsBlock = [];
|
|
50313
|
+
scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
|
|
50314
|
+
scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
|
|
50315
|
+
scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
|
|
50316
|
+
scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
|
|
50317
|
+
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
50318
|
+
for (const { name, root } of plugins) {
|
|
50319
|
+
scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
|
|
50320
|
+
scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
|
|
50321
|
+
}
|
|
50322
|
+
fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
|
|
50323
|
+
return [...builtinBlock, ...fsBlock];
|
|
50324
|
+
}
|
|
50325
|
+
};
|
|
50326
|
+
|
|
50327
|
+
// src/persona/manager.ts
|
|
50328
|
+
var PersonaManager = class {
|
|
50329
|
+
constructor(deps) {
|
|
50330
|
+
this.deps = deps;
|
|
50331
|
+
}
|
|
50332
|
+
deps;
|
|
50333
|
+
/**
|
|
50334
|
+
* slug 是 persona 的身份,label 只是显示名——两者刻意分开:id 落进文件路径 /
|
|
50335
|
+
* 分享链接且创建后不可改,label 可中文、可随时改。此前 id 从 label 推导,
|
|
50336
|
+
* 非 ascii 被剥空后一律 fallback 成 `persona-persona`。
|
|
50337
|
+
*
|
|
50338
|
+
* 撞名直接抛错而非改名:id 由调用方显式指定,静默换成带后缀的 id 等于把
|
|
50339
|
+
* 用户的选择偷偷改掉。字符集校验在 PersonaCreateArgsSchema(路径穿越边界)。
|
|
50340
|
+
*/
|
|
50341
|
+
create(args) {
|
|
50342
|
+
const personaId2 = `persona-${args.slug}`;
|
|
50343
|
+
if (this.deps.store.has(personaId2)) {
|
|
50344
|
+
throw new Error(`personaId already exists: ${personaId2}`);
|
|
50345
|
+
}
|
|
50346
|
+
const now = Date.now();
|
|
50347
|
+
const persona = {
|
|
50348
|
+
personaId: personaId2,
|
|
50349
|
+
label: args.label,
|
|
50350
|
+
model: args.model,
|
|
50351
|
+
// effort 兜底 high:persona 一律持有具体档位(spec 2026-08-12),UI 会带界面上高亮的
|
|
50352
|
+
// 那一档,但 persona:create 也可能来自 butler 的 persona-authoring skill 这类不带该
|
|
50353
|
+
// 字段的调用方——不兜的话要等下次 daemon 启动 backfill 才补上,中间建的 session 就漏了。
|
|
50354
|
+
// 取值理由与 backfillPersonaSessionDefaults 一致(见那里的注释)。
|
|
50355
|
+
effort: args.effort ?? "high",
|
|
50356
|
+
tool: args.tool,
|
|
50357
|
+
public: args.public ?? false,
|
|
50358
|
+
iconKey: args.iconKey,
|
|
50359
|
+
createdAt: now,
|
|
50360
|
+
updatedAt: now
|
|
50361
|
+
};
|
|
50362
|
+
this.deps.store.write(persona, args.personality);
|
|
50363
|
+
this.deps.store.writeCodexSandboxSettings(personaId2, CODEX_SANDBOX_DEFAULT);
|
|
50364
|
+
this.deps.registry.set(persona);
|
|
50365
|
+
return persona;
|
|
50366
|
+
}
|
|
50367
|
+
update(personaId2, patch, texts) {
|
|
50368
|
+
const existing = this.deps.registry.get(personaId2);
|
|
50369
|
+
if (!existing) throw new Error(`persona not found: ${personaId2}`);
|
|
50370
|
+
const { iconKey: iconKeyPatch, ...restPatch } = patch;
|
|
50371
|
+
const updated = {
|
|
50372
|
+
...existing,
|
|
50373
|
+
...restPatch,
|
|
50374
|
+
updatedAt: Date.now()
|
|
50375
|
+
};
|
|
50376
|
+
const toolChanged = patch.tool !== void 0 && (patch.tool ?? "claude") !== (existing.tool ?? "claude");
|
|
50377
|
+
if (toolChanged) {
|
|
50378
|
+
if (patch.model === void 0) delete updated.model;
|
|
50379
|
+
if (patch.effort === void 0) delete updated.effort;
|
|
50380
|
+
}
|
|
50381
|
+
if (iconKeyPatch === null) {
|
|
50382
|
+
delete updated.iconKey;
|
|
50383
|
+
} else if (iconKeyPatch !== void 0) {
|
|
50384
|
+
updated.iconKey = iconKeyPatch;
|
|
50385
|
+
}
|
|
50386
|
+
if (texts?.personality !== void 0) {
|
|
50387
|
+
this.deps.store.writePersonality(personaId2, texts.personality);
|
|
50388
|
+
}
|
|
50389
|
+
if (texts?.personalityLocal !== void 0) {
|
|
50390
|
+
this.deps.store.writePersonalityLocal(personaId2, texts.personalityLocal);
|
|
50391
|
+
}
|
|
50392
|
+
this.deps.store.writeMeta(updated);
|
|
50393
|
+
this.deps.registry.set(updated);
|
|
50394
|
+
return updated;
|
|
50395
|
+
}
|
|
50396
|
+
/** 读取 CLAUDE.md 内容;persona 目录或文件不存在时返回 null。透传给 handler 拼响应。 */
|
|
50397
|
+
readPersonality(personaId2) {
|
|
50398
|
+
return this.deps.store.readPersonality(personaId2);
|
|
50399
|
+
}
|
|
50400
|
+
/** 读人格补充层(`.clawd/personality.local.md`);没写过返回 null。供 persona:get 拼响应。 */
|
|
50401
|
+
readPersonalityLocal(personaId2) {
|
|
50402
|
+
return this.deps.store.readPersonalityLocal(personaId2);
|
|
50403
|
+
}
|
|
50404
|
+
/** 扫 persona 私有 skills 目录;目录不存在返回空数组。供 persona:get handler 拼响应。 */
|
|
50405
|
+
listSkills(personaId2) {
|
|
50406
|
+
return listSkillsForDir(this.deps.store.skillsDir(personaId2), "project");
|
|
50407
|
+
}
|
|
50408
|
+
/**
|
|
50409
|
+
* 读取 persona `.claude/settings.json` 中已启用的插件列表(value === true 的 key)。
|
|
50410
|
+
* 文件不存在 / 解析失败 / 字段缺失 → 空数组。供 persona:get handler 拼响应。
|
|
50411
|
+
*/
|
|
50412
|
+
listEnabledPlugins(personaId2) {
|
|
50413
|
+
return this.deps.store.readEnabledPlugins(personaId2);
|
|
50414
|
+
}
|
|
50415
|
+
/** 读 codex guest 沙箱配置(`.clawd/codex-sandbox.json`);缺失 / 坏 → null。透传给 handler 拼响应。 */
|
|
50416
|
+
readCodexSandboxSettings(personaId2) {
|
|
50417
|
+
return this.deps.store.readCodexSandboxSettings(personaId2);
|
|
50418
|
+
}
|
|
50419
|
+
/**
|
|
50420
|
+
* 局部合并写 codex guest 沙箱配置,返回合并后的全量。
|
|
50421
|
+
*
|
|
50422
|
+
* **必须是合并不是覆盖**:UI 的「访客联网」开关只发 `{network}`,整体覆盖会静默抹掉 owner
|
|
50423
|
+
* 手配的 writableRoots / denyRead(丢的是安全边界,且用户不会立刻发现)。
|
|
50424
|
+
* 不走 PersonaManager.update 是因为它管的是 PersonaFile meta + 人格两层文本,
|
|
50425
|
+
* 而这份配置是另一个文件、另一套 schema。
|
|
50426
|
+
*
|
|
50427
|
+
* **读不到时 base 用 CODEX_SANDBOX_DEFAULT 而不是 `{}`**:`{}` 会让这次「合并」实际写出一份
|
|
50428
|
+
* 只有 patch 字段的残缺配置(例如只有 `{network:true}`,没有包管理器缓存目录 → `npm install`
|
|
50429
|
+
* EPERM),而且从此 migrateCodexSandbox 见文件已存在就跳过,UI 上再也补不回来。
|
|
50430
|
+
* 正常路径下文件在 create 时就已物化,这条兜底只在文件被删 / 被改坏时触发。
|
|
50431
|
+
*
|
|
50432
|
+
* ⚠️ 已知限制:`CodexSandboxSettingsSchema` 是 `.strict()` 的,owner 手编时多写一个键
|
|
50433
|
+
* (注释键 / 历史字段)会让整份文件读成 null,于是这次合并把它替换成默认值 ⊕ patch。
|
|
50434
|
+
* 已有测试锁定该 strict 语义(store.spec「schema 校验失败 → 返回 null」),本次不动它——
|
|
50435
|
+
* 至少残缺配置不会再被写出去。要放宽得单独评估。
|
|
50436
|
+
*/
|
|
50437
|
+
mergeCodexSandbox(personaId2, patch) {
|
|
50438
|
+
if (!this.deps.registry.get(personaId2)) throw new Error(`persona not found: ${personaId2}`);
|
|
50439
|
+
const base = this.deps.store.readCodexSandboxSettings(personaId2) ?? CODEX_SANDBOX_DEFAULT;
|
|
50440
|
+
const merged = { ...base, ...patch };
|
|
50441
|
+
this.deps.store.writeCodexSandboxSettings(personaId2, merged);
|
|
50442
|
+
return merged;
|
|
50443
|
+
}
|
|
50444
|
+
/** 读 sandbox-settings.json;不存在 / 损坏返回 null。供 persona:get handler 拼响应。 */
|
|
50445
|
+
readSandboxSettings(personaId2) {
|
|
50446
|
+
return this.deps.store.readSandboxSettings(personaId2);
|
|
50447
|
+
}
|
|
50448
|
+
/**
|
|
50449
|
+
* 删除 persona。
|
|
50450
|
+
* PersonaStore.remove(personaId) 级联删整个 <personaRoot>/<personaId>/ 目录
|
|
50451
|
+
* (含 .clawd/sessions/owner/ 和 .clawd/sessions/guests/<capId>/),rmSync
|
|
50452
|
+
* recursive force 一锅清。
|
|
50453
|
+
*/
|
|
50454
|
+
delete(personaId2) {
|
|
50455
|
+
this.deps.store.remove(personaId2);
|
|
50456
|
+
this.deps.registry.remove(personaId2);
|
|
50457
|
+
}
|
|
50458
|
+
};
|
|
50459
|
+
|
|
50425
50460
|
// src/share-md-viewer/load.ts
|
|
50426
50461
|
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
50427
50462
|
var import_node_path10 = __toESM(require("path"), 1);
|
|
@@ -51154,8 +51189,8 @@ function turnStartInput(text) {
|
|
|
51154
51189
|
const items = [];
|
|
51155
51190
|
let leftover = text;
|
|
51156
51191
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
51157
|
-
const [marker, name,
|
|
51158
|
-
items.push({ type: "skill", name, path:
|
|
51192
|
+
const [marker, name, path91] = m2;
|
|
51193
|
+
items.push({ type: "skill", name, path: path91 });
|
|
51159
51194
|
leftover = leftover.replace(marker, "");
|
|
51160
51195
|
}
|
|
51161
51196
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -55842,13 +55877,13 @@ function mapSkillsListResponse(res) {
|
|
|
55842
55877
|
const r = s ?? {};
|
|
55843
55878
|
const name = str3(r.name);
|
|
55844
55879
|
if (!name) continue;
|
|
55845
|
-
const
|
|
55880
|
+
const path91 = str3(r.path);
|
|
55846
55881
|
const description = str3(r.description);
|
|
55847
55882
|
const isPlugin = name.includes(":");
|
|
55848
55883
|
out.push({
|
|
55849
55884
|
name,
|
|
55850
55885
|
source: isPlugin ? "plugin" : "project",
|
|
55851
|
-
...
|
|
55886
|
+
...path91 ? { path: path91 } : {},
|
|
55852
55887
|
...description ? { description } : {},
|
|
55853
55888
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
55854
55889
|
});
|
|
@@ -60170,9 +60205,9 @@ var CentralClientError = class extends Error {
|
|
|
60170
60205
|
code;
|
|
60171
60206
|
cause;
|
|
60172
60207
|
};
|
|
60173
|
-
async function centralRequest(opts,
|
|
60208
|
+
async function centralRequest(opts, path91, init) {
|
|
60174
60209
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
60175
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
60210
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path91}`;
|
|
60176
60211
|
const ctrl = new AbortController();
|
|
60177
60212
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
60178
60213
|
let res;
|
|
@@ -60653,7 +60688,7 @@ var ServerKeyStore = class {
|
|
|
60653
60688
|
init_protocol();
|
|
60654
60689
|
|
|
60655
60690
|
// src/handlers/index.ts
|
|
60656
|
-
var
|
|
60691
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
60657
60692
|
|
|
60658
60693
|
// src/handlers/session.ts
|
|
60659
60694
|
init_protocol();
|
|
@@ -60996,8 +61031,133 @@ function appendImportLedger(dataDir, entry) {
|
|
|
60996
61031
|
import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
60997
61032
|
}
|
|
60998
61033
|
|
|
61034
|
+
// src/tools/transcript-search.ts
|
|
61035
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
61036
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
61037
|
+
var SNIPPET_PAD = 60;
|
|
61038
|
+
var INJECTED_ENVELOPE_RE = /^<(system-reminder|command-name|command-message|command-args|local-command-stdout|local-command-stderr|task-notification|user-prompt-submit-hook|environment_context|user_instructions)\b/;
|
|
61039
|
+
var CODEX_WRAPPER_RE = /<(related-dir|environment_context|user_instructions)>[\s\S]*?<\/\1>/g;
|
|
61040
|
+
function asRecord(v2) {
|
|
61041
|
+
return typeof v2 === "object" && v2 !== null ? v2 : null;
|
|
61042
|
+
}
|
|
61043
|
+
function textOfBlocks(content, types) {
|
|
61044
|
+
if (!Array.isArray(content)) return null;
|
|
61045
|
+
const parts = [];
|
|
61046
|
+
for (const block of content) {
|
|
61047
|
+
const b2 = asRecord(block);
|
|
61048
|
+
if (!b2 || typeof b2.type !== "string" || !types.includes(b2.type)) continue;
|
|
61049
|
+
const text = b2.text;
|
|
61050
|
+
if (typeof text === "string" && text !== "") parts.push(text);
|
|
61051
|
+
}
|
|
61052
|
+
return parts.length > 0 ? parts.join("\n") : null;
|
|
61053
|
+
}
|
|
61054
|
+
function lineToSearchableText(raw) {
|
|
61055
|
+
const line = asRecord(raw);
|
|
61056
|
+
if (!line) return null;
|
|
61057
|
+
if (line.type === "response_item") {
|
|
61058
|
+
const payload = asRecord(line.payload);
|
|
61059
|
+
if (!payload || payload.type !== "message") return null;
|
|
61060
|
+
const role = payload.role;
|
|
61061
|
+
if (role !== "user" && role !== "assistant") return null;
|
|
61062
|
+
const text2 = textOfBlocks(payload.content, ["input_text", "output_text"]);
|
|
61063
|
+
if (text2 === null) return null;
|
|
61064
|
+
if (role !== "user") return text2;
|
|
61065
|
+
const stripped = text2.replace(CODEX_WRAPPER_RE, "").trim();
|
|
61066
|
+
if (stripped === "") return null;
|
|
61067
|
+
return INJECTED_ENVELOPE_RE.test(stripped) ? null : stripped;
|
|
61068
|
+
}
|
|
61069
|
+
if (line.type !== "user" && line.type !== "assistant") return null;
|
|
61070
|
+
const message = asRecord(line.message);
|
|
61071
|
+
if (!message) return null;
|
|
61072
|
+
const content = message.content;
|
|
61073
|
+
const text = typeof content === "string" && content !== "" ? content : textOfBlocks(content, ["text"]);
|
|
61074
|
+
if (text === null) return null;
|
|
61075
|
+
if (line.type === "user" && (line.isMeta === true || line.isSynthetic === true)) return null;
|
|
61076
|
+
if (line.type === "user" && INJECTED_ENVELOPE_RE.test(text.trimStart())) return null;
|
|
61077
|
+
return text;
|
|
61078
|
+
}
|
|
61079
|
+
function escapeRegExp(s) {
|
|
61080
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
61081
|
+
}
|
|
61082
|
+
function makeSnippet(text, at, needleLength) {
|
|
61083
|
+
const from = Math.max(0, at - SNIPPET_PAD);
|
|
61084
|
+
const to = Math.min(text.length, at + needleLength + SNIPPET_PAD);
|
|
61085
|
+
const body = text.slice(from, to).replace(/\s+/g, " ").trim();
|
|
61086
|
+
return `${from > 0 ? "\u2026 " : ""}${body}${to < text.length ? " \u2026" : ""}`;
|
|
61087
|
+
}
|
|
61088
|
+
function searchTranscriptFile(file, query) {
|
|
61089
|
+
let buf;
|
|
61090
|
+
try {
|
|
61091
|
+
buf = import_node_fs48.default.readFileSync(file);
|
|
61092
|
+
} catch {
|
|
61093
|
+
return null;
|
|
61094
|
+
}
|
|
61095
|
+
const haystack = buf.toString("latin1");
|
|
61096
|
+
const needle = Buffer.from(query, "utf8").toString("latin1");
|
|
61097
|
+
const re = new RegExp(escapeRegExp(needle), "gi");
|
|
61098
|
+
let m2;
|
|
61099
|
+
while ((m2 = re.exec(haystack)) !== null) {
|
|
61100
|
+
const lineStart = haystack.lastIndexOf("\n", m2.index) + 1;
|
|
61101
|
+
let lineEnd = haystack.indexOf("\n", m2.index);
|
|
61102
|
+
if (lineEnd < 0) lineEnd = haystack.length;
|
|
61103
|
+
re.lastIndex = lineEnd + 1;
|
|
61104
|
+
let parsed;
|
|
61105
|
+
try {
|
|
61106
|
+
parsed = JSON.parse(Buffer.from(haystack.slice(lineStart, lineEnd), "latin1").toString("utf8"));
|
|
61107
|
+
} catch {
|
|
61108
|
+
continue;
|
|
61109
|
+
}
|
|
61110
|
+
const text = lineToSearchableText(parsed);
|
|
61111
|
+
if (text === null) continue;
|
|
61112
|
+
const at = text.toLowerCase().indexOf(query.toLowerCase());
|
|
61113
|
+
if (at < 0) continue;
|
|
61114
|
+
return makeSnippet(text, at, query.length);
|
|
61115
|
+
}
|
|
61116
|
+
return null;
|
|
61117
|
+
}
|
|
61118
|
+
var ROLLOUT_NAME_RE = /-([0-9a-fA-F-]{36})\.jsonl$/;
|
|
61119
|
+
function createCodexRolloutLocator(roots) {
|
|
61120
|
+
let index = null;
|
|
61121
|
+
const walk2 = (dir, into) => {
|
|
61122
|
+
let entries;
|
|
61123
|
+
try {
|
|
61124
|
+
entries = import_node_fs48.default.readdirSync(dir, { withFileTypes: true });
|
|
61125
|
+
} catch {
|
|
61126
|
+
return;
|
|
61127
|
+
}
|
|
61128
|
+
for (const entry of entries) {
|
|
61129
|
+
const full = import_node_path54.default.join(dir, entry.name);
|
|
61130
|
+
if (entry.isDirectory()) {
|
|
61131
|
+
walk2(full, into);
|
|
61132
|
+
continue;
|
|
61133
|
+
}
|
|
61134
|
+
const matched = ROLLOUT_NAME_RE.exec(entry.name);
|
|
61135
|
+
if (matched) into.set(matched[1].toLowerCase(), full);
|
|
61136
|
+
}
|
|
61137
|
+
};
|
|
61138
|
+
return (toolSessionId) => {
|
|
61139
|
+
if (index === null) {
|
|
61140
|
+
index = /* @__PURE__ */ new Map();
|
|
61141
|
+
for (const root of roots) walk2(root, index);
|
|
61142
|
+
}
|
|
61143
|
+
return index.get(toolSessionId.toLowerCase()) ?? null;
|
|
61144
|
+
};
|
|
61145
|
+
}
|
|
61146
|
+
|
|
60999
61147
|
// src/handlers/session.ts
|
|
61000
61148
|
init_protocol();
|
|
61149
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
61150
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
61151
|
+
function canReadSearchHit(ctx, file) {
|
|
61152
|
+
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
61153
|
+
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
61154
|
+
}
|
|
61155
|
+
var DEFAULT_SEARCH_LIMIT = 9;
|
|
61156
|
+
function codexRolloutRoots(dataDir) {
|
|
61157
|
+
const roots = [import_node_path55.default.join(import_node_os19.default.homedir(), ".codex", "sessions")];
|
|
61158
|
+
if (dataDir) roots.push(import_node_path55.default.join(dataDir, "codex-home", "sessions"));
|
|
61159
|
+
return roots;
|
|
61160
|
+
}
|
|
61001
61161
|
function buildSessionHandlers(deps) {
|
|
61002
61162
|
const { manager, observer, getAdapter: getAdapter2, store, ownerPrincipalId } = deps;
|
|
61003
61163
|
const ensureSessionAccess = (ctx, sessionId, action) => {
|
|
@@ -61373,6 +61533,23 @@ ${attribution}` } : args;
|
|
|
61373
61533
|
const { response, broadcast } = manager.markRead(args);
|
|
61374
61534
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
61375
61535
|
};
|
|
61536
|
+
const searchContent = async (frame, _client, ctx) => {
|
|
61537
|
+
const args = SessionSearchContentArgs.parse(frame);
|
|
61538
|
+
const limit = args.limit ?? DEFAULT_SEARCH_LIMIT;
|
|
61539
|
+
const locateCodexRollout = createCodexRolloutLocator(codexRolloutRoots(deps.dataDir));
|
|
61540
|
+
const matches = [];
|
|
61541
|
+
for (const sessionId of args.sessionIds) {
|
|
61542
|
+
if (matches.length >= limit) break;
|
|
61543
|
+
const file = manager.findOwnedSession(sessionId);
|
|
61544
|
+
if (!file?.toolSessionId) continue;
|
|
61545
|
+
if (!canReadSearchHit(ctx, file)) continue;
|
|
61546
|
+
const transcript = file.tool === "codex" ? locateCodexRollout(file.toolSessionId) : deps.history?.resolveTranscriptFile(file.cwd, file.toolSessionId) ?? null;
|
|
61547
|
+
if (!transcript) continue;
|
|
61548
|
+
const snippet = searchTranscriptFile(transcript, args.query);
|
|
61549
|
+
if (snippet !== null) matches.push({ sessionId, snippet });
|
|
61550
|
+
}
|
|
61551
|
+
return { response: { type: "session:searchContent", matches } };
|
|
61552
|
+
};
|
|
61376
61553
|
const reorderPins = async (frame) => {
|
|
61377
61554
|
const args = SessionReorderPinsArgs.parse(frame);
|
|
61378
61555
|
const { response, broadcast } = manager.reorderPins(args);
|
|
@@ -61493,6 +61670,7 @@ ${attribution}` } : args;
|
|
|
61493
61670
|
"session:pin": pin,
|
|
61494
61671
|
"session:archive": archive,
|
|
61495
61672
|
"session:markRead": markRead,
|
|
61673
|
+
"session:searchContent": searchContent,
|
|
61496
61674
|
"session:reorderPins": reorderPins,
|
|
61497
61675
|
"session:answerQuestion": answerQuestion,
|
|
61498
61676
|
"session:cancelQuestion": cancelQuestion,
|
|
@@ -61519,7 +61697,7 @@ function buildPermissionHandlers(deps) {
|
|
|
61519
61697
|
}
|
|
61520
61698
|
|
|
61521
61699
|
// src/handlers/history.ts
|
|
61522
|
-
var
|
|
61700
|
+
var path70 = __toESM(require("path"), 1);
|
|
61523
61701
|
init_protocol();
|
|
61524
61702
|
|
|
61525
61703
|
// src/session/recent-dirs.ts
|
|
@@ -61537,7 +61715,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
61537
61715
|
}
|
|
61538
61716
|
|
|
61539
61717
|
// src/permission/persona-paths.ts
|
|
61540
|
-
var
|
|
61718
|
+
var path69 = __toESM(require("path"), 1);
|
|
61541
61719
|
function getAllowedPersonaIds(grants, action) {
|
|
61542
61720
|
const ids = /* @__PURE__ */ new Set();
|
|
61543
61721
|
for (const g2 of grants) {
|
|
@@ -61550,42 +61728,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
61550
61728
|
return ids;
|
|
61551
61729
|
}
|
|
61552
61730
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
61553
|
-
const target =
|
|
61731
|
+
const target = path69.resolve(absPath);
|
|
61554
61732
|
if (userWorkDir) {
|
|
61555
|
-
const u =
|
|
61556
|
-
const usep = u.endsWith(
|
|
61733
|
+
const u = path69.resolve(userWorkDir);
|
|
61734
|
+
const usep = u.endsWith(path69.sep) ? "" : path69.sep;
|
|
61557
61735
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
61558
61736
|
}
|
|
61559
|
-
const root =
|
|
61560
|
-
const sep4 = root.endsWith(
|
|
61737
|
+
const root = path69.resolve(personaRoot);
|
|
61738
|
+
const sep4 = root.endsWith(path69.sep) ? "" : path69.sep;
|
|
61561
61739
|
if (!target.startsWith(root + sep4)) return false;
|
|
61562
|
-
const rel =
|
|
61740
|
+
const rel = path69.relative(root, target);
|
|
61563
61741
|
if (!rel || rel.startsWith("..")) return false;
|
|
61564
|
-
const personaId2 = rel.split(
|
|
61742
|
+
const personaId2 = rel.split(path69.sep)[0];
|
|
61565
61743
|
if (!personaId2) return false;
|
|
61566
61744
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
61567
61745
|
if (allowed === "*") return true;
|
|
61568
61746
|
return allowed.has(personaId2);
|
|
61569
61747
|
}
|
|
61570
61748
|
function personaIdFromPath(absPath, personaRoot) {
|
|
61571
|
-
const root =
|
|
61572
|
-
const target =
|
|
61573
|
-
const sep4 = root.endsWith(
|
|
61749
|
+
const root = path69.resolve(personaRoot);
|
|
61750
|
+
const target = path69.resolve(absPath);
|
|
61751
|
+
const sep4 = root.endsWith(path69.sep) ? "" : path69.sep;
|
|
61574
61752
|
if (!target.startsWith(root + sep4)) return null;
|
|
61575
|
-
const rel =
|
|
61753
|
+
const rel = path69.relative(root, target);
|
|
61576
61754
|
if (!rel || rel.startsWith("..")) return null;
|
|
61577
|
-
const id = rel.split(
|
|
61755
|
+
const id = rel.split(path69.sep)[0];
|
|
61578
61756
|
return id || null;
|
|
61579
61757
|
}
|
|
61580
61758
|
function isPathWithin(dir, absPath) {
|
|
61581
|
-
const d =
|
|
61582
|
-
const t =
|
|
61583
|
-
const sep4 = d.endsWith(
|
|
61759
|
+
const d = path69.resolve(dir);
|
|
61760
|
+
const t = path69.resolve(absPath);
|
|
61761
|
+
const sep4 = d.endsWith(path69.sep) ? "" : path69.sep;
|
|
61584
61762
|
return t === d || t.startsWith(d + sep4);
|
|
61585
61763
|
}
|
|
61586
61764
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
61587
61765
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
61588
|
-
return personaIdFromPath(
|
|
61766
|
+
return personaIdFromPath(path69.resolve(absPath), personaRoot) === personaId2;
|
|
61589
61767
|
}
|
|
61590
61768
|
|
|
61591
61769
|
// src/handlers/history.ts
|
|
@@ -61638,7 +61816,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61638
61816
|
if (!pid) return false;
|
|
61639
61817
|
return isGuestPathAllowed(
|
|
61640
61818
|
ctx.grants,
|
|
61641
|
-
|
|
61819
|
+
path70.join(personaRoot, pid),
|
|
61642
61820
|
personaRoot,
|
|
61643
61821
|
"read",
|
|
61644
61822
|
userWorkDir
|
|
@@ -61650,7 +61828,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61650
61828
|
};
|
|
61651
61829
|
const list = async (frame, _client, ctx) => {
|
|
61652
61830
|
const args = HistoryListArgs.parse(frame);
|
|
61653
|
-
assertGuestPath(ctx,
|
|
61831
|
+
assertGuestPath(ctx, path70.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
61654
61832
|
const sessions = await history.listSessions(args);
|
|
61655
61833
|
return { response: { type: "history:list", sessions } };
|
|
61656
61834
|
};
|
|
@@ -61698,14 +61876,14 @@ function buildHistoryHandlers(deps) {
|
|
|
61698
61876
|
};
|
|
61699
61877
|
const subagents = async (frame, _client, ctx) => {
|
|
61700
61878
|
const args = HistorySubagentsArgs.parse(frame);
|
|
61701
|
-
assertGuestPath(ctx,
|
|
61879
|
+
assertGuestPath(ctx, path70.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
61702
61880
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
61703
61881
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
61704
61882
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
61705
61883
|
};
|
|
61706
61884
|
const subagentRead = async (frame, _client, ctx) => {
|
|
61707
61885
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
61708
|
-
assertGuestPath(ctx,
|
|
61886
|
+
assertGuestPath(ctx, path70.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
61709
61887
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
61710
61888
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
61711
61889
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -61715,7 +61893,7 @@ function buildHistoryHandlers(deps) {
|
|
|
61715
61893
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
61716
61894
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
61717
61895
|
const filtered = dirs.filter(
|
|
61718
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
61896
|
+
(d) => isGuestPathAllowed(ctx.grants, path70.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
61719
61897
|
);
|
|
61720
61898
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
61721
61899
|
}
|
|
@@ -61732,17 +61910,17 @@ function buildHistoryHandlers(deps) {
|
|
|
61732
61910
|
}
|
|
61733
61911
|
|
|
61734
61912
|
// src/handlers/projects.ts
|
|
61735
|
-
var
|
|
61736
|
-
var
|
|
61737
|
-
var
|
|
61913
|
+
var fs64 = __toESM(require("fs"), 1);
|
|
61914
|
+
var os21 = __toESM(require("os"), 1);
|
|
61915
|
+
var path71 = __toESM(require("path"), 1);
|
|
61738
61916
|
var import_node_child_process13 = require("child_process");
|
|
61739
61917
|
init_protocol();
|
|
61740
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
61918
|
+
var DEFAULT_PROJECTS_ROOT = path71.join(os21.homedir(), "Documents", "ChatGPT");
|
|
61741
61919
|
function allocateDir(root, name) {
|
|
61742
|
-
let candidate =
|
|
61920
|
+
let candidate = path71.join(root, name);
|
|
61743
61921
|
let n = 2;
|
|
61744
|
-
while (
|
|
61745
|
-
candidate =
|
|
61922
|
+
while (fs64.existsSync(candidate)) {
|
|
61923
|
+
candidate = path71.join(root, `${name} ${n}`);
|
|
61746
61924
|
n += 1;
|
|
61747
61925
|
}
|
|
61748
61926
|
return candidate;
|
|
@@ -61770,7 +61948,7 @@ function buildProjectHandlers(deps) {
|
|
|
61770
61948
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
61771
61949
|
}
|
|
61772
61950
|
try {
|
|
61773
|
-
if (!
|
|
61951
|
+
if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
61774
61952
|
} catch {
|
|
61775
61953
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
61776
61954
|
}
|
|
@@ -61786,7 +61964,7 @@ function buildProjectHandlers(deps) {
|
|
|
61786
61964
|
let target;
|
|
61787
61965
|
if (args.path) {
|
|
61788
61966
|
try {
|
|
61789
|
-
if (!
|
|
61967
|
+
if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
61790
61968
|
} catch {
|
|
61791
61969
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
61792
61970
|
}
|
|
@@ -61794,15 +61972,15 @@ function buildProjectHandlers(deps) {
|
|
|
61794
61972
|
} else {
|
|
61795
61973
|
const name = args.name;
|
|
61796
61974
|
try {
|
|
61797
|
-
|
|
61975
|
+
fs64.mkdirSync(root, { recursive: true });
|
|
61798
61976
|
target = allocateDir(root, name);
|
|
61799
|
-
|
|
61977
|
+
fs64.mkdirSync(target);
|
|
61800
61978
|
} catch (err) {
|
|
61801
61979
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
61802
61980
|
}
|
|
61803
61981
|
const git = (0, import_node_child_process13.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
61804
61982
|
if (git.status !== 0) {
|
|
61805
|
-
|
|
61983
|
+
fs64.rmSync(target, { recursive: true, force: true });
|
|
61806
61984
|
throw new ClawdError(
|
|
61807
61985
|
ERROR_CODES.INVALID_CWD,
|
|
61808
61986
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -61827,8 +62005,8 @@ function buildProjectHandlers(deps) {
|
|
|
61827
62005
|
}
|
|
61828
62006
|
|
|
61829
62007
|
// src/handlers/workspace.ts
|
|
61830
|
-
var
|
|
61831
|
-
var
|
|
62008
|
+
var path72 = __toESM(require("path"), 1);
|
|
62009
|
+
var os22 = __toESM(require("os"), 1);
|
|
61832
62010
|
init_protocol();
|
|
61833
62011
|
init_protocol();
|
|
61834
62012
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -61868,23 +62046,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
61868
62046
|
const list = async (frame, _client, ctx) => {
|
|
61869
62047
|
const args = WorkspaceListArgs.parse(frame);
|
|
61870
62048
|
const isGuest = ctx?.principal.kind === "guest";
|
|
61871
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
61872
|
-
const resolvedCwd =
|
|
61873
|
-
const target = args.path ?
|
|
62049
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os22.homedir();
|
|
62050
|
+
const resolvedCwd = path72.resolve(args.cwd ?? fallbackCwd);
|
|
62051
|
+
const target = args.path ? path72.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
61874
62052
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
61875
62053
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
61876
62054
|
return { response: { type: "workspace:list", ...res } };
|
|
61877
62055
|
};
|
|
61878
62056
|
const read = async (frame, _client, ctx) => {
|
|
61879
62057
|
const args = WorkspaceReadArgs.parse(frame);
|
|
61880
|
-
const target =
|
|
62058
|
+
const target = path72.isAbsolute(args.path) ? path72.resolve(args.path) : path72.resolve(args.cwd, args.path);
|
|
61881
62059
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
61882
62060
|
const res = workspace.read(args);
|
|
61883
62061
|
return { response: { type: "workspace:read", ...res } };
|
|
61884
62062
|
};
|
|
61885
62063
|
const skillsList = async (frame, _client, ctx) => {
|
|
61886
62064
|
const args = SkillsListArgs.parse(frame);
|
|
61887
|
-
const cwdAbs =
|
|
62065
|
+
const cwdAbs = path72.resolve(args.cwd);
|
|
61888
62066
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
61889
62067
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
61890
62068
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -61896,7 +62074,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
61896
62074
|
};
|
|
61897
62075
|
const agentsList = async (frame, _client, ctx) => {
|
|
61898
62076
|
const args = AgentsListArgs.parse(frame);
|
|
61899
|
-
const cwdAbs =
|
|
62077
|
+
const cwdAbs = path72.resolve(args.cwd);
|
|
61900
62078
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
61901
62079
|
if (args.tool === "codex") {
|
|
61902
62080
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -61918,20 +62096,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
61918
62096
|
}
|
|
61919
62097
|
|
|
61920
62098
|
// src/handlers/git.ts
|
|
61921
|
-
var
|
|
62099
|
+
var path74 = __toESM(require("path"), 1);
|
|
61922
62100
|
init_protocol();
|
|
61923
62101
|
init_protocol();
|
|
61924
62102
|
|
|
61925
62103
|
// src/workspace/git.ts
|
|
61926
62104
|
var import_node_child_process14 = require("child_process");
|
|
61927
|
-
var
|
|
61928
|
-
var
|
|
62105
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
62106
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
61929
62107
|
var import_node_util = require("util");
|
|
61930
62108
|
var pexec = (0, import_node_util.promisify)(import_node_child_process14.execFile);
|
|
61931
62109
|
function normalizePath(p2) {
|
|
61932
|
-
const resolved =
|
|
62110
|
+
const resolved = import_node_path56.default.resolve(p2);
|
|
61933
62111
|
try {
|
|
61934
|
-
return
|
|
62112
|
+
return import_node_fs49.default.realpathSync(resolved);
|
|
61935
62113
|
} catch {
|
|
61936
62114
|
return resolved;
|
|
61937
62115
|
}
|
|
@@ -62005,7 +62183,7 @@ async function listGitBranches(cwd) {
|
|
|
62005
62183
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
62006
62184
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
62007
62185
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
62008
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
62186
|
+
if (!isGuestPathAllowed(ctx.grants, path74.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
62009
62187
|
throw new ClawdError(
|
|
62010
62188
|
ERROR_CODES.UNAUTHORIZED,
|
|
62011
62189
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -62550,7 +62728,7 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
62550
62728
|
}
|
|
62551
62729
|
|
|
62552
62730
|
// src/handlers/meta.ts
|
|
62553
|
-
var
|
|
62731
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
62554
62732
|
init_protocol();
|
|
62555
62733
|
|
|
62556
62734
|
// src/handlers/method-grants.ts
|
|
@@ -62626,6 +62804,9 @@ var METHOD_GRANT_MAP = {
|
|
|
62626
62804
|
"session:pin": CAPABILITY_SCOPED,
|
|
62627
62805
|
"session:archive": CAPABILITY_SCOPED,
|
|
62628
62806
|
"session:markRead": CAPABILITY_SCOPED,
|
|
62807
|
+
// 全局搜索扫 transcript 正文。与 history:read 同档:guest 进 persona VM 后要能搜自己的会话,
|
|
62808
|
+
// handler 内仍逐条 ensureSessionAccess,可见面不因 sessionIds 由客户端给定而放大
|
|
62809
|
+
"session:searchContent": CAPABILITY_SCOPED,
|
|
62629
62810
|
"session:reorderPins": ADMIN_ANY,
|
|
62630
62811
|
// owner 全局操作,无 personaId 维度
|
|
62631
62812
|
// mirror peer sessions (2026-05-26):owner-only — guest 不应能写/删本机 mirror SessionFile
|
|
@@ -62837,21 +63018,21 @@ function computeMethodAccess(args) {
|
|
|
62837
63018
|
}
|
|
62838
63019
|
|
|
62839
63020
|
// src/version.ts
|
|
62840
|
-
var version = "0.2.
|
|
63021
|
+
var version = "0.2.441".length > 0 ? "0.2.441" : "dev";
|
|
62841
63022
|
|
|
62842
63023
|
// src/cli-probe/probe.ts
|
|
62843
|
-
var
|
|
62844
|
-
var
|
|
63024
|
+
var fs66 = __toESM(require("fs"), 1);
|
|
63025
|
+
var path75 = __toESM(require("path"), 1);
|
|
62845
63026
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
62846
63027
|
var BIN_NAME = "clawd";
|
|
62847
63028
|
var MAX_PARENT_HOPS = 5;
|
|
62848
63029
|
function probeGlobalCli(pathEnv) {
|
|
62849
63030
|
if (!pathEnv) return null;
|
|
62850
|
-
for (const dir of pathEnv.split(
|
|
63031
|
+
for (const dir of pathEnv.split(path75.delimiter)) {
|
|
62851
63032
|
if (!dir) continue;
|
|
62852
63033
|
let real;
|
|
62853
63034
|
try {
|
|
62854
|
-
real =
|
|
63035
|
+
real = fs66.realpathSync(path75.join(dir, BIN_NAME));
|
|
62855
63036
|
} catch {
|
|
62856
63037
|
continue;
|
|
62857
63038
|
}
|
|
@@ -62861,15 +63042,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
62861
63042
|
return null;
|
|
62862
63043
|
}
|
|
62863
63044
|
function readOwnPackageVersion(entryPath) {
|
|
62864
|
-
let dir =
|
|
63045
|
+
let dir = path75.dirname(entryPath);
|
|
62865
63046
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
62866
63047
|
try {
|
|
62867
|
-
const raw =
|
|
63048
|
+
const raw = fs66.readFileSync(path75.join(dir, "package.json"), "utf8");
|
|
62868
63049
|
const pkg = JSON.parse(raw);
|
|
62869
63050
|
if (pkg.name !== PKG_NAME) return null;
|
|
62870
63051
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
62871
63052
|
} catch {
|
|
62872
|
-
const parent =
|
|
63053
|
+
const parent = path75.dirname(dir);
|
|
62873
63054
|
if (parent === dir) return null;
|
|
62874
63055
|
dir = parent;
|
|
62875
63056
|
}
|
|
@@ -62905,7 +63086,7 @@ function buildReadyFrame(deps, client) {
|
|
|
62905
63086
|
return {
|
|
62906
63087
|
version,
|
|
62907
63088
|
protocolVersion: PROTOCOL_VERSION,
|
|
62908
|
-
hostname:
|
|
63089
|
+
hostname: import_node_os20.default.hostname(),
|
|
62909
63090
|
os: process.platform,
|
|
62910
63091
|
tools,
|
|
62911
63092
|
runningSessions: info.runningSessions,
|
|
@@ -63021,16 +63202,8 @@ function buildPersonaHandlers(deps) {
|
|
|
63021
63202
|
const args = parseArgs2(PersonaUpdateArgsSchema, frame, "persona:update");
|
|
63022
63203
|
const { personality, personalityLocal, codexSandbox, ...metaPatch } = args.patch;
|
|
63023
63204
|
const persona = personaManager.update(args.personaId, metaPatch, { personality, personalityLocal });
|
|
63024
|
-
|
|
63025
|
-
return {
|
|
63026
|
-
response: {
|
|
63027
|
-
type: "persona:info",
|
|
63028
|
-
...persona,
|
|
63029
|
-
// 只在本次确实动过时回带,让调用方拿到合并后的真值而不用再 get 一次;
|
|
63030
|
-
// 没动就不带(与 personality 等分层字段同口径:persona:update 的响应是 meta 视图)。
|
|
63031
|
-
...mergedCodexSandbox ? { codexSandbox: mergedCodexSandbox } : {}
|
|
63032
|
-
}
|
|
63033
|
-
};
|
|
63205
|
+
if (codexSandbox) personaManager.mergeCodexSandbox(args.personaId, codexSandbox);
|
|
63206
|
+
return { response: { type: "persona:info", ...persona } };
|
|
63034
63207
|
};
|
|
63035
63208
|
const del = async (frame) => {
|
|
63036
63209
|
const args = parseArgs2(PersonaIdArgsSchema, frame, "persona:delete");
|
|
@@ -63049,7 +63222,7 @@ function buildPersonaHandlers(deps) {
|
|
|
63049
63222
|
}
|
|
63050
63223
|
|
|
63051
63224
|
// src/handlers/attachment.ts
|
|
63052
|
-
var
|
|
63225
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
63053
63226
|
init_protocol();
|
|
63054
63227
|
init_protocol();
|
|
63055
63228
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -63129,12 +63302,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
63129
63302
|
`session ${args.sessionId} scope unresolved`
|
|
63130
63303
|
);
|
|
63131
63304
|
}
|
|
63132
|
-
const cwdAbs =
|
|
63133
|
-
const candidateAbs =
|
|
63305
|
+
const cwdAbs = import_node_path57.default.resolve(sessionFile.cwd);
|
|
63306
|
+
const candidateAbs = import_node_path57.default.isAbsolute(args.relPath) ? import_node_path57.default.resolve(args.relPath) : import_node_path57.default.resolve(cwdAbs, args.relPath);
|
|
63134
63307
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
63135
63308
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
63136
63309
|
const entry = entries.find((e) => {
|
|
63137
|
-
const storedAbs =
|
|
63310
|
+
const storedAbs = import_node_path57.default.isAbsolute(e.relPath) ? import_node_path57.default.resolve(e.relPath) : import_node_path57.default.resolve(cwdAbs, e.relPath);
|
|
63138
63311
|
return storedAbs === candidateAbs && !e.stale;
|
|
63139
63312
|
});
|
|
63140
63313
|
if (!entry) {
|
|
@@ -63159,7 +63332,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
63159
63332
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
63160
63333
|
const f = deps.sessionStore.read(sessionId);
|
|
63161
63334
|
if (!f) return;
|
|
63162
|
-
assertGuestAttachmentPath(ctx,
|
|
63335
|
+
assertGuestAttachmentPath(ctx, import_node_path57.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
63163
63336
|
}
|
|
63164
63337
|
const groupAdd = async (frame, _client, ctx) => {
|
|
63165
63338
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -63174,8 +63347,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
63174
63347
|
if (!scope) {
|
|
63175
63348
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
63176
63349
|
}
|
|
63177
|
-
const cwdAbs =
|
|
63178
|
-
const candidateAbs =
|
|
63350
|
+
const cwdAbs = import_node_path57.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
63351
|
+
const candidateAbs = import_node_path57.default.isAbsolute(args.relPath) ? import_node_path57.default.resolve(args.relPath) : import_node_path57.default.resolve(cwdAbs, args.relPath);
|
|
63179
63352
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
63180
63353
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
63181
63354
|
const size = 0;
|
|
@@ -63234,19 +63407,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
63234
63407
|
|
|
63235
63408
|
// src/handlers/extension.ts
|
|
63236
63409
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
63237
|
-
var
|
|
63410
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
63238
63411
|
init_protocol();
|
|
63239
63412
|
|
|
63240
63413
|
// src/extension/bundle-zip.ts
|
|
63241
63414
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
63242
|
-
var
|
|
63415
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
63243
63416
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
63244
63417
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
63245
63418
|
async function bundleExtensionDir(dir) {
|
|
63246
63419
|
const entries = await listFilesSorted(dir);
|
|
63247
63420
|
const zip = new import_jszip2.default();
|
|
63248
63421
|
for (const rel of entries) {
|
|
63249
|
-
const abs =
|
|
63422
|
+
const abs = import_node_path58.default.join(dir, rel);
|
|
63250
63423
|
const content = await import_promises9.default.readFile(abs);
|
|
63251
63424
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
63252
63425
|
}
|
|
@@ -63267,7 +63440,7 @@ async function listFilesSorted(rootDir) {
|
|
|
63267
63440
|
return out;
|
|
63268
63441
|
}
|
|
63269
63442
|
async function walk(absRoot, relPrefix, out) {
|
|
63270
|
-
const dirAbs =
|
|
63443
|
+
const dirAbs = import_node_path58.default.join(absRoot, relPrefix);
|
|
63271
63444
|
const entries = await import_promises9.default.readdir(dirAbs, { withFileTypes: true });
|
|
63272
63445
|
for (const e of entries) {
|
|
63273
63446
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -63321,25 +63494,25 @@ function computePublishCheck(args) {
|
|
|
63321
63494
|
|
|
63322
63495
|
// src/extension/install-flow.ts
|
|
63323
63496
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
63324
|
-
var
|
|
63325
|
-
var
|
|
63497
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
63498
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
63326
63499
|
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
63327
63500
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
63328
63501
|
|
|
63329
63502
|
// src/extension/paths.ts
|
|
63330
|
-
var
|
|
63331
|
-
var
|
|
63503
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
63504
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
63332
63505
|
function clawdHomeRoot(override) {
|
|
63333
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
63506
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path59.default.join(import_node_os21.default.homedir(), ".clawd");
|
|
63334
63507
|
}
|
|
63335
63508
|
function extensionsRoot(override) {
|
|
63336
|
-
return
|
|
63509
|
+
return import_node_path59.default.join(clawdHomeRoot(override), "extensions");
|
|
63337
63510
|
}
|
|
63338
63511
|
function publishedChannelsFile(override) {
|
|
63339
|
-
return
|
|
63512
|
+
return import_node_path59.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
63340
63513
|
}
|
|
63341
63514
|
function bundleCacheRoot(override) {
|
|
63342
|
-
return
|
|
63515
|
+
return import_node_path59.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
63343
63516
|
}
|
|
63344
63517
|
|
|
63345
63518
|
// src/extension/install-flow.ts
|
|
@@ -63366,7 +63539,7 @@ async function installFromChannel(args, deps) {
|
|
|
63366
63539
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
63367
63540
|
}
|
|
63368
63541
|
for (const name of Object.keys(zip.files)) {
|
|
63369
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
63542
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path60.default.isAbsolute(name)) {
|
|
63370
63543
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
63371
63544
|
}
|
|
63372
63545
|
}
|
|
@@ -63398,7 +63571,7 @@ async function installFromChannel(args, deps) {
|
|
|
63398
63571
|
);
|
|
63399
63572
|
}
|
|
63400
63573
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
63401
|
-
const destDir =
|
|
63574
|
+
const destDir = import_node_path60.default.join(deps.extensionsRoot, localExtId);
|
|
63402
63575
|
let destExists = false;
|
|
63403
63576
|
try {
|
|
63404
63577
|
await import_promises10.default.access(destDir);
|
|
@@ -63412,16 +63585,16 @@ async function installFromChannel(args, deps) {
|
|
|
63412
63585
|
);
|
|
63413
63586
|
}
|
|
63414
63587
|
const stage = await import_promises10.default.mkdtemp(
|
|
63415
|
-
|
|
63588
|
+
import_node_path60.default.join(import_node_os22.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
63416
63589
|
);
|
|
63417
63590
|
try {
|
|
63418
63591
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
63419
|
-
const dest =
|
|
63592
|
+
const dest = import_node_path60.default.join(stage, name);
|
|
63420
63593
|
if (entry.dir) {
|
|
63421
63594
|
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
63422
63595
|
continue;
|
|
63423
63596
|
}
|
|
63424
|
-
await import_promises10.default.mkdir(
|
|
63597
|
+
await import_promises10.default.mkdir(import_node_path60.default.dirname(dest), { recursive: true });
|
|
63425
63598
|
if (name === "manifest.json") {
|
|
63426
63599
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
63427
63600
|
await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -63442,8 +63615,8 @@ async function installFromChannel(args, deps) {
|
|
|
63442
63615
|
|
|
63443
63616
|
// src/extension/update-flow.ts
|
|
63444
63617
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
63445
|
-
var
|
|
63446
|
-
var
|
|
63618
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
63619
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
63447
63620
|
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
63448
63621
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
63449
63622
|
var UpdateError = class extends Error {
|
|
@@ -63459,11 +63632,11 @@ async function updateFromChannel(args, deps) {
|
|
|
63459
63632
|
channelRef.extId,
|
|
63460
63633
|
channelRef.ownerPrincipalId
|
|
63461
63634
|
);
|
|
63462
|
-
const liveDir =
|
|
63635
|
+
const liveDir = import_node_path61.default.join(deps.extensionsRoot, localExtId);
|
|
63463
63636
|
const prevDir = `${liveDir}.prev`;
|
|
63464
63637
|
let existingVersion;
|
|
63465
63638
|
try {
|
|
63466
|
-
const raw = await import_promises11.default.readFile(
|
|
63639
|
+
const raw = await import_promises11.default.readFile(import_node_path61.default.join(liveDir, "manifest.json"), "utf8");
|
|
63467
63640
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
63468
63641
|
if (!parsed2.success) {
|
|
63469
63642
|
throw new UpdateError(
|
|
@@ -63496,7 +63669,7 @@ async function updateFromChannel(args, deps) {
|
|
|
63496
63669
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
63497
63670
|
}
|
|
63498
63671
|
for (const name of Object.keys(zip.files)) {
|
|
63499
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
63672
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path61.default.isAbsolute(name)) {
|
|
63500
63673
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
63501
63674
|
}
|
|
63502
63675
|
}
|
|
@@ -63531,16 +63704,16 @@ async function updateFromChannel(args, deps) {
|
|
|
63531
63704
|
await import_promises11.default.rm(prevDir, { recursive: true, force: true });
|
|
63532
63705
|
await import_promises11.default.rename(liveDir, prevDir);
|
|
63533
63706
|
const stage = await import_promises11.default.mkdtemp(
|
|
63534
|
-
|
|
63707
|
+
import_node_path61.default.join(import_node_os23.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
63535
63708
|
);
|
|
63536
63709
|
try {
|
|
63537
63710
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
63538
|
-
const dest =
|
|
63711
|
+
const dest = import_node_path61.default.join(stage, name);
|
|
63539
63712
|
if (entry.dir) {
|
|
63540
63713
|
await import_promises11.default.mkdir(dest, { recursive: true });
|
|
63541
63714
|
continue;
|
|
63542
63715
|
}
|
|
63543
|
-
await import_promises11.default.mkdir(
|
|
63716
|
+
await import_promises11.default.mkdir(import_node_path61.default.dirname(dest), { recursive: true });
|
|
63544
63717
|
if (name === "manifest.json") {
|
|
63545
63718
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
63546
63719
|
await import_promises11.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -63607,7 +63780,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
63607
63780
|
);
|
|
63608
63781
|
}
|
|
63609
63782
|
}
|
|
63610
|
-
const manifestPath =
|
|
63783
|
+
const manifestPath = import_node_path62.default.join(root, extId, "manifest.json");
|
|
63611
63784
|
const manifest = await readManifest(root, extId);
|
|
63612
63785
|
const next = { ...manifest, version: newVersion };
|
|
63613
63786
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -63615,7 +63788,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
63615
63788
|
await import_promises12.default.rename(tmp, manifestPath);
|
|
63616
63789
|
}
|
|
63617
63790
|
async function readManifest(root, extId) {
|
|
63618
|
-
const file =
|
|
63791
|
+
const file = import_node_path62.default.join(root, extId, "manifest.json");
|
|
63619
63792
|
let raw;
|
|
63620
63793
|
try {
|
|
63621
63794
|
raw = await import_promises12.default.readFile(file, "utf8");
|
|
@@ -63699,7 +63872,7 @@ function buildExtensionHandlers(deps) {
|
|
|
63699
63872
|
};
|
|
63700
63873
|
async function buildSnapshotMeta(extId) {
|
|
63701
63874
|
const manifest = await readManifest(deps.root, extId);
|
|
63702
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
63875
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path62.default.join(deps.root, extId));
|
|
63703
63876
|
return { manifest, contentHash: sha256, buffer };
|
|
63704
63877
|
}
|
|
63705
63878
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -63874,9 +64047,9 @@ function buildExtensionHandlers(deps) {
|
|
|
63874
64047
|
}
|
|
63875
64048
|
|
|
63876
64049
|
// src/app-builder/project-store.ts
|
|
63877
|
-
var
|
|
64050
|
+
var import_node_fs50 = require("fs");
|
|
63878
64051
|
var import_node_child_process15 = require("child_process");
|
|
63879
|
-
var
|
|
64052
|
+
var import_node_path63 = require("path");
|
|
63880
64053
|
init_protocol();
|
|
63881
64054
|
var PROJECTS_DIR = "projects";
|
|
63882
64055
|
var META_FILE = ".clawd-project.json";
|
|
@@ -63890,19 +64063,19 @@ var ProjectStore = class {
|
|
|
63890
64063
|
root;
|
|
63891
64064
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
63892
64065
|
metaPath(name) {
|
|
63893
|
-
return (0,
|
|
64066
|
+
return (0, import_node_path63.join)(this.projectsRoot(), name, META_FILE);
|
|
63894
64067
|
}
|
|
63895
64068
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
63896
64069
|
projectDir(name) {
|
|
63897
|
-
return (0,
|
|
64070
|
+
return (0, import_node_path63.join)(this.projectsRoot(), name);
|
|
63898
64071
|
}
|
|
63899
64072
|
projectsRoot() {
|
|
63900
|
-
return (0,
|
|
64073
|
+
return (0, import_node_path63.join)(this.root, PROJECTS_DIR);
|
|
63901
64074
|
}
|
|
63902
64075
|
async list() {
|
|
63903
64076
|
let entries;
|
|
63904
64077
|
try {
|
|
63905
|
-
entries = await
|
|
64078
|
+
entries = await import_node_fs50.promises.readdir(this.projectsRoot());
|
|
63906
64079
|
} catch (err) {
|
|
63907
64080
|
if (err.code === "ENOENT") return [];
|
|
63908
64081
|
throw err;
|
|
@@ -63910,7 +64083,7 @@ var ProjectStore = class {
|
|
|
63910
64083
|
const out = [];
|
|
63911
64084
|
for (const name of entries) {
|
|
63912
64085
|
try {
|
|
63913
|
-
const raw = await
|
|
64086
|
+
const raw = await import_node_fs50.promises.readFile(this.metaPath(name), "utf8");
|
|
63914
64087
|
const json = JSON.parse(raw);
|
|
63915
64088
|
let migrated = false;
|
|
63916
64089
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -63921,7 +64094,7 @@ var ProjectStore = class {
|
|
|
63921
64094
|
if (parsed.success) {
|
|
63922
64095
|
out.push(parsed.data);
|
|
63923
64096
|
if (migrated) {
|
|
63924
|
-
void
|
|
64097
|
+
void import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
63925
64098
|
});
|
|
63926
64099
|
}
|
|
63927
64100
|
}
|
|
@@ -63965,8 +64138,8 @@ var ProjectStore = class {
|
|
|
63965
64138
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
63966
64139
|
}
|
|
63967
64140
|
const dir = this.projectDir(name);
|
|
63968
|
-
await
|
|
63969
|
-
await
|
|
64141
|
+
await import_node_fs50.promises.mkdir(dir, { recursive: true });
|
|
64142
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
63970
64143
|
return meta;
|
|
63971
64144
|
}
|
|
63972
64145
|
/**
|
|
@@ -64009,7 +64182,7 @@ var ProjectStore = class {
|
|
|
64009
64182
|
}
|
|
64010
64183
|
async delete(name) {
|
|
64011
64184
|
const dir = this.projectDir(name);
|
|
64012
|
-
await
|
|
64185
|
+
await import_node_fs50.promises.rm(dir, { recursive: true, force: true });
|
|
64013
64186
|
}
|
|
64014
64187
|
async updatePort(name, newPort) {
|
|
64015
64188
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -64025,7 +64198,7 @@ var ProjectStore = class {
|
|
|
64025
64198
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
64026
64199
|
}
|
|
64027
64200
|
const updated = { ...target, port: newPort };
|
|
64028
|
-
await
|
|
64201
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
64029
64202
|
return updated;
|
|
64030
64203
|
}
|
|
64031
64204
|
/**
|
|
@@ -64042,7 +64215,7 @@ var ProjectStore = class {
|
|
|
64042
64215
|
if (!validated.success) {
|
|
64043
64216
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
64044
64217
|
}
|
|
64045
|
-
await
|
|
64218
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
64046
64219
|
return validated.data;
|
|
64047
64220
|
}
|
|
64048
64221
|
/**
|
|
@@ -64063,7 +64236,7 @@ var ProjectStore = class {
|
|
|
64063
64236
|
if (!validated.success) {
|
|
64064
64237
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
64065
64238
|
}
|
|
64066
|
-
await
|
|
64239
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
64067
64240
|
return validated.data;
|
|
64068
64241
|
}
|
|
64069
64242
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -64078,7 +64251,7 @@ var ProjectStore = class {
|
|
|
64078
64251
|
if (!validated.success) {
|
|
64079
64252
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
64080
64253
|
}
|
|
64081
|
-
await
|
|
64254
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
64082
64255
|
return validated.data;
|
|
64083
64256
|
}
|
|
64084
64257
|
};
|
|
@@ -64199,8 +64372,8 @@ var PublishJobRegistry = class {
|
|
|
64199
64372
|
|
|
64200
64373
|
// src/app-builder/publish-job-runner.ts
|
|
64201
64374
|
var import_node_child_process17 = require("child_process");
|
|
64202
|
-
var
|
|
64203
|
-
var
|
|
64375
|
+
var import_node_fs51 = require("fs");
|
|
64376
|
+
var import_node_path64 = require("path");
|
|
64204
64377
|
|
|
64205
64378
|
// src/app-builder/publish-stage-parser.ts
|
|
64206
64379
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -64232,10 +64405,10 @@ async function startPublishJob(deps, args) {
|
|
|
64232
64405
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
64233
64406
|
}
|
|
64234
64407
|
const projDir = projectDir(args.name);
|
|
64235
|
-
const logPath = (0,
|
|
64408
|
+
const logPath = (0, import_node_path64.join)(projDir, ".publish.log");
|
|
64236
64409
|
let logStream = null;
|
|
64237
64410
|
try {
|
|
64238
|
-
logStream = (0,
|
|
64411
|
+
logStream = (0, import_node_fs51.createWriteStream)(logPath, { flags: "w" });
|
|
64239
64412
|
} catch {
|
|
64240
64413
|
logStream = null;
|
|
64241
64414
|
}
|
|
@@ -64492,8 +64665,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
64492
64665
|
|
|
64493
64666
|
// src/handlers/app-builder.ts
|
|
64494
64667
|
init_protocol();
|
|
64495
|
-
var
|
|
64496
|
-
var
|
|
64668
|
+
var import_node_path65 = require("path");
|
|
64669
|
+
var import_node_fs52 = require("fs");
|
|
64497
64670
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
64498
64671
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
64499
64672
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -64574,7 +64747,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
64574
64747
|
async function listAllUsersProjects() {
|
|
64575
64748
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
64576
64749
|
const getStore = deps.getStore;
|
|
64577
|
-
const userIds = await
|
|
64750
|
+
const userIds = await import_node_fs52.promises.readdir(deps.usersRoot).catch(() => []);
|
|
64578
64751
|
const perUser = await Promise.all(
|
|
64579
64752
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
64580
64753
|
);
|
|
@@ -64643,8 +64816,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
64643
64816
|
const project = await userStore.create(f.name, reservedPorts);
|
|
64644
64817
|
try {
|
|
64645
64818
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
64646
|
-
const templateSrcDir = (0,
|
|
64647
|
-
const scaffoldScript = (0,
|
|
64819
|
+
const templateSrcDir = (0, import_node_path65.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
64820
|
+
const scaffoldScript = (0, import_node_path65.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
64648
64821
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
64649
64822
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
64650
64823
|
name: project.name,
|
|
@@ -64848,7 +65021,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
64848
65021
|
await userStore.clearPublishJob(args.name);
|
|
64849
65022
|
}
|
|
64850
65023
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
64851
|
-
const scriptPath = (0,
|
|
65024
|
+
const scriptPath = (0, import_node_path65.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
64852
65025
|
deps.logger?.info("app-builder.publish.start", {
|
|
64853
65026
|
name: args.name,
|
|
64854
65027
|
sessionId: boundSession.sessionId,
|
|
@@ -65404,20 +65577,20 @@ function mapPrState(state, isDraft) {
|
|
|
65404
65577
|
if (state === "CLOSED") return "closed";
|
|
65405
65578
|
return isDraft === true ? "draft" : "open";
|
|
65406
65579
|
}
|
|
65407
|
-
function
|
|
65580
|
+
function asRecord2(v2) {
|
|
65408
65581
|
return typeof v2 === "object" && v2 !== null ? v2 : {};
|
|
65409
65582
|
}
|
|
65410
65583
|
function lastCommitRollup(node) {
|
|
65411
|
-
const first =
|
|
65412
|
-
return
|
|
65584
|
+
const first = asRecord2(node.commits).nodes?.[0];
|
|
65585
|
+
return asRecord2(asRecord2(first).commit).statusCheckRollup;
|
|
65413
65586
|
}
|
|
65414
65587
|
function parsePrListResponse(json) {
|
|
65415
|
-
const nodes =
|
|
65588
|
+
const nodes = asRecord2(asRecord2(asRecord2(json).data).search).nodes ?? [];
|
|
65416
65589
|
const items = [];
|
|
65417
65590
|
for (const raw of nodes) {
|
|
65418
|
-
const n =
|
|
65591
|
+
const n = asRecord2(raw);
|
|
65419
65592
|
if (typeof n.number !== "number") continue;
|
|
65420
|
-
const nameWithOwner = String(
|
|
65593
|
+
const nameWithOwner = String(asRecord2(n.repository).nameWithOwner ?? "");
|
|
65421
65594
|
const slash = nameWithOwner.indexOf("/");
|
|
65422
65595
|
if (slash <= 0) continue;
|
|
65423
65596
|
const rollup = lastCommitRollup(n);
|
|
@@ -65431,27 +65604,27 @@ function parsePrListResponse(json) {
|
|
|
65431
65604
|
additions: typeof n.additions === "number" ? n.additions : 0,
|
|
65432
65605
|
deletions: typeof n.deletions === "number" ? n.deletions : 0,
|
|
65433
65606
|
updatedAt: String(n.updatedAt ?? ""),
|
|
65434
|
-
author: String(
|
|
65435
|
-
checksRollup: rollup == null ? "none" : mapRollupState(
|
|
65607
|
+
author: String(asRecord2(n.author).login ?? ""),
|
|
65608
|
+
checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state)
|
|
65436
65609
|
});
|
|
65437
65610
|
}
|
|
65438
65611
|
return items;
|
|
65439
65612
|
}
|
|
65440
65613
|
function parsePrDetailResponse(json, repoRef) {
|
|
65441
|
-
const pr =
|
|
65614
|
+
const pr = asRecord2(asRecord2(asRecord2(json).data).repository).pullRequest;
|
|
65442
65615
|
if (pr == null || typeof pr !== "object") return null;
|
|
65443
|
-
const n =
|
|
65616
|
+
const n = asRecord2(pr);
|
|
65444
65617
|
const rollup = lastCommitRollup(n);
|
|
65445
|
-
const contextNodes =
|
|
65618
|
+
const contextNodes = asRecord2(asRecord2(rollup).contexts).nodes ?? [];
|
|
65446
65619
|
const checks = [];
|
|
65447
65620
|
for (const c of contextNodes) {
|
|
65448
|
-
const mapped = mapCheckNode(
|
|
65621
|
+
const mapped = mapCheckNode(asRecord2(c));
|
|
65449
65622
|
if (mapped) checks.push(mapped);
|
|
65450
65623
|
}
|
|
65451
|
-
const reviewerNodes =
|
|
65452
|
-
const reviewers = reviewerNodes.map((r) => String(
|
|
65624
|
+
const reviewerNodes = asRecord2(n.reviewRequests).nodes ?? [];
|
|
65625
|
+
const reviewers = reviewerNodes.map((r) => String(asRecord2(asRecord2(r).requestedReviewer).login ?? "")).filter((s) => s !== "");
|
|
65453
65626
|
const mergeable = n.mergeable === "MERGEABLE" ? "mergeable" : n.mergeable === "CONFLICTING" ? "conflicting" : "unknown";
|
|
65454
|
-
const commentCountRaw =
|
|
65627
|
+
const commentCountRaw = asRecord2(n.comments).totalCount;
|
|
65455
65628
|
return {
|
|
65456
65629
|
owner: repoRef.owner,
|
|
65457
65630
|
repo: repoRef.repo,
|
|
@@ -65459,7 +65632,7 @@ function parsePrDetailResponse(json, repoRef) {
|
|
|
65459
65632
|
title: String(n.title ?? ""),
|
|
65460
65633
|
body: String(n.body ?? ""),
|
|
65461
65634
|
state: mapPrState(n.state, n.isDraft),
|
|
65462
|
-
author: String(
|
|
65635
|
+
author: String(asRecord2(n.author).login ?? ""),
|
|
65463
65636
|
updatedAt: String(n.updatedAt ?? ""),
|
|
65464
65637
|
headRef: String(n.headRefName ?? ""),
|
|
65465
65638
|
baseRef: String(n.baseRefName ?? ""),
|
|
@@ -65469,7 +65642,7 @@ function parsePrDetailResponse(json, repoRef) {
|
|
|
65469
65642
|
mergeable,
|
|
65470
65643
|
reviewers,
|
|
65471
65644
|
commentCount: typeof commentCountRaw === "number" ? commentCountRaw : 0,
|
|
65472
|
-
checksRollup: rollup == null ? "none" : mapRollupState(
|
|
65645
|
+
checksRollup: rollup == null ? "none" : mapRollupState(asRecord2(rollup).state),
|
|
65473
65646
|
checks
|
|
65474
65647
|
};
|
|
65475
65648
|
}
|
|
@@ -65607,7 +65780,7 @@ function buildVisitorHandlers(deps) {
|
|
|
65607
65780
|
|
|
65608
65781
|
// src/extension/registry.ts
|
|
65609
65782
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
65610
|
-
var
|
|
65783
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
65611
65784
|
async function loadAll(root) {
|
|
65612
65785
|
let entries;
|
|
65613
65786
|
try {
|
|
@@ -65620,13 +65793,13 @@ async function loadAll(root) {
|
|
|
65620
65793
|
for (const ent of entries) {
|
|
65621
65794
|
if (!ent.isDirectory()) continue;
|
|
65622
65795
|
if (ent.name.startsWith(".")) continue;
|
|
65623
|
-
records.push(await loadOne(
|
|
65796
|
+
records.push(await loadOne(import_node_path66.default.join(root, ent.name), ent.name));
|
|
65624
65797
|
}
|
|
65625
65798
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
65626
65799
|
return records;
|
|
65627
65800
|
}
|
|
65628
65801
|
async function loadOne(dir, dirName) {
|
|
65629
|
-
const manifestPath =
|
|
65802
|
+
const manifestPath = import_node_path66.default.join(dir, "manifest.json");
|
|
65630
65803
|
let raw;
|
|
65631
65804
|
try {
|
|
65632
65805
|
raw = await import_promises14.default.readFile(manifestPath, "utf8");
|
|
@@ -65671,7 +65844,7 @@ async function loadOne(dir, dirName) {
|
|
|
65671
65844
|
|
|
65672
65845
|
// src/extension/uninstall.ts
|
|
65673
65846
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
65674
|
-
var
|
|
65847
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
65675
65848
|
var UninstallError = class extends Error {
|
|
65676
65849
|
constructor(code, message) {
|
|
65677
65850
|
super(message);
|
|
@@ -65680,7 +65853,7 @@ var UninstallError = class extends Error {
|
|
|
65680
65853
|
code;
|
|
65681
65854
|
};
|
|
65682
65855
|
async function uninstall(deps) {
|
|
65683
|
-
const dir =
|
|
65856
|
+
const dir = import_node_path67.default.join(deps.root, deps.extId);
|
|
65684
65857
|
try {
|
|
65685
65858
|
await import_promises15.default.access(dir);
|
|
65686
65859
|
} catch {
|
|
@@ -65698,14 +65871,14 @@ init_protocol();
|
|
|
65698
65871
|
|
|
65699
65872
|
// src/peer-ops/run-command.ts
|
|
65700
65873
|
var import_node_child_process18 = require("child_process");
|
|
65701
|
-
var
|
|
65874
|
+
var import_node_os24 = __toESM(require("os"), 1);
|
|
65702
65875
|
var DEFAULT_TIMEOUT_MS5 = 3e4;
|
|
65703
65876
|
var MAX_TIMEOUT_MS = 3e5;
|
|
65704
65877
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
65705
65878
|
function runCommand(command, opts = {}) {
|
|
65706
65879
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
|
|
65707
65880
|
return new Promise((resolve9) => {
|
|
65708
|
-
const child = (0, import_node_child_process18.spawn)("bash", ["-c", command], { cwd:
|
|
65881
|
+
const child = (0, import_node_child_process18.spawn)("bash", ["-c", command], { cwd: import_node_os24.default.homedir() });
|
|
65709
65882
|
const out = [];
|
|
65710
65883
|
const err = [];
|
|
65711
65884
|
let outBytes = 0;
|
|
@@ -65913,7 +66086,7 @@ function buildMethodHandlers(deps) {
|
|
|
65913
66086
|
broadcast: deps.broadcastToOwners
|
|
65914
66087
|
}),
|
|
65915
66088
|
...buildMasterHandlers({
|
|
65916
|
-
authorityTablePath:
|
|
66089
|
+
authorityTablePath: import_node_path68.default.join(deps.masterDataDir, "master-authority.json")
|
|
65917
66090
|
}),
|
|
65918
66091
|
...buildTopicHandlers({
|
|
65919
66092
|
topicStore: deps.topicStore,
|
|
@@ -65949,18 +66122,18 @@ init_claude();
|
|
|
65949
66122
|
|
|
65950
66123
|
// src/tools/shell-path.ts
|
|
65951
66124
|
var import_node_child_process19 = require("child_process");
|
|
65952
|
-
var
|
|
66125
|
+
var import_node_os25 = __toESM(require("os"), 1);
|
|
65953
66126
|
function refreshPathFromLoginShell() {
|
|
65954
66127
|
if (process.platform === "win32") return;
|
|
65955
|
-
const shell = process.env.SHELL ??
|
|
66128
|
+
const shell = process.env.SHELL ?? import_node_os25.default.userInfo().shell ?? "/bin/zsh";
|
|
65956
66129
|
try {
|
|
65957
66130
|
const out = (0, import_node_child_process19.execFileSync)(shell, ["-ilc", 'command echo -n "$PATH"'], {
|
|
65958
66131
|
encoding: "utf8",
|
|
65959
66132
|
timeout: 3e3,
|
|
65960
66133
|
stdio: ["ignore", "pipe", "ignore"]
|
|
65961
66134
|
});
|
|
65962
|
-
const
|
|
65963
|
-
if (
|
|
66135
|
+
const path91 = out.trim();
|
|
66136
|
+
if (path91) process.env.PATH = path91;
|
|
65964
66137
|
} catch {
|
|
65965
66138
|
}
|
|
65966
66139
|
}
|
|
@@ -66374,7 +66547,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
66374
66547
|
|
|
66375
66548
|
// src/extension/runtime.ts
|
|
66376
66549
|
var import_node_child_process22 = require("child_process");
|
|
66377
|
-
var
|
|
66550
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
66378
66551
|
var import_promises16 = require("timers/promises");
|
|
66379
66552
|
|
|
66380
66553
|
// src/extension/port-allocator.ts
|
|
@@ -66475,7 +66648,7 @@ var Runtime = class {
|
|
|
66475
66648
|
/\$CLAWOS_EXT_PORT/g,
|
|
66476
66649
|
String(port)
|
|
66477
66650
|
);
|
|
66478
|
-
const dir =
|
|
66651
|
+
const dir = import_node_path69.default.join(this.root, extId);
|
|
66479
66652
|
const env = {
|
|
66480
66653
|
...process.env,
|
|
66481
66654
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -66587,7 +66760,7 @@ ${handle.stderrTail}`
|
|
|
66587
66760
|
|
|
66588
66761
|
// src/extension/published-channels.ts
|
|
66589
66762
|
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
66590
|
-
var
|
|
66763
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
66591
66764
|
init_zod();
|
|
66592
66765
|
var PublishedChannelsError = class extends Error {
|
|
66593
66766
|
constructor(code, message) {
|
|
@@ -66686,7 +66859,7 @@ var PublishedChannelStore = class {
|
|
|
66686
66859
|
)
|
|
66687
66860
|
};
|
|
66688
66861
|
const tmp = `${this.filePath}.tmp`;
|
|
66689
|
-
await import_promises17.default.mkdir(
|
|
66862
|
+
await import_promises17.default.mkdir(import_node_path70.default.dirname(this.filePath), { recursive: true });
|
|
66690
66863
|
await import_promises17.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
66691
66864
|
await import_promises17.default.rename(tmp, this.filePath);
|
|
66692
66865
|
}
|
|
@@ -66694,7 +66867,7 @@ var PublishedChannelStore = class {
|
|
|
66694
66867
|
|
|
66695
66868
|
// src/extension/bundle-cache.ts
|
|
66696
66869
|
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
66697
|
-
var
|
|
66870
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
66698
66871
|
var BundleCache = class {
|
|
66699
66872
|
constructor(rootDir) {
|
|
66700
66873
|
this.rootDir = rootDir;
|
|
@@ -66703,14 +66876,14 @@ var BundleCache = class {
|
|
|
66703
66876
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
66704
66877
|
async write(snapshotHash, buffer) {
|
|
66705
66878
|
await import_promises18.default.mkdir(this.rootDir, { recursive: true });
|
|
66706
|
-
const file =
|
|
66879
|
+
const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
66707
66880
|
const tmp = `${file}.tmp`;
|
|
66708
66881
|
await import_promises18.default.writeFile(tmp, buffer, { mode: 384 });
|
|
66709
66882
|
await import_promises18.default.rename(tmp, file);
|
|
66710
66883
|
}
|
|
66711
66884
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
66712
66885
|
async read(snapshotHash) {
|
|
66713
|
-
const file =
|
|
66886
|
+
const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
66714
66887
|
try {
|
|
66715
66888
|
return await import_promises18.default.readFile(file);
|
|
66716
66889
|
} catch (e) {
|
|
@@ -66720,7 +66893,7 @@ var BundleCache = class {
|
|
|
66720
66893
|
}
|
|
66721
66894
|
/** Idempotent — missing file is not an error. */
|
|
66722
66895
|
async delete(snapshotHash) {
|
|
66723
|
-
const file =
|
|
66896
|
+
const file = import_node_path71.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
66724
66897
|
await import_promises18.default.rm(file, { force: true });
|
|
66725
66898
|
}
|
|
66726
66899
|
};
|
|
@@ -66741,26 +66914,26 @@ async function startDaemon(config) {
|
|
|
66741
66914
|
},
|
|
66742
66915
|
source: "daemon",
|
|
66743
66916
|
sampling: logShippingCfg.sampling,
|
|
66744
|
-
homeDir:
|
|
66917
|
+
homeDir: import_node_os26.default.homedir()
|
|
66745
66918
|
});
|
|
66746
|
-
const logDir =
|
|
66747
|
-
|
|
66919
|
+
const logDir = import_node_path72.default.join(config.dataDir, "log");
|
|
66920
|
+
import_node_fs53.default.mkdirSync(logDir, { recursive: true });
|
|
66748
66921
|
const logger = createLogger({
|
|
66749
66922
|
level: config.logLevel,
|
|
66750
|
-
file:
|
|
66923
|
+
file: import_node_path72.default.join(logDir, "clawd.log"),
|
|
66751
66924
|
logClient
|
|
66752
66925
|
});
|
|
66753
66926
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
66754
66927
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
66755
|
-
file:
|
|
66928
|
+
file: import_node_path72.default.join(logDir, "screen-idle-probe.log"),
|
|
66756
66929
|
level: "debug"
|
|
66757
66930
|
});
|
|
66758
66931
|
logger.info("screen-idle probe logger enabled", {
|
|
66759
|
-
file:
|
|
66932
|
+
file: import_node_path72.default.join(logDir, "screen-idle-probe.log")
|
|
66760
66933
|
});
|
|
66761
66934
|
const CAP_TARGETS = [
|
|
66762
|
-
|
|
66763
|
-
|
|
66935
|
+
import_node_path72.default.join(logDir, "clawd.log"),
|
|
66936
|
+
import_node_path72.default.join(logDir, "screen-idle-probe.log")
|
|
66764
66937
|
];
|
|
66765
66938
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
66766
66939
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -66882,8 +67055,8 @@ async function startDaemon(config) {
|
|
|
66882
67055
|
const agents = new AgentsScanner();
|
|
66883
67056
|
const history = new ClaudeHistoryReader();
|
|
66884
67057
|
let transport = null;
|
|
66885
|
-
const personaStore = new PersonaStore(
|
|
66886
|
-
const usersRoot =
|
|
67058
|
+
const personaStore = new PersonaStore(import_node_path72.default.join(config.dataDir, "personas"));
|
|
67059
|
+
const usersRoot = import_node_path72.default.join(config.dataDir, "users");
|
|
66887
67060
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
66888
67061
|
if (defaultsRoot) {
|
|
66889
67062
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -66907,7 +67080,7 @@ async function startDaemon(config) {
|
|
|
66907
67080
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
66908
67081
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
66909
67082
|
const dispatchStore = createDispatchStore({
|
|
66910
|
-
filePath:
|
|
67083
|
+
filePath: import_node_path72.default.join(config.dataDir, "dispatch.json"),
|
|
66911
67084
|
now: () => Date.now(),
|
|
66912
67085
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
66913
67086
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -66916,7 +67089,7 @@ async function startDaemon(config) {
|
|
|
66916
67089
|
await dispatchStore.load();
|
|
66917
67090
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
66918
67091
|
const channelStore = createChannelStore({
|
|
66919
|
-
filePath:
|
|
67092
|
+
filePath: import_node_path72.default.join(config.dataDir, "channels.json"),
|
|
66920
67093
|
now: () => Date.now(),
|
|
66921
67094
|
genId: () => `ch-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
66922
67095
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -66925,7 +67098,7 @@ async function startDaemon(config) {
|
|
|
66925
67098
|
});
|
|
66926
67099
|
await channelStore.load();
|
|
66927
67100
|
const topicStore = createTopicStore({
|
|
66928
|
-
filePath:
|
|
67101
|
+
filePath: import_node_path72.default.join(config.dataDir, "topics.json"),
|
|
66929
67102
|
now: () => Date.now(),
|
|
66930
67103
|
genId: () => `tp-${(0, import_node_crypto22.randomUUID)().slice(0, 8)}`,
|
|
66931
67104
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -66952,18 +67125,18 @@ async function startDaemon(config) {
|
|
|
66952
67125
|
});
|
|
66953
67126
|
}
|
|
66954
67127
|
});
|
|
66955
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
67128
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path72.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
66956
67129
|
const mcpConfigs = [];
|
|
66957
67130
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
66958
67131
|
const dispatchServerCandidates = [
|
|
66959
|
-
|
|
67132
|
+
import_node_path72.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
66960
67133
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
66961
|
-
|
|
67134
|
+
import_node_path72.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
66962
67135
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
66963
67136
|
];
|
|
66964
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
67137
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
66965
67138
|
if (dispatchServerScriptPath) {
|
|
66966
|
-
const dispatchLogPath =
|
|
67139
|
+
const dispatchLogPath = import_node_path72.default.join(logDir, "dispatch-mcp-server.log");
|
|
66967
67140
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
66968
67141
|
dataDir: config.dataDir,
|
|
66969
67142
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -66983,12 +67156,12 @@ async function startDaemon(config) {
|
|
|
66983
67156
|
});
|
|
66984
67157
|
}
|
|
66985
67158
|
const ticketServerCandidates = [
|
|
66986
|
-
|
|
66987
|
-
|
|
67159
|
+
import_node_path72.default.join(here, "ticket", "mcp-server.cjs"),
|
|
67160
|
+
import_node_path72.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
66988
67161
|
];
|
|
66989
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
67162
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
66990
67163
|
if (ticketServerScriptPath) {
|
|
66991
|
-
const ticketLogPath =
|
|
67164
|
+
const ticketLogPath = import_node_path72.default.join(logDir, "ticket-mcp-server.log");
|
|
66992
67165
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
66993
67166
|
dataDir: config.dataDir,
|
|
66994
67167
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -67010,12 +67183,12 @@ async function startDaemon(config) {
|
|
|
67010
67183
|
});
|
|
67011
67184
|
}
|
|
67012
67185
|
const shiftServerCandidates = [
|
|
67013
|
-
|
|
67014
|
-
|
|
67186
|
+
import_node_path72.default.join(here, "shift", "mcp-server.cjs"),
|
|
67187
|
+
import_node_path72.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
67015
67188
|
];
|
|
67016
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
67189
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67017
67190
|
if (shiftServerScriptPath) {
|
|
67018
|
-
const shiftLogPath =
|
|
67191
|
+
const shiftLogPath = import_node_path72.default.join(logDir, "shift-mcp-server.log");
|
|
67019
67192
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
67020
67193
|
dataDir: config.dataDir,
|
|
67021
67194
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -67036,12 +67209,12 @@ async function startDaemon(config) {
|
|
|
67036
67209
|
);
|
|
67037
67210
|
}
|
|
67038
67211
|
const inboxServerCandidates = [
|
|
67039
|
-
|
|
67040
|
-
|
|
67212
|
+
import_node_path72.default.join(here, "inbox", "mcp-server.cjs"),
|
|
67213
|
+
import_node_path72.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
67041
67214
|
];
|
|
67042
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
67215
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67043
67216
|
if (inboxServerScriptPath) {
|
|
67044
|
-
const inboxLogPath =
|
|
67217
|
+
const inboxLogPath = import_node_path72.default.join(logDir, "inbox-mcp-server.log");
|
|
67045
67218
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
67046
67219
|
dataDir: config.dataDir,
|
|
67047
67220
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -67062,10 +67235,10 @@ async function startDaemon(config) {
|
|
|
67062
67235
|
);
|
|
67063
67236
|
}
|
|
67064
67237
|
const peerOpsServerCandidates = [
|
|
67065
|
-
|
|
67066
|
-
|
|
67238
|
+
import_node_path72.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
67239
|
+
import_node_path72.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
67067
67240
|
];
|
|
67068
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
67241
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67069
67242
|
if (peerOpsServerScriptPath) {
|
|
67070
67243
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
67071
67244
|
dataDir: config.dataDir,
|
|
@@ -67085,12 +67258,12 @@ async function startDaemon(config) {
|
|
|
67085
67258
|
);
|
|
67086
67259
|
}
|
|
67087
67260
|
const rpcToolServerCandidates = [
|
|
67088
|
-
|
|
67089
|
-
|
|
67261
|
+
import_node_path72.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
67262
|
+
import_node_path72.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
67090
67263
|
];
|
|
67091
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
67264
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
67092
67265
|
if (rpcToolServerScriptPath) {
|
|
67093
|
-
const rpcToolLogPath =
|
|
67266
|
+
const rpcToolLogPath = import_node_path72.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
67094
67267
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
67095
67268
|
dataDir: config.dataDir,
|
|
67096
67269
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -67111,7 +67284,7 @@ async function startDaemon(config) {
|
|
|
67111
67284
|
);
|
|
67112
67285
|
}
|
|
67113
67286
|
const shiftStore = createShiftStore({
|
|
67114
|
-
filePath:
|
|
67287
|
+
filePath: import_node_path72.default.join(config.dataDir, "shift.json"),
|
|
67115
67288
|
ownerIdProvider: () => ownerPrincipalId,
|
|
67116
67289
|
now: () => Date.now()
|
|
67117
67290
|
});
|
|
@@ -67133,7 +67306,7 @@ async function startDaemon(config) {
|
|
|
67133
67306
|
getAdapter,
|
|
67134
67307
|
historyReader: history,
|
|
67135
67308
|
dataDir: config.dataDir,
|
|
67136
|
-
personaRoot:
|
|
67309
|
+
personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
|
|
67137
67310
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
67138
67311
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
67139
67312
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -67187,10 +67360,10 @@ async function startDaemon(config) {
|
|
|
67187
67360
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
67188
67361
|
attachmentGroup: {
|
|
67189
67362
|
onFileEdit: (input) => {
|
|
67190
|
-
const absPath =
|
|
67363
|
+
const absPath = import_node_path72.default.isAbsolute(input.relPath) ? input.relPath : import_node_path72.default.join(input.cwd, input.relPath);
|
|
67191
67364
|
let size = 0;
|
|
67192
67365
|
try {
|
|
67193
|
-
size =
|
|
67366
|
+
size = import_node_fs53.default.statSync(absPath).size;
|
|
67194
67367
|
} catch (err) {
|
|
67195
67368
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
67196
67369
|
sessionId: input.sessionId,
|
|
@@ -67220,9 +67393,9 @@ async function startDaemon(config) {
|
|
|
67220
67393
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
67221
67394
|
}
|
|
67222
67395
|
const projectsStore = new ProjectsStore({
|
|
67223
|
-
file:
|
|
67396
|
+
file: import_node_path72.default.join(config.dataDir, "projects.json"),
|
|
67224
67397
|
clawdDir: config.dataDir,
|
|
67225
|
-
codexStateFile:
|
|
67398
|
+
codexStateFile: import_node_path72.default.join(import_node_os26.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
67226
67399
|
logger
|
|
67227
67400
|
});
|
|
67228
67401
|
const observer = new SessionObserver({
|
|
@@ -67282,13 +67455,13 @@ async function startDaemon(config) {
|
|
|
67282
67455
|
screenIdleProbeLogger
|
|
67283
67456
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
67284
67457
|
registerAdapter("claude", claudeAdapter);
|
|
67285
|
-
const codexIsolatedHome =
|
|
67458
|
+
const codexIsolatedHome = import_node_path72.default.join(config.dataDir, "codex-home");
|
|
67286
67459
|
try {
|
|
67287
|
-
|
|
67460
|
+
import_node_fs53.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
67288
67461
|
for (const f of ["auth.json", "config.toml"]) {
|
|
67289
|
-
const link =
|
|
67290
|
-
const target =
|
|
67291
|
-
if (!
|
|
67462
|
+
const link = import_node_path72.default.join(codexIsolatedHome, f);
|
|
67463
|
+
const target = import_node_path72.default.join(import_node_os26.default.homedir(), ".codex", f);
|
|
67464
|
+
if (!import_node_fs53.default.existsSync(link) && import_node_fs53.default.existsSync(target)) import_node_fs53.default.symlinkSync(target, link);
|
|
67292
67465
|
}
|
|
67293
67466
|
} catch (err) {
|
|
67294
67467
|
logger.warn("codex isolated home setup failed", { err: String(err) });
|
|
@@ -67301,11 +67474,11 @@ async function startDaemon(config) {
|
|
|
67301
67474
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
67302
67475
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
67303
67476
|
cwd,
|
|
67304
|
-
personaRoot:
|
|
67477
|
+
personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
|
|
67305
67478
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
67306
67479
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
67307
67480
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
67308
|
-
sharedHome:
|
|
67481
|
+
sharedHome: import_node_path72.default.join(import_node_os26.default.homedir(), ".codex"),
|
|
67309
67482
|
isolatedHome: codexIsolatedHome
|
|
67310
67483
|
})
|
|
67311
67484
|
})
|
|
@@ -67589,11 +67762,11 @@ async function startDaemon(config) {
|
|
|
67589
67762
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
67590
67763
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
67591
67764
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
67592
|
-
personaRoot:
|
|
67765
|
+
personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
|
|
67593
67766
|
usersRoot
|
|
67594
67767
|
},
|
|
67595
67768
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
67596
|
-
personaRoot:
|
|
67769
|
+
personaRoot: import_node_path72.default.join(config.dataDir, "personas"),
|
|
67597
67770
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
67598
67771
|
usersRoot,
|
|
67599
67772
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -67692,11 +67865,11 @@ async function startDaemon(config) {
|
|
|
67692
67865
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
67693
67866
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
67694
67867
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
67695
|
-
appBuilderPersonaRoot:
|
|
67868
|
+
appBuilderPersonaRoot: import_node_path72.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
67696
67869
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
67697
|
-
deployKitRoot:
|
|
67870
|
+
deployKitRoot: import_node_path72.default.join(config.dataDir, "deploy-kit"),
|
|
67698
67871
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
67699
|
-
resolvePersonaRoot: (personaId2) =>
|
|
67872
|
+
resolvePersonaRoot: (personaId2) => import_node_path72.default.join(config.dataDir, "personas", personaId2),
|
|
67700
67873
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
67701
67874
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
67702
67875
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -67751,7 +67924,7 @@ async function startDaemon(config) {
|
|
|
67751
67924
|
sourceSessionId: args.sourceSessionId
|
|
67752
67925
|
});
|
|
67753
67926
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
67754
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
67927
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os26.default.homedir());
|
|
67755
67928
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
67756
67929
|
dispatchId: args.dispatchId,
|
|
67757
67930
|
sourceJsonlPath,
|
|
@@ -67817,7 +67990,7 @@ async function startDaemon(config) {
|
|
|
67817
67990
|
});
|
|
67818
67991
|
shiftScheduler.start();
|
|
67819
67992
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
67820
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
67993
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path72.default.join(config.dataDir, "personas"));
|
|
67821
67994
|
const larkBotCloud = createLarkBotCloudClient({
|
|
67822
67995
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
67823
67996
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -67831,7 +68004,7 @@ async function startDaemon(config) {
|
|
|
67831
68004
|
store: larkBotStore,
|
|
67832
68005
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
67833
68006
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
67834
|
-
mediaRootFor: (chatId) =>
|
|
68007
|
+
mediaRootFor: (chatId) => import_node_path72.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
67835
68008
|
isShuttingDown: () => larkDraining,
|
|
67836
68009
|
logger: {
|
|
67837
68010
|
warn: (msg) => logger.warn(msg),
|
|
@@ -68136,8 +68309,8 @@ async function startDaemon(config) {
|
|
|
68136
68309
|
const lines = [
|
|
68137
68310
|
`Tunnel: ${r.url}`,
|
|
68138
68311
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
68139
|
-
`Frpc config: ${
|
|
68140
|
-
`Frpc log: ${
|
|
68312
|
+
`Frpc config: ${import_node_path72.default.join(config.dataDir, "frpc.toml")}`,
|
|
68313
|
+
`Frpc log: ${import_node_path72.default.join(logDir, "frpc.log")}`
|
|
68141
68314
|
];
|
|
68142
68315
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
68143
68316
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -68150,8 +68323,8 @@ ${bar}
|
|
|
68150
68323
|
|
|
68151
68324
|
`);
|
|
68152
68325
|
try {
|
|
68153
|
-
const connectPath =
|
|
68154
|
-
|
|
68326
|
+
const connectPath = import_node_path72.default.join(config.dataDir, "connect.txt");
|
|
68327
|
+
import_node_fs53.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
68155
68328
|
} catch {
|
|
68156
68329
|
}
|
|
68157
68330
|
} catch (err) {
|
|
@@ -68238,9 +68411,9 @@ ${bar}
|
|
|
68238
68411
|
};
|
|
68239
68412
|
}
|
|
68240
68413
|
function migrateDropPersonsDir(dataDir) {
|
|
68241
|
-
const dir =
|
|
68414
|
+
const dir = import_node_path72.default.join(dataDir, "persons");
|
|
68242
68415
|
try {
|
|
68243
|
-
|
|
68416
|
+
import_node_fs53.default.rmSync(dir, { recursive: true, force: true });
|
|
68244
68417
|
} catch {
|
|
68245
68418
|
}
|
|
68246
68419
|
}
|