@clawos-dev/clawd 0.2.287 → 0.2.289
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
CHANGED
|
@@ -7376,7 +7376,17 @@ var init_schemas = __esm({
|
|
|
7376
7376
|
SessionForkArgs = external_exports.object({
|
|
7377
7377
|
cwd: external_exports.string().min(1),
|
|
7378
7378
|
toolSessionId: external_exports.string().min(1),
|
|
7379
|
-
messageUuid: external_exports.string().min(1)
|
|
7379
|
+
messageUuid: external_exports.string().min(1),
|
|
7380
|
+
/**
|
|
7381
|
+
* 派生 jsonl 的落点 cwd(缺省 = 源文件所在目录,保持老行为)。
|
|
7382
|
+
*
|
|
7383
|
+
* 必须传的场景:调用方随后要用这条 transcript 建 session,而那个 session 的 cwd 与
|
|
7384
|
+
* 源 session 不同——最典型是 persona session(daemon 按 ownerPersonaId 把 cwd 强制
|
|
7385
|
+
* 派生成 persona 根)。CC `--resume` 只在**当前 cwd 的** projects 目录里找 session,
|
|
7386
|
+
* 落点与目标 cwd 分家 = 历史读不到 + resume 接不上(bug: quick-ask-blank-after-worktree)。
|
|
7387
|
+
* 正确编排:先 sessionCreate 拿到 daemon 定的真实 cwd,再以它作 targetCwd fork。
|
|
7388
|
+
*/
|
|
7389
|
+
targetCwd: external_exports.string().min(1).optional()
|
|
7380
7390
|
});
|
|
7381
7391
|
SessionForkResponseSchema = external_exports.object({
|
|
7382
7392
|
forkedToolSessionId: external_exports.string().min(1),
|
|
@@ -8448,6 +8458,16 @@ var init_visitor_schemas = __esm({
|
|
|
8448
8458
|
}
|
|
8449
8459
|
});
|
|
8450
8460
|
|
|
8461
|
+
// ../protocol/src/lark-bot-format.ts
|
|
8462
|
+
function formatLarkSpeakerReminder(speaker) {
|
|
8463
|
+
return `<system-reminder>\u6B64\u6D88\u606F\u6765\u81EA\u98DE\u4E66\u7FA4\u6210\u5458 ${speaker}</system-reminder>`;
|
|
8464
|
+
}
|
|
8465
|
+
var init_lark_bot_format = __esm({
|
|
8466
|
+
"../protocol/src/lark-bot-format.ts"() {
|
|
8467
|
+
"use strict";
|
|
8468
|
+
}
|
|
8469
|
+
});
|
|
8470
|
+
|
|
8451
8471
|
// ../protocol/src/runtime.ts
|
|
8452
8472
|
var init_runtime = __esm({
|
|
8453
8473
|
"../protocol/src/runtime.ts"() {
|
|
@@ -8474,6 +8494,7 @@ var init_runtime = __esm({
|
|
|
8474
8494
|
init_visitor_schemas();
|
|
8475
8495
|
init_shift_internal();
|
|
8476
8496
|
init_lark_bot_schemas();
|
|
8497
|
+
init_lark_bot_format();
|
|
8477
8498
|
}
|
|
8478
8499
|
});
|
|
8479
8500
|
|
|
@@ -13968,6 +13989,26 @@ var init_claude_history = __esm({
|
|
|
13968
13989
|
this.projectsRoot = import_node_path5.default.join(base, "projects");
|
|
13969
13990
|
this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
|
|
13970
13991
|
}
|
|
13992
|
+
/**
|
|
13993
|
+
* [T-17] 定位一条 session 的 transcript 所在 project 目录,带 relocation 兜底。
|
|
13994
|
+
*
|
|
13995
|
+
* 常规路径:`<projectsRoot>/cwdToHashDir(cwd)`。但 CC 中途改 cwd(典型:会话里
|
|
13996
|
+
* EnterWorktree)会把 `<tsid>.jsonl` 挪到新 hash 目录,而调用方手里的 cwd 可能仍是老值——
|
|
13997
|
+
* persona session 尤其顽固:fork 出的新 session 因带 ownerPersonaId 被 manager 强制
|
|
13998
|
+
* 改写 cwd 回 persona 根(session/manager.ts derivePersonaSpawnCwd),与 jsonl 实际
|
|
13999
|
+
* 落点(源文件所在目录,见 session/fork.ts)永久分家。
|
|
14000
|
+
* 拼不出路径时按 tsid 全局兜底(与 fork.ts / observer 同款),命中则用它所在目录。
|
|
14001
|
+
*
|
|
14002
|
+
* 兜底失败仍返回按 cwd 算的目录:下游 readJsonlLines / readdir 都容忍不存在,
|
|
14003
|
+
* 保持"查无此 session 返回空"的既有语义,不抛。
|
|
14004
|
+
* bug: quick-ask-blank-after-worktree(fork 出的快速问答面板整片空白)
|
|
14005
|
+
*/
|
|
14006
|
+
resolveSessionDir(cwd, toolSessionId) {
|
|
14007
|
+
const byCwd = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(cwd));
|
|
14008
|
+
if (import_node_fs6.default.existsSync(import_node_path5.default.join(byCwd, `${toolSessionId}.jsonl`))) return byCwd;
|
|
14009
|
+
const found = findTranscriptByToolSessionId(this.projectsRoot, toolSessionId);
|
|
14010
|
+
return found ? import_node_path5.default.dirname(found) : byCwd;
|
|
14011
|
+
}
|
|
13971
14012
|
async listProjects() {
|
|
13972
14013
|
let entries;
|
|
13973
14014
|
try {
|
|
@@ -14059,8 +14100,7 @@ var init_claude_history = __esm({
|
|
|
14059
14100
|
}
|
|
14060
14101
|
async read(args) {
|
|
14061
14102
|
const file = import_node_path5.default.join(
|
|
14062
|
-
this.
|
|
14063
|
-
cwdToHashDir(args.cwd),
|
|
14103
|
+
this.resolveSessionDir(args.cwd, args.toolSessionId),
|
|
14064
14104
|
`${args.toolSessionId}.jsonl`
|
|
14065
14105
|
);
|
|
14066
14106
|
const lines = readJsonlLines(file);
|
|
@@ -14096,8 +14136,7 @@ var init_claude_history = __esm({
|
|
|
14096
14136
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
14097
14137
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
14098
14138
|
const dir = import_node_path5.default.join(
|
|
14099
|
-
this.
|
|
14100
|
-
cwdToHashDir(cwd),
|
|
14139
|
+
this.resolveSessionDir(cwd, toolSessionId),
|
|
14101
14140
|
toolSessionId,
|
|
14102
14141
|
"subagents"
|
|
14103
14142
|
);
|
|
@@ -14131,8 +14170,7 @@ var init_claude_history = __esm({
|
|
|
14131
14170
|
}
|
|
14132
14171
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
14133
14172
|
const file = import_node_path5.default.join(
|
|
14134
|
-
this.
|
|
14135
|
-
cwdToHashDir(cwd),
|
|
14173
|
+
this.resolveSessionDir(cwd, toolSessionId),
|
|
14136
14174
|
`${toolSessionId}.jsonl`
|
|
14137
14175
|
);
|
|
14138
14176
|
const lines = readJsonlLines(file);
|
|
@@ -14166,8 +14204,7 @@ var init_claude_history = __esm({
|
|
|
14166
14204
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
14167
14205
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
14168
14206
|
const file = import_node_path5.default.join(
|
|
14169
|
-
this.
|
|
14170
|
-
cwdToHashDir(cwd),
|
|
14207
|
+
this.resolveSessionDir(cwd, toolSessionId),
|
|
14171
14208
|
toolSessionId,
|
|
14172
14209
|
"subagents",
|
|
14173
14210
|
`agent-${subagentId}.jsonl`
|
|
@@ -14194,8 +14231,7 @@ var init_claude_history = __esm({
|
|
|
14194
14231
|
*/
|
|
14195
14232
|
readFileHistorySnapshots(args) {
|
|
14196
14233
|
const file = import_node_path5.default.join(
|
|
14197
|
-
this.
|
|
14198
|
-
cwdToHashDir(args.cwd),
|
|
14234
|
+
this.resolveSessionDir(args.cwd, args.toolSessionId),
|
|
14199
14235
|
`${args.toolSessionId}.jsonl`
|
|
14200
14236
|
);
|
|
14201
14237
|
const lines = readJsonlLines(file);
|
|
@@ -14326,8 +14362,7 @@ var init_claude_history = __esm({
|
|
|
14326
14362
|
}
|
|
14327
14363
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
14328
14364
|
const file = import_node_path5.default.join(
|
|
14329
|
-
this.
|
|
14330
|
-
cwdToHashDir(cwd),
|
|
14365
|
+
this.resolveSessionDir(cwd, toolSessionId),
|
|
14331
14366
|
`${toolSessionId}.jsonl`
|
|
14332
14367
|
);
|
|
14333
14368
|
const lines = readJsonlLines(file);
|
|
@@ -46020,6 +46055,14 @@ var SessionManager = class {
|
|
|
46020
46055
|
},
|
|
46021
46056
|
this.deps.personaRoot
|
|
46022
46057
|
);
|
|
46058
|
+
if (args.forkedFromSessionId && args.cwd && args.cwd !== cwd) {
|
|
46059
|
+
this.deps.logger?.info("session-create.fork-cwd-rewritten", {
|
|
46060
|
+
argCwd: args.cwd,
|
|
46061
|
+
derivedCwd: cwd,
|
|
46062
|
+
ownerPersonaId: args.ownerPersonaId,
|
|
46063
|
+
forkedFromSessionId: args.forkedFromSessionId
|
|
46064
|
+
});
|
|
46065
|
+
}
|
|
46023
46066
|
} else if (args.cwd) {
|
|
46024
46067
|
cwd = args.cwd;
|
|
46025
46068
|
} else {
|
|
@@ -51906,6 +51949,7 @@ function createLarkBotCloudClient(opts) {
|
|
|
51906
51949
|
}
|
|
51907
51950
|
|
|
51908
51951
|
// src/lark-bot-connector/chat-router.ts
|
|
51952
|
+
init_protocol();
|
|
51909
51953
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
51910
51954
|
var DEFAULT_TURN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
51911
51955
|
function createLarkChatRouter(deps) {
|
|
@@ -51919,8 +51963,11 @@ function createLarkChatRouter(deps) {
|
|
|
51919
51963
|
deps.logger?.warn(`larkBot chat-router: message envelope missing messageId, drop ${env.eventId}`);
|
|
51920
51964
|
return;
|
|
51921
51965
|
}
|
|
51922
|
-
const
|
|
51923
|
-
const
|
|
51966
|
+
const speaker = env.senderName || env.senderOpenId || "\u672A\u77E5\u6210\u5458";
|
|
51967
|
+
const body = env.text?.trim() ? env.text : "[\u975E\u6587\u672C\u6D88\u606F]";
|
|
51968
|
+
const text = `${body}
|
|
51969
|
+
|
|
51970
|
+
${formatLarkSpeakerReminder(speaker)}`;
|
|
51924
51971
|
const turn = deps.manager.runLarkChatTurn({
|
|
51925
51972
|
personaId: env.personaId,
|
|
51926
51973
|
chatId: env.chatId,
|
|
@@ -57029,8 +57076,9 @@ function forkSession(input) {
|
|
|
57029
57076
|
}
|
|
57030
57077
|
forkedLines.push(JSON.stringify(forked));
|
|
57031
57078
|
}
|
|
57032
|
-
const
|
|
57033
|
-
|
|
57079
|
+
const outDir = input.targetCwd ? import_node_path48.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
57080
|
+
const forkedFilePath = import_node_path48.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
57081
|
+
import_node_fs43.default.mkdirSync(outDir, { recursive: true });
|
|
57034
57082
|
import_node_fs43.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
57035
57083
|
return { forkedToolSessionId, forkedFilePath };
|
|
57036
57084
|
}
|
|
@@ -57255,9 +57303,25 @@ function buildSessionHandlers(deps) {
|
|
|
57255
57303
|
response: { type: "session:rewindable-message-ids", ...response }
|
|
57256
57304
|
};
|
|
57257
57305
|
};
|
|
57258
|
-
const fork = async (frame) => {
|
|
57306
|
+
const fork = async (frame, _client, ctx) => {
|
|
57259
57307
|
const args = SessionForkArgs.parse(frame);
|
|
57308
|
+
if (ctx && ctx.principal.kind === "guest") {
|
|
57309
|
+
const src = store.list().find((s) => s.toolSessionId === args.toolSessionId);
|
|
57310
|
+
const ok = src != null && canAccessPersona(ctx.grants, src.ownerPersonaId, "read") && src.creatorPrincipalId === ctx.principal.id;
|
|
57311
|
+
if (!ok) {
|
|
57312
|
+
throw new ClawdError(
|
|
57313
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
57314
|
+
`principal guest:${ctx.principal.id} cannot fork tool session ${args.toolSessionId}`
|
|
57315
|
+
);
|
|
57316
|
+
}
|
|
57317
|
+
}
|
|
57260
57318
|
const result = forkSession(args);
|
|
57319
|
+
deps.logger?.info("session-fork.done", {
|
|
57320
|
+
argCwd: args.cwd,
|
|
57321
|
+
sourceToolSessionId: args.toolSessionId,
|
|
57322
|
+
forkedToolSessionId: result.forkedToolSessionId,
|
|
57323
|
+
forkedFilePath: result.forkedFilePath
|
|
57324
|
+
});
|
|
57261
57325
|
return { response: { type: "session:fork", ...result } };
|
|
57262
57326
|
};
|
|
57263
57327
|
const newSession = async (frame, _client, ctx) => {
|
|
@@ -57635,15 +57699,28 @@ function buildHistoryHandlers(deps) {
|
|
|
57635
57699
|
const messages = args.slim ? slimHistoryMessages(res.messages) : res.messages;
|
|
57636
57700
|
return { response: { type: "history:read", ...res, messages } };
|
|
57637
57701
|
};
|
|
57702
|
+
const assertGuestOwnsToolSession = (ctx, toolSessionId, method) => {
|
|
57703
|
+
if (!ctx || ctx.principal.kind !== "guest") return;
|
|
57704
|
+
const f = store.list().find((s) => s.toolSessionId === toolSessionId);
|
|
57705
|
+
const ok = f != null && canAccessPersona(ctx.grants, f.ownerPersonaId, "read") && f.creatorPrincipalId === ctx.principal.id;
|
|
57706
|
+
if (!ok) {
|
|
57707
|
+
throw new ClawdError(
|
|
57708
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
57709
|
+
`principal guest:${ctx.principal.id} cannot ${method} of tool session ${toolSessionId}`
|
|
57710
|
+
);
|
|
57711
|
+
}
|
|
57712
|
+
};
|
|
57638
57713
|
const subagents = async (frame, _client, ctx) => {
|
|
57639
57714
|
const args = HistorySubagentsArgs.parse(frame);
|
|
57640
57715
|
assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
57716
|
+
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
57641
57717
|
const subs = await history.listSubagents(args);
|
|
57642
57718
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
57643
57719
|
};
|
|
57644
57720
|
const subagentRead = async (frame, _client, ctx) => {
|
|
57645
57721
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
57646
57722
|
assertGuestPath(ctx, path59.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
57723
|
+
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
57647
57724
|
const res = await history.readSubagent(args);
|
|
57648
57725
|
return { response: { type: "history:subagent-read", ...res } };
|
|
57649
57726
|
};
|
|
@@ -58712,7 +58789,7 @@ function computeMethodAccess(args) {
|
|
|
58712
58789
|
}
|
|
58713
58790
|
|
|
58714
58791
|
// src/version.ts
|
|
58715
|
-
var version = "0.2.
|
|
58792
|
+
var version = "0.2.289".length > 0 ? "0.2.289" : "dev";
|
|
58716
58793
|
|
|
58717
58794
|
// src/cli-probe/probe.ts
|
|
58718
58795
|
var fs55 = __toESM(require("fs"), 1);
|
|
@@ -22520,7 +22520,17 @@ var SessionResumeArgs = external_exports.object({
|
|
|
22520
22520
|
var SessionForkArgs = external_exports.object({
|
|
22521
22521
|
cwd: external_exports.string().min(1),
|
|
22522
22522
|
toolSessionId: external_exports.string().min(1),
|
|
22523
|
-
messageUuid: external_exports.string().min(1)
|
|
22523
|
+
messageUuid: external_exports.string().min(1),
|
|
22524
|
+
/**
|
|
22525
|
+
* 派生 jsonl 的落点 cwd(缺省 = 源文件所在目录,保持老行为)。
|
|
22526
|
+
*
|
|
22527
|
+
* 必须传的场景:调用方随后要用这条 transcript 建 session,而那个 session 的 cwd 与
|
|
22528
|
+
* 源 session 不同——最典型是 persona session(daemon 按 ownerPersonaId 把 cwd 强制
|
|
22529
|
+
* 派生成 persona 根)。CC `--resume` 只在**当前 cwd 的** projects 目录里找 session,
|
|
22530
|
+
* 落点与目标 cwd 分家 = 历史读不到 + resume 接不上(bug: quick-ask-blank-after-worktree)。
|
|
22531
|
+
* 正确编排:先 sessionCreate 拿到 daemon 定的真实 cwd,再以它作 targetCwd fork。
|
|
22532
|
+
*/
|
|
22533
|
+
targetCwd: external_exports.string().min(1).optional()
|
|
22524
22534
|
});
|
|
22525
22535
|
var SessionForkResponseSchema = external_exports.object({
|
|
22526
22536
|
forkedToolSessionId: external_exports.string().min(1),
|