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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Migration } from '@nocobase/server';
|
|
2
|
+
|
|
3
|
+
export default class AddOrchestratorTraceFieldsToSkillExecutions extends Migration {
|
|
4
|
+
on = 'afterLoad';
|
|
5
|
+
appVersion = '>=0.1.0';
|
|
6
|
+
|
|
7
|
+
async up() {
|
|
8
|
+
const queryInterface = this.db.sequelize.getQueryInterface();
|
|
9
|
+
const tablePrefix = this.db.options.tablePrefix || '';
|
|
10
|
+
const tableName = `${tablePrefix}skillExecutions`;
|
|
11
|
+
const tableExists = await queryInterface.tableExists(tableName).catch(() => false);
|
|
12
|
+
if (!tableExists) return;
|
|
13
|
+
|
|
14
|
+
const tableDesc = await queryInterface.describeTable(tableName);
|
|
15
|
+
const addIfMissing = async (name: string) => {
|
|
16
|
+
if (tableDesc[name]) return;
|
|
17
|
+
await queryInterface.addColumn(tableName, name, {
|
|
18
|
+
type: 'VARCHAR(100)',
|
|
19
|
+
allowNull: true,
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
await addIfMissing('orchestratorRootRunId');
|
|
24
|
+
await addIfMissing('orchestratorSpanId');
|
|
25
|
+
await addIfMissing('orchestratorParentSpanId');
|
|
26
|
+
await addIfMissing('orchestratorToolCallId');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async down() {
|
|
30
|
+
// No rollback: keeping nullable trace-link columns is safe.
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/server/plugin.ts
CHANGED
|
@@ -2,20 +2,33 @@ import { Plugin } from '@nocobase/server';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { createDelegateToolsProvider } from './tools/delegate-task';
|
|
4
4
|
import { registerTracingResource } from './resources/tracing';
|
|
5
|
+
import SkillHubSubFeature from './skill-hub/plugin';
|
|
5
6
|
|
|
6
7
|
export class PluginAgentOrchestratorServer extends Plugin {
|
|
7
|
-
|
|
8
|
+
skillHub: SkillHubSubFeature;
|
|
9
|
+
|
|
10
|
+
async afterAdd() {
|
|
11
|
+
this.skillHub = new SkillHubSubFeature(this);
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
async beforeLoad() {
|
|
10
15
|
// Import collection definitions
|
|
11
16
|
this.db.import({ directory: path.resolve(__dirname, 'collections') });
|
|
17
|
+
|
|
18
|
+
this.db.addMigrations({
|
|
19
|
+
namespace: this.name,
|
|
20
|
+
directory: path.resolve(__dirname, 'migrations'),
|
|
21
|
+
context: { plugin: this },
|
|
22
|
+
});
|
|
12
23
|
}
|
|
13
24
|
|
|
14
25
|
async load() {
|
|
26
|
+
await this.skillHub.load();
|
|
27
|
+
|
|
15
28
|
// --- ACL ---
|
|
16
29
|
this.app.acl.registerSnippet({
|
|
17
30
|
name: `pm.${this.name}`,
|
|
18
|
-
actions: ['orchestratorConfig:*'],
|
|
31
|
+
actions: ['orchestratorConfig:*', 'orchestratorTracing:*', 'agentExecutionSpans:*', 'skillDefinitions:*', 'skillExecutions:*', 'skillHub:*', 'skillWorkerConfigs:*'],
|
|
19
32
|
});
|
|
20
33
|
|
|
21
34
|
// --- Register Dynamic Tools ---
|
|
@@ -29,18 +42,53 @@ export class PluginAgentOrchestratorServer extends Plugin {
|
|
|
29
42
|
// Custom read-only resource for the Swarm Tracing admin page.
|
|
30
43
|
registerTracingResource(this);
|
|
31
44
|
|
|
45
|
+
// --- Log Retention ---
|
|
46
|
+
// Daily prune of orchestratorLogs / agentExecutionSpans to keep tables bounded.
|
|
47
|
+
// Override window via env: ORCHESTRATOR_LOG_RETENTION_DAYS (default 30).
|
|
48
|
+
this.app.cronJobManager.addJob({
|
|
49
|
+
cronTime: '0 30 2 * * *',
|
|
50
|
+
onTick: async () => {
|
|
51
|
+
try {
|
|
52
|
+
const days = Number(process.env.ORCHESTRATOR_LOG_RETENTION_DAYS || 30);
|
|
53
|
+
if (!Number.isFinite(days) || days <= 0) return;
|
|
54
|
+
const cutoff = new Date(Date.now() - days * 86400000);
|
|
55
|
+
const repo = this.db.getRepository('orchestratorLogs');
|
|
56
|
+
const spansRepo = this.db.getRepository('agentExecutionSpans');
|
|
57
|
+
const deletedLogs = repo
|
|
58
|
+
? await repo.destroy({
|
|
59
|
+
filter: { createdAt: { $lt: cutoff.toISOString() } },
|
|
60
|
+
})
|
|
61
|
+
: 0;
|
|
62
|
+
const deletedSpans = spansRepo
|
|
63
|
+
? await spansRepo.destroy({
|
|
64
|
+
filter: { createdAt: { $lt: cutoff.toISOString() } },
|
|
65
|
+
})
|
|
66
|
+
: 0;
|
|
67
|
+
this.app.log.info(
|
|
68
|
+
`[AgentOrchestrator] Pruned ${deletedLogs} orchestratorLogs and ${deletedSpans} agentExecutionSpans rows older than ${days} day(s).`,
|
|
69
|
+
);
|
|
70
|
+
} catch (e) {
|
|
71
|
+
this.app.log.error('[AgentOrchestrator] Log retention job failed', e);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
|
|
32
76
|
// NOTE: The createReactAgent approach does NOT create aiConversation records,
|
|
33
77
|
// so there is no need for a middleware to hide "headless" conversations.
|
|
34
78
|
// If future versions need conversation logging, add it here.
|
|
35
79
|
}
|
|
36
80
|
|
|
37
81
|
async install() {
|
|
38
|
-
|
|
82
|
+
await this.skillHub.install();
|
|
39
83
|
}
|
|
40
84
|
|
|
41
85
|
async afterEnable() {}
|
|
42
86
|
async afterDisable() {}
|
|
43
87
|
async remove() {}
|
|
88
|
+
|
|
89
|
+
async beforeStop() {
|
|
90
|
+
await this.skillHub.beforeStop();
|
|
91
|
+
}
|
|
44
92
|
}
|
|
45
93
|
|
|
46
94
|
export default PluginAgentOrchestratorServer;
|
|
@@ -1,5 +1,108 @@
|
|
|
1
1
|
import { Plugin } from '@nocobase/server';
|
|
2
2
|
|
|
3
|
+
function toPlain(row: any) {
|
|
4
|
+
return row?.toJSON?.() || row;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function normalizeSpanFilter(filter: any = {}) {
|
|
8
|
+
const next = { ...filter };
|
|
9
|
+
if (next.subAgentUsername) {
|
|
10
|
+
next.employeeUsername = next.subAgentUsername;
|
|
11
|
+
delete next.subAgentUsername;
|
|
12
|
+
}
|
|
13
|
+
return next;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function spanTitle(row: any) {
|
|
17
|
+
if (row.title) return row.title;
|
|
18
|
+
if (row.type === 'sub_agent') return `${row.leaderUsername || '-'} -> ${row.employeeUsername || '-'}`;
|
|
19
|
+
return row.toolName || row.type || 'span';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function formatSpanListRow(raw: any) {
|
|
23
|
+
const row = toPlain(raw);
|
|
24
|
+
const metadata = row.metadata || {};
|
|
25
|
+
const input = row.input || {};
|
|
26
|
+
return {
|
|
27
|
+
id: row.id,
|
|
28
|
+
rootRunId: row.rootRunId,
|
|
29
|
+
parentSpanId: row.parentSpanId,
|
|
30
|
+
type: row.type,
|
|
31
|
+
leaderUsername: row.leaderUsername,
|
|
32
|
+
subAgentUsername: row.employeeUsername,
|
|
33
|
+
employeeUsername: row.employeeUsername,
|
|
34
|
+
toolName: row.toolName,
|
|
35
|
+
task: input.task || metadata.task || row.title || '',
|
|
36
|
+
context: input.context || '',
|
|
37
|
+
result: row.output,
|
|
38
|
+
status: row.status,
|
|
39
|
+
depth: metadata.depth ?? 0,
|
|
40
|
+
durationMs: row.durationMs,
|
|
41
|
+
error: row.error,
|
|
42
|
+
userId: row.userId,
|
|
43
|
+
createdAt: row.createdAt || row.startedAt,
|
|
44
|
+
traceCount: metadata.traceCount || 0,
|
|
45
|
+
messageCount: Array.isArray(metadata.messages) ? metadata.messages.length : metadata.messageCount || 0,
|
|
46
|
+
hasUnifiedTrace: true,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function buildSpanTree(rows: any[]) {
|
|
51
|
+
const plainRows = rows.map(toPlain);
|
|
52
|
+
const byId = new Map<string, any>();
|
|
53
|
+
const roots: any[] = [];
|
|
54
|
+
|
|
55
|
+
for (const row of plainRows) {
|
|
56
|
+
const node = { ...row, children: [] };
|
|
57
|
+
byId.set(String(row.id), node);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (const row of byId.values()) {
|
|
61
|
+
if (row.parentSpanId && byId.has(String(row.parentSpanId))) {
|
|
62
|
+
byId.get(String(row.parentSpanId)).children.push(row);
|
|
63
|
+
} else {
|
|
64
|
+
roots.push(row);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const sortTree = (items: any[]) => {
|
|
69
|
+
items.sort(
|
|
70
|
+
(a, b) =>
|
|
71
|
+
new Date(a.startedAt || a.createdAt || 0).getTime() -
|
|
72
|
+
new Date(b.startedAt || b.createdAt || 0).getTime(),
|
|
73
|
+
);
|
|
74
|
+
for (const item of items) sortTree(item.children || []);
|
|
75
|
+
};
|
|
76
|
+
sortTree(roots);
|
|
77
|
+
return roots;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function flattenSpanTimeline(rows: any[]) {
|
|
81
|
+
return rows
|
|
82
|
+
.map(toPlain)
|
|
83
|
+
.sort(
|
|
84
|
+
(a, b) =>
|
|
85
|
+
new Date(a.startedAt || a.createdAt || 0).getTime() -
|
|
86
|
+
new Date(b.startedAt || b.createdAt || 0).getTime(),
|
|
87
|
+
)
|
|
88
|
+
.map((row) => {
|
|
89
|
+
const input = row.input || {};
|
|
90
|
+
const metadata = row.metadata || {};
|
|
91
|
+
return {
|
|
92
|
+
type: row.type,
|
|
93
|
+
at: row.startedAt || row.createdAt,
|
|
94
|
+
title: spanTitle(row),
|
|
95
|
+
toolName: row.toolName,
|
|
96
|
+
args: row.type === 'tool' || row.type === 'skill' ? input : undefined,
|
|
97
|
+
status: row.status,
|
|
98
|
+
content: row.output || row.error || input.task || metadata.summary || '',
|
|
99
|
+
spanId: row.id,
|
|
100
|
+
parentSpanId: row.parentSpanId,
|
|
101
|
+
skillExecutionId: row.skillExecutionId,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
3
106
|
/**
|
|
4
107
|
* Custom resource for the Swarm Tracing admin UI (Phase 5).
|
|
5
108
|
* Queries the dedicated orchestratorLogs collection instead of
|
|
@@ -15,11 +118,41 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
15
118
|
* List all delegation execution logs.
|
|
16
119
|
*/
|
|
17
120
|
async list(ctx, next) {
|
|
18
|
-
const
|
|
19
|
-
const { page = 1, pageSize = 50, sort = ['-createdAt'] } = ctx.action.params;
|
|
121
|
+
const { page = 1, pageSize = 50, sort = ['-createdAt'], filter = {} } = ctx.action.params;
|
|
20
122
|
|
|
21
123
|
try {
|
|
124
|
+
const spanRepo = ctx.db.getRepository('agentExecutionSpans');
|
|
125
|
+
if (spanRepo) {
|
|
126
|
+
const spanFilter = {
|
|
127
|
+
...normalizeSpanFilter(filter),
|
|
128
|
+
parentSpanId: null,
|
|
129
|
+
type: 'sub_agent',
|
|
130
|
+
};
|
|
131
|
+
const [spanRows, spanCount] = await spanRepo.findAndCount({
|
|
132
|
+
filter: spanFilter,
|
|
133
|
+
sort,
|
|
134
|
+
offset: (Number(page) - 1) * Number(pageSize),
|
|
135
|
+
limit: Number(pageSize),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (spanCount > 0) {
|
|
139
|
+
ctx.body = {
|
|
140
|
+
data: spanRows.map(formatSpanListRow),
|
|
141
|
+
meta: {
|
|
142
|
+
count: spanCount,
|
|
143
|
+
page: Number(page),
|
|
144
|
+
pageSize: Number(pageSize),
|
|
145
|
+
totalPage: Math.ceil(spanCount / Number(pageSize)),
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
await next();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const repo = ctx.db.getRepository('orchestratorLogs');
|
|
22
154
|
const [rows, count] = await repo.findAndCount({
|
|
155
|
+
filter,
|
|
23
156
|
sort,
|
|
24
157
|
offset: (Number(page) - 1) * Number(pageSize),
|
|
25
158
|
limit: Number(pageSize),
|
|
@@ -32,6 +165,7 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
32
165
|
subAgentUsername: row.subAgentUsername,
|
|
33
166
|
toolName: row.toolName,
|
|
34
167
|
task: row.task,
|
|
168
|
+
context: row.context,
|
|
35
169
|
result: row.result,
|
|
36
170
|
status: row.status,
|
|
37
171
|
depth: row.depth,
|
|
@@ -39,6 +173,9 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
39
173
|
error: row.error,
|
|
40
174
|
userId: row.userId,
|
|
41
175
|
createdAt: row.createdAt,
|
|
176
|
+
traceCount: Array.isArray(row.trace) ? row.trace.length : 0,
|
|
177
|
+
messageCount: Array.isArray(row.messages) ? row.messages.length : 0,
|
|
178
|
+
hasUnifiedTrace: false,
|
|
42
179
|
})),
|
|
43
180
|
meta: {
|
|
44
181
|
count,
|
|
@@ -47,9 +184,10 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
47
184
|
totalPage: Math.ceil(count / Number(pageSize)),
|
|
48
185
|
},
|
|
49
186
|
};
|
|
50
|
-
} catch (e) {
|
|
187
|
+
} catch (e: any) {
|
|
188
|
+
// Bubble up so the admin sees an error toast instead of an empty grid.
|
|
51
189
|
ctx.log.error('[AgentOrchestrator] Tracing list error', e);
|
|
52
|
-
ctx.
|
|
190
|
+
ctx.throw(500, e?.message || 'Failed to load tracing logs');
|
|
53
191
|
}
|
|
54
192
|
|
|
55
193
|
await next();
|
|
@@ -59,7 +197,7 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
59
197
|
* Get a single delegation log by ID.
|
|
60
198
|
*/
|
|
61
199
|
async get(ctx, next) {
|
|
62
|
-
const { filterByTk } = ctx.action.params;
|
|
200
|
+
const { filterByTk, source } = ctx.action.params;
|
|
63
201
|
|
|
64
202
|
if (!filterByTk) {
|
|
65
203
|
ctx.throw(400, 'id is required');
|
|
@@ -67,15 +205,52 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
67
205
|
}
|
|
68
206
|
|
|
69
207
|
try {
|
|
208
|
+
const spanRepo = ctx.db.getRepository('agentExecutionSpans');
|
|
209
|
+
if (spanRepo && source !== 'log') {
|
|
210
|
+
const span = await spanRepo.findOne({
|
|
211
|
+
filter: { id: filterByTk },
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (span) {
|
|
215
|
+
const plainSpan = toPlain(span);
|
|
216
|
+
const rows = await spanRepo.find({
|
|
217
|
+
filter: { rootRunId: plainSpan.rootRunId },
|
|
218
|
+
sort: ['createdAt'],
|
|
219
|
+
});
|
|
220
|
+
const tree = buildSpanTree(rows);
|
|
221
|
+
const timeline = flattenSpanTimeline(rows);
|
|
222
|
+
const rootRow = formatSpanListRow(plainSpan);
|
|
223
|
+
const metadata = plainSpan.metadata || {};
|
|
224
|
+
|
|
225
|
+
ctx.body = {
|
|
226
|
+
data: {
|
|
227
|
+
...rootRow,
|
|
228
|
+
input: plainSpan.input,
|
|
229
|
+
output: plainSpan.output,
|
|
230
|
+
metadata,
|
|
231
|
+
trace: timeline,
|
|
232
|
+
messages: metadata.messages || [],
|
|
233
|
+
children: tree,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
await next();
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
70
241
|
const repo = ctx.db.getRepository('orchestratorLogs');
|
|
71
|
-
const log =
|
|
72
|
-
|
|
73
|
-
|
|
242
|
+
const log =
|
|
243
|
+
source === 'span'
|
|
244
|
+
? null
|
|
245
|
+
: await repo.findOne({
|
|
246
|
+
filter: { id: filterByTk },
|
|
247
|
+
});
|
|
74
248
|
|
|
75
|
-
|
|
76
|
-
|
|
249
|
+
const plainLog = log?.toJSON?.() || log;
|
|
250
|
+
ctx.body = { data: plainLog ? { ...plainLog, hasUnifiedTrace: false } : null };
|
|
251
|
+
} catch (e: any) {
|
|
77
252
|
ctx.log.error('[AgentOrchestrator] Tracing get error', e);
|
|
78
|
-
ctx.
|
|
253
|
+
ctx.throw(500, e?.message || 'Failed to load tracing log');
|
|
79
254
|
}
|
|
80
255
|
|
|
81
256
|
await next();
|
|
@@ -83,9 +258,5 @@ export function registerTracingResource(plugin: Plugin) {
|
|
|
83
258
|
},
|
|
84
259
|
});
|
|
85
260
|
|
|
86
|
-
// ACL:
|
|
87
|
-
app.acl.registerSnippet({
|
|
88
|
-
name: `pm.${plugin.name}.tracing`,
|
|
89
|
-
actions: ['orchestratorTracing:list', 'orchestratorTracing:get'],
|
|
90
|
-
});
|
|
261
|
+
// ACL: access is granted by the parent plugin's snippet (pm.plugin-agent-orchestrator → orchestratorTracing:*)
|
|
91
262
|
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
interface ForbiddenPattern {
|
|
2
|
+
pattern: RegExp;
|
|
3
|
+
reason: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const DANGEROUS_NODE_PATTERNS: ForbiddenPattern[] = [
|
|
7
|
+
{ pattern: /require\s*\(\s*['"]child_process['"]\s*\)/, reason: 'child_process module not allowed' },
|
|
8
|
+
{ pattern: /require\s*\(\s*['"]cluster['"]\s*\)/, reason: 'cluster module not allowed' },
|
|
9
|
+
{ pattern: /require\s*\(\s*['"]dgram['"]\s*\)/, reason: 'dgram module not allowed' },
|
|
10
|
+
{ pattern: /require\s*\(\s*['"]net['"]\s*\)/, reason: 'net module not allowed' },
|
|
11
|
+
{ pattern: /require\s*\(\s*['"]http['"]\s*\)/, reason: 'http module not allowed' },
|
|
12
|
+
{ pattern: /require\s*\(\s*['"]https['"]\s*\)/, reason: 'https module not allowed' },
|
|
13
|
+
{ pattern: /require\s*\(\s*['"]vm['"]\s*\)/, reason: 'vm module not allowed' },
|
|
14
|
+
{ pattern: /process\.exit/, reason: 'process.exit not allowed' },
|
|
15
|
+
{ pattern: /process\.env(?!\s*\.OUTPUT_DIR)/, reason: 'process.env access not allowed (use OUTPUT_DIR only)' },
|
|
16
|
+
{ pattern: /process\.kill/, reason: 'process.kill not allowed' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const DANGEROUS_PYTHON_PATTERNS: ForbiddenPattern[] = [
|
|
20
|
+
{ pattern: /import\s+subprocess/, reason: 'subprocess module not allowed' },
|
|
21
|
+
{ pattern: /from\s+subprocess\s+import/, reason: 'subprocess module not allowed' },
|
|
22
|
+
{ pattern: /import\s+shutil/, reason: 'shutil module not allowed' },
|
|
23
|
+
{ pattern: /__import__\s*\(/, reason: '__import__ not allowed' },
|
|
24
|
+
{ pattern: /os\.system\s*\(/, reason: 'os.system not allowed' },
|
|
25
|
+
{ pattern: /os\.popen\s*\(/, reason: 'os.popen not allowed' },
|
|
26
|
+
{ pattern: /os\.exec\w*\s*\(/, reason: 'os.exec* not allowed' },
|
|
27
|
+
{ pattern: /os\.spawn\w*\s*\(/, reason: 'os.spawn* not allowed' },
|
|
28
|
+
{ pattern: /\beval\s*\(/, reason: 'eval not allowed' },
|
|
29
|
+
{ pattern: /\bexec\s*\(/, reason: 'exec not allowed' },
|
|
30
|
+
{ pattern: /\bcompile\s*\(/, reason: 'compile not allowed' },
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
/** Built-in Node.js modules that are always allowed in sandbox code */
|
|
34
|
+
const NODE_BUILTINS = [
|
|
35
|
+
'fs', 'path', 'os', 'crypto', 'util', 'stream', 'buffer',
|
|
36
|
+
'querystring', 'url', 'assert', 'events', 'string_decoder', 'zlib',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/** Built-in Python modules that are always allowed in sandbox code */
|
|
40
|
+
const PYTHON_BUILTINS = [
|
|
41
|
+
'os', 'sys', 'json', 'math', 'datetime', 'collections', 'itertools',
|
|
42
|
+
'functools', 'pathlib', 'typing', 'io', 'csv', 're', 'string', 'textwrap',
|
|
43
|
+
'decimal', 'fractions', 'random', 'statistics', 'copy', 'enum', 'dataclasses',
|
|
44
|
+
'abc', 'contextlib', 'operator', 'time', 'calendar', 'locale', 'struct',
|
|
45
|
+
'hashlib', 'base64', 'binascii', 'codecs', 'unicodedata', 'pprint',
|
|
46
|
+
'warnings', 'traceback', 'logging', 'unittest', 'argparse',
|
|
47
|
+
'tempfile', 'xml', 'zipfile',
|
|
48
|
+
// Pre-installed local packages (trusted, bundled with plugin)
|
|
49
|
+
'svg_to_pptx',
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Maps PyPI package names to their Python import names
|
|
54
|
+
* (only where they differ from the package name).
|
|
55
|
+
*/
|
|
56
|
+
const PYTHON_IMPORT_NAME_MAP: Record<string, string> = {
|
|
57
|
+
'python-docx': 'docx',
|
|
58
|
+
'python-pptx': 'pptx',
|
|
59
|
+
'Pillow': 'PIL',
|
|
60
|
+
'pyyaml': 'yaml',
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export class CodeValidator {
|
|
64
|
+
/**
|
|
65
|
+
* Check code against forbidden patterns (dangerous modules/functions).
|
|
66
|
+
* @throws CodeValidationError if a forbidden pattern is found.
|
|
67
|
+
*/
|
|
68
|
+
validate(code: string, language: 'node' | 'python'): void {
|
|
69
|
+
const patterns = language === 'node'
|
|
70
|
+
? DANGEROUS_NODE_PATTERNS
|
|
71
|
+
: DANGEROUS_PYTHON_PATTERNS;
|
|
72
|
+
|
|
73
|
+
for (const { pattern, reason } of patterns) {
|
|
74
|
+
if (pattern.test(code)) {
|
|
75
|
+
throw new CodeValidationError(reason, pattern.source);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validate that code only imports packages in the whitelist.
|
|
82
|
+
* Called after the basic forbidden pattern check.
|
|
83
|
+
* Skips validation if whitelist is empty (env not initialized yet).
|
|
84
|
+
*
|
|
85
|
+
* @param code - The code to validate
|
|
86
|
+
* @param language - 'node' or 'python'
|
|
87
|
+
* @param whitelist - Array of allowed package names (from skillWorkerConfigs.packageWhitelist)
|
|
88
|
+
*/
|
|
89
|
+
validateImports(code: string, language: 'node' | 'python', whitelist: string[]): void {
|
|
90
|
+
if (!whitelist?.length) return; // Skip if env not initialized
|
|
91
|
+
|
|
92
|
+
if (language === 'node') {
|
|
93
|
+
this.validateNodeImports(code, whitelist);
|
|
94
|
+
} else if (language === 'python') {
|
|
95
|
+
this.validatePythonImports(code, whitelist);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Check Node.js require() calls against the whitelist.
|
|
101
|
+
* Built-in modules (fs, path, etc.) are always allowed.
|
|
102
|
+
*/
|
|
103
|
+
private validateNodeImports(code: string, whitelist: string[]): void {
|
|
104
|
+
// Match require statements with string literal arguments (non-relative paths)
|
|
105
|
+
const requires = [...code.matchAll(/require\s*\(\s*['"]([^'"./][^'"]*)['"]\s*\)/g)];
|
|
106
|
+
|
|
107
|
+
for (const match of requires) {
|
|
108
|
+
const raw = match[1];
|
|
109
|
+
// Handle scoped packages (e.g. '@org/lib') and subpaths (e.g. 'lib/utils')
|
|
110
|
+
const pkgName = raw.startsWith('@')
|
|
111
|
+
? raw.split('/').slice(0, 2).join('/')
|
|
112
|
+
: raw.split('/')[0];
|
|
113
|
+
|
|
114
|
+
if (NODE_BUILTINS.includes(pkgName)) continue;
|
|
115
|
+
if (whitelist.includes(pkgName)) continue;
|
|
116
|
+
|
|
117
|
+
throw new CodeValidationError(
|
|
118
|
+
`Package "${pkgName}" is not in the allowed whitelist. Allowed: ${whitelist.join(', ')}`,
|
|
119
|
+
`require('${pkgName}')`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check Python import/from statements against the whitelist.
|
|
126
|
+
* Built-in modules (os, sys, json, etc.) are always allowed.
|
|
127
|
+
* Handles PyPI→import name mapping (e.g., python-docx → docx, Pillow → PIL).
|
|
128
|
+
*/
|
|
129
|
+
private validatePythonImports(code: string, whitelist: string[]): void {
|
|
130
|
+
// Match: import pkg, from pkg import ..., import pkg.sub
|
|
131
|
+
const imports = [...code.matchAll(/(?:^|\n)\s*(?:import|from)\s+([a-zA-Z_][a-zA-Z0-9_]*)/g)];
|
|
132
|
+
|
|
133
|
+
// Build allowed import names from whitelist
|
|
134
|
+
const allowedImports = new Set([
|
|
135
|
+
...PYTHON_BUILTINS,
|
|
136
|
+
...whitelist.map((p) => PYTHON_IMPORT_NAME_MAP[p] || p),
|
|
137
|
+
]);
|
|
138
|
+
|
|
139
|
+
for (const match of imports) {
|
|
140
|
+
const pkg = match[1];
|
|
141
|
+
if (allowedImports.has(pkg)) continue;
|
|
142
|
+
|
|
143
|
+
throw new CodeValidationError(
|
|
144
|
+
`Module "${pkg}" is not in the allowed whitelist. Allowed: ${[...allowedImports].join(', ')}`,
|
|
145
|
+
`import ${pkg}`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export class CodeValidationError extends Error {
|
|
152
|
+
constructor(
|
|
153
|
+
message: string,
|
|
154
|
+
public matchedPattern: string,
|
|
155
|
+
) {
|
|
156
|
+
super(`Code validation failed: ${message}`);
|
|
157
|
+
this.name = 'CodeValidationError';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export const ORCHESTRATOR_TRACE_CONTEXT_KEY = '__orchestratorTraceContext';
|
|
2
|
+
|
|
3
|
+
export type OrchestratorTraceContext = {
|
|
4
|
+
rootRunId: string;
|
|
5
|
+
spanId?: string;
|
|
6
|
+
parentSpanId?: string;
|
|
7
|
+
toolCallId?: string;
|
|
8
|
+
leaderUsername?: string;
|
|
9
|
+
employeeUsername?: string;
|
|
10
|
+
toolName?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type SpanValues = {
|
|
14
|
+
rootRunId: string;
|
|
15
|
+
parentSpanId?: string;
|
|
16
|
+
type: string;
|
|
17
|
+
status: string;
|
|
18
|
+
leaderUsername?: string;
|
|
19
|
+
employeeUsername?: string;
|
|
20
|
+
toolName?: string;
|
|
21
|
+
title?: string;
|
|
22
|
+
input?: any;
|
|
23
|
+
output?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
durationMs?: number;
|
|
26
|
+
startedAt?: Date;
|
|
27
|
+
endedAt?: Date;
|
|
28
|
+
orchestratorLogId?: string | number;
|
|
29
|
+
skillExecutionId?: string | number;
|
|
30
|
+
metadata?: any;
|
|
31
|
+
userId?: string | number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function toPlain(record: any) {
|
|
35
|
+
return record?.toJSON?.() || record;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class ExecutionSpanService {
|
|
39
|
+
constructor(private readonly plugin: any) {}
|
|
40
|
+
|
|
41
|
+
async create(values: SpanValues) {
|
|
42
|
+
try {
|
|
43
|
+
const repo = this.plugin.db.getRepository('agentExecutionSpans');
|
|
44
|
+
if (!repo) return null;
|
|
45
|
+
|
|
46
|
+
const record = await repo.create({
|
|
47
|
+
values: {
|
|
48
|
+
...values,
|
|
49
|
+
startedAt: values.startedAt || new Date(),
|
|
50
|
+
createdAt: new Date(),
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return toPlain(record);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
this.plugin.app.log?.warn?.('[AgentOrchestrator] Failed to create execution span', error);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async update(spanId: string | number | undefined, values: Record<string, any>) {
|
|
61
|
+
if (!spanId) return null;
|
|
62
|
+
try {
|
|
63
|
+
const repo = this.plugin.db.getRepository('agentExecutionSpans');
|
|
64
|
+
if (!repo) return null;
|
|
65
|
+
await repo.update({
|
|
66
|
+
filterByTk: spanId,
|
|
67
|
+
values: {
|
|
68
|
+
...values,
|
|
69
|
+
updatedAt: new Date(),
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
return { id: spanId };
|
|
73
|
+
} catch (error) {
|
|
74
|
+
this.plugin.app.log?.warn?.(`[AgentOrchestrator] Failed to update execution span ${spanId}`, error);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async finish(
|
|
80
|
+
spanId: string | number | undefined,
|
|
81
|
+
status: 'success' | 'error' | 'canceled' | 'timeout',
|
|
82
|
+
startedAt: number,
|
|
83
|
+
values: Record<string, any> = {},
|
|
84
|
+
) {
|
|
85
|
+
return this.update(spanId, {
|
|
86
|
+
...values,
|
|
87
|
+
status,
|
|
88
|
+
endedAt: new Date(),
|
|
89
|
+
durationMs: Date.now() - startedAt,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function getOrchestratorTraceContext(ctx: any): OrchestratorTraceContext | null {
|
|
95
|
+
return (
|
|
96
|
+
ctx?.[ORCHESTRATOR_TRACE_CONTEXT_KEY] ||
|
|
97
|
+
ctx?.state?.orchestratorTraceContext ||
|
|
98
|
+
ctx?.runtime?.context?.orchestratorTraceContext ||
|
|
99
|
+
null
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function setOrchestratorTraceContext(ctx: any, traceContext: OrchestratorTraceContext) {
|
|
104
|
+
ctx[ORCHESTRATOR_TRACE_CONTEXT_KEY] = traceContext;
|
|
105
|
+
return ctx;
|
|
106
|
+
}
|