@clawos-dev/clawd 0.2.392 → 0.2.394
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 +221 -35
- package/dist/dispatch/mcp-server.cjs +49 -3
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-BHvC4vAI.css +32 -0
- package/dist/share-ui/assets/guest-CB9N_kze.js +585 -0
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/share-ui/assets/guest-IKclDpC3.js +0 -559
- package/dist/share-ui/assets/guest-n9dDlVV_.css +0 -32
package/dist/cli.cjs
CHANGED
|
@@ -6174,11 +6174,13 @@ var init_dispatch = __esm({
|
|
|
6174
6174
|
external_exports.object({
|
|
6175
6175
|
kind: external_exports.literal("success"),
|
|
6176
6176
|
text: external_exports.string(),
|
|
6177
|
+
brief: external_exports.string().optional(),
|
|
6177
6178
|
filePaths: external_exports.array(external_exports.string()).optional()
|
|
6178
6179
|
}),
|
|
6179
6180
|
external_exports.object({
|
|
6180
6181
|
kind: external_exports.literal("failure"),
|
|
6181
|
-
reason: external_exports.string()
|
|
6182
|
+
reason: external_exports.string(),
|
|
6183
|
+
brief: external_exports.string().optional()
|
|
6182
6184
|
})
|
|
6183
6185
|
]);
|
|
6184
6186
|
DispatchRunArgsSchema = external_exports.object({
|
|
@@ -6189,6 +6191,9 @@ var init_dispatch = __esm({
|
|
|
6189
6191
|
// 省略 = 新开一件事,daemon 铸新 id。
|
|
6190
6192
|
dispatchId: external_exports.string().min(1).optional(),
|
|
6191
6193
|
prompt: external_exports.string(),
|
|
6194
|
+
// 派活方写的 2-3 句摘要(与 prompt 同源同结构)。落台账 `taskBrief` + 进任务包信封
|
|
6195
|
+
// `<brief>`,worker session 的卡片头常显。optional 同 DispatchOutcome.brief 的理由。
|
|
6196
|
+
brief: external_exports.string().optional(),
|
|
6192
6197
|
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
6193
6198
|
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
6194
6199
|
targetDeviceId: external_exports.string().min(1).optional(),
|
|
@@ -6241,6 +6246,18 @@ var init_dispatch = __esm({
|
|
|
6241
6246
|
workerSessionId: external_exports.string().min(1).optional(),
|
|
6242
6247
|
/** 任务摘要;截断(≤500 字符)在 daemon store.add 处保证 */
|
|
6243
6248
|
taskText: external_exports.string(),
|
|
6249
|
+
/**
|
|
6250
|
+
* 派活方写的 2-3 句任务摘要(`DispatchRunArgs.brief`)。台账列表 / butler 面板显示它
|
|
6251
|
+
* 而不是被截断到 500 字符的 `taskText` 半截原文。回报侧的 brief 随 `outcome` 已落盘,
|
|
6252
|
+
* 不在这里重复存。
|
|
6253
|
+
*/
|
|
6254
|
+
taskBrief: external_exports.string().optional(),
|
|
6255
|
+
/**
|
|
6256
|
+
* 第几轮:新开 = 1,每次续派 +1。续派**不单开分型**(一件事一行一 id),
|
|
6257
|
+
* 「第 N 轮」这个语义就落在这里,并透进任务包信封的 `round` 属性供卡片头显示。
|
|
6258
|
+
* 老台账行缺省 → 消费方按 1 处理。
|
|
6259
|
+
*/
|
|
6260
|
+
round: external_exports.number().int().positive().optional(),
|
|
6244
6261
|
status: DispatchStatusSchema,
|
|
6245
6262
|
outcome: DispatchOutcomeSchema.optional(),
|
|
6246
6263
|
/** 上层消费者语义(如司礼监的口谕/验收状态),daemon 不解释 */
|
|
@@ -7089,7 +7106,14 @@ var init_events = __esm({
|
|
|
7089
7106
|
"skill-hint",
|
|
7090
7107
|
"meta-text",
|
|
7091
7108
|
"attachment-skills",
|
|
7092
|
-
"attachment-deferred-tools"
|
|
7109
|
+
"attachment-deferred-tools",
|
|
7110
|
+
// persona dispatch 来源分型(信封契约见 dispatch-format.ts):
|
|
7111
|
+
// dispatch-task 派出去的任务包(首发 + 续派,续派靠信封 round 属性区分,不单开分型)
|
|
7112
|
+
// dispatch-result worker 干完回报注入发起方 session 的结果包
|
|
7113
|
+
// 这两类跟其它 meta 的关键差别:**它们是一轮真实交互**,参与 turn 切分与分页计数
|
|
7114
|
+
// (见 isDispatchUserMeta 的消费点),不是 CC 内部注入的辅助消息。
|
|
7115
|
+
"dispatch-task",
|
|
7116
|
+
"dispatch-result"
|
|
7093
7117
|
];
|
|
7094
7118
|
SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
|
|
7095
7119
|
AGENT_SOURCE_VALUES = [
|
|
@@ -9033,12 +9057,87 @@ var init_visitor_schemas = __esm({
|
|
|
9033
9057
|
function formatLarkSpeakerReminder(speaker) {
|
|
9034
9058
|
return `<system-reminder>\u6B64\u6D88\u606F\u6765\u81EA\u98DE\u4E66\u7FA4\u6210\u5458 ${speaker}</system-reminder>`;
|
|
9035
9059
|
}
|
|
9060
|
+
function formatSenderAttribution(sender) {
|
|
9061
|
+
if (sender.principal === "owner") return "";
|
|
9062
|
+
if (!sender.displayName) return "";
|
|
9063
|
+
return `<system-reminder>\u6B64\u6D88\u606F\u6765\u81EA ${sender.principal}\uFF1A${sender.displayName}</system-reminder>`;
|
|
9064
|
+
}
|
|
9036
9065
|
var init_lark_bot_format = __esm({
|
|
9037
9066
|
"../protocol/src/lark-bot-format.ts"() {
|
|
9038
9067
|
"use strict";
|
|
9039
9068
|
}
|
|
9040
9069
|
});
|
|
9041
9070
|
|
|
9071
|
+
// ../protocol/src/dispatch-format.ts
|
|
9072
|
+
function formatDispatchTaskEnvelope(args) {
|
|
9073
|
+
const attrs = [
|
|
9074
|
+
`dispatch-id="${escapeAttr(args.dispatchId)}"`,
|
|
9075
|
+
...args.from ? [`from="${escapeAttr(args.from)}"`] : [],
|
|
9076
|
+
`round="${args.round}"`
|
|
9077
|
+
].join(" ");
|
|
9078
|
+
return [
|
|
9079
|
+
`<${DISPATCH_TASK_TAG} ${attrs}>`,
|
|
9080
|
+
...briefSection(args.brief),
|
|
9081
|
+
"<detail>",
|
|
9082
|
+
escapeInner(args.detail),
|
|
9083
|
+
"</detail>",
|
|
9084
|
+
`</${DISPATCH_TASK_TAG}>`
|
|
9085
|
+
].join("\n");
|
|
9086
|
+
}
|
|
9087
|
+
function formatDispatchResultEnvelope(args) {
|
|
9088
|
+
const attrs = [
|
|
9089
|
+
`dispatch-id="${escapeAttr(args.dispatchId)}"`,
|
|
9090
|
+
`from="${escapeAttr(args.from)}"`,
|
|
9091
|
+
`status="${args.status}"`
|
|
9092
|
+
].join(" ");
|
|
9093
|
+
return [
|
|
9094
|
+
`<${DISPATCH_RESULT_TAG} ${attrs}>`,
|
|
9095
|
+
...briefSection(args.brief),
|
|
9096
|
+
"<detail>",
|
|
9097
|
+
escapeInner(args.detail),
|
|
9098
|
+
"</detail>",
|
|
9099
|
+
...filesSection(args.filePaths),
|
|
9100
|
+
`</${DISPATCH_RESULT_TAG}>`
|
|
9101
|
+
].join("\n");
|
|
9102
|
+
}
|
|
9103
|
+
function detectDispatchEnvelope(text) {
|
|
9104
|
+
if (!text) return null;
|
|
9105
|
+
const task = text.search(openTagRe(DISPATCH_TASK_TAG));
|
|
9106
|
+
const result = text.search(openTagRe(DISPATCH_RESULT_TAG));
|
|
9107
|
+
if (task < 0 && result < 0) return null;
|
|
9108
|
+
if (result < 0) return "task";
|
|
9109
|
+
if (task < 0) return "result";
|
|
9110
|
+
return task < result ? "task" : "result";
|
|
9111
|
+
}
|
|
9112
|
+
function briefSection(brief) {
|
|
9113
|
+
if (!brief || brief.trim().length === 0) return [];
|
|
9114
|
+
return ["<brief>", escapeInner(brief.trim()), "</brief>"];
|
|
9115
|
+
}
|
|
9116
|
+
function escapeInner(s) {
|
|
9117
|
+
return s.replace(INNER_TAG_ESCAPE_RE, "<\\$1$2$3");
|
|
9118
|
+
}
|
|
9119
|
+
function filesSection(filePaths) {
|
|
9120
|
+
if (!filePaths || filePaths.length === 0) return [];
|
|
9121
|
+
return ["<files>", ...filePaths.map((p2) => `- ${p2}`), "</files>"];
|
|
9122
|
+
}
|
|
9123
|
+
function openTagRe(tag) {
|
|
9124
|
+
return new RegExp(`<${tag}\\b[^>]*>`, "i");
|
|
9125
|
+
}
|
|
9126
|
+
function escapeAttr(v2) {
|
|
9127
|
+
return v2.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
9128
|
+
}
|
|
9129
|
+
var DISPATCH_TASK_TAG, DISPATCH_RESULT_TAG, INNER_TAG_NAMES, INNER_TAG_ESCAPE_RE, INNER_TAG_UNESCAPE_RE;
|
|
9130
|
+
var init_dispatch_format = __esm({
|
|
9131
|
+
"../protocol/src/dispatch-format.ts"() {
|
|
9132
|
+
"use strict";
|
|
9133
|
+
DISPATCH_TASK_TAG = "clawd-dispatch-task";
|
|
9134
|
+
DISPATCH_RESULT_TAG = "clawd-dispatch-result";
|
|
9135
|
+
INNER_TAG_NAMES = "clawd-dispatch-task|clawd-dispatch-result|brief|detail|files";
|
|
9136
|
+
INNER_TAG_ESCAPE_RE = new RegExp(`<(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
9137
|
+
INNER_TAG_UNESCAPE_RE = new RegExp(`<\\\\(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
9138
|
+
}
|
|
9139
|
+
});
|
|
9140
|
+
|
|
9042
9141
|
// ../protocol/src/runtime.ts
|
|
9043
9142
|
var init_runtime = __esm({
|
|
9044
9143
|
"../protocol/src/runtime.ts"() {
|
|
@@ -9070,6 +9169,7 @@ var init_runtime = __esm({
|
|
|
9070
9169
|
init_shift_internal();
|
|
9071
9170
|
init_lark_bot_schemas();
|
|
9072
9171
|
init_lark_bot_format();
|
|
9172
|
+
init_dispatch_format();
|
|
9073
9173
|
init_onboarding_schemas();
|
|
9074
9174
|
}
|
|
9075
9175
|
});
|
|
@@ -14330,6 +14430,10 @@ function classifyUserMessage(input) {
|
|
|
14330
14430
|
if (parentToolUseId) out.parentToolUseId = parentToolUseId;
|
|
14331
14431
|
return out;
|
|
14332
14432
|
}
|
|
14433
|
+
const dispatchKind = detectDispatchEnvelope(text);
|
|
14434
|
+
if (dispatchKind) {
|
|
14435
|
+
return { meta: dispatchKind === "task" ? "dispatch-task" : "dispatch-result" };
|
|
14436
|
+
}
|
|
14333
14437
|
if (SLASH_COMMAND_RE.test(text)) return { meta: "slash-command" };
|
|
14334
14438
|
if (LOCAL_COMMAND_RE.test(text)) return { meta: "local-command" };
|
|
14335
14439
|
if (SYSTEM_REMINDER_RE.test(text) || OPENSPEC_BLOCK_RE.test(text)) {
|
|
@@ -14586,6 +14690,7 @@ var init_claude_history = __esm({
|
|
|
14586
14690
|
import_node_path5 = __toESM(require("path"), 1);
|
|
14587
14691
|
import_node_string_decoder = require("string_decoder");
|
|
14588
14692
|
init_lib();
|
|
14693
|
+
init_protocol();
|
|
14589
14694
|
init_tool_result_extra();
|
|
14590
14695
|
JSONL_CHUNK_BYTES = 256 * 1024;
|
|
14591
14696
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -44590,7 +44695,7 @@ function mergeOwnerCredentials(guestSandbox, bundle) {
|
|
|
44590
44695
|
// src/shift/wrap.ts
|
|
44591
44696
|
function wrapShiftFirePrompt(args) {
|
|
44592
44697
|
return [
|
|
44593
|
-
`<clawd-shift-fire target-persona="${
|
|
44698
|
+
`<clawd-shift-fire target-persona="${escapeAttr2(args.targetPersona)}">`,
|
|
44594
44699
|
"This is a scheduled shift fire \u2014 not a live user message.",
|
|
44595
44700
|
"Respond as an assistant turn (start your output directly).",
|
|
44596
44701
|
"",
|
|
@@ -44599,7 +44704,7 @@ function wrapShiftFirePrompt(args) {
|
|
|
44599
44704
|
"</clawd-shift-fire>"
|
|
44600
44705
|
].join("\n");
|
|
44601
44706
|
}
|
|
44602
|
-
function
|
|
44707
|
+
function escapeAttr2(v2) {
|
|
44603
44708
|
return v2.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
44604
44709
|
}
|
|
44605
44710
|
|
|
@@ -44645,6 +44750,7 @@ function dispatchShiftEnd(info, settle, killImpl) {
|
|
|
44645
44750
|
}
|
|
44646
44751
|
|
|
44647
44752
|
// src/dispatch/delivery.ts
|
|
44753
|
+
init_protocol();
|
|
44648
44754
|
function selectPendingForDelivery(records, sourceSessionId) {
|
|
44649
44755
|
return records.filter(
|
|
44650
44756
|
(r) => r.sourceSessionId === sourceSessionId && (r.status === "completed" || r.status === "failed") && !r.deliveredAt
|
|
@@ -44652,16 +44758,24 @@ function selectPendingForDelivery(records, sourceSessionId) {
|
|
|
44652
44758
|
}
|
|
44653
44759
|
function formatDeliveryText(records) {
|
|
44654
44760
|
const blocks = records.map((r) => {
|
|
44655
|
-
const head = `[dispatch ${r.dispatchId} \u2192 ${r.targetPersonaId}]`;
|
|
44656
44761
|
if (r.outcome?.kind === "success") {
|
|
44657
|
-
|
|
44658
|
-
|
|
44659
|
-
|
|
44660
|
-
|
|
44661
|
-
|
|
44762
|
+
return formatDispatchResultEnvelope({
|
|
44763
|
+
dispatchId: r.dispatchId,
|
|
44764
|
+
from: r.targetPersonaId,
|
|
44765
|
+
status: "success",
|
|
44766
|
+
...r.outcome.brief ? { brief: r.outcome.brief } : {},
|
|
44767
|
+
detail: r.outcome.text,
|
|
44768
|
+
...r.outcome.filePaths && r.outcome.filePaths.length > 0 ? { filePaths: r.outcome.filePaths } : {}
|
|
44769
|
+
});
|
|
44662
44770
|
}
|
|
44663
44771
|
const reason = r.outcome?.kind === "failure" ? r.outcome.reason : "unknown failure";
|
|
44664
|
-
return
|
|
44772
|
+
return formatDispatchResultEnvelope({
|
|
44773
|
+
dispatchId: r.dispatchId,
|
|
44774
|
+
from: r.targetPersonaId,
|
|
44775
|
+
status: "failure",
|
|
44776
|
+
...r.outcome?.kind === "failure" && r.outcome.brief ? { brief: r.outcome.brief } : {},
|
|
44777
|
+
detail: reason
|
|
44778
|
+
});
|
|
44665
44779
|
});
|
|
44666
44780
|
return ["\u4F60\u4E4B\u524D\u59D4\u6D3E\u51FA\u53BB\u7684\u4EFB\u52A1\u6709\u4E86\u7ED3\u679C\uFF1A", "", blocks.join("\n\n")].join("\n");
|
|
44667
44781
|
}
|
|
@@ -44832,6 +44946,7 @@ var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A perso
|
|
|
44832
44946
|
|
|
44833
44947
|
- \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
|
|
44834
44948
|
- \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
|
|
44949
|
+
- \`brief = 2-3 \u53E5\u8BF4\u6E05\u4F60\u5728\u8981\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48\u91CD\u8981\`\uFF08\u5BF9\u65B9 session \u7684\u5361\u7247\u5934\u5E38\u663E\u8FD9\u6BB5\uFF0C\u7528\u6237\u4E0D\u5C55\u5F00\u5C31\u53EA\u770B\u5F97\u5230\u5B83\uFF1B\u7ED3\u6784\u8981\u8DDF prompt \u5BF9\u5E94\uFF0C\u522B\u8BB2\u4E24\u4E2A\u6545\u4E8B\uFF09
|
|
44835
44950
|
|
|
44836
44951
|
\u544A\u8BC9\u7528\u6237"\u4EFB\u52A1\u5DF2\u4EA4\u529E"\u5373\u53EF\u7ED3\u675F\u672C\u8F6E\u3002\u7ED3\u679C\u4F1A\u4F5C\u4E3A\u4E00\u6761\u65B0\u6D88\u606F\u81EA\u52A8\u6CE8\u5165\u56DE\u4F60\u7684 session\uFF0C\u5C4A\u65F6\u518D\u7EFC\u5408\u8F6C\u8FBE\u7ED9\u7528\u6237\u3002\u60F3\u67E5\u8FDB\u5C55\u65F6\uFF08\u7528\u6237\u95EE\u8D77\uFF09\u8C03\u540C\u4E00 MCP \u7684 \`personaDispatchList\`\u3002
|
|
44837
44952
|
|
|
@@ -44867,13 +44982,26 @@ deviceId \u76F4\u63A5\u53D6\u81EA token\uFF0C\u4E0D\u8981\u6539\u5199\u6216\u731
|
|
|
44867
44982
|
|
|
44868
44983
|
## \u88AB dispatch \u63A5\u5230\u4EFB\u52A1
|
|
44869
44984
|
|
|
44870
|
-
\u5982\u679C\
|
|
44985
|
+
\u5982\u679C\u6536\u5230\u4E00\u6761\u5305\u5728 \`<clawd-dispatch-task \u2026>\` \u4FE1\u5C01\u91CC\u7684\u6D88\u606F\uFF0C\u4F60\u662F\u88AB\u53E6\u4E00\u4E2A persona \u59D4\u6D3E\u6765\u5E72\u6D3B\u7684\uFF1A
|
|
44986
|
+
|
|
44987
|
+
\`\`\`
|
|
44988
|
+
<clawd-dispatch-task dispatch-id="\u2026" from="<\u6D3E\u6D3B\u65B9 persona>" round="1">
|
|
44989
|
+
<brief>\u6D3E\u6D3B\u65B9\u5199\u7684 2-3 \u53E5\u6458\u8981</brief>
|
|
44990
|
+
<detail>
|
|
44991
|
+
[Dispatched from owner \u2014 another persona session\u59D4\u6D3E\u7ED9\u4F60\u6267\u884C\u4EFB\u52A1]
|
|
44992
|
+
\u2026\u4EFB\u52A1\u6B63\u6587\u2026
|
|
44993
|
+
</detail>
|
|
44994
|
+
</clawd-dispatch-task>
|
|
44995
|
+
\`\`\`
|
|
44871
44996
|
|
|
44872
|
-
- \u4EFB\u52A1\u5728 \`Task:\` \
|
|
44997
|
+
- \u4EFB\u52A1\u5728 \`<detail>\` \u6BB5\u7684 \`Task:\` \u91CC\uFF1B\`<brief>\` \u53EA\u662F\u6458\u8981\uFF0C\u522B\u5F53\u4EFB\u52A1\u8BFB
|
|
44998
|
+
- \`round="N"\`\uFF1A\`1\` = \u9996\u6B21\u6D3E\u6D3B\uFF0C\`2\` \u53CA\u4EE5\u4E0A = **\u540C\u4E00\u4EF6\u4E8B\u7684\u7B2C N \u8F6E\u7EED\u6D3E**\uFF08\u4E0A\u4E0B\u6587\u8FD8\u5728\uFF0C\u63A5\u7740\u5E72\uFF0C\u4E0D\u8981\u4ECE\u5934\u6765\uFF09
|
|
44873
44999
|
- \u539F\u4F1A\u8BDD\u7684\u5BF9\u8BDD\u5386\u53F2\u5728 \`Source conversation\` \u6BB5\u7ED9\u7684 jsonl \u8DEF\u5F84\u4E0B\uFF1B\u6309\u9700 Read \u5B83\u4E86\u89E3\u4E0A\u4E0B\u6587\uFF08\u4E0D\u5FC5\u8BFB\u5B8C\uFF09
|
|
44874
45000
|
- \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`clawd-dispatch\` MCP \u7684 \`personaDispatchComplete\` tool \u62A5\u544A\u7ED3\u679C\uFF1A
|
|
44875
|
-
- \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
|
|
44876
|
-
- \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "..." }\`
|
|
45001
|
+
- \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", brief: "2-3 \u53E5", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
|
|
45002
|
+
- \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "...", brief: "2-3 \u53E5\u8BF4\u6E05\u5361\u5728\u54EA" }\`
|
|
45003
|
+
- \`brief\` \u4E24\u79CD\u60C5\u51B5\u90FD\u8981\u586B\uFF1A\u5B83\u662F\u5BF9\u65B9\u770B\u5230\u7684\u5E38\u663E\u6458\u8981\uFF08\u987A\u4E0D\u987A\u3001\u6709\u6CA1\u6709\u574F\u3001\u6700\u8BE5\u77E5\u9053\u7684\u4E00\u4EF6\u4E8B\uFF09\uFF0C
|
|
45004
|
+
\u7ED3\u6784\u8DDF \`text\` / \`reason\` \u4E00\u4E00\u5BF9\u5E94\u2014\u2014brief \u8BF4\u4E09\u70B9\uFF0C\u6B63\u6587\u5C31\u8BE5\u6709\u5BF9\u5E94\u7684\u4E09\u6BB5\uFF0C\u522B\u8BB2\u4E24\u4E2A\u6545\u4E8B
|
|
44877
45005
|
- \u62A5\u544A\u5B8C\u540E\u4F60\u7684 session \u5C31\u7ED3\u675F\u4E86\uFF0C\u4E0D\u8981\u7EE7\u7EED\u8F93\u51FA`;
|
|
44878
45006
|
|
|
44879
45007
|
// src/session/reducer-types.ts
|
|
@@ -45315,7 +45443,10 @@ function applyCommand(state, command, deps) {
|
|
|
45315
45443
|
kind: "user_text",
|
|
45316
45444
|
text: command.text,
|
|
45317
45445
|
uuid: deps.genUuid?.(),
|
|
45318
|
-
sender: command.senderPrincipal
|
|
45446
|
+
sender: command.senderPrincipal,
|
|
45447
|
+
// dispatch 来源分型(L2):daemon 自注入的消息在 command 上显式带分型值。
|
|
45448
|
+
// history 侧同一条消息由 classifyUserMessage 从信封解出同一个值 —— 两路必须一致。
|
|
45449
|
+
...command.meta ? { meta: command.meta } : {}
|
|
45319
45450
|
};
|
|
45320
45451
|
const pushed = pushEventToBuffer(next, userEvent, deps);
|
|
45321
45452
|
effects.push(...pushed.effects);
|
|
@@ -46369,6 +46500,16 @@ function newSessionId() {
|
|
|
46369
46500
|
return v4_default().replace(/-/g, "").slice(0, 16);
|
|
46370
46501
|
}
|
|
46371
46502
|
function buildDispatchTaskPack(args) {
|
|
46503
|
+
return formatDispatchTaskEnvelope({
|
|
46504
|
+
dispatchId: args.dispatchId,
|
|
46505
|
+
...args.from ? { from: args.from } : {},
|
|
46506
|
+
// 首发恒 1;续派包由 handlers/persona-dispatch.ts 的 buildFollowUpTaskPack 带 N
|
|
46507
|
+
round: 1,
|
|
46508
|
+
...args.brief ? { brief: args.brief } : {},
|
|
46509
|
+
detail: buildDispatchTaskDetail(args)
|
|
46510
|
+
});
|
|
46511
|
+
}
|
|
46512
|
+
function buildDispatchTaskDetail(args) {
|
|
46372
46513
|
return `[Dispatched from owner \u2014 another persona session\u59D4\u6D3E\u7ED9\u4F60\u6267\u884C\u4EFB\u52A1]
|
|
46373
46514
|
|
|
46374
46515
|
Task:
|
|
@@ -47314,7 +47455,8 @@ var SessionManager = class {
|
|
|
47314
47455
|
if (pending.length === 0) return;
|
|
47315
47456
|
const state = this.tryGetState(sourceSessionId);
|
|
47316
47457
|
if (state && compressStatus(state.status) === "running") return;
|
|
47317
|
-
if (!this.injectIntoSession(sourceSessionId, formatDeliveryText(pending)))
|
|
47458
|
+
if (!this.injectIntoSession(sourceSessionId, formatDeliveryText(pending), "dispatch-result"))
|
|
47459
|
+
return;
|
|
47318
47460
|
const nowIso3 = new Date(this.deps.now?.() ?? Date.now()).toISOString();
|
|
47319
47461
|
for (const r of pending) store.update(r.dispatchId, { deliveredAt: nowIso3 });
|
|
47320
47462
|
this.deps.logger?.info("dispatch.deliver.ok", {
|
|
@@ -47328,8 +47470,17 @@ var SessionManager = class {
|
|
|
47328
47470
|
* (deliverPending)与续派任务包(handlers/persona-dispatch 经 sendFollowUp 闭包)共用。
|
|
47329
47471
|
* session 文件不存在或 send 抛错 → false(记 log,不 throw)。直接 runner.input
|
|
47330
47472
|
* (无 collector),frames 经 routeFromRunner 正常广播上 wire。
|
|
47473
|
+
*
|
|
47474
|
+
* 来源分型(L2):`meta` 显式声明"这条注入是什么"('dispatch-task' / 'dispatch-result'),
|
|
47475
|
+
* reducer 原样 stamp 到 synth 的 user_text,与 history 侧 classifyUserMessage 从信封
|
|
47476
|
+
* 解出的值必须一致。
|
|
47477
|
+
*
|
|
47478
|
+
* sender 仍是 owner —— **sender 与 origin 是两个正交维度**:sender 回答"以谁的身份跑
|
|
47479
|
+
* 这一轮"(MCP endpoint / ticket api 主键要它,daemon 是代 owner 触发的,伪造 'persona'
|
|
47480
|
+
* 会污染下游主键),origin 回答"这条消息从哪来",后者由 meta + 信封表达。渲染层按
|
|
47481
|
+
* origin 分 owner / guest / persona 三档,persona 档正是 meta 命中 dispatch-* 这一支。
|
|
47331
47482
|
*/
|
|
47332
|
-
injectIntoSession(sessionId, text) {
|
|
47483
|
+
injectIntoSession(sessionId, text, meta) {
|
|
47333
47484
|
if (!this.deps.ownerPrincipalId) {
|
|
47334
47485
|
this.deps.logger?.warn("dispatch.inject.no-owner-principal", { sessionId });
|
|
47335
47486
|
return false;
|
|
@@ -47350,7 +47501,7 @@ var SessionManager = class {
|
|
|
47350
47501
|
const runner = this.ensureRunnerForScope(file, this.scopeForFile(file));
|
|
47351
47502
|
runner.input({
|
|
47352
47503
|
kind: "command",
|
|
47353
|
-
command: { kind: "send", text, senderPrincipal: sender }
|
|
47504
|
+
command: { kind: "send", text, senderPrincipal: sender, ...meta ? { meta } : {} }
|
|
47354
47505
|
});
|
|
47355
47506
|
return true;
|
|
47356
47507
|
} catch (err) {
|
|
@@ -47926,10 +48077,13 @@ var SessionManager = class {
|
|
|
47926
48077
|
dispatchId: args.dispatchId,
|
|
47927
48078
|
bSessionId: sessionId
|
|
47928
48079
|
});
|
|
48080
|
+
const fromPersonaId = args.guestPrincipalId ? args.guestDisplayName : this.findOwnedSession(args.sourceSessionId)?.ownerPersonaId;
|
|
47929
48081
|
const taskPack = buildDispatchTaskPack({
|
|
47930
48082
|
prompt: args.prompt,
|
|
47931
48083
|
sourceJsonlPath: args.sourceJsonlPath,
|
|
47932
|
-
dispatchId: args.dispatchId
|
|
48084
|
+
dispatchId: args.dispatchId,
|
|
48085
|
+
...fromPersonaId ? { from: fromPersonaId } : {},
|
|
48086
|
+
...args.brief ? { brief: args.brief } : {}
|
|
47933
48087
|
});
|
|
47934
48088
|
let dispatchSender;
|
|
47935
48089
|
if (args.guestPrincipalId) {
|
|
@@ -47950,7 +48104,14 @@ var SessionManager = class {
|
|
|
47950
48104
|
}
|
|
47951
48105
|
runner.input({
|
|
47952
48106
|
kind: "command",
|
|
47953
|
-
|
|
48107
|
+
// 来源分型(L2):realtime 路径显式带 meta,与 history 侧 classifyUserMessage
|
|
48108
|
+
// 从信封解出的值一致 —— 两路不一致会打歪 trimHistoryOverlap 的 anchor。
|
|
48109
|
+
command: {
|
|
48110
|
+
kind: "send",
|
|
48111
|
+
text: taskPack,
|
|
48112
|
+
senderPrincipal: dispatchSender,
|
|
48113
|
+
meta: "dispatch-task"
|
|
48114
|
+
}
|
|
47954
48115
|
});
|
|
47955
48116
|
this.deps.logger?.info("dispatch.createDispatchedSession.task-pack-sent", {
|
|
47956
48117
|
dispatchId: args.dispatchId,
|
|
@@ -52488,6 +52649,7 @@ var PersonaDispatchManager = class {
|
|
|
52488
52649
|
...args.sourcePersonaId ? { sourcePersonaId: args.sourcePersonaId } : {},
|
|
52489
52650
|
targetPersonaId: args.targetPersona,
|
|
52490
52651
|
taskText: args.taskText,
|
|
52652
|
+
...args.taskBrief ? { taskBrief: args.taskBrief } : {},
|
|
52491
52653
|
...args.meta ? { meta: args.meta } : {}
|
|
52492
52654
|
});
|
|
52493
52655
|
return { dispatchId };
|
|
@@ -52600,6 +52762,9 @@ function createDispatchStore(deps) {
|
|
|
52600
52762
|
...input.sourcePersonaId ? { sourcePersonaId: input.sourcePersonaId } : {},
|
|
52601
52763
|
targetPersonaId: input.targetPersonaId,
|
|
52602
52764
|
taskText: input.taskText.slice(0, TASK_TEXT_MAX),
|
|
52765
|
+
...input.taskBrief ? { taskBrief: input.taskBrief } : {},
|
|
52766
|
+
// 新开 dispatch = 第 1 轮;续派在 handler 里 +1
|
|
52767
|
+
round: 1,
|
|
52603
52768
|
status: "running",
|
|
52604
52769
|
...input.meta ? { meta: input.meta } : {},
|
|
52605
52770
|
createdAt: new Date(deps.now()).toISOString()
|
|
@@ -54349,16 +54514,20 @@ function canAccessPersona(grants, personaId2, action) {
|
|
|
54349
54514
|
|
|
54350
54515
|
// src/handlers/persona-dispatch.ts
|
|
54351
54516
|
init_claude();
|
|
54352
|
-
function buildFollowUpTaskPack(dispatchId, prompt) {
|
|
54353
|
-
return
|
|
54354
|
-
|
|
54355
|
-
|
|
54356
|
-
|
|
54357
|
-
|
|
54358
|
-
|
|
54359
|
-
|
|
54360
|
-
|
|
54361
|
-
|
|
54517
|
+
function buildFollowUpTaskPack(dispatchId, prompt, round) {
|
|
54518
|
+
return formatDispatchTaskEnvelope({
|
|
54519
|
+
dispatchId,
|
|
54520
|
+
round,
|
|
54521
|
+
detail: [
|
|
54522
|
+
`[Follow-up instruction for dispatch ${dispatchId}]`,
|
|
54523
|
+
"",
|
|
54524
|
+
`Task: ${prompt}`,
|
|
54525
|
+
"",
|
|
54526
|
+
`This is a follow-up turn in the same dispatched task (dispatchId=${dispatchId}).`,
|
|
54527
|
+
"When you finish this round, report back by calling personaDispatchComplete again,",
|
|
54528
|
+
"exactly as you did before."
|
|
54529
|
+
].join("\n")
|
|
54530
|
+
});
|
|
54362
54531
|
}
|
|
54363
54532
|
function buildPersonaDispatchHandlers(deps) {
|
|
54364
54533
|
const { personaDispatchManager: mgr, spawnB, logger } = deps;
|
|
@@ -54405,12 +54574,15 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54405
54574
|
if (!deps.sendFollowUp) {
|
|
54406
54575
|
throw new Error("follow-up dispatch not wired (sendFollowUp missing)");
|
|
54407
54576
|
}
|
|
54577
|
+
const nextRound = (rec4.round ?? 1) + 1;
|
|
54408
54578
|
deps.store.update(args.dispatchId, {
|
|
54409
54579
|
status: "running",
|
|
54410
54580
|
outcome: void 0,
|
|
54411
54581
|
completedAt: void 0,
|
|
54412
54582
|
deliveredAt: void 0,
|
|
54413
54583
|
taskText: args.prompt.slice(0, TASK_TEXT_MAX),
|
|
54584
|
+
round: nextRound,
|
|
54585
|
+
...args.brief ? { taskBrief: args.brief } : {},
|
|
54414
54586
|
...args.meta ? { meta: { ...rec4.meta ?? {}, ...args.meta } } : {}
|
|
54415
54587
|
});
|
|
54416
54588
|
mgr.reopen(args.dispatchId, {
|
|
@@ -54425,7 +54597,10 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54425
54597
|
});
|
|
54426
54598
|
const ok = deps.sendFollowUp(
|
|
54427
54599
|
rec4.workerSessionId,
|
|
54428
|
-
buildFollowUpTaskPack(args.dispatchId, args.prompt)
|
|
54600
|
+
buildFollowUpTaskPack(args.dispatchId, args.prompt, nextRound),
|
|
54601
|
+
// 来源分型(L2):续派并进 dispatch-task;realtime 侧靠这个 meta 打标,
|
|
54602
|
+
// history 侧靠 classifyUserMessage 从信封解出同值。
|
|
54603
|
+
"dispatch-task"
|
|
54429
54604
|
);
|
|
54430
54605
|
if (!ok) {
|
|
54431
54606
|
mgr.complete(args.dispatchId, {
|
|
@@ -54487,6 +54662,7 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54487
54662
|
sourceSessionId,
|
|
54488
54663
|
targetPersona,
|
|
54489
54664
|
taskText: args.prompt,
|
|
54665
|
+
...args.brief ? { taskBrief: args.brief } : {},
|
|
54490
54666
|
...args.meta ? { meta: args.meta } : {}
|
|
54491
54667
|
});
|
|
54492
54668
|
logger?.info("dispatch.run.forward", {
|
|
@@ -54520,6 +54696,7 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54520
54696
|
sourceSessionId: ctx.principal.id,
|
|
54521
54697
|
targetPersona,
|
|
54522
54698
|
taskText: args.prompt,
|
|
54699
|
+
...args.brief ? { taskBrief: args.brief } : {},
|
|
54523
54700
|
...args.meta ? { meta: args.meta } : {}
|
|
54524
54701
|
});
|
|
54525
54702
|
logger?.info("dispatch.run.received.guest", {
|
|
@@ -54533,6 +54710,7 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54533
54710
|
sourceSessionId: ctx.principal.id,
|
|
54534
54711
|
targetPersona,
|
|
54535
54712
|
prompt: args.prompt,
|
|
54713
|
+
...args.brief ? { brief: args.brief } : {},
|
|
54536
54714
|
guestPrincipalId: ctx.principal.id,
|
|
54537
54715
|
guestDisplayName: ctx.principal.displayName,
|
|
54538
54716
|
// T-31: 把 A 的飞书 union_id 透传给 B(connectGuestContext 已把它挂在 principal.feishuUnionId)
|
|
@@ -54557,6 +54735,7 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54557
54735
|
sourceSessionId,
|
|
54558
54736
|
targetPersona,
|
|
54559
54737
|
taskText: args.prompt,
|
|
54738
|
+
...args.brief ? { taskBrief: args.brief } : {},
|
|
54560
54739
|
...args.meta ? { meta: args.meta } : {}
|
|
54561
54740
|
});
|
|
54562
54741
|
logger?.info("dispatch.run.received", {
|
|
@@ -54570,6 +54749,7 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54570
54749
|
sourceSessionId,
|
|
54571
54750
|
targetPersona,
|
|
54572
54751
|
prompt: args.prompt,
|
|
54752
|
+
...args.brief ? { brief: args.brief } : {},
|
|
54573
54753
|
...args.model ? { model: args.model } : {},
|
|
54574
54754
|
// 一次性 engine override(spec 2026-08-24):只有本机 owner 入口能带(guest 已在上方拒)
|
|
54575
54755
|
...args.tool ? { tool: args.tool } : {},
|
|
@@ -60201,7 +60381,11 @@ function buildSessionHandlers(deps) {
|
|
|
60201
60381
|
deps.getOwnerIdentity().feishuUnionId
|
|
60202
60382
|
)
|
|
60203
60383
|
);
|
|
60204
|
-
const
|
|
60384
|
+
const attribution = formatSenderAttribution(sender);
|
|
60385
|
+
const outbound = attribution ? { ...args, text: `${args.text}
|
|
60386
|
+
|
|
60387
|
+
${attribution}` } : args;
|
|
60388
|
+
const { broadcast } = manager.send(outbound, sender);
|
|
60205
60389
|
return { response: { type: "session:send", ok: true }, broadcast };
|
|
60206
60390
|
};
|
|
60207
60391
|
const currentTurnSender = async (frame, _client, ctx) => {
|
|
@@ -61912,7 +62096,7 @@ function computeMethodAccess(args) {
|
|
|
61912
62096
|
}
|
|
61913
62097
|
|
|
61914
62098
|
// src/version.ts
|
|
61915
|
-
var version = "0.2.
|
|
62099
|
+
var version = "0.2.394".length > 0 ? "0.2.394" : "dev";
|
|
61916
62100
|
|
|
61917
62101
|
// src/cli-probe/probe.ts
|
|
61918
62102
|
var fs66 = __toESM(require("fs"), 1);
|
|
@@ -66647,7 +66831,7 @@ async function startDaemon(config) {
|
|
|
66647
66831
|
return { personaIds: [...ch.memberPersonaIds], deviceIds: [...ch.memberContactDeviceIds] };
|
|
66648
66832
|
},
|
|
66649
66833
|
// 续派(spec 2026-07-21):任务包注入 worker session,复用投递同款注入路径。
|
|
66650
|
-
sendFollowUp: (workerSessionId, text) => manager.injectIntoSession(workerSessionId, text),
|
|
66834
|
+
sendFollowUp: (workerSessionId, text, meta) => manager.injectIntoSession(workerSessionId, text, meta),
|
|
66651
66835
|
logger,
|
|
66652
66836
|
spawnB: async (args) => {
|
|
66653
66837
|
logger.info("dispatch.spawnB.start", {
|
|
@@ -66668,6 +66852,8 @@ async function startDaemon(config) {
|
|
|
66668
66852
|
targetPersona: args.targetPersona,
|
|
66669
66853
|
prompt: args.prompt,
|
|
66670
66854
|
sourceJsonlPath,
|
|
66855
|
+
// 派活方写的 2-3 句摘要 → 任务包信封 <brief>(卡片头常显)
|
|
66856
|
+
...args.brief ? { brief: args.brief } : {},
|
|
66671
66857
|
// B 角色(跨设备):非空 → guest scope + creatorPrincipalId/creatorDisplayName = A。
|
|
66672
66858
|
guestPrincipalId: args.guestPrincipalId,
|
|
66673
66859
|
guestDisplayName: args.guestDisplayName,
|
|
@@ -21450,11 +21450,13 @@ var DispatchOutcomeSchema = external_exports.discriminatedUnion("kind", [
|
|
|
21450
21450
|
external_exports.object({
|
|
21451
21451
|
kind: external_exports.literal("success"),
|
|
21452
21452
|
text: external_exports.string(),
|
|
21453
|
+
brief: external_exports.string().optional(),
|
|
21453
21454
|
filePaths: external_exports.array(external_exports.string()).optional()
|
|
21454
21455
|
}),
|
|
21455
21456
|
external_exports.object({
|
|
21456
21457
|
kind: external_exports.literal("failure"),
|
|
21457
|
-
reason: external_exports.string()
|
|
21458
|
+
reason: external_exports.string(),
|
|
21459
|
+
brief: external_exports.string().optional()
|
|
21458
21460
|
})
|
|
21459
21461
|
]);
|
|
21460
21462
|
var DispatchRunArgsSchema = external_exports.object({
|
|
@@ -21465,6 +21467,9 @@ var DispatchRunArgsSchema = external_exports.object({
|
|
|
21465
21467
|
// 省略 = 新开一件事,daemon 铸新 id。
|
|
21466
21468
|
dispatchId: external_exports.string().min(1).optional(),
|
|
21467
21469
|
prompt: external_exports.string(),
|
|
21470
|
+
// 派活方写的 2-3 句摘要(与 prompt 同源同结构)。落台账 `taskBrief` + 进任务包信封
|
|
21471
|
+
// `<brief>`,worker session 的卡片头常显。optional 同 DispatchOutcome.brief 的理由。
|
|
21472
|
+
brief: external_exports.string().optional(),
|
|
21468
21473
|
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
21469
21474
|
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
21470
21475
|
targetDeviceId: external_exports.string().min(1).optional(),
|
|
@@ -21517,6 +21522,18 @@ var DispatchRecordSchema = external_exports.object({
|
|
|
21517
21522
|
workerSessionId: external_exports.string().min(1).optional(),
|
|
21518
21523
|
/** 任务摘要;截断(≤500 字符)在 daemon store.add 处保证 */
|
|
21519
21524
|
taskText: external_exports.string(),
|
|
21525
|
+
/**
|
|
21526
|
+
* 派活方写的 2-3 句任务摘要(`DispatchRunArgs.brief`)。台账列表 / butler 面板显示它
|
|
21527
|
+
* 而不是被截断到 500 字符的 `taskText` 半截原文。回报侧的 brief 随 `outcome` 已落盘,
|
|
21528
|
+
* 不在这里重复存。
|
|
21529
|
+
*/
|
|
21530
|
+
taskBrief: external_exports.string().optional(),
|
|
21531
|
+
/**
|
|
21532
|
+
* 第几轮:新开 = 1,每次续派 +1。续派**不单开分型**(一件事一行一 id),
|
|
21533
|
+
* 「第 N 轮」这个语义就落在这里,并透进任务包信封的 `round` 属性供卡片头显示。
|
|
21534
|
+
* 老台账行缺省 → 消费方按 1 处理。
|
|
21535
|
+
*/
|
|
21536
|
+
round: external_exports.number().int().positive().optional(),
|
|
21520
21537
|
status: DispatchStatusSchema,
|
|
21521
21538
|
outcome: DispatchOutcomeSchema.optional(),
|
|
21522
21539
|
/** 上层消费者语义(如司礼监的口谕/验收状态),daemon 不解释 */
|
|
@@ -22235,7 +22252,14 @@ var HISTORY_USER_META_VALUES = [
|
|
|
22235
22252
|
"skill-hint",
|
|
22236
22253
|
"meta-text",
|
|
22237
22254
|
"attachment-skills",
|
|
22238
|
-
"attachment-deferred-tools"
|
|
22255
|
+
"attachment-deferred-tools",
|
|
22256
|
+
// persona dispatch 来源分型(信封契约见 dispatch-format.ts):
|
|
22257
|
+
// dispatch-task 派出去的任务包(首发 + 续派,续派靠信封 round 属性区分,不单开分型)
|
|
22258
|
+
// dispatch-result worker 干完回报注入发起方 session 的结果包
|
|
22259
|
+
// 这两类跟其它 meta 的关键差别:**它们是一轮真实交互**,参与 turn 切分与分页计数
|
|
22260
|
+
// (见 isDispatchUserMeta 的消费点),不是 CC 内部注入的辅助消息。
|
|
22261
|
+
"dispatch-task",
|
|
22262
|
+
"dispatch-result"
|
|
22239
22263
|
];
|
|
22240
22264
|
var SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
|
|
22241
22265
|
var AGENT_SOURCE_VALUES = [
|
|
@@ -24007,6 +24031,11 @@ var VisitorRecordSchema = external_exports.object({
|
|
|
24007
24031
|
});
|
|
24008
24032
|
var VisitorListResultSchema = external_exports.object({ visitors: external_exports.array(VisitorRecordSchema) });
|
|
24009
24033
|
|
|
24034
|
+
// ../protocol/src/dispatch-format.ts
|
|
24035
|
+
var INNER_TAG_NAMES = "clawd-dispatch-task|clawd-dispatch-result|brief|detail|files";
|
|
24036
|
+
var INNER_TAG_ESCAPE_RE = new RegExp(`<(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
24037
|
+
var INNER_TAG_UNESCAPE_RE = new RegExp(`<\\\\(\\\\*)(/?)(${INNER_TAG_NAMES})\\b`, "g");
|
|
24038
|
+
|
|
24010
24039
|
// src/tools/claude-history.ts
|
|
24011
24040
|
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
24012
24041
|
var import_node_fs = __toESM(require("fs"), 1);
|
|
@@ -24644,6 +24673,11 @@ function log(msg, info) {
|
|
|
24644
24673
|
} catch {
|
|
24645
24674
|
}
|
|
24646
24675
|
}
|
|
24676
|
+
function BRIEF_DESCRIBE(schema, what) {
|
|
24677
|
+
return schema.describe(
|
|
24678
|
+
`2-3 sentences on ${what}. This is what the user sees **without expanding**; they decide from it whether to read the detail. Mirror the detail's top-level structure: if the brief makes three points, the detail must have the three matching sections in the same order. Do not tell a different story from the detail. Always fill this in.`
|
|
24679
|
+
);
|
|
24680
|
+
}
|
|
24647
24681
|
async function handlePersonaDispatchToolCall(input, ctx) {
|
|
24648
24682
|
const f = ctx.fetch ?? fetch;
|
|
24649
24683
|
log("personaDispatch tool entered", {
|
|
@@ -24681,6 +24715,8 @@ async function handlePersonaDispatchToolCall(input, ctx) {
|
|
|
24681
24715
|
// 续派时可省 targetPersona(daemon 从台账取)
|
|
24682
24716
|
...input.targetPersona ? { targetPersona: input.targetPersona } : {},
|
|
24683
24717
|
prompt: input.prompt,
|
|
24718
|
+
// brief(老板拍板 2026-08-25):进台账 taskBrief + 任务包信封 <brief>
|
|
24719
|
+
...input.brief ? { brief: input.brief } : {},
|
|
24684
24720
|
// 续派(spec 2026-07-21):非空 = 把 prompt 打进该 dispatch 的原 worker session。
|
|
24685
24721
|
...input.dispatchId ? { dispatchId: input.dispatchId } : {},
|
|
24686
24722
|
// 跨设备:非空时透传,daemon run handler 据此走 A 角色转发分支。
|
|
@@ -24801,10 +24837,12 @@ async function handlePersonaDispatchCompleteToolCall(input, ctx) {
|
|
|
24801
24837
|
}
|
|
24802
24838
|
const outcome = input.isFailure ? {
|
|
24803
24839
|
kind: "failure",
|
|
24804
|
-
reason: input.reason ?? "unspecified failure"
|
|
24840
|
+
reason: input.reason ?? "unspecified failure",
|
|
24841
|
+
...input.brief ? { brief: input.brief } : {}
|
|
24805
24842
|
} : {
|
|
24806
24843
|
kind: "success",
|
|
24807
24844
|
text: input.text ?? "",
|
|
24845
|
+
...input.brief ? { brief: input.brief } : {},
|
|
24808
24846
|
filePaths: input.filePaths
|
|
24809
24847
|
};
|
|
24810
24848
|
const url = `${ctx.daemonUrl}/rpc/personaDispatch:complete`;
|
|
@@ -24873,6 +24911,10 @@ async function main() {
|
|
|
24873
24911
|
prompt: external_exports.string().describe(
|
|
24874
24912
|
"the task to perform, with the @persona/<id> token stripped out"
|
|
24875
24913
|
),
|
|
24914
|
+
brief: BRIEF_DESCRIBE(
|
|
24915
|
+
external_exports.string().optional(),
|
|
24916
|
+
"what you are asking for and why it matters"
|
|
24917
|
+
),
|
|
24876
24918
|
targetDeviceId: external_exports.string().optional().describe(
|
|
24877
24919
|
"contact deviceId of the remote device when delegating cross-device (omit for a local persona)"
|
|
24878
24920
|
),
|
|
@@ -24911,6 +24953,10 @@ async function main() {
|
|
|
24911
24953
|
description: "You were dispatched by owner. When you finish the task, call this tool with your result and any relevant file paths. On failure, set isFailure=true and provide a reason. After calling this, your session is done.",
|
|
24912
24954
|
inputSchema: {
|
|
24913
24955
|
text: external_exports.string().optional().describe("your result text (omit on failure)"),
|
|
24956
|
+
brief: BRIEF_DESCRIBE(
|
|
24957
|
+
external_exports.string().optional(),
|
|
24958
|
+
"what happened \u2014 did it go smoothly, did anything break, what's the one thing the reader must know"
|
|
24959
|
+
),
|
|
24914
24960
|
filePaths: external_exports.array(external_exports.string()).optional().describe("absolute paths to files you produced or modified"),
|
|
24915
24961
|
isFailure: external_exports.boolean().optional(),
|
|
24916
24962
|
reason: external_exports.string().optional().describe("failure reason (required when isFailure=true)")
|