@ai-setting/roy-agent-core 1.7.72 → 1.7.75
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/env/agent/agent-component.js +6 -6
- package/dist/env/agent/agent-registry.d.ts +4 -1
- package/dist/env/agent/index.js +6 -6
- package/dist/env/error-reply.d.ts +46 -0
- package/dist/env/error-reply.js +3 -1
- package/dist/env/event-source/event-source-handlers.js +12 -12
- package/dist/env/event-source/index.js +13 -13
- package/dist/env/index.js +30 -30
- package/dist/env/llm/index.js +2 -2
- package/dist/env/llm/orphan-toolcall.d.ts +107 -0
- package/dist/env/plugin/index.js +3 -3
- package/dist/env/prompt/index.js +3 -3
- package/dist/env/prompt/prompts-index.d.ts +24 -2
- package/dist/env/session/index.js +4 -4
- package/dist/env/session/storage/index.js +3 -3
- package/dist/env/task/delegate/delegate-tool.d.ts +8 -0
- package/dist/env/task/delegate/delegate-tool.js +4 -4
- package/dist/env/task/delegate/index.js +4 -4
- package/dist/env/task/index.js +7 -7
- package/dist/env/task/mcp/index.js +2 -2
- package/dist/env/task/plugins/index.d.ts +3 -0
- package/dist/env/task/plugins/index.js +32 -9
- package/dist/env/task/plugins/lark-card-patch-notifier.d.ts +61 -0
- package/dist/env/task/plugins/lark-card-patch-notifier.js +6 -2
- package/dist/env/task/plugins/lark-cli-task-notify-plugin.d.ts +42 -0
- package/dist/env/task/prompt/index.js +1 -1
- package/dist/env/task/prompt/task-discipline.d.ts +9 -3
- package/dist/env/task/tools/cancel-tool.d.ts +28 -0
- package/dist/env/task/tools/index.d.ts +1 -0
- package/dist/env/task/tools/index.js +4 -2
- package/dist/env/task/tools/task-types.d.ts +22 -0
- package/dist/env/tool/built-in/compact-session-tool.d.ts +120 -0
- package/dist/env/tool/built-in/index.d.ts +2 -0
- package/dist/env/tool/built-in/index.js +6 -2
- package/dist/env/tool/index.js +4 -4
- package/dist/env/workflow/engine/index.js +6 -6
- package/dist/env/workflow/index.js +15 -13
- package/dist/env/workflow/plugins/index.js +2 -2
- package/dist/env/workflow/tools/ask-user-tool.d.ts +88 -0
- package/dist/env/workflow/tools/index.js +11 -9
- package/dist/env/workflow/tools/run-workflow.d.ts +2 -2
- package/dist/env/workflow/types/index.js +2 -2
- package/dist/env/workflow/types/workflow-hil.d.ts +25 -1
- package/dist/env/workflow/utils/index.js +5 -5
- package/dist/index.js +33 -33
- package/dist/shared/@ai-setting/{roy-agent-core-sm0sf6sb.js → roy-agent-core-0qyrk5k0.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-kmbct9yg.js → roy-agent-core-0snm5hc5.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-4jjwewvw.js → roy-agent-core-11shp00p.js} +31 -10
- package/dist/shared/@ai-setting/{roy-agent-core-yr1mryb8.js → roy-agent-core-1v4g0d4x.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-rxb00gjm.js → roy-agent-core-264qexac.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-34jz9mgh.js → roy-agent-core-29b6hc39.js} +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-2akfd64z.js +374 -0
- package/dist/shared/@ai-setting/{roy-agent-core-yhwxpj12.js → roy-agent-core-3e6gg17d.js} +90 -12
- package/dist/shared/@ai-setting/{roy-agent-core-skyc30qx.js → roy-agent-core-3fh1f7s7.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-2gzt2q8c.js → roy-agent-core-4gr3k7qg.js} +17 -4
- package/dist/shared/@ai-setting/{roy-agent-core-y12kyxwa.js → roy-agent-core-60jbrfye.js} +6 -6
- package/dist/shared/@ai-setting/{roy-agent-core-add1zqsh.js → roy-agent-core-6cy43nss.js} +22 -1
- package/dist/shared/@ai-setting/{roy-agent-core-vah6g5yx.js → roy-agent-core-6rh8k6ba.js} +5 -5
- package/dist/shared/@ai-setting/{roy-agent-core-kpg25s2q.js → roy-agent-core-8ez6mccb.js} +4 -2
- package/dist/shared/@ai-setting/{roy-agent-core-sjr1kmfz.js → roy-agent-core-acj8ag08.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-mds8tqd0.js → roy-agent-core-cgtq6427.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-pakhchy7.js → roy-agent-core-ddyk1rc0.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-jgb3bb42.js → roy-agent-core-djpq6yb0.js} +16 -7
- package/dist/shared/@ai-setting/{roy-agent-core-attpry6g.js → roy-agent-core-dqxec05w.js} +4 -3
- package/dist/shared/@ai-setting/{roy-agent-core-vm8h5zyj.js → roy-agent-core-ed233k5z.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-jrj30vq3.js → roy-agent-core-er070zjq.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-40rv283c.js → roy-agent-core-fghc2m8z.js} +152 -2
- package/dist/shared/@ai-setting/{roy-agent-core-7sj9xs9c.js → roy-agent-core-hnyk1by7.js} +110 -2
- package/dist/shared/@ai-setting/{roy-agent-core-7qvw65jt.js → roy-agent-core-jg65qnwa.js} +11 -8
- package/dist/shared/@ai-setting/{roy-agent-core-e25xkv53.js → roy-agent-core-mkc3zshb.js} +3 -1
- package/dist/shared/@ai-setting/{roy-agent-core-hfyfavp3.js → roy-agent-core-mww0mnd9.js} +231 -27
- package/dist/shared/@ai-setting/{roy-agent-core-wr7mv7k3.js → roy-agent-core-n9q1encx.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-46rv4d7d.js → roy-agent-core-nmx9934r.js} +92 -2
- package/dist/shared/@ai-setting/{roy-agent-core-1w9y7mxj.js → roy-agent-core-p3zv1mx5.js} +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-snvh4s2p.js +662 -0
- package/dist/shared/@ai-setting/{roy-agent-core-dt104qa1.js → roy-agent-core-v85n42ve.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-gr48c89p.js → roy-agent-core-v87njmq7.js} +3 -3
- package/dist/shared/@ai-setting/{roy-agent-core-5gw0qa8m.js → roy-agent-core-y7x2qzwc.js} +553 -92
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-1p6syv85.js +0 -1083
- package/dist/shared/@ai-setting/roy-agent-core-58804s3j.js +0 -155
|
@@ -401,6 +401,27 @@ function __resetFailureReplyDedupForTest() {
|
|
|
401
401
|
repliedTriggers.clear();
|
|
402
402
|
}
|
|
403
403
|
var DEFAULT_REPLY_TIMEOUT_MS = 5000;
|
|
404
|
+
async function deliverAskUserMessage(options) {
|
|
405
|
+
const { chatId, messageId, profile, content } = options;
|
|
406
|
+
if (!chatId && !messageId) {
|
|
407
|
+
return { sent: false, error: "no-target" };
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
await spawnLarkReply({
|
|
411
|
+
chatId,
|
|
412
|
+
messageId,
|
|
413
|
+
content,
|
|
414
|
+
profile,
|
|
415
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_REPLY_TIMEOUT_MS
|
|
416
|
+
});
|
|
417
|
+
return { sent: true };
|
|
418
|
+
} catch (err) {
|
|
419
|
+
return {
|
|
420
|
+
sent: false,
|
|
421
|
+
error: err instanceof Error ? err.message : String(err)
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
404
425
|
function spawnLarkReply(options) {
|
|
405
426
|
return new Promise((resolve, reject) => {
|
|
406
427
|
const { chatId, messageId, content, profile } = options;
|
|
@@ -521,4 +542,4 @@ async function notifyReactFailure(options) {
|
|
|
521
542
|
}
|
|
522
543
|
}
|
|
523
544
|
|
|
524
|
-
export { extractRetryAfterSeconds, humanizeRetryAfter, getFailureRuleIds, classifyReactFailure, buildFailureReplyMarkdown, formatCliFailureLine, __resetFailureReplyDedupForTest, notifyReactFailure };
|
|
545
|
+
export { extractRetryAfterSeconds, humanizeRetryAfter, getFailureRuleIds, classifyReactFailure, buildFailureReplyMarkdown, formatCliFailureLine, __resetFailureReplyDedupForTest, deliverAskUserMessage, notifyReactFailure };
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
AgentComponentAdapter,
|
|
9
9
|
init_agent_component_adapter
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-dqxec05w.js";
|
|
11
11
|
import {
|
|
12
12
|
PythonCallNode,
|
|
13
13
|
SkillNode,
|
|
@@ -37,23 +37,23 @@ import {
|
|
|
37
37
|
import {
|
|
38
38
|
TemplateResolver,
|
|
39
39
|
init_template_resolver
|
|
40
|
-
} from "./roy-agent-core-
|
|
40
|
+
} from "./roy-agent-core-acj8ag08.js";
|
|
41
41
|
import {
|
|
42
42
|
DAGManager,
|
|
43
43
|
init_dag_manager
|
|
44
|
-
} from "./roy-agent-core-
|
|
44
|
+
} from "./roy-agent-core-cgtq6427.js";
|
|
45
45
|
import {
|
|
46
46
|
WorkflowError,
|
|
47
47
|
createWorkflowEvent,
|
|
48
48
|
init_event,
|
|
49
49
|
init_types,
|
|
50
50
|
init_workflow_error
|
|
51
|
-
} from "./roy-agent-core-
|
|
51
|
+
} from "./roy-agent-core-er070zjq.js";
|
|
52
52
|
import {
|
|
53
53
|
AskUserError,
|
|
54
54
|
createNodeInterruptEvent,
|
|
55
55
|
init_workflow_hil
|
|
56
|
-
} from "./roy-agent-core-
|
|
56
|
+
} from "./roy-agent-core-mkc3zshb.js";
|
|
57
57
|
import {
|
|
58
58
|
TracedAs,
|
|
59
59
|
init_decorator
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
understandImageTool
|
|
3
3
|
} from "./roy-agent-core-xwm8zavb.js";
|
|
4
4
|
import {
|
|
5
|
+
compactSessionTool,
|
|
5
6
|
queryBackgroundProcessTool
|
|
6
|
-
} from "./roy-agent-core-
|
|
7
|
+
} from "./roy-agent-core-2akfd64z.js";
|
|
7
8
|
import {
|
|
8
9
|
getCurrentProcessRegistry,
|
|
9
10
|
killProcessTree
|
|
@@ -939,7 +940,8 @@ function getAllBuiltInTools() {
|
|
|
939
940
|
editFileTool,
|
|
940
941
|
grepTool,
|
|
941
942
|
understandImageTool,
|
|
942
|
-
queryBackgroundProcessTool
|
|
943
|
+
queryBackgroundProcessTool,
|
|
944
|
+
compactSessionTool
|
|
943
945
|
];
|
|
944
946
|
}
|
|
945
947
|
function getBuiltInTool(name) {
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isToolUnavailableError,
|
|
3
3
|
truncateOutputInline
|
|
4
|
-
} from "./roy-agent-core-
|
|
4
|
+
} from "./roy-agent-core-v85n42ve.js";
|
|
5
5
|
import {
|
|
6
6
|
AgentRegistry
|
|
7
|
-
} from "./roy-agent-core-
|
|
7
|
+
} from "./roy-agent-core-ed233k5z.js";
|
|
8
8
|
import {
|
|
9
9
|
enqueueToAddFakeUserMessage
|
|
10
10
|
} from "./roy-agent-core-f77k3gqt.js";
|
|
11
11
|
import {
|
|
12
12
|
SessionMessageConverter
|
|
13
|
-
} from "./roy-agent-core-
|
|
13
|
+
} from "./roy-agent-core-0snm5hc5.js";
|
|
14
14
|
import {
|
|
15
15
|
parseToolArgsStrict,
|
|
16
16
|
safeParseToolArgs,
|
|
17
17
|
withTimeout
|
|
18
|
-
} from "./roy-agent-core-
|
|
18
|
+
} from "./roy-agent-core-fghc2m8z.js";
|
|
19
19
|
import {
|
|
20
20
|
getCurrentBgTaskId
|
|
21
21
|
} from "./roy-agent-core-c1v263jn.js";
|
|
22
22
|
import {
|
|
23
23
|
AskUserError,
|
|
24
24
|
init_workflow_hil
|
|
25
|
-
} from "./roy-agent-core-
|
|
25
|
+
} from "./roy-agent-core-mkc3zshb.js";
|
|
26
26
|
import {
|
|
27
27
|
ContextError
|
|
28
28
|
} from "./roy-agent-core-ctdhjv68.js";
|
|
@@ -1393,6 +1393,7 @@ class AgentComponent extends BaseComponent {
|
|
|
1393
1393
|
role: "assistant",
|
|
1394
1394
|
content: assistantParts
|
|
1395
1395
|
});
|
|
1396
|
+
this.addRemainingToolResults(hookCtx, llmOutput.toolCalls, 0, "[Tool result missing: run interrupted] ContextError");
|
|
1396
1397
|
} else if (llmOutput.content) {
|
|
1397
1398
|
const assistantParts = [];
|
|
1398
1399
|
if (llmOutput.content) {
|
|
@@ -1438,7 +1439,9 @@ class AgentComponent extends BaseComponent {
|
|
|
1438
1439
|
query: error.query,
|
|
1439
1440
|
sessionId: error.sessionId,
|
|
1440
1441
|
nodeId: error.nodeId,
|
|
1441
|
-
nodeType: error.nodeType
|
|
1442
|
+
nodeType: error.nodeType,
|
|
1443
|
+
agentSessionId: error.agentSessionId,
|
|
1444
|
+
delivered: error.delivered === true
|
|
1442
1445
|
};
|
|
1443
1446
|
result.error = `__ASK_USER_ERROR__:${JSON.stringify(errorInfo)}`;
|
|
1444
1447
|
} else {
|
|
@@ -1979,7 +1982,13 @@ class AgentComponent extends BaseComponent {
|
|
|
1979
1982
|
fallbackModel: ctx.context.fallbackModel,
|
|
1980
1983
|
...effectiveFallbackModels.length > 0 ? { fallbackModels: effectiveFallbackModels } : fallbackExplicitlySet ? { fallbackModels: [] } : {},
|
|
1981
1984
|
workdir: ctx.context.metadata?.workdir,
|
|
1982
|
-
metadata:
|
|
1985
|
+
metadata: {
|
|
1986
|
+
...ctx.context.metadata ?? {},
|
|
1987
|
+
...ctx._runId ? { runId: ctx._runId } : {},
|
|
1988
|
+
...ctx.context.sessionId ? { sessionId: ctx.context.sessionId } : {},
|
|
1989
|
+
...ctx.context.agentType ? { agentType: ctx.context.agentType } : {},
|
|
1990
|
+
...ctx.agent?.name ? { agentName: ctx.agent.name } : {}
|
|
1991
|
+
}
|
|
1983
1992
|
};
|
|
1984
1993
|
const request = {
|
|
1985
1994
|
name: toolName,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
AskUserError,
|
|
7
7
|
init_workflow_hil
|
|
8
|
-
} from "./roy-agent-core-
|
|
8
|
+
} from "./roy-agent-core-mkc3zshb.js";
|
|
9
9
|
import {
|
|
10
10
|
globalHookManager,
|
|
11
11
|
init_global_hook_manager
|
|
@@ -324,7 +324,8 @@ var init_agent_component_adapter = __esm(() => {
|
|
|
324
324
|
runId,
|
|
325
325
|
nodeId,
|
|
326
326
|
sessionId: agentSessionId,
|
|
327
|
-
outputSchema
|
|
327
|
+
outputSchema,
|
|
328
|
+
askUserDelivery: "off"
|
|
328
329
|
};
|
|
329
330
|
if (outputSchema) {
|
|
330
331
|
context.pluginEnabled = {
|
|
@@ -359,7 +360,7 @@ var init_agent_component_adapter = __esm(() => {
|
|
|
359
360
|
if (result.error?.startsWith("__ASK_USER_ERROR__:")) {
|
|
360
361
|
const jsonStr = result.error.substring("__ASK_USER_ERROR__:".length);
|
|
361
362
|
const errorInfo = JSON.parse(jsonStr);
|
|
362
|
-
throw new AskUserError(runId, errorInfo.sessionId, errorInfo.nodeId, errorInfo.nodeType || "agent", errorInfo.query);
|
|
363
|
+
throw new AskUserError(runId, errorInfo.sessionId, errorInfo.nodeId, errorInfo.nodeType || "agent", errorInfo.query, errorInfo.agentSessionId, undefined, errorInfo.delivered === true);
|
|
363
364
|
}
|
|
364
365
|
const duration = Date.now() - startTime;
|
|
365
366
|
if (agentSessionId) {
|
|
@@ -323,7 +323,7 @@ class AgentRegistry {
|
|
|
323
323
|
type: "sub",
|
|
324
324
|
description: "Roy — versatile AI assistant inspired by Jarvis. Built-in general-purpose subagent for coding, research, planning, and complex multi-step tasks. Always available without `agent add roy`.",
|
|
325
325
|
systemPromptRef: "roy",
|
|
326
|
-
deniedTools: ["delegate_task", "stop_task"]
|
|
326
|
+
deniedTools: ["delegate_task", "stop_task", "task_complete", "task_cancel"]
|
|
327
327
|
};
|
|
328
328
|
this.agents.set(name, agent);
|
|
329
329
|
}
|
|
@@ -838,6 +838,126 @@ import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
|
838
838
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
839
839
|
init_logger();
|
|
840
840
|
|
|
841
|
+
// src/env/llm/orphan-toolcall.ts
|
|
842
|
+
var ORPHAN_PLACEHOLDER_PREFIX = "[Tool result missing: run interrupted]";
|
|
843
|
+
function toolNameOf(tc) {
|
|
844
|
+
return tc.function?.name || tc.name || "unknown";
|
|
845
|
+
}
|
|
846
|
+
function extractPendingEvent(msg, events) {
|
|
847
|
+
const added = [];
|
|
848
|
+
const removed = [];
|
|
849
|
+
const toolCalls = msg.toolCalls;
|
|
850
|
+
if (Array.isArray(toolCalls)) {
|
|
851
|
+
for (const tc of toolCalls) {
|
|
852
|
+
if (tc?.id)
|
|
853
|
+
added.push({ id: tc.id, name: toolNameOf(tc) });
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
const content = msg.content;
|
|
857
|
+
if (Array.isArray(content)) {
|
|
858
|
+
for (const part of content) {
|
|
859
|
+
if (!part)
|
|
860
|
+
continue;
|
|
861
|
+
if (part.type === "tool-call" && typeof part.toolCallId === "string") {
|
|
862
|
+
added.push({
|
|
863
|
+
id: part.toolCallId,
|
|
864
|
+
name: typeof part.toolName === "string" ? part.toolName : "unknown"
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
if (part.type === "tool-result" && typeof part.toolCallId === "string") {
|
|
868
|
+
removed.push(part.toolCallId);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (msg.role === "tool" && typeof msg.toolCallId === "string") {
|
|
873
|
+
removed.push(msg.toolCallId);
|
|
874
|
+
}
|
|
875
|
+
events.push({ added, removed });
|
|
876
|
+
}
|
|
877
|
+
function collectOrphans(roles, events) {
|
|
878
|
+
const pending = new Map;
|
|
879
|
+
const orphans = [];
|
|
880
|
+
const reported = new Set;
|
|
881
|
+
for (let index = 0;index < roles.length; index++) {
|
|
882
|
+
const { added, removed } = events[index];
|
|
883
|
+
for (const id of removed)
|
|
884
|
+
pending.delete(id);
|
|
885
|
+
for (const { id, name } of added) {
|
|
886
|
+
if (!pending.has(id))
|
|
887
|
+
pending.set(id, name);
|
|
888
|
+
}
|
|
889
|
+
const role = roles[index];
|
|
890
|
+
if ((role === "user" || role === "system") && pending.size > 0) {
|
|
891
|
+
for (const [id, name] of pending) {
|
|
892
|
+
if (!reported.has(id)) {
|
|
893
|
+
reported.add(id);
|
|
894
|
+
orphans.push({ toolCallId: id, toolName: name, messageIndex: index });
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
pending.clear();
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
for (const [id, name] of pending) {
|
|
901
|
+
if (!reported.has(id)) {
|
|
902
|
+
reported.add(id);
|
|
903
|
+
orphans.push({
|
|
904
|
+
toolCallId: id,
|
|
905
|
+
toolName: name,
|
|
906
|
+
messageIndex: roles.length
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return orphans;
|
|
911
|
+
}
|
|
912
|
+
function repairOrphanSdkMessages(messages, options) {
|
|
913
|
+
const events = [];
|
|
914
|
+
const roles = [];
|
|
915
|
+
for (const msg of messages) {
|
|
916
|
+
roles.push(msg.role);
|
|
917
|
+
extractPendingEvent(msg, events);
|
|
918
|
+
}
|
|
919
|
+
const orphans = collectOrphans(roles, events);
|
|
920
|
+
if (orphans.length === 0) {
|
|
921
|
+
return { messages, orphans: [], repairedCount: 0 };
|
|
922
|
+
}
|
|
923
|
+
const reason = options?.reason ?? "context limit or crash";
|
|
924
|
+
const value = JSON.stringify({ error: `${ORPHAN_PLACEHOLDER_PREFIX} ${reason}` });
|
|
925
|
+
const byIndex = new Map;
|
|
926
|
+
for (const orphan of orphans) {
|
|
927
|
+
const list = byIndex.get(orphan.messageIndex) ?? [];
|
|
928
|
+
list.push(orphan);
|
|
929
|
+
byIndex.set(orphan.messageIndex, list);
|
|
930
|
+
}
|
|
931
|
+
const result = [];
|
|
932
|
+
const endGroup = byIndex.get(messages.length);
|
|
933
|
+
const placeholder = (orphan) => ({
|
|
934
|
+
role: "tool",
|
|
935
|
+
content: [
|
|
936
|
+
{
|
|
937
|
+
type: "tool-result",
|
|
938
|
+
toolCallId: orphan.toolCallId,
|
|
939
|
+
toolName: orphan.toolName,
|
|
940
|
+
output: { type: "text", value }
|
|
941
|
+
}
|
|
942
|
+
]
|
|
943
|
+
});
|
|
944
|
+
messages.forEach((msg, index) => {
|
|
945
|
+
const group = byIndex.get(index);
|
|
946
|
+
if (group) {
|
|
947
|
+
for (const orphan of group) {
|
|
948
|
+
result.push(placeholder(orphan));
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
result.push(msg);
|
|
952
|
+
});
|
|
953
|
+
if (endGroup) {
|
|
954
|
+
for (const orphan of endGroup) {
|
|
955
|
+
result.push(placeholder(orphan));
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return { messages: result, orphans, repairedCount: orphans.length };
|
|
959
|
+
}
|
|
960
|
+
|
|
841
961
|
// src/env/llm/llm-cache.ts
|
|
842
962
|
function isOpenAICompatibleProvider(providerName) {
|
|
843
963
|
return providerName === "openai-compatible" || providerName === "openai" || providerName.startsWith("minimax") || providerName === "deepseek" || providerName.startsWith("deepseek") || providerName === "glm" || providerName.startsWith("glm");
|
|
@@ -1207,6 +1327,24 @@ function convertToSDKMessages(messages, options) {
|
|
|
1207
1327
|
};
|
|
1208
1328
|
}
|
|
1209
1329
|
if (msg.role === "tool") {
|
|
1330
|
+
if (!msg.toolCallId && Array.isArray(msg.content)) {
|
|
1331
|
+
const part = msg.content.find((p) => p?.type === "tool-result" && typeof p.toolCallId === "string");
|
|
1332
|
+
if (part) {
|
|
1333
|
+
const convertedPart = {
|
|
1334
|
+
role: "tool",
|
|
1335
|
+
content: [{
|
|
1336
|
+
type: "tool-result",
|
|
1337
|
+
toolCallId: part.toolCallId,
|
|
1338
|
+
toolName: part.toolName || "unknown",
|
|
1339
|
+
output: {
|
|
1340
|
+
type: "text",
|
|
1341
|
+
value: typeof part.output === "string" ? part.output : JSON.stringify(part.output ?? "")
|
|
1342
|
+
}
|
|
1343
|
+
}]
|
|
1344
|
+
};
|
|
1345
|
+
return convertedPart;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1210
1348
|
if (!msg.toolCallId) {
|
|
1211
1349
|
logger3.warn("Tool message missing toolCallId", { msg });
|
|
1212
1350
|
}
|
|
@@ -1410,6 +1548,12 @@ async function invoke(config, options, ctx) {
|
|
|
1410
1548
|
sessionId: options.context?.sessionId,
|
|
1411
1549
|
provider: providerId
|
|
1412
1550
|
});
|
|
1551
|
+
const orphanRepair = repairOrphanSdkMessages(messages, {
|
|
1552
|
+
reason: "repaired before AI SDK fallback (Task #4992 defence 2)"
|
|
1553
|
+
});
|
|
1554
|
+
if (orphanRepair.repairedCount > 0) {
|
|
1555
|
+
logger3.warn(`[invoke] Repaired ${orphanRepair.repairedCount} orphan tool-call(s) before AI SDK fallback: ` + orphanRepair.orphans.map((o) => o.toolCallId).join(", "));
|
|
1556
|
+
}
|
|
1413
1557
|
const toolCallIds = new Set;
|
|
1414
1558
|
const assistantToolCalls = [];
|
|
1415
1559
|
const toolResultIds = [];
|
|
@@ -1457,7 +1601,7 @@ async function invoke(config, options, ctx) {
|
|
|
1457
1601
|
}
|
|
1458
1602
|
const streamTextOptions = {
|
|
1459
1603
|
model: provider.languageModel(modelId),
|
|
1460
|
-
messages,
|
|
1604
|
+
messages: orphanRepair.messages,
|
|
1461
1605
|
tools,
|
|
1462
1606
|
temperature: providerOptions.temperature,
|
|
1463
1607
|
maxTokens: providerOptions.maxTokens,
|
|
@@ -1704,6 +1848,12 @@ async function invokeNonStream(config, options, ctx) {
|
|
|
1704
1848
|
sessionId: options.context?.sessionId,
|
|
1705
1849
|
provider: providerId
|
|
1706
1850
|
});
|
|
1851
|
+
const orphanRepair = repairOrphanSdkMessages(messages, {
|
|
1852
|
+
reason: "repaired before AI SDK generateText (Task #4992 defence 2)"
|
|
1853
|
+
});
|
|
1854
|
+
if (orphanRepair.repairedCount > 0) {
|
|
1855
|
+
logger3.warn(`[invokeNonStream] Repaired ${orphanRepair.repairedCount} orphan tool-call(s): ` + orphanRepair.orphans.map((o) => o.toolCallId).join(", "));
|
|
1856
|
+
}
|
|
1707
1857
|
const tools = options.tools && options.tools.length > 0 ? convertToolsToSDK(options.tools, providerId) : undefined;
|
|
1708
1858
|
const providerOptions = generateProviderOptions(providerId, {
|
|
1709
1859
|
temperature: options.temperature,
|
|
@@ -1713,7 +1863,7 @@ async function invokeNonStream(config, options, ctx) {
|
|
|
1713
1863
|
const genTextFn = generateText;
|
|
1714
1864
|
const result = await genTextFn({
|
|
1715
1865
|
model: provider.languageModel(modelId),
|
|
1716
|
-
messages,
|
|
1866
|
+
messages: orphanRepair.messages,
|
|
1717
1867
|
tools,
|
|
1718
1868
|
temperature: providerOptions.temperature,
|
|
1719
1869
|
maxTokens: providerOptions.maxTokens,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
TASK_COMPLETE_VERIFY_DUTY,
|
|
8
8
|
TASK_COMPLETION_HINT_ANCHOR,
|
|
9
9
|
TASK_DISCIPLINE_GOALS
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-11shp00p.js";
|
|
11
11
|
import {
|
|
12
12
|
getEnvContextOrEmpty,
|
|
13
13
|
init_env_context,
|
|
@@ -103,6 +103,9 @@ var DeleteTaskToolSchema = z.object({
|
|
|
103
103
|
var CompleteTaskToolSchema = withLegacyTaskId({
|
|
104
104
|
deliverable_storage_path: z.string().optional().describe("交付物的寻址地址(路径 / URL / 分支名等)。" + "调用本工具前,请先读取任务的 goal(description)和 delivery(goals_and_expected_deliverables)栏位," + "建议验证目标和交付物是否符合预期,然后将实际交付物的寻址地址填入此参数。")
|
|
105
105
|
});
|
|
106
|
+
var CancelTaskToolSchema = withLegacyTaskId({
|
|
107
|
+
reason: z.string().optional().describe("取消原因(可选)。会写入该任务的 operation 记录,便于事后追溯验收结论。")
|
|
108
|
+
});
|
|
106
109
|
var BatchArchiveToolSchema = z.object({
|
|
107
110
|
task_ids: z.array(z.number()).describe("要归档的任务 ID 列表"),
|
|
108
111
|
reason: z.string().optional().describe("归档原因(可选,会写入每个任务的 operation 记录)")
|
|
@@ -828,6 +831,22 @@ function updateTaskTool(taskComponent) {
|
|
|
828
831
|
};
|
|
829
832
|
}
|
|
830
833
|
}
|
|
834
|
+
const callerAgentType = ctx.metadata?.agentType ?? undefined;
|
|
835
|
+
const callerAgentName = ctx.metadata?.agentName ?? undefined;
|
|
836
|
+
if (params.status === "completed" && callerAgentType === "sub") {
|
|
837
|
+
const agentComponent = taskComponent.env?.getComponent?.("agent");
|
|
838
|
+
const callerAgent = callerAgentName && agentComponent?.getAgent ? agentComponent.getAgent(callerAgentName) : undefined;
|
|
839
|
+
const cfg = callerAgent?.config;
|
|
840
|
+
const hasCompletePermission = cfg ? Array.isArray(cfg.allowedTools) && cfg.allowedTools.includes("task_complete") || !Array.isArray(cfg.allowedTools) && !(Array.isArray(cfg.deniedTools) && cfg.deniedTools.includes("task_complete")) : false;
|
|
841
|
+
if (!hasCompletePermission) {
|
|
842
|
+
return {
|
|
843
|
+
success: false,
|
|
844
|
+
output: "",
|
|
845
|
+
error: `Cannot set status="completed" without acceptance permission (Task #5007 — 验收权分离). ` + `执行方只能推进进度:用 task_update(progress=100) 表示"我这边干完了",` + `再 task_operation_create 记录结论,然后结束返回;` + `任务终态必须由验收方(default agent / 主智能体)调用 task_complete 落定。`,
|
|
846
|
+
metadata: { execution_time_ms: 0 }
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
}
|
|
831
850
|
const task = await taskComponent.updateTask(params.task_id, {
|
|
832
851
|
title: params.title,
|
|
833
852
|
description: params.description,
|
|
@@ -1020,6 +1039,95 @@ Deliverable: (no path provided)`,
|
|
|
1020
1039
|
}
|
|
1021
1040
|
};
|
|
1022
1041
|
}
|
|
1042
|
+
// src/env/task/tools/cancel-tool.ts
|
|
1043
|
+
init_logger();
|
|
1044
|
+
var logger5 = createLogger("tool:cancel-task");
|
|
1045
|
+
var NON_CANCELLABLE_STATUSES = new Set(["completed", "cancelled", "archived"]);
|
|
1046
|
+
var TASK_CANCEL_DESCRIPTION = `
|
|
1047
|
+
Cancel a task (task.status = "cancelled"). This is the **acceptance-side** cancel:
|
|
1048
|
+
use it when the work is abandoned, the user asked to stop, or acceptance failed.
|
|
1049
|
+
|
|
1050
|
+
**When to use**:
|
|
1051
|
+
- The user asks to cancel / stop / drop the task
|
|
1052
|
+
- Acceptance failed and re-delegation is not worth it
|
|
1053
|
+
- The sub-agent timed out or went off-track and the task is no longer relevant
|
|
1054
|
+
|
|
1055
|
+
**What it does NOT do**:
|
|
1056
|
+
- It does **NOT** stop a running background process — that is \`stop_task\`
|
|
1057
|
+
(which takes a bg-process id from \`delegate_task\`). If the sub-agent is still
|
|
1058
|
+
running, call \`stop_task\` **first**, then \`task_cancel\` to close the record.
|
|
1059
|
+
|
|
1060
|
+
**Side effects**:
|
|
1061
|
+
- Sets \`status = "cancelled"\` and fires the task terminal-state hooks
|
|
1062
|
+
(notifications / card state machine converge to the cancelled state).
|
|
1063
|
+
- Writes an operation record so the cancellation reason stays auditable.
|
|
1064
|
+
- A cancelled task can be reopened later with \`task_update(status="active")\`.
|
|
1065
|
+
|
|
1066
|
+
**Parameters**:
|
|
1067
|
+
- \`task_id\` (required): the task to cancel
|
|
1068
|
+
- \`reason\` (optional): why it is being cancelled — recorded in the operation trail
|
|
1069
|
+
`.trim();
|
|
1070
|
+
function cancelTaskTool(taskComponent) {
|
|
1071
|
+
return {
|
|
1072
|
+
name: "task_cancel",
|
|
1073
|
+
description: TASK_CANCEL_DESCRIPTION,
|
|
1074
|
+
parameters: CancelTaskToolSchema,
|
|
1075
|
+
execute: async (args, ctx) => {
|
|
1076
|
+
const params = CancelTaskToolSchema.parse(args);
|
|
1077
|
+
const sessionId = ctx.session_id || "unknown";
|
|
1078
|
+
try {
|
|
1079
|
+
const current = await taskComponent.getTask(params.task_id);
|
|
1080
|
+
if (!current) {
|
|
1081
|
+
return {
|
|
1082
|
+
success: false,
|
|
1083
|
+
output: "",
|
|
1084
|
+
error: `Task not found: ${params.task_id}`,
|
|
1085
|
+
metadata: { execution_time_ms: 0 }
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
if (NON_CANCELLABLE_STATUSES.has(current.status)) {
|
|
1089
|
+
return {
|
|
1090
|
+
success: false,
|
|
1091
|
+
output: "",
|
|
1092
|
+
error: `Cannot cancel task #${params.task_id}: it is already in terminal status "${current.status}".`,
|
|
1093
|
+
metadata: { execution_time_ms: 0, task_id: params.task_id }
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
const task = await taskComponent.updateTask(params.task_id, {
|
|
1097
|
+
status: "cancelled"
|
|
1098
|
+
});
|
|
1099
|
+
if (!task) {
|
|
1100
|
+
return {
|
|
1101
|
+
success: false,
|
|
1102
|
+
output: "",
|
|
1103
|
+
error: `Task not found: ${params.task_id}`,
|
|
1104
|
+
metadata: { execution_time_ms: 0 }
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
await taskComponent.createOperation({
|
|
1108
|
+
taskId: params.task_id,
|
|
1109
|
+
sessionId,
|
|
1110
|
+
milestoneType: "decision",
|
|
1111
|
+
milestoneTitle: `Task cancelled: #${params.task_id}`,
|
|
1112
|
+
milestoneDescription: params.reason ? `Cancelled by acceptance side. Reason: ${params.reason}` : "Cancelled by acceptance side (no reason given)."
|
|
1113
|
+
});
|
|
1114
|
+
logger5.info(`[cancelTask] Task #${params.task_id} cancelled (previous status: ${current.status})`);
|
|
1115
|
+
return {
|
|
1116
|
+
success: true,
|
|
1117
|
+
output: `Task cancelled: #${params.task_id} - ${task.title}`,
|
|
1118
|
+
metadata: { execution_time_ms: 0, task }
|
|
1119
|
+
};
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
return {
|
|
1122
|
+
success: false,
|
|
1123
|
+
output: "",
|
|
1124
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1125
|
+
metadata: { execution_time_ms: 0 }
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1023
1131
|
// src/env/task/tools/task-tree-tool.ts
|
|
1024
1132
|
function compareTasksDesc(a, b) {
|
|
1025
1133
|
if (a.updatedAt < b.updatedAt)
|
|
@@ -1158,4 +1266,4 @@ function treeTasksTool(taskComponent) {
|
|
|
1158
1266
|
}
|
|
1159
1267
|
};
|
|
1160
1268
|
}
|
|
1161
|
-
export { createTaskTool, getTaskTool, listTasksTool, searchTasksTool, batchArchiveTaskTool, batchDeleteTaskTool, updateTaskTool, deleteTaskTool, completeTaskTool, treeTasksTool };
|
|
1269
|
+
export { createTaskTool, getTaskTool, listTasksTool, searchTasksTool, batchArchiveTaskTool, batchDeleteTaskTool, updateTaskTool, deleteTaskTool, completeTaskTool, cancelTaskTool, treeTasksTool };
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
} from "./roy-agent-core-na18zwj0.js";
|
|
8
8
|
import {
|
|
9
9
|
builtInPrompts
|
|
10
|
-
} from "./roy-agent-core-
|
|
10
|
+
} from "./roy-agent-core-3e6gg17d.js";
|
|
11
11
|
import {
|
|
12
12
|
TaskHookPoints
|
|
13
13
|
} from "./roy-agent-core-1pg0fepg.js";
|
|
14
14
|
import {
|
|
15
15
|
DEFAULT_SUBAGENT_PROMPT
|
|
16
|
-
} from "./roy-agent-core-
|
|
16
|
+
} from "./roy-agent-core-ed233k5z.js";
|
|
17
17
|
import {
|
|
18
18
|
runWithBgTaskIdAsync
|
|
19
19
|
} from "./roy-agent-core-c1v263jn.js";
|
|
@@ -819,7 +819,7 @@ var builtInSubAgents = [
|
|
|
819
819
|
mode: "subagent",
|
|
820
820
|
description: "Versatile AI assistant inspired by Jarvis — intelligent, proactive, and capable. Use for general-purpose tasks, coding, research, and complex multi-step work. Always available (built-in) without `agent add roy`.",
|
|
821
821
|
promptOverride: builtInPrompts["roy"],
|
|
822
|
-
deniedTools: ["delegate_task", "stop_task"]
|
|
822
|
+
deniedTools: ["delegate_task", "stop_task", "task_complete", "task_cancel"]
|
|
823
823
|
}
|
|
824
824
|
];
|
|
825
825
|
function getSubAgentSpec(id) {
|
|
@@ -1089,6 +1089,7 @@ class BackgroundTaskManager {
|
|
|
1089
1089
|
nodeId: e.nodeId,
|
|
1090
1090
|
nodeType: e.nodeType || "agent",
|
|
1091
1091
|
agentSessionId: e.agentSessionId,
|
|
1092
|
+
delivered: e.delivered === true,
|
|
1092
1093
|
rawErrorMessage
|
|
1093
1094
|
};
|
|
1094
1095
|
}
|
|
@@ -1103,6 +1104,7 @@ class BackgroundTaskManager {
|
|
|
1103
1104
|
nodeId: parsed.nodeId,
|
|
1104
1105
|
nodeType: parsed.nodeType || "agent",
|
|
1105
1106
|
agentSessionId: parsed.agentSessionId,
|
|
1107
|
+
delivered: parsed.delivered === true,
|
|
1106
1108
|
rawErrorMessage
|
|
1107
1109
|
};
|
|
1108
1110
|
} catch (parseErr) {
|
|
@@ -1267,9 +1269,9 @@ class BackgroundTaskManager {
|
|
|
1267
1269
|
task.lastUpdatedAt = completedAt;
|
|
1268
1270
|
task.result = result;
|
|
1269
1271
|
const executionTimeMs = task.completedAt - task.startedAt;
|
|
1270
|
-
task.associatedTaskId =
|
|
1272
|
+
task.associatedTaskId = await this.resolveAssociatedTaskIdBySubSession(task.subSessionId);
|
|
1271
1273
|
if (task.associatedTaskId === undefined) {
|
|
1272
|
-
task.associatedTaskId =
|
|
1274
|
+
task.associatedTaskId = getCurrentTaskId();
|
|
1273
1275
|
}
|
|
1274
1276
|
const completedPayload = {
|
|
1275
1277
|
backgroundTaskId: task.id,
|
|
@@ -1294,9 +1296,9 @@ class BackgroundTaskManager {
|
|
|
1294
1296
|
const completedAt = Date.now();
|
|
1295
1297
|
task.completedAt = completedAt;
|
|
1296
1298
|
task.lastUpdatedAt = completedAt;
|
|
1297
|
-
task.associatedTaskId =
|
|
1299
|
+
task.associatedTaskId = await this.resolveAssociatedTaskIdBySubSession(task.subSessionId);
|
|
1298
1300
|
if (task.associatedTaskId === undefined) {
|
|
1299
|
-
task.associatedTaskId =
|
|
1301
|
+
task.associatedTaskId = getCurrentTaskId();
|
|
1300
1302
|
}
|
|
1301
1303
|
if (askUserInfo) {
|
|
1302
1304
|
task.status = "awaiting-user";
|
|
@@ -1313,6 +1315,7 @@ class BackgroundTaskManager {
|
|
|
1313
1315
|
nodeId: askUserInfo.nodeId,
|
|
1314
1316
|
nodeType: askUserInfo.nodeType,
|
|
1315
1317
|
agentSessionId: askUserInfo.agentSessionId,
|
|
1318
|
+
delivered: askUserInfo.delivered === true,
|
|
1316
1319
|
error: askUserInfo.rawErrorMessage,
|
|
1317
1320
|
executionTimeMs,
|
|
1318
1321
|
hints: [
|
|
@@ -1399,7 +1402,7 @@ class BackgroundTaskManager {
|
|
|
1399
1402
|
return;
|
|
1400
1403
|
}
|
|
1401
1404
|
const currentTaskId = getCurrentTaskId();
|
|
1402
|
-
if (currentTaskId !== undefined) {
|
|
1405
|
+
if (currentTaskId !== undefined && task.associatedTaskId === undefined) {
|
|
1403
1406
|
task.associatedTaskId = currentTaskId;
|
|
1404
1407
|
}
|
|
1405
1408
|
task.lastUpdatedAt = Date.now();
|
|
@@ -35,9 +35,10 @@ var init_workflow_hil = __esm(() => {
|
|
|
35
35
|
query;
|
|
36
36
|
agentSessionId;
|
|
37
37
|
timestamp;
|
|
38
|
+
delivered;
|
|
38
39
|
type = "ask-user";
|
|
39
40
|
name = "AskUserError";
|
|
40
|
-
constructor(runId, sessionId, nodeId, nodeType, query, agentSessionId, timestamp = Date.now()) {
|
|
41
|
+
constructor(runId, sessionId, nodeId, nodeType, query, agentSessionId, timestamp = Date.now(), delivered = false) {
|
|
41
42
|
super(`[${nodeType}:${nodeId}] Ask user: ${query}`);
|
|
42
43
|
this.runId = runId;
|
|
43
44
|
this.sessionId = sessionId;
|
|
@@ -46,6 +47,7 @@ var init_workflow_hil = __esm(() => {
|
|
|
46
47
|
this.query = query;
|
|
47
48
|
this.agentSessionId = agentSessionId;
|
|
48
49
|
this.timestamp = timestamp;
|
|
50
|
+
this.delivered = delivered;
|
|
49
51
|
}
|
|
50
52
|
toEvent() {
|
|
51
53
|
return {
|