@clawos-dev/clawd 0.2.381 → 0.2.383
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 +1578 -552
- package/dist/dispatch/mcp-server.cjs +251 -2
- package/dist/persona-defaults/persona-master/.claude/agents/line-watcher.md +47 -0
- package/dist/persona-defaults/persona-master/CLAUDE.md +151 -0
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-BYXoorJY.js +559 -0
- package/dist/share-ui/assets/guest-Bu1Swx93.css +32 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-B0hI591-.js +0 -559
- package/dist/share-ui/assets/guest-BHxPh0N8.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: path89, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path89, ...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, path89, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path89;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -6202,7 +6202,11 @@ var init_dispatch = __esm({
|
|
|
6202
6202
|
// 时 daemon 层静默丢弃(避免半途改 label 造成 sidebar 抖动)。
|
|
6203
6203
|
// 上限 60 字符——sidebar 显示 tolerance,卡在 dispatch 入口即可。
|
|
6204
6204
|
// 协议层不硬拒 sessionLabel + dispatchId 同传,保留 forward-compat。
|
|
6205
|
-
sessionLabel: external_exports.string().min(1).max(60).optional()
|
|
6205
|
+
sessionLabel: external_exports.string().min(1).max(60).optional(),
|
|
6206
|
+
// 上层消费者(Master)挂载话题/线语义:topicId / lineId / 验收标准 / rejectCount 等。
|
|
6207
|
+
// daemon **不解释**内容,只透传进台账行 DispatchRecord.meta(新开)或与既有 meta
|
|
6208
|
+
// merge(续派,见 handlers/persona-dispatch.ts)。与台账行 meta 同款自由 JSON 契约。
|
|
6209
|
+
meta: external_exports.record(external_exports.unknown()).optional()
|
|
6206
6210
|
}).refine((v2) => v2.targetPersona !== void 0 || v2.dispatchId !== void 0, {
|
|
6207
6211
|
message: "either targetPersona (new dispatch) or dispatchId (follow-up) is required"
|
|
6208
6212
|
}).refine((v2) => !(v2.dispatchId !== void 0 && v2.targetDeviceId !== void 0), {
|
|
@@ -6594,6 +6598,202 @@ var init_shift_internal = __esm({
|
|
|
6594
6598
|
}
|
|
6595
6599
|
});
|
|
6596
6600
|
|
|
6601
|
+
// ../protocol/src/channel.ts
|
|
6602
|
+
var ChannelSchema, nonBlank, ChannelCreateArgsSchema, ChannelUpdateArgsSchema, ChannelDeleteArgsSchema, ChannelListResultSchema, ChannelResultSchema, ChannelDeleteResultSchema;
|
|
6603
|
+
var init_channel = __esm({
|
|
6604
|
+
"../protocol/src/channel.ts"() {
|
|
6605
|
+
"use strict";
|
|
6606
|
+
init_zod();
|
|
6607
|
+
ChannelSchema = external_exports.object({
|
|
6608
|
+
id: external_exports.string().min(1),
|
|
6609
|
+
name: external_exports.string().min(1),
|
|
6610
|
+
/** 该频道里可被派活的 persona */
|
|
6611
|
+
memberPersonaIds: external_exports.array(external_exports.string().min(1)),
|
|
6612
|
+
/** 人类成员(contact deviceId);M2 只存不用,P1 异步询问才消费 */
|
|
6613
|
+
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)),
|
|
6614
|
+
createdAt: external_exports.string().min(1),
|
|
6615
|
+
updatedAt: external_exports.string().min(1)
|
|
6616
|
+
});
|
|
6617
|
+
nonBlank = external_exports.string().trim().min(1);
|
|
6618
|
+
ChannelCreateArgsSchema = external_exports.object({
|
|
6619
|
+
name: nonBlank,
|
|
6620
|
+
memberPersonaIds: external_exports.array(external_exports.string().min(1)).default([]),
|
|
6621
|
+
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).default([])
|
|
6622
|
+
});
|
|
6623
|
+
ChannelUpdateArgsSchema = external_exports.object({
|
|
6624
|
+
channelId: external_exports.string().min(1),
|
|
6625
|
+
name: nonBlank.optional(),
|
|
6626
|
+
memberPersonaIds: external_exports.array(external_exports.string().min(1)).optional(),
|
|
6627
|
+
memberContactDeviceIds: external_exports.array(external_exports.string().min(1)).optional()
|
|
6628
|
+
});
|
|
6629
|
+
ChannelDeleteArgsSchema = external_exports.object({ channelId: external_exports.string().min(1) });
|
|
6630
|
+
ChannelListResultSchema = external_exports.object({ channels: external_exports.array(ChannelSchema) });
|
|
6631
|
+
ChannelResultSchema = external_exports.object({ channel: ChannelSchema });
|
|
6632
|
+
ChannelDeleteResultSchema = external_exports.object({
|
|
6633
|
+
ok: external_exports.literal(true),
|
|
6634
|
+
/** 一并清掉的已结束话题数:不留悬挂记录,也不静默——删了几条明确回给调用方 */
|
|
6635
|
+
removedTopics: external_exports.number().int().min(0)
|
|
6636
|
+
});
|
|
6637
|
+
}
|
|
6638
|
+
});
|
|
6639
|
+
|
|
6640
|
+
// ../protocol/src/topic.ts
|
|
6641
|
+
var nonBlank2, TOPIC_STATES, TopicStateSchema, TopicActivityEntrySchema, TopicLineMetaSchema, TopicSchema, TopicLineViewSchema, TopicListArgsSchema, TopicGetArgsSchema, TopicCreateArgsSchema, TopicSetPlanArgsSchema, TopicAppendArgsSchema, TopicRejectArgsSchema, TopicAcceptArgsSchema, TopicCloseArgsSchema, TopicListItemSchema, TopicListResultSchema, TopicGetResultSchema, TopicCreateResultSchema, TopicRejectResultSchema, TopicAcceptResultSchema, TopicResultSchema;
|
|
6642
|
+
var init_topic = __esm({
|
|
6643
|
+
"../protocol/src/topic.ts"() {
|
|
6644
|
+
"use strict";
|
|
6645
|
+
init_zod();
|
|
6646
|
+
init_dispatch();
|
|
6647
|
+
nonBlank2 = external_exports.string().trim().min(1);
|
|
6648
|
+
TOPIC_STATES = ["planning", "running", "done", "archived"];
|
|
6649
|
+
TopicStateSchema = external_exports.enum(TOPIC_STATES);
|
|
6650
|
+
TopicActivityEntrySchema = external_exports.object({
|
|
6651
|
+
at: external_exports.string().min(1),
|
|
6652
|
+
actor: external_exports.string().min(1),
|
|
6653
|
+
action: external_exports.string().min(1),
|
|
6654
|
+
target: external_exports.string().optional(),
|
|
6655
|
+
reason: external_exports.string().min(1),
|
|
6656
|
+
/** 该动作确认的产出物(watcher 返回的 artifacts);影响面视图的唯一数据源 */
|
|
6657
|
+
artifacts: external_exports.array(nonBlank2).optional()
|
|
6658
|
+
});
|
|
6659
|
+
TopicLineMetaSchema = external_exports.object({
|
|
6660
|
+
rejectCount: external_exports.number().int().min(0),
|
|
6661
|
+
accepted: external_exports.boolean().default(false)
|
|
6662
|
+
});
|
|
6663
|
+
TopicSchema = external_exports.object({
|
|
6664
|
+
id: external_exports.string().min(1),
|
|
6665
|
+
channelId: external_exports.string().min(1),
|
|
6666
|
+
title: external_exports.string(),
|
|
6667
|
+
/** 该话题的 Master session;topic:create 时一并起,1:1 */
|
|
6668
|
+
masterSessionId: external_exports.string().min(1),
|
|
6669
|
+
goal: external_exports.string(),
|
|
6670
|
+
boundaries: external_exports.string(),
|
|
6671
|
+
acceptanceCriteria: external_exports.array(external_exports.string()),
|
|
6672
|
+
activity: external_exports.array(TopicActivityEntrySchema),
|
|
6673
|
+
/** lineId -> 线级元数据 */
|
|
6674
|
+
lineMeta: external_exports.record(TopicLineMetaSchema),
|
|
6675
|
+
state: TopicStateSchema,
|
|
6676
|
+
createdAt: external_exports.string().min(1),
|
|
6677
|
+
updatedAt: external_exports.string().min(1)
|
|
6678
|
+
});
|
|
6679
|
+
TopicLineViewSchema = external_exports.object({
|
|
6680
|
+
lineId: external_exports.string().min(1),
|
|
6681
|
+
dispatchId: external_exports.string().min(1),
|
|
6682
|
+
workerSessionId: external_exports.string().optional(),
|
|
6683
|
+
assignee: external_exports.string().min(1),
|
|
6684
|
+
focus: external_exports.string(),
|
|
6685
|
+
status: DispatchStatusSchema,
|
|
6686
|
+
acceptance: external_exports.array(external_exports.string()),
|
|
6687
|
+
rejectCount: external_exports.number().int().min(0),
|
|
6688
|
+
/** 已被 Master 判定合格(`topic:accept`)。UI 的「合格」态靠它,不是猜的 */
|
|
6689
|
+
accepted: external_exports.boolean()
|
|
6690
|
+
});
|
|
6691
|
+
TopicListArgsSchema = external_exports.object({ channelId: external_exports.string().min(1) });
|
|
6692
|
+
TopicGetArgsSchema = external_exports.object({
|
|
6693
|
+
topicId: external_exports.string().min(1).optional(),
|
|
6694
|
+
sessionId: external_exports.string().min(1).optional()
|
|
6695
|
+
}).refine((v2) => v2.topicId !== void 0 || v2.sessionId !== void 0, {
|
|
6696
|
+
message: "either topicId or sessionId is required"
|
|
6697
|
+
});
|
|
6698
|
+
TopicCreateArgsSchema = external_exports.object({
|
|
6699
|
+
channelId: external_exports.string().min(1),
|
|
6700
|
+
/** 可后补:spike 动线是老板先说一句话,标题随 topic:setPlan 落 */
|
|
6701
|
+
title: nonBlank2.optional()
|
|
6702
|
+
});
|
|
6703
|
+
TopicSetPlanArgsSchema = external_exports.object({
|
|
6704
|
+
topicId: external_exports.string().min(1),
|
|
6705
|
+
title: nonBlank2.optional(),
|
|
6706
|
+
goal: nonBlank2,
|
|
6707
|
+
boundaries: external_exports.string(),
|
|
6708
|
+
// 没有验收标准就不开工(PRD §6.1):否则 Master 无法自主判定收敛,
|
|
6709
|
+
// 只能照单全收 worker 自述,退化成传话筒。
|
|
6710
|
+
acceptanceCriteria: external_exports.array(nonBlank2).min(1)
|
|
6711
|
+
});
|
|
6712
|
+
TopicAppendArgsSchema = external_exports.object({
|
|
6713
|
+
topicId: external_exports.string().min(1),
|
|
6714
|
+
action: nonBlank2,
|
|
6715
|
+
target: nonBlank2.optional(),
|
|
6716
|
+
reason: nonBlank2,
|
|
6717
|
+
/** 该动作确认的产出物;影响面视图只吃这个字段 */
|
|
6718
|
+
artifacts: external_exports.array(nonBlank2).optional()
|
|
6719
|
+
});
|
|
6720
|
+
TopicRejectArgsSchema = external_exports.object({
|
|
6721
|
+
topicId: external_exports.string().min(1),
|
|
6722
|
+
lineId: nonBlank2,
|
|
6723
|
+
reason: nonBlank2
|
|
6724
|
+
});
|
|
6725
|
+
TopicAcceptArgsSchema = external_exports.object({
|
|
6726
|
+
topicId: external_exports.string().min(1),
|
|
6727
|
+
lineId: nonBlank2,
|
|
6728
|
+
/** 凭什么判合格(逐条标准对应到什么证据)——与打回同样必填 */
|
|
6729
|
+
reason: nonBlank2,
|
|
6730
|
+
/** watcher 认定的产出物,一并进影响面 */
|
|
6731
|
+
artifacts: external_exports.array(nonBlank2).optional()
|
|
6732
|
+
});
|
|
6733
|
+
TopicCloseArgsSchema = external_exports.object({
|
|
6734
|
+
topicId: external_exports.string().min(1),
|
|
6735
|
+
state: external_exports.enum(["done", "archived"])
|
|
6736
|
+
});
|
|
6737
|
+
TopicListItemSchema = TopicSchema.extend({
|
|
6738
|
+
lineCount: external_exports.number().int().min(0)
|
|
6739
|
+
});
|
|
6740
|
+
TopicListResultSchema = external_exports.object({ topics: external_exports.array(TopicListItemSchema) });
|
|
6741
|
+
TopicGetResultSchema = external_exports.object({
|
|
6742
|
+
topic: TopicSchema,
|
|
6743
|
+
lines: external_exports.array(TopicLineViewSchema)
|
|
6744
|
+
});
|
|
6745
|
+
TopicCreateResultSchema = external_exports.object({
|
|
6746
|
+
topicId: external_exports.string().min(1),
|
|
6747
|
+
masterSessionId: external_exports.string().min(1)
|
|
6748
|
+
});
|
|
6749
|
+
TopicRejectResultSchema = external_exports.object({
|
|
6750
|
+
rejectCount: external_exports.number().int().min(1),
|
|
6751
|
+
/** 连续两次打回仍不合格 → 必须上报老板(PRD §10.3),不靠 Master 自己数 */
|
|
6752
|
+
needsOwnerAttention: external_exports.boolean()
|
|
6753
|
+
});
|
|
6754
|
+
TopicAcceptResultSchema = external_exports.object({
|
|
6755
|
+
acceptedLines: external_exports.number().int().min(1),
|
|
6756
|
+
totalLines: external_exports.number().int().min(1),
|
|
6757
|
+
/** 全部线都合格了 → 可以收敛上报。由 daemon 数,不让 Master 自己盘 */
|
|
6758
|
+
allAccepted: external_exports.boolean()
|
|
6759
|
+
});
|
|
6760
|
+
TopicResultSchema = external_exports.object({ topic: TopicSchema });
|
|
6761
|
+
}
|
|
6762
|
+
});
|
|
6763
|
+
|
|
6764
|
+
// ../protocol/src/master.ts
|
|
6765
|
+
var LineDigestArgsSchema, LineDigestResultSchema, AUTHORITY_ACTIONS, AuthorityActionSchema, AuthorityRuleSchema, AuthorityTableSchema, AuthorityCheckArgsSchema, AuthorityCheckResultSchema;
|
|
6766
|
+
var init_master = __esm({
|
|
6767
|
+
"../protocol/src/master.ts"() {
|
|
6768
|
+
"use strict";
|
|
6769
|
+
init_zod();
|
|
6770
|
+
LineDigestArgsSchema = external_exports.object({
|
|
6771
|
+
/** 一条线 = 一条 dispatch;daemon 内部据此解析 worker session 与 transcript */
|
|
6772
|
+
dispatchId: external_exports.string().min(1)
|
|
6773
|
+
});
|
|
6774
|
+
LineDigestResultSchema = external_exports.object({
|
|
6775
|
+
digest: external_exports.string(),
|
|
6776
|
+
/** 抽取时是否因超上限被截断——watcher 据此避免"仅凭没看到就判 fail" */
|
|
6777
|
+
truncated: external_exports.boolean()
|
|
6778
|
+
});
|
|
6779
|
+
AUTHORITY_ACTIONS = ["ask", "allow", "deny"];
|
|
6780
|
+
AuthorityActionSchema = external_exports.enum(AUTHORITY_ACTIONS);
|
|
6781
|
+
AuthorityRuleSchema = external_exports.object({
|
|
6782
|
+
id: external_exports.string().min(1),
|
|
6783
|
+
desc: external_exports.string().min(1),
|
|
6784
|
+
action: AuthorityActionSchema
|
|
6785
|
+
});
|
|
6786
|
+
AuthorityTableSchema = external_exports.object({ rules: external_exports.array(AuthorityRuleSchema) });
|
|
6787
|
+
AuthorityCheckArgsSchema = external_exports.object({ ruleId: external_exports.string().min(1) });
|
|
6788
|
+
AuthorityCheckResultSchema = external_exports.object({
|
|
6789
|
+
action: AuthorityActionSchema,
|
|
6790
|
+
desc: external_exports.string(),
|
|
6791
|
+
/** 裁决出处:'table' / 'default' / 'fallback:<原因>'。异常兜底成 ask 时靠它说明为什么 */
|
|
6792
|
+
source: external_exports.string().min(1)
|
|
6793
|
+
});
|
|
6794
|
+
}
|
|
6795
|
+
});
|
|
6796
|
+
|
|
6597
6797
|
// ../protocol/src/github.ts
|
|
6598
6798
|
var GITHUB_PR_ROLES, REPO_SEGMENT, owner, repo, number, GithubPrListArgs, GithubPrDetailArgs, GithubPrMergeArgs, GithubPrCommentArgs, GithubPrSetReadyArgs, GithubCollaboratorsArgs, GithubPrRequestReviewersArgs;
|
|
6599
6799
|
var init_github = __esm({
|
|
@@ -8025,6 +8225,9 @@ var init_methods = __esm({
|
|
|
8025
8225
|
init_inbox();
|
|
8026
8226
|
init_peer_exec();
|
|
8027
8227
|
init_shift_internal();
|
|
8228
|
+
init_channel();
|
|
8229
|
+
init_topic();
|
|
8230
|
+
init_master();
|
|
8028
8231
|
init_github();
|
|
8029
8232
|
init_lark_bot_schemas();
|
|
8030
8233
|
init_onboarding_schemas();
|
|
@@ -8213,6 +8416,68 @@ var init_methods = __esm({
|
|
|
8213
8416
|
summary: "\u5217\u51FA owner \u7684\u5168\u90E8 shift\uFF08\u6392\u73ED\uFF09\uFF0C\u7ED9 UI \u65E5\u5386\u6E32\u67D3\u7528\uFF1Bowner-only",
|
|
8214
8417
|
args: NO_ARGS
|
|
8215
8418
|
},
|
|
8419
|
+
// ---- channel:*(Channel × Master:话题的聚合,纯组织单位)----
|
|
8420
|
+
"channel:list": {
|
|
8421
|
+
summary: "\u5217\u51FA\u5168\u90E8\u9891\u9053\uFF08Channel \xD7 Master \u7684\u7EC4\u7EC7\u5355\u4F4D\uFF1A\u6210\u5458\u540D\u5355 + \u8BDD\u9898\u7684\u805A\u5408\uFF09\uFF1Bowner-only\u3002\u65E0\u53C2\u6570",
|
|
8422
|
+
args: NO_ARGS
|
|
8423
|
+
},
|
|
8424
|
+
"channel:create": {
|
|
8425
|
+
summary: "\u5EFA\u9891\u9053\uFF1Aname \u975E\u7A7A\uFF0C\u6210\u5458 persona / \u8054\u7CFB\u4EBA\u53EF\u7A7A\u3002\u8FD4\u56DE\u65B0\u5EFA\u7684 Channel",
|
|
8426
|
+
args: ChannelCreateArgsSchema
|
|
8427
|
+
},
|
|
8428
|
+
"channel:update": {
|
|
8429
|
+
summary: "\u6539\u9891\u9053\uFF1AchannelId \u5FC5\u586B\uFF0Cname / \u6210\u5458\u5217\u8868\u6309\u9700\u5C40\u90E8\u66F4\u65B0",
|
|
8430
|
+
args: ChannelUpdateArgsSchema
|
|
8431
|
+
},
|
|
8432
|
+
"channel:delete": {
|
|
8433
|
+
summary: "\u5220\u9891\u9053\uFF1B\u5176\u4E0B\u4ECD\u6709\u672A\u7ED3\u675F\u8BDD\u9898\u65F6\u62D2\u7EDD\uFF08fail-fast\uFF0C\u4E0D\u7EA7\u8054\u5220\u8BDD\u9898\uFF09",
|
|
8434
|
+
args: ChannelDeleteArgsSchema
|
|
8435
|
+
},
|
|
8436
|
+
// ---- topic:*(话题:一个任务的容器;一个话题 = 一个 Master session)----
|
|
8437
|
+
"topic:list": {
|
|
8438
|
+
summary: "\u5217\u67D0\u9891\u9053\u4E0B\u5168\u90E8\u8BDD\u9898\uFF08\u542B\u72B6\u6001\uFF0C\u4F9B\u9891\u9053 flyout \u5217\u8868\uFF09",
|
|
8439
|
+
args: TopicListArgsSchema
|
|
8440
|
+
},
|
|
8441
|
+
"topic:get": {
|
|
8442
|
+
summary: "\u8BDD\u9898\u8BE6\u60C5\uFF1A\u4E09\u8981\u7D20 + \u6D41\u6C34 + lines\uFF08lines \u4ECE dispatch \u53F0\u8D26 join\uFF0C\u4E0D\u5355\u72EC\u843D\u5E93\uFF09\u3002topicId \u6216 sessionId \u4E8C\u9009\u4E00\u2014\u2014Master \u4E0D\u5E26\u53C2\u8C03\uFF08\u6865\u81EA\u52A8\u586B sessionId\uFF09\u5373\u300C\u67E5\u6211\u7ED1\u7684\u90A3\u6761\u8BDD\u9898\u300D\uFF0C\u4E5F\u662F\u5B83\u88AB\u6E05\u7A7A\u540E\u91CD\u5EFA\u73B0\u573A\u7684\u5165\u53E3",
|
|
8443
|
+
args: TopicGetArgsSchema,
|
|
8444
|
+
argsConstraints: {
|
|
8445
|
+
anyOf: [{ required: ["topicId"] }, { required: ["sessionId"] }]
|
|
8446
|
+
}
|
|
8447
|
+
},
|
|
8448
|
+
"topic:create": {
|
|
8449
|
+
summary: "\u5EFA\u8BDD\u9898\u5E76\u4E00\u5E76\u8D77\u8BE5\u8BDD\u9898\u7684 Master session\uFF081:1\uFF09\uFF0C\u8FD4\u56DE topicId + masterSessionId\u3002title \u53EF\u540E\u8865",
|
|
8450
|
+
args: TopicCreateArgsSchema
|
|
8451
|
+
},
|
|
8452
|
+
"topic:setPlan": {
|
|
8453
|
+
summary: "\u63A5\u6D3B\u5BF9\u9F50\u540E\u9501\u5B9A\u4E09\u8981\u7D20\uFF1BacceptanceCriteria \u5FC5\u987B\u975E\u7A7A\u2014\u2014\u6CA1\u6709\u9A8C\u6536\u6807\u51C6\u5C31\u4E0D\u5F00\u5DE5",
|
|
8454
|
+
args: TopicSetPlanArgsSchema
|
|
8455
|
+
},
|
|
8456
|
+
"topic:append": {
|
|
8457
|
+
summary: '\u5F80\u8BDD\u9898\u6D41\u6C34\u8FFD\u52A0\u4E00\u6761\uFF1Breason \u5FC5\u586B\uFF08\u8001\u677F\u4E8B\u540E\u770B\u7684\u662F"\u51ED\u4EC0\u4E48\u8FD9\u4E48\u5224\u65AD"\uFF09',
|
|
8458
|
+
args: TopicAppendArgsSchema
|
|
8459
|
+
},
|
|
8460
|
+
"topic:reject": {
|
|
8461
|
+
summary: "\u6253\u56DE\u67D0\u6761\u7EBF\uFF1A\u8BA1\u6570 +1 \u5E76\u540C\u6B65\u843D\u4E00\u6761\u6D41\u6C34\uFF1Breason \u5FC5\u586B\u3002\u8FD4\u56DE rejectCount \u4E0E needsOwnerAttention\uFF08\u22652 \u5373 true\uFF09",
|
|
8462
|
+
args: TopicRejectArgsSchema
|
|
8463
|
+
},
|
|
8464
|
+
"topic:accept": {
|
|
8465
|
+
summary: "\u5224\u67D0\u6761\u7EBF\u5408\u683C\uFF1A\u7F6E accepted \u5E76\u540C\u6B65\u843D\u4E00\u6761\u6D41\u6C34\uFF1Breason \u5FC5\u586B\uFF08\u4E0E\u6253\u56DE\u5BF9\u79F0\uFF0C\u53EA\u8BB0\u6253\u56DE\u7B49\u4E8E\u53EA\u8BB0\u5206\u5B50\uFF09\u3002\u8FD4\u56DE acceptedLines / totalLines / allAccepted\uFF0C\u6536\u655B\u65F6\u673A\u7531 daemon \u6570\u4E0D\u7531 Master \u76D8",
|
|
8466
|
+
args: TopicAcceptArgsSchema
|
|
8467
|
+
},
|
|
8468
|
+
"topic:close": {
|
|
8469
|
+
summary: "\u6536\u655B\u8BDD\u9898\uFF1Astate \u7F6E done / archived",
|
|
8470
|
+
args: TopicCloseArgsSchema
|
|
8471
|
+
},
|
|
8472
|
+
// ---- line:digest / master:*(核验与授权,Master 经 clawd-rpc 桥调)----
|
|
8473
|
+
"line:digest": {
|
|
8474
|
+
summary: "\u628A\u4E00\u6761\u7EBF\uFF08dispatch\uFF09\u7684 worker transcript \u62BD\u6210 \u226420KB digest\uFF1A\u6539\u52A8\u8FC7\u7684\u6587\u4EF6 / \u6267\u884C\u8FC7\u7684\u547D\u4EE4 / \u6210\u529F\u547D\u4EE4\u8F93\u51FA\u6458\u5F55 / \u62A5\u9519\u805A\u5408 / \u5C3E\u90E8 assistant \u8F93\u51FA\u3002\u6838\u9A8C subagent \u7528\u5B83\uFF0C\u907F\u514D\u76F4\u63A5\u8BFB\u53EF\u8FBE 10MB \u7684\u539F\u59CB\u6D41",
|
|
8475
|
+
args: LineDigestArgsSchema
|
|
8476
|
+
},
|
|
8477
|
+
"master:authorityCheck": {
|
|
8478
|
+
summary: "\u67E5 Master \u7684\u6388\u6743\u8BBE\u5B9A\uFF08\u5168\u5C40\u4E00\u5957\uFF09\uFF1A\u8FD4\u56DE ask / allow / deny\u3002\u8868\u7F3A\u5931\u3001\u8BFB\u574F\u3001\u7ED3\u6784\u4E0D\u5BF9\u3001action \u62FC\u9519\u3001id \u672A\u767B\u8BB0\uFF0C\u4E00\u5F8B\u88C1\u51B3 ask",
|
|
8479
|
+
args: AuthorityCheckArgsSchema
|
|
8480
|
+
},
|
|
8216
8481
|
"github:status": {
|
|
8217
8482
|
summary: "\u63A2\u6D4B\u672C\u673A gh CLI\uFF08PR \u6536\u4EF6\u7BB1\u524D\u7F6E\uFF09\uFF1A\u662F\u5426\u5B89\u88C5\u3001\u662F\u5426\u5DF2\u767B\u5F55 github.com\u3001\u767B\u5F55\u540D\u3002\u65E0\u53C2\u6570",
|
|
8218
8483
|
args: NO_ARGS
|
|
@@ -8743,6 +9008,9 @@ var init_runtime = __esm({
|
|
|
8743
9008
|
init_extension();
|
|
8744
9009
|
init_feishu_auth();
|
|
8745
9010
|
init_dispatch();
|
|
9011
|
+
init_channel();
|
|
9012
|
+
init_topic();
|
|
9013
|
+
init_master();
|
|
8746
9014
|
init_log();
|
|
8747
9015
|
init_visitor_schemas();
|
|
8748
9016
|
init_github();
|
|
@@ -9024,8 +9292,8 @@ var require_req = __commonJS({
|
|
|
9024
9292
|
if (req.originalUrl) {
|
|
9025
9293
|
_req.url = req.originalUrl;
|
|
9026
9294
|
} else {
|
|
9027
|
-
const
|
|
9028
|
-
_req.url = typeof
|
|
9295
|
+
const path89 = req.path;
|
|
9296
|
+
_req.url = typeof path89 === "string" ? path89 : req.url ? req.url.path || req.url : void 0;
|
|
9029
9297
|
}
|
|
9030
9298
|
if (req.query) {
|
|
9031
9299
|
_req.query = req.query;
|
|
@@ -9190,14 +9458,14 @@ var require_redact = __commonJS({
|
|
|
9190
9458
|
}
|
|
9191
9459
|
return obj;
|
|
9192
9460
|
}
|
|
9193
|
-
function parsePath(
|
|
9461
|
+
function parsePath(path89) {
|
|
9194
9462
|
const parts = [];
|
|
9195
9463
|
let current = "";
|
|
9196
9464
|
let inBrackets = false;
|
|
9197
9465
|
let inQuotes = false;
|
|
9198
9466
|
let quoteChar = "";
|
|
9199
|
-
for (let i = 0; i <
|
|
9200
|
-
const char =
|
|
9467
|
+
for (let i = 0; i < path89.length; i++) {
|
|
9468
|
+
const char = path89[i];
|
|
9201
9469
|
if (!inBrackets && char === ".") {
|
|
9202
9470
|
if (current) {
|
|
9203
9471
|
parts.push(current);
|
|
@@ -9328,10 +9596,10 @@ var require_redact = __commonJS({
|
|
|
9328
9596
|
return current;
|
|
9329
9597
|
}
|
|
9330
9598
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9331
|
-
for (const
|
|
9332
|
-
const parts = parsePath(
|
|
9599
|
+
for (const path89 of paths) {
|
|
9600
|
+
const parts = parsePath(path89);
|
|
9333
9601
|
if (parts.includes("*")) {
|
|
9334
|
-
redactWildcardPath(obj, parts, censor,
|
|
9602
|
+
redactWildcardPath(obj, parts, censor, path89, remove);
|
|
9335
9603
|
} else {
|
|
9336
9604
|
if (remove) {
|
|
9337
9605
|
removeKey(obj, parts);
|
|
@@ -9416,8 +9684,8 @@ var require_redact = __commonJS({
|
|
|
9416
9684
|
}
|
|
9417
9685
|
} else {
|
|
9418
9686
|
if (afterWildcard.includes("*")) {
|
|
9419
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9420
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9687
|
+
const wrappedCensor = typeof censor === "function" ? (value, path89) => {
|
|
9688
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path89];
|
|
9421
9689
|
return censor(value, fullPath);
|
|
9422
9690
|
} : censor;
|
|
9423
9691
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9452,8 +9720,8 @@ var require_redact = __commonJS({
|
|
|
9452
9720
|
return null;
|
|
9453
9721
|
}
|
|
9454
9722
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9455
|
-
for (const
|
|
9456
|
-
const parts = parsePath(
|
|
9723
|
+
for (const path89 of pathsToClone) {
|
|
9724
|
+
const parts = parsePath(path89);
|
|
9457
9725
|
let current = pathStructure;
|
|
9458
9726
|
for (let i = 0; i < parts.length; i++) {
|
|
9459
9727
|
const part = parts[i];
|
|
@@ -9505,24 +9773,24 @@ var require_redact = __commonJS({
|
|
|
9505
9773
|
}
|
|
9506
9774
|
return cloneSelectively(obj, pathStructure);
|
|
9507
9775
|
}
|
|
9508
|
-
function validatePath(
|
|
9509
|
-
if (typeof
|
|
9776
|
+
function validatePath(path89) {
|
|
9777
|
+
if (typeof path89 !== "string") {
|
|
9510
9778
|
throw new Error("Paths must be (non-empty) strings");
|
|
9511
9779
|
}
|
|
9512
|
-
if (
|
|
9780
|
+
if (path89 === "") {
|
|
9513
9781
|
throw new Error("Invalid redaction path ()");
|
|
9514
9782
|
}
|
|
9515
|
-
if (
|
|
9516
|
-
throw new Error(`Invalid redaction path (${
|
|
9783
|
+
if (path89.includes("..")) {
|
|
9784
|
+
throw new Error(`Invalid redaction path (${path89})`);
|
|
9517
9785
|
}
|
|
9518
|
-
if (
|
|
9519
|
-
throw new Error(`Invalid redaction path (${
|
|
9786
|
+
if (path89.includes(",")) {
|
|
9787
|
+
throw new Error(`Invalid redaction path (${path89})`);
|
|
9520
9788
|
}
|
|
9521
9789
|
let bracketCount = 0;
|
|
9522
9790
|
let inQuotes = false;
|
|
9523
9791
|
let quoteChar = "";
|
|
9524
|
-
for (let i = 0; i <
|
|
9525
|
-
const char =
|
|
9792
|
+
for (let i = 0; i < path89.length; i++) {
|
|
9793
|
+
const char = path89[i];
|
|
9526
9794
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9527
9795
|
if (!inQuotes) {
|
|
9528
9796
|
inQuotes = true;
|
|
@@ -9536,20 +9804,20 @@ var require_redact = __commonJS({
|
|
|
9536
9804
|
} else if (char === "]" && !inQuotes) {
|
|
9537
9805
|
bracketCount--;
|
|
9538
9806
|
if (bracketCount < 0) {
|
|
9539
|
-
throw new Error(`Invalid redaction path (${
|
|
9807
|
+
throw new Error(`Invalid redaction path (${path89})`);
|
|
9540
9808
|
}
|
|
9541
9809
|
}
|
|
9542
9810
|
}
|
|
9543
9811
|
if (bracketCount !== 0) {
|
|
9544
|
-
throw new Error(`Invalid redaction path (${
|
|
9812
|
+
throw new Error(`Invalid redaction path (${path89})`);
|
|
9545
9813
|
}
|
|
9546
9814
|
}
|
|
9547
9815
|
function validatePaths(paths) {
|
|
9548
9816
|
if (!Array.isArray(paths)) {
|
|
9549
9817
|
throw new TypeError("paths must be an array");
|
|
9550
9818
|
}
|
|
9551
|
-
for (const
|
|
9552
|
-
validatePath(
|
|
9819
|
+
for (const path89 of paths) {
|
|
9820
|
+
validatePath(path89);
|
|
9553
9821
|
}
|
|
9554
9822
|
}
|
|
9555
9823
|
function slowRedact(options = {}) {
|
|
@@ -9717,8 +9985,8 @@ var require_redaction = __commonJS({
|
|
|
9717
9985
|
if (shape[k2] === null) {
|
|
9718
9986
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9719
9987
|
} else {
|
|
9720
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9721
|
-
return censor(value, [k2, ...
|
|
9988
|
+
const wrappedCensor = typeof censor === "function" ? (value, path89) => {
|
|
9989
|
+
return censor(value, [k2, ...path89]);
|
|
9722
9990
|
} : censor;
|
|
9723
9991
|
o[k2] = Redact({
|
|
9724
9992
|
paths: shape[k2],
|
|
@@ -9936,10 +10204,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
9936
10204
|
var require_sonic_boom = __commonJS({
|
|
9937
10205
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
9938
10206
|
"use strict";
|
|
9939
|
-
var
|
|
10207
|
+
var fs79 = require("fs");
|
|
9940
10208
|
var EventEmitter3 = require("events");
|
|
9941
10209
|
var inherits = require("util").inherits;
|
|
9942
|
-
var
|
|
10210
|
+
var path89 = require("path");
|
|
9943
10211
|
var sleep2 = require_atomic_sleep();
|
|
9944
10212
|
var assert = require("assert");
|
|
9945
10213
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -9993,20 +10261,20 @@ var require_sonic_boom = __commonJS({
|
|
|
9993
10261
|
const mode = sonic.mode;
|
|
9994
10262
|
if (sonic.sync) {
|
|
9995
10263
|
try {
|
|
9996
|
-
if (sonic.mkdir)
|
|
9997
|
-
const fd =
|
|
10264
|
+
if (sonic.mkdir) fs79.mkdirSync(path89.dirname(file), { recursive: true });
|
|
10265
|
+
const fd = fs79.openSync(file, flags, mode);
|
|
9998
10266
|
fileOpened(null, fd);
|
|
9999
10267
|
} catch (err) {
|
|
10000
10268
|
fileOpened(err);
|
|
10001
10269
|
throw err;
|
|
10002
10270
|
}
|
|
10003
10271
|
} else if (sonic.mkdir) {
|
|
10004
|
-
|
|
10272
|
+
fs79.mkdir(path89.dirname(file), { recursive: true }, (err) => {
|
|
10005
10273
|
if (err) return fileOpened(err);
|
|
10006
|
-
|
|
10274
|
+
fs79.open(file, flags, mode, fileOpened);
|
|
10007
10275
|
});
|
|
10008
10276
|
} else {
|
|
10009
|
-
|
|
10277
|
+
fs79.open(file, flags, mode, fileOpened);
|
|
10010
10278
|
}
|
|
10011
10279
|
}
|
|
10012
10280
|
function SonicBoom(opts) {
|
|
@@ -10047,8 +10315,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10047
10315
|
this.flush = flushBuffer;
|
|
10048
10316
|
this.flushSync = flushBufferSync;
|
|
10049
10317
|
this._actualWrite = actualWriteBuffer;
|
|
10050
|
-
fsWriteSync = () =>
|
|
10051
|
-
fsWrite = () =>
|
|
10318
|
+
fsWriteSync = () => fs79.writeSync(this.fd, this._writingBuf);
|
|
10319
|
+
fsWrite = () => fs79.write(this.fd, this._writingBuf, this.release);
|
|
10052
10320
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10053
10321
|
this._writingBuf = "";
|
|
10054
10322
|
this.write = write;
|
|
@@ -10057,15 +10325,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10057
10325
|
this._actualWrite = actualWrite;
|
|
10058
10326
|
fsWriteSync = () => {
|
|
10059
10327
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10060
|
-
return
|
|
10328
|
+
return fs79.writeSync(this.fd, this._writingBuf);
|
|
10061
10329
|
}
|
|
10062
|
-
return
|
|
10330
|
+
return fs79.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10063
10331
|
};
|
|
10064
10332
|
fsWrite = () => {
|
|
10065
10333
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10066
|
-
return
|
|
10334
|
+
return fs79.write(this.fd, this._writingBuf, this.release);
|
|
10067
10335
|
}
|
|
10068
|
-
return
|
|
10336
|
+
return fs79.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10069
10337
|
};
|
|
10070
10338
|
} else {
|
|
10071
10339
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10122,7 +10390,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10122
10390
|
}
|
|
10123
10391
|
}
|
|
10124
10392
|
if (this._fsync) {
|
|
10125
|
-
|
|
10393
|
+
fs79.fsyncSync(this.fd);
|
|
10126
10394
|
}
|
|
10127
10395
|
const len = this._len;
|
|
10128
10396
|
if (this._reopening) {
|
|
@@ -10236,7 +10504,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10236
10504
|
const onDrain = () => {
|
|
10237
10505
|
if (!this._fsync) {
|
|
10238
10506
|
try {
|
|
10239
|
-
|
|
10507
|
+
fs79.fsync(this.fd, (err) => {
|
|
10240
10508
|
this._flushPending = false;
|
|
10241
10509
|
cb(err);
|
|
10242
10510
|
});
|
|
@@ -10338,7 +10606,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10338
10606
|
const fd = this.fd;
|
|
10339
10607
|
this.once("ready", () => {
|
|
10340
10608
|
if (fd !== this.fd) {
|
|
10341
|
-
|
|
10609
|
+
fs79.close(fd, (err) => {
|
|
10342
10610
|
if (err) {
|
|
10343
10611
|
return this.emit("error", err);
|
|
10344
10612
|
}
|
|
@@ -10387,7 +10655,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10387
10655
|
buf = this._bufs[0];
|
|
10388
10656
|
}
|
|
10389
10657
|
try {
|
|
10390
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10658
|
+
const n = Buffer.isBuffer(buf) ? fs79.writeSync(this.fd, buf) : fs79.writeSync(this.fd, buf, "utf8");
|
|
10391
10659
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10392
10660
|
buf = releasedBufObj.writingBuf;
|
|
10393
10661
|
this._len = releasedBufObj.len;
|
|
@@ -10403,7 +10671,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10403
10671
|
}
|
|
10404
10672
|
}
|
|
10405
10673
|
try {
|
|
10406
|
-
|
|
10674
|
+
fs79.fsyncSync(this.fd);
|
|
10407
10675
|
} catch {
|
|
10408
10676
|
}
|
|
10409
10677
|
}
|
|
@@ -10424,7 +10692,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10424
10692
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10425
10693
|
}
|
|
10426
10694
|
try {
|
|
10427
|
-
const n =
|
|
10695
|
+
const n = fs79.writeSync(this.fd, buf);
|
|
10428
10696
|
buf = buf.subarray(n);
|
|
10429
10697
|
this._len = Math.max(this._len - n, 0);
|
|
10430
10698
|
if (buf.length <= 0) {
|
|
@@ -10452,13 +10720,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10452
10720
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10453
10721
|
if (this.sync) {
|
|
10454
10722
|
try {
|
|
10455
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
10723
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs79.writeSync(this.fd, this._writingBuf) : fs79.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10456
10724
|
release(null, written);
|
|
10457
10725
|
} catch (err) {
|
|
10458
10726
|
release(err);
|
|
10459
10727
|
}
|
|
10460
10728
|
} else {
|
|
10461
|
-
|
|
10729
|
+
fs79.write(this.fd, this._writingBuf, release);
|
|
10462
10730
|
}
|
|
10463
10731
|
}
|
|
10464
10732
|
function actualWriteBuffer() {
|
|
@@ -10467,7 +10735,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10467
10735
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10468
10736
|
if (this.sync) {
|
|
10469
10737
|
try {
|
|
10470
|
-
const written =
|
|
10738
|
+
const written = fs79.writeSync(this.fd, this._writingBuf);
|
|
10471
10739
|
release(null, written);
|
|
10472
10740
|
} catch (err) {
|
|
10473
10741
|
release(err);
|
|
@@ -10476,7 +10744,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10476
10744
|
if (kCopyBuffer) {
|
|
10477
10745
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10478
10746
|
}
|
|
10479
|
-
|
|
10747
|
+
fs79.write(this.fd, this._writingBuf, release);
|
|
10480
10748
|
}
|
|
10481
10749
|
}
|
|
10482
10750
|
function actualClose(sonic) {
|
|
@@ -10492,12 +10760,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10492
10760
|
sonic._lens = [];
|
|
10493
10761
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10494
10762
|
try {
|
|
10495
|
-
|
|
10763
|
+
fs79.fsync(sonic.fd, closeWrapped);
|
|
10496
10764
|
} catch {
|
|
10497
10765
|
}
|
|
10498
10766
|
function closeWrapped() {
|
|
10499
10767
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10500
|
-
|
|
10768
|
+
fs79.close(sonic.fd, done);
|
|
10501
10769
|
} else {
|
|
10502
10770
|
done();
|
|
10503
10771
|
}
|
|
@@ -13632,11 +13900,11 @@ var init_lib = __esm({
|
|
|
13632
13900
|
}
|
|
13633
13901
|
}
|
|
13634
13902
|
},
|
|
13635
|
-
addToPath: function addToPath(
|
|
13636
|
-
var last =
|
|
13903
|
+
addToPath: function addToPath(path89, added, removed, oldPosInc, options) {
|
|
13904
|
+
var last = path89.lastComponent;
|
|
13637
13905
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13638
13906
|
return {
|
|
13639
|
-
oldPos:
|
|
13907
|
+
oldPos: path89.oldPos + oldPosInc,
|
|
13640
13908
|
lastComponent: {
|
|
13641
13909
|
count: last.count + 1,
|
|
13642
13910
|
added,
|
|
@@ -13646,7 +13914,7 @@ var init_lib = __esm({
|
|
|
13646
13914
|
};
|
|
13647
13915
|
} else {
|
|
13648
13916
|
return {
|
|
13649
|
-
oldPos:
|
|
13917
|
+
oldPos: path89.oldPos + oldPosInc,
|
|
13650
13918
|
lastComponent: {
|
|
13651
13919
|
count: 1,
|
|
13652
13920
|
added,
|
|
@@ -13956,24 +14224,46 @@ function safeStatMtime(p2) {
|
|
|
13956
14224
|
return 0;
|
|
13957
14225
|
}
|
|
13958
14226
|
}
|
|
13959
|
-
function
|
|
13960
|
-
let
|
|
14227
|
+
function* streamJsonlLines(file) {
|
|
14228
|
+
let fd;
|
|
13961
14229
|
try {
|
|
13962
|
-
|
|
14230
|
+
fd = import_node_fs6.default.openSync(file, "r");
|
|
13963
14231
|
} catch (err) {
|
|
13964
|
-
if (err.code === "ENOENT") return
|
|
14232
|
+
if (err.code === "ENOENT") return;
|
|
13965
14233
|
throw err;
|
|
13966
14234
|
}
|
|
13967
|
-
const
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
14235
|
+
const decoder = new import_node_string_decoder.StringDecoder("utf8");
|
|
14236
|
+
const buf = Buffer.allocUnsafe(JSONL_CHUNK_BYTES);
|
|
14237
|
+
let pending = "";
|
|
14238
|
+
try {
|
|
14239
|
+
for (; ; ) {
|
|
14240
|
+
const n = import_node_fs6.default.readSync(fd, buf, 0, JSONL_CHUNK_BYTES, null);
|
|
14241
|
+
if (n === 0) break;
|
|
14242
|
+
pending += decoder.write(buf.subarray(0, n));
|
|
14243
|
+
let nl;
|
|
14244
|
+
while ((nl = pending.indexOf("\n")) >= 0) {
|
|
14245
|
+
const line = pending.slice(0, nl).trim();
|
|
14246
|
+
pending = pending.slice(nl + 1);
|
|
14247
|
+
if (!line) continue;
|
|
14248
|
+
try {
|
|
14249
|
+
yield JSON.parse(line);
|
|
14250
|
+
} catch {
|
|
14251
|
+
}
|
|
14252
|
+
}
|
|
14253
|
+
}
|
|
14254
|
+
const last = (pending + decoder.end()).trim();
|
|
14255
|
+
if (last) {
|
|
14256
|
+
try {
|
|
14257
|
+
yield JSON.parse(last);
|
|
14258
|
+
} catch {
|
|
14259
|
+
}
|
|
13974
14260
|
}
|
|
14261
|
+
} finally {
|
|
14262
|
+
import_node_fs6.default.closeSync(fd);
|
|
13975
14263
|
}
|
|
13976
|
-
|
|
14264
|
+
}
|
|
14265
|
+
function readJsonlLines(file) {
|
|
14266
|
+
return [...streamJsonlLines(file)];
|
|
13977
14267
|
}
|
|
13978
14268
|
function classifyUserMessage(input) {
|
|
13979
14269
|
const text = input.text ?? "";
|
|
@@ -14178,10 +14468,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14178
14468
|
const memories = raw.map((m2) => {
|
|
14179
14469
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14180
14470
|
const rec4 = m2;
|
|
14181
|
-
const
|
|
14471
|
+
const path89 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14182
14472
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14183
|
-
if (!
|
|
14184
|
-
const entry = { path:
|
|
14473
|
+
if (!path89 || content == null) return null;
|
|
14474
|
+
const entry = { path: path89, content };
|
|
14185
14475
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14186
14476
|
return entry;
|
|
14187
14477
|
}).filter((m2) => m2 !== null);
|
|
@@ -14233,7 +14523,7 @@ function readCurrentContent(filePath) {
|
|
|
14233
14523
|
return null;
|
|
14234
14524
|
}
|
|
14235
14525
|
}
|
|
14236
|
-
var import_node_crypto3, import_node_fs6, import_node_os3, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
14526
|
+
var import_node_crypto3, import_node_fs6, import_node_os3, import_node_path5, import_node_string_decoder, JSONL_CHUNK_BYTES, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
14237
14527
|
var init_claude_history = __esm({
|
|
14238
14528
|
"src/tools/claude-history.ts"() {
|
|
14239
14529
|
"use strict";
|
|
@@ -14241,8 +14531,10 @@ var init_claude_history = __esm({
|
|
|
14241
14531
|
import_node_fs6 = __toESM(require("fs"), 1);
|
|
14242
14532
|
import_node_os3 = __toESM(require("os"), 1);
|
|
14243
14533
|
import_node_path5 = __toESM(require("path"), 1);
|
|
14534
|
+
import_node_string_decoder = require("string_decoder");
|
|
14244
14535
|
init_lib();
|
|
14245
14536
|
init_tool_result_extra();
|
|
14537
|
+
JSONL_CHUNK_BYTES = 256 * 1024;
|
|
14246
14538
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
14247
14539
|
TASK_ID_RE = /<task-id>\s*([^<\s][^<]*?)\s*<\/task-id>/i;
|
|
14248
14540
|
TOOL_USE_ID_RE = /<tool-use-id>\s*([^<\s][^<]*?)\s*<\/tool-use-id>/i;
|
|
@@ -14288,6 +14580,20 @@ var init_claude_history = __esm({
|
|
|
14288
14580
|
const found = findTranscriptByToolSessionId(this.projectsRoot, toolSessionId);
|
|
14289
14581
|
return found ? import_node_path5.default.dirname(found) : byCwd;
|
|
14290
14582
|
}
|
|
14583
|
+
/**
|
|
14584
|
+
* 定位一条 session 的 transcript 文件;不存在返回 null。
|
|
14585
|
+
*
|
|
14586
|
+
* 对外开这一口是为了让 adapter 之外的消费者(`line:digest`)**不必自己拼路径**:
|
|
14587
|
+
* 「按 cwd 直取 → 按 tsid 全局兜底」这套 relocation 逻辑曾被抄成第二份,
|
|
14588
|
+
* 规则一改就静默漂移。路径编码(cwdToHashDir)与兜底顺序全仓只此一处。
|
|
14589
|
+
*
|
|
14590
|
+
* 返回 null 而不是不存在的路径:调用方要能区分「还没写盘」与「读到空 transcript」——
|
|
14591
|
+
* 后者会让核验把一条刚 spawn 的线判成假完成。
|
|
14592
|
+
*/
|
|
14593
|
+
resolveTranscriptFile(cwd, toolSessionId) {
|
|
14594
|
+
const file = import_node_path5.default.join(this.resolveSessionDir(cwd, toolSessionId), `${toolSessionId}.jsonl`);
|
|
14595
|
+
return import_node_fs6.default.existsSync(file) ? file : null;
|
|
14596
|
+
}
|
|
14291
14597
|
async listProjects() {
|
|
14292
14598
|
let entries;
|
|
14293
14599
|
try {
|
|
@@ -15032,10 +15338,10 @@ function parseAttachment(obj) {
|
|
|
15032
15338
|
const memories = raw.map((m2) => {
|
|
15033
15339
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15034
15340
|
const rec4 = m2;
|
|
15035
|
-
const
|
|
15341
|
+
const path89 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15036
15342
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15037
|
-
if (!
|
|
15038
|
-
const out = { path:
|
|
15343
|
+
if (!path89 || content == null) return null;
|
|
15344
|
+
const out = { path: path89, content };
|
|
15039
15345
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15040
15346
|
return out;
|
|
15041
15347
|
}).filter((m2) => m2 !== null);
|
|
@@ -34101,8 +34407,8 @@ var require_string_decoder = __commonJS({
|
|
|
34101
34407
|
if (typeof nenc !== "string" && (Buffer2.isEncoding === isEncoding || !isEncoding(enc))) throw new Error("Unknown encoding: " + enc);
|
|
34102
34408
|
return nenc || enc;
|
|
34103
34409
|
}
|
|
34104
|
-
exports2.StringDecoder =
|
|
34105
|
-
function
|
|
34410
|
+
exports2.StringDecoder = StringDecoder2;
|
|
34411
|
+
function StringDecoder2(encoding) {
|
|
34106
34412
|
this.encoding = normalizeEncoding(encoding);
|
|
34107
34413
|
var nb;
|
|
34108
34414
|
switch (this.encoding) {
|
|
@@ -34129,7 +34435,7 @@ var require_string_decoder = __commonJS({
|
|
|
34129
34435
|
this.lastTotal = 0;
|
|
34130
34436
|
this.lastChar = Buffer2.allocUnsafe(nb);
|
|
34131
34437
|
}
|
|
34132
|
-
|
|
34438
|
+
StringDecoder2.prototype.write = function(buf) {
|
|
34133
34439
|
if (buf.length === 0) return "";
|
|
34134
34440
|
var r;
|
|
34135
34441
|
var i;
|
|
@@ -34144,9 +34450,9 @@ var require_string_decoder = __commonJS({
|
|
|
34144
34450
|
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
|
34145
34451
|
return r || "";
|
|
34146
34452
|
};
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
|
|
34453
|
+
StringDecoder2.prototype.end = utf8End;
|
|
34454
|
+
StringDecoder2.prototype.text = utf8Text;
|
|
34455
|
+
StringDecoder2.prototype.fillLast = function(buf) {
|
|
34150
34456
|
if (this.lastNeed <= buf.length) {
|
|
34151
34457
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
|
34152
34458
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
@@ -34318,7 +34624,7 @@ var require_stream_readable = __commonJS({
|
|
|
34318
34624
|
}
|
|
34319
34625
|
var BufferList = require_BufferList();
|
|
34320
34626
|
var destroyImpl = require_destroy();
|
|
34321
|
-
var
|
|
34627
|
+
var StringDecoder2;
|
|
34322
34628
|
util2.inherits(Readable3, Stream);
|
|
34323
34629
|
var kProxyEvents = ["error", "close", "destroy", "pause", "resume"];
|
|
34324
34630
|
function prependListener(emitter, event, fn) {
|
|
@@ -34360,8 +34666,8 @@ var require_stream_readable = __commonJS({
|
|
|
34360
34666
|
this.decoder = null;
|
|
34361
34667
|
this.encoding = null;
|
|
34362
34668
|
if (options.encoding) {
|
|
34363
|
-
if (!
|
|
34364
|
-
this.decoder = new
|
|
34669
|
+
if (!StringDecoder2) StringDecoder2 = require_string_decoder().StringDecoder;
|
|
34670
|
+
this.decoder = new StringDecoder2(options.encoding);
|
|
34365
34671
|
this.encoding = options.encoding;
|
|
34366
34672
|
}
|
|
34367
34673
|
}
|
|
@@ -34477,8 +34783,8 @@ var require_stream_readable = __commonJS({
|
|
|
34477
34783
|
return this._readableState.flowing === false;
|
|
34478
34784
|
};
|
|
34479
34785
|
Readable3.prototype.setEncoding = function(enc) {
|
|
34480
|
-
if (!
|
|
34481
|
-
this._readableState.decoder = new
|
|
34786
|
+
if (!StringDecoder2) StringDecoder2 = require_string_decoder().StringDecoder;
|
|
34787
|
+
this._readableState.decoder = new StringDecoder2(enc);
|
|
34482
34788
|
this._readableState.encoding = enc;
|
|
34483
34789
|
return this;
|
|
34484
34790
|
};
|
|
@@ -36009,8 +36315,8 @@ var require_utils = __commonJS({
|
|
|
36009
36315
|
var result = transform[inputType][outputType](input);
|
|
36010
36316
|
return result;
|
|
36011
36317
|
};
|
|
36012
|
-
exports2.resolve = function(
|
|
36013
|
-
var parts =
|
|
36318
|
+
exports2.resolve = function(path89) {
|
|
36319
|
+
var parts = path89.split("/");
|
|
36014
36320
|
var result = [];
|
|
36015
36321
|
for (var index = 0; index < parts.length; index++) {
|
|
36016
36322
|
var part = parts[index];
|
|
@@ -41863,18 +42169,18 @@ var require_object = __commonJS({
|
|
|
41863
42169
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
41864
42170
|
this.files[name] = object;
|
|
41865
42171
|
};
|
|
41866
|
-
var parentFolder = function(
|
|
41867
|
-
if (
|
|
41868
|
-
|
|
42172
|
+
var parentFolder = function(path89) {
|
|
42173
|
+
if (path89.slice(-1) === "/") {
|
|
42174
|
+
path89 = path89.substring(0, path89.length - 1);
|
|
41869
42175
|
}
|
|
41870
|
-
var lastSlash =
|
|
41871
|
-
return lastSlash > 0 ?
|
|
42176
|
+
var lastSlash = path89.lastIndexOf("/");
|
|
42177
|
+
return lastSlash > 0 ? path89.substring(0, lastSlash) : "";
|
|
41872
42178
|
};
|
|
41873
|
-
var forceTrailingSlash = function(
|
|
41874
|
-
if (
|
|
41875
|
-
|
|
42179
|
+
var forceTrailingSlash = function(path89) {
|
|
42180
|
+
if (path89.slice(-1) !== "/") {
|
|
42181
|
+
path89 += "/";
|
|
41876
42182
|
}
|
|
41877
|
-
return
|
|
42183
|
+
return path89;
|
|
41878
42184
|
};
|
|
41879
42185
|
var folderAdd = function(name, createFolders) {
|
|
41880
42186
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -42876,7 +43182,7 @@ var require_lib3 = __commonJS({
|
|
|
42876
43182
|
// src/run-case/recorder.ts
|
|
42877
43183
|
function startRunCaseRecorder(opts) {
|
|
42878
43184
|
const now = opts.now ?? Date.now;
|
|
42879
|
-
const dir =
|
|
43185
|
+
const dir = import_node_path71.default.dirname(opts.recordPath);
|
|
42880
43186
|
let stream = null;
|
|
42881
43187
|
let closing = false;
|
|
42882
43188
|
let closedSettled = false;
|
|
@@ -42916,12 +43222,12 @@ function startRunCaseRecorder(opts) {
|
|
|
42916
43222
|
};
|
|
42917
43223
|
return { tap, close, closed };
|
|
42918
43224
|
}
|
|
42919
|
-
var import_node_fs53,
|
|
43225
|
+
var import_node_fs53, import_node_path71;
|
|
42920
43226
|
var init_recorder = __esm({
|
|
42921
43227
|
"src/run-case/recorder.ts"() {
|
|
42922
43228
|
"use strict";
|
|
42923
43229
|
import_node_fs53 = __toESM(require("fs"), 1);
|
|
42924
|
-
|
|
43230
|
+
import_node_path71 = __toESM(require("path"), 1);
|
|
42925
43231
|
}
|
|
42926
43232
|
});
|
|
42927
43233
|
|
|
@@ -42964,7 +43270,7 @@ var init_wire = __esm({
|
|
|
42964
43270
|
// src/run-case/controller.ts
|
|
42965
43271
|
async function runController(opts) {
|
|
42966
43272
|
const now = opts.now ?? Date.now;
|
|
42967
|
-
const cwd = opts.cwd ?? (0, import_node_fs54.mkdtempSync)(
|
|
43273
|
+
const cwd = opts.cwd ?? (0, import_node_fs54.mkdtempSync)(import_node_path72.default.join(import_node_os25.default.tmpdir(), "clawd-runcase-"));
|
|
42968
43274
|
const ownsCwd = opts.cwd === void 0;
|
|
42969
43275
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
42970
43276
|
const spawnCtx = { cwd };
|
|
@@ -43131,13 +43437,13 @@ async function runController(opts) {
|
|
|
43131
43437
|
}
|
|
43132
43438
|
return exitCode ?? 0;
|
|
43133
43439
|
}
|
|
43134
|
-
var import_node_fs54, import_node_os25,
|
|
43440
|
+
var import_node_fs54, import_node_os25, import_node_path72;
|
|
43135
43441
|
var init_controller = __esm({
|
|
43136
43442
|
"src/run-case/controller.ts"() {
|
|
43137
43443
|
"use strict";
|
|
43138
43444
|
import_node_fs54 = require("fs");
|
|
43139
43445
|
import_node_os25 = __toESM(require("os"), 1);
|
|
43140
|
-
|
|
43446
|
+
import_node_path72 = __toESM(require("path"), 1);
|
|
43141
43447
|
init_claude();
|
|
43142
43448
|
init_stdout_splitter();
|
|
43143
43449
|
init_permission_stdio();
|
|
@@ -43412,7 +43718,7 @@ Env (advanced):
|
|
|
43412
43718
|
`;
|
|
43413
43719
|
|
|
43414
43720
|
// src/index.ts
|
|
43415
|
-
var
|
|
43721
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
43416
43722
|
var import_node_fs52 = __toESM(require("fs"), 1);
|
|
43417
43723
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
43418
43724
|
|
|
@@ -49191,6 +49497,21 @@ var DEFAULT_PERSONAS = [
|
|
|
49191
49497
|
denyRead: [".secrets/**"],
|
|
49192
49498
|
network: true
|
|
49193
49499
|
}
|
|
49500
|
+
},
|
|
49501
|
+
{
|
|
49502
|
+
// Master:spec superpowers/specs/2026-08-21-channel-master-m2-design.md
|
|
49503
|
+
// 代替老板操盘一群 worker persona:拆线 / 派活 / **验收 / 打回** / 收敛 / 上报。
|
|
49504
|
+
// 判断力靠 CLAUDE.md 人格 + .claude/agents/line-watcher.md(核验 subagent),
|
|
49505
|
+
// 纪律靠 daemon 侧 zod(`topic:*` 的 reason / acceptanceCriteria 非空在 RPC 入口拒,
|
|
49506
|
+
// 没有绕过路径)+ `master:authorityCheck` 查表。M1 那三个 bundle 内 .mjs 脚本已随
|
|
49507
|
+
// M2「MCP 化」整体拆除,别再照那套找。
|
|
49508
|
+
personaId: "persona-master",
|
|
49509
|
+
label: "Master",
|
|
49510
|
+
model: "opus",
|
|
49511
|
+
effort: "high",
|
|
49512
|
+
iconKey: "assist",
|
|
49513
|
+
public: false,
|
|
49514
|
+
sandboxProfile: DEFAULT_BYPASS_PROFILE
|
|
49194
49515
|
}
|
|
49195
49516
|
];
|
|
49196
49517
|
function bundleSiblingFromArgv(argv1, sibling) {
|
|
@@ -49290,7 +49611,7 @@ function copyBundleExtras(srcDir, dstDir) {
|
|
|
49290
49611
|
}
|
|
49291
49612
|
}
|
|
49292
49613
|
}
|
|
49293
|
-
var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills"];
|
|
49614
|
+
var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json", ".claude/skills", ".claude/agents"];
|
|
49294
49615
|
function replaceManagedPath(src, dst) {
|
|
49295
49616
|
if (!fs14.statSync(src).isDirectory()) {
|
|
49296
49617
|
fs14.mkdirSync(path17.dirname(dst), { recursive: true });
|
|
@@ -50275,8 +50596,8 @@ function turnStartInput(text) {
|
|
|
50275
50596
|
const items = [];
|
|
50276
50597
|
let leftover = text;
|
|
50277
50598
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
50278
|
-
const [marker, name,
|
|
50279
|
-
items.push({ type: "skill", name, path:
|
|
50599
|
+
const [marker, name, path89] = m2;
|
|
50600
|
+
items.push({ type: "skill", name, path: path89 });
|
|
50280
50601
|
leftover = leftover.replace(marker, "");
|
|
50281
50602
|
}
|
|
50282
50603
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -52045,7 +52366,8 @@ var PersonaDispatchManager = class {
|
|
|
52045
52366
|
sourceSessionId: args.sourceSessionId,
|
|
52046
52367
|
...args.sourcePersonaId ? { sourcePersonaId: args.sourcePersonaId } : {},
|
|
52047
52368
|
targetPersonaId: args.targetPersona,
|
|
52048
|
-
taskText: args.taskText
|
|
52369
|
+
taskText: args.taskText,
|
|
52370
|
+
...args.meta ? { meta: args.meta } : {}
|
|
52049
52371
|
});
|
|
52050
52372
|
return { dispatchId };
|
|
52051
52373
|
}
|
|
@@ -52194,11 +52516,203 @@ function createDispatchStore(deps) {
|
|
|
52194
52516
|
return { load, flushNow, add, update, list, get, markInterruptedAsFailed };
|
|
52195
52517
|
}
|
|
52196
52518
|
|
|
52519
|
+
// src/channel/json-store.ts
|
|
52520
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
52521
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
52522
|
+
function createJsonStore(deps) {
|
|
52523
|
+
let items = [];
|
|
52524
|
+
let flushTimer = null;
|
|
52525
|
+
async function flushNow() {
|
|
52526
|
+
if (flushTimer) {
|
|
52527
|
+
clearTimeout(flushTimer);
|
|
52528
|
+
flushTimer = null;
|
|
52529
|
+
}
|
|
52530
|
+
const content = { version: 1, [deps.key]: items };
|
|
52531
|
+
await import_promises2.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
|
|
52532
|
+
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52533
|
+
await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52534
|
+
await import_promises2.default.rename(tmp, deps.filePath);
|
|
52535
|
+
}
|
|
52536
|
+
return {
|
|
52537
|
+
all: () => items,
|
|
52538
|
+
flushNow,
|
|
52539
|
+
async load() {
|
|
52540
|
+
let raw;
|
|
52541
|
+
try {
|
|
52542
|
+
raw = await import_promises2.default.readFile(deps.filePath, "utf8");
|
|
52543
|
+
} catch (e) {
|
|
52544
|
+
if (e.code === "ENOENT") {
|
|
52545
|
+
items = [];
|
|
52546
|
+
return;
|
|
52547
|
+
}
|
|
52548
|
+
throw e;
|
|
52549
|
+
}
|
|
52550
|
+
const parsed = JSON.parse(raw);
|
|
52551
|
+
if (parsed.version !== 1) {
|
|
52552
|
+
throw new Error(`${deps.key}.json: unsupported version ${String(parsed.version)}`);
|
|
52553
|
+
}
|
|
52554
|
+
items = parsed[deps.key] ?? [];
|
|
52555
|
+
},
|
|
52556
|
+
scheduleFlush() {
|
|
52557
|
+
if (flushTimer) return;
|
|
52558
|
+
flushTimer = setTimeout(() => {
|
|
52559
|
+
flushTimer = null;
|
|
52560
|
+
flushNow().catch((err) => deps.onFlushError?.(err));
|
|
52561
|
+
}, STORE_FLUSH_DEBOUNCE_MS);
|
|
52562
|
+
}
|
|
52563
|
+
};
|
|
52564
|
+
}
|
|
52565
|
+
|
|
52566
|
+
// src/channel/store.ts
|
|
52567
|
+
function createChannelStore(deps) {
|
|
52568
|
+
const file = createJsonStore({ ...deps, key: "channels" });
|
|
52569
|
+
const get = (id) => file.all().find((c) => c.id === id);
|
|
52570
|
+
return {
|
|
52571
|
+
load: file.load,
|
|
52572
|
+
flushNow: file.flushNow,
|
|
52573
|
+
list: () => [...file.all()],
|
|
52574
|
+
get,
|
|
52575
|
+
create(input) {
|
|
52576
|
+
const iso = new Date(deps.now()).toISOString();
|
|
52577
|
+
const c = {
|
|
52578
|
+
id: deps.genId(),
|
|
52579
|
+
name: input.name,
|
|
52580
|
+
memberPersonaIds: input.memberPersonaIds,
|
|
52581
|
+
memberContactDeviceIds: input.memberContactDeviceIds,
|
|
52582
|
+
createdAt: iso,
|
|
52583
|
+
updatedAt: iso
|
|
52584
|
+
};
|
|
52585
|
+
file.all().push(c);
|
|
52586
|
+
file.scheduleFlush();
|
|
52587
|
+
return c;
|
|
52588
|
+
},
|
|
52589
|
+
update(id, patch) {
|
|
52590
|
+
const c = get(id);
|
|
52591
|
+
if (!c) return void 0;
|
|
52592
|
+
if (patch.name !== void 0) c.name = patch.name;
|
|
52593
|
+
if (patch.memberPersonaIds !== void 0) c.memberPersonaIds = patch.memberPersonaIds;
|
|
52594
|
+
if (patch.memberContactDeviceIds !== void 0) {
|
|
52595
|
+
c.memberContactDeviceIds = patch.memberContactDeviceIds;
|
|
52596
|
+
}
|
|
52597
|
+
c.updatedAt = new Date(deps.now()).toISOString();
|
|
52598
|
+
file.scheduleFlush();
|
|
52599
|
+
return c;
|
|
52600
|
+
},
|
|
52601
|
+
remove(id) {
|
|
52602
|
+
const items = file.all();
|
|
52603
|
+
const i = items.findIndex((c) => c.id === id);
|
|
52604
|
+
if (i < 0) return false;
|
|
52605
|
+
items.splice(i, 1);
|
|
52606
|
+
file.scheduleFlush();
|
|
52607
|
+
return true;
|
|
52608
|
+
}
|
|
52609
|
+
};
|
|
52610
|
+
}
|
|
52611
|
+
|
|
52612
|
+
// src/channel/topic-store.ts
|
|
52613
|
+
function createTopicStore(deps) {
|
|
52614
|
+
const file = createJsonStore({ ...deps, key: "topics" });
|
|
52615
|
+
const get = (topicId) => file.all().find((t) => t.id === topicId);
|
|
52616
|
+
const touch = (t) => {
|
|
52617
|
+
t.updatedAt = new Date(deps.now()).toISOString();
|
|
52618
|
+
};
|
|
52619
|
+
const lineMetaOf = (t, lineId) => t.lineMeta[lineId] ??= { rejectCount: 0, accepted: false };
|
|
52620
|
+
return {
|
|
52621
|
+
load: file.load,
|
|
52622
|
+
flushNow: file.flushNow,
|
|
52623
|
+
get,
|
|
52624
|
+
getByMasterSession: (masterSessionId) => file.all().find((t) => t.masterSessionId === masterSessionId),
|
|
52625
|
+
listByChannel: (channelId) => file.all().filter((t) => t.channelId === channelId),
|
|
52626
|
+
create(input) {
|
|
52627
|
+
const iso = new Date(deps.now()).toISOString();
|
|
52628
|
+
const t = {
|
|
52629
|
+
id: deps.genId(),
|
|
52630
|
+
channelId: input.channelId,
|
|
52631
|
+
title: input.title ?? "",
|
|
52632
|
+
masterSessionId: input.masterSessionId,
|
|
52633
|
+
goal: "",
|
|
52634
|
+
boundaries: "",
|
|
52635
|
+
acceptanceCriteria: [],
|
|
52636
|
+
activity: [],
|
|
52637
|
+
lineMeta: {},
|
|
52638
|
+
state: "planning",
|
|
52639
|
+
createdAt: iso,
|
|
52640
|
+
updatedAt: iso
|
|
52641
|
+
};
|
|
52642
|
+
file.all().push(t);
|
|
52643
|
+
file.scheduleFlush();
|
|
52644
|
+
return t;
|
|
52645
|
+
},
|
|
52646
|
+
setPlan(topicId, plan) {
|
|
52647
|
+
const t = get(topicId);
|
|
52648
|
+
if (!t) return void 0;
|
|
52649
|
+
if (plan.title !== void 0) t.title = plan.title;
|
|
52650
|
+
t.goal = plan.goal;
|
|
52651
|
+
t.boundaries = plan.boundaries;
|
|
52652
|
+
t.acceptanceCriteria = plan.acceptanceCriteria;
|
|
52653
|
+
t.state = "running";
|
|
52654
|
+
touch(t);
|
|
52655
|
+
file.scheduleFlush();
|
|
52656
|
+
return t;
|
|
52657
|
+
},
|
|
52658
|
+
appendActivity(topicId, entry) {
|
|
52659
|
+
const t = get(topicId);
|
|
52660
|
+
if (!t) return void 0;
|
|
52661
|
+
t.activity.push({ at: new Date(deps.now()).toISOString(), ...entry });
|
|
52662
|
+
touch(t);
|
|
52663
|
+
file.scheduleFlush();
|
|
52664
|
+
return t;
|
|
52665
|
+
},
|
|
52666
|
+
bumpReject(topicId, lineId) {
|
|
52667
|
+
const t = get(topicId);
|
|
52668
|
+
if (!t) return void 0;
|
|
52669
|
+
const meta = lineMetaOf(t, lineId);
|
|
52670
|
+
meta.rejectCount += 1;
|
|
52671
|
+
meta.accepted = false;
|
|
52672
|
+
touch(t);
|
|
52673
|
+
file.scheduleFlush();
|
|
52674
|
+
return meta;
|
|
52675
|
+
},
|
|
52676
|
+
markAccepted(topicId, lineId) {
|
|
52677
|
+
const t = get(topicId);
|
|
52678
|
+
if (!t) return void 0;
|
|
52679
|
+
const meta = lineMetaOf(t, lineId);
|
|
52680
|
+
meta.accepted = true;
|
|
52681
|
+
touch(t);
|
|
52682
|
+
file.scheduleFlush();
|
|
52683
|
+
return meta;
|
|
52684
|
+
},
|
|
52685
|
+
close(topicId, state) {
|
|
52686
|
+
const t = get(topicId);
|
|
52687
|
+
if (!t) return void 0;
|
|
52688
|
+
t.state = state;
|
|
52689
|
+
touch(t);
|
|
52690
|
+
file.scheduleFlush();
|
|
52691
|
+
return t;
|
|
52692
|
+
},
|
|
52693
|
+
hasUnfinished(channelId) {
|
|
52694
|
+
return file.all().some((t) => t.channelId === channelId && (t.state === "planning" || t.state === "running"));
|
|
52695
|
+
},
|
|
52696
|
+
removeByChannel(channelId) {
|
|
52697
|
+
const items = file.all();
|
|
52698
|
+
let removed = 0;
|
|
52699
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
52700
|
+
if (items[i].channelId === channelId) {
|
|
52701
|
+
items.splice(i, 1);
|
|
52702
|
+
removed += 1;
|
|
52703
|
+
}
|
|
52704
|
+
}
|
|
52705
|
+
if (removed) file.scheduleFlush();
|
|
52706
|
+
return removed;
|
|
52707
|
+
}
|
|
52708
|
+
};
|
|
52709
|
+
}
|
|
52710
|
+
|
|
52197
52711
|
// src/dispatch/mcp-config.ts
|
|
52198
52712
|
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
52199
|
-
var
|
|
52713
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
52200
52714
|
function dispatchMcpConfigPath(dataDir) {
|
|
52201
|
-
return
|
|
52715
|
+
return import_node_path20.default.join(dataDir, "dispatch.mcp.json");
|
|
52202
52716
|
}
|
|
52203
52717
|
function writeDispatchMcpConfig(args) {
|
|
52204
52718
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -52224,9 +52738,9 @@ function writeDispatchMcpConfig(args) {
|
|
|
52224
52738
|
|
|
52225
52739
|
// src/ticket/mcp-config.ts
|
|
52226
52740
|
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
52227
|
-
var
|
|
52741
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
52228
52742
|
function ticketMcpConfigPath(dataDir) {
|
|
52229
|
-
return
|
|
52743
|
+
return import_node_path21.default.join(dataDir, "ticket.mcp.json");
|
|
52230
52744
|
}
|
|
52231
52745
|
function writeTicketMcpConfig(args) {
|
|
52232
52746
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
@@ -52255,9 +52769,9 @@ function writeTicketMcpConfig(args) {
|
|
|
52255
52769
|
|
|
52256
52770
|
// src/shift/mcp-config.ts
|
|
52257
52771
|
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
52258
|
-
var
|
|
52772
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
52259
52773
|
function shiftMcpConfigPath(dataDir) {
|
|
52260
|
-
return
|
|
52774
|
+
return import_node_path22.default.join(dataDir, "shift.mcp.json");
|
|
52261
52775
|
}
|
|
52262
52776
|
async function writeShiftMcpConfig(args) {
|
|
52263
52777
|
const cfgPath = shiftMcpConfigPath(args.dataDir);
|
|
@@ -52283,9 +52797,9 @@ async function writeShiftMcpConfig(args) {
|
|
|
52283
52797
|
|
|
52284
52798
|
// src/inbox/mcp-config.ts
|
|
52285
52799
|
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
52286
|
-
var
|
|
52800
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
52287
52801
|
function inboxMcpConfigPath(dataDir) {
|
|
52288
|
-
return
|
|
52802
|
+
return import_node_path23.default.join(dataDir, "inbox.mcp.json");
|
|
52289
52803
|
}
|
|
52290
52804
|
async function writeInboxMcpConfig(args) {
|
|
52291
52805
|
const cfgPath = inboxMcpConfigPath(args.dataDir);
|
|
@@ -52311,9 +52825,9 @@ async function writeInboxMcpConfig(args) {
|
|
|
52311
52825
|
|
|
52312
52826
|
// src/peer-ops/mcp-config.ts
|
|
52313
52827
|
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
52314
|
-
var
|
|
52828
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
52315
52829
|
function peerOpsMcpConfigPath(dataDir) {
|
|
52316
|
-
return
|
|
52830
|
+
return import_node_path24.default.join(dataDir, "peer-ops.mcp.json");
|
|
52317
52831
|
}
|
|
52318
52832
|
function writePeerOpsMcpConfig(args) {
|
|
52319
52833
|
const cfgPath = peerOpsMcpConfigPath(args.dataDir);
|
|
@@ -52337,9 +52851,9 @@ function writePeerOpsMcpConfig(args) {
|
|
|
52337
52851
|
|
|
52338
52852
|
// src/rpc-tool/mcp-config.ts
|
|
52339
52853
|
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
52340
|
-
var
|
|
52854
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
52341
52855
|
function rpcToolMcpConfigPath(dataDir) {
|
|
52342
|
-
return
|
|
52856
|
+
return import_node_path25.default.join(dataDir, "rpc-tool.mcp.json");
|
|
52343
52857
|
}
|
|
52344
52858
|
function writeRpcToolMcpConfig(args) {
|
|
52345
52859
|
const cfgPath = rpcToolMcpConfigPath(args.dataDir);
|
|
@@ -52364,12 +52878,12 @@ function writeRpcToolMcpConfig(args) {
|
|
|
52364
52878
|
}
|
|
52365
52879
|
|
|
52366
52880
|
// src/dispatch/source-transcript.ts
|
|
52367
|
-
var
|
|
52881
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
52368
52882
|
init_claude_history();
|
|
52369
52883
|
var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
|
|
52370
52884
|
function resolveSourceJsonlPath(sourceFile, home) {
|
|
52371
52885
|
if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
|
|
52372
|
-
return
|
|
52886
|
+
return import_node_path26.default.join(
|
|
52373
52887
|
home,
|
|
52374
52888
|
".claude",
|
|
52375
52889
|
"projects",
|
|
@@ -52379,8 +52893,8 @@ function resolveSourceJsonlPath(sourceFile, home) {
|
|
|
52379
52893
|
}
|
|
52380
52894
|
|
|
52381
52895
|
// src/shift/store.ts
|
|
52382
|
-
var
|
|
52383
|
-
var
|
|
52896
|
+
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
52897
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
52384
52898
|
var import_node_crypto6 = require("crypto");
|
|
52385
52899
|
|
|
52386
52900
|
// src/shift/schedule.ts
|
|
@@ -52427,7 +52941,7 @@ function createShiftStore(deps) {
|
|
|
52427
52941
|
async function load() {
|
|
52428
52942
|
let raw;
|
|
52429
52943
|
try {
|
|
52430
|
-
raw = await
|
|
52944
|
+
raw = await import_promises3.default.readFile(deps.filePath, "utf8");
|
|
52431
52945
|
} catch (e) {
|
|
52432
52946
|
if (e.code === "ENOENT") {
|
|
52433
52947
|
shifts = [];
|
|
@@ -52455,10 +52969,10 @@ function createShiftStore(deps) {
|
|
|
52455
52969
|
flushTimer = null;
|
|
52456
52970
|
}
|
|
52457
52971
|
const content = { version: 1, shifts };
|
|
52458
|
-
await
|
|
52972
|
+
await import_promises3.default.mkdir(import_node_path27.default.dirname(deps.filePath), { recursive: true });
|
|
52459
52973
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52460
|
-
await
|
|
52461
|
-
await
|
|
52974
|
+
await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52975
|
+
await import_promises3.default.rename(tmp, deps.filePath);
|
|
52462
52976
|
}
|
|
52463
52977
|
function scheduleFlush() {
|
|
52464
52978
|
if (flushTimer) return;
|
|
@@ -53124,9 +53638,9 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
53124
53638
|
|
|
53125
53639
|
// src/lark-bot-connector/binding-store.ts
|
|
53126
53640
|
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
53127
|
-
var
|
|
53641
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
53128
53642
|
function createLarkBotBindingStore(personaRoot) {
|
|
53129
|
-
const filePath = (personaId2) =>
|
|
53643
|
+
const filePath = (personaId2) => import_node_path28.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
53130
53644
|
const read = (personaId2) => {
|
|
53131
53645
|
const file = filePath(personaId2);
|
|
53132
53646
|
if (!import_node_fs26.default.existsSync(file)) return null;
|
|
@@ -53140,7 +53654,7 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
53140
53654
|
};
|
|
53141
53655
|
const write = (personaId2, meta) => {
|
|
53142
53656
|
const file = filePath(personaId2);
|
|
53143
|
-
import_node_fs26.default.mkdirSync(
|
|
53657
|
+
import_node_fs26.default.mkdirSync(import_node_path28.default.dirname(file), { recursive: true });
|
|
53144
53658
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
53145
53659
|
import_node_fs26.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
53146
53660
|
import_node_fs26.default.renameSync(tmp, file);
|
|
@@ -53304,7 +53818,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
53304
53818
|
|
|
53305
53819
|
// src/lark-bot-connector/chat-router.ts
|
|
53306
53820
|
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
53307
|
-
var
|
|
53821
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
53308
53822
|
init_protocol();
|
|
53309
53823
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
53310
53824
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -53370,7 +53884,7 @@ function createLarkChatRouter(deps) {
|
|
|
53370
53884
|
}
|
|
53371
53885
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53372
53886
|
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
53373
|
-
const p2 =
|
|
53887
|
+
const p2 = import_node_path29.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
53374
53888
|
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
53375
53889
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53376
53890
|
} catch (err) {
|
|
@@ -53393,7 +53907,7 @@ function createLarkChatRouter(deps) {
|
|
|
53393
53907
|
}
|
|
53394
53908
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53395
53909
|
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
53396
|
-
const p2 =
|
|
53910
|
+
const p2 = import_node_path29.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
53397
53911
|
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
53398
53912
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53399
53913
|
} catch (err) {
|
|
@@ -53755,7 +54269,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
53755
54269
|
outcome: void 0,
|
|
53756
54270
|
completedAt: void 0,
|
|
53757
54271
|
deliveredAt: void 0,
|
|
53758
|
-
taskText: args.prompt.slice(0, TASK_TEXT_MAX)
|
|
54272
|
+
taskText: args.prompt.slice(0, TASK_TEXT_MAX),
|
|
54273
|
+
...args.meta ? { meta: { ...rec4.meta ?? {}, ...args.meta } } : {}
|
|
53759
54274
|
});
|
|
53760
54275
|
mgr.reopen(args.dispatchId, {
|
|
53761
54276
|
sourceSessionId,
|
|
@@ -53802,7 +54317,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
53802
54317
|
const { dispatchId: dispatchId2 } = mgr.start({
|
|
53803
54318
|
sourceSessionId,
|
|
53804
54319
|
targetPersona,
|
|
53805
|
-
taskText: args.prompt
|
|
54320
|
+
taskText: args.prompt,
|
|
54321
|
+
...args.meta ? { meta: args.meta } : {}
|
|
53806
54322
|
});
|
|
53807
54323
|
logger?.info("dispatch.run.forward", {
|
|
53808
54324
|
dispatchId: dispatchId2,
|
|
@@ -53834,7 +54350,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
53834
54350
|
const { dispatchId: dispatchId2 } = mgr.start({
|
|
53835
54351
|
sourceSessionId: ctx.principal.id,
|
|
53836
54352
|
targetPersona,
|
|
53837
|
-
taskText: args.prompt
|
|
54353
|
+
taskText: args.prompt,
|
|
54354
|
+
...args.meta ? { meta: args.meta } : {}
|
|
53838
54355
|
});
|
|
53839
54356
|
logger?.info("dispatch.run.received.guest", {
|
|
53840
54357
|
dispatchId: dispatchId2,
|
|
@@ -53870,7 +54387,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
53870
54387
|
const { dispatchId } = mgr.start({
|
|
53871
54388
|
sourceSessionId,
|
|
53872
54389
|
targetPersona,
|
|
53873
|
-
taskText: args.prompt
|
|
54390
|
+
taskText: args.prompt,
|
|
54391
|
+
...args.meta ? { meta: args.meta } : {}
|
|
53874
54392
|
});
|
|
53875
54393
|
logger?.info("dispatch.run.received", {
|
|
53876
54394
|
dispatchId,
|
|
@@ -54420,7 +54938,7 @@ var CodexHistoryReader = class {
|
|
|
54420
54938
|
};
|
|
54421
54939
|
|
|
54422
54940
|
// src/tools/codex-skills.ts
|
|
54423
|
-
var
|
|
54941
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
54424
54942
|
function str3(v2) {
|
|
54425
54943
|
return typeof v2 === "string" ? v2 : void 0;
|
|
54426
54944
|
}
|
|
@@ -54435,13 +54953,13 @@ function mapSkillsListResponse(res) {
|
|
|
54435
54953
|
const r = s ?? {};
|
|
54436
54954
|
const name = str3(r.name);
|
|
54437
54955
|
if (!name) continue;
|
|
54438
|
-
const
|
|
54956
|
+
const path89 = str3(r.path);
|
|
54439
54957
|
const description = str3(r.description);
|
|
54440
54958
|
const isPlugin = name.includes(":");
|
|
54441
54959
|
out.push({
|
|
54442
54960
|
name,
|
|
54443
54961
|
source: isPlugin ? "plugin" : "project",
|
|
54444
|
-
...
|
|
54962
|
+
...path89 ? { path: path89 } : {},
|
|
54445
54963
|
...description ? { description } : {},
|
|
54446
54964
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
54447
54965
|
});
|
|
@@ -54457,14 +54975,14 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
54457
54975
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
54458
54976
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
54459
54977
|
beforeRequest: (client) => {
|
|
54460
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
54978
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path30.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
54461
54979
|
}
|
|
54462
54980
|
});
|
|
54463
54981
|
return mapSkillsListResponse(res);
|
|
54464
54982
|
}
|
|
54465
54983
|
|
|
54466
54984
|
// src/tools/codex-turn-context.ts
|
|
54467
|
-
var
|
|
54985
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
54468
54986
|
function parseTurnContextFromRollout(raw) {
|
|
54469
54987
|
const lines = raw.split("\n");
|
|
54470
54988
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -54499,7 +55017,7 @@ async function readCodexTurnContext(args, deps = {}) {
|
|
|
54499
55017
|
);
|
|
54500
55018
|
const rolloutPath = str4(rec3(res?.thread)?.path);
|
|
54501
55019
|
if (!rolloutPath) return null;
|
|
54502
|
-
return parseTurnContextFromRollout(await
|
|
55020
|
+
return parseTurnContextFromRollout(await import_promises4.default.readFile(rolloutPath, "utf8"));
|
|
54503
55021
|
}
|
|
54504
55022
|
function createCodexResolvedMetaHydrator(deps) {
|
|
54505
55023
|
const fetchedThreadIds = /* @__PURE__ */ new Set();
|
|
@@ -54544,14 +55062,14 @@ function str4(v2) {
|
|
|
54544
55062
|
// src/workspace/browser.ts
|
|
54545
55063
|
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
54546
55064
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
54547
|
-
var
|
|
55065
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
54548
55066
|
init_protocol();
|
|
54549
55067
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
54550
55068
|
function resolveInsideCwd(cwd, subpath) {
|
|
54551
|
-
const absCwd =
|
|
54552
|
-
const joined =
|
|
54553
|
-
const rel =
|
|
54554
|
-
if (rel.startsWith("..") ||
|
|
55069
|
+
const absCwd = import_node_path31.default.resolve(cwd);
|
|
55070
|
+
const joined = import_node_path31.default.resolve(absCwd, subpath ?? ".");
|
|
55071
|
+
const rel = import_node_path31.default.relative(absCwd, joined);
|
|
55072
|
+
if (rel.startsWith("..") || import_node_path31.default.isAbsolute(rel)) {
|
|
54555
55073
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
54556
55074
|
}
|
|
54557
55075
|
return joined;
|
|
@@ -54582,7 +55100,7 @@ var WorkspaceBrowser = class {
|
|
|
54582
55100
|
mtime: ""
|
|
54583
55101
|
};
|
|
54584
55102
|
try {
|
|
54585
|
-
const st = import_node_fs28.default.statSync(
|
|
55103
|
+
const st = import_node_fs28.default.statSync(import_node_path31.default.join(full, d.name));
|
|
54586
55104
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
54587
55105
|
if (d.isFile()) entry.size = st.size;
|
|
54588
55106
|
} catch {
|
|
@@ -54629,7 +55147,7 @@ var WorkspaceBrowser = class {
|
|
|
54629
55147
|
// src/skills/agents-scanner.ts
|
|
54630
55148
|
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
54631
55149
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
54632
|
-
var
|
|
55150
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
54633
55151
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
54634
55152
|
function isDirLikeSync2(p2) {
|
|
54635
55153
|
try {
|
|
@@ -54667,10 +55185,10 @@ function scanAgentsDir(dir, source, seen, out) {
|
|
|
54667
55185
|
}
|
|
54668
55186
|
for (const ent of entries) {
|
|
54669
55187
|
if (!ent.name.endsWith(".md")) continue;
|
|
54670
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
55188
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path32.default.join(dir, ent.name)))) {
|
|
54671
55189
|
continue;
|
|
54672
55190
|
}
|
|
54673
|
-
const filePath =
|
|
55191
|
+
const filePath = import_node_path32.default.join(dir, ent.name);
|
|
54674
55192
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
54675
55193
|
if (seen.has(baseName)) continue;
|
|
54676
55194
|
seen.add(baseName);
|
|
@@ -54693,7 +55211,7 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
54693
55211
|
return;
|
|
54694
55212
|
}
|
|
54695
55213
|
for (const ent of entries) {
|
|
54696
|
-
const childPath =
|
|
55214
|
+
const childPath = import_node_path32.default.join(dir, ent.name);
|
|
54697
55215
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
54698
55216
|
walk2(childPath, [...namespaces, ent.name]);
|
|
54699
55217
|
continue;
|
|
@@ -54718,9 +55236,9 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
54718
55236
|
walk2(root, []);
|
|
54719
55237
|
}
|
|
54720
55238
|
function readInstalledPlugins2(home) {
|
|
54721
|
-
const pluginsDir =
|
|
54722
|
-
const v2 =
|
|
54723
|
-
const v1 =
|
|
55239
|
+
const pluginsDir = import_node_path32.default.join(home, ".claude", "plugins");
|
|
55240
|
+
const v2 = import_node_path32.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
55241
|
+
const v1 = import_node_path32.default.join(pluginsDir, "installed_plugins.json");
|
|
54724
55242
|
let raw = null;
|
|
54725
55243
|
for (const candidate of [v2, v1]) {
|
|
54726
55244
|
try {
|
|
@@ -54749,19 +55267,19 @@ function readInstalledPlugins2(home) {
|
|
|
54749
55267
|
return out;
|
|
54750
55268
|
}
|
|
54751
55269
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
54752
|
-
let cur =
|
|
54753
|
-
const fsRoot =
|
|
55270
|
+
let cur = import_node_path32.default.resolve(startCwd);
|
|
55271
|
+
const fsRoot = import_node_path32.default.parse(cur).root;
|
|
54754
55272
|
while (true) {
|
|
54755
|
-
scanAgentsDir(
|
|
55273
|
+
scanAgentsDir(import_node_path32.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
54756
55274
|
let hasGit = false;
|
|
54757
55275
|
try {
|
|
54758
|
-
hasGit = import_node_fs29.default.existsSync(
|
|
55276
|
+
hasGit = import_node_fs29.default.existsSync(import_node_path32.default.join(cur, ".git"));
|
|
54759
55277
|
} catch {
|
|
54760
55278
|
}
|
|
54761
55279
|
if (hasGit) return;
|
|
54762
55280
|
if (cur === home) return;
|
|
54763
55281
|
if (cur === fsRoot) return;
|
|
54764
|
-
const parent =
|
|
55282
|
+
const parent = import_node_path32.default.dirname(cur);
|
|
54765
55283
|
if (parent === cur) return;
|
|
54766
55284
|
cur = parent;
|
|
54767
55285
|
}
|
|
@@ -54796,7 +55314,7 @@ var AgentsScanner = class {
|
|
|
54796
55314
|
}
|
|
54797
55315
|
const fsBlock = [];
|
|
54798
55316
|
scanAgentsDir(
|
|
54799
|
-
|
|
55317
|
+
import_node_path32.default.join(this.home, ".claude", "agents"),
|
|
54800
55318
|
"global",
|
|
54801
55319
|
seen,
|
|
54802
55320
|
fsBlock
|
|
@@ -54810,7 +55328,7 @@ var AgentsScanner = class {
|
|
|
54810
55328
|
...this.extraPluginRoots
|
|
54811
55329
|
];
|
|
54812
55330
|
for (const { name, root } of plugins) {
|
|
54813
|
-
const agentsRoot =
|
|
55331
|
+
const agentsRoot = import_node_path32.default.join(root, "agents");
|
|
54814
55332
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
54815
55333
|
}
|
|
54816
55334
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -54820,13 +55338,13 @@ var AgentsScanner = class {
|
|
|
54820
55338
|
// src/observer/session-observer.ts
|
|
54821
55339
|
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
54822
55340
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
54823
|
-
var
|
|
55341
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
54824
55342
|
init_claude_history();
|
|
54825
55343
|
|
|
54826
55344
|
// src/observer/subagent-meta-observer.ts
|
|
54827
55345
|
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
54828
55346
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
54829
|
-
var
|
|
55347
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
54830
55348
|
init_claude_history();
|
|
54831
55349
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
54832
55350
|
var SubagentMetaObserver = class {
|
|
@@ -54839,7 +55357,7 @@ var SubagentMetaObserver = class {
|
|
|
54839
55357
|
watches = /* @__PURE__ */ new Map();
|
|
54840
55358
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
54841
55359
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
54842
|
-
return
|
|
55360
|
+
return import_node_path33.default.join(
|
|
54843
55361
|
this.home,
|
|
54844
55362
|
".claude",
|
|
54845
55363
|
"projects",
|
|
@@ -54895,7 +55413,7 @@ var SubagentMetaObserver = class {
|
|
|
54895
55413
|
if (!m2) return;
|
|
54896
55414
|
const agentId = m2[1];
|
|
54897
55415
|
if (w2.emitted.has(agentId)) return;
|
|
54898
|
-
const file =
|
|
55416
|
+
const file = import_node_path33.default.join(w2.dirPath, name);
|
|
54899
55417
|
let raw;
|
|
54900
55418
|
try {
|
|
54901
55419
|
raw = import_node_fs30.default.readFileSync(file, "utf8");
|
|
@@ -54955,7 +55473,7 @@ var SessionObserver = class {
|
|
|
54955
55473
|
metaObserver;
|
|
54956
55474
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
54957
55475
|
if (override) return override;
|
|
54958
|
-
return
|
|
55476
|
+
return import_node_path34.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
54959
55477
|
}
|
|
54960
55478
|
start(args) {
|
|
54961
55479
|
this.stop(args.sessionId);
|
|
@@ -54981,10 +55499,10 @@ var SessionObserver = class {
|
|
|
54981
55499
|
lastDeriveMs: 0
|
|
54982
55500
|
};
|
|
54983
55501
|
try {
|
|
54984
|
-
import_node_fs31.default.mkdirSync(
|
|
55502
|
+
import_node_fs31.default.mkdirSync(import_node_path34.default.dirname(filePath), { recursive: true });
|
|
54985
55503
|
} catch {
|
|
54986
55504
|
}
|
|
54987
|
-
w2.watcher = import_node_fs31.default.watch(
|
|
55505
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path34.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
54988
55506
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
54989
55507
|
this.poll(w2);
|
|
54990
55508
|
});
|
|
@@ -55081,7 +55599,7 @@ var SessionObserver = class {
|
|
|
55081
55599
|
const now = Date.now();
|
|
55082
55600
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
55083
55601
|
w2.lastRelocateScanMs = now;
|
|
55084
|
-
const projectsRoot =
|
|
55602
|
+
const projectsRoot = import_node_path34.default.join(this.home, ".claude", "projects");
|
|
55085
55603
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
55086
55604
|
if (!found || found === w2.filePath) return;
|
|
55087
55605
|
try {
|
|
@@ -55090,7 +55608,7 @@ var SessionObserver = class {
|
|
|
55090
55608
|
}
|
|
55091
55609
|
w2.filePath = found;
|
|
55092
55610
|
try {
|
|
55093
|
-
w2.watcher = import_node_fs31.default.watch(
|
|
55611
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path34.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
55094
55612
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
55095
55613
|
this.poll(w2);
|
|
55096
55614
|
});
|
|
@@ -55213,7 +55731,7 @@ function listRegistered() {
|
|
|
55213
55731
|
var import_node_child_process8 = require("child_process");
|
|
55214
55732
|
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
55215
55733
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
55216
|
-
var
|
|
55734
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55217
55735
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
55218
55736
|
var TITLE_MODEL_BY_TOOL = {
|
|
55219
55737
|
claude: "haiku",
|
|
@@ -55284,7 +55802,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
55284
55802
|
if (!text) return null;
|
|
55285
55803
|
let workDir;
|
|
55286
55804
|
try {
|
|
55287
|
-
workDir = import_node_fs32.default.mkdtempSync(
|
|
55805
|
+
workDir = import_node_fs32.default.mkdtempSync(import_node_path35.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
55288
55806
|
} catch {
|
|
55289
55807
|
return null;
|
|
55290
55808
|
}
|
|
@@ -55294,8 +55812,8 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
55294
55812
|
} catch {
|
|
55295
55813
|
}
|
|
55296
55814
|
};
|
|
55297
|
-
const outFile =
|
|
55298
|
-
const schemaFile =
|
|
55815
|
+
const outFile = import_node_path35.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
55816
|
+
const schemaFile = import_node_path35.default.join(workDir, "title-schema.json");
|
|
55299
55817
|
if (tool === "codex") {
|
|
55300
55818
|
try {
|
|
55301
55819
|
import_node_fs32.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
@@ -56033,8 +56551,8 @@ async function authenticate(token, deps) {
|
|
|
56033
56551
|
}
|
|
56034
56552
|
|
|
56035
56553
|
// src/legacy-cleanup.ts
|
|
56036
|
-
var
|
|
56037
|
-
var
|
|
56554
|
+
var fs41 = __toESM(require("fs/promises"), 1);
|
|
56555
|
+
var path43 = __toESM(require("path"), 1);
|
|
56038
56556
|
var LEGACY_FILES = [
|
|
56039
56557
|
"personal-capability.json",
|
|
56040
56558
|
"received-capabilities.json",
|
|
@@ -56043,9 +56561,9 @@ var LEGACY_FILES = [
|
|
|
56043
56561
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
56044
56562
|
const removed = [];
|
|
56045
56563
|
for (const name of LEGACY_FILES) {
|
|
56046
|
-
const p2 =
|
|
56564
|
+
const p2 = path43.join(dataDir, name);
|
|
56047
56565
|
try {
|
|
56048
|
-
await
|
|
56566
|
+
await fs41.unlink(p2);
|
|
56049
56567
|
removed.push(name);
|
|
56050
56568
|
logger.debug("legacy capability file removed", { file: name });
|
|
56051
56569
|
} catch (err) {
|
|
@@ -56057,13 +56575,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
56057
56575
|
}
|
|
56058
56576
|
|
|
56059
56577
|
// src/inbox/inbox-store.ts
|
|
56060
|
-
var
|
|
56061
|
-
var
|
|
56578
|
+
var fs42 = __toESM(require("fs"), 1);
|
|
56579
|
+
var path44 = __toESM(require("path"), 1);
|
|
56062
56580
|
var INBOX_SUBDIR = "inbox";
|
|
56063
56581
|
var InboxStore = class {
|
|
56064
56582
|
constructor(dataDir) {
|
|
56065
56583
|
this.dataDir = dataDir;
|
|
56066
|
-
|
|
56584
|
+
fs42.mkdirSync(this.dirPath(), { recursive: true });
|
|
56067
56585
|
}
|
|
56068
56586
|
dataDir;
|
|
56069
56587
|
/**
|
|
@@ -56075,7 +56593,7 @@ var InboxStore = class {
|
|
|
56075
56593
|
const file = this.filePath(peerDeviceId);
|
|
56076
56594
|
let raw;
|
|
56077
56595
|
try {
|
|
56078
|
-
raw =
|
|
56596
|
+
raw = fs42.readFileSync(file, "utf8");
|
|
56079
56597
|
} catch (err) {
|
|
56080
56598
|
if (err?.code === "ENOENT") return [];
|
|
56081
56599
|
return [];
|
|
@@ -56091,7 +56609,7 @@ var InboxStore = class {
|
|
|
56091
56609
|
const dir = this.dirPath();
|
|
56092
56610
|
let entries;
|
|
56093
56611
|
try {
|
|
56094
|
-
entries =
|
|
56612
|
+
entries = fs42.readdirSync(dir);
|
|
56095
56613
|
} catch (err) {
|
|
56096
56614
|
if (err?.code === "ENOENT") return [];
|
|
56097
56615
|
return [];
|
|
@@ -56107,9 +56625,9 @@ var InboxStore = class {
|
|
|
56107
56625
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
56108
56626
|
const file = this.filePath(message.peerDeviceId);
|
|
56109
56627
|
const line = JSON.stringify(message) + "\n";
|
|
56110
|
-
|
|
56628
|
+
fs42.appendFileSync(file, line, { mode: 384 });
|
|
56111
56629
|
try {
|
|
56112
|
-
|
|
56630
|
+
fs42.chmodSync(file, 384);
|
|
56113
56631
|
} catch {
|
|
56114
56632
|
}
|
|
56115
56633
|
}
|
|
@@ -56139,7 +56657,7 @@ var InboxStore = class {
|
|
|
56139
56657
|
removeByPeerDeviceId(peerDeviceId) {
|
|
56140
56658
|
const file = this.filePath(peerDeviceId);
|
|
56141
56659
|
try {
|
|
56142
|
-
|
|
56660
|
+
fs42.unlinkSync(file);
|
|
56143
56661
|
} catch (err) {
|
|
56144
56662
|
if (err?.code === "ENOENT") return;
|
|
56145
56663
|
}
|
|
@@ -56148,18 +56666,18 @@ var InboxStore = class {
|
|
|
56148
56666
|
const file = this.filePath(peerDeviceId);
|
|
56149
56667
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
56150
56668
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
56151
|
-
|
|
56152
|
-
|
|
56669
|
+
fs42.writeFileSync(tmp, content, { mode: 384 });
|
|
56670
|
+
fs42.renameSync(tmp, file);
|
|
56153
56671
|
try {
|
|
56154
|
-
|
|
56672
|
+
fs42.chmodSync(file, 384);
|
|
56155
56673
|
} catch {
|
|
56156
56674
|
}
|
|
56157
56675
|
}
|
|
56158
56676
|
dirPath() {
|
|
56159
|
-
return
|
|
56677
|
+
return path44.join(this.dataDir, INBOX_SUBDIR);
|
|
56160
56678
|
}
|
|
56161
56679
|
filePath(peerDeviceId) {
|
|
56162
|
-
return
|
|
56680
|
+
return path44.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
56163
56681
|
}
|
|
56164
56682
|
};
|
|
56165
56683
|
function parseAllLines(raw) {
|
|
@@ -56247,8 +56765,8 @@ var InboxManager = class {
|
|
|
56247
56765
|
};
|
|
56248
56766
|
|
|
56249
56767
|
// src/state/contact-store.ts
|
|
56250
|
-
var
|
|
56251
|
-
var
|
|
56768
|
+
var fs43 = __toESM(require("fs"), 1);
|
|
56769
|
+
var path45 = __toESM(require("path"), 1);
|
|
56252
56770
|
var FILE_NAME = "contacts.json";
|
|
56253
56771
|
var ContactStore = class {
|
|
56254
56772
|
constructor(dataDir) {
|
|
@@ -56258,10 +56776,10 @@ var ContactStore = class {
|
|
|
56258
56776
|
contacts = /* @__PURE__ */ new Map();
|
|
56259
56777
|
load() {
|
|
56260
56778
|
this.contacts.clear();
|
|
56261
|
-
const file =
|
|
56779
|
+
const file = path45.join(this.dataDir, FILE_NAME);
|
|
56262
56780
|
let raw;
|
|
56263
56781
|
try {
|
|
56264
|
-
raw =
|
|
56782
|
+
raw = fs43.readFileSync(file, "utf8");
|
|
56265
56783
|
} catch (err) {
|
|
56266
56784
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
56267
56785
|
return;
|
|
@@ -56330,20 +56848,20 @@ var ContactStore = class {
|
|
|
56330
56848
|
return true;
|
|
56331
56849
|
}
|
|
56332
56850
|
flush() {
|
|
56333
|
-
const file =
|
|
56851
|
+
const file = path45.join(this.dataDir, FILE_NAME);
|
|
56334
56852
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
56335
56853
|
const content = JSON.stringify(
|
|
56336
56854
|
{ contacts: Array.from(this.contacts.values()) },
|
|
56337
56855
|
null,
|
|
56338
56856
|
2
|
|
56339
56857
|
);
|
|
56340
|
-
|
|
56341
|
-
|
|
56342
|
-
|
|
56858
|
+
fs43.mkdirSync(this.dataDir, { recursive: true });
|
|
56859
|
+
fs43.writeFileSync(tmp, content, { mode: 384 });
|
|
56860
|
+
fs43.renameSync(tmp, file);
|
|
56343
56861
|
}
|
|
56344
56862
|
renameBak(file) {
|
|
56345
56863
|
try {
|
|
56346
|
-
|
|
56864
|
+
fs43.renameSync(file, `${file}.bak`);
|
|
56347
56865
|
} catch {
|
|
56348
56866
|
}
|
|
56349
56867
|
}
|
|
@@ -56451,61 +56969,61 @@ async function connectRemote(args) {
|
|
|
56451
56969
|
}
|
|
56452
56970
|
|
|
56453
56971
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
56454
|
-
var
|
|
56455
|
-
var
|
|
56972
|
+
var fs44 = __toESM(require("fs"), 1);
|
|
56973
|
+
var path46 = __toESM(require("path"), 1);
|
|
56456
56974
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
56457
56975
|
function migrateFlattenSessions(opts) {
|
|
56458
56976
|
const dataDir = opts.dataDir;
|
|
56459
56977
|
const now = opts.now ?? Date.now;
|
|
56460
|
-
const sessionsDir =
|
|
56461
|
-
const flagPath =
|
|
56978
|
+
const sessionsDir = path46.join(dataDir, "sessions");
|
|
56979
|
+
const flagPath = path46.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
56462
56980
|
if (existsSync3(flagPath)) {
|
|
56463
56981
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
56464
56982
|
}
|
|
56465
56983
|
let movedBare = 0;
|
|
56466
56984
|
let movedVmOwner = 0;
|
|
56467
56985
|
let archivedListener = 0;
|
|
56468
|
-
const defaultDir =
|
|
56986
|
+
const defaultDir = path46.join(sessionsDir, "default");
|
|
56469
56987
|
if (existsSync3(defaultDir)) {
|
|
56470
56988
|
for (const entry of readdirSafe(defaultDir)) {
|
|
56471
56989
|
if (!entry.endsWith(".json")) continue;
|
|
56472
|
-
const src =
|
|
56473
|
-
const dst =
|
|
56474
|
-
|
|
56990
|
+
const src = path46.join(defaultDir, entry);
|
|
56991
|
+
const dst = path46.join(sessionsDir, entry);
|
|
56992
|
+
fs44.renameSync(src, dst);
|
|
56475
56993
|
movedBare += 1;
|
|
56476
56994
|
}
|
|
56477
56995
|
rmdirIfEmpty(defaultDir);
|
|
56478
56996
|
}
|
|
56479
56997
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
56480
|
-
const personaDir =
|
|
56998
|
+
const personaDir = path46.join(sessionsDir, pid);
|
|
56481
56999
|
if (!isDir(personaDir)) continue;
|
|
56482
57000
|
if (pid === "default") continue;
|
|
56483
|
-
const ownerSrc =
|
|
57001
|
+
const ownerSrc = path46.join(personaDir, "owner");
|
|
56484
57002
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
56485
|
-
const ownerDst =
|
|
56486
|
-
|
|
57003
|
+
const ownerDst = path46.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
57004
|
+
fs44.mkdirSync(ownerDst, { recursive: true });
|
|
56487
57005
|
for (const file of readdirSafe(ownerSrc)) {
|
|
56488
57006
|
if (!file.endsWith(".json")) continue;
|
|
56489
|
-
|
|
57007
|
+
fs44.renameSync(path46.join(ownerSrc, file), path46.join(ownerDst, file));
|
|
56490
57008
|
movedVmOwner += 1;
|
|
56491
57009
|
}
|
|
56492
57010
|
rmdirIfEmpty(ownerSrc);
|
|
56493
57011
|
}
|
|
56494
|
-
const listenerSrc =
|
|
57012
|
+
const listenerSrc = path46.join(personaDir, "listener");
|
|
56495
57013
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
56496
|
-
const archiveDst =
|
|
56497
|
-
|
|
57014
|
+
const archiveDst = path46.join(dataDir, ".legacy", `listener-${pid}`);
|
|
57015
|
+
fs44.mkdirSync(archiveDst, { recursive: true });
|
|
56498
57016
|
for (const file of readdirSafe(listenerSrc)) {
|
|
56499
57017
|
if (!file.endsWith(".json")) continue;
|
|
56500
|
-
|
|
57018
|
+
fs44.renameSync(path46.join(listenerSrc, file), path46.join(archiveDst, file));
|
|
56501
57019
|
archivedListener += 1;
|
|
56502
57020
|
}
|
|
56503
57021
|
rmdirIfEmpty(listenerSrc);
|
|
56504
57022
|
}
|
|
56505
57023
|
rmdirIfEmpty(personaDir);
|
|
56506
57024
|
}
|
|
56507
|
-
|
|
56508
|
-
|
|
57025
|
+
fs44.mkdirSync(sessionsDir, { recursive: true });
|
|
57026
|
+
fs44.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
56509
57027
|
return {
|
|
56510
57028
|
skipped: false,
|
|
56511
57029
|
flagWritten: true,
|
|
@@ -56516,7 +57034,7 @@ function migrateFlattenSessions(opts) {
|
|
|
56516
57034
|
}
|
|
56517
57035
|
function existsSync3(p2) {
|
|
56518
57036
|
try {
|
|
56519
|
-
|
|
57037
|
+
fs44.statSync(p2);
|
|
56520
57038
|
return true;
|
|
56521
57039
|
} catch {
|
|
56522
57040
|
return false;
|
|
@@ -56524,61 +57042,61 @@ function existsSync3(p2) {
|
|
|
56524
57042
|
}
|
|
56525
57043
|
function isDir(p2) {
|
|
56526
57044
|
try {
|
|
56527
|
-
return
|
|
57045
|
+
return fs44.statSync(p2).isDirectory();
|
|
56528
57046
|
} catch {
|
|
56529
57047
|
return false;
|
|
56530
57048
|
}
|
|
56531
57049
|
}
|
|
56532
57050
|
function readdirSafe(p2) {
|
|
56533
57051
|
try {
|
|
56534
|
-
return
|
|
57052
|
+
return fs44.readdirSync(p2);
|
|
56535
57053
|
} catch {
|
|
56536
57054
|
return [];
|
|
56537
57055
|
}
|
|
56538
57056
|
}
|
|
56539
57057
|
function rmdirIfEmpty(p2) {
|
|
56540
57058
|
try {
|
|
56541
|
-
|
|
57059
|
+
fs44.rmdirSync(p2);
|
|
56542
57060
|
} catch {
|
|
56543
57061
|
}
|
|
56544
57062
|
}
|
|
56545
57063
|
|
|
56546
57064
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
56547
|
-
var
|
|
56548
|
-
var
|
|
57065
|
+
var fs45 = __toESM(require("fs"), 1);
|
|
57066
|
+
var path47 = __toESM(require("path"), 1);
|
|
56549
57067
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
56550
57068
|
function dropSeededProjects(opts) {
|
|
56551
|
-
|
|
56552
|
-
const flag =
|
|
56553
|
-
if (
|
|
56554
|
-
const file =
|
|
57069
|
+
fs45.mkdirSync(opts.dataDir, { recursive: true });
|
|
57070
|
+
const flag = path47.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
57071
|
+
if (fs45.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
57072
|
+
const file = path47.join(opts.dataDir, "projects.json");
|
|
56555
57073
|
let raw = null;
|
|
56556
57074
|
let dropped = 0;
|
|
56557
57075
|
try {
|
|
56558
|
-
raw =
|
|
57076
|
+
raw = fs45.readFileSync(file, "utf8");
|
|
56559
57077
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
56560
57078
|
} catch {
|
|
56561
57079
|
}
|
|
56562
57080
|
let backup = null;
|
|
56563
57081
|
if (raw != null && dropped > 0) {
|
|
56564
|
-
const dir =
|
|
56565
|
-
|
|
56566
|
-
backup =
|
|
56567
|
-
|
|
57082
|
+
const dir = path47.join(opts.dataDir, "backups");
|
|
57083
|
+
fs45.mkdirSync(dir, { recursive: true });
|
|
57084
|
+
backup = path47.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
57085
|
+
fs45.writeFileSync(backup, raw);
|
|
56568
57086
|
}
|
|
56569
57087
|
if (raw != null || dropped > 0) {
|
|
56570
|
-
|
|
57088
|
+
fs45.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
56571
57089
|
}
|
|
56572
|
-
|
|
57090
|
+
fs45.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
56573
57091
|
return { skipped: false, dropped, backup };
|
|
56574
57092
|
}
|
|
56575
57093
|
|
|
56576
57094
|
// src/transport/http-router.ts
|
|
56577
57095
|
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
56578
|
-
var
|
|
57096
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
56579
57097
|
|
|
56580
57098
|
// src/attachment/mime.ts
|
|
56581
|
-
var
|
|
57099
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
56582
57100
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
56583
57101
|
var EXT_TO_NATIVE_MIME = {
|
|
56584
57102
|
// 图片
|
|
@@ -56685,7 +57203,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
56685
57203
|
".mk"
|
|
56686
57204
|
]);
|
|
56687
57205
|
function lookupMime(filePathOrName) {
|
|
56688
|
-
const ext =
|
|
57206
|
+
const ext = import_node_path36.default.extname(filePathOrName).toLowerCase();
|
|
56689
57207
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
56690
57208
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
56691
57209
|
return "application/octet-stream";
|
|
@@ -56756,9 +57274,9 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
56756
57274
|
|
|
56757
57275
|
// src/attachment/upload.ts
|
|
56758
57276
|
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
56759
|
-
var
|
|
57277
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56760
57278
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
56761
|
-
var
|
|
57279
|
+
var import_promises5 = require("stream/promises");
|
|
56762
57280
|
var UploadError = class extends Error {
|
|
56763
57281
|
constructor(code, message) {
|
|
56764
57282
|
super(message);
|
|
@@ -56768,14 +57286,14 @@ var UploadError = class extends Error {
|
|
|
56768
57286
|
code;
|
|
56769
57287
|
};
|
|
56770
57288
|
function assertValidFileName(fileName) {
|
|
56771
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
57289
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path37.default.basename(fileName)) {
|
|
56772
57290
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
56773
57291
|
}
|
|
56774
57292
|
}
|
|
56775
57293
|
var HASH_PREFIX_LEN = 16;
|
|
56776
57294
|
async function writeUploadedAttachment(args) {
|
|
56777
57295
|
assertValidFileName(args.fileName);
|
|
56778
|
-
const attachmentsRoot =
|
|
57296
|
+
const attachmentsRoot = import_node_path37.default.join(args.baseDir, ".attachments");
|
|
56779
57297
|
try {
|
|
56780
57298
|
import_node_fs33.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
56781
57299
|
} catch (err) {
|
|
@@ -56783,12 +57301,12 @@ async function writeUploadedAttachment(args) {
|
|
|
56783
57301
|
}
|
|
56784
57302
|
const hasher = import_node_crypto9.default.createHash("sha256");
|
|
56785
57303
|
let actualSize = 0;
|
|
56786
|
-
const tmpPath =
|
|
57304
|
+
const tmpPath = import_node_path37.default.join(
|
|
56787
57305
|
attachmentsRoot,
|
|
56788
57306
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
|
|
56789
57307
|
);
|
|
56790
57308
|
try {
|
|
56791
|
-
await (0,
|
|
57309
|
+
await (0, import_promises5.pipeline)(
|
|
56792
57310
|
args.body,
|
|
56793
57311
|
async function* (source) {
|
|
56794
57312
|
for await (const chunk of source) {
|
|
@@ -56818,7 +57336,7 @@ async function writeUploadedAttachment(args) {
|
|
|
56818
57336
|
);
|
|
56819
57337
|
}
|
|
56820
57338
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
56821
|
-
const hashDir =
|
|
57339
|
+
const hashDir = import_node_path37.default.join(attachmentsRoot, attachmentId);
|
|
56822
57340
|
let finalFileName;
|
|
56823
57341
|
let hashDirExists = false;
|
|
56824
57342
|
try {
|
|
@@ -56836,7 +57354,7 @@ async function writeUploadedAttachment(args) {
|
|
|
56836
57354
|
try {
|
|
56837
57355
|
import_node_fs33.default.mkdirSync(hashDir, { recursive: true });
|
|
56838
57356
|
finalFileName = args.fileName;
|
|
56839
|
-
import_node_fs33.default.renameSync(tmpPath,
|
|
57357
|
+
import_node_fs33.default.renameSync(tmpPath, import_node_path37.default.join(hashDir, finalFileName));
|
|
56840
57358
|
} catch (err) {
|
|
56841
57359
|
try {
|
|
56842
57360
|
import_node_fs33.default.unlinkSync(tmpPath);
|
|
@@ -56845,7 +57363,7 @@ async function writeUploadedAttachment(args) {
|
|
|
56845
57363
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
56846
57364
|
}
|
|
56847
57365
|
}
|
|
56848
|
-
const absPath =
|
|
57366
|
+
const absPath = import_node_path37.default.join(hashDir, finalFileName);
|
|
56849
57367
|
const relPath = absPath;
|
|
56850
57368
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
56851
57369
|
relPath: absPath,
|
|
@@ -56859,8 +57377,8 @@ async function writeUploadedAttachment(args) {
|
|
|
56859
57377
|
}
|
|
56860
57378
|
|
|
56861
57379
|
// src/extension/import.ts
|
|
56862
|
-
var
|
|
56863
|
-
var
|
|
57380
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
57381
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
56864
57382
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
56865
57383
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
56866
57384
|
var ImportError = class extends Error {
|
|
@@ -56878,7 +57396,7 @@ async function importZip(buf, root) {
|
|
|
56878
57396
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
56879
57397
|
}
|
|
56880
57398
|
for (const name of Object.keys(zip.files)) {
|
|
56881
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
57399
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path38.default.isAbsolute(name)) {
|
|
56882
57400
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
56883
57401
|
}
|
|
56884
57402
|
}
|
|
@@ -56911,33 +57429,33 @@ async function importZip(buf, root) {
|
|
|
56911
57429
|
);
|
|
56912
57430
|
}
|
|
56913
57431
|
}
|
|
56914
|
-
const destDir =
|
|
57432
|
+
const destDir = import_node_path38.default.join(root, manifest.id);
|
|
56915
57433
|
let destExists = false;
|
|
56916
57434
|
try {
|
|
56917
|
-
await
|
|
57435
|
+
await import_promises6.default.access(destDir);
|
|
56918
57436
|
destExists = true;
|
|
56919
57437
|
} catch {
|
|
56920
57438
|
}
|
|
56921
57439
|
if (destExists) {
|
|
56922
57440
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
56923
57441
|
}
|
|
56924
|
-
const stage = await
|
|
57442
|
+
const stage = await import_promises6.default.mkdtemp(import_node_path38.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
56925
57443
|
try {
|
|
56926
57444
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56927
|
-
const dest =
|
|
57445
|
+
const dest = import_node_path38.default.join(stage, name);
|
|
56928
57446
|
if (entry.dir) {
|
|
56929
|
-
await
|
|
57447
|
+
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
56930
57448
|
continue;
|
|
56931
57449
|
}
|
|
56932
|
-
await
|
|
57450
|
+
await import_promises6.default.mkdir(import_node_path38.default.dirname(dest), { recursive: true });
|
|
56933
57451
|
const content = await entry.async("nodebuffer");
|
|
56934
|
-
await
|
|
57452
|
+
await import_promises6.default.writeFile(dest, content);
|
|
56935
57453
|
}
|
|
56936
|
-
await
|
|
56937
|
-
await
|
|
57454
|
+
await import_promises6.default.mkdir(root, { recursive: true });
|
|
57455
|
+
await import_promises6.default.rename(stage, destDir);
|
|
56938
57456
|
return { extId: manifest.id };
|
|
56939
57457
|
} catch (e) {
|
|
56940
|
-
await
|
|
57458
|
+
await import_promises6.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
56941
57459
|
});
|
|
56942
57460
|
throw e;
|
|
56943
57461
|
}
|
|
@@ -56959,7 +57477,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
56959
57477
|
".wasm": "application/wasm"
|
|
56960
57478
|
};
|
|
56961
57479
|
function shareUiAssetMime(filePath) {
|
|
56962
|
-
const ext =
|
|
57480
|
+
const ext = import_node_path39.default.extname(filePath).toLowerCase();
|
|
56963
57481
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
56964
57482
|
}
|
|
56965
57483
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -57058,7 +57576,7 @@ function isValidUploadFileName(fileName) {
|
|
|
57058
57576
|
if (fileName === "." || fileName === "..") return false;
|
|
57059
57577
|
if (fileName.startsWith(".")) return false;
|
|
57060
57578
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
57061
|
-
return fileName ===
|
|
57579
|
+
return fileName === import_node_path39.default.basename(fileName);
|
|
57062
57580
|
}
|
|
57063
57581
|
function createHttpRouter(deps) {
|
|
57064
57582
|
return async (req, res) => {
|
|
@@ -57294,7 +57812,7 @@ function createHttpRouter(deps) {
|
|
|
57294
57812
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
57295
57813
|
return true;
|
|
57296
57814
|
}
|
|
57297
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
57815
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path39.default.basename(r.absPath)));
|
|
57298
57816
|
return true;
|
|
57299
57817
|
}
|
|
57300
57818
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -57415,7 +57933,7 @@ function createHttpRouter(deps) {
|
|
|
57415
57933
|
return true;
|
|
57416
57934
|
}
|
|
57417
57935
|
let absPath;
|
|
57418
|
-
if (
|
|
57936
|
+
if (import_node_path39.default.isAbsolute(pathParam)) {
|
|
57419
57937
|
absPath = pathParam;
|
|
57420
57938
|
} else if (deps.sessionStore) {
|
|
57421
57939
|
const file = deps.sessionStore.read(sid);
|
|
@@ -57423,7 +57941,7 @@ function createHttpRouter(deps) {
|
|
|
57423
57941
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
57424
57942
|
return true;
|
|
57425
57943
|
}
|
|
57426
|
-
absPath =
|
|
57944
|
+
absPath = import_node_path39.default.join(file.cwd, pathParam);
|
|
57427
57945
|
} else {
|
|
57428
57946
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
57429
57947
|
return true;
|
|
@@ -57525,7 +58043,7 @@ function streamFile(res, absPath, logger) {
|
|
|
57525
58043
|
return;
|
|
57526
58044
|
}
|
|
57527
58045
|
const mime = lookupMime(absPath);
|
|
57528
|
-
const basename2 =
|
|
58046
|
+
const basename2 = import_node_path39.default.basename(absPath);
|
|
57529
58047
|
res.writeHead(200, {
|
|
57530
58048
|
"Content-Type": mime,
|
|
57531
58049
|
"Content-Length": String(stat.size),
|
|
@@ -57543,7 +58061,7 @@ function streamFile(res, absPath, logger) {
|
|
|
57543
58061
|
|
|
57544
58062
|
// src/attachment/gc.ts
|
|
57545
58063
|
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
57546
|
-
var
|
|
58064
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
57547
58065
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
57548
58066
|
function runAttachmentGc(args) {
|
|
57549
58067
|
const now = (args.now ?? Date.now)();
|
|
@@ -57552,12 +58070,12 @@ function runAttachmentGc(args) {
|
|
|
57552
58070
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
57553
58071
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
57554
58072
|
if (entry.stale) continue;
|
|
57555
|
-
if (
|
|
58073
|
+
if (import_node_path40.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
57556
58074
|
}
|
|
57557
58075
|
}
|
|
57558
58076
|
const visited = /* @__PURE__ */ new Set();
|
|
57559
58077
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
57560
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
58078
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path40.default.join(
|
|
57561
58079
|
args.dataDir,
|
|
57562
58080
|
"sessions",
|
|
57563
58081
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -57570,7 +58088,7 @@ function runAttachmentGc(args) {
|
|
|
57570
58088
|
return true;
|
|
57571
58089
|
});
|
|
57572
58090
|
for (const rootDir of roots) {
|
|
57573
|
-
const attRoot =
|
|
58091
|
+
const attRoot = import_node_path40.default.join(rootDir, ".attachments");
|
|
57574
58092
|
let hashDirs;
|
|
57575
58093
|
try {
|
|
57576
58094
|
hashDirs = import_node_fs35.default.readdirSync(attRoot);
|
|
@@ -57580,7 +58098,7 @@ function runAttachmentGc(args) {
|
|
|
57580
58098
|
continue;
|
|
57581
58099
|
}
|
|
57582
58100
|
for (const hashDir of hashDirs) {
|
|
57583
|
-
const hashDirAbs =
|
|
58101
|
+
const hashDirAbs = import_node_path40.default.join(attRoot, hashDir);
|
|
57584
58102
|
let files;
|
|
57585
58103
|
try {
|
|
57586
58104
|
files = import_node_fs35.default.readdirSync(hashDirAbs);
|
|
@@ -57588,7 +58106,7 @@ function runAttachmentGc(args) {
|
|
|
57588
58106
|
continue;
|
|
57589
58107
|
}
|
|
57590
58108
|
for (const name of files) {
|
|
57591
|
-
const file =
|
|
58109
|
+
const file = import_node_path40.default.join(hashDirAbs, name);
|
|
57592
58110
|
let stat;
|
|
57593
58111
|
try {
|
|
57594
58112
|
stat = import_node_fs35.default.statSync(file);
|
|
@@ -57620,7 +58138,7 @@ function runAttachmentGc(args) {
|
|
|
57620
58138
|
|
|
57621
58139
|
// src/attachment/group.ts
|
|
57622
58140
|
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
57623
|
-
var
|
|
58141
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
57624
58142
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
57625
58143
|
init_protocol();
|
|
57626
58144
|
var GroupFileStore = class {
|
|
@@ -57632,11 +58150,11 @@ var GroupFileStore = class {
|
|
|
57632
58150
|
this.logger = opts.logger;
|
|
57633
58151
|
}
|
|
57634
58152
|
rootForScope(scope) {
|
|
57635
|
-
return
|
|
58153
|
+
return import_node_path41.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
57636
58154
|
}
|
|
57637
58155
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
57638
58156
|
filePath(scope, sessionId) {
|
|
57639
|
-
return
|
|
58157
|
+
return import_node_path41.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
57640
58158
|
}
|
|
57641
58159
|
cacheKey(scope, sessionId) {
|
|
57642
58160
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -57671,7 +58189,7 @@ var GroupFileStore = class {
|
|
|
57671
58189
|
}
|
|
57672
58190
|
writeFile(scope, sessionId, entries) {
|
|
57673
58191
|
const file = this.filePath(scope, sessionId);
|
|
57674
|
-
import_node_fs36.default.mkdirSync(
|
|
58192
|
+
import_node_fs36.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
|
|
57675
58193
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
57676
58194
|
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
57677
58195
|
import_node_fs36.default.renameSync(tmp, file);
|
|
@@ -57761,9 +58279,9 @@ var GroupFileStore = class {
|
|
|
57761
58279
|
|
|
57762
58280
|
// src/discovery/state-file.ts
|
|
57763
58281
|
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
57764
|
-
var
|
|
58282
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
57765
58283
|
function defaultStateFilePath(dataDir) {
|
|
57766
|
-
return
|
|
58284
|
+
return import_node_path42.default.join(dataDir, "state.json");
|
|
57767
58285
|
}
|
|
57768
58286
|
function isPidAlive(pid) {
|
|
57769
58287
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -57799,7 +58317,7 @@ var StateFileManager = class {
|
|
|
57799
58317
|
return { status: "stale", existing };
|
|
57800
58318
|
}
|
|
57801
58319
|
write(state) {
|
|
57802
|
-
import_node_fs37.default.mkdirSync(
|
|
58320
|
+
import_node_fs37.default.mkdirSync(import_node_path42.default.dirname(this.file), { recursive: true });
|
|
57803
58321
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
57804
58322
|
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
57805
58323
|
import_node_fs37.default.renameSync(tmp, this.file);
|
|
@@ -57827,13 +58345,13 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
57827
58345
|
|
|
57828
58346
|
// src/tunnel/tunnel-manager.ts
|
|
57829
58347
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
57830
|
-
var
|
|
58348
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
57831
58349
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
57832
58350
|
var import_node_child_process11 = require("child_process");
|
|
57833
58351
|
|
|
57834
58352
|
// src/tunnel/tunnel-store.ts
|
|
57835
58353
|
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
57836
|
-
var
|
|
58354
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
57837
58355
|
var TunnelStore = class {
|
|
57838
58356
|
constructor(filePath) {
|
|
57839
58357
|
this.filePath = filePath;
|
|
@@ -57852,7 +58370,7 @@ var TunnelStore = class {
|
|
|
57852
58370
|
}
|
|
57853
58371
|
}
|
|
57854
58372
|
async set(v2) {
|
|
57855
|
-
const dir =
|
|
58373
|
+
const dir = import_node_path43.default.dirname(this.filePath);
|
|
57856
58374
|
await import_node_fs38.default.promises.mkdir(dir, { recursive: true });
|
|
57857
58375
|
const data = JSON.stringify(v2, null, 2);
|
|
57858
58376
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
@@ -57964,10 +58482,10 @@ function escape(v2) {
|
|
|
57964
58482
|
// src/tunnel/frpc-binary.ts
|
|
57965
58483
|
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
57966
58484
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
57967
|
-
var
|
|
58485
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
57968
58486
|
var import_node_child_process9 = require("child_process");
|
|
57969
58487
|
var import_node_stream3 = require("stream");
|
|
57970
|
-
var
|
|
58488
|
+
var import_promises7 = require("stream/promises");
|
|
57971
58489
|
var FRPC_VERSION = "0.68.0";
|
|
57972
58490
|
var UnsupportedPlatformError = class extends Error {
|
|
57973
58491
|
constructor(platform, arch) {
|
|
@@ -58003,13 +58521,13 @@ async function ensureFrpcBinary(opts) {
|
|
|
58003
58521
|
}
|
|
58004
58522
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
58005
58523
|
const platform = opts.platform ?? detectPlatform();
|
|
58006
|
-
const binDir =
|
|
58524
|
+
const binDir = import_node_path44.default.join(opts.dataDir, "bin");
|
|
58007
58525
|
import_node_fs39.default.mkdirSync(binDir, { recursive: true });
|
|
58008
58526
|
cleanupStaleArtifacts(binDir);
|
|
58009
|
-
const stableBin =
|
|
58527
|
+
const stableBin = import_node_path44.default.join(binDir, "frpc");
|
|
58010
58528
|
if (import_node_fs39.default.existsSync(stableBin)) return stableBin;
|
|
58011
58529
|
const partialBin = `${stableBin}.partial`;
|
|
58012
|
-
const tarballPath =
|
|
58530
|
+
const tarballPath = import_node_path44.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
58013
58531
|
try {
|
|
58014
58532
|
const url = frpcDownloadUrl(version2, platform);
|
|
58015
58533
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -58035,7 +58553,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
58035
58553
|
}
|
|
58036
58554
|
for (const name of entries) {
|
|
58037
58555
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
58038
|
-
const full =
|
|
58556
|
+
const full = import_node_path44.default.join(binDir, name);
|
|
58039
58557
|
try {
|
|
58040
58558
|
import_node_fs39.default.rmSync(full, { recursive: true, force: true });
|
|
58041
58559
|
} catch {
|
|
@@ -58058,10 +58576,10 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
58058
58576
|
}
|
|
58059
58577
|
const out = import_node_fs39.default.createWriteStream(dest);
|
|
58060
58578
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
58061
|
-
await (0,
|
|
58579
|
+
await (0, import_promises7.pipeline)(nodeStream, out);
|
|
58062
58580
|
}
|
|
58063
58581
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
58064
|
-
const work =
|
|
58582
|
+
const work = import_node_path44.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
58065
58583
|
import_node_fs39.default.mkdirSync(work, { recursive: true });
|
|
58066
58584
|
try {
|
|
58067
58585
|
await new Promise((resolve9, reject) => {
|
|
@@ -58070,7 +58588,7 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
58070
58588
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
58071
58589
|
});
|
|
58072
58590
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
58073
|
-
const src =
|
|
58591
|
+
const src = import_node_path44.default.join(work, dirName, "frpc");
|
|
58074
58592
|
if (!import_node_fs39.default.existsSync(src)) {
|
|
58075
58593
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
58076
58594
|
}
|
|
@@ -58082,10 +58600,10 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
58082
58600
|
|
|
58083
58601
|
// src/tunnel/frpc-process.ts
|
|
58084
58602
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
58085
|
-
var
|
|
58603
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
58086
58604
|
var import_node_child_process10 = require("child_process");
|
|
58087
58605
|
function frpcPidFilePath(dataDir) {
|
|
58088
|
-
return
|
|
58606
|
+
return import_node_path45.default.join(dataDir, "frpc.pid");
|
|
58089
58607
|
}
|
|
58090
58608
|
function writeFrpcPid(dataDir, pid) {
|
|
58091
58609
|
try {
|
|
@@ -58127,7 +58645,7 @@ function defaultSleep2(ms) {
|
|
|
58127
58645
|
}
|
|
58128
58646
|
async function killStaleFrpc(deps) {
|
|
58129
58647
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
58130
|
-
const tomlPath =
|
|
58648
|
+
const tomlPath = import_node_path45.default.join(deps.dataDir, "frpc.toml");
|
|
58131
58649
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
58132
58650
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
58133
58651
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -58199,7 +58717,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
58199
58717
|
var TunnelManager = class {
|
|
58200
58718
|
constructor(deps) {
|
|
58201
58719
|
this.deps = deps;
|
|
58202
|
-
this.store = deps.store ?? new TunnelStore(
|
|
58720
|
+
this.store = deps.store ?? new TunnelStore(import_node_path46.default.join(deps.dataDir, "tunnel.json"));
|
|
58203
58721
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
58204
58722
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
58205
58723
|
}
|
|
@@ -58326,7 +58844,7 @@ var TunnelManager = class {
|
|
|
58326
58844
|
dataDir: this.deps.dataDir,
|
|
58327
58845
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
58328
58846
|
});
|
|
58329
|
-
const tomlPath =
|
|
58847
|
+
const tomlPath = import_node_path46.default.join(this.deps.dataDir, "frpc.toml");
|
|
58330
58848
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
|
|
58331
58849
|
const toml = buildFrpcToml({
|
|
58332
58850
|
serverAddr: t.frpsHost,
|
|
@@ -58341,9 +58859,9 @@ var TunnelManager = class {
|
|
|
58341
58859
|
const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(frpcBin, ["-c", tomlPath], {
|
|
58342
58860
|
stdio: ["ignore", "pipe", "pipe"]
|
|
58343
58861
|
});
|
|
58344
|
-
const logDir =
|
|
58862
|
+
const logDir = import_node_path46.default.join(this.deps.dataDir, "log");
|
|
58345
58863
|
import_node_fs41.default.mkdirSync(logDir, { recursive: true });
|
|
58346
|
-
const logFilePath =
|
|
58864
|
+
const logFilePath = import_node_path46.default.join(logDir, "frpc.log");
|
|
58347
58865
|
const logStream = import_node_fs41.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
58348
58866
|
logStream.on("error", () => {
|
|
58349
58867
|
});
|
|
@@ -58427,15 +58945,15 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
58427
58945
|
|
|
58428
58946
|
// src/tunnel/device-key.ts
|
|
58429
58947
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
58430
|
-
var
|
|
58948
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
58431
58949
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
58432
58950
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
58433
58951
|
function deriveStableDeviceKey(opts = {}) {
|
|
58434
58952
|
const hostname = opts.hostname ?? import_node_os15.default.hostname();
|
|
58435
58953
|
const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
|
|
58436
58954
|
const home = opts.home ?? import_node_os15.default.homedir();
|
|
58437
|
-
const defaultDataDir =
|
|
58438
|
-
const normalizedDataDir = opts.dataDir ?
|
|
58955
|
+
const defaultDataDir = import_node_path47.default.resolve(import_node_path47.default.join(home, ".clawd"));
|
|
58956
|
+
const normalizedDataDir = opts.dataDir ? import_node_path47.default.resolve(opts.dataDir) : null;
|
|
58439
58957
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
58440
58958
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
58441
58959
|
return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
@@ -58443,11 +58961,11 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
58443
58961
|
|
|
58444
58962
|
// src/auth-store.ts
|
|
58445
58963
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
58446
|
-
var
|
|
58964
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
58447
58965
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
58448
58966
|
var AUTH_FILE_NAME = "auth.json";
|
|
58449
58967
|
function authFilePath(dataDir) {
|
|
58450
|
-
return
|
|
58968
|
+
return import_node_path48.default.join(dataDir, AUTH_FILE_NAME);
|
|
58451
58969
|
}
|
|
58452
58970
|
function loadOrCreateAuthFile(opts) {
|
|
58453
58971
|
const file = authFilePath(opts.dataDir);
|
|
@@ -58499,7 +59017,7 @@ function readAuthFile(file) {
|
|
|
58499
59017
|
}
|
|
58500
59018
|
}
|
|
58501
59019
|
function writeAuthFile(file, content) {
|
|
58502
|
-
import_node_fs42.default.mkdirSync(
|
|
59020
|
+
import_node_fs42.default.mkdirSync(import_node_path48.default.dirname(file), { recursive: true });
|
|
58503
59021
|
import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
58504
59022
|
try {
|
|
58505
59023
|
import_node_fs42.default.chmodSync(file, 384);
|
|
@@ -58510,10 +59028,10 @@ function writeAuthFile(file, content) {
|
|
|
58510
59028
|
// src/owner-profile.ts
|
|
58511
59029
|
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
58512
59030
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
58513
|
-
var
|
|
59031
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
58514
59032
|
var PROFILE_FILENAME = "profile.json";
|
|
58515
59033
|
function profilePath(dataDir) {
|
|
58516
|
-
return
|
|
59034
|
+
return import_node_path49.default.join(dataDir, PROFILE_FILENAME);
|
|
58517
59035
|
}
|
|
58518
59036
|
function loadOwnerProfile(dataDir) {
|
|
58519
59037
|
let raw;
|
|
@@ -58551,12 +59069,12 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
58551
59069
|
|
|
58552
59070
|
// src/feishu-auth/owner-identity-store.ts
|
|
58553
59071
|
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
58554
|
-
var
|
|
59072
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
58555
59073
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
58556
59074
|
var OwnerIdentityStore = class {
|
|
58557
59075
|
file;
|
|
58558
59076
|
constructor(dataDir) {
|
|
58559
|
-
this.file =
|
|
59077
|
+
this.file = import_node_path50.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
58560
59078
|
}
|
|
58561
59079
|
read() {
|
|
58562
59080
|
let raw;
|
|
@@ -58589,7 +59107,7 @@ var OwnerIdentityStore = class {
|
|
|
58589
59107
|
};
|
|
58590
59108
|
}
|
|
58591
59109
|
write(record3) {
|
|
58592
|
-
import_node_fs44.default.mkdirSync(
|
|
59110
|
+
import_node_fs44.default.mkdirSync(import_node_path50.default.dirname(this.file), { recursive: true });
|
|
58593
59111
|
import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
58594
59112
|
try {
|
|
58595
59113
|
import_node_fs44.default.chmodSync(this.file, 384);
|
|
@@ -58735,9 +59253,9 @@ var CentralClientError = class extends Error {
|
|
|
58735
59253
|
code;
|
|
58736
59254
|
cause;
|
|
58737
59255
|
};
|
|
58738
|
-
async function centralRequest(opts,
|
|
59256
|
+
async function centralRequest(opts, path89, init) {
|
|
58739
59257
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
58740
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
59258
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path89}`;
|
|
58741
59259
|
const ctrl = new AbortController();
|
|
58742
59260
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
58743
59261
|
let res;
|
|
@@ -58931,8 +59449,8 @@ function verifyConnectToken(args) {
|
|
|
58931
59449
|
}
|
|
58932
59450
|
|
|
58933
59451
|
// src/feishu-auth/server-key.ts
|
|
58934
|
-
var
|
|
58935
|
-
var
|
|
59452
|
+
var fs59 = __toESM(require("fs"), 1);
|
|
59453
|
+
var path63 = __toESM(require("path"), 1);
|
|
58936
59454
|
var FILE_NAME2 = "server-signing-key.json";
|
|
58937
59455
|
var ServerKeyStore = class {
|
|
58938
59456
|
constructor(dataDir) {
|
|
@@ -58940,12 +59458,12 @@ var ServerKeyStore = class {
|
|
|
58940
59458
|
}
|
|
58941
59459
|
dataDir;
|
|
58942
59460
|
filePath() {
|
|
58943
|
-
return
|
|
59461
|
+
return path63.join(this.dataDir, FILE_NAME2);
|
|
58944
59462
|
}
|
|
58945
59463
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
58946
59464
|
read() {
|
|
58947
59465
|
try {
|
|
58948
|
-
const raw =
|
|
59466
|
+
const raw = fs59.readFileSync(this.filePath(), "utf8");
|
|
58949
59467
|
const parsed = JSON.parse(raw);
|
|
58950
59468
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
58951
59469
|
return parsed.publicKeyPem;
|
|
@@ -58960,12 +59478,12 @@ var ServerKeyStore = class {
|
|
|
58960
59478
|
publicKeyPem,
|
|
58961
59479
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
58962
59480
|
};
|
|
58963
|
-
|
|
58964
|
-
|
|
59481
|
+
fs59.mkdirSync(this.dataDir, { recursive: true });
|
|
59482
|
+
fs59.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
58965
59483
|
}
|
|
58966
59484
|
clear() {
|
|
58967
59485
|
try {
|
|
58968
|
-
|
|
59486
|
+
fs59.unlinkSync(this.filePath());
|
|
58969
59487
|
} catch {
|
|
58970
59488
|
}
|
|
58971
59489
|
}
|
|
@@ -58974,13 +59492,16 @@ var ServerKeyStore = class {
|
|
|
58974
59492
|
// src/index.ts
|
|
58975
59493
|
init_protocol();
|
|
58976
59494
|
|
|
59495
|
+
// src/handlers/index.ts
|
|
59496
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
59497
|
+
|
|
58977
59498
|
// src/handlers/session.ts
|
|
58978
59499
|
init_protocol();
|
|
58979
59500
|
|
|
58980
59501
|
// src/session/fork.ts
|
|
58981
59502
|
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
58982
59503
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
58983
|
-
var
|
|
59504
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58984
59505
|
init_claude_history();
|
|
58985
59506
|
function readJsonlEntries(file) {
|
|
58986
59507
|
const raw = import_node_fs45.default.readFileSync(file, "utf8");
|
|
@@ -58996,19 +59517,19 @@ function readJsonlEntries(file) {
|
|
|
58996
59517
|
return out;
|
|
58997
59518
|
}
|
|
58998
59519
|
function forkSession(input) {
|
|
58999
|
-
const baseDir = input.baseDir ??
|
|
59000
|
-
let projectDir =
|
|
59001
|
-
let sourceFile =
|
|
59520
|
+
const baseDir = input.baseDir ?? import_node_path51.default.join(import_node_os17.default.homedir(), ".claude");
|
|
59521
|
+
let projectDir = import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
59522
|
+
let sourceFile = import_node_path51.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
59002
59523
|
if (!import_node_fs45.default.existsSync(sourceFile)) {
|
|
59003
59524
|
const found = findTranscriptByToolSessionId(
|
|
59004
|
-
|
|
59525
|
+
import_node_path51.default.join(baseDir, "projects"),
|
|
59005
59526
|
input.toolSessionId
|
|
59006
59527
|
);
|
|
59007
59528
|
if (!found) {
|
|
59008
59529
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
59009
59530
|
}
|
|
59010
59531
|
sourceFile = found;
|
|
59011
|
-
projectDir =
|
|
59532
|
+
projectDir = import_node_path51.default.dirname(found);
|
|
59012
59533
|
}
|
|
59013
59534
|
const entries = readJsonlEntries(sourceFile);
|
|
59014
59535
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -59037,8 +59558,8 @@ function forkSession(input) {
|
|
|
59037
59558
|
}
|
|
59038
59559
|
forkedLines.push(JSON.stringify(forked));
|
|
59039
59560
|
}
|
|
59040
|
-
const outDir = input.targetCwd ?
|
|
59041
|
-
const forkedFilePath =
|
|
59561
|
+
const outDir = input.targetCwd ? import_node_path51.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
59562
|
+
const forkedFilePath = import_node_path51.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
59042
59563
|
import_node_fs45.default.mkdirSync(outDir, { recursive: true });
|
|
59043
59564
|
import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
59044
59565
|
return { forkedToolSessionId, forkedFilePath };
|
|
@@ -59046,18 +59567,18 @@ function forkSession(input) {
|
|
|
59046
59567
|
|
|
59047
59568
|
// src/session/external-scan.ts
|
|
59048
59569
|
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
59049
|
-
var
|
|
59570
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
59050
59571
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
59051
|
-
var
|
|
59572
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
59052
59573
|
var import_node_module = require("module");
|
|
59053
59574
|
var import_node_child_process12 = require("child_process");
|
|
59054
59575
|
var import_meta4 = {};
|
|
59055
59576
|
function defaultRoots() {
|
|
59056
59577
|
const home = import_node_os18.default.homedir();
|
|
59057
59578
|
return {
|
|
59058
|
-
claudeProjectsDir:
|
|
59059
|
-
codexDir:
|
|
59060
|
-
clawdDir:
|
|
59579
|
+
claudeProjectsDir: import_node_path52.default.join(home, ".claude", "projects"),
|
|
59580
|
+
codexDir: import_node_path52.default.join(home, ".codex"),
|
|
59581
|
+
clawdDir: import_node_path52.default.join(home, ".clawd")
|
|
59061
59582
|
};
|
|
59062
59583
|
}
|
|
59063
59584
|
function width(s) {
|
|
@@ -59085,7 +59606,7 @@ function toMs(v2) {
|
|
|
59085
59606
|
async function* jsonLines(file) {
|
|
59086
59607
|
let raw;
|
|
59087
59608
|
try {
|
|
59088
|
-
raw = await
|
|
59609
|
+
raw = await import_promises8.default.readFile(file, "utf8");
|
|
59089
59610
|
} catch {
|
|
59090
59611
|
return;
|
|
59091
59612
|
}
|
|
@@ -59125,13 +59646,13 @@ async function scanClaude(roots) {
|
|
|
59125
59646
|
if (!d.isDirectory()) continue;
|
|
59126
59647
|
let files;
|
|
59127
59648
|
try {
|
|
59128
|
-
files = import_node_fs46.default.readdirSync(
|
|
59649
|
+
files = import_node_fs46.default.readdirSync(import_node_path52.default.join(roots.claudeProjectsDir, d.name));
|
|
59129
59650
|
} catch {
|
|
59130
59651
|
continue;
|
|
59131
59652
|
}
|
|
59132
59653
|
for (const name of files) {
|
|
59133
59654
|
if (!name.endsWith(".jsonl")) continue;
|
|
59134
|
-
const file =
|
|
59655
|
+
const file = import_node_path52.default.join(roots.claudeProjectsDir, d.name, name);
|
|
59135
59656
|
let st;
|
|
59136
59657
|
try {
|
|
59137
59658
|
st = import_node_fs46.default.statSync(file);
|
|
@@ -59261,7 +59782,7 @@ async function codexFromRows(rows) {
|
|
|
59261
59782
|
async function scanCodex(roots) {
|
|
59262
59783
|
let dbs = [];
|
|
59263
59784
|
try {
|
|
59264
|
-
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) =>
|
|
59785
|
+
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path52.default.join(roots.codexDir, n));
|
|
59265
59786
|
} catch {
|
|
59266
59787
|
}
|
|
59267
59788
|
if (!dbs.length) return [];
|
|
@@ -59270,14 +59791,14 @@ async function scanCodex(roots) {
|
|
|
59270
59791
|
}
|
|
59271
59792
|
async function scanExternalSessions(rootsIn) {
|
|
59272
59793
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
59273
|
-
const personaRoot =
|
|
59794
|
+
const personaRoot = import_node_path52.default.join(roots.clawdDir, "personas");
|
|
59274
59795
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
59275
59796
|
const out = [];
|
|
59276
59797
|
for (const c of all) {
|
|
59277
59798
|
if (c.skip) continue;
|
|
59278
59799
|
if (c.turns < 1) continue;
|
|
59279
59800
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
59280
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
59801
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path52.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path52.default.sep)) {
|
|
59281
59802
|
continue;
|
|
59282
59803
|
}
|
|
59283
59804
|
out.push({
|
|
@@ -59295,12 +59816,12 @@ async function scanExternalSessions(rootsIn) {
|
|
|
59295
59816
|
|
|
59296
59817
|
// src/session/import-ledger.ts
|
|
59297
59818
|
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
59298
|
-
var
|
|
59819
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
59299
59820
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
59300
59821
|
function readImportLedger(dataDir) {
|
|
59301
59822
|
try {
|
|
59302
59823
|
const parsed = JSON.parse(
|
|
59303
|
-
import_node_fs47.default.readFileSync(
|
|
59824
|
+
import_node_fs47.default.readFileSync(import_node_path53.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
59304
59825
|
);
|
|
59305
59826
|
return Array.isArray(parsed) ? parsed : [];
|
|
59306
59827
|
} catch {
|
|
@@ -59308,7 +59829,7 @@ function readImportLedger(dataDir) {
|
|
|
59308
59829
|
}
|
|
59309
59830
|
}
|
|
59310
59831
|
function appendImportLedger(dataDir, entry) {
|
|
59311
|
-
const file =
|
|
59832
|
+
const file = import_node_path53.default.join(dataDir, LEDGER_FILENAME);
|
|
59312
59833
|
const entries = readImportLedger(dataDir);
|
|
59313
59834
|
entries.push(entry);
|
|
59314
59835
|
import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
@@ -59814,7 +60335,7 @@ function buildPermissionHandlers(deps) {
|
|
|
59814
60335
|
}
|
|
59815
60336
|
|
|
59816
60337
|
// src/handlers/history.ts
|
|
59817
|
-
var
|
|
60338
|
+
var path68 = __toESM(require("path"), 1);
|
|
59818
60339
|
init_protocol();
|
|
59819
60340
|
|
|
59820
60341
|
// src/session/recent-dirs.ts
|
|
@@ -59832,7 +60353,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
59832
60353
|
}
|
|
59833
60354
|
|
|
59834
60355
|
// src/permission/persona-paths.ts
|
|
59835
|
-
var
|
|
60356
|
+
var path67 = __toESM(require("path"), 1);
|
|
59836
60357
|
function getAllowedPersonaIds(grants, action) {
|
|
59837
60358
|
const ids = /* @__PURE__ */ new Set();
|
|
59838
60359
|
for (const g2 of grants) {
|
|
@@ -59845,42 +60366,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
59845
60366
|
return ids;
|
|
59846
60367
|
}
|
|
59847
60368
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
59848
|
-
const target =
|
|
60369
|
+
const target = path67.resolve(absPath);
|
|
59849
60370
|
if (userWorkDir) {
|
|
59850
|
-
const u =
|
|
59851
|
-
const usep = u.endsWith(
|
|
60371
|
+
const u = path67.resolve(userWorkDir);
|
|
60372
|
+
const usep = u.endsWith(path67.sep) ? "" : path67.sep;
|
|
59852
60373
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
59853
60374
|
}
|
|
59854
|
-
const root =
|
|
59855
|
-
const sep4 = root.endsWith(
|
|
60375
|
+
const root = path67.resolve(personaRoot);
|
|
60376
|
+
const sep4 = root.endsWith(path67.sep) ? "" : path67.sep;
|
|
59856
60377
|
if (!target.startsWith(root + sep4)) return false;
|
|
59857
|
-
const rel =
|
|
60378
|
+
const rel = path67.relative(root, target);
|
|
59858
60379
|
if (!rel || rel.startsWith("..")) return false;
|
|
59859
|
-
const personaId2 = rel.split(
|
|
60380
|
+
const personaId2 = rel.split(path67.sep)[0];
|
|
59860
60381
|
if (!personaId2) return false;
|
|
59861
60382
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
59862
60383
|
if (allowed === "*") return true;
|
|
59863
60384
|
return allowed.has(personaId2);
|
|
59864
60385
|
}
|
|
59865
60386
|
function personaIdFromPath(absPath, personaRoot) {
|
|
59866
|
-
const root =
|
|
59867
|
-
const target =
|
|
59868
|
-
const sep4 = root.endsWith(
|
|
60387
|
+
const root = path67.resolve(personaRoot);
|
|
60388
|
+
const target = path67.resolve(absPath);
|
|
60389
|
+
const sep4 = root.endsWith(path67.sep) ? "" : path67.sep;
|
|
59869
60390
|
if (!target.startsWith(root + sep4)) return null;
|
|
59870
|
-
const rel =
|
|
60391
|
+
const rel = path67.relative(root, target);
|
|
59871
60392
|
if (!rel || rel.startsWith("..")) return null;
|
|
59872
|
-
const id = rel.split(
|
|
60393
|
+
const id = rel.split(path67.sep)[0];
|
|
59873
60394
|
return id || null;
|
|
59874
60395
|
}
|
|
59875
60396
|
function isPathWithin(dir, absPath) {
|
|
59876
|
-
const d =
|
|
59877
|
-
const t =
|
|
59878
|
-
const sep4 = d.endsWith(
|
|
60397
|
+
const d = path67.resolve(dir);
|
|
60398
|
+
const t = path67.resolve(absPath);
|
|
60399
|
+
const sep4 = d.endsWith(path67.sep) ? "" : path67.sep;
|
|
59879
60400
|
return t === d || t.startsWith(d + sep4);
|
|
59880
60401
|
}
|
|
59881
60402
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
59882
60403
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
59883
|
-
return personaIdFromPath(
|
|
60404
|
+
return personaIdFromPath(path67.resolve(absPath), personaRoot) === personaId2;
|
|
59884
60405
|
}
|
|
59885
60406
|
|
|
59886
60407
|
// src/handlers/history.ts
|
|
@@ -59933,7 +60454,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59933
60454
|
if (!pid) return false;
|
|
59934
60455
|
return isGuestPathAllowed(
|
|
59935
60456
|
ctx.grants,
|
|
59936
|
-
|
|
60457
|
+
path68.join(personaRoot, pid),
|
|
59937
60458
|
personaRoot,
|
|
59938
60459
|
"read",
|
|
59939
60460
|
userWorkDir
|
|
@@ -59945,7 +60466,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59945
60466
|
};
|
|
59946
60467
|
const list = async (frame, _client, ctx) => {
|
|
59947
60468
|
const args = HistoryListArgs.parse(frame);
|
|
59948
|
-
assertGuestPath(ctx,
|
|
60469
|
+
assertGuestPath(ctx, path68.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
59949
60470
|
const sessions = await history.listSessions(args);
|
|
59950
60471
|
return { response: { type: "history:list", sessions } };
|
|
59951
60472
|
};
|
|
@@ -59993,14 +60514,14 @@ function buildHistoryHandlers(deps) {
|
|
|
59993
60514
|
};
|
|
59994
60515
|
const subagents = async (frame, _client, ctx) => {
|
|
59995
60516
|
const args = HistorySubagentsArgs.parse(frame);
|
|
59996
|
-
assertGuestPath(ctx,
|
|
60517
|
+
assertGuestPath(ctx, path68.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
59997
60518
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
59998
60519
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
59999
60520
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
60000
60521
|
};
|
|
60001
60522
|
const subagentRead = async (frame, _client, ctx) => {
|
|
60002
60523
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
60003
|
-
assertGuestPath(ctx,
|
|
60524
|
+
assertGuestPath(ctx, path68.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
60004
60525
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
60005
60526
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
60006
60527
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -60010,7 +60531,7 @@ function buildHistoryHandlers(deps) {
|
|
|
60010
60531
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
60011
60532
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
60012
60533
|
const filtered = dirs.filter(
|
|
60013
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
60534
|
+
(d) => isGuestPathAllowed(ctx.grants, path68.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
60014
60535
|
);
|
|
60015
60536
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
60016
60537
|
}
|
|
@@ -60027,17 +60548,17 @@ function buildHistoryHandlers(deps) {
|
|
|
60027
60548
|
}
|
|
60028
60549
|
|
|
60029
60550
|
// src/handlers/projects.ts
|
|
60030
|
-
var
|
|
60551
|
+
var fs63 = __toESM(require("fs"), 1);
|
|
60031
60552
|
var os20 = __toESM(require("os"), 1);
|
|
60032
|
-
var
|
|
60553
|
+
var path69 = __toESM(require("path"), 1);
|
|
60033
60554
|
var import_node_child_process13 = require("child_process");
|
|
60034
60555
|
init_protocol();
|
|
60035
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
60556
|
+
var DEFAULT_PROJECTS_ROOT = path69.join(os20.homedir(), "Documents", "ChatGPT");
|
|
60036
60557
|
function allocateDir(root, name) {
|
|
60037
|
-
let candidate =
|
|
60558
|
+
let candidate = path69.join(root, name);
|
|
60038
60559
|
let n = 2;
|
|
60039
|
-
while (
|
|
60040
|
-
candidate =
|
|
60560
|
+
while (fs63.existsSync(candidate)) {
|
|
60561
|
+
candidate = path69.join(root, `${name} ${n}`);
|
|
60041
60562
|
n += 1;
|
|
60042
60563
|
}
|
|
60043
60564
|
return candidate;
|
|
@@ -60065,7 +60586,7 @@ function buildProjectHandlers(deps) {
|
|
|
60065
60586
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
60066
60587
|
}
|
|
60067
60588
|
try {
|
|
60068
|
-
if (!
|
|
60589
|
+
if (!fs63.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
60069
60590
|
} catch {
|
|
60070
60591
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
60071
60592
|
}
|
|
@@ -60081,7 +60602,7 @@ function buildProjectHandlers(deps) {
|
|
|
60081
60602
|
let target;
|
|
60082
60603
|
if (args.path) {
|
|
60083
60604
|
try {
|
|
60084
|
-
if (!
|
|
60605
|
+
if (!fs63.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
60085
60606
|
} catch {
|
|
60086
60607
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
60087
60608
|
}
|
|
@@ -60089,15 +60610,15 @@ function buildProjectHandlers(deps) {
|
|
|
60089
60610
|
} else {
|
|
60090
60611
|
const name = args.name;
|
|
60091
60612
|
try {
|
|
60092
|
-
|
|
60613
|
+
fs63.mkdirSync(root, { recursive: true });
|
|
60093
60614
|
target = allocateDir(root, name);
|
|
60094
|
-
|
|
60615
|
+
fs63.mkdirSync(target);
|
|
60095
60616
|
} catch (err) {
|
|
60096
60617
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
60097
60618
|
}
|
|
60098
60619
|
const git = (0, import_node_child_process13.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
60099
60620
|
if (git.status !== 0) {
|
|
60100
|
-
|
|
60621
|
+
fs63.rmSync(target, { recursive: true, force: true });
|
|
60101
60622
|
throw new ClawdError(
|
|
60102
60623
|
ERROR_CODES.INVALID_CWD,
|
|
60103
60624
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -60122,7 +60643,7 @@ function buildProjectHandlers(deps) {
|
|
|
60122
60643
|
}
|
|
60123
60644
|
|
|
60124
60645
|
// src/handlers/workspace.ts
|
|
60125
|
-
var
|
|
60646
|
+
var path70 = __toESM(require("path"), 1);
|
|
60126
60647
|
var os21 = __toESM(require("os"), 1);
|
|
60127
60648
|
init_protocol();
|
|
60128
60649
|
init_protocol();
|
|
@@ -60164,22 +60685,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60164
60685
|
const args = WorkspaceListArgs.parse(frame);
|
|
60165
60686
|
const isGuest = ctx?.principal.kind === "guest";
|
|
60166
60687
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os21.homedir();
|
|
60167
|
-
const resolvedCwd =
|
|
60168
|
-
const target = args.path ?
|
|
60688
|
+
const resolvedCwd = path70.resolve(args.cwd ?? fallbackCwd);
|
|
60689
|
+
const target = args.path ? path70.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
60169
60690
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
60170
60691
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
60171
60692
|
return { response: { type: "workspace:list", ...res } };
|
|
60172
60693
|
};
|
|
60173
60694
|
const read = async (frame, _client, ctx) => {
|
|
60174
60695
|
const args = WorkspaceReadArgs.parse(frame);
|
|
60175
|
-
const target =
|
|
60696
|
+
const target = path70.isAbsolute(args.path) ? path70.resolve(args.path) : path70.resolve(args.cwd, args.path);
|
|
60176
60697
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
60177
60698
|
const res = workspace.read(args);
|
|
60178
60699
|
return { response: { type: "workspace:read", ...res } };
|
|
60179
60700
|
};
|
|
60180
60701
|
const skillsList = async (frame, _client, ctx) => {
|
|
60181
60702
|
const args = SkillsListArgs.parse(frame);
|
|
60182
|
-
const cwdAbs =
|
|
60703
|
+
const cwdAbs = path70.resolve(args.cwd);
|
|
60183
60704
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
60184
60705
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
60185
60706
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -60191,7 +60712,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60191
60712
|
};
|
|
60192
60713
|
const agentsList = async (frame, _client, ctx) => {
|
|
60193
60714
|
const args = AgentsListArgs.parse(frame);
|
|
60194
|
-
const cwdAbs =
|
|
60715
|
+
const cwdAbs = path70.resolve(args.cwd);
|
|
60195
60716
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
60196
60717
|
if (args.tool === "codex") {
|
|
60197
60718
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -60213,18 +60734,18 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60213
60734
|
}
|
|
60214
60735
|
|
|
60215
60736
|
// src/handlers/git.ts
|
|
60216
|
-
var
|
|
60737
|
+
var path72 = __toESM(require("path"), 1);
|
|
60217
60738
|
init_protocol();
|
|
60218
60739
|
init_protocol();
|
|
60219
60740
|
|
|
60220
60741
|
// src/workspace/git.ts
|
|
60221
60742
|
var import_node_child_process14 = require("child_process");
|
|
60222
60743
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
60223
|
-
var
|
|
60744
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60224
60745
|
var import_node_util = require("util");
|
|
60225
60746
|
var pexec = (0, import_node_util.promisify)(import_node_child_process14.execFile);
|
|
60226
60747
|
function normalizePath(p2) {
|
|
60227
|
-
const resolved =
|
|
60748
|
+
const resolved = import_node_path54.default.resolve(p2);
|
|
60228
60749
|
try {
|
|
60229
60750
|
return import_node_fs48.default.realpathSync(resolved);
|
|
60230
60751
|
} catch {
|
|
@@ -60300,7 +60821,7 @@ async function listGitBranches(cwd) {
|
|
|
60300
60821
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
60301
60822
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
60302
60823
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
60303
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
60824
|
+
if (!isGuestPathAllowed(ctx.grants, path72.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
60304
60825
|
throw new ClawdError(
|
|
60305
60826
|
ERROR_CODES.UNAUTHORIZED,
|
|
60306
60827
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -61038,6 +61559,22 @@ var METHOD_GRANT_MAP = {
|
|
|
61038
61559
|
// ---- shift:* (排班 mock,owner-only 读) ----
|
|
61039
61560
|
// mock 阶段只 owner 用;接 guest 后再考虑分级
|
|
61040
61561
|
"shift:list": ADMIN_ANY,
|
|
61562
|
+
// channel:* / topic:*(Channel × Master):owner 本机资源,owner-only 一刀切。
|
|
61563
|
+
// Master 是 owner-scope persona session,经 clawd-rpc 桥调,同样落在 ADMIN_ANY。
|
|
61564
|
+
"channel:list": ADMIN_ANY,
|
|
61565
|
+
"channel:create": ADMIN_ANY,
|
|
61566
|
+
"channel:update": ADMIN_ANY,
|
|
61567
|
+
"channel:delete": ADMIN_ANY,
|
|
61568
|
+
"topic:list": ADMIN_ANY,
|
|
61569
|
+
"topic:get": ADMIN_ANY,
|
|
61570
|
+
"topic:create": ADMIN_ANY,
|
|
61571
|
+
"topic:setPlan": ADMIN_ANY,
|
|
61572
|
+
"topic:append": ADMIN_ANY,
|
|
61573
|
+
"topic:reject": ADMIN_ANY,
|
|
61574
|
+
"topic:accept": ADMIN_ANY,
|
|
61575
|
+
"topic:close": ADMIN_ANY,
|
|
61576
|
+
"line:digest": ADMIN_ANY,
|
|
61577
|
+
"master:authorityCheck": ADMIN_ANY,
|
|
61041
61578
|
// project:*(sidebar 项目分区,spec 2026-08-17):registry 是 owner 本机资源,owner-only 一刀切
|
|
61042
61579
|
"project:list": ADMIN_ANY,
|
|
61043
61580
|
"project:create": ADMIN_ANY,
|
|
@@ -61203,21 +61740,21 @@ function computeMethodAccess(args) {
|
|
|
61203
61740
|
}
|
|
61204
61741
|
|
|
61205
61742
|
// src/version.ts
|
|
61206
|
-
var version = "0.2.
|
|
61743
|
+
var version = "0.2.383".length > 0 ? "0.2.383" : "dev";
|
|
61207
61744
|
|
|
61208
61745
|
// src/cli-probe/probe.ts
|
|
61209
|
-
var
|
|
61210
|
-
var
|
|
61746
|
+
var fs65 = __toESM(require("fs"), 1);
|
|
61747
|
+
var path73 = __toESM(require("path"), 1);
|
|
61211
61748
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
61212
61749
|
var BIN_NAME = "clawd";
|
|
61213
61750
|
var MAX_PARENT_HOPS = 5;
|
|
61214
61751
|
function probeGlobalCli(pathEnv) {
|
|
61215
61752
|
if (!pathEnv) return null;
|
|
61216
|
-
for (const dir of pathEnv.split(
|
|
61753
|
+
for (const dir of pathEnv.split(path73.delimiter)) {
|
|
61217
61754
|
if (!dir) continue;
|
|
61218
61755
|
let real;
|
|
61219
61756
|
try {
|
|
61220
|
-
real =
|
|
61757
|
+
real = fs65.realpathSync(path73.join(dir, BIN_NAME));
|
|
61221
61758
|
} catch {
|
|
61222
61759
|
continue;
|
|
61223
61760
|
}
|
|
@@ -61227,15 +61764,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
61227
61764
|
return null;
|
|
61228
61765
|
}
|
|
61229
61766
|
function readOwnPackageVersion(entryPath) {
|
|
61230
|
-
let dir =
|
|
61767
|
+
let dir = path73.dirname(entryPath);
|
|
61231
61768
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
61232
61769
|
try {
|
|
61233
|
-
const raw =
|
|
61770
|
+
const raw = fs65.readFileSync(path73.join(dir, "package.json"), "utf8");
|
|
61234
61771
|
const pkg = JSON.parse(raw);
|
|
61235
61772
|
if (pkg.name !== PKG_NAME) return null;
|
|
61236
61773
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
61237
61774
|
} catch {
|
|
61238
|
-
const parent =
|
|
61775
|
+
const parent = path73.dirname(dir);
|
|
61239
61776
|
if (parent === dir) return null;
|
|
61240
61777
|
dir = parent;
|
|
61241
61778
|
}
|
|
@@ -61398,7 +61935,7 @@ function buildPersonaHandlers(deps) {
|
|
|
61398
61935
|
}
|
|
61399
61936
|
|
|
61400
61937
|
// src/handlers/attachment.ts
|
|
61401
|
-
var
|
|
61938
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
61402
61939
|
init_protocol();
|
|
61403
61940
|
init_protocol();
|
|
61404
61941
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -61478,12 +62015,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
61478
62015
|
`session ${args.sessionId} scope unresolved`
|
|
61479
62016
|
);
|
|
61480
62017
|
}
|
|
61481
|
-
const cwdAbs =
|
|
61482
|
-
const candidateAbs =
|
|
62018
|
+
const cwdAbs = import_node_path55.default.resolve(sessionFile.cwd);
|
|
62019
|
+
const candidateAbs = import_node_path55.default.isAbsolute(args.relPath) ? import_node_path55.default.resolve(args.relPath) : import_node_path55.default.resolve(cwdAbs, args.relPath);
|
|
61483
62020
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
61484
62021
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
61485
62022
|
const entry = entries.find((e) => {
|
|
61486
|
-
const storedAbs =
|
|
62023
|
+
const storedAbs = import_node_path55.default.isAbsolute(e.relPath) ? import_node_path55.default.resolve(e.relPath) : import_node_path55.default.resolve(cwdAbs, e.relPath);
|
|
61487
62024
|
return storedAbs === candidateAbs && !e.stale;
|
|
61488
62025
|
});
|
|
61489
62026
|
if (!entry) {
|
|
@@ -61508,7 +62045,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
61508
62045
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
61509
62046
|
const f = deps.sessionStore.read(sessionId);
|
|
61510
62047
|
if (!f) return;
|
|
61511
|
-
assertGuestAttachmentPath(ctx,
|
|
62048
|
+
assertGuestAttachmentPath(ctx, import_node_path55.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
61512
62049
|
}
|
|
61513
62050
|
const groupAdd = async (frame, _client, ctx) => {
|
|
61514
62051
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -61523,8 +62060,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
61523
62060
|
if (!scope) {
|
|
61524
62061
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
61525
62062
|
}
|
|
61526
|
-
const cwdAbs =
|
|
61527
|
-
const candidateAbs =
|
|
62063
|
+
const cwdAbs = import_node_path55.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
62064
|
+
const candidateAbs = import_node_path55.default.isAbsolute(args.relPath) ? import_node_path55.default.resolve(args.relPath) : import_node_path55.default.resolve(cwdAbs, args.relPath);
|
|
61528
62065
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
61529
62066
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
61530
62067
|
const size = 0;
|
|
@@ -61582,21 +62119,21 @@ function buildAttachmentHandlers(deps) {
|
|
|
61582
62119
|
}
|
|
61583
62120
|
|
|
61584
62121
|
// src/handlers/extension.ts
|
|
61585
|
-
var
|
|
61586
|
-
var
|
|
62122
|
+
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62123
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
61587
62124
|
init_protocol();
|
|
61588
62125
|
|
|
61589
62126
|
// src/extension/bundle-zip.ts
|
|
61590
|
-
var
|
|
61591
|
-
var
|
|
62127
|
+
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
62128
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
61592
62129
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
61593
62130
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
61594
62131
|
async function bundleExtensionDir(dir) {
|
|
61595
62132
|
const entries = await listFilesSorted(dir);
|
|
61596
62133
|
const zip = new import_jszip2.default();
|
|
61597
62134
|
for (const rel of entries) {
|
|
61598
|
-
const abs =
|
|
61599
|
-
const content = await
|
|
62135
|
+
const abs = import_node_path56.default.join(dir, rel);
|
|
62136
|
+
const content = await import_promises9.default.readFile(abs);
|
|
61600
62137
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
61601
62138
|
}
|
|
61602
62139
|
const buffer = await zip.generateAsync({
|
|
@@ -61616,8 +62153,8 @@ async function listFilesSorted(rootDir) {
|
|
|
61616
62153
|
return out;
|
|
61617
62154
|
}
|
|
61618
62155
|
async function walk(absRoot, relPrefix, out) {
|
|
61619
|
-
const dirAbs =
|
|
61620
|
-
const entries = await
|
|
62156
|
+
const dirAbs = import_node_path56.default.join(absRoot, relPrefix);
|
|
62157
|
+
const entries = await import_promises9.default.readdir(dirAbs, { withFileTypes: true });
|
|
61621
62158
|
for (const e of entries) {
|
|
61622
62159
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
61623
62160
|
const rel = relPrefix ? `${relPrefix}/${e.name}` : e.name;
|
|
@@ -61669,26 +62206,26 @@ function computePublishCheck(args) {
|
|
|
61669
62206
|
}
|
|
61670
62207
|
|
|
61671
62208
|
// src/extension/install-flow.ts
|
|
61672
|
-
var
|
|
61673
|
-
var
|
|
62209
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
62210
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
61674
62211
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
61675
62212
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
61676
62213
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
61677
62214
|
|
|
61678
62215
|
// src/extension/paths.ts
|
|
61679
62216
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
61680
|
-
var
|
|
62217
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
61681
62218
|
function clawdHomeRoot(override) {
|
|
61682
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
62219
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path57.default.join(import_node_os20.default.homedir(), ".clawd");
|
|
61683
62220
|
}
|
|
61684
62221
|
function extensionsRoot(override) {
|
|
61685
|
-
return
|
|
62222
|
+
return import_node_path57.default.join(clawdHomeRoot(override), "extensions");
|
|
61686
62223
|
}
|
|
61687
62224
|
function publishedChannelsFile(override) {
|
|
61688
|
-
return
|
|
62225
|
+
return import_node_path57.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
61689
62226
|
}
|
|
61690
62227
|
function bundleCacheRoot(override) {
|
|
61691
|
-
return
|
|
62228
|
+
return import_node_path57.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
61692
62229
|
}
|
|
61693
62230
|
|
|
61694
62231
|
// src/extension/install-flow.ts
|
|
@@ -61715,7 +62252,7 @@ async function installFromChannel(args, deps) {
|
|
|
61715
62252
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
61716
62253
|
}
|
|
61717
62254
|
for (const name of Object.keys(zip.files)) {
|
|
61718
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
62255
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path58.default.isAbsolute(name)) {
|
|
61719
62256
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
61720
62257
|
}
|
|
61721
62258
|
}
|
|
@@ -61747,10 +62284,10 @@ async function installFromChannel(args, deps) {
|
|
|
61747
62284
|
);
|
|
61748
62285
|
}
|
|
61749
62286
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
61750
|
-
const destDir =
|
|
62287
|
+
const destDir = import_node_path58.default.join(deps.extensionsRoot, localExtId);
|
|
61751
62288
|
let destExists = false;
|
|
61752
62289
|
try {
|
|
61753
|
-
await
|
|
62290
|
+
await import_promises10.default.access(destDir);
|
|
61754
62291
|
destExists = true;
|
|
61755
62292
|
} catch {
|
|
61756
62293
|
}
|
|
@@ -61760,28 +62297,28 @@ async function installFromChannel(args, deps) {
|
|
|
61760
62297
|
`extension ${localExtId} already installed locally (from owner ${channelRef.ownerPrincipalId})`
|
|
61761
62298
|
);
|
|
61762
62299
|
}
|
|
61763
|
-
const stage = await
|
|
61764
|
-
|
|
62300
|
+
const stage = await import_promises10.default.mkdtemp(
|
|
62301
|
+
import_node_path58.default.join(import_node_os21.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
61765
62302
|
);
|
|
61766
62303
|
try {
|
|
61767
62304
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
61768
|
-
const dest =
|
|
62305
|
+
const dest = import_node_path58.default.join(stage, name);
|
|
61769
62306
|
if (entry.dir) {
|
|
61770
|
-
await
|
|
62307
|
+
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
61771
62308
|
continue;
|
|
61772
62309
|
}
|
|
61773
|
-
await
|
|
62310
|
+
await import_promises10.default.mkdir(import_node_path58.default.dirname(dest), { recursive: true });
|
|
61774
62311
|
if (name === "manifest.json") {
|
|
61775
62312
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
61776
|
-
await
|
|
62313
|
+
await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
61777
62314
|
} else {
|
|
61778
|
-
await
|
|
62315
|
+
await import_promises10.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
61779
62316
|
}
|
|
61780
62317
|
}
|
|
61781
|
-
await
|
|
61782
|
-
await
|
|
62318
|
+
await import_promises10.default.mkdir(deps.extensionsRoot, { recursive: true });
|
|
62319
|
+
await import_promises10.default.rename(stage, destDir);
|
|
61783
62320
|
} catch (e) {
|
|
61784
|
-
await
|
|
62321
|
+
await import_promises10.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
61785
62322
|
});
|
|
61786
62323
|
throw e;
|
|
61787
62324
|
}
|
|
@@ -61790,8 +62327,8 @@ async function installFromChannel(args, deps) {
|
|
|
61790
62327
|
}
|
|
61791
62328
|
|
|
61792
62329
|
// src/extension/update-flow.ts
|
|
61793
|
-
var
|
|
61794
|
-
var
|
|
62330
|
+
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
62331
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
61795
62332
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
61796
62333
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
61797
62334
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -61808,11 +62345,11 @@ async function updateFromChannel(args, deps) {
|
|
|
61808
62345
|
channelRef.extId,
|
|
61809
62346
|
channelRef.ownerPrincipalId
|
|
61810
62347
|
);
|
|
61811
|
-
const liveDir =
|
|
62348
|
+
const liveDir = import_node_path59.default.join(deps.extensionsRoot, localExtId);
|
|
61812
62349
|
const prevDir = `${liveDir}.prev`;
|
|
61813
62350
|
let existingVersion;
|
|
61814
62351
|
try {
|
|
61815
|
-
const raw = await
|
|
62352
|
+
const raw = await import_promises11.default.readFile(import_node_path59.default.join(liveDir, "manifest.json"), "utf8");
|
|
61816
62353
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
61817
62354
|
if (!parsed2.success) {
|
|
61818
62355
|
throw new UpdateError(
|
|
@@ -61845,7 +62382,7 @@ async function updateFromChannel(args, deps) {
|
|
|
61845
62382
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
61846
62383
|
}
|
|
61847
62384
|
for (const name of Object.keys(zip.files)) {
|
|
61848
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
62385
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path59.default.isAbsolute(name)) {
|
|
61849
62386
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
61850
62387
|
}
|
|
61851
62388
|
}
|
|
@@ -61877,31 +62414,31 @@ async function updateFromChannel(args, deps) {
|
|
|
61877
62414
|
);
|
|
61878
62415
|
}
|
|
61879
62416
|
await deps.runtime.close(localExtId);
|
|
61880
|
-
await
|
|
61881
|
-
await
|
|
61882
|
-
const stage = await
|
|
61883
|
-
|
|
62417
|
+
await import_promises11.default.rm(prevDir, { recursive: true, force: true });
|
|
62418
|
+
await import_promises11.default.rename(liveDir, prevDir);
|
|
62419
|
+
const stage = await import_promises11.default.mkdtemp(
|
|
62420
|
+
import_node_path59.default.join(import_node_os22.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
61884
62421
|
);
|
|
61885
62422
|
try {
|
|
61886
62423
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
61887
|
-
const dest =
|
|
62424
|
+
const dest = import_node_path59.default.join(stage, name);
|
|
61888
62425
|
if (entry.dir) {
|
|
61889
|
-
await
|
|
62426
|
+
await import_promises11.default.mkdir(dest, { recursive: true });
|
|
61890
62427
|
continue;
|
|
61891
62428
|
}
|
|
61892
|
-
await
|
|
62429
|
+
await import_promises11.default.mkdir(import_node_path59.default.dirname(dest), { recursive: true });
|
|
61893
62430
|
if (name === "manifest.json") {
|
|
61894
62431
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
61895
|
-
await
|
|
62432
|
+
await import_promises11.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
61896
62433
|
} else {
|
|
61897
|
-
await
|
|
62434
|
+
await import_promises11.default.writeFile(dest, await entry.async("nodebuffer"));
|
|
61898
62435
|
}
|
|
61899
62436
|
}
|
|
61900
|
-
await
|
|
62437
|
+
await import_promises11.default.rename(stage, liveDir);
|
|
61901
62438
|
} catch (e) {
|
|
61902
|
-
await
|
|
62439
|
+
await import_promises11.default.rm(stage, { recursive: true, force: true }).catch(() => {
|
|
61903
62440
|
});
|
|
61904
|
-
await
|
|
62441
|
+
await import_promises11.default.rename(prevDir, liveDir).catch(() => {
|
|
61905
62442
|
});
|
|
61906
62443
|
await deps.runtime.open(localExtId).catch(() => {
|
|
61907
62444
|
});
|
|
@@ -61923,7 +62460,7 @@ async function updateFromChannel(args, deps) {
|
|
|
61923
62460
|
reason: e.message
|
|
61924
62461
|
};
|
|
61925
62462
|
}
|
|
61926
|
-
await
|
|
62463
|
+
await import_promises11.default.rm(prevDir, { recursive: true, force: true });
|
|
61927
62464
|
return {
|
|
61928
62465
|
kind: "updated",
|
|
61929
62466
|
extId: localExtId,
|
|
@@ -61931,9 +62468,9 @@ async function updateFromChannel(args, deps) {
|
|
|
61931
62468
|
};
|
|
61932
62469
|
}
|
|
61933
62470
|
async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
61934
|
-
await
|
|
62471
|
+
await import_promises11.default.rm(liveDir, { recursive: true, force: true }).catch(() => {
|
|
61935
62472
|
});
|
|
61936
|
-
await
|
|
62473
|
+
await import_promises11.default.rename(prevDir, liveDir).catch(() => {
|
|
61937
62474
|
});
|
|
61938
62475
|
await deps.runtime.open(localExtId).catch(() => {
|
|
61939
62476
|
});
|
|
@@ -61956,18 +62493,18 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
61956
62493
|
);
|
|
61957
62494
|
}
|
|
61958
62495
|
}
|
|
61959
|
-
const manifestPath =
|
|
62496
|
+
const manifestPath = import_node_path60.default.join(root, extId, "manifest.json");
|
|
61960
62497
|
const manifest = await readManifest(root, extId);
|
|
61961
62498
|
const next = { ...manifest, version: newVersion };
|
|
61962
62499
|
const tmp = `${manifestPath}.tmp`;
|
|
61963
|
-
await
|
|
61964
|
-
await
|
|
62500
|
+
await import_promises12.default.writeFile(tmp, JSON.stringify(next, null, 2));
|
|
62501
|
+
await import_promises12.default.rename(tmp, manifestPath);
|
|
61965
62502
|
}
|
|
61966
62503
|
async function readManifest(root, extId) {
|
|
61967
|
-
const file =
|
|
62504
|
+
const file = import_node_path60.default.join(root, extId, "manifest.json");
|
|
61968
62505
|
let raw;
|
|
61969
62506
|
try {
|
|
61970
|
-
raw = await
|
|
62507
|
+
raw = await import_promises12.default.readFile(file, "utf8");
|
|
61971
62508
|
} catch (e) {
|
|
61972
62509
|
if (e.code === "ENOENT") {
|
|
61973
62510
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `extension ${extId} not installed`);
|
|
@@ -62048,7 +62585,7 @@ function buildExtensionHandlers(deps) {
|
|
|
62048
62585
|
};
|
|
62049
62586
|
async function buildSnapshotMeta(extId) {
|
|
62050
62587
|
const manifest = await readManifest(deps.root, extId);
|
|
62051
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
62588
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path60.default.join(deps.root, extId));
|
|
62052
62589
|
return { manifest, contentHash: sha256, buffer };
|
|
62053
62590
|
}
|
|
62054
62591
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -62225,7 +62762,7 @@ function buildExtensionHandlers(deps) {
|
|
|
62225
62762
|
// src/app-builder/project-store.ts
|
|
62226
62763
|
var import_node_fs49 = require("fs");
|
|
62227
62764
|
var import_node_child_process15 = require("child_process");
|
|
62228
|
-
var
|
|
62765
|
+
var import_node_path61 = require("path");
|
|
62229
62766
|
init_protocol();
|
|
62230
62767
|
var PROJECTS_DIR = "projects";
|
|
62231
62768
|
var META_FILE = ".clawd-project.json";
|
|
@@ -62239,14 +62776,14 @@ var ProjectStore = class {
|
|
|
62239
62776
|
root;
|
|
62240
62777
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
62241
62778
|
metaPath(name) {
|
|
62242
|
-
return (0,
|
|
62779
|
+
return (0, import_node_path61.join)(this.projectsRoot(), name, META_FILE);
|
|
62243
62780
|
}
|
|
62244
62781
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
62245
62782
|
projectDir(name) {
|
|
62246
|
-
return (0,
|
|
62783
|
+
return (0, import_node_path61.join)(this.projectsRoot(), name);
|
|
62247
62784
|
}
|
|
62248
62785
|
projectsRoot() {
|
|
62249
|
-
return (0,
|
|
62786
|
+
return (0, import_node_path61.join)(this.root, PROJECTS_DIR);
|
|
62250
62787
|
}
|
|
62251
62788
|
async list() {
|
|
62252
62789
|
let entries;
|
|
@@ -62549,7 +63086,7 @@ var PublishJobRegistry = class {
|
|
|
62549
63086
|
// src/app-builder/publish-job-runner.ts
|
|
62550
63087
|
var import_node_child_process17 = require("child_process");
|
|
62551
63088
|
var import_node_fs50 = require("fs");
|
|
62552
|
-
var
|
|
63089
|
+
var import_node_path62 = require("path");
|
|
62553
63090
|
|
|
62554
63091
|
// src/app-builder/publish-stage-parser.ts
|
|
62555
63092
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -62581,7 +63118,7 @@ async function startPublishJob(deps, args) {
|
|
|
62581
63118
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
62582
63119
|
}
|
|
62583
63120
|
const projDir = projectDir(args.name);
|
|
62584
|
-
const logPath = (0,
|
|
63121
|
+
const logPath = (0, import_node_path62.join)(projDir, ".publish.log");
|
|
62585
63122
|
let logStream = null;
|
|
62586
63123
|
try {
|
|
62587
63124
|
logStream = (0, import_node_fs50.createWriteStream)(logPath, { flags: "w" });
|
|
@@ -62841,7 +63378,7 @@ async function recoverInterruptedJobs(deps) {
|
|
|
62841
63378
|
|
|
62842
63379
|
// src/handlers/app-builder.ts
|
|
62843
63380
|
init_protocol();
|
|
62844
|
-
var
|
|
63381
|
+
var import_node_path63 = require("path");
|
|
62845
63382
|
var import_node_fs51 = require("fs");
|
|
62846
63383
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
62847
63384
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
@@ -62992,8 +63529,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
62992
63529
|
const project = await userStore.create(f.name, reservedPorts);
|
|
62993
63530
|
try {
|
|
62994
63531
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
62995
|
-
const templateSrcDir = (0,
|
|
62996
|
-
const scaffoldScript = (0,
|
|
63532
|
+
const templateSrcDir = (0, import_node_path63.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
63533
|
+
const scaffoldScript = (0, import_node_path63.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
62997
63534
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
62998
63535
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
62999
63536
|
name: project.name,
|
|
@@ -63197,7 +63734,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
63197
63734
|
await userStore.clearPublishJob(args.name);
|
|
63198
63735
|
}
|
|
63199
63736
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
63200
|
-
const scriptPath = (0,
|
|
63737
|
+
const scriptPath = (0, import_node_path63.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
63201
63738
|
deps.logger?.info("app-builder.publish.start", {
|
|
63202
63739
|
name: args.name,
|
|
63203
63740
|
sessionId: boundSession.sessionId,
|
|
@@ -63346,6 +63883,427 @@ function buildShiftHandlers(deps) {
|
|
|
63346
63883
|
};
|
|
63347
63884
|
}
|
|
63348
63885
|
|
|
63886
|
+
// src/handlers/channel.ts
|
|
63887
|
+
init_protocol();
|
|
63888
|
+
function buildChannelHandlers(deps) {
|
|
63889
|
+
return {
|
|
63890
|
+
"channel:list": async () => ({
|
|
63891
|
+
response: ChannelListResultSchema.parse({ channels: deps.channelStore.list() })
|
|
63892
|
+
}),
|
|
63893
|
+
"channel:create": async (frame) => {
|
|
63894
|
+
const args = ChannelCreateArgsSchema.parse(frame);
|
|
63895
|
+
const channel = deps.channelStore.create({
|
|
63896
|
+
name: args.name,
|
|
63897
|
+
memberPersonaIds: args.memberPersonaIds,
|
|
63898
|
+
memberContactDeviceIds: args.memberContactDeviceIds
|
|
63899
|
+
});
|
|
63900
|
+
return { response: ChannelResultSchema.parse({ channel }) };
|
|
63901
|
+
},
|
|
63902
|
+
"channel:update": async (frame) => {
|
|
63903
|
+
const args = ChannelUpdateArgsSchema.parse(frame);
|
|
63904
|
+
const channel = deps.channelStore.update(args.channelId, {
|
|
63905
|
+
...args.name !== void 0 ? { name: args.name } : {},
|
|
63906
|
+
...args.memberPersonaIds !== void 0 ? { memberPersonaIds: args.memberPersonaIds } : {},
|
|
63907
|
+
...args.memberContactDeviceIds !== void 0 ? { memberContactDeviceIds: args.memberContactDeviceIds } : {}
|
|
63908
|
+
});
|
|
63909
|
+
if (!channel) {
|
|
63910
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `channel not found: ${args.channelId}`);
|
|
63911
|
+
}
|
|
63912
|
+
return { response: ChannelResultSchema.parse({ channel }) };
|
|
63913
|
+
},
|
|
63914
|
+
"channel:delete": async (frame) => {
|
|
63915
|
+
const { channelId } = ChannelDeleteArgsSchema.parse(frame);
|
|
63916
|
+
if (!deps.channelStore.get(channelId)) {
|
|
63917
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `channel not found: ${channelId}`);
|
|
63918
|
+
}
|
|
63919
|
+
if (deps.topicStore.hasUnfinished(channelId)) {
|
|
63920
|
+
throw new ClawdError(
|
|
63921
|
+
ERROR_CODES.INVALID_PARAM,
|
|
63922
|
+
"\u8BE5\u9891\u9053\u4E0B\u4ECD\u6709\u672A\u7ED3\u675F\u8BDD\u9898\uFF0C\u5148\u6536\u655B\u6216\u5F52\u6863\u5B83\u4EEC\u518D\u5220\u9891\u9053"
|
|
63923
|
+
);
|
|
63924
|
+
}
|
|
63925
|
+
const removedTopics = deps.topicStore.removeByChannel(channelId);
|
|
63926
|
+
deps.channelStore.remove(channelId);
|
|
63927
|
+
return { response: ChannelDeleteResultSchema.parse({ ok: true, removedTopics }) };
|
|
63928
|
+
}
|
|
63929
|
+
};
|
|
63930
|
+
}
|
|
63931
|
+
|
|
63932
|
+
// src/handlers/topic.ts
|
|
63933
|
+
init_protocol();
|
|
63934
|
+
var REJECT_ESCALATE_AT = 2;
|
|
63935
|
+
function joinLines(records, lineMeta) {
|
|
63936
|
+
const out = [];
|
|
63937
|
+
for (const r of records) {
|
|
63938
|
+
const meta = r.meta ?? {};
|
|
63939
|
+
if (typeof meta.lineId !== "string" || !meta.lineId) continue;
|
|
63940
|
+
out.push({
|
|
63941
|
+
lineId: meta.lineId,
|
|
63942
|
+
dispatchId: r.dispatchId,
|
|
63943
|
+
...r.workerSessionId ? { workerSessionId: r.workerSessionId } : {},
|
|
63944
|
+
assignee: r.targetPersonaId,
|
|
63945
|
+
focus: r.taskText,
|
|
63946
|
+
status: r.status,
|
|
63947
|
+
acceptance: Array.isArray(meta.acceptance) ? meta.acceptance.map(String) : [],
|
|
63948
|
+
rejectCount: lineMeta[meta.lineId]?.rejectCount ?? 0,
|
|
63949
|
+
accepted: lineMeta[meta.lineId]?.accepted ?? false
|
|
63950
|
+
});
|
|
63951
|
+
}
|
|
63952
|
+
return out;
|
|
63953
|
+
}
|
|
63954
|
+
function buildTopicHandlers(deps) {
|
|
63955
|
+
const mustGet = (topicId) => {
|
|
63956
|
+
const t = deps.topicStore.get(topicId);
|
|
63957
|
+
if (!t) throw new ClawdError(ERROR_CODES.INVALID_PARAM, `topic not found: ${topicId}`);
|
|
63958
|
+
return t;
|
|
63959
|
+
};
|
|
63960
|
+
const linesOf = (t) => joinLines(deps.dispatchStore.list({ sourceSessionId: t.masterSessionId }), t.lineMeta);
|
|
63961
|
+
return {
|
|
63962
|
+
"topic:list": async (frame) => {
|
|
63963
|
+
const { channelId } = TopicListArgsSchema.parse(frame);
|
|
63964
|
+
const topics = deps.topicStore.listByChannel(channelId).map((t) => ({ ...t, lineCount: linesOf(t).length }));
|
|
63965
|
+
return { response: TopicListResultSchema.parse({ topics }) };
|
|
63966
|
+
},
|
|
63967
|
+
"topic:get": async (frame) => {
|
|
63968
|
+
const args = TopicGetArgsSchema.parse(frame);
|
|
63969
|
+
const topic = args.topicId ? mustGet(args.topicId) : deps.topicStore.getByMasterSession(args.sessionId);
|
|
63970
|
+
if (!topic) {
|
|
63971
|
+
throw new ClawdError(
|
|
63972
|
+
ERROR_CODES.INVALID_PARAM,
|
|
63973
|
+
`topic not found for session: ${args.sessionId}`
|
|
63974
|
+
);
|
|
63975
|
+
}
|
|
63976
|
+
return { response: TopicGetResultSchema.parse({ topic, lines: linesOf(topic) }) };
|
|
63977
|
+
},
|
|
63978
|
+
"topic:create": async (frame) => {
|
|
63979
|
+
const args = TopicCreateArgsSchema.parse(frame);
|
|
63980
|
+
if (!deps.channelStore.get(args.channelId)) {
|
|
63981
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `channel not found: ${args.channelId}`);
|
|
63982
|
+
}
|
|
63983
|
+
const { sessionId } = deps.createMasterSession({ label: args.title ?? "\u65B0\u8BDD\u9898" });
|
|
63984
|
+
const topic = deps.topicStore.create({
|
|
63985
|
+
channelId: args.channelId,
|
|
63986
|
+
...args.title ? { title: args.title } : {},
|
|
63987
|
+
masterSessionId: sessionId
|
|
63988
|
+
});
|
|
63989
|
+
return {
|
|
63990
|
+
response: TopicCreateResultSchema.parse({
|
|
63991
|
+
topicId: topic.id,
|
|
63992
|
+
masterSessionId: sessionId
|
|
63993
|
+
})
|
|
63994
|
+
};
|
|
63995
|
+
},
|
|
63996
|
+
"topic:setPlan": async (frame) => {
|
|
63997
|
+
const args = TopicSetPlanArgsSchema.parse(frame);
|
|
63998
|
+
mustGet(args.topicId);
|
|
63999
|
+
const topic = deps.topicStore.setPlan(args.topicId, {
|
|
64000
|
+
...args.title ? { title: args.title } : {},
|
|
64001
|
+
goal: args.goal,
|
|
64002
|
+
boundaries: args.boundaries,
|
|
64003
|
+
acceptanceCriteria: args.acceptanceCriteria
|
|
64004
|
+
});
|
|
64005
|
+
return { response: TopicResultSchema.parse({ topic }) };
|
|
64006
|
+
},
|
|
64007
|
+
"topic:append": async (frame) => {
|
|
64008
|
+
const args = TopicAppendArgsSchema.parse(frame);
|
|
64009
|
+
mustGet(args.topicId);
|
|
64010
|
+
deps.topicStore.appendActivity(args.topicId, {
|
|
64011
|
+
actor: "master",
|
|
64012
|
+
action: args.action,
|
|
64013
|
+
...args.target ? { target: args.target } : {},
|
|
64014
|
+
reason: args.reason,
|
|
64015
|
+
...args.artifacts ? { artifacts: args.artifacts } : {}
|
|
64016
|
+
});
|
|
64017
|
+
return { response: { ok: true } };
|
|
64018
|
+
},
|
|
64019
|
+
"topic:reject": async (frame) => {
|
|
64020
|
+
const args = TopicRejectArgsSchema.parse(frame);
|
|
64021
|
+
mustGet(args.topicId);
|
|
64022
|
+
const { rejectCount } = deps.topicStore.bumpReject(args.topicId, args.lineId);
|
|
64023
|
+
deps.topicStore.appendActivity(args.topicId, {
|
|
64024
|
+
actor: "master",
|
|
64025
|
+
action: `\u6253\u56DE ${args.lineId}\uFF08\u7B2C ${rejectCount} \u6B21\uFF09`,
|
|
64026
|
+
target: args.lineId,
|
|
64027
|
+
reason: args.reason
|
|
64028
|
+
});
|
|
64029
|
+
return {
|
|
64030
|
+
response: TopicRejectResultSchema.parse({
|
|
64031
|
+
rejectCount,
|
|
64032
|
+
needsOwnerAttention: rejectCount >= REJECT_ESCALATE_AT
|
|
64033
|
+
})
|
|
64034
|
+
};
|
|
64035
|
+
},
|
|
64036
|
+
"topic:accept": async (frame) => {
|
|
64037
|
+
const args = TopicAcceptArgsSchema.parse(frame);
|
|
64038
|
+
const topic = mustGet(args.topicId);
|
|
64039
|
+
if (!linesOf(topic).some((l) => l.lineId === args.lineId)) {
|
|
64040
|
+
throw new ClawdError(
|
|
64041
|
+
ERROR_CODES.INVALID_PARAM,
|
|
64042
|
+
`line not found in this topic: ${args.lineId}`
|
|
64043
|
+
);
|
|
64044
|
+
}
|
|
64045
|
+
deps.topicStore.markAccepted(args.topicId, args.lineId);
|
|
64046
|
+
deps.topicStore.appendActivity(args.topicId, {
|
|
64047
|
+
actor: "master",
|
|
64048
|
+
action: `\u5224\u5B9A ${args.lineId} \u5408\u683C`,
|
|
64049
|
+
target: args.lineId,
|
|
64050
|
+
reason: args.reason,
|
|
64051
|
+
...args.artifacts ? { artifacts: args.artifacts } : {}
|
|
64052
|
+
});
|
|
64053
|
+
const lines = linesOf(mustGet(args.topicId));
|
|
64054
|
+
const acceptedLines = lines.filter((l) => l.accepted).length;
|
|
64055
|
+
return {
|
|
64056
|
+
response: TopicAcceptResultSchema.parse({
|
|
64057
|
+
acceptedLines,
|
|
64058
|
+
totalLines: lines.length,
|
|
64059
|
+
allAccepted: acceptedLines === lines.length
|
|
64060
|
+
})
|
|
64061
|
+
};
|
|
64062
|
+
},
|
|
64063
|
+
"topic:close": async (frame) => {
|
|
64064
|
+
const args = TopicCloseArgsSchema.parse(frame);
|
|
64065
|
+
mustGet(args.topicId);
|
|
64066
|
+
const topic = deps.topicStore.close(args.topicId, args.state);
|
|
64067
|
+
return { response: TopicResultSchema.parse({ topic }) };
|
|
64068
|
+
}
|
|
64069
|
+
};
|
|
64070
|
+
}
|
|
64071
|
+
|
|
64072
|
+
// src/handlers/line.ts
|
|
64073
|
+
init_protocol();
|
|
64074
|
+
init_claude_history();
|
|
64075
|
+
|
|
64076
|
+
// src/channel/digest.ts
|
|
64077
|
+
var QUOTA = { files: 0.14, commands: 0.12, outputs: 0.22, errors: 0.24, tail: 0.28 };
|
|
64078
|
+
var WRITE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
64079
|
+
var READ_TOOLS = /* @__PURE__ */ new Set(["Read", "NotebookRead"]);
|
|
64080
|
+
var DIGEST_DEFAULTS = { tailAssistant: 12, maxBytes: 2e4 };
|
|
64081
|
+
var firstLine = (s) => String(s ?? "").split("\n")[0].trim();
|
|
64082
|
+
var errSignature = (s) => firstLine(s).replace(/\d+/g, "N").replace(/(^|[\s'"`([])\/[^\s'"`)\]]+/g, "$1<path>").slice(0, 200);
|
|
64083
|
+
var blocksOf = (rec4) => {
|
|
64084
|
+
const c = rec4?.message?.content;
|
|
64085
|
+
return Array.isArray(c) ? c : [];
|
|
64086
|
+
};
|
|
64087
|
+
function takeWithin(lines, budget) {
|
|
64088
|
+
if (!lines.length) return { out: ["- \uFF08\u65E0\uFF09"], clipped: false };
|
|
64089
|
+
const out = [];
|
|
64090
|
+
let used = 0;
|
|
64091
|
+
for (let i = 0; i < lines.length; i++) {
|
|
64092
|
+
const size = Buffer.byteLength(lines[i], "utf8") + 1;
|
|
64093
|
+
if (used + size > budget && out.length) {
|
|
64094
|
+
out.push(`- \u2026\u672C\u8282\u8FD8\u6709 ${lines.length - i} \u6761\u672A\u5217\u51FA\uFF08\u672C\u8282\u914D\u989D ${budget} \u5B57\u8282\u5DF2\u6EE1\uFF09`);
|
|
64095
|
+
return { out, clipped: true };
|
|
64096
|
+
}
|
|
64097
|
+
out.push(lines[i]);
|
|
64098
|
+
used += size;
|
|
64099
|
+
}
|
|
64100
|
+
return { out, clipped: false };
|
|
64101
|
+
}
|
|
64102
|
+
function clampBytes(text, limit) {
|
|
64103
|
+
if (Buffer.byteLength(text, "utf8") <= limit) return text;
|
|
64104
|
+
let lo = 0;
|
|
64105
|
+
let hi = text.length;
|
|
64106
|
+
while (lo < hi) {
|
|
64107
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
64108
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf8") <= limit) lo = mid;
|
|
64109
|
+
else hi = mid - 1;
|
|
64110
|
+
}
|
|
64111
|
+
return text.slice(0, lo);
|
|
64112
|
+
}
|
|
64113
|
+
function buildDigest(records, opts = {}) {
|
|
64114
|
+
const maxBytes = opts.maxBytes ?? DIGEST_DEFAULTS.maxBytes;
|
|
64115
|
+
const tailAssistant = opts.tailAssistant ?? DIGEST_DEFAULTS.tailAssistant;
|
|
64116
|
+
const filesWritten = /* @__PURE__ */ new Set();
|
|
64117
|
+
const filesRead = /* @__PURE__ */ new Set();
|
|
64118
|
+
const commands = /* @__PURE__ */ new Map();
|
|
64119
|
+
const errors = /* @__PURE__ */ new Map();
|
|
64120
|
+
const outputs = [];
|
|
64121
|
+
const pendingCmd = /* @__PURE__ */ new Map();
|
|
64122
|
+
let lastCmd = null;
|
|
64123
|
+
const tail = [];
|
|
64124
|
+
let toolCalls = 0;
|
|
64125
|
+
for (const rec4 of records) {
|
|
64126
|
+
for (const b2 of blocksOf(rec4)) {
|
|
64127
|
+
if (b2.type === "tool_use") {
|
|
64128
|
+
toolCalls += 1;
|
|
64129
|
+
const fp = b2.input?.file_path ?? b2.input?.notebook_path;
|
|
64130
|
+
if (fp && b2.name && WRITE_TOOLS.has(b2.name)) filesWritten.add(String(fp));
|
|
64131
|
+
else if (fp && b2.name && READ_TOOLS.has(b2.name)) filesRead.add(String(fp));
|
|
64132
|
+
if (b2.name === "Bash" && b2.input?.command) {
|
|
64133
|
+
const c = firstLine(b2.input.command);
|
|
64134
|
+
commands.set(c, (commands.get(c) ?? 0) + 1);
|
|
64135
|
+
if (b2.id) pendingCmd.set(b2.id, c);
|
|
64136
|
+
lastCmd = c;
|
|
64137
|
+
}
|
|
64138
|
+
} else if (b2.type === "tool_result" && !b2.is_error) {
|
|
64139
|
+
const cmd = b2.tool_use_id ? pendingCmd.get(b2.tool_use_id) : lastCmd;
|
|
64140
|
+
if (cmd) {
|
|
64141
|
+
const text2 = typeof b2.content === "string" ? b2.content : JSON.stringify(b2.content ?? "");
|
|
64142
|
+
const flat = text2.replace(/\s+/g, " ").trim();
|
|
64143
|
+
if (flat) {
|
|
64144
|
+
outputs.push(`- ${cmd} \u2192 \u2026${flat.slice(-220)}`);
|
|
64145
|
+
if (outputs.length > 40) outputs.shift();
|
|
64146
|
+
}
|
|
64147
|
+
if (b2.tool_use_id) pendingCmd.delete(b2.tool_use_id);
|
|
64148
|
+
}
|
|
64149
|
+
} else if (b2.type === "tool_result" && b2.is_error) {
|
|
64150
|
+
const text2 = typeof b2.content === "string" ? b2.content : JSON.stringify(b2.content ?? "");
|
|
64151
|
+
const sig = errSignature(text2);
|
|
64152
|
+
const prev = errors.get(sig);
|
|
64153
|
+
if (prev) prev.count += 1;
|
|
64154
|
+
else errors.set(sig, { count: 1, sample: firstLine(text2).slice(0, 300) });
|
|
64155
|
+
} else if (b2.type === "text" && rec4.type === "assistant") {
|
|
64156
|
+
tail.push(b2.text ?? "");
|
|
64157
|
+
if (tail.length > tailAssistant) tail.shift();
|
|
64158
|
+
}
|
|
64159
|
+
}
|
|
64160
|
+
}
|
|
64161
|
+
const budget = (k2) => Math.max(200, Math.floor(maxBytes * QUOTA[k2]));
|
|
64162
|
+
let anyClipped = false;
|
|
64163
|
+
const take = (lines, k2) => {
|
|
64164
|
+
const r = takeWithin(lines, budget(k2));
|
|
64165
|
+
if (r.clipped) anyClipped = true;
|
|
64166
|
+
return r.out;
|
|
64167
|
+
};
|
|
64168
|
+
const errLines = [...errors.entries()].sort((x, y2) => y2[1].count - x[1].count).map(([, v2]) => `- \xD7${v2.count} ${v2.sample}`);
|
|
64169
|
+
const cmdLines = [...commands.entries()].map(([c, n]) => n > 1 ? `- \xD7${n} ${c}` : `- ${c}`);
|
|
64170
|
+
const out = [
|
|
64171
|
+
"# worker transcript digest",
|
|
64172
|
+
...opts.transcriptPath ? [`transcript: ${opts.transcriptPath}`] : [],
|
|
64173
|
+
`\u5DE5\u5177\u8C03\u7528\u603B\u6570: ${toolCalls}\uFF5C\u5199\u6587\u4EF6 ${filesWritten.size} \u4E2A\uFF5C\u8BFB\u6587\u4EF6 ${filesRead.size} \u4E2A\uFF5C\u4E0D\u540C\u547D\u4EE4 ${commands.size} \u6761\uFF5C\u62A5\u9519\u7B7E\u540D ${errors.size} \u79CD`,
|
|
64174
|
+
"",
|
|
64175
|
+
"## \u6539\u52A8\u8FC7\u7684\u6587\u4EF6\uFF08\u5F71\u54CD\u9762\uFF1B\u53EA\u7EDF\u8BA1 Write/Edit/MultiEdit/NotebookEdit\uFF09",
|
|
64176
|
+
...take([...filesWritten].map((f) => `- ${f}`), "files"),
|
|
64177
|
+
"",
|
|
64178
|
+
"## \u6267\u884C\u8FC7\u7684\u547D\u4EE4\uFF08\u91CD\u590D\u7684\u6298\u53E0\u8BA1\u6570\uFF09",
|
|
64179
|
+
...take(cmdLines, "commands"),
|
|
64180
|
+
"",
|
|
64181
|
+
"## \u62A5\u9519\uFF08\u6309\u7B7E\u540D\u805A\u5408\uFF1B\u91CD\u590D\u6B21\u6570\u9AD8 = \u649E\u5899\uFF09",
|
|
64182
|
+
...take(errLines, "errors"),
|
|
64183
|
+
"",
|
|
64184
|
+
"## \u6210\u529F\u547D\u4EE4\u7684\u8F93\u51FA\u6458\u5F55\uFF08\u5404\u53D6\u5C3E\u90E8\uFF1B\u5224\u300C\u6D4B\u8BD5\u771F\u8DD1\u8FC7\u6CA1\u3001\u8FC7\u4E86\u51E0\u6761\u300D\u770B\u8FD9\u91CC\uFF09",
|
|
64185
|
+
...take(outputs, "outputs"),
|
|
64186
|
+
"",
|
|
64187
|
+
`## \u6700\u540E ${tail.length} \u6BB5 assistant \u8F93\u51FA\uFF08\u4FDD\u7559\u539F\u6587\u6362\u884C\uFF0C\u6BCF\u6BB5\u622A\u65AD\u81F3 500 \u5B57\uFF09`,
|
|
64188
|
+
// 只留首行会把 worker 的收尾报告砍成「做完了」这种没信息量的一句,
|
|
64189
|
+
// 而那正是判「假完成」最需要的原文。
|
|
64190
|
+
...take(tail.map((t) => `- ${String(t ?? "").slice(0, 500)}`), "tail")
|
|
64191
|
+
];
|
|
64192
|
+
let text = out.join("\n");
|
|
64193
|
+
let truncated = anyClipped;
|
|
64194
|
+
if (Buffer.byteLength(text, "utf8") > maxBytes) {
|
|
64195
|
+
text = clampBytes(text, maxBytes);
|
|
64196
|
+
text += `
|
|
64197
|
+
|
|
64198
|
+
\u26A0\uFE0F digest \u5DF2\u622A\u65AD\uFF08\u4E0A\u9650 ${maxBytes} \u5B57\u8282\uFF09\u2014\u2014\u672A\u89C1\u5168\u90E8\u5185\u5BB9\uFF0C\u5224\u5B9A"\u6CA1\u505A"\u524D\u5148\u8981\u6C42 worker \u81EA\u8BC1\u3002`;
|
|
64199
|
+
truncated = true;
|
|
64200
|
+
} else if (anyClipped) {
|
|
64201
|
+
text += `
|
|
64202
|
+
|
|
64203
|
+
\u26A0\uFE0F digest \u5DF2\u622A\u65AD\uFF08\u6709\u5C0F\u8282\u8D85\u51FA\u914D\u989D\uFF0C\u89C1\u4E0A\u65B9\u300C\u672A\u5217\u51FA\u300D\u6807\u6CE8\uFF09\u2014\u2014\u672A\u89C1\u5168\u90E8\u5185\u5BB9\uFF0C\u5224\u5B9A"\u6CA1\u505A"\u524D\u5148\u8981\u6C42 worker \u81EA\u8BC1\u3002`;
|
|
64204
|
+
}
|
|
64205
|
+
return { digest: text, truncated };
|
|
64206
|
+
}
|
|
64207
|
+
|
|
64208
|
+
// src/handlers/line.ts
|
|
64209
|
+
function buildLineHandlers(deps) {
|
|
64210
|
+
return {
|
|
64211
|
+
"line:digest": async (frame) => {
|
|
64212
|
+
const args = LineDigestArgsSchema.parse(frame);
|
|
64213
|
+
const rec4 = deps.dispatchStore.get(args.dispatchId);
|
|
64214
|
+
if (!rec4) {
|
|
64215
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `dispatch not found: ${args.dispatchId}`);
|
|
64216
|
+
}
|
|
64217
|
+
if (!rec4.workerSessionId) {
|
|
64218
|
+
throw new ClawdError(
|
|
64219
|
+
ERROR_CODES.INVALID_PARAM,
|
|
64220
|
+
`\u8BE5\u7EBF\u8FD8\u6CA1\u6709 worker \u4F1A\u8BDD\uFF08spawn \u672A\u5B8C\u6210\uFF09\uFF0C\u6682\u65F6\u65E0\u6CD5\u6838\u9A8C: ${args.dispatchId}`
|
|
64221
|
+
);
|
|
64222
|
+
}
|
|
64223
|
+
const sf = deps.getSessionFile(rec4.workerSessionId);
|
|
64224
|
+
if (!sf?.toolSessionId) {
|
|
64225
|
+
throw new ClawdError(
|
|
64226
|
+
ERROR_CODES.INVALID_PARAM,
|
|
64227
|
+
`worker \u4F1A\u8BDD\u5C1A\u672A\u4EA7\u751F transcript\uFF08\u8FD8\u6CA1\u8DD1\u8D77\u6765\uFF09: ${rec4.workerSessionId}`
|
|
64228
|
+
);
|
|
64229
|
+
}
|
|
64230
|
+
const file = deps.history.resolveTranscriptFile(sf.cwd, sf.toolSessionId);
|
|
64231
|
+
if (!file) {
|
|
64232
|
+
throw new ClawdError(
|
|
64233
|
+
ERROR_CODES.INVALID_PARAM,
|
|
64234
|
+
`transcript \u4E0D\u5B58\u5728\uFF08worker \u53EF\u80FD\u8FD8\u6CA1\u5199\u76D8\uFF09: ${sf.toolSessionId}`
|
|
64235
|
+
);
|
|
64236
|
+
}
|
|
64237
|
+
return {
|
|
64238
|
+
response: LineDigestResultSchema.parse(
|
|
64239
|
+
buildDigest(streamJsonlLines(file), { transcriptPath: file })
|
|
64240
|
+
)
|
|
64241
|
+
};
|
|
64242
|
+
}
|
|
64243
|
+
};
|
|
64244
|
+
}
|
|
64245
|
+
|
|
64246
|
+
// src/handlers/master.ts
|
|
64247
|
+
init_protocol();
|
|
64248
|
+
|
|
64249
|
+
// src/channel/authority.ts
|
|
64250
|
+
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
64251
|
+
init_protocol();
|
|
64252
|
+
var DEFAULT_AUTHORITY_RULES = [
|
|
64253
|
+
{ id: "outbound-message", desc: "\u4EE5\u8001\u677F\u540D\u4E49\u7ED9\u5176\u4ED6\u4EBA\u53D1\u6D88\u606F\uFF08IM/\u90AE\u4EF6\uFF09", action: "ask" },
|
|
64254
|
+
{ id: "push-remote", desc: "\u63A8\u4EE3\u7801\u5230\u8FDC\u7AEF / \u5408 PR / \u53D1\u5E03\u4E0A\u7EBF", action: "ask" },
|
|
64255
|
+
{ id: "destructive", desc: "\u5220\u9664\u6570\u636E / \u52A8\u751F\u4EA7\u73AF\u5883", action: "ask" },
|
|
64256
|
+
{ id: "spend", desc: "\u82B1\u94B1", action: "ask" }
|
|
64257
|
+
];
|
|
64258
|
+
var askBecause = (reason) => ({
|
|
64259
|
+
action: "ask",
|
|
64260
|
+
desc: reason,
|
|
64261
|
+
source: `fallback:${reason}`
|
|
64262
|
+
});
|
|
64263
|
+
async function resolveAuthority(args) {
|
|
64264
|
+
let rules;
|
|
64265
|
+
let source;
|
|
64266
|
+
let raw = null;
|
|
64267
|
+
try {
|
|
64268
|
+
raw = await import_promises13.default.readFile(args.tablePath, "utf8");
|
|
64269
|
+
} catch (e) {
|
|
64270
|
+
if (e.code !== "ENOENT") {
|
|
64271
|
+
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u8BFB\u4E0D\u51FA\u6765\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
|
|
64272
|
+
}
|
|
64273
|
+
}
|
|
64274
|
+
if (raw === null) {
|
|
64275
|
+
rules = DEFAULT_AUTHORITY_RULES.map((r) => ({ ...r }));
|
|
64276
|
+
source = "default";
|
|
64277
|
+
} else {
|
|
64278
|
+
let parsed;
|
|
64279
|
+
try {
|
|
64280
|
+
parsed = JSON.parse(raw);
|
|
64281
|
+
} catch (e) {
|
|
64282
|
+
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u4E0D\u662F\u5408\u6CD5 JSON\uFF08${args.tablePath}\uFF09\uFF1A${e.message}`);
|
|
64283
|
+
}
|
|
64284
|
+
const check = AuthorityTableSchema.safeParse(parsed);
|
|
64285
|
+
if (!check.success) {
|
|
64286
|
+
return askBecause(`\u6388\u6743\u8BBE\u5B9A\u7ED3\u6784\u4E0D\u5BF9\uFF08${args.tablePath}\uFF09\uFF1A${check.error.issues[0]?.message ?? "\u672A\u77E5"}`);
|
|
64287
|
+
}
|
|
64288
|
+
rules = check.data.rules;
|
|
64289
|
+
source = "table";
|
|
64290
|
+
}
|
|
64291
|
+
const hit = rules.find((r) => r.id === args.ruleId);
|
|
64292
|
+
if (!hit) return askBecause(`\u8868\u91CC\u6CA1\u6709 "${args.ruleId}" \u8FD9\u6761\uFF0C\u672A\u77E5\u52A8\u4F5C\u4E00\u5F8B\u505C\u4E0B\u95EE\u8001\u677F`);
|
|
64293
|
+
return { action: hit.action, desc: hit.desc, source };
|
|
64294
|
+
}
|
|
64295
|
+
|
|
64296
|
+
// src/handlers/master.ts
|
|
64297
|
+
function buildMasterHandlers(deps) {
|
|
64298
|
+
return {
|
|
64299
|
+
"master:authorityCheck": async (frame) => {
|
|
64300
|
+
const { ruleId } = AuthorityCheckArgsSchema.parse(frame);
|
|
64301
|
+
const result = await resolveAuthority({ tablePath: deps.authorityTablePath, ruleId });
|
|
64302
|
+
return { response: AuthorityCheckResultSchema.parse(result) };
|
|
64303
|
+
}
|
|
64304
|
+
};
|
|
64305
|
+
}
|
|
64306
|
+
|
|
63349
64307
|
// src/handlers/github.ts
|
|
63350
64308
|
init_protocol();
|
|
63351
64309
|
|
|
@@ -63616,12 +64574,12 @@ function buildVisitorHandlers(deps) {
|
|
|
63616
64574
|
}
|
|
63617
64575
|
|
|
63618
64576
|
// src/extension/registry.ts
|
|
63619
|
-
var
|
|
63620
|
-
var
|
|
64577
|
+
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
64578
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
63621
64579
|
async function loadAll(root) {
|
|
63622
64580
|
let entries;
|
|
63623
64581
|
try {
|
|
63624
|
-
entries = await
|
|
64582
|
+
entries = await import_promises14.default.readdir(root, { withFileTypes: true });
|
|
63625
64583
|
} catch (e) {
|
|
63626
64584
|
if (e.code === "ENOENT") return [];
|
|
63627
64585
|
throw e;
|
|
@@ -63630,16 +64588,16 @@ async function loadAll(root) {
|
|
|
63630
64588
|
for (const ent of entries) {
|
|
63631
64589
|
if (!ent.isDirectory()) continue;
|
|
63632
64590
|
if (ent.name.startsWith(".")) continue;
|
|
63633
|
-
records.push(await loadOne(
|
|
64591
|
+
records.push(await loadOne(import_node_path64.default.join(root, ent.name), ent.name));
|
|
63634
64592
|
}
|
|
63635
64593
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
63636
64594
|
return records;
|
|
63637
64595
|
}
|
|
63638
64596
|
async function loadOne(dir, dirName) {
|
|
63639
|
-
const manifestPath =
|
|
64597
|
+
const manifestPath = import_node_path64.default.join(dir, "manifest.json");
|
|
63640
64598
|
let raw;
|
|
63641
64599
|
try {
|
|
63642
|
-
raw = await
|
|
64600
|
+
raw = await import_promises14.default.readFile(manifestPath, "utf8");
|
|
63643
64601
|
} catch {
|
|
63644
64602
|
return {
|
|
63645
64603
|
extId: dirName,
|
|
@@ -63680,8 +64638,8 @@ async function loadOne(dir, dirName) {
|
|
|
63680
64638
|
}
|
|
63681
64639
|
|
|
63682
64640
|
// src/extension/uninstall.ts
|
|
63683
|
-
var
|
|
63684
|
-
var
|
|
64641
|
+
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
64642
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
63685
64643
|
var UninstallError = class extends Error {
|
|
63686
64644
|
constructor(code, message) {
|
|
63687
64645
|
super(message);
|
|
@@ -63690,14 +64648,14 @@ var UninstallError = class extends Error {
|
|
|
63690
64648
|
code;
|
|
63691
64649
|
};
|
|
63692
64650
|
async function uninstall(deps) {
|
|
63693
|
-
const dir =
|
|
64651
|
+
const dir = import_node_path65.default.join(deps.root, deps.extId);
|
|
63694
64652
|
try {
|
|
63695
|
-
await
|
|
64653
|
+
await import_promises15.default.access(dir);
|
|
63696
64654
|
} catch {
|
|
63697
64655
|
throw new UninstallError("NOT_FOUND", `extension ${deps.extId} not installed`);
|
|
63698
64656
|
}
|
|
63699
64657
|
await deps.runtime.close(deps.extId);
|
|
63700
|
-
await
|
|
64658
|
+
await import_promises15.default.rm(dir, { recursive: true, force: true });
|
|
63701
64659
|
}
|
|
63702
64660
|
|
|
63703
64661
|
// src/handlers/index.ts
|
|
@@ -63916,6 +64874,22 @@ function buildMethodHandlers(deps) {
|
|
|
63916
64874
|
resolvePersonaRoot: deps.resolvePersonaRoot,
|
|
63917
64875
|
broadcastSessionFrame: deps.broadcastSessionFrame
|
|
63918
64876
|
}),
|
|
64877
|
+
...buildChannelHandlers({ channelStore: deps.channelStore, topicStore: deps.topicStore }),
|
|
64878
|
+
...buildMasterHandlers({
|
|
64879
|
+
authorityTablePath: import_node_path66.default.join(deps.masterDataDir, "master-authority.json")
|
|
64880
|
+
}),
|
|
64881
|
+
...buildLineHandlers({
|
|
64882
|
+
dispatchStore: deps.dispatchStore,
|
|
64883
|
+
getSessionFile: deps.getWorkerSessionFile,
|
|
64884
|
+
// transcript 定位/读取复用 history:* 那个同一个 reader,不另起一份路径规则
|
|
64885
|
+
history: deps.history
|
|
64886
|
+
}),
|
|
64887
|
+
...buildTopicHandlers({
|
|
64888
|
+
topicStore: deps.topicStore,
|
|
64889
|
+
channelStore: deps.channelStore,
|
|
64890
|
+
dispatchStore: deps.dispatchStore,
|
|
64891
|
+
createMasterSession: deps.createMasterSession
|
|
64892
|
+
}),
|
|
63919
64893
|
...buildShiftHandlers({
|
|
63920
64894
|
shiftStore: deps.shiftStore,
|
|
63921
64895
|
ownerIdProvider: deps.shiftOwnerIdProvider,
|
|
@@ -64343,8 +65317,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
64343
65317
|
|
|
64344
65318
|
// src/extension/runtime.ts
|
|
64345
65319
|
var import_node_child_process21 = require("child_process");
|
|
64346
|
-
var
|
|
64347
|
-
var
|
|
65320
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
65321
|
+
var import_promises16 = require("timers/promises");
|
|
64348
65322
|
|
|
64349
65323
|
// src/extension/port-allocator.ts
|
|
64350
65324
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
@@ -64444,7 +65418,7 @@ var Runtime = class {
|
|
|
64444
65418
|
/\$CLAWOS_EXT_PORT/g,
|
|
64445
65419
|
String(port)
|
|
64446
65420
|
);
|
|
64447
|
-
const dir =
|
|
65421
|
+
const dir = import_node_path67.default.join(this.root, extId);
|
|
64448
65422
|
const env = {
|
|
64449
65423
|
...process.env,
|
|
64450
65424
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -64520,7 +65494,7 @@ ${handle.stderrTail}`
|
|
|
64520
65494
|
if (res.ok) return;
|
|
64521
65495
|
} catch {
|
|
64522
65496
|
}
|
|
64523
|
-
await (0,
|
|
65497
|
+
await (0, import_promises16.setTimeout)(this.healthzIntervalMs);
|
|
64524
65498
|
}
|
|
64525
65499
|
throw new RuntimeError(
|
|
64526
65500
|
"HEALTHZ_FAILED",
|
|
@@ -64545,7 +65519,7 @@ ${handle.stderrTail}`
|
|
|
64545
65519
|
};
|
|
64546
65520
|
killGroup("SIGTERM");
|
|
64547
65521
|
const exited = new Promise((resolve9) => child.once("exit", () => resolve9()));
|
|
64548
|
-
const timed = (0,
|
|
65522
|
+
const timed = (0, import_promises16.setTimeout)(5e3).then(() => "timeout");
|
|
64549
65523
|
const winner = await Promise.race([exited.then(() => "exited"), timed]);
|
|
64550
65524
|
if (winner === "timeout" && child.exitCode === null) {
|
|
64551
65525
|
killGroup("SIGKILL");
|
|
@@ -64555,8 +65529,8 @@ ${handle.stderrTail}`
|
|
|
64555
65529
|
};
|
|
64556
65530
|
|
|
64557
65531
|
// src/extension/published-channels.ts
|
|
64558
|
-
var
|
|
64559
|
-
var
|
|
65532
|
+
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
65533
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
64560
65534
|
init_zod();
|
|
64561
65535
|
var PublishedChannelsError = class extends Error {
|
|
64562
65536
|
constructor(code, message) {
|
|
@@ -64586,7 +65560,7 @@ var PublishedChannelStore = class {
|
|
|
64586
65560
|
this.channels.clear();
|
|
64587
65561
|
let raw;
|
|
64588
65562
|
try {
|
|
64589
|
-
raw = await
|
|
65563
|
+
raw = await import_promises17.default.readFile(this.filePath, "utf8");
|
|
64590
65564
|
} catch (e) {
|
|
64591
65565
|
if (e.code === "ENOENT") {
|
|
64592
65566
|
this.loaded = true;
|
|
@@ -64655,15 +65629,15 @@ var PublishedChannelStore = class {
|
|
|
64655
65629
|
)
|
|
64656
65630
|
};
|
|
64657
65631
|
const tmp = `${this.filePath}.tmp`;
|
|
64658
|
-
await
|
|
64659
|
-
await
|
|
64660
|
-
await
|
|
65632
|
+
await import_promises17.default.mkdir(import_node_path68.default.dirname(this.filePath), { recursive: true });
|
|
65633
|
+
await import_promises17.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
65634
|
+
await import_promises17.default.rename(tmp, this.filePath);
|
|
64661
65635
|
}
|
|
64662
65636
|
};
|
|
64663
65637
|
|
|
64664
65638
|
// src/extension/bundle-cache.ts
|
|
64665
|
-
var
|
|
64666
|
-
var
|
|
65639
|
+
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
65640
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
64667
65641
|
var BundleCache = class {
|
|
64668
65642
|
constructor(rootDir) {
|
|
64669
65643
|
this.rootDir = rootDir;
|
|
@@ -64671,17 +65645,17 @@ var BundleCache = class {
|
|
|
64671
65645
|
rootDir;
|
|
64672
65646
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
64673
65647
|
async write(snapshotHash, buffer) {
|
|
64674
|
-
await
|
|
64675
|
-
const file =
|
|
65648
|
+
await import_promises18.default.mkdir(this.rootDir, { recursive: true });
|
|
65649
|
+
const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
64676
65650
|
const tmp = `${file}.tmp`;
|
|
64677
|
-
await
|
|
64678
|
-
await
|
|
65651
|
+
await import_promises18.default.writeFile(tmp, buffer, { mode: 384 });
|
|
65652
|
+
await import_promises18.default.rename(tmp, file);
|
|
64679
65653
|
}
|
|
64680
65654
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
64681
65655
|
async read(snapshotHash) {
|
|
64682
|
-
const file =
|
|
65656
|
+
const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
64683
65657
|
try {
|
|
64684
|
-
return await
|
|
65658
|
+
return await import_promises18.default.readFile(file);
|
|
64685
65659
|
} catch (e) {
|
|
64686
65660
|
if (e.code === "ENOENT") return null;
|
|
64687
65661
|
throw e;
|
|
@@ -64689,8 +65663,8 @@ var BundleCache = class {
|
|
|
64689
65663
|
}
|
|
64690
65664
|
/** Idempotent — missing file is not an error. */
|
|
64691
65665
|
async delete(snapshotHash) {
|
|
64692
|
-
const file =
|
|
64693
|
-
await
|
|
65666
|
+
const file = import_node_path69.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
65667
|
+
await import_promises18.default.rm(file, { force: true });
|
|
64694
65668
|
}
|
|
64695
65669
|
};
|
|
64696
65670
|
|
|
@@ -64712,24 +65686,24 @@ async function startDaemon(config) {
|
|
|
64712
65686
|
sampling: logShippingCfg.sampling,
|
|
64713
65687
|
homeDir: import_node_os24.default.homedir()
|
|
64714
65688
|
});
|
|
64715
|
-
const logDir =
|
|
65689
|
+
const logDir = import_node_path70.default.join(config.dataDir, "log");
|
|
64716
65690
|
import_node_fs52.default.mkdirSync(logDir, { recursive: true });
|
|
64717
65691
|
const logger = createLogger({
|
|
64718
65692
|
level: config.logLevel,
|
|
64719
|
-
file:
|
|
65693
|
+
file: import_node_path70.default.join(logDir, "clawd.log"),
|
|
64720
65694
|
logClient
|
|
64721
65695
|
});
|
|
64722
65696
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
64723
65697
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
64724
|
-
file:
|
|
65698
|
+
file: import_node_path70.default.join(logDir, "screen-idle-probe.log"),
|
|
64725
65699
|
level: "debug"
|
|
64726
65700
|
});
|
|
64727
65701
|
logger.info("screen-idle probe logger enabled", {
|
|
64728
|
-
file:
|
|
65702
|
+
file: import_node_path70.default.join(logDir, "screen-idle-probe.log")
|
|
64729
65703
|
});
|
|
64730
65704
|
const CAP_TARGETS = [
|
|
64731
|
-
|
|
64732
|
-
|
|
65705
|
+
import_node_path70.default.join(logDir, "clawd.log"),
|
|
65706
|
+
import_node_path70.default.join(logDir, "screen-idle-probe.log")
|
|
64733
65707
|
];
|
|
64734
65708
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
64735
65709
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -64825,8 +65799,8 @@ async function startDaemon(config) {
|
|
|
64825
65799
|
const agents = new AgentsScanner();
|
|
64826
65800
|
const history = new ClaudeHistoryReader();
|
|
64827
65801
|
let transport = null;
|
|
64828
|
-
const personaStore = new PersonaStore(
|
|
64829
|
-
const usersRoot =
|
|
65802
|
+
const personaStore = new PersonaStore(import_node_path70.default.join(config.dataDir, "personas"));
|
|
65803
|
+
const usersRoot = import_node_path70.default.join(config.dataDir, "users");
|
|
64830
65804
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
64831
65805
|
if (defaultsRoot) {
|
|
64832
65806
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -64849,7 +65823,7 @@ async function startDaemon(config) {
|
|
|
64849
65823
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
64850
65824
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
64851
65825
|
const dispatchStore = createDispatchStore({
|
|
64852
|
-
filePath:
|
|
65826
|
+
filePath: import_node_path70.default.join(config.dataDir, "dispatch.json"),
|
|
64853
65827
|
now: () => Date.now(),
|
|
64854
65828
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
64855
65829
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -64857,6 +65831,24 @@ async function startDaemon(config) {
|
|
|
64857
65831
|
});
|
|
64858
65832
|
await dispatchStore.load();
|
|
64859
65833
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
65834
|
+
const channelStore = createChannelStore({
|
|
65835
|
+
filePath: import_node_path70.default.join(config.dataDir, "channels.json"),
|
|
65836
|
+
now: () => Date.now(),
|
|
65837
|
+
genId: () => `ch-${v4_default().slice(0, 8)}`,
|
|
65838
|
+
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
65839
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
65840
|
+
})
|
|
65841
|
+
});
|
|
65842
|
+
await channelStore.load();
|
|
65843
|
+
const topicStore = createTopicStore({
|
|
65844
|
+
filePath: import_node_path70.default.join(config.dataDir, "topics.json"),
|
|
65845
|
+
now: () => Date.now(),
|
|
65846
|
+
genId: () => `tp-${v4_default().slice(0, 8)}`,
|
|
65847
|
+
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
65848
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
65849
|
+
})
|
|
65850
|
+
});
|
|
65851
|
+
await topicStore.load();
|
|
64860
65852
|
let deliverPendingRef;
|
|
64861
65853
|
const personaDispatchManager = new PersonaDispatchManager({
|
|
64862
65854
|
genId: () => v4_default(),
|
|
@@ -64864,18 +65856,18 @@ async function startDaemon(config) {
|
|
|
64864
65856
|
now: () => Date.now(),
|
|
64865
65857
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
64866
65858
|
});
|
|
64867
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
65859
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path70.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
64868
65860
|
const mcpConfigs = [];
|
|
64869
65861
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
64870
65862
|
const dispatchServerCandidates = [
|
|
64871
|
-
|
|
65863
|
+
import_node_path70.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
64872
65864
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
64873
|
-
|
|
65865
|
+
import_node_path70.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
64874
65866
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
64875
65867
|
];
|
|
64876
65868
|
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64877
65869
|
if (dispatchServerScriptPath) {
|
|
64878
|
-
const dispatchLogPath =
|
|
65870
|
+
const dispatchLogPath = import_node_path70.default.join(logDir, "dispatch-mcp-server.log");
|
|
64879
65871
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
64880
65872
|
dataDir: config.dataDir,
|
|
64881
65873
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -64895,12 +65887,12 @@ async function startDaemon(config) {
|
|
|
64895
65887
|
});
|
|
64896
65888
|
}
|
|
64897
65889
|
const ticketServerCandidates = [
|
|
64898
|
-
|
|
64899
|
-
|
|
65890
|
+
import_node_path70.default.join(here, "ticket", "mcp-server.cjs"),
|
|
65891
|
+
import_node_path70.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
64900
65892
|
];
|
|
64901
65893
|
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64902
65894
|
if (ticketServerScriptPath) {
|
|
64903
|
-
const ticketLogPath =
|
|
65895
|
+
const ticketLogPath = import_node_path70.default.join(logDir, "ticket-mcp-server.log");
|
|
64904
65896
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
64905
65897
|
dataDir: config.dataDir,
|
|
64906
65898
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -64922,12 +65914,12 @@ async function startDaemon(config) {
|
|
|
64922
65914
|
});
|
|
64923
65915
|
}
|
|
64924
65916
|
const shiftServerCandidates = [
|
|
64925
|
-
|
|
64926
|
-
|
|
65917
|
+
import_node_path70.default.join(here, "shift", "mcp-server.cjs"),
|
|
65918
|
+
import_node_path70.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
64927
65919
|
];
|
|
64928
65920
|
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64929
65921
|
if (shiftServerScriptPath) {
|
|
64930
|
-
const shiftLogPath =
|
|
65922
|
+
const shiftLogPath = import_node_path70.default.join(logDir, "shift-mcp-server.log");
|
|
64931
65923
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
64932
65924
|
dataDir: config.dataDir,
|
|
64933
65925
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -64948,12 +65940,12 @@ async function startDaemon(config) {
|
|
|
64948
65940
|
);
|
|
64949
65941
|
}
|
|
64950
65942
|
const inboxServerCandidates = [
|
|
64951
|
-
|
|
64952
|
-
|
|
65943
|
+
import_node_path70.default.join(here, "inbox", "mcp-server.cjs"),
|
|
65944
|
+
import_node_path70.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
64953
65945
|
];
|
|
64954
65946
|
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64955
65947
|
if (inboxServerScriptPath) {
|
|
64956
|
-
const inboxLogPath =
|
|
65948
|
+
const inboxLogPath = import_node_path70.default.join(logDir, "inbox-mcp-server.log");
|
|
64957
65949
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
64958
65950
|
dataDir: config.dataDir,
|
|
64959
65951
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -64974,8 +65966,8 @@ async function startDaemon(config) {
|
|
|
64974
65966
|
);
|
|
64975
65967
|
}
|
|
64976
65968
|
const peerOpsServerCandidates = [
|
|
64977
|
-
|
|
64978
|
-
|
|
65969
|
+
import_node_path70.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
65970
|
+
import_node_path70.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
64979
65971
|
];
|
|
64980
65972
|
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64981
65973
|
if (peerOpsServerScriptPath) {
|
|
@@ -64997,12 +65989,12 @@ async function startDaemon(config) {
|
|
|
64997
65989
|
);
|
|
64998
65990
|
}
|
|
64999
65991
|
const rpcToolServerCandidates = [
|
|
65000
|
-
|
|
65001
|
-
|
|
65992
|
+
import_node_path70.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
65993
|
+
import_node_path70.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
65002
65994
|
];
|
|
65003
65995
|
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
65004
65996
|
if (rpcToolServerScriptPath) {
|
|
65005
|
-
const rpcToolLogPath =
|
|
65997
|
+
const rpcToolLogPath = import_node_path70.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
65006
65998
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
65007
65999
|
dataDir: config.dataDir,
|
|
65008
66000
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -65023,7 +66015,7 @@ async function startDaemon(config) {
|
|
|
65023
66015
|
);
|
|
65024
66016
|
}
|
|
65025
66017
|
const shiftStore = createShiftStore({
|
|
65026
|
-
filePath:
|
|
66018
|
+
filePath: import_node_path70.default.join(config.dataDir, "shift.json"),
|
|
65027
66019
|
ownerIdProvider: () => ownerPrincipalId,
|
|
65028
66020
|
now: () => Date.now()
|
|
65029
66021
|
});
|
|
@@ -65045,7 +66037,7 @@ async function startDaemon(config) {
|
|
|
65045
66037
|
getAdapter,
|
|
65046
66038
|
historyReader: history,
|
|
65047
66039
|
dataDir: config.dataDir,
|
|
65048
|
-
personaRoot:
|
|
66040
|
+
personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
|
|
65049
66041
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
65050
66042
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
65051
66043
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -65099,7 +66091,7 @@ async function startDaemon(config) {
|
|
|
65099
66091
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
65100
66092
|
attachmentGroup: {
|
|
65101
66093
|
onFileEdit: (input) => {
|
|
65102
|
-
const absPath =
|
|
66094
|
+
const absPath = import_node_path70.default.isAbsolute(input.relPath) ? input.relPath : import_node_path70.default.join(input.cwd, input.relPath);
|
|
65103
66095
|
let size = 0;
|
|
65104
66096
|
try {
|
|
65105
66097
|
size = import_node_fs52.default.statSync(absPath).size;
|
|
@@ -65132,9 +66124,9 @@ async function startDaemon(config) {
|
|
|
65132
66124
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
65133
66125
|
}
|
|
65134
66126
|
const projectsStore = new ProjectsStore({
|
|
65135
|
-
file:
|
|
66127
|
+
file: import_node_path70.default.join(config.dataDir, "projects.json"),
|
|
65136
66128
|
clawdDir: config.dataDir,
|
|
65137
|
-
codexStateFile:
|
|
66129
|
+
codexStateFile: import_node_path70.default.join(import_node_os24.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
65138
66130
|
logger
|
|
65139
66131
|
});
|
|
65140
66132
|
const observer = new SessionObserver({
|
|
@@ -65194,12 +66186,12 @@ async function startDaemon(config) {
|
|
|
65194
66186
|
screenIdleProbeLogger
|
|
65195
66187
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
65196
66188
|
registerAdapter("claude", claudeAdapter);
|
|
65197
|
-
const codexIsolatedHome =
|
|
66189
|
+
const codexIsolatedHome = import_node_path70.default.join(config.dataDir, "codex-home");
|
|
65198
66190
|
try {
|
|
65199
66191
|
import_node_fs52.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
65200
66192
|
for (const f of ["auth.json", "config.toml"]) {
|
|
65201
|
-
const link =
|
|
65202
|
-
const target =
|
|
66193
|
+
const link = import_node_path70.default.join(codexIsolatedHome, f);
|
|
66194
|
+
const target = import_node_path70.default.join(import_node_os24.default.homedir(), ".codex", f);
|
|
65203
66195
|
if (!import_node_fs52.default.existsSync(link) && import_node_fs52.default.existsSync(target)) import_node_fs52.default.symlinkSync(target, link);
|
|
65204
66196
|
}
|
|
65205
66197
|
} catch (err) {
|
|
@@ -65213,11 +66205,11 @@ async function startDaemon(config) {
|
|
|
65213
66205
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
65214
66206
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
65215
66207
|
cwd,
|
|
65216
|
-
personaRoot:
|
|
66208
|
+
personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
|
|
65217
66209
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
65218
66210
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
65219
66211
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
65220
|
-
sharedHome:
|
|
66212
|
+
sharedHome: import_node_path70.default.join(import_node_os24.default.homedir(), ".codex"),
|
|
65221
66213
|
isolatedHome: codexIsolatedHome
|
|
65222
66214
|
})
|
|
65223
66215
|
})
|
|
@@ -65359,6 +66351,29 @@ async function startDaemon(config) {
|
|
|
65359
66351
|
});
|
|
65360
66352
|
const handlers = {
|
|
65361
66353
|
...buildMethodHandlers({
|
|
66354
|
+
channelStore,
|
|
66355
|
+
topicStore,
|
|
66356
|
+
dispatchStore,
|
|
66357
|
+
// line:digest 用:worker session 的 cwd / toolSessionId(transcript 定位的输入)
|
|
66358
|
+
getWorkerSessionFile: (sessionId) => {
|
|
66359
|
+
const f = manager.findOwnedSession(sessionId);
|
|
66360
|
+
return f ? { cwd: f.cwd, ...f.toolSessionId ? { toolSessionId: f.toolSessionId } : {} } : void 0;
|
|
66361
|
+
},
|
|
66362
|
+
masterDataDir: config.dataDir,
|
|
66363
|
+
// 建话题即起该话题的 Master session(1:1)。走与 session:create 同一条 manager.create
|
|
66364
|
+
// 链路,不复制会话创建逻辑;creatorPrincipalId 用本机 deviceId(owner ctx 的 principal.id)。
|
|
66365
|
+
createMasterSession: ({ label }) => {
|
|
66366
|
+
const { response } = manager.create(
|
|
66367
|
+
{ ownerPersonaId: "persona-master", label },
|
|
66368
|
+
authFile.deviceId,
|
|
66369
|
+
ownerDisplayName
|
|
66370
|
+
);
|
|
66371
|
+
const sessionId = response.sessionId;
|
|
66372
|
+
if (typeof sessionId !== "string" || !sessionId) {
|
|
66373
|
+
throw new Error("createMasterSession: manager.create \u6CA1\u6709\u8FD4\u56DE sessionId");
|
|
66374
|
+
}
|
|
66375
|
+
return { sessionId };
|
|
66376
|
+
},
|
|
65362
66377
|
// meta:methods 自省:飞书 gate getter + 最终 handler 表(下面还会 spread 进
|
|
65363
66378
|
// dispatch / shift-internal 两组,只看 buildMethodHandlers 内部表会误报死方法)
|
|
65364
66379
|
feishuActive: () => feishuActive,
|
|
@@ -65408,11 +66423,11 @@ async function startDaemon(config) {
|
|
|
65408
66423
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
65409
66424
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
65410
66425
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
65411
|
-
personaRoot:
|
|
66426
|
+
personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
|
|
65412
66427
|
usersRoot
|
|
65413
66428
|
},
|
|
65414
66429
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
65415
|
-
personaRoot:
|
|
66430
|
+
personaRoot: import_node_path70.default.join(config.dataDir, "personas"),
|
|
65416
66431
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
65417
66432
|
usersRoot,
|
|
65418
66433
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -65545,11 +66560,11 @@ async function startDaemon(config) {
|
|
|
65545
66560
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
65546
66561
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
65547
66562
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
65548
|
-
appBuilderPersonaRoot:
|
|
66563
|
+
appBuilderPersonaRoot: import_node_path70.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
65549
66564
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
65550
|
-
deployKitRoot:
|
|
66565
|
+
deployKitRoot: import_node_path70.default.join(config.dataDir, "deploy-kit"),
|
|
65551
66566
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
65552
|
-
resolvePersonaRoot: (personaId2) =>
|
|
66567
|
+
resolvePersonaRoot: (personaId2) => import_node_path70.default.join(config.dataDir, "personas", personaId2),
|
|
65553
66568
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
65554
66569
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
65555
66570
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -65654,7 +66669,7 @@ async function startDaemon(config) {
|
|
|
65654
66669
|
});
|
|
65655
66670
|
shiftScheduler.start();
|
|
65656
66671
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
65657
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
66672
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path70.default.join(config.dataDir, "personas"));
|
|
65658
66673
|
const larkBotCloud = createLarkBotCloudClient({
|
|
65659
66674
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
65660
66675
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -65668,7 +66683,7 @@ async function startDaemon(config) {
|
|
|
65668
66683
|
store: larkBotStore,
|
|
65669
66684
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
65670
66685
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
65671
|
-
mediaRootFor: (chatId) =>
|
|
66686
|
+
mediaRootFor: (chatId) => import_node_path70.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
65672
66687
|
isShuttingDown: () => larkDraining,
|
|
65673
66688
|
logger: {
|
|
65674
66689
|
warn: (msg) => logger.warn(msg),
|
|
@@ -65973,8 +66988,8 @@ async function startDaemon(config) {
|
|
|
65973
66988
|
const lines = [
|
|
65974
66989
|
`Tunnel: ${r.url}`,
|
|
65975
66990
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
65976
|
-
`Frpc config: ${
|
|
65977
|
-
`Frpc log: ${
|
|
66991
|
+
`Frpc config: ${import_node_path70.default.join(config.dataDir, "frpc.toml")}`,
|
|
66992
|
+
`Frpc log: ${import_node_path70.default.join(logDir, "frpc.log")}`
|
|
65978
66993
|
];
|
|
65979
66994
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
65980
66995
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -65987,7 +67002,7 @@ ${bar}
|
|
|
65987
67002
|
|
|
65988
67003
|
`);
|
|
65989
67004
|
try {
|
|
65990
|
-
const connectPath =
|
|
67005
|
+
const connectPath = import_node_path70.default.join(config.dataDir, "connect.txt");
|
|
65991
67006
|
import_node_fs52.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
65992
67007
|
} catch {
|
|
65993
67008
|
}
|
|
@@ -66051,6 +67066,17 @@ ${bar}
|
|
|
66051
67066
|
await tunnelMgr.stop();
|
|
66052
67067
|
}
|
|
66053
67068
|
await wss.stop();
|
|
67069
|
+
for (const [name, store2] of [
|
|
67070
|
+
["channels", channelStore],
|
|
67071
|
+
["topics", topicStore]
|
|
67072
|
+
]) {
|
|
67073
|
+
await store2.flushNow().catch((err) => {
|
|
67074
|
+
logger.warn("shutdown.store-flush-failed", {
|
|
67075
|
+
store: name,
|
|
67076
|
+
error: err instanceof Error ? err.message : String(err)
|
|
67077
|
+
});
|
|
67078
|
+
});
|
|
67079
|
+
}
|
|
66054
67080
|
stateMgr.delete();
|
|
66055
67081
|
if (logClient) await logClient.dispose();
|
|
66056
67082
|
};
|
|
@@ -66063,7 +67089,7 @@ ${bar}
|
|
|
66063
67089
|
};
|
|
66064
67090
|
}
|
|
66065
67091
|
function migrateDropPersonsDir(dataDir) {
|
|
66066
|
-
const dir =
|
|
67092
|
+
const dir = import_node_path70.default.join(dataDir, "persons");
|
|
66067
67093
|
try {
|
|
66068
67094
|
import_node_fs52.default.rmSync(dir, { recursive: true, force: true });
|
|
66069
67095
|
} catch {
|