@ai-setting/roy-agent-core 1.7.35 → 1.7.37
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/config/index.js +6 -6
- package/dist/env/agent/index.js +7 -7
- package/dist/env/commands/index.js +6 -6
- package/dist/env/context/index.js +2 -2
- package/dist/env/debug/index.js +6 -6
- package/dist/env/event-source/index.js +8 -8
- package/dist/env/hook/index.js +4 -4
- package/dist/env/index.js +21 -21
- package/dist/env/llm/index.js +6 -6
- package/dist/env/log-trace/index.js +6 -6
- package/dist/env/mcp/index.js +6 -6
- package/dist/env/memory/index.js +6 -6
- package/dist/env/plugin/index.js +6 -6
- package/dist/env/prompt/index.js +6 -6
- package/dist/env/session/index.js +6 -6
- package/dist/env/skill/index.js +6 -6
- package/dist/env/task/delegate/index.js +4 -4
- package/dist/env/task/index.js +8 -8
- package/dist/env/task/plugins/index.js +3 -3
- package/dist/env/task/tools/index.js +2 -2
- package/dist/env/tool/index.js +6 -6
- package/dist/env/workflow/engine/index.js +5 -5
- package/dist/env/workflow/index.js +10 -10
- package/dist/env/workflow/tools/index.js +7 -7
- package/dist/index.js +28 -28
- package/dist/shared/@ai-setting/{roy-agent-core-krmhhje6.js → roy-agent-core-1btakphh.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-2aq5f4e1.js → roy-agent-core-1nvqn17p.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-dz3m7dt4.js → roy-agent-core-1q6gjxba.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-zma7p5p7.js → roy-agent-core-1vj7dd14.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-z7q1re07.js → roy-agent-core-2qke91fm.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-j6h99erf.js → roy-agent-core-2wbdfrtg.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-t2vwy92b.js → roy-agent-core-462v5d24.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-821bsh3r.js → roy-agent-core-88tfzaxg.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-0czz1ynz.js → roy-agent-core-a8zf7ts4.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-bny3nd8q.js → roy-agent-core-bb57xjfh.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-1dacps3n.js → roy-agent-core-dfay0w56.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-gcnvcbft.js → roy-agent-core-e4v61k3j.js} +24 -2
- package/dist/shared/@ai-setting/{roy-agent-core-242peyss.js → roy-agent-core-em8618g6.js} +88 -45
- package/dist/shared/@ai-setting/{roy-agent-core-743510fc.js → roy-agent-core-fym6zz5a.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-anwh7050.js → roy-agent-core-fytqnxrd.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-62c1t7wr.js → roy-agent-core-m7dppx2p.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-axh3vn8k.js → roy-agent-core-mdaew65f.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-3x6ej9vm.js → roy-agent-core-mwaesrpc.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-2adayzfa.js → roy-agent-core-mxwaq8ey.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-jxgprc5a.js → roy-agent-core-n82acszf.js} +2 -1
- package/dist/shared/@ai-setting/{roy-agent-core-52yt7e1t.js → roy-agent-core-pxyyrxnn.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-hs75rxp3.js → roy-agent-core-q8vew3zh.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-zfcwa3w7.js → roy-agent-core-qhtejtpc.js} +27 -5
- package/dist/shared/@ai-setting/{roy-agent-core-6thjwx6v.js → roy-agent-core-rx8whb18.js} +112 -1
- package/dist/shared/@ai-setting/{roy-agent-core-xgarc0t2.js → roy-agent-core-s53yya0w.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-n094tbjh.js → roy-agent-core-w457586k.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-1kcstbn3.js → roy-agent-core-whta3f53.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-63nkhqa4.js → roy-agent-core-x4wev4rn.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-h1zamsb9.js → roy-agent-core-zekkw27m.js} +3 -3
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
TaskTagPlugin,
|
|
3
3
|
createLarkCliTaskNotifyHook,
|
|
4
4
|
createPerTaskGroupChatPlugin
|
|
5
|
-
} from "./roy-agent-core-
|
|
5
|
+
} from "./roy-agent-core-e4v61k3j.js";
|
|
6
6
|
import {
|
|
7
7
|
normalizeLarkAtMentions
|
|
8
8
|
} from "./roy-agent-core-rmn29nrh.js";
|
|
@@ -11,18 +11,18 @@ import {
|
|
|
11
11
|
} from "./roy-agent-core-7hh0brvs.js";
|
|
12
12
|
import {
|
|
13
13
|
BaseComponent
|
|
14
|
-
} from "./roy-agent-core-
|
|
14
|
+
} from "./roy-agent-core-m7dppx2p.js";
|
|
15
15
|
import {
|
|
16
16
|
globalHookManager,
|
|
17
17
|
init_global_hook_manager
|
|
18
|
-
} from "./roy-agent-core-
|
|
18
|
+
} from "./roy-agent-core-fym6zz5a.js";
|
|
19
19
|
import {
|
|
20
20
|
init_context
|
|
21
|
-
} from "./roy-agent-core-
|
|
21
|
+
} from "./roy-agent-core-whta3f53.js";
|
|
22
22
|
import {
|
|
23
23
|
createEnvContext,
|
|
24
24
|
runWithEnvContext
|
|
25
|
-
} from "./roy-agent-core-
|
|
25
|
+
} from "./roy-agent-core-n82acszf.js";
|
|
26
26
|
import {
|
|
27
27
|
TracedAs,
|
|
28
28
|
init_decorator
|
|
@@ -832,6 +832,9 @@ var bountyCliHandler = {
|
|
|
832
832
|
// src/env/event-source/event-source-handlers.ts
|
|
833
833
|
init_logger();
|
|
834
834
|
var logger = createLogger("lark-cli:event-source");
|
|
835
|
+
function isPluginDebugEnabled() {
|
|
836
|
+
return process.env.ROY_TASK_NOTIFY_DEBUG === "1" || process.env.ROY_TRACE_DEBUG === "1";
|
|
837
|
+
}
|
|
835
838
|
var BUILT_IN_PLUGIN_FACTORIES = {
|
|
836
839
|
LarkCliTaskNotifyPlugin: (cfg) => createLarkCliTaskNotifyHook(cfg),
|
|
837
840
|
PerTaskGroupChatPlugin: (cfg) => createPerTaskGroupChatPlugin(cfg),
|
|
@@ -864,55 +867,49 @@ function buildLarkRecommendedAction(opts) {
|
|
|
864
867
|
const profileFlag = profile ? `--profile ${profile} ` : "";
|
|
865
868
|
const profileWarn = profile ? `(⚠️ 必须用 profile="${profile}" 调 lark-cli;openId per-app 隔离,换 profile 会失败)` : "";
|
|
866
869
|
const isGroup = chatType === "group";
|
|
867
|
-
const scopeHint = isGroup ? `群聊消息;回复到 replyTo.chatId。如需
|
|
870
|
+
const scopeHint = isGroup ? `群聊消息;回复到 replyTo.chatId。如需 @发件人,用结构化 at 节点 {"tag":"at","user_id":"<senderId>"}(不要写 <at> 文本标签)` : "p2p 私聊消息;回复到 replyTo.chatId";
|
|
868
871
|
const scopeWord = isGroup ? "群聊" : "p2p 私聊";
|
|
869
872
|
const action = [
|
|
870
873
|
`处理飞书 ${scopeWord}消息并以机器人身份回复${profileWarn}。`,
|
|
871
874
|
`scope: ${scopeHint}。`,
|
|
872
875
|
``,
|
|
873
|
-
`## ⭐ 关键 1:
|
|
874
|
-
`lark-cli
|
|
875
|
-
|
|
876
|
-
`一堆 raw 符号, 完全没法用。`,
|
|
877
|
-
`正确做法: 调 im +messages-{send,reply} 时必须显式加 --markdown <content>,`,
|
|
878
|
-
`飞书才会按 Markdown 渲染 rich format。`,
|
|
879
|
-
`**严禁**: 使用 --text flag (直接导致 rich format 失效, 是最常见的回归路径)`,
|
|
880
|
-
` 使用 --msg-type text (同理, --msg-type post 也可以但需对应结构,`,
|
|
881
|
-
` 最稳的仍然是 --markdown flag)`,
|
|
882
|
-
` 不加任何 content flag (会按 plain text 默认值处理)`,
|
|
883
|
-
``,
|
|
884
|
-
`## ⭐ 关键 2: @-mention 必须用空闭合标签 <at user_id="ou_xxx"></at>`,
|
|
885
|
-
`飞书只识别空闭合形式: <at user_id="ou_xxx"></at> (开始标签 + 结束标签, 中间为空)。`,
|
|
886
|
-
`自闭合形式 <at user_id="ou_xxx"/> 飞书不解析, 用户会看到原始 <at> 标签字面字符,`,
|
|
887
|
-
`跟 plain text 一样坏掉 — mention 完全失效。`,
|
|
876
|
+
`## ⭐ 关键 1: 飞书回复必须用结构化 post content(--msg-type post --content)`,
|
|
877
|
+
`lark-cli 默认把消息当 plain text;而 @mention 只有在**结构化 at 节点**里才会被`,
|
|
878
|
+
`飞书识别为真实 @。所以回复统一走 post 的 --content JSON:`,
|
|
888
879
|
``,
|
|
889
|
-
|
|
890
|
-
`
|
|
880
|
+
` {"zh_cn":{"content":[`,
|
|
881
|
+
` [ {"tag":"at","user_id":"ou_xxx"} ], // @某人:结构化节点(可多个/多段)`,
|
|
882
|
+
` [ {"tag":"md","text":"正文 Markdown(标题/表格/加粗都支持)"} ] // 正文:单个 md 节点`,
|
|
883
|
+
` ]}}`,
|
|
891
884
|
``,
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
885
|
+
`- @mention:用 {"tag":"at","user_id":"ou_xxx"}(user_id 填对方 open_id;@所有人填 "all")`,
|
|
886
|
+
`- 正文:全部放进 {"tag":"md","text":"..."} 这一个节点里`,
|
|
887
|
+
`- 不需要 @ 时,content 里只放 md 节点:{"zh_cn":{"content":[[{"tag":"md","text":"..."}]]}}`,
|
|
888
|
+
`**严禁**: 用 --text(plain text,Markdown 全部失效)`,
|
|
889
|
+
` 用 --markdown(无法携带结构化 at 节点,@ 会退化成普通文本)`,
|
|
890
|
+
` 在正文里写 <at user_id="ou_xxx"/> 或 <at user_id="ou_xxx"></at> 文本标签`,
|
|
891
|
+
` (飞书不识别文本标签,只认结构化 at 节点;写文本标签会显示成原始字符)`,
|
|
895
892
|
``,
|
|
896
|
-
`##
|
|
897
|
-
|
|
898
|
-
`原因:agent 工具调用层不做 shell 展开。`,
|
|
893
|
+
`## 关键 2: 安全构造 content(照抄,避免 JSON 转义地狱)`,
|
|
894
|
+
`把 Markdown 正文写进临时文件,再用 jq 组装(jq 会自动把换行转义为反斜杠+n):`,
|
|
899
895
|
``,
|
|
900
|
-
|
|
901
|
-
`
|
|
902
|
-
`
|
|
903
|
-
`
|
|
904
|
-
` ...(这里是回复的 Markdown 内容,可以多行 / 含特殊字符)`,
|
|
896
|
+
` body_file="$(mktemp /tmp/lark-reply.XXXXXX.md)"`,
|
|
897
|
+
` trap 'rm -f "$body_file"' EXIT`,
|
|
898
|
+
` cat > "$body_file" <<'LARK_REPLY_EOF'`,
|
|
899
|
+
` ...(回复的 Markdown 正文,可多行 / 含表格 / 含特殊字符;不要写 <at> 标签)`,
|
|
905
900
|
` LARK_REPLY_EOF`,
|
|
906
|
-
`
|
|
901
|
+
` content="$(jq -nc --rawfile md "$body_file" --arg uid "<senderId>" '{zh_cn:{content:[[{tag:"at",user_id:$uid}],[{tag:"md",text:$md}]]}}')"`,
|
|
902
|
+
` lark-cli ${profileFlag}im +messages-reply --message-id <取自 replyTo.messageId> --as bot --msg-type post --content "$content"`,
|
|
907
903
|
``,
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
904
|
+
`不需要 @ 某人时,把 jq 表达式换成 '{zh_cn:{content:[[{tag:"md",text:$md}]]}}'。`,
|
|
905
|
+
``,
|
|
906
|
+
`## 禁止`,
|
|
907
|
+
`- 禁止 --text / --msg-type text(plain text,Markdown 全部失效)`,
|
|
908
|
+
`- 禁止 --markdown(无法携带结构化 at 节点)`,
|
|
909
|
+
`- 禁止在正文里写 <at user_id=".."/> 或 <at user_id=".."></at> 文本标签`,
|
|
910
|
+
`- 禁止把多行 Markdown 直接拼进 --content 参数(必须走上面的 jq --rawfile)`,
|
|
911
911
|
`- 禁止字面反斜杠+n(即 \\n 两个字符,不是 0x0A 控制字符)`,
|
|
912
|
-
`- 禁止
|
|
913
|
-
`- 禁止 at-file 形式传 Markdown(--markdown 后接 @ 符号加文件名的写法)`,
|
|
914
|
-
`- 禁止 --text flag(让 lark-cli 把消息当 plain text, rich format 全部失效 — 见顶部说明)`,
|
|
915
|
-
`- 禁止 --msg-type text(同理, --msg-type post 可选但需对应结构, 仍不如 --markdown flag 稳)`,
|
|
912
|
+
`- 禁止 bash ANSI-C 引号语法(dollar 符号紧跟单引号)`,
|
|
916
913
|
``,
|
|
917
914
|
`## 必须使用 replyTo 里给定的值`,
|
|
918
915
|
`profile / chatId / messageId / --as bot 必须原样取自 recommendedAction.replyTo;不要凭印象自己拼接。`
|
|
@@ -1154,6 +1151,7 @@ class LarkCliInstance {
|
|
|
1154
1151
|
registerPluginHooks(plugin) {
|
|
1155
1152
|
const pluginName = plugin.name || "unknown";
|
|
1156
1153
|
this.injectTaskUpdater(plugin);
|
|
1154
|
+
this.injectSessionComponent(plugin);
|
|
1157
1155
|
if (typeof plugin.init === "function") {
|
|
1158
1156
|
const pluginEnv = {
|
|
1159
1157
|
getComponent: () => null,
|
|
@@ -1239,6 +1237,48 @@ class LarkCliInstance {
|
|
|
1239
1237
|
};
|
|
1240
1238
|
plugin.setTaskUpdater(taskUpdater);
|
|
1241
1239
|
}
|
|
1240
|
+
injectSessionComponent(plugin) {
|
|
1241
|
+
if (typeof plugin.setSessionComponent !== "function") {
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
if (typeof plugin.hasSessionComponent === "function" && plugin.hasSessionComponent()) {
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
if (!this.environment?.getComponent) {
|
|
1248
|
+
if (isPluginDebugEnabled()) {
|
|
1249
|
+
console.debug(`[LarkCliInstance] ${plugin.name || "plugin"} has setSessionComponent but ` + `environment not injected (setEnvironment not called). ` + `chat↔task 绑定将不会写入。`);
|
|
1250
|
+
}
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const sessionComponent = this.environment.getComponent("session");
|
|
1254
|
+
if (!sessionComponent?.upsertChatTaskBinding) {
|
|
1255
|
+
if (isPluginDebugEnabled()) {
|
|
1256
|
+
console.debug(`[LarkCliInstance] ${plugin.name || "plugin"} has setSessionComponent but ` + `sessionComponent or upsertChatTaskBinding not found via env.getComponent('session'). ` + `chat↔task 绑定将不会写入。`);
|
|
1257
|
+
}
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
plugin.setSessionComponent(sessionComponent);
|
|
1261
|
+
if (isPluginDebugEnabled()) {
|
|
1262
|
+
console.debug(`[LarkCliInstance] SessionComponent injected for plugin ${plugin.name || "unknown"} ` + `(sourceId=${this.config.id})`);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
async resolveChatTaskBinding(chatId) {
|
|
1266
|
+
if (!chatId)
|
|
1267
|
+
return null;
|
|
1268
|
+
const sessionComponent = this.environment?.getComponent?.("session");
|
|
1269
|
+
if (!sessionComponent?.getChatTaskBinding)
|
|
1270
|
+
return null;
|
|
1271
|
+
try {
|
|
1272
|
+
const binding = await sessionComponent.getChatTaskBinding(chatId);
|
|
1273
|
+
if (binding && binding.status === "ready" && typeof binding.taskId === "number" && binding.taskId > 0) {
|
|
1274
|
+
return binding.taskId;
|
|
1275
|
+
}
|
|
1276
|
+
return null;
|
|
1277
|
+
} catch (err) {
|
|
1278
|
+
logger.warn(`[LarkCliInstance] resolveChatTaskBinding failed for chatId=${chatId}: ${err}. ` + `群消息将不会注入 parentTaskId。`);
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1242
1282
|
unloadPlugins() {
|
|
1243
1283
|
for (const plugin of this.loadedPlugins) {
|
|
1244
1284
|
for (const hook of plugin.hooks) {
|
|
@@ -1258,7 +1298,7 @@ class LarkCliInstance {
|
|
|
1258
1298
|
}
|
|
1259
1299
|
}
|
|
1260
1300
|
}
|
|
1261
|
-
handleEvent(rawData) {
|
|
1301
|
+
async handleEvent(rawData) {
|
|
1262
1302
|
let dedupKey;
|
|
1263
1303
|
try {
|
|
1264
1304
|
const parsed = JSON.parse(rawData);
|
|
@@ -1325,6 +1365,7 @@ class LarkCliInstance {
|
|
|
1325
1365
|
eventSourceId: this.config.id
|
|
1326
1366
|
};
|
|
1327
1367
|
const { metadata, replyChannel, recommendedAction } = extractMetadata(enrichedEvent, eventType);
|
|
1368
|
+
const parentTaskId = await this.resolveChatTaskBinding(metadata?.chatId);
|
|
1328
1369
|
const message = JSON.stringify({
|
|
1329
1370
|
rawData,
|
|
1330
1371
|
recommendedAction
|
|
@@ -1347,7 +1388,8 @@ class LarkCliInstance {
|
|
|
1347
1388
|
plugins,
|
|
1348
1389
|
pluginEnabled,
|
|
1349
1390
|
replyChannel,
|
|
1350
|
-
agent
|
|
1391
|
+
agent,
|
|
1392
|
+
parentTaskId: parentTaskId ?? undefined
|
|
1351
1393
|
},
|
|
1352
1394
|
payload: {
|
|
1353
1395
|
sourceId: this.config.id,
|
|
@@ -1357,7 +1399,8 @@ class LarkCliInstance {
|
|
|
1357
1399
|
metadata,
|
|
1358
1400
|
replyChannel,
|
|
1359
1401
|
recommendedAction,
|
|
1360
|
-
timestamp
|
|
1402
|
+
timestamp,
|
|
1403
|
+
parentTaskId: parentTaskId ?? undefined
|
|
1361
1404
|
}
|
|
1362
1405
|
};
|
|
1363
1406
|
const userId = this.extractUserId(rawEvent);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
init_context
|
|
3
|
-
} from "./roy-agent-core-
|
|
3
|
+
} from "./roy-agent-core-whta3f53.js";
|
|
4
4
|
import {
|
|
5
5
|
getEnvContext
|
|
6
|
-
} from "./roy-agent-core-
|
|
6
|
+
} from "./roy-agent-core-n82acszf.js";
|
|
7
7
|
import {
|
|
8
8
|
__esm
|
|
9
9
|
} from "./roy-agent-core-fs0mn2jk.js";
|
|
@@ -19,12 +19,12 @@ import {
|
|
|
19
19
|
} from "./roy-agent-core-7hh0brvs.js";
|
|
20
20
|
import {
|
|
21
21
|
BaseComponent
|
|
22
|
-
} from "./roy-agent-core-
|
|
22
|
+
} from "./roy-agent-core-m7dppx2p.js";
|
|
23
23
|
import {
|
|
24
24
|
LLMHookPoints,
|
|
25
25
|
globalHookManager,
|
|
26
26
|
init_global_hook_manager
|
|
27
|
-
} from "./roy-agent-core-
|
|
27
|
+
} from "./roy-agent-core-fym6zz5a.js";
|
|
28
28
|
import {
|
|
29
29
|
TracedAs,
|
|
30
30
|
init_decorator,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createHook
|
|
3
|
-
} from "./roy-agent-core-
|
|
3
|
+
} from "./roy-agent-core-w457586k.js";
|
|
4
4
|
import {
|
|
5
5
|
HookManager
|
|
6
|
-
} from "./roy-agent-core-
|
|
6
|
+
} from "./roy-agent-core-fym6zz5a.js";
|
|
7
7
|
|
|
8
8
|
// src/env/component.ts
|
|
9
9
|
class BaseComponent {
|
|
@@ -11,16 +11,16 @@ import {
|
|
|
11
11
|
} from "./roy-agent-core-7hh0brvs.js";
|
|
12
12
|
import {
|
|
13
13
|
BaseComponent
|
|
14
|
-
} from "./roy-agent-core-
|
|
14
|
+
} from "./roy-agent-core-m7dppx2p.js";
|
|
15
15
|
import {
|
|
16
16
|
ToolHookPoints,
|
|
17
17
|
globalHookManager,
|
|
18
18
|
init_global_hook_manager
|
|
19
|
-
} from "./roy-agent-core-
|
|
19
|
+
} from "./roy-agent-core-fym6zz5a.js";
|
|
20
20
|
import {
|
|
21
21
|
getCurrentTaskId,
|
|
22
22
|
init_env_context
|
|
23
|
-
} from "./roy-agent-core-
|
|
23
|
+
} from "./roy-agent-core-n82acszf.js";
|
|
24
24
|
import {
|
|
25
25
|
TracedAs,
|
|
26
26
|
init_decorator
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
createWorkflowSearchTool,
|
|
14
14
|
createWorkflowTagListTool,
|
|
15
15
|
createWorkflowValidateTool
|
|
16
|
-
} from "./roy-agent-core-
|
|
16
|
+
} from "./roy-agent-core-pxyyrxnn.js";
|
|
17
17
|
import {
|
|
18
18
|
WorkflowService
|
|
19
19
|
} from "./roy-agent-core-j9ejsmsj.js";
|
|
@@ -21,10 +21,10 @@ import {
|
|
|
21
21
|
WorkflowEngine,
|
|
22
22
|
exports_engine,
|
|
23
23
|
init_engine
|
|
24
|
-
} from "./roy-agent-core-
|
|
24
|
+
} from "./roy-agent-core-x4wev4rn.js";
|
|
25
25
|
import {
|
|
26
26
|
BaseComponent
|
|
27
|
-
} from "./roy-agent-core-
|
|
27
|
+
} from "./roy-agent-core-m7dppx2p.js";
|
|
28
28
|
import {
|
|
29
29
|
createLogger,
|
|
30
30
|
init_logger
|
|
@@ -141,7 +141,7 @@ class WorkflowComponent extends BaseComponent {
|
|
|
141
141
|
if (!agentRunner && this._workflowEnv) {
|
|
142
142
|
const agentComponent = this._workflowEnv.getComponent("agent");
|
|
143
143
|
if (agentComponent) {
|
|
144
|
-
const { AgentComponentAdapter } = await import("./roy-agent-core-
|
|
144
|
+
const { AgentComponentAdapter } = await import("./roy-agent-core-s53yya0w.js");
|
|
145
145
|
agentRunner = new AgentComponentAdapter(agentComponent, {}, this.sessionComponent);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -141,7 +141,8 @@ function createEnvContext(options) {
|
|
|
141
141
|
replyChannel,
|
|
142
142
|
pluginEnabled: options.pluginEnabled,
|
|
143
143
|
plugins: options.plugins,
|
|
144
|
-
timestamp: options.timestamp ?? Date.now()
|
|
144
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
145
|
+
parentTaskId: options.parentTaskId
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
148
|
function mergeEnvContext(partial) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
getEnvContextOrEmpty,
|
|
2
3
|
init_env_context,
|
|
3
4
|
setCurrentTaskId
|
|
4
|
-
} from "./roy-agent-core-
|
|
5
|
+
} from "./roy-agent-core-n82acszf.js";
|
|
5
6
|
import {
|
|
6
7
|
createLogger,
|
|
7
8
|
init_logger
|
|
@@ -333,6 +334,25 @@ function createTaskTool(taskComponent) {
|
|
|
333
334
|
rather than rejected, to preserve backward compatibility. The
|
|
334
335
|
auto-injection of \`created_at\` / \`worktree_path\` is best-effort.
|
|
335
336
|
|
|
337
|
+
## Task Binding Inheritance (Task #4023)
|
|
338
|
+
|
|
339
|
+
When this tool is called from inside a per-task group chat, the
|
|
340
|
+
event-source handler resolves the chat↔task binding and injects the
|
|
341
|
+
bound task id into \`EnvContext.parentTaskId\`. This tool reads that
|
|
342
|
+
value and uses it as the default \`parent_task_id\`, so the LLM
|
|
343
|
+
doesn't need to know the task tree to attach subtasks to the
|
|
344
|
+
correct parent.
|
|
345
|
+
|
|
346
|
+
Priority order (highest → lowest):
|
|
347
|
+
1. Caller's explicit \`parent_task_id\` (always wins)
|
|
348
|
+
2. \`EnvContext.parentTaskId\` injected from chat binding
|
|
349
|
+
3. No parent (creates a root task, as before)
|
|
350
|
+
|
|
351
|
+
When the env-injected parent doesn't exist in the DB, the tool
|
|
352
|
+
fails fast (does not silently create an orphan). When the
|
|
353
|
+
env-injected value is 0 / negative / non-integer, it's treated as
|
|
354
|
+
missing — only positive integers are honored.
|
|
355
|
+
|
|
336
356
|
`,
|
|
337
357
|
parameters: CreateTaskToolSchema,
|
|
338
358
|
execute: async (args, ctx) => {
|
|
@@ -340,12 +360,14 @@ function createTaskTool(taskComponent) {
|
|
|
340
360
|
const sessionId = ctx.session_id || "unknown";
|
|
341
361
|
const detectedWorktree = detectWorktree();
|
|
342
362
|
let enrichedContext = params.context;
|
|
363
|
+
const envParentTaskId = getEnvContextOrEmpty().parentTaskId;
|
|
364
|
+
const effectiveParentTaskId = params.parent_task_id !== undefined && params.parent_task_id !== null ? params.parent_task_id : envParentTaskId !== undefined && envParentTaskId !== null && Number.isInteger(envParentTaskId) && envParentTaskId > 0 ? envParentTaskId : undefined;
|
|
343
365
|
let inheritedProjectPath = params.project_path && params.project_path.trim() !== "" ? params.project_path : undefined;
|
|
344
366
|
let inheritedTags = params.tags;
|
|
345
367
|
let inheritedContext;
|
|
346
|
-
if (
|
|
368
|
+
if (effectiveParentTaskId !== undefined) {
|
|
347
369
|
try {
|
|
348
|
-
const parent = await taskComponent.getTask(
|
|
370
|
+
const parent = await taskComponent.getTask(effectiveParentTaskId);
|
|
349
371
|
if (parent) {
|
|
350
372
|
const inherited = inheritChildContext({
|
|
351
373
|
parent: {
|
|
@@ -370,7 +392,7 @@ function createTaskTool(taskComponent) {
|
|
|
370
392
|
inheritedContext = inherited.context;
|
|
371
393
|
}
|
|
372
394
|
} catch (err) {
|
|
373
|
-
logger2.debug(`[task_create] failed to pre-load parent #${
|
|
395
|
+
logger2.debug(`[task_create] failed to pre-load parent #${effectiveParentTaskId} for context inheritance: ${err instanceof Error ? err.message : String(err)}`);
|
|
374
396
|
}
|
|
375
397
|
}
|
|
376
398
|
try {
|
|
@@ -399,7 +421,7 @@ function createTaskTool(taskComponent) {
|
|
|
399
421
|
}
|
|
400
422
|
try {
|
|
401
423
|
const task = await taskComponent.createTask({
|
|
402
|
-
parent_task_id:
|
|
424
|
+
parent_task_id: effectiveParentTaskId,
|
|
403
425
|
title: params.title,
|
|
404
426
|
description: params.description,
|
|
405
427
|
priority: params.priority,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./roy-agent-core-7hh0brvs.js";
|
|
13
13
|
import {
|
|
14
14
|
BaseComponent
|
|
15
|
-
} from "./roy-agent-core-
|
|
15
|
+
} from "./roy-agent-core-m7dppx2p.js";
|
|
16
16
|
import {
|
|
17
17
|
TracedAs,
|
|
18
18
|
init_decorator
|
|
@@ -334,6 +334,103 @@ class SessionComponent extends BaseComponent {
|
|
|
334
334
|
}
|
|
335
335
|
return success ?? false;
|
|
336
336
|
}
|
|
337
|
+
chatBindingCache = new Map;
|
|
338
|
+
static CHAT_BINDING_CACHE_TTL_MS = 60000;
|
|
339
|
+
static CHAT_BINDING_CACHE_MAX = 1000;
|
|
340
|
+
async upsertChatTaskBinding(opts) {
|
|
341
|
+
if (!opts.chatId || typeof opts.chatId !== "string") {
|
|
342
|
+
throw new Error("upsertChatTaskBinding: chatId is required (non-empty string)");
|
|
343
|
+
}
|
|
344
|
+
if (typeof opts.taskId !== "number" || !Number.isInteger(opts.taskId) || opts.taskId <= 0) {
|
|
345
|
+
throw new Error(`upsertChatTaskBinding: taskId must be a positive integer, got ${JSON.stringify(opts.taskId)}`);
|
|
346
|
+
}
|
|
347
|
+
const now = new Date().toISOString();
|
|
348
|
+
const desiredStatus = opts.status ?? "ready";
|
|
349
|
+
const existing = await this.getChatTaskBinding(opts.chatId);
|
|
350
|
+
let rebindCount = existing?.rebindCount ?? 0;
|
|
351
|
+
let resolvedTaskId = opts.taskId;
|
|
352
|
+
if (existing && existing.taskId !== opts.taskId) {
|
|
353
|
+
rebindCount += 1;
|
|
354
|
+
resolvedTaskId = existing.taskId;
|
|
355
|
+
logger.warn(`[SessionComponent] upsertChatTaskBinding: rebind detected for chatId=${opts.chatId}: ` + `existing taskId=${existing.taskId}, requested taskId=${opts.taskId}; ` + `keeping existing. rebindCount=${rebindCount}`);
|
|
356
|
+
}
|
|
357
|
+
const binding = {
|
|
358
|
+
chatId: opts.chatId,
|
|
359
|
+
taskId: resolvedTaskId,
|
|
360
|
+
profile: opts.profile,
|
|
361
|
+
boundAt: now,
|
|
362
|
+
status: desiredStatus,
|
|
363
|
+
errorMessage: opts.errorMessage ?? null,
|
|
364
|
+
rebindCount
|
|
365
|
+
};
|
|
366
|
+
const session = await this.get(opts.chatId);
|
|
367
|
+
if (session) {
|
|
368
|
+
const mergedMetadata = {
|
|
369
|
+
...session.metadata ?? {},
|
|
370
|
+
larkChat: binding
|
|
371
|
+
};
|
|
372
|
+
await this.update(opts.chatId, { metadata: mergedMetadata });
|
|
373
|
+
} else {
|
|
374
|
+
const newMetadata = {
|
|
375
|
+
larkChat: binding
|
|
376
|
+
};
|
|
377
|
+
await this.create({
|
|
378
|
+
id: opts.chatId,
|
|
379
|
+
title: `lark-chat:${opts.chatId}`,
|
|
380
|
+
directory: ".",
|
|
381
|
+
metadata: newMetadata
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
this.chatBindingCache.set(opts.chatId, {
|
|
385
|
+
binding,
|
|
386
|
+
cachedAt: Date.now()
|
|
387
|
+
});
|
|
388
|
+
this.evictStaleChatBindingCache();
|
|
389
|
+
logger.info(`[SessionComponent] upsertChatTaskBinding: chatId=${opts.chatId} → taskId=${resolvedTaskId} ` + `status=${binding.status} rebindCount=${rebindCount}`);
|
|
390
|
+
return binding;
|
|
391
|
+
}
|
|
392
|
+
async getChatTaskBinding(chatId) {
|
|
393
|
+
if (!chatId)
|
|
394
|
+
return null;
|
|
395
|
+
const cached = this.chatBindingCache.get(chatId);
|
|
396
|
+
if (cached) {
|
|
397
|
+
const age = Date.now() - cached.cachedAt;
|
|
398
|
+
if (age < SessionComponent.CHAT_BINDING_CACHE_TTL_MS) {
|
|
399
|
+
return cached.binding;
|
|
400
|
+
}
|
|
401
|
+
this.chatBindingCache.delete(chatId);
|
|
402
|
+
}
|
|
403
|
+
const session = await this.get(chatId);
|
|
404
|
+
if (!session) {
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
const binding = session.metadata?.larkChat;
|
|
408
|
+
if (!binding || typeof binding !== "object") {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
this.chatBindingCache.set(chatId, {
|
|
412
|
+
binding,
|
|
413
|
+
cachedAt: Date.now()
|
|
414
|
+
});
|
|
415
|
+
this.evictStaleChatBindingCache();
|
|
416
|
+
return binding;
|
|
417
|
+
}
|
|
418
|
+
evictStaleChatBindingCache() {
|
|
419
|
+
if (this.chatBindingCache.size <= SessionComponent.CHAT_BINDING_CACHE_MAX)
|
|
420
|
+
return;
|
|
421
|
+
const now = Date.now();
|
|
422
|
+
for (const [k, v] of this.chatBindingCache) {
|
|
423
|
+
if (now - v.cachedAt >= SessionComponent.CHAT_BINDING_CACHE_TTL_MS) {
|
|
424
|
+
this.chatBindingCache.delete(k);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
while (this.chatBindingCache.size > SessionComponent.CHAT_BINDING_CACHE_MAX) {
|
|
428
|
+
const firstKey = this.chatBindingCache.keys().next().value;
|
|
429
|
+
if (!firstKey)
|
|
430
|
+
break;
|
|
431
|
+
this.chatBindingCache.delete(firstKey);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
337
434
|
getActiveSession() {
|
|
338
435
|
if (!this.activeSessionId)
|
|
339
436
|
return;
|
|
@@ -858,6 +955,20 @@ class SessionComponent extends BaseComponent {
|
|
|
858
955
|
};
|
|
859
956
|
}
|
|
860
957
|
}
|
|
958
|
+
__legacyDecorateClassTS([
|
|
959
|
+
TracedAs("session.upsertChatTaskBinding", {
|
|
960
|
+
recordParams: false,
|
|
961
|
+
recordResult: false,
|
|
962
|
+
log: true
|
|
963
|
+
})
|
|
964
|
+
], SessionComponent.prototype, "upsertChatTaskBinding", null);
|
|
965
|
+
__legacyDecorateClassTS([
|
|
966
|
+
TracedAs("session.getChatTaskBinding", {
|
|
967
|
+
recordParams: false,
|
|
968
|
+
recordResult: false,
|
|
969
|
+
log: false
|
|
970
|
+
})
|
|
971
|
+
], SessionComponent.prototype, "getChatTaskBinding", null);
|
|
861
972
|
__legacyDecorateClassTS([
|
|
862
973
|
TracedAs("session.generateCompactHint")
|
|
863
974
|
], SessionComponent.prototype, "generateCompactHint", null);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentComponentAdapter,
|
|
3
3
|
init_agent_component_adapter
|
|
4
|
-
} from "./roy-agent-core-
|
|
4
|
+
} from "./roy-agent-core-q8vew3zh.js";
|
|
5
5
|
import"./roy-agent-core-1db4vpc6.js";
|
|
6
6
|
import"./roy-agent-core-e25xkv53.js";
|
|
7
|
-
import"./roy-agent-core-
|
|
8
|
-
import"./roy-agent-core-
|
|
9
|
-
import"./roy-agent-core-
|
|
7
|
+
import"./roy-agent-core-fym6zz5a.js";
|
|
8
|
+
import"./roy-agent-core-whta3f53.js";
|
|
9
|
+
import"./roy-agent-core-n82acszf.js";
|
|
10
10
|
import"./roy-agent-core-qhjm0bxm.js";
|
|
11
11
|
import"./roy-agent-core-8seq65bp.js";
|
|
12
12
|
import"./roy-agent-core-jnszp0jq.js";
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
globalHookManager,
|
|
19
19
|
init_global_hook_manager
|
|
20
|
-
} from "./roy-agent-core-
|
|
20
|
+
} from "./roy-agent-core-fym6zz5a.js";
|
|
21
21
|
import {
|
|
22
22
|
init_context
|
|
23
|
-
} from "./roy-agent-core-
|
|
23
|
+
} from "./roy-agent-core-whta3f53.js";
|
|
24
24
|
import {
|
|
25
25
|
getCurrentTaskId,
|
|
26
26
|
getEnvContext
|
|
27
|
-
} from "./roy-agent-core-
|
|
27
|
+
} from "./roy-agent-core-n82acszf.js";
|
|
28
28
|
import {
|
|
29
29
|
TracedAs,
|
|
30
30
|
init_decorator,
|