plugin-agent-orchestrator 1.0.6 → 1.0.14
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/README.md +16 -291
- package/dist/client/AIEmployeesContext.d.ts +7 -0
- package/dist/client/OrchestratorSettings.d.ts +2 -1
- package/dist/client/index.js +1 -1
- package/dist/client/plugin.d.ts +1 -0
- package/dist/client/skill-hub/components/ExecutionHistory.d.ts +2 -0
- package/dist/client/skill-hub/components/ExecutionProgress.d.ts +20 -0
- package/dist/client/skill-hub/components/GitSkillImport.d.ts +7 -0
- package/dist/client/skill-hub/components/SkillEditor.d.ts +7 -0
- package/dist/client/skill-hub/components/SkillManager.d.ts +2 -0
- package/dist/client/skill-hub/components/SkillMetrics.d.ts +2 -0
- package/dist/client/skill-hub/components/SkillTestPanel.d.ts +7 -0
- package/dist/client/skill-hub/index.d.ts +10 -0
- package/dist/client/skill-hub/locale.d.ts +3 -0
- package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +19 -0
- package/dist/client/skill-hub/tools/SkillHubCard.d.ts +3 -0
- package/dist/client/skill-hub/utils/jsonFields.d.ts +3 -0
- package/dist/externalVersion.js +6 -6
- package/dist/node_modules/adm-zip/LICENSE +21 -0
- package/dist/node_modules/adm-zip/adm-zip.js +1 -0
- package/dist/node_modules/adm-zip/headers/entryHeader.js +377 -0
- package/dist/node_modules/adm-zip/headers/index.js +2 -0
- package/dist/node_modules/adm-zip/headers/mainHeader.js +130 -0
- package/dist/node_modules/adm-zip/methods/deflater.js +33 -0
- package/dist/node_modules/adm-zip/methods/index.js +3 -0
- package/dist/node_modules/adm-zip/methods/inflater.js +34 -0
- package/dist/node_modules/adm-zip/methods/zipcrypto.js +175 -0
- package/dist/node_modules/adm-zip/package.json +1 -0
- package/dist/node_modules/adm-zip/util/constants.js +142 -0
- package/dist/node_modules/adm-zip/util/decoder.js +5 -0
- package/dist/node_modules/adm-zip/util/errors.js +63 -0
- package/dist/node_modules/adm-zip/util/fattr.js +76 -0
- package/dist/node_modules/adm-zip/util/index.js +5 -0
- package/dist/node_modules/adm-zip/util/utils.js +339 -0
- package/dist/node_modules/adm-zip/zipEntry.js +405 -0
- package/dist/node_modules/adm-zip/zipFile.js +446 -0
- package/dist/node_modules/simple-git/dist/cjs/index.js +7399 -0
- package/dist/node_modules/simple-git/dist/esm/index.js +4745 -0
- package/dist/node_modules/simple-git/dist/esm/package.json +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/api.d.ts +13 -0
- package/dist/node_modules/simple-git/dist/src/lib/args/log-format.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/errors/git-construct-error.d.ts +15 -0
- package/dist/node_modules/simple-git/dist/src/lib/errors/git-error.d.ts +30 -0
- package/dist/node_modules/simple-git/dist/src/lib/errors/git-plugin-error.d.ts +7 -0
- package/dist/node_modules/simple-git/dist/src/lib/errors/git-response-error.d.ts +32 -0
- package/dist/node_modules/simple-git/dist/src/lib/errors/task-configuration-error.d.ts +12 -0
- package/dist/node_modules/simple-git/dist/src/lib/git-factory.d.ts +15 -0
- package/dist/node_modules/simple-git/dist/src/lib/git-logger.d.ts +21 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch-delete.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-commit.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-diff-summary.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-fetch.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-list-log-summary.d.ts +6 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-merge.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-move.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-pull.d.ts +6 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-push.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-messages.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-objects.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/abort-plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/block-unsafe-operations-plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/command-config-prefixing-plugin.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/completion-detection.plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/custom-binary.plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/error-detection.plugin.d.ts +7 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/index.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/plugin-store.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/progress-monitor-plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/simple-git-plugin.d.ts +48 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/spawn-options-plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/suffix-paths.plugin.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/plugins/timout-plugin.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/BranchDeleteSummary.d.ts +12 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/BranchSummary.d.ts +14 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/CheckIgnore.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/CleanSummary.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/ConfigList.d.ts +13 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/DiffSummary.d.ts +10 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/FileStatusSummary.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/GetRemoteSummary.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/InitSummary.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/MergeSummary.d.ts +16 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/PullSummary.d.ts +25 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/StatusSummary.d.ts +19 -0
- package/dist/node_modules/simple-git/dist/src/lib/responses/TagList.d.ts +7 -0
- package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor-chain.d.ts +25 -0
- package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor.d.ts +14 -0
- package/dist/node_modules/simple-git/dist/src/lib/runners/promise-wrapped.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/runners/scheduler.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/runners/tasks-pending-queue.d.ts +23 -0
- package/dist/node_modules/simple-git/dist/src/lib/simple-git-api.d.ts +20 -0
- package/dist/node_modules/simple-git/dist/src/lib/task-callback.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/apply-patch.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/branch.d.ts +7 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/change-working-directory.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/check-ignore.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/check-is-repo.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/checkout.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/clean.d.ts +25 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/clone.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/commit.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/config.d.ts +8 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/count-objects.d.ts +12 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/diff-name-status.d.ts +12 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/diff.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/fetch.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/first-commit.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/grep.d.ts +12 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/hash-object.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/init.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/log.d.ts +32 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/merge.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/move.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/pull.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/push.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/remote.d.ts +8 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/reset.d.ts +11 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/show.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/stash-list.d.ts +4 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/status.d.ts +3 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/sub-module.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/tag.d.ts +18 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/task.d.ts +14 -0
- package/dist/node_modules/simple-git/dist/src/lib/tasks/version.d.ts +9 -0
- package/dist/node_modules/simple-git/dist/src/lib/types/handlers.d.ts +21 -0
- package/dist/node_modules/simple-git/dist/src/lib/types/index.d.ts +136 -0
- package/dist/node_modules/simple-git/dist/src/lib/types/tasks.d.ts +19 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/argument-filters.d.ts +14 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/exit-codes.d.ts +10 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/git-output-streams.d.ts +7 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/index.d.ts +8 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/line-parser.d.ts +15 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/simple-git-options.d.ts +2 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/task-options.d.ts +13 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/task-parser.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/src/lib/utils/util.d.ts +47 -0
- package/dist/node_modules/simple-git/dist/typings/errors.d.ts +5 -0
- package/dist/node_modules/simple-git/dist/typings/index.d.ts +14 -0
- package/dist/node_modules/simple-git/dist/typings/response.d.ts +556 -0
- package/dist/node_modules/simple-git/dist/typings/simple-git.d.ts +1033 -0
- package/dist/node_modules/simple-git/dist/typings/types.d.ts +22 -0
- package/dist/node_modules/simple-git/node_modules/debug/package.json +64 -0
- package/dist/node_modules/simple-git/node_modules/debug/src/browser.js +272 -0
- package/dist/node_modules/simple-git/node_modules/debug/src/common.js +292 -0
- package/dist/node_modules/simple-git/node_modules/debug/src/index.js +10 -0
- package/dist/node_modules/simple-git/node_modules/debug/src/node.js +263 -0
- package/dist/node_modules/simple-git/package.json +1 -0
- package/dist/node_modules/simple-git/promise.js +17 -0
- package/dist/server/collections/agent-execution-spans.d.ts +9 -0
- package/dist/server/collections/agent-execution-spans.js +152 -0
- package/dist/server/collections/orchestrator-config.js +16 -0
- package/dist/server/collections/orchestrator-logs.js +19 -2
- package/dist/server/collections/skill-definitions.d.ts +3 -0
- package/dist/server/collections/skill-definitions.js +158 -0
- package/dist/server/collections/skill-executions.d.ts +3 -0
- package/dist/server/collections/skill-executions.js +123 -0
- package/dist/server/collections/skill-worker-configs.d.ts +3 -0
- package/dist/server/collections/skill-worker-configs.js +115 -0
- package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +4 -0
- package/dist/server/migrations/20260423000000-add-progress-fields.js +69 -0
- package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +4 -0
- package/dist/server/migrations/20260425000000-add-interaction-schema.js +61 -0
- package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +7 -0
- package/dist/server/migrations/20260427000000-add-tracing-detail-fields.js +62 -0
- package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +4 -0
- package/dist/server/migrations/20260427000000-change-packages-to-text.js +70 -0
- package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +4 -0
- package/dist/server/migrations/20260427000001-change-other-json-to-text.js +80 -0
- package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +7 -0
- package/dist/server/migrations/20260429000000-add-llm-fields.js +68 -0
- package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +16 -0
- package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.js +51 -0
- package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +7 -0
- package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.js +57 -0
- package/dist/server/plugin.d.ts +3 -0
- package/dist/server/plugin.js +37 -1
- package/dist/server/resources/tracing.js +160 -12
- package/dist/server/services/CodeValidator.d.ts +32 -0
- package/dist/server/services/CodeValidator.js +205 -0
- package/dist/server/services/ExecutionSpanService.d.ts +44 -0
- package/dist/server/services/ExecutionSpanService.js +104 -0
- package/dist/server/services/FileManager.d.ts +28 -0
- package/dist/server/services/FileManager.js +151 -0
- package/dist/server/services/SandboxRunner.d.ts +41 -0
- package/dist/server/services/SandboxRunner.js +167 -0
- package/dist/server/services/SkillManager.d.ts +6 -0
- package/dist/server/services/SkillManager.js +640 -0
- package/dist/server/services/SkillRepositoryService.d.ts +22 -0
- package/dist/server/services/SkillRepositoryService.js +157 -0
- package/dist/server/services/WorkerEnvManager.d.ts +26 -0
- package/dist/server/services/WorkerEnvManager.js +120 -0
- package/dist/server/skill-hub/actions/git-import.d.ts +21 -0
- package/dist/server/skill-hub/actions/git-import.js +413 -0
- package/dist/server/skill-hub/mcp/McpController.d.ts +15 -0
- package/dist/server/skill-hub/mcp/McpController.js +111 -0
- package/dist/server/skill-hub/plugin.d.ts +58 -0
- package/dist/server/skill-hub/plugin.js +694 -0
- package/dist/server/skill-hub/sandbox-config.json +6 -0
- package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +14 -0
- package/dist/server/skill-hub/tasks/SkillExecutionTask.js +267 -0
- package/dist/server/skill-hub/utils/json-fields.d.ts +7 -0
- package/dist/server/skill-hub/utils/json-fields.js +88 -0
- package/dist/server/tools/delegate-task.d.ts +4 -0
- package/dist/server/tools/delegate-task.js +832 -119
- package/dist/server/tools/skill-execute.d.ts +36 -0
- package/dist/server/tools/skill-execute.js +167 -0
- package/package.json +3 -1
- package/src/client/AIEmployeeSelect.tsx +1 -3
- package/src/client/AIEmployeesContext.tsx +28 -13
- package/src/client/OrchestratorSettings.tsx +43 -5
- package/src/client/RulesTab.tsx +368 -21
- package/src/client/TracingTab.tsx +316 -102
- package/src/client/plugin.tsx +39 -0
- package/src/client/skill-hub/components/ExecutionHistory.tsx +201 -0
- package/src/client/skill-hub/components/ExecutionProgress.tsx +55 -0
- package/src/client/skill-hub/components/GitSkillImport.tsx +555 -0
- package/src/client/skill-hub/components/SkillEditor.tsx +456 -0
- package/src/client/skill-hub/components/SkillManager.tsx +181 -0
- package/src/client/skill-hub/components/SkillMetrics.tsx +124 -0
- package/src/client/skill-hub/components/SkillTestPanel.tsx +144 -0
- package/src/client/skill-hub/index.tsx +75 -0
- package/src/client/skill-hub/locale.ts +16 -0
- package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +59 -0
- package/src/client/skill-hub/tools/SkillHubCard.tsx +78 -0
- package/src/client/skill-hub/utils/jsonFields.ts +37 -0
- package/src/server/collections/agent-execution-spans.ts +129 -0
- package/src/server/collections/orchestrator-config.ts +17 -0
- package/src/server/collections/orchestrator-logs.ts +19 -2
- package/src/server/collections/skill-definitions.ts +128 -0
- package/src/server/collections/skill-executions.ts +94 -0
- package/src/server/collections/skill-worker-configs.ts +86 -0
- package/src/server/migrations/20260423000000-add-progress-fields.ts +50 -0
- package/src/server/migrations/20260425000000-add-interaction-schema.ts +35 -0
- package/src/server/migrations/20260427000000-add-tracing-detail-fields.ts +41 -0
- package/src/server/migrations/20260427000000-change-packages-to-text.ts +47 -0
- package/src/server/migrations/20260427000001-change-other-json-to-text.ts +57 -0
- package/src/server/migrations/20260429000000-add-llm-fields.ts +46 -0
- package/src/server/migrations/20260429000000-fix-inputargs-json-to-text.ts +38 -0
- package/src/server/migrations/20260503000000-add-orchestrator-trace-fields.ts +32 -0
- package/src/server/plugin.ts +51 -3
- package/src/server/resources/tracing.ts +187 -16
- package/src/server/services/CodeValidator.ts +159 -0
- package/src/server/services/ExecutionSpanService.ts +106 -0
- package/src/server/services/FileManager.ts +144 -0
- package/src/server/services/SandboxRunner.ts +205 -0
- package/src/server/services/SkillManager.ts +623 -0
- package/src/server/services/SkillRepositoryService.ts +142 -0
- package/src/server/services/WorkerEnvManager.ts +113 -0
- package/src/server/skill-hub/actions/git-import.ts +486 -0
- package/src/server/skill-hub/mcp/McpController.ts +86 -0
- package/src/server/skill-hub/plugin.ts +771 -0
- package/src/server/skill-hub/sandbox-config.json +6 -0
- package/src/server/skill-hub/tasks/SkillExecutionTask.ts +297 -0
- package/src/server/skill-hub/utils/json-fields.ts +57 -0
- package/src/server/tools/delegate-task.ts +1085 -147
- package/src/server/tools/skill-execute.ts +157 -0
|
@@ -26,110 +26,640 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
26
26
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
27
|
var delegate_task_exports = {};
|
|
28
28
|
__export(delegate_task_exports, {
|
|
29
|
-
createDelegateToolsProvider: () => createDelegateToolsProvider
|
|
29
|
+
createDelegateToolsProvider: () => createDelegateToolsProvider,
|
|
30
|
+
invalidateDelegateToolsCache: () => invalidateDelegateToolsCache
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(delegate_task_exports);
|
|
32
33
|
var import_zod = require("zod");
|
|
34
|
+
var import_crypto = require("crypto");
|
|
33
35
|
var import_prebuilt = require("@langchain/langgraph/prebuilt");
|
|
34
36
|
var import_tools = require("@langchain/core/tools");
|
|
35
37
|
var import_messages = require("@langchain/core/messages");
|
|
38
|
+
var import_ExecutionSpanService = require("../services/ExecutionSpanService");
|
|
36
39
|
const ORCHESTRATOR_DEPTH_KEY = "__orchestratorDepth";
|
|
40
|
+
const MAX_DISPATCH_CONCURRENCY = 5;
|
|
41
|
+
const MAX_DISPATCH_TASKS = 20;
|
|
42
|
+
const MAX_TOOL_NAME_LENGTH = 64;
|
|
43
|
+
function sanitizeToolPart(value) {
|
|
44
|
+
return (value || "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
45
|
+
}
|
|
46
|
+
function buildDelegateToolName(leaderUsername, subAgentUsername) {
|
|
47
|
+
return `delegate_${sanitizeToolPart(leaderUsername)}_to_${sanitizeToolPart(subAgentUsername)}`;
|
|
48
|
+
}
|
|
49
|
+
function buildDispatchToolName(leaderUsername) {
|
|
50
|
+
return `dispatch_subagents_${sanitizeToolPart(leaderUsername)}`;
|
|
51
|
+
}
|
|
52
|
+
function createRootRunId(seed = "") {
|
|
53
|
+
const hash = (0, import_crypto.createHash)("sha1").update(`${Date.now()}::${Math.random()}::${seed}`).digest("hex").slice(0, 10);
|
|
54
|
+
return `run_${Date.now()}_${hash}`;
|
|
55
|
+
}
|
|
56
|
+
let registeredDelegateNamesByPlugin = /* @__PURE__ */ new WeakMap();
|
|
57
|
+
function isDelegateToolName(plugin, toolName) {
|
|
58
|
+
var _a;
|
|
59
|
+
return ((_a = registeredDelegateNamesByPlugin.get(plugin)) == null ? void 0 : _a.has(toolName)) ?? false;
|
|
60
|
+
}
|
|
61
|
+
async function runWithConcurrency(items, limit, fn) {
|
|
62
|
+
const results = new Array(items.length);
|
|
63
|
+
let cursor = 0;
|
|
64
|
+
const workerCount = Math.max(1, Math.min(limit, items.length));
|
|
65
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
66
|
+
while (cursor < items.length) {
|
|
67
|
+
const i = cursor;
|
|
68
|
+
cursor += 1;
|
|
69
|
+
results[i] = await fn(items[i], i);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
await Promise.all(workers);
|
|
73
|
+
return results;
|
|
74
|
+
}
|
|
75
|
+
function createDelegateToolOptions(plugin, options) {
|
|
76
|
+
const {
|
|
77
|
+
leaderUsername,
|
|
78
|
+
subAgentUsername,
|
|
79
|
+
subAgentEmployee,
|
|
80
|
+
maxDepth,
|
|
81
|
+
timeout,
|
|
82
|
+
toolName,
|
|
83
|
+
legacyAlias,
|
|
84
|
+
llmService,
|
|
85
|
+
model,
|
|
86
|
+
recursionLimit
|
|
87
|
+
} = options;
|
|
88
|
+
const dispatchToolName = buildDispatchToolName(leaderUsername);
|
|
89
|
+
const toolDescription = [
|
|
90
|
+
`Delegate a task from "${leaderUsername}" to the AI Employee "${subAgentEmployee.nickname || subAgentUsername}".`,
|
|
91
|
+
legacyAlias ? "This is a backward-compatible alias for existing skill assignments." : "",
|
|
92
|
+
subAgentEmployee.about ? `Specialist profile: ${subAgentEmployee.about.substring(0, 200)}` : "",
|
|
93
|
+
"The sub-agent will execute the task independently and return its final answer.",
|
|
94
|
+
`For multiple INDEPENDENT sub-tasks, prefer "${dispatchToolName}" to fan-out in one call (up to ${MAX_DISPATCH_CONCURRENCY} run in parallel), or emit several delegate_* calls in the SAME assistant turn so they run concurrently.`
|
|
95
|
+
].filter(Boolean).join(" ");
|
|
96
|
+
return {
|
|
97
|
+
scope: "CUSTOM",
|
|
98
|
+
execution: "backend",
|
|
99
|
+
defaultPermission: "ALLOW",
|
|
100
|
+
silence: false,
|
|
101
|
+
introduction: {
|
|
102
|
+
title: `[${leaderUsername}] ${subAgentEmployee.nickname || subAgentUsername}${legacyAlias ? " (legacy)" : ""}`,
|
|
103
|
+
about: toolDescription
|
|
104
|
+
},
|
|
105
|
+
definition: {
|
|
106
|
+
name: toolName,
|
|
107
|
+
description: toolDescription,
|
|
108
|
+
schema: import_zod.z.object({
|
|
109
|
+
task: import_zod.z.string().describe("The detailed task description for the sub-agent to execute."),
|
|
110
|
+
context: import_zod.z.string().optional().describe("Optional additional context to help the sub-agent understand the task better.")
|
|
111
|
+
})
|
|
112
|
+
},
|
|
113
|
+
invoke: async (ctx, args, id) => {
|
|
114
|
+
const callingEmployee = await resolveCallingEmployee(ctx, plugin);
|
|
115
|
+
if (!callingEmployee) {
|
|
116
|
+
await logDelegation(ctx, plugin, {
|
|
117
|
+
leaderUsername,
|
|
118
|
+
subAgentUsername,
|
|
119
|
+
toolName,
|
|
120
|
+
task: args.task,
|
|
121
|
+
context: args.context,
|
|
122
|
+
result: "",
|
|
123
|
+
status: "error",
|
|
124
|
+
depth: ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0,
|
|
125
|
+
durationMs: 0,
|
|
126
|
+
error: `Cannot determine calling AI employee for delegation tool "${toolName}".`
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
status: "error",
|
|
130
|
+
content: `Cannot determine calling AI employee for "${toolName}". Start the request from an AI Employee conversation so leader scoping can be enforced.`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (callingEmployee && callingEmployee !== leaderUsername) {
|
|
134
|
+
await logDelegation(ctx, plugin, {
|
|
135
|
+
leaderUsername,
|
|
136
|
+
subAgentUsername,
|
|
137
|
+
toolName,
|
|
138
|
+
task: args.task,
|
|
139
|
+
context: args.context,
|
|
140
|
+
result: "",
|
|
141
|
+
status: "error",
|
|
142
|
+
depth: ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0,
|
|
143
|
+
durationMs: 0,
|
|
144
|
+
error: `Employee "${callingEmployee}" is not authorized to use this delegation rule.`
|
|
145
|
+
});
|
|
146
|
+
return {
|
|
147
|
+
status: "error",
|
|
148
|
+
content: `Employee "${callingEmployee}" is not authorized to delegate to "${subAgentUsername}". Configure an orchestration rule first.`
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return invokeDelegateTask(ctx, plugin, {
|
|
152
|
+
leaderUsername,
|
|
153
|
+
subAgentUsername,
|
|
154
|
+
subAgentEmployee,
|
|
155
|
+
task: args.task,
|
|
156
|
+
context: args.context,
|
|
157
|
+
maxDepth: maxDepth ?? 1,
|
|
158
|
+
timeout: timeout ?? 12e4,
|
|
159
|
+
toolCallId: id,
|
|
160
|
+
toolName,
|
|
161
|
+
llmService,
|
|
162
|
+
model,
|
|
163
|
+
recursionLimit
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function formatDispatchResults(results, rulesBySubAgent) {
|
|
169
|
+
var _a;
|
|
170
|
+
const total = results.length;
|
|
171
|
+
const ok = results.filter((r) => r.status === "success").length;
|
|
172
|
+
const lines = [
|
|
173
|
+
`Dispatched ${total} sub-task(s) \u2014 ${ok} succeeded, ${total - ok} failed (max ${MAX_DISPATCH_CONCURRENCY} ran in parallel).`,
|
|
174
|
+
""
|
|
175
|
+
];
|
|
176
|
+
for (const r of results) {
|
|
177
|
+
const employee = (_a = rulesBySubAgent.get(r.subAgent)) == null ? void 0 : _a.employee;
|
|
178
|
+
const displayName = (employee == null ? void 0 : employee.nickname) || r.subAgent;
|
|
179
|
+
const dur = `${(r.durationMs / 1e3).toFixed(1)}s`;
|
|
180
|
+
lines.push(`--- [${r.index + 1}] ${displayName} (${r.subAgent}) [${r.status}] (${dur}) ---`);
|
|
181
|
+
lines.push(r.content || "(empty)");
|
|
182
|
+
lines.push("");
|
|
183
|
+
}
|
|
184
|
+
return lines.join("\n").trimEnd();
|
|
185
|
+
}
|
|
186
|
+
function createDispatchToolOptions(plugin, options) {
|
|
187
|
+
const { leaderUsername, rulesBySubAgent } = options;
|
|
188
|
+
const toolName = buildDispatchToolName(leaderUsername);
|
|
189
|
+
const subAgentNames = Array.from(rulesBySubAgent.keys());
|
|
190
|
+
const subAgentList = subAgentNames.map((username) => {
|
|
191
|
+
var _a, _b;
|
|
192
|
+
const entry = rulesBySubAgent.get(username);
|
|
193
|
+
if (!entry) return `- ${username}`;
|
|
194
|
+
const profile = ((_a = entry.employee) == null ? void 0 : _a.about) ? ` \u2014 ${String(entry.employee.about).substring(0, 120)}` : "";
|
|
195
|
+
const display = ((_b = entry.employee) == null ? void 0 : _b.nickname) ? ` (${entry.employee.nickname})` : "";
|
|
196
|
+
return `- ${username}${display}${profile}`;
|
|
197
|
+
}).join("\n");
|
|
198
|
+
const description = [
|
|
199
|
+
`Dispatch multiple tasks from "${leaderUsername}" to its configured sub-agents in one call.`,
|
|
200
|
+
`At most ${MAX_DISPATCH_CONCURRENCY} sub-tasks run in parallel; up to ${MAX_DISPATCH_TASKS} tasks per call.`,
|
|
201
|
+
"Use this when you have already planned independent sub-tasks and want to fan-out, then aggregate the results.",
|
|
202
|
+
`Available sub-agents:
|
|
203
|
+
${subAgentList}`
|
|
204
|
+
].join(" ");
|
|
205
|
+
return {
|
|
206
|
+
scope: "CUSTOM",
|
|
207
|
+
execution: "backend",
|
|
208
|
+
defaultPermission: "ALLOW",
|
|
209
|
+
silence: false,
|
|
210
|
+
introduction: {
|
|
211
|
+
title: `[${leaderUsername}] Dispatch sub-agents`,
|
|
212
|
+
about: description
|
|
213
|
+
},
|
|
214
|
+
definition: {
|
|
215
|
+
name: toolName,
|
|
216
|
+
description,
|
|
217
|
+
schema: import_zod.z.object({
|
|
218
|
+
tasks: import_zod.z.array(
|
|
219
|
+
import_zod.z.object({
|
|
220
|
+
subAgent: import_zod.z.enum(subAgentNames).describe("Username of the sub-agent that should execute this task."),
|
|
221
|
+
task: import_zod.z.string().describe("Detailed task description for the sub-agent."),
|
|
222
|
+
context: import_zod.z.string().optional().describe("Optional additional context for the sub-agent.")
|
|
223
|
+
})
|
|
224
|
+
).min(1).max(MAX_DISPATCH_TASKS).describe(`List of sub-tasks to dispatch concurrently. Up to ${MAX_DISPATCH_CONCURRENCY} run in parallel.`)
|
|
225
|
+
})
|
|
226
|
+
},
|
|
227
|
+
invoke: async (ctx, args, id) => {
|
|
228
|
+
var _a;
|
|
229
|
+
const callingEmployee = await resolveCallingEmployee(ctx, plugin);
|
|
230
|
+
if (!callingEmployee) {
|
|
231
|
+
const distinctSubs = Array.from(new Set((args.tasks ?? []).map((t) => t.subAgent).filter(Boolean)));
|
|
232
|
+
const reportedSub = distinctSubs.length === 1 ? distinctSubs[0] : "(multiple)";
|
|
233
|
+
await logDelegation(ctx, plugin, {
|
|
234
|
+
leaderUsername,
|
|
235
|
+
subAgentUsername: reportedSub,
|
|
236
|
+
toolName,
|
|
237
|
+
task: truncateText(args.tasks ?? [], 2e3),
|
|
238
|
+
result: "",
|
|
239
|
+
status: "error",
|
|
240
|
+
depth: ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0,
|
|
241
|
+
durationMs: 0,
|
|
242
|
+
error: `Cannot determine calling AI employee for dispatch tool "${toolName}". Targets: ${distinctSubs.join(", ") || "(empty)"}.`
|
|
243
|
+
});
|
|
244
|
+
return {
|
|
245
|
+
status: "error",
|
|
246
|
+
content: `Cannot determine calling AI employee for "${toolName}". Start the request from an AI Employee conversation so leader scoping can be enforced.`
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
if (callingEmployee && callingEmployee !== leaderUsername) {
|
|
250
|
+
const distinctSubs = Array.from(new Set((args.tasks ?? []).map((t) => t.subAgent).filter(Boolean)));
|
|
251
|
+
const reportedSub = distinctSubs.length === 1 ? distinctSubs[0] : "(multiple)";
|
|
252
|
+
await logDelegation(ctx, plugin, {
|
|
253
|
+
leaderUsername,
|
|
254
|
+
subAgentUsername: reportedSub,
|
|
255
|
+
toolName,
|
|
256
|
+
task: truncateText(args.tasks ?? [], 2e3),
|
|
257
|
+
result: "",
|
|
258
|
+
status: "error",
|
|
259
|
+
depth: ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0,
|
|
260
|
+
durationMs: 0,
|
|
261
|
+
error: `Employee "${callingEmployee}" is not authorized to dispatch sub-agents for leader "${leaderUsername}". Targets: ${distinctSubs.join(", ") || "(empty)"}.`
|
|
262
|
+
});
|
|
263
|
+
return {
|
|
264
|
+
status: "error",
|
|
265
|
+
content: `Employee "${callingEmployee}" is not authorized to dispatch sub-agents for leader "${leaderUsername}".`
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const tasks = args.tasks ?? [];
|
|
269
|
+
if (!tasks.length) {
|
|
270
|
+
return {
|
|
271
|
+
status: "error",
|
|
272
|
+
content: "No tasks provided. Pass at least one item in `tasks`."
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
const dispatchRootRunId = ((_a = (0, import_ExecutionSpanService.getOrchestratorTraceContext)(ctx)) == null ? void 0 : _a.rootRunId) || createRootRunId(`${leaderUsername}:dispatch`);
|
|
276
|
+
const results = await runWithConcurrency(tasks, MAX_DISPATCH_CONCURRENCY, async (item, i) => {
|
|
277
|
+
const startedAt = Date.now();
|
|
278
|
+
const entry = rulesBySubAgent.get(item.subAgent);
|
|
279
|
+
if (!entry) {
|
|
280
|
+
return {
|
|
281
|
+
index: i,
|
|
282
|
+
subAgent: item.subAgent,
|
|
283
|
+
status: "error",
|
|
284
|
+
content: `Unknown sub-agent "${item.subAgent}". Allowed: ${subAgentNames.join(", ")}.`,
|
|
285
|
+
durationMs: 0
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const res = await invokeDelegateTask(ctx, plugin, {
|
|
290
|
+
leaderUsername,
|
|
291
|
+
subAgentUsername: item.subAgent,
|
|
292
|
+
subAgentEmployee: entry.employee,
|
|
293
|
+
task: item.task,
|
|
294
|
+
context: item.context,
|
|
295
|
+
maxDepth: entry.rule.maxDepth ?? 1,
|
|
296
|
+
timeout: entry.rule.timeout ?? 12e4,
|
|
297
|
+
toolCallId: `${id}-${i}`,
|
|
298
|
+
toolName,
|
|
299
|
+
llmService: entry.rule.llmService,
|
|
300
|
+
model: entry.rule.model,
|
|
301
|
+
recursionLimit: entry.rule.recursionLimit,
|
|
302
|
+
rootRunId: dispatchRootRunId
|
|
303
|
+
});
|
|
304
|
+
return {
|
|
305
|
+
index: i,
|
|
306
|
+
subAgent: item.subAgent,
|
|
307
|
+
status: res.status,
|
|
308
|
+
content: res.content,
|
|
309
|
+
durationMs: Date.now() - startedAt
|
|
310
|
+
};
|
|
311
|
+
} catch (e) {
|
|
312
|
+
return {
|
|
313
|
+
index: i,
|
|
314
|
+
subAgent: item.subAgent,
|
|
315
|
+
status: "error",
|
|
316
|
+
content: (e == null ? void 0 : e.message) || String(e),
|
|
317
|
+
durationMs: Date.now() - startedAt
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
const successCount = results.filter((r) => r.status === "success").length;
|
|
322
|
+
return {
|
|
323
|
+
status: successCount > 0 ? "success" : "error",
|
|
324
|
+
content: formatDispatchResults(results, rulesBySubAgent)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function captureCtxSnapshot(ctx) {
|
|
330
|
+
var _a, _b, _c, _d;
|
|
331
|
+
let userId;
|
|
332
|
+
try {
|
|
333
|
+
userId = ((_b = (_a = ctx.auth) == null ? void 0 : _a.user) == null ? void 0 : _b.id) || ((_d = (_c = ctx.state) == null ? void 0 : _c.currentUser) == null ? void 0 : _d.id);
|
|
334
|
+
} catch {
|
|
335
|
+
}
|
|
336
|
+
return { userId };
|
|
337
|
+
}
|
|
338
|
+
function normalizeEmployeeUsername(raw) {
|
|
339
|
+
if (!raw) return null;
|
|
340
|
+
if (typeof raw === "string") return raw;
|
|
341
|
+
return raw.username || raw.aiEmployeeUsername || raw.name || null;
|
|
342
|
+
}
|
|
343
|
+
async function resolveCallingEmployee(ctx, plugin) {
|
|
344
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
345
|
+
const values = ((_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) || {};
|
|
346
|
+
const raw = ctx._currentAIEmployee || ((_c = ctx.state) == null ? void 0 : _c.currentAIEmployee) || ((_e = (_d = ctx.runtime) == null ? void 0 : _d.context) == null ? void 0 : _e.currentAIEmployee) || values.aiEmployee;
|
|
347
|
+
const direct = normalizeEmployeeUsername(raw);
|
|
348
|
+
if (direct) return direct;
|
|
349
|
+
const sessionId = values.sessionId || ((_g = (_f = ctx.action) == null ? void 0 : _f.params) == null ? void 0 : _g.sessionId);
|
|
350
|
+
if (!sessionId) return null;
|
|
351
|
+
try {
|
|
352
|
+
const repo = ((_i = (_h = ctx.db) == null ? void 0 : _h.getRepository) == null ? void 0 : _i.call(_h, "aiConversations")) || plugin.db.getRepository("aiConversations");
|
|
353
|
+
const conversation = await repo.findOne({
|
|
354
|
+
filter: { sessionId }
|
|
355
|
+
});
|
|
356
|
+
return normalizeEmployeeUsername((conversation == null ? void 0 : conversation.aiEmployeeUsername) || ((_j = conversation == null ? void 0 : conversation.get) == null ? void 0 : _j.call(conversation, "aiEmployeeUsername")));
|
|
357
|
+
} catch (e) {
|
|
358
|
+
plugin.app.log.warn(`[AgentOrchestrator] Failed to resolve AI employee for session "${sessionId}"`, e);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function truncateText(value, maxLen) {
|
|
363
|
+
const text = typeof value === "string" ? value : value == null ? "" : JSON.stringify(value);
|
|
364
|
+
return text.length > maxLen ? `${text.slice(0, maxLen)}
|
|
365
|
+
...[truncated]` : text;
|
|
366
|
+
}
|
|
367
|
+
function nowIso() {
|
|
368
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
369
|
+
}
|
|
370
|
+
function hasModelSettings(value) {
|
|
371
|
+
return Boolean((value == null ? void 0 : value.llmService) && (value == null ? void 0 : value.model));
|
|
372
|
+
}
|
|
373
|
+
const TOOLS_CACHE_TTL_MS = 3e4;
|
|
374
|
+
let toolsCacheByPlugin = /* @__PURE__ */ new WeakMap();
|
|
375
|
+
let hooksAttached = null;
|
|
376
|
+
function attachInvalidationHooks(plugin) {
|
|
377
|
+
if (!hooksAttached) hooksAttached = /* @__PURE__ */ new WeakSet();
|
|
378
|
+
if (hooksAttached.has(plugin)) return;
|
|
379
|
+
hooksAttached.add(plugin);
|
|
380
|
+
const invalidate = () => {
|
|
381
|
+
toolsCacheByPlugin.delete(plugin);
|
|
382
|
+
registeredDelegateNamesByPlugin.delete(plugin);
|
|
383
|
+
};
|
|
384
|
+
plugin.db.on("orchestratorConfig.afterCreate", invalidate);
|
|
385
|
+
plugin.db.on("orchestratorConfig.afterUpdate", invalidate);
|
|
386
|
+
plugin.db.on("orchestratorConfig.afterDestroy", invalidate);
|
|
387
|
+
plugin.db.on("aiEmployees.afterCreate", invalidate);
|
|
388
|
+
plugin.db.on("aiEmployees.afterUpdate", invalidate);
|
|
389
|
+
plugin.db.on("aiEmployees.afterDestroy", invalidate);
|
|
390
|
+
}
|
|
391
|
+
async function buildDelegateTools(plugin) {
|
|
392
|
+
const configRepo = plugin.db.getRepository("orchestratorConfig");
|
|
393
|
+
if (!configRepo) {
|
|
394
|
+
registeredDelegateNamesByPlugin.set(plugin, /* @__PURE__ */ new Set());
|
|
395
|
+
return [];
|
|
396
|
+
}
|
|
397
|
+
const configs = await configRepo.find({
|
|
398
|
+
filter: { enabled: true }
|
|
399
|
+
});
|
|
400
|
+
if (!(configs == null ? void 0 : configs.length)) {
|
|
401
|
+
registeredDelegateNamesByPlugin.set(plugin, /* @__PURE__ */ new Set());
|
|
402
|
+
return [];
|
|
403
|
+
}
|
|
404
|
+
const employeeCache = /* @__PURE__ */ new Map();
|
|
405
|
+
const tools = [];
|
|
406
|
+
const generatedNames = /* @__PURE__ */ new Map();
|
|
407
|
+
const configsBySubAgent = /* @__PURE__ */ new Map();
|
|
408
|
+
for (const config of configs) {
|
|
409
|
+
const items = configsBySubAgent.get(config.subAgentUsername) || [];
|
|
410
|
+
items.push(config);
|
|
411
|
+
configsBySubAgent.set(config.subAgentUsername, items);
|
|
412
|
+
}
|
|
413
|
+
for (const config of configs) {
|
|
414
|
+
const { leaderUsername, subAgentUsername, maxDepth, timeout, recursionLimit } = config;
|
|
415
|
+
let subAgentEmployee = employeeCache.get(subAgentUsername);
|
|
416
|
+
if (!subAgentEmployee) {
|
|
417
|
+
subAgentEmployee = await plugin.db.getRepository("aiEmployees").findOne({
|
|
418
|
+
filter: { username: subAgentUsername }
|
|
419
|
+
});
|
|
420
|
+
if (subAgentEmployee) {
|
|
421
|
+
employeeCache.set(subAgentUsername, subAgentEmployee);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (!subAgentEmployee) continue;
|
|
425
|
+
const toolName = buildDelegateToolName(leaderUsername, subAgentUsername);
|
|
426
|
+
if (toolName.length > MAX_TOOL_NAME_LENGTH) {
|
|
427
|
+
plugin.app.log.error(
|
|
428
|
+
`[AgentOrchestrator] Tool name "${toolName}" exceeds the ${MAX_TOOL_NAME_LENGTH}-char limit enforced by most LLM providers. Skipping rule (${leaderUsername} \u2192 ${subAgentUsername}). Shorten one of the usernames.`
|
|
429
|
+
);
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
const existing = generatedNames.get(toolName);
|
|
433
|
+
if (existing) {
|
|
434
|
+
const suffix = (0, import_crypto.createHash)("sha1").update(`${leaderUsername}::${subAgentUsername}`).digest("hex").slice(0, 6);
|
|
435
|
+
plugin.app.log.error(
|
|
436
|
+
`[AgentOrchestrator] Tool-name collision: rule (${leaderUsername} \u2192 ${subAgentUsername}) sanitizes to "${toolName}", same as (${existing.leader} \u2192 ${existing.sub}). Skipping duplicate registration. Rename one of the usernames or apply suffix "_${suffix}" manually.`
|
|
437
|
+
);
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
440
|
+
generatedNames.set(toolName, { leader: leaderUsername, sub: subAgentUsername });
|
|
441
|
+
tools.push(
|
|
442
|
+
createDelegateToolOptions(plugin, {
|
|
443
|
+
leaderUsername,
|
|
444
|
+
subAgentUsername,
|
|
445
|
+
subAgentEmployee,
|
|
446
|
+
maxDepth,
|
|
447
|
+
timeout,
|
|
448
|
+
toolName,
|
|
449
|
+
llmService: config.llmService,
|
|
450
|
+
model: config.model,
|
|
451
|
+
recursionLimit
|
|
452
|
+
})
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
for (const [subAgentUsername, items] of configsBySubAgent.entries()) {
|
|
456
|
+
if (items.length !== 1) {
|
|
457
|
+
const leaders = items.map((c) => c.leaderUsername).join(", ");
|
|
458
|
+
plugin.app.log.warn(
|
|
459
|
+
`[AgentOrchestrator] Legacy alias "delegate_to_${sanitizeToolPart(
|
|
460
|
+
subAgentUsername
|
|
461
|
+
)}" is NOT registered for sub-agent "${subAgentUsername}" because it has multiple leaders (${leaders}). Leaders must use the per-rule "delegate_<leader>_to_<sub>" tool name.`
|
|
462
|
+
);
|
|
463
|
+
continue;
|
|
464
|
+
}
|
|
465
|
+
const config = items[0];
|
|
466
|
+
const subAgentEmployee = employeeCache.get(subAgentUsername);
|
|
467
|
+
if (!subAgentEmployee) continue;
|
|
468
|
+
const legacyToolName = `delegate_to_${sanitizeToolPart(subAgentUsername)}`;
|
|
469
|
+
if (legacyToolName.length > MAX_TOOL_NAME_LENGTH) {
|
|
470
|
+
plugin.app.log.error(
|
|
471
|
+
`[AgentOrchestrator] Legacy alias "${legacyToolName}" exceeds the ${MAX_TOOL_NAME_LENGTH}-char limit. Skipping alias for sub-agent "${subAgentUsername}".`
|
|
472
|
+
);
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const aliasExisting = generatedNames.get(legacyToolName);
|
|
476
|
+
if (aliasExisting) {
|
|
477
|
+
plugin.app.log.error(
|
|
478
|
+
`[AgentOrchestrator] Legacy alias "${legacyToolName}" collides with another rule (${aliasExisting.leader} \u2192 ${aliasExisting.sub}). Skipping alias registration.`
|
|
479
|
+
);
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
generatedNames.set(legacyToolName, {
|
|
483
|
+
leader: config.leaderUsername,
|
|
484
|
+
sub: subAgentUsername
|
|
485
|
+
});
|
|
486
|
+
tools.push(
|
|
487
|
+
createDelegateToolOptions(plugin, {
|
|
488
|
+
leaderUsername: config.leaderUsername,
|
|
489
|
+
subAgentUsername,
|
|
490
|
+
subAgentEmployee,
|
|
491
|
+
maxDepth: config.maxDepth,
|
|
492
|
+
timeout: config.timeout,
|
|
493
|
+
toolName: legacyToolName,
|
|
494
|
+
legacyAlias: true,
|
|
495
|
+
llmService: config.llmService,
|
|
496
|
+
model: config.model,
|
|
497
|
+
recursionLimit: config.recursionLimit
|
|
498
|
+
})
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
const rulesByLeader = /* @__PURE__ */ new Map();
|
|
502
|
+
for (const config of configs) {
|
|
503
|
+
const subAgentEmployee = employeeCache.get(config.subAgentUsername);
|
|
504
|
+
if (!subAgentEmployee) continue;
|
|
505
|
+
let bucket = rulesByLeader.get(config.leaderUsername);
|
|
506
|
+
if (!bucket) {
|
|
507
|
+
bucket = /* @__PURE__ */ new Map();
|
|
508
|
+
rulesByLeader.set(config.leaderUsername, bucket);
|
|
509
|
+
}
|
|
510
|
+
bucket.set(config.subAgentUsername, { rule: config, employee: subAgentEmployee });
|
|
511
|
+
}
|
|
512
|
+
for (const [leaderUsername, rulesBySubAgent] of rulesByLeader.entries()) {
|
|
513
|
+
if (!rulesBySubAgent.size) continue;
|
|
514
|
+
const dispatchToolName = buildDispatchToolName(leaderUsername);
|
|
515
|
+
if (dispatchToolName.length > MAX_TOOL_NAME_LENGTH) {
|
|
516
|
+
plugin.app.log.error(
|
|
517
|
+
`[AgentOrchestrator] Dispatch tool "${dispatchToolName}" exceeds the ${MAX_TOOL_NAME_LENGTH}-char limit. Skipping for leader "${leaderUsername}".`
|
|
518
|
+
);
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
const dispatchExisting = generatedNames.get(dispatchToolName);
|
|
522
|
+
if (dispatchExisting) {
|
|
523
|
+
plugin.app.log.error(
|
|
524
|
+
`[AgentOrchestrator] Dispatch tool "${dispatchToolName}" collides with another generated tool (${dispatchExisting.leader} \u2192 ${dispatchExisting.sub}). Skipping dispatch registration for leader "${leaderUsername}".`
|
|
525
|
+
);
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
generatedNames.set(dispatchToolName, { leader: leaderUsername, sub: "(dispatch)" });
|
|
529
|
+
tools.push(createDispatchToolOptions(plugin, { leaderUsername, rulesBySubAgent }));
|
|
530
|
+
}
|
|
531
|
+
registeredDelegateNamesByPlugin.set(plugin, new Set(generatedNames.keys()));
|
|
532
|
+
return tools;
|
|
533
|
+
}
|
|
37
534
|
function createDelegateToolsProvider(plugin) {
|
|
535
|
+
attachInvalidationHooks(plugin);
|
|
38
536
|
return async (register) => {
|
|
39
537
|
try {
|
|
40
|
-
|
|
41
|
-
if (!
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (!(configs == null ? void 0 : configs.length)) return;
|
|
46
|
-
const leadersByTool = /* @__PURE__ */ new Map();
|
|
47
|
-
for (const config of configs) {
|
|
48
|
-
const toolName = `delegate_to_${config.subAgentUsername.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
49
|
-
if (!leadersByTool.has(toolName)) {
|
|
50
|
-
leadersByTool.set(toolName, /* @__PURE__ */ new Set());
|
|
51
|
-
}
|
|
52
|
-
leadersByTool.get(toolName).add(config.leaderUsername);
|
|
538
|
+
let toolsCache = toolsCacheByPlugin.get(plugin);
|
|
539
|
+
if (!toolsCache || toolsCache.expiresAt <= Date.now()) {
|
|
540
|
+
const tools = await buildDelegateTools(plugin);
|
|
541
|
+
toolsCache = { tools, expiresAt: Date.now() + TOOLS_CACHE_TTL_MS };
|
|
542
|
+
toolsCacheByPlugin.set(plugin, toolsCache);
|
|
53
543
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const { leaderUsername, subAgentUsername, maxDepth, timeout } = config;
|
|
57
|
-
if (seenSubAgents.has(subAgentUsername)) continue;
|
|
58
|
-
seenSubAgents.add(subAgentUsername);
|
|
59
|
-
const subAgentEmployee = await plugin.db.getRepository("aiEmployees").findOne({
|
|
60
|
-
filter: { username: subAgentUsername }
|
|
61
|
-
});
|
|
62
|
-
if (!subAgentEmployee) continue;
|
|
63
|
-
const toolName = `delegate_to_${subAgentUsername.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
64
|
-
const toolDescription = [
|
|
65
|
-
`Delegate a task to the AI Employee "${subAgentEmployee.nickname || subAgentUsername}".`,
|
|
66
|
-
subAgentEmployee.about ? `Specialist profile: ${subAgentEmployee.about.substring(0, 200)}` : "",
|
|
67
|
-
"The sub-agent will execute the task independently and return its final answer."
|
|
68
|
-
].filter(Boolean).join(" ");
|
|
69
|
-
const allowedLeaders = leadersByTool.get(toolName);
|
|
70
|
-
register.registerTools({
|
|
71
|
-
scope: "CUSTOM",
|
|
72
|
-
execution: "backend",
|
|
73
|
-
defaultPermission: "ALLOW",
|
|
74
|
-
silence: false,
|
|
75
|
-
introduction: {
|
|
76
|
-
title: `[Sub-Agent] ${subAgentEmployee.nickname || subAgentUsername}`,
|
|
77
|
-
about: toolDescription
|
|
78
|
-
},
|
|
79
|
-
definition: {
|
|
80
|
-
name: toolName,
|
|
81
|
-
description: toolDescription,
|
|
82
|
-
schema: import_zod.z.object({
|
|
83
|
-
task: import_zod.z.string().describe("The detailed task description for the sub-agent to execute."),
|
|
84
|
-
context: import_zod.z.string().optional().describe("Optional additional context to help the sub-agent understand the task better.")
|
|
85
|
-
})
|
|
86
|
-
},
|
|
87
|
-
invoke: async (ctx, args, id) => {
|
|
88
|
-
var _a, _b;
|
|
89
|
-
const callingEmployee = ((_a = ctx._currentAIEmployee) == null ? void 0 : _a.username) || ((_b = ctx.state) == null ? void 0 : _b.currentAIEmployee);
|
|
90
|
-
if (callingEmployee && !allowedLeaders.has(callingEmployee)) {
|
|
91
|
-
return {
|
|
92
|
-
status: "error",
|
|
93
|
-
content: `Employee "${callingEmployee}" is not authorized to delegate to "${subAgentUsername}". Configure an orchestration rule first.`
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
return invokeDelegateTask(ctx, plugin, {
|
|
97
|
-
leaderUsername: callingEmployee || Array.from(allowedLeaders)[0] || "",
|
|
98
|
-
subAgentUsername,
|
|
99
|
-
subAgentEmployee,
|
|
100
|
-
task: args.task,
|
|
101
|
-
context: args.context,
|
|
102
|
-
maxDepth: maxDepth ?? 1,
|
|
103
|
-
timeout: timeout ?? 12e4,
|
|
104
|
-
toolCallId: id
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
544
|
+
if (toolsCache.tools.length) {
|
|
545
|
+
register.registerTools(toolsCache.tools);
|
|
108
546
|
}
|
|
109
547
|
} catch (e) {
|
|
110
548
|
plugin.app.log.error("[AgentOrchestrator] Failed to register delegate tools", e);
|
|
111
549
|
}
|
|
112
550
|
};
|
|
113
551
|
}
|
|
552
|
+
function invalidateDelegateToolsCache() {
|
|
553
|
+
toolsCacheByPlugin = /* @__PURE__ */ new WeakMap();
|
|
554
|
+
registeredDelegateNamesByPlugin = /* @__PURE__ */ new WeakMap();
|
|
555
|
+
}
|
|
114
556
|
async function invokeDelegateTask(ctx, plugin, options) {
|
|
115
|
-
var _a, _b;
|
|
116
|
-
const {
|
|
557
|
+
var _a, _b, _c, _d, _e;
|
|
558
|
+
const {
|
|
559
|
+
leaderUsername,
|
|
560
|
+
subAgentUsername,
|
|
561
|
+
subAgentEmployee,
|
|
562
|
+
task,
|
|
563
|
+
context,
|
|
564
|
+
maxDepth,
|
|
565
|
+
timeout,
|
|
566
|
+
toolCallId,
|
|
567
|
+
toolName,
|
|
568
|
+
llmService,
|
|
569
|
+
model,
|
|
570
|
+
recursionLimit,
|
|
571
|
+
rootRunId: providedRootRunId,
|
|
572
|
+
parentSpanId: providedParentSpanId
|
|
573
|
+
} = options;
|
|
574
|
+
const ctxSnapshot = captureCtxSnapshot(ctx);
|
|
117
575
|
const currentDepth = ctx[ORCHESTRATOR_DEPTH_KEY] ?? 0;
|
|
118
576
|
if (currentDepth >= maxDepth) {
|
|
577
|
+
await logDelegation(ctx, plugin, {
|
|
578
|
+
leaderUsername,
|
|
579
|
+
subAgentUsername,
|
|
580
|
+
toolName,
|
|
581
|
+
task,
|
|
582
|
+
context,
|
|
583
|
+
result: "",
|
|
584
|
+
status: "error",
|
|
585
|
+
depth: currentDepth,
|
|
586
|
+
durationMs: 0,
|
|
587
|
+
error: `Delegation depth limit reached (${currentDepth}/${maxDepth}).`,
|
|
588
|
+
snapshot: ctxSnapshot
|
|
589
|
+
});
|
|
119
590
|
return {
|
|
120
591
|
status: "error",
|
|
121
592
|
content: `Delegation depth limit reached (${currentDepth}/${maxDepth}). Sub-agent "${subAgentUsername}" cannot delegate further.`
|
|
122
593
|
};
|
|
123
594
|
}
|
|
595
|
+
const spanService = new import_ExecutionSpanService.ExecutionSpanService(plugin);
|
|
596
|
+
const upstreamTraceContext = (0, import_ExecutionSpanService.getOrchestratorTraceContext)(ctx);
|
|
597
|
+
const rootRunId = providedRootRunId || (upstreamTraceContext == null ? void 0 : upstreamTraceContext.rootRunId) || createRootRunId(`${leaderUsername}:${subAgentUsername}`);
|
|
598
|
+
const parentSpanId = providedParentSpanId || (upstreamTraceContext == null ? void 0 : upstreamTraceContext.spanId) || (upstreamTraceContext == null ? void 0 : upstreamTraceContext.parentSpanId);
|
|
124
599
|
const startTime = Date.now();
|
|
600
|
+
const trace = [
|
|
601
|
+
{
|
|
602
|
+
type: "start",
|
|
603
|
+
at: nowIso(),
|
|
604
|
+
title: `Delegation started: ${leaderUsername} -> ${subAgentUsername}`,
|
|
605
|
+
content: task
|
|
606
|
+
}
|
|
607
|
+
];
|
|
608
|
+
const executionSpan = await spanService.create({
|
|
609
|
+
rootRunId,
|
|
610
|
+
parentSpanId,
|
|
611
|
+
type: "sub_agent",
|
|
612
|
+
status: "running",
|
|
613
|
+
leaderUsername,
|
|
614
|
+
employeeUsername: subAgentUsername,
|
|
615
|
+
title: `Delegation: ${leaderUsername} -> ${subAgentUsername}`,
|
|
616
|
+
input: { task, context },
|
|
617
|
+
metadata: {
|
|
618
|
+
depth: currentDepth,
|
|
619
|
+
maxDepth,
|
|
620
|
+
toolName,
|
|
621
|
+
recursionLimit,
|
|
622
|
+
llmOverride: llmService && model ? { llmService, model } : void 0
|
|
623
|
+
},
|
|
624
|
+
userId: ctxSnapshot.userId
|
|
625
|
+
});
|
|
626
|
+
const executionSpanId = (executionSpan == null ? void 0 : executionSpan.id) ? String(executionSpan.id) : void 0;
|
|
627
|
+
const logRecord = await logDelegation(ctx, plugin, {
|
|
628
|
+
leaderUsername,
|
|
629
|
+
subAgentUsername,
|
|
630
|
+
toolName,
|
|
631
|
+
task,
|
|
632
|
+
context,
|
|
633
|
+
result: "",
|
|
634
|
+
status: "running",
|
|
635
|
+
depth: currentDepth,
|
|
636
|
+
durationMs: 0,
|
|
637
|
+
trace,
|
|
638
|
+
snapshot: ctxSnapshot
|
|
639
|
+
});
|
|
640
|
+
if (executionSpanId && (logRecord == null ? void 0 : logRecord.id)) {
|
|
641
|
+
await spanService.update(executionSpanId, { orchestratorLogId: logRecord.id });
|
|
642
|
+
}
|
|
125
643
|
try {
|
|
126
644
|
const aiPlugin = ctx.app.pm.get("ai");
|
|
127
645
|
if (!aiPlugin) {
|
|
128
646
|
throw new Error("Plugin AI is not installed or enabled");
|
|
129
647
|
}
|
|
130
|
-
|
|
131
|
-
if (
|
|
132
|
-
|
|
648
|
+
let modelSettings = hasModelSettings(subAgentEmployee.modelSettings) ? subAgentEmployee.modelSettings : void 0;
|
|
649
|
+
if (llmService && model) {
|
|
650
|
+
modelSettings = { llmService, model };
|
|
651
|
+
}
|
|
652
|
+
if (!hasModelSettings(modelSettings)) {
|
|
653
|
+
const leaderEmployee = await plugin.db.getRepository("aiEmployees").findOne({
|
|
654
|
+
filter: { username: leaderUsername }
|
|
655
|
+
});
|
|
656
|
+
const dynamicModel = (_c = (_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) == null ? void 0 : _c.model;
|
|
657
|
+
modelSettings = hasModelSettings(leaderEmployee == null ? void 0 : leaderEmployee.modelSettings) ? leaderEmployee.modelSettings : hasModelSettings(dynamicModel) ? dynamicModel : void 0;
|
|
658
|
+
if (!hasModelSettings(modelSettings)) {
|
|
659
|
+
throw new Error(
|
|
660
|
+
`Sub-agent "${subAgentUsername}" has no LLM model configured (and leader fallback failed). Please configure a model in the Orchestrator Config or AI Employee settings.`
|
|
661
|
+
);
|
|
662
|
+
}
|
|
133
663
|
}
|
|
134
664
|
const { provider } = await aiPlugin.aiManager.getLLMService({
|
|
135
665
|
llmService: modelSettings.llmService,
|
|
@@ -138,27 +668,100 @@ async function invokeDelegateTask(ctx, plugin, options) {
|
|
|
138
668
|
const chatModel = provider.createModel();
|
|
139
669
|
const coreToolsManager = ctx.app.aiManager.toolsManager;
|
|
140
670
|
const allTools = await coreToolsManager.listTools();
|
|
141
|
-
const employeeSkills = (((
|
|
671
|
+
const employeeSkills = (((_d = subAgentEmployee.skillSettings) == null ? void 0 : _d.skills) ?? []).map(
|
|
672
|
+
(s) => typeof s === "string" ? { name: s, autoCall: false } : { name: s == null ? void 0 : s.name, autoCall: (s == null ? void 0 : s.autoCall) === true }
|
|
673
|
+
).filter((s) => Boolean(s.name));
|
|
674
|
+
const employeeSkillMap = new Map(employeeSkills.map((skill) => [skill.name, skill]));
|
|
142
675
|
const langchainTools = [];
|
|
143
676
|
for (const toolEntry of allTools) {
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
146
|
-
|
|
677
|
+
const entryName = toolEntry.definition.name;
|
|
678
|
+
if (!entryName) continue;
|
|
679
|
+
const employeeSkill = employeeSkillMap.get(entryName);
|
|
680
|
+
if (!employeeSkill || isDelegateToolName(plugin, entryName) || employeeSkill.autoCall !== true || toolEntry.defaultPermission !== "ALLOW") {
|
|
147
681
|
continue;
|
|
148
682
|
}
|
|
149
683
|
langchainTools.push(
|
|
150
684
|
new import_tools.DynamicStructuredTool({
|
|
151
|
-
name:
|
|
152
|
-
description: toolEntry.definition.description ||
|
|
685
|
+
name: entryName.replace(/[^a-zA-Z0-9_-]/g, "_"),
|
|
686
|
+
description: toolEntry.definition.description || entryName,
|
|
153
687
|
schema: toolEntry.definition.schema || import_zod.z.object({}),
|
|
154
688
|
func: async (toolArgs) => {
|
|
689
|
+
var _a2;
|
|
155
690
|
const invokeCtx = Object.create(ctx);
|
|
156
691
|
invokeCtx[ORCHESTRATOR_DEPTH_KEY] = currentDepth + 1;
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
692
|
+
const toolStartedAt = Date.now();
|
|
693
|
+
const isSkillHubTool = entryName === "skill_hub_execute" || entryName.startsWith("skill_hub_");
|
|
694
|
+
const toolSpan = await spanService.create({
|
|
695
|
+
rootRunId,
|
|
696
|
+
parentSpanId: executionSpanId,
|
|
697
|
+
type: isSkillHubTool ? "skill" : "tool",
|
|
698
|
+
status: "running",
|
|
699
|
+
leaderUsername,
|
|
700
|
+
employeeUsername: subAgentUsername,
|
|
701
|
+
toolName: toolEntry.definition.name,
|
|
702
|
+
title: isSkillHubTool ? `Skill: ${toolEntry.definition.name}` : `Tool: ${toolEntry.definition.name}`,
|
|
703
|
+
input: toolArgs,
|
|
704
|
+
metadata: {
|
|
705
|
+
depth: currentDepth + 1,
|
|
706
|
+
toolCallId: `orch-${toolCallId}`,
|
|
707
|
+
defaultPermission: toolEntry.defaultPermission
|
|
708
|
+
},
|
|
709
|
+
userId: ctxSnapshot.userId
|
|
710
|
+
});
|
|
711
|
+
const toolSpanId = (toolSpan == null ? void 0 : toolSpan.id) ? String(toolSpan.id) : void 0;
|
|
712
|
+
(0, import_ExecutionSpanService.setOrchestratorTraceContext)(invokeCtx, {
|
|
713
|
+
rootRunId,
|
|
714
|
+
spanId: toolSpanId,
|
|
715
|
+
parentSpanId: executionSpanId,
|
|
716
|
+
toolCallId: `orch-${toolCallId}`,
|
|
717
|
+
leaderUsername,
|
|
718
|
+
employeeUsername: subAgentUsername,
|
|
719
|
+
toolName: toolEntry.definition.name
|
|
720
|
+
});
|
|
721
|
+
trace.push({
|
|
722
|
+
type: "tool_call",
|
|
723
|
+
at: nowIso(),
|
|
724
|
+
title: `Calling tool: ${toolEntry.definition.name}`,
|
|
725
|
+
toolName: toolEntry.definition.name,
|
|
726
|
+
args: toolArgs
|
|
727
|
+
});
|
|
728
|
+
try {
|
|
729
|
+
const res = await toolEntry.invoke(invokeCtx, toolArgs, `orch-${toolCallId}`);
|
|
730
|
+
const output = truncateText((res == null ? void 0 : res.content) ?? (res == null ? void 0 : res.result) ?? res, 5e4);
|
|
731
|
+
trace.push({
|
|
732
|
+
type: "tool_result",
|
|
733
|
+
at: nowIso(),
|
|
734
|
+
title: `Tool finished: ${toolEntry.definition.name}`,
|
|
735
|
+
toolName: toolEntry.definition.name,
|
|
736
|
+
status: (res == null ? void 0 : res.status) || "success",
|
|
737
|
+
content: truncateText(output, 2e3)
|
|
738
|
+
});
|
|
739
|
+
if ((res == null ? void 0 : res.status) === "error") {
|
|
740
|
+
await spanService.finish(toolSpanId, "error", toolStartedAt, {
|
|
741
|
+
output,
|
|
742
|
+
error: truncateText(res.content || output, 1e4)
|
|
743
|
+
});
|
|
744
|
+
throw new Error(`Tool <${toolEntry.definition.name}> failed: ${res.content}`);
|
|
745
|
+
}
|
|
746
|
+
await spanService.finish(toolSpanId, "success", toolStartedAt, {
|
|
747
|
+
output,
|
|
748
|
+
skillExecutionId: ((_a2 = res == null ? void 0 : res.result) == null ? void 0 : _a2.execId) || (res == null ? void 0 : res.execId)
|
|
749
|
+
});
|
|
750
|
+
return typeof (res == null ? void 0 : res.content) === "string" ? res.content : JSON.stringify(res);
|
|
751
|
+
} catch (e) {
|
|
752
|
+
trace.push({
|
|
753
|
+
type: "tool_error",
|
|
754
|
+
at: nowIso(),
|
|
755
|
+
title: `Tool failed: ${toolEntry.definition.name}`,
|
|
756
|
+
toolName: toolEntry.definition.name,
|
|
757
|
+
status: "error",
|
|
758
|
+
content: e.message
|
|
759
|
+
});
|
|
760
|
+
await spanService.finish(toolSpanId, "error", toolStartedAt, {
|
|
761
|
+
error: truncateText(e.message, 1e4)
|
|
762
|
+
});
|
|
763
|
+
throw e;
|
|
160
764
|
}
|
|
161
|
-
return typeof (res == null ? void 0 : res.content) === "string" ? res.content : JSON.stringify(res);
|
|
162
765
|
}
|
|
163
766
|
})
|
|
164
767
|
);
|
|
@@ -168,25 +771,59 @@ async function invokeDelegateTask(ctx, plugin, options) {
|
|
|
168
771
|
llm: chatModel,
|
|
169
772
|
tools: langchainTools
|
|
170
773
|
});
|
|
171
|
-
const systemPrompt = ((
|
|
774
|
+
const systemPrompt = ((_e = subAgentEmployee.chatSettings) == null ? void 0 : _e.systemPrompt) || subAgentEmployee.bio || `You are an AI assistant named "${subAgentEmployee.nickname || subAgentUsername}". ${subAgentEmployee.about || ""}`;
|
|
172
775
|
const combinedTask = context ? `Task: ${task}
|
|
173
776
|
|
|
174
777
|
Context Provided:
|
|
175
778
|
${context}` : `Task: ${task}`;
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
779
|
+
const effectiveRecursionLimit = Number.isFinite(recursionLimit) && recursionLimit > 0 ? recursionLimit : 50;
|
|
780
|
+
const invokePromise = executeAgent(
|
|
781
|
+
executor,
|
|
782
|
+
systemPrompt,
|
|
783
|
+
combinedTask,
|
|
784
|
+
abortController.signal,
|
|
785
|
+
effectiveRecursionLimit
|
|
786
|
+
);
|
|
787
|
+
const timeoutHandle = createTimeout(timeout, subAgentUsername, abortController);
|
|
788
|
+
let result;
|
|
789
|
+
try {
|
|
790
|
+
result = await Promise.race([invokePromise, timeoutHandle.promise]);
|
|
791
|
+
} finally {
|
|
792
|
+
timeoutHandle.cancel();
|
|
793
|
+
}
|
|
794
|
+
const content = result.content || "Sub-agent completed the task but produced no output.";
|
|
795
|
+
trace.push({
|
|
796
|
+
type: "finish",
|
|
797
|
+
at: nowIso(),
|
|
798
|
+
title: `Delegation finished: ${subAgentUsername}`,
|
|
799
|
+
status: "success",
|
|
800
|
+
content: truncateText(content, 2e3)
|
|
801
|
+
});
|
|
182
802
|
await logDelegation(ctx, plugin, {
|
|
803
|
+
id: logRecord == null ? void 0 : logRecord.id,
|
|
183
804
|
leaderUsername,
|
|
184
805
|
subAgentUsername,
|
|
806
|
+
toolName,
|
|
185
807
|
task,
|
|
808
|
+
context,
|
|
186
809
|
result: content,
|
|
187
810
|
status: "success",
|
|
188
811
|
depth: currentDepth,
|
|
189
|
-
durationMs: Date.now() - startTime
|
|
812
|
+
durationMs: Date.now() - startTime,
|
|
813
|
+
trace,
|
|
814
|
+
messages: result.messages,
|
|
815
|
+
snapshot: ctxSnapshot
|
|
816
|
+
});
|
|
817
|
+
await spanService.finish(executionSpanId, "success", startTime, {
|
|
818
|
+
output: content,
|
|
819
|
+
metadata: {
|
|
820
|
+
depth: currentDepth,
|
|
821
|
+
maxDepth,
|
|
822
|
+
toolName,
|
|
823
|
+
recursionLimit,
|
|
824
|
+
messages: result.messages,
|
|
825
|
+
traceCount: trace.length
|
|
826
|
+
}
|
|
190
827
|
});
|
|
191
828
|
return {
|
|
192
829
|
status: "success",
|
|
@@ -195,15 +832,40 @@ ${context}` : `Task: ${task}`;
|
|
|
195
832
|
} catch (e) {
|
|
196
833
|
plugin.app.log.error(`[AgentOrchestrator] Sub-agent ${subAgentUsername} failed`, e);
|
|
197
834
|
await logDelegation(ctx, plugin, {
|
|
835
|
+
id: logRecord == null ? void 0 : logRecord.id,
|
|
198
836
|
leaderUsername,
|
|
199
837
|
subAgentUsername,
|
|
838
|
+
toolName,
|
|
200
839
|
task,
|
|
840
|
+
context,
|
|
201
841
|
result: "",
|
|
202
842
|
status: "error",
|
|
203
843
|
depth: currentDepth,
|
|
204
844
|
durationMs: Date.now() - startTime,
|
|
205
|
-
error: e.message
|
|
206
|
-
|
|
845
|
+
error: e.message,
|
|
846
|
+
trace: [
|
|
847
|
+
...trace,
|
|
848
|
+
{
|
|
849
|
+
type: "error",
|
|
850
|
+
at: nowIso(),
|
|
851
|
+
title: `Delegation failed: ${subAgentUsername}`,
|
|
852
|
+
status: "error",
|
|
853
|
+
content: e.message
|
|
854
|
+
}
|
|
855
|
+
],
|
|
856
|
+
snapshot: ctxSnapshot
|
|
857
|
+
}).catch((logErr) => {
|
|
858
|
+
plugin.app.log.warn("[AgentOrchestrator] Failed to save error log for delegation", logErr);
|
|
859
|
+
});
|
|
860
|
+
await spanService.finish(executionSpanId, "error", startTime, {
|
|
861
|
+
error: truncateText(e.message, 1e4),
|
|
862
|
+
metadata: {
|
|
863
|
+
depth: currentDepth,
|
|
864
|
+
maxDepth,
|
|
865
|
+
toolName,
|
|
866
|
+
recursionLimit,
|
|
867
|
+
traceCount: trace.length + 1
|
|
868
|
+
}
|
|
207
869
|
});
|
|
208
870
|
return {
|
|
209
871
|
status: "error",
|
|
@@ -212,30 +874,56 @@ ${context}` : `Task: ${task}`;
|
|
|
212
874
|
}
|
|
213
875
|
}
|
|
214
876
|
async function logDelegation(ctx, plugin, data) {
|
|
215
|
-
var _a, _b, _c, _d;
|
|
877
|
+
var _a, _b, _c, _d, _e, _f;
|
|
216
878
|
try {
|
|
217
879
|
const logsRepo = plugin.db.getRepository("orchestratorLogs");
|
|
218
|
-
if (!logsRepo)
|
|
219
|
-
|
|
880
|
+
if (!logsRepo) {
|
|
881
|
+
plugin.app.log.warn("[AgentOrchestrator] orchestratorLogs repository not found \u2014 skipping log");
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
let userId = (_a = data.snapshot) == null ? void 0 : _a.userId;
|
|
885
|
+
if (userId == null) {
|
|
886
|
+
try {
|
|
887
|
+
userId = ((_c = (_b = ctx.auth) == null ? void 0 : _b.user) == null ? void 0 : _c.id) || ((_e = (_d = ctx.state) == null ? void 0 : _d.currentUser) == null ? void 0 : _e.id);
|
|
888
|
+
} catch {
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
const values = {
|
|
892
|
+
leaderUsername: data.leaderUsername,
|
|
893
|
+
subAgentUsername: data.subAgentUsername,
|
|
894
|
+
toolName: data.toolName,
|
|
895
|
+
task: truncateText(data.task, 1e4),
|
|
896
|
+
context: truncateText(data.context || "", 1e4),
|
|
897
|
+
result: truncateText(data.result || "", 5e4),
|
|
898
|
+
status: data.status,
|
|
899
|
+
depth: data.depth,
|
|
900
|
+
durationMs: data.durationMs,
|
|
901
|
+
error: truncateText(data.error || "", 1e4),
|
|
902
|
+
trace: data.trace || [],
|
|
903
|
+
messages: data.messages || [],
|
|
904
|
+
userId,
|
|
905
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
906
|
+
};
|
|
907
|
+
if (data.id) {
|
|
908
|
+
await logsRepo.update({
|
|
909
|
+
filterByTk: data.id,
|
|
910
|
+
values
|
|
911
|
+
});
|
|
912
|
+
return { id: data.id };
|
|
913
|
+
}
|
|
914
|
+
const record = await logsRepo.create({
|
|
220
915
|
values: {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
toolName: `delegate_to_${data.subAgentUsername}`,
|
|
224
|
-
task: (data.task || "").substring(0, 2e3),
|
|
225
|
-
result: (data.result || "").substring(0, 5e3),
|
|
226
|
-
status: data.status,
|
|
227
|
-
depth: data.depth,
|
|
228
|
-
durationMs: data.durationMs,
|
|
229
|
-
error: (data.error || "").substring(0, 2e3),
|
|
230
|
-
userId: ((_b = (_a = ctx.auth) == null ? void 0 : _a.user) == null ? void 0 : _b.id) || ((_d = (_c = ctx.state) == null ? void 0 : _c.currentUser) == null ? void 0 : _d.id)
|
|
916
|
+
...values,
|
|
917
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
231
918
|
}
|
|
232
919
|
});
|
|
920
|
+
return ((_f = record == null ? void 0 : record.toJSON) == null ? void 0 : _f.call(record)) || record;
|
|
233
921
|
} catch (e) {
|
|
234
922
|
plugin.app.log.warn("[AgentOrchestrator] Failed to log delegation event", e);
|
|
235
923
|
}
|
|
236
924
|
}
|
|
237
|
-
async function executeAgent(executor, systemPrompt, task, signal) {
|
|
238
|
-
const config = { recursionLimit
|
|
925
|
+
async function executeAgent(executor, systemPrompt, task, signal, recursionLimit = 50) {
|
|
926
|
+
const config = { recursionLimit };
|
|
239
927
|
if (signal) {
|
|
240
928
|
config.signal = signal;
|
|
241
929
|
}
|
|
@@ -248,25 +936,50 @@ async function executeAgent(executor, systemPrompt, task, signal) {
|
|
|
248
936
|
const messages = (finalState == null ? void 0 : finalState.messages) || [];
|
|
249
937
|
const lastAIMessage = [...messages].reverse().find((m) => m.getType() === "ai");
|
|
250
938
|
if (!lastAIMessage || !lastAIMessage.content) {
|
|
251
|
-
return "";
|
|
939
|
+
return { content: "", messages: serializeMessages(messages) };
|
|
252
940
|
}
|
|
941
|
+
let content = "";
|
|
253
942
|
if (typeof lastAIMessage.content === "string") {
|
|
254
|
-
|
|
943
|
+
content = lastAIMessage.content;
|
|
944
|
+
} else if (Array.isArray(lastAIMessage.content)) {
|
|
945
|
+
content = lastAIMessage.content.map((c) => c.text || JSON.stringify(c)).join("\n");
|
|
946
|
+
} else {
|
|
947
|
+
content = String(lastAIMessage.content);
|
|
255
948
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return
|
|
949
|
+
return { content, messages: serializeMessages(messages) };
|
|
950
|
+
}
|
|
951
|
+
function serializeMessages(messages) {
|
|
952
|
+
return (messages || []).map((message, index) => {
|
|
953
|
+
const type = typeof message.getType === "function" ? message.getType() : message.type;
|
|
954
|
+
return {
|
|
955
|
+
index,
|
|
956
|
+
type,
|
|
957
|
+
name: message.name,
|
|
958
|
+
content: truncateText(message.content, 1e4),
|
|
959
|
+
toolCalls: message.tool_calls || message.toolCalls || [],
|
|
960
|
+
toolCallId: message.tool_call_id,
|
|
961
|
+
additionalKwargs: message.additional_kwargs,
|
|
962
|
+
responseMetadata: message.response_metadata
|
|
963
|
+
};
|
|
964
|
+
});
|
|
260
965
|
}
|
|
261
966
|
function createTimeout(ms, agentName, abortController) {
|
|
262
|
-
|
|
263
|
-
|
|
967
|
+
let timer;
|
|
968
|
+
const promise = new Promise((_resolve, reject) => {
|
|
969
|
+
timer = setTimeout(() => {
|
|
264
970
|
abortController == null ? void 0 : abortController.abort();
|
|
265
971
|
reject(new Error(`Sub-agent "${agentName}" timed out after ${ms / 1e3}s`));
|
|
266
|
-
}, ms)
|
|
267
|
-
);
|
|
972
|
+
}, ms);
|
|
973
|
+
});
|
|
974
|
+
return {
|
|
975
|
+
promise,
|
|
976
|
+
cancel: () => {
|
|
977
|
+
if (timer) clearTimeout(timer);
|
|
978
|
+
}
|
|
979
|
+
};
|
|
268
980
|
}
|
|
269
981
|
// Annotate the CommonJS export names for ESM import in node:
|
|
270
982
|
0 && (module.exports = {
|
|
271
|
-
createDelegateToolsProvider
|
|
983
|
+
createDelegateToolsProvider,
|
|
984
|
+
invalidateDelegateToolsCache
|
|
272
985
|
});
|