@nocobase/app-plugin-agents 0.1.0-beta.1 → 0.1.0-beta.10
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/CHANGELOG.md +355 -0
- package/README.md +107 -67
- package/dist/client/api/client.d.ts +25 -17
- package/dist/client/api/client.d.ts.map +1 -1
- package/dist/client/api/client.js +29 -27
- package/dist/client/api/client.js.map +1 -1
- package/dist/client/api/keys.d.ts +1 -1
- package/dist/client/api/keys.d.ts.map +1 -1
- package/dist/client/api/keys.js +1 -1
- package/dist/client/api/keys.js.map +1 -1
- package/dist/client/chat/api.d.ts +2 -7
- package/dist/client/chat/api.d.ts.map +1 -1
- package/dist/client/chat/api.js +0 -7
- package/dist/client/chat/api.js.map +1 -1
- package/dist/client/chat/consultation-identity.d.ts +7 -0
- package/dist/client/chat/consultation-identity.d.ts.map +1 -0
- package/dist/client/chat/consultation-identity.js +39 -0
- package/dist/client/chat/consultation-identity.js.map +1 -0
- package/dist/client/chat/message-model.d.ts +4 -2
- package/dist/client/chat/message-model.d.ts.map +1 -1
- package/dist/client/chat/message-model.js +28 -3
- package/dist/client/chat/message-model.js.map +1 -1
- package/dist/client/chat/use-chat.d.ts +2 -10
- package/dist/client/chat/use-chat.d.ts.map +1 -1
- package/dist/client/chat/use-chat.js +3 -10
- package/dist/client/chat/use-chat.js.map +1 -1
- package/dist/client/chat.d.ts +4 -1
- package/dist/client/chat.d.ts.map +1 -1
- package/dist/client/chat.js +3 -0
- package/dist/client/chat.js.map +1 -1
- package/dist/client/components/agent-picker.d.ts +6 -23
- package/dist/client/components/agent-picker.d.ts.map +1 -1
- package/dist/client/components/agent-picker.js +19 -39
- package/dist/client/components/agent-picker.js.map +1 -1
- package/dist/client/components/variables/variable-dialogs.d.ts +6 -1
- package/dist/client/components/variables/variable-dialogs.d.ts.map +1 -1
- package/dist/client/components/variables/variable-dialogs.js +27 -11
- package/dist/client/components/variables/variable-dialogs.js.map +1 -1
- package/dist/client/components/variables/variables-panel.d.ts.map +1 -1
- package/dist/client/components/variables/variables-panel.js +9 -2
- package/dist/client/components/variables/variables-panel.js.map +1 -1
- package/dist/client/hooks/use-agent-picker-labels.d.ts.map +1 -1
- package/dist/client/hooks/use-agent-picker-labels.js +3 -12
- package/dist/client/hooks/use-agent-picker-labels.js.map +1 -1
- package/dist/client/kit.d.ts +9 -12
- package/dist/client/kit.d.ts.map +1 -1
- package/dist/client/kit.js +12 -14
- package/dist/client/kit.js.map +1 -1
- package/dist/client/lib/agents.d.ts +5 -13
- package/dist/client/lib/agents.d.ts.map +1 -1
- package/dist/client/lib/agents.js +17 -32
- package/dist/client/lib/agents.js.map +1 -1
- package/dist/client/lib/install.js +1 -1
- package/dist/client/locales/chat.en-US.d.ts +9 -22
- package/dist/client/locales/chat.en-US.d.ts.map +1 -1
- package/dist/client/locales/chat.en-US.js +13 -25
- package/dist/client/locales/chat.en-US.js.map +1 -1
- package/dist/client/locales/chat.zh-CN.d.ts.map +1 -1
- package/dist/client/locales/chat.zh-CN.js +10 -22
- package/dist/client/locales/chat.zh-CN.js.map +1 -1
- package/dist/client/locales/en-US.d.ts +100 -219
- package/dist/client/locales/en-US.d.ts.map +1 -1
- package/dist/client/locales/en-US.js +105 -219
- package/dist/client/locales/en-US.js.map +1 -1
- package/dist/client/locales/runWait.en-US.d.ts +38 -0
- package/dist/client/locales/runWait.en-US.d.ts.map +1 -0
- package/dist/client/locales/runWait.en-US.js +37 -0
- package/dist/client/locales/runWait.en-US.js.map +1 -0
- package/dist/client/locales/runWait.zh-CN.d.ts +5 -0
- package/dist/client/locales/runWait.zh-CN.d.ts.map +1 -0
- package/dist/client/locales/runWait.zh-CN.js +32 -0
- package/dist/client/locales/runWait.zh-CN.js.map +1 -0
- package/dist/client/locales/runtimes.en-US.d.ts +55 -0
- package/dist/client/locales/runtimes.en-US.d.ts.map +1 -1
- package/dist/client/locales/runtimes.en-US.js +58 -3
- package/dist/client/locales/runtimes.en-US.js.map +1 -1
- package/dist/client/locales/runtimes.zh-CN.d.ts.map +1 -1
- package/dist/client/locales/runtimes.zh-CN.js +58 -3
- package/dist/client/locales/runtimes.zh-CN.js.map +1 -1
- package/dist/client/locales/zh-CN.d.ts.map +1 -1
- package/dist/client/locales/zh-CN.js +107 -221
- package/dist/client/locales/zh-CN.js.map +1 -1
- package/dist/client/online/services.d.ts.map +1 -1
- package/dist/client/online/services.js +5 -6
- package/dist/client/online/services.js.map +1 -1
- package/dist/client/pages/agents/agent-dialog.d.ts +9 -0
- package/dist/client/pages/agents/agent-dialog.d.ts.map +1 -0
- package/dist/client/pages/agents/agent-dialog.js +106 -0
- package/dist/client/pages/agents/agent-dialog.js.map +1 -0
- package/dist/client/pages/agents/agent-state.d.ts +11 -0
- package/dist/client/pages/agents/agent-state.d.ts.map +1 -0
- package/dist/client/pages/agents/agent-state.js +28 -0
- package/dist/client/pages/agents/agent-state.js.map +1 -0
- package/dist/client/pages/agents/index.d.ts +1 -1
- package/dist/client/pages/agents/index.d.ts.map +1 -1
- package/dist/client/pages/agents/index.js +6 -100
- package/dist/client/pages/agents/index.js.map +1 -1
- package/dist/client/pages/agents/runner-agents.d.ts +3 -0
- package/dist/client/pages/agents/runner-agents.d.ts.map +1 -0
- package/dist/client/pages/agents/runner-agents.js +172 -0
- package/dist/client/pages/agents/runner-agents.js.map +1 -0
- package/dist/client/pages/runtimes/connect.js +1 -1
- package/dist/client/pages/runtimes/connect.js.map +1 -1
- package/dist/client/pages/runtimes/index.d.ts.map +1 -1
- package/dist/client/pages/runtimes/index.js +3 -2
- package/dist/client/pages/runtimes/index.js.map +1 -1
- package/dist/client/pages/runtimes/runner-cells.d.ts +1 -1
- package/dist/client/pages/runtimes/runner-cells.d.ts.map +1 -1
- package/dist/client/pages/runtimes/runner-cells.js +4 -1
- package/dist/client/pages/runtimes/runner-cells.js.map +1 -1
- package/dist/client/pages/runtimes/runner-sheet.d.ts.map +1 -1
- package/dist/client/pages/runtimes/runner-sheet.js +12 -3
- package/dist/client/pages/runtimes/runner-sheet.js.map +1 -1
- package/dist/client/pages/runtimes/workspace-diagnostics.d.ts +9 -0
- package/dist/client/pages/runtimes/workspace-diagnostics.d.ts.map +1 -0
- package/dist/client/pages/runtimes/workspace-diagnostics.js +70 -0
- package/dist/client/pages/runtimes/workspace-diagnostics.js.map +1 -0
- package/dist/client/pages/usage/index.js +2 -2
- package/dist/client/pages/usage/index.js.map +1 -1
- package/dist/client/profile/default-agent.d.ts.map +1 -1
- package/dist/client/profile/default-agent.js +2 -4
- package/dist/client/profile/default-agent.js.map +1 -1
- package/dist/client/routes.d.ts +1 -1
- package/dist/client/routes.d.ts.map +1 -1
- package/dist/client/routes.js +1 -13
- package/dist/client/routes.js.map +1 -1
- package/dist/client/runs/format-wait.d.ts +21 -0
- package/dist/client/runs/format-wait.d.ts.map +1 -0
- package/dist/client/runs/format-wait.js +90 -0
- package/dist/client/runs/format-wait.js.map +1 -0
- package/dist/client/runs/subject-runs.d.ts +5 -0
- package/dist/client/runs/subject-runs.d.ts.map +1 -1
- package/dist/client/runs/subject-runs.js +13 -7
- package/dist/client/runs/subject-runs.js.map +1 -1
- package/dist/client/runs.d.ts +3 -1
- package/dist/client/runs.d.ts.map +1 -1
- package/dist/client/runs.js +3 -1
- package/dist/client/runs.js.map +1 -1
- package/dist/database/migrations/.manifest.json +48 -0
- package/dist/database/migrations/202610090001_ag_add_team_runner_variables.d.ts +9 -0
- package/dist/database/migrations/202610090001_ag_add_team_runner_variables.d.ts.map +1 -0
- package/dist/database/migrations/202610090001_ag_add_team_runner_variables.js +28 -0
- package/dist/database/migrations/202610090001_ag_add_team_runner_variables.js.map +1 -0
- package/dist/database/migrations/202610090002_ag_create_run_requests.d.ts +10 -0
- package/dist/database/migrations/202610090002_ag_create_run_requests.d.ts.map +1 -0
- package/dist/database/migrations/202610090002_ag_create_run_requests.js +105 -0
- package/dist/database/migrations/202610090002_ag_create_run_requests.js.map +1 -0
- package/dist/database/migrations/202610090003_ag_add_execution_history.d.ts +4 -0
- package/dist/database/migrations/202610090003_ag_add_execution_history.d.ts.map +1 -0
- package/dist/database/migrations/202610090003_ag_add_execution_history.js +17 -0
- package/dist/database/migrations/202610090003_ag_add_execution_history.js.map +1 -0
- package/dist/database/migrations/202610090004_ag_add_runner_workspace_usage.d.ts +9 -0
- package/dist/database/migrations/202610090004_ag_add_runner_workspace_usage.d.ts.map +1 -0
- package/dist/database/migrations/202610090004_ag_add_runner_workspace_usage.js +22 -0
- package/dist/database/migrations/202610090004_ag_add_runner_workspace_usage.js.map +1 -0
- package/dist/database/migrations/202610090005_ag_add_runner_variables.d.ts +10 -0
- package/dist/database/migrations/202610090005_ag_add_runner_variables.d.ts.map +1 -0
- package/dist/database/migrations/202610090005_ag_add_runner_variables.js +36 -0
- package/dist/database/migrations/202610090005_ag_add_runner_variables.js.map +1 -0
- package/dist/database/migrations/202610100001_ag_index_run_event_types.d.ts +4 -0
- package/dist/database/migrations/202610100001_ag_index_run_event_types.d.ts.map +1 -0
- package/dist/database/migrations/202610100001_ag_index_run_event_types.js +17 -0
- package/dist/database/migrations/202610100001_ag_index_run_event_types.js.map +1 -0
- package/dist/database/migrations/202610100002_ag_add_run_git_credentials.d.ts +9 -0
- package/dist/database/migrations/202610100002_ag_add_run_git_credentials.d.ts.map +1 -0
- package/dist/database/migrations/202610100002_ag_add_run_git_credentials.js +30 -0
- package/dist/database/migrations/202610100002_ag_add_run_git_credentials.js.map +1 -0
- package/dist/database/migrations/202610110001_ag_add_fresh_sessions.d.ts +4 -0
- package/dist/database/migrations/202610110001_ag_add_fresh_sessions.d.ts.map +1 -0
- package/dist/database/migrations/202610110001_ag_add_fresh_sessions.js +23 -0
- package/dist/database/migrations/202610110001_ag_add_fresh_sessions.js.map +1 -0
- package/dist/database/migrations/202610120001_ag_index_run_retries.d.ts +4 -0
- package/dist/database/migrations/202610120001_ag_index_run_retries.d.ts.map +1 -0
- package/dist/database/migrations/202610120001_ag_index_run_retries.js +17 -0
- package/dist/database/migrations/202610120001_ag_index_run_retries.js.map +1 -0
- package/dist/database/migrations/202610120002_ag_add_queue_entered_at.d.ts +4 -0
- package/dist/database/migrations/202610120002_ag_add_queue_entered_at.d.ts.map +1 -0
- package/dist/database/migrations/202610120002_ag_add_queue_entered_at.js +50 -0
- package/dist/database/migrations/202610120002_ag_add_queue_entered_at.js.map +1 -0
- package/dist/database/migrations/202610240020_ag_runner_agents.d.ts +4 -0
- package/dist/database/migrations/202610240020_ag_runner_agents.d.ts.map +1 -0
- package/dist/database/migrations/202610240020_ag_runner_agents.js +115 -0
- package/dist/database/migrations/202610240020_ag_runner_agents.js.map +1 -0
- package/dist/database/migrations/202610240040_ag_discovery_preferences.d.ts +4 -0
- package/dist/database/migrations/202610240040_ag_discovery_preferences.d.ts.map +1 -0
- package/dist/database/migrations/202610240040_ag_discovery_preferences.js +18 -0
- package/dist/database/migrations/202610240040_ag_discovery_preferences.js.map +1 -0
- package/dist/package.json +8 -10
- package/dist/server/cli/run-credential.js +1 -1
- package/dist/server/composition.d.ts +39 -37
- package/dist/server/composition.d.ts.map +1 -1
- package/dist/server/composition.js +53 -65
- package/dist/server/composition.js.map +1 -1
- package/dist/server/core/agents/agent.service.d.ts +51 -43
- package/dist/server/core/agents/agent.service.d.ts.map +1 -1
- package/dist/server/core/agents/agent.service.js +342 -317
- package/dist/server/core/agents/agent.service.js.map +1 -1
- package/dist/server/core/agents/agent.store.d.ts +24 -12
- package/dist/server/core/agents/agent.store.d.ts.map +1 -1
- package/dist/server/core/agents/agent.store.js +65 -64
- package/dist/server/core/agents/agent.store.js.map +1 -1
- package/dist/server/core/agents/agent.views.d.ts +29 -0
- package/dist/server/core/agents/agent.views.d.ts.map +1 -0
- package/dist/server/core/agents/agent.views.js +86 -0
- package/dist/server/core/agents/agent.views.js.map +1 -0
- package/dist/server/core/agents/discovery.d.ts +12 -0
- package/dist/server/core/agents/discovery.d.ts.map +1 -0
- package/dist/server/core/agents/discovery.js +39 -0
- package/dist/server/core/agents/discovery.js.map +1 -0
- package/dist/server/core/agents/index.d.ts +2 -1
- package/dist/server/core/agents/index.d.ts.map +1 -1
- package/dist/server/core/agents/index.js +2 -1
- package/dist/server/core/agents/index.js.map +1 -1
- package/dist/server/core/brief/brief.js +1 -1
- package/dist/server/core/brief/brief.js.map +1 -1
- package/dist/server/core/callers/index.d.ts +1 -1
- package/dist/server/core/conversations/availability.d.ts +11 -10
- package/dist/server/core/conversations/availability.d.ts.map +1 -1
- package/dist/server/core/conversations/availability.js +14 -32
- package/dist/server/core/conversations/availability.js.map +1 -1
- package/dist/server/core/conversations/chat-settings.d.ts.map +1 -1
- package/dist/server/core/conversations/chat-settings.js +5 -3
- package/dist/server/core/conversations/chat-settings.js.map +1 -1
- package/dist/server/core/conversations/conversation.service.d.ts +3 -5
- package/dist/server/core/conversations/conversation.service.d.ts.map +1 -1
- package/dist/server/core/conversations/conversation.service.js +161 -221
- package/dist/server/core/conversations/conversation.service.js.map +1 -1
- package/dist/server/core/conversations/ports.d.ts +3 -17
- package/dist/server/core/conversations/ports.d.ts.map +1 -1
- package/dist/server/core/reports/report.service.d.ts.map +1 -1
- package/dist/server/core/reports/report.service.js +5 -2
- package/dist/server/core/reports/report.service.js.map +1 -1
- package/dist/server/core/runs/availability.d.ts +18 -7
- package/dist/server/core/runs/availability.d.ts.map +1 -1
- package/dist/server/core/runs/availability.js +35 -24
- package/dist/server/core/runs/availability.js.map +1 -1
- package/dist/server/core/runs/claim.d.ts +33 -65
- package/dist/server/core/runs/claim.d.ts.map +1 -1
- package/dist/server/core/runs/claim.js +566 -307
- package/dist/server/core/runs/claim.js.map +1 -1
- package/dist/server/core/runs/eligibility.d.ts +51 -0
- package/dist/server/core/runs/eligibility.d.ts.map +1 -0
- package/dist/server/core/runs/eligibility.js +44 -0
- package/dist/server/core/runs/eligibility.js.map +1 -0
- package/dist/server/core/runs/execution-view.d.ts +10 -0
- package/dist/server/core/runs/execution-view.d.ts.map +1 -0
- package/dist/server/core/runs/execution-view.js +25 -0
- package/dist/server/core/runs/execution-view.js.map +1 -0
- package/dist/server/core/runs/execution.d.ts +13 -0
- package/dist/server/core/runs/execution.d.ts.map +1 -0
- package/dist/server/core/runs/execution.js +85 -0
- package/dist/server/core/runs/execution.js.map +1 -0
- package/dist/server/core/runs/extensions.d.ts +59 -4
- package/dist/server/core/runs/extensions.d.ts.map +1 -1
- package/dist/server/core/runs/extensions.js +45 -9
- package/dist/server/core/runs/extensions.js.map +1 -1
- package/dist/server/core/runs/git-credentials.d.ts +43 -0
- package/dist/server/core/runs/git-credentials.d.ts.map +1 -0
- package/dist/server/core/runs/git-credentials.js +129 -0
- package/dist/server/core/runs/git-credentials.js.map +1 -0
- package/dist/server/core/runs/identity.d.ts +6 -0
- package/dist/server/core/runs/identity.d.ts.map +1 -0
- package/dist/server/core/runs/identity.js +49 -0
- package/dist/server/core/runs/identity.js.map +1 -0
- package/dist/server/core/runs/index.d.ts +9 -5
- package/dist/server/core/runs/index.d.ts.map +1 -1
- package/dist/server/core/runs/index.js +9 -5
- package/dist/server/core/runs/index.js.map +1 -1
- package/dist/server/core/runs/input-gate.d.ts +34 -0
- package/dist/server/core/runs/input-gate.d.ts.map +1 -0
- package/dist/server/core/runs/input-gate.js +54 -0
- package/dist/server/core/runs/input-gate.js.map +1 -0
- package/dist/server/core/runs/lifecycle.d.ts +9 -19
- package/dist/server/core/runs/lifecycle.d.ts.map +1 -1
- package/dist/server/core/runs/lifecycle.js +76 -34
- package/dist/server/core/runs/lifecycle.js.map +1 -1
- package/dist/server/core/runs/policy.d.ts +8 -0
- package/dist/server/core/runs/policy.d.ts.map +1 -1
- package/dist/server/core/runs/policy.js +10 -0
- package/dist/server/core/runs/policy.js.map +1 -1
- package/dist/server/core/runs/ports.d.ts +84 -28
- package/dist/server/core/runs/ports.d.ts.map +1 -1
- package/dist/server/core/runs/ports.js +2 -13
- package/dist/server/core/runs/ports.js.map +1 -1
- package/dist/server/core/runs/preview.d.ts.map +1 -1
- package/dist/server/core/runs/preview.js +3 -3
- package/dist/server/core/runs/preview.js.map +1 -1
- package/dist/server/core/runs/run-requests.d.ts +220 -0
- package/dist/server/core/runs/run-requests.d.ts.map +1 -0
- package/dist/server/core/runs/run-requests.js +475 -0
- package/dist/server/core/runs/run-requests.js.map +1 -0
- package/dist/server/core/runs/run.service.d.ts +84 -11
- package/dist/server/core/runs/run.service.d.ts.map +1 -1
- package/dist/server/core/runs/run.service.js +433 -93
- package/dist/server/core/runs/run.service.js.map +1 -1
- package/dist/server/core/runs/run.store.d.ts +20 -3
- package/dist/server/core/runs/run.store.d.ts.map +1 -1
- package/dist/server/core/runs/run.store.js +49 -2
- package/dist/server/core/runs/run.store.js.map +1 -1
- package/dist/server/core/runs/runner-view.d.ts +6 -4
- package/dist/server/core/runs/runner-view.d.ts.map +1 -1
- package/dist/server/core/runs/runner-view.js +13 -11
- package/dist/server/core/runs/runner-view.js.map +1 -1
- package/dist/server/core/runs/selection.d.ts +13 -0
- package/dist/server/core/runs/selection.d.ts.map +1 -0
- package/dist/server/core/runs/selection.js +21 -0
- package/dist/server/core/runs/selection.js.map +1 -0
- package/dist/server/core/runs/sweeper.d.ts.map +1 -1
- package/dist/server/core/runs/sweeper.js +54 -10
- package/dist/server/core/runs/sweeper.js.map +1 -1
- package/dist/server/core/runs/transitions.d.ts +1 -1
- package/dist/server/core/runs/transitions.d.ts.map +1 -1
- package/dist/server/core/runs/transitions.js +69 -5
- package/dist/server/core/runs/transitions.js.map +1 -1
- package/dist/server/core/runs/workload.d.ts +3 -3
- package/dist/server/core/runs/workload.d.ts.map +1 -1
- package/dist/server/core/runs/workload.js +154 -45
- package/dist/server/core/runs/workload.js.map +1 -1
- package/dist/server/core/variables/index.d.ts +1 -1
- package/dist/server/core/variables/index.d.ts.map +1 -1
- package/dist/server/core/variables/index.js +1 -1
- package/dist/server/core/variables/index.js.map +1 -1
- package/dist/server/core/variables/variable.service.d.ts +38 -6
- package/dist/server/core/variables/variable.service.d.ts.map +1 -1
- package/dist/server/core/variables/variable.service.js +201 -30
- package/dist/server/core/variables/variable.service.js.map +1 -1
- package/dist/server/distribution/dist.service.d.ts +27 -5
- package/dist/server/distribution/dist.service.d.ts.map +1 -1
- package/dist/server/distribution/dist.service.js +41 -5
- package/dist/server/distribution/dist.service.js.map +1 -1
- package/dist/server/distribution/download-tokens.d.ts +1 -1
- package/dist/server/distribution/download-tokens.d.ts.map +1 -1
- package/dist/server/distribution/download-tokens.js +7 -4
- package/dist/server/distribution/download-tokens.js.map +1 -1
- package/dist/server/distribution/index.d.ts +11 -3
- package/dist/server/distribution/index.d.ts.map +1 -1
- package/dist/server/distribution/index.js +31 -8
- package/dist/server/distribution/index.js.map +1 -1
- package/dist/server/jobs/index.d.ts +1 -1
- package/dist/server/jobs/index.d.ts.map +1 -1
- package/dist/server/jobs/index.js +1 -1
- package/dist/server/jobs/index.js.map +1 -1
- package/dist/server/jobs/job.service.d.ts +3 -1
- package/dist/server/jobs/job.service.d.ts.map +1 -1
- package/dist/server/jobs/job.service.js +11 -3
- package/dist/server/jobs/job.service.js.map +1 -1
- package/dist/server/jobs/spec.d.ts +4 -0
- package/dist/server/jobs/spec.d.ts.map +1 -1
- package/dist/server/jobs/spec.js +6 -0
- package/dist/server/jobs/spec.js.map +1 -1
- package/dist/server/kernel/errors.d.ts +1 -1
- package/dist/server/kernel/errors.d.ts.map +1 -1
- package/dist/server/kernel/errors.js +1 -0
- package/dist/server/kernel/errors.js.map +1 -1
- package/dist/server/kernel/events.d.ts +34 -9
- package/dist/server/kernel/events.d.ts.map +1 -1
- package/dist/server/kernel/events.js.map +1 -1
- package/dist/server/kernel/redaction.d.ts +2 -0
- package/dist/server/kernel/redaction.d.ts.map +1 -1
- package/dist/server/kernel/redaction.js +17 -0
- package/dist/server/kernel/redaction.js.map +1 -1
- package/dist/server/online/index.d.ts +0 -5
- package/dist/server/online/index.d.ts.map +1 -1
- package/dist/server/online/index.js +0 -5
- package/dist/server/online/index.js.map +1 -1
- package/dist/server/online/routes.d.ts.map +1 -1
- package/dist/server/online/routes.js +6 -35
- package/dist/server/online/routes.js.map +1 -1
- package/dist/server/providers/agents.d.ts +4 -25
- package/dist/server/providers/agents.d.ts.map +1 -1
- package/dist/server/providers/agents.js +8 -75
- package/dist/server/providers/agents.js.map +1 -1
- package/dist/server/routes/admin.d.ts.map +1 -1
- package/dist/server/routes/admin.js +140 -201
- package/dist/server/routes/admin.js.map +1 -1
- package/dist/server/routes/chat.d.ts.map +1 -1
- package/dist/server/routes/chat.js +12 -70
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/index.d.ts.map +1 -1
- package/dist/server/routes/index.js +11 -1
- package/dist/server/routes/index.js.map +1 -1
- package/dist/server/routes/roster.d.ts.map +1 -1
- package/dist/server/routes/roster.js +6 -21
- package/dist/server/routes/roster.js.map +1 -1
- package/dist/server/routes/run-requests.d.ts +6 -0
- package/dist/server/routes/run-requests.d.ts.map +1 -0
- package/dist/server/routes/run-requests.js +216 -0
- package/dist/server/routes/run-requests.js.map +1 -0
- package/dist/server/routes/runners/admin.d.ts +9 -1
- package/dist/server/routes/runners/admin.d.ts.map +1 -1
- package/dist/server/routes/runners/admin.js +62 -24
- package/dist/server/routes/runners/admin.js.map +1 -1
- package/dist/server/routes/runners/dist.d.ts +5 -1
- package/dist/server/routes/runners/dist.d.ts.map +1 -1
- package/dist/server/routes/runners/dist.js +36 -9
- package/dist/server/routes/runners/dist.js.map +1 -1
- package/dist/server/routes/runners/install.d.ts.map +1 -1
- package/dist/server/routes/runners/install.js +98 -15
- package/dist/server/routes/runners/install.js.map +1 -1
- package/dist/server/routes/runners/runner.d.ts.map +1 -1
- package/dist/server/routes/runners/runner.js +25 -7
- package/dist/server/routes/runners/runner.js.map +1 -1
- package/dist/server/routes/runners/runs.d.ts +1 -1
- package/dist/server/routes/runners/runs.d.ts.map +1 -1
- package/dist/server/routes/runners/runs.js +23 -3
- package/dist/server/routes/runners/runs.js.map +1 -1
- package/dist/server/routes/schemas.d.ts +37 -8
- package/dist/server/routes/schemas.d.ts.map +1 -1
- package/dist/server/routes/schemas.js +367 -82
- package/dist/server/routes/schemas.js.map +1 -1
- package/dist/server/runners/index.d.ts +1 -0
- package/dist/server/runners/index.d.ts.map +1 -1
- package/dist/server/runners/index.js +1 -0
- package/dist/server/runners/index.js.map +1 -1
- package/dist/server/runners/runner.service.d.ts +22 -8
- package/dist/server/runners/runner.service.d.ts.map +1 -1
- package/dist/server/runners/runner.service.js +112 -14
- package/dist/server/runners/runner.service.js.map +1 -1
- package/dist/server/runners/runner.store.d.ts +10 -1
- package/dist/server/runners/runner.store.d.ts.map +1 -1
- package/dist/server/runners/runner.store.js +117 -4
- package/dist/server/runners/runner.store.js.map +1 -1
- package/dist/server/runners/sweeper.d.ts +5 -0
- package/dist/server/runners/sweeper.d.ts.map +1 -1
- package/dist/server/runners/sweeper.js +4 -2
- package/dist/server/runners/sweeper.js.map +1 -1
- package/dist/server/runners/workspaces.d.ts +33 -0
- package/dist/server/runners/workspaces.d.ts.map +1 -0
- package/dist/server/runners/workspaces.js +248 -0
- package/dist/server/runners/workspaces.js.map +1 -0
- package/dist/server/testing.d.ts +0 -2
- package/dist/server/testing.d.ts.map +1 -1
- package/dist/server/testing.js +1 -4
- package/dist/server/testing.js.map +1 -1
- package/dist/server/tokens.d.ts +12 -9
- package/dist/server/tokens.d.ts.map +1 -1
- package/dist/server/tokens.js +6 -2
- package/dist/server/tokens.js.map +1 -1
- package/dist/shared/access.d.ts +2 -6
- package/dist/shared/access.d.ts.map +1 -1
- package/dist/shared/access.js +2 -6
- package/dist/shared/access.js.map +1 -1
- package/dist/shared/agents.d.ts +128 -165
- package/dist/shared/agents.d.ts.map +1 -1
- package/dist/shared/agents.js +46 -97
- package/dist/shared/agents.js.map +1 -1
- package/dist/shared/conversations.d.ts +43 -89
- package/dist/shared/conversations.d.ts.map +1 -1
- package/dist/shared/conversations.js +5 -24
- package/dist/shared/conversations.js.map +1 -1
- package/dist/shared/model-catalog.d.ts +48 -0
- package/dist/shared/model-catalog.d.ts.map +1 -0
- package/dist/shared/model-catalog.js +148 -0
- package/dist/shared/model-catalog.js.map +1 -0
- package/dist/shared/models.js +1 -1
- package/dist/shared/models.js.map +1 -1
- package/dist/shared/runners.d.ts +107 -17
- package/dist/shared/runners.d.ts.map +1 -1
- package/dist/shared/runners.js +49 -7
- package/dist/shared/runners.js.map +1 -1
- package/dist/shared/runs.d.ts +203 -1
- package/dist/shared/runs.d.ts.map +1 -1
- package/dist/shared/runs.js +24 -0
- package/dist/shared/runs.js.map +1 -1
- package/dist/shared/variables.d.ts +22 -0
- package/dist/shared/variables.d.ts.map +1 -1
- package/dist/shared/variables.js +9 -1
- package/dist/shared/variables.js.map +1 -1
- package/package.json +24 -26
- package/skills/nocobase-app-plugin-agents/SKILL.md +8 -7
- package/skills/nocobase-app-plugin-agents/references/agents.md +30 -0
- package/skills/nocobase-app-plugin-agents/references/distribution.md +21 -4
- package/skills/nocobase-app-plugin-agents/references/extension-points.md +30 -20
- package/skills/nocobase-app-plugin-agents/references/model-services.md +17 -0
- package/skills/nocobase-app-plugin-agents/references/runners.md +15 -1
- package/skills/nocobase-app-plugin-agents/references/setup-and-config.md +4 -7
- package/skills/nocobase-app-plugin-agents/references/variables-skills-usage.md +4 -4
- package/skills/nocobase-app-plugin-agents/references/verification-and-troubleshooting.md +33 -32
- package/dist/client/chat/settings-section.d.ts +0 -5
- package/dist/client/chat/settings-section.d.ts.map +0 -1
- package/dist/client/chat/settings-section.js +0 -76
- package/dist/client/chat/settings-section.js.map +0 -1
- package/dist/client/components/agent-fields.d.ts +0 -45
- package/dist/client/components/agent-fields.d.ts.map +0 -1
- package/dist/client/components/agent-fields.js +0 -83
- package/dist/client/components/agent-fields.js.map +0 -1
- package/dist/client/components/agent-type.d.ts +0 -32
- package/dist/client/components/agent-type.d.ts.map +0 -1
- package/dist/client/components/agent-type.js +0 -80
- package/dist/client/components/agent-type.js.map +0 -1
- package/dist/client/components/model-entries.d.ts +0 -35
- package/dist/client/components/model-entries.d.ts.map +0 -1
- package/dist/client/components/model-entries.js +0 -82
- package/dist/client/components/model-entries.js.map +0 -1
- package/dist/client/hooks/use-agent-save.d.ts +0 -9
- package/dist/client/hooks/use-agent-save.d.ts.map +0 -1
- package/dist/client/hooks/use-agent-save.js +0 -40
- package/dist/client/hooks/use-agent-save.js.map +0 -1
- package/dist/client/hooks/use-model-catalog.d.ts +0 -9
- package/dist/client/hooks/use-model-catalog.d.ts.map +0 -1
- package/dist/client/hooks/use-model-catalog.js +0 -27
- package/dist/client/hooks/use-model-catalog.js.map +0 -1
- package/dist/client/lib/tool-policy.d.ts +0 -5
- package/dist/client/lib/tool-policy.d.ts.map +0 -1
- package/dist/client/lib/tool-policy.js +0 -10
- package/dist/client/lib/tool-policy.js.map +0 -1
- package/dist/client/online/default-model.d.ts +0 -5
- package/dist/client/online/default-model.d.ts.map +0 -1
- package/dist/client/online/default-model.js +0 -65
- package/dist/client/online/default-model.js.map +0 -1
- package/dist/client/pages/agents/agent-model.d.ts +0 -73
- package/dist/client/pages/agents/agent-model.d.ts.map +0 -1
- package/dist/client/pages/agents/agent-model.js +0 -172
- package/dist/client/pages/agents/agent-model.js.map +0 -1
- package/dist/client/pages/agents/detail/brief-preview.d.ts +0 -7
- package/dist/client/pages/agents/detail/brief-preview.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/brief-preview.js +0 -43
- package/dist/client/pages/agents/detail/brief-preview.js.map +0 -1
- package/dist/client/pages/agents/detail/history.d.ts +0 -11
- package/dist/client/pages/agents/detail/history.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/history.js +0 -149
- package/dist/client/pages/agents/detail/history.js.map +0 -1
- package/dist/client/pages/agents/detail/index.d.ts +0 -3
- package/dist/client/pages/agents/detail/index.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/index.js +0 -241
- package/dist/client/pages/agents/detail/index.js.map +0 -1
- package/dist/client/pages/agents/detail/sections.d.ts +0 -22
- package/dist/client/pages/agents/detail/sections.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/sections.js +0 -311
- package/dist/client/pages/agents/detail/sections.js.map +0 -1
- package/dist/client/pages/agents/detail/tab-draft.d.ts +0 -43
- package/dist/client/pages/agents/detail/tab-draft.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/tab-draft.js +0 -115
- package/dist/client/pages/agents/detail/tab-draft.js.map +0 -1
- package/dist/client/pages/agents/detail/unsaved-bar.d.ts +0 -13
- package/dist/client/pages/agents/detail/unsaved-bar.d.ts.map +0 -1
- package/dist/client/pages/agents/detail/unsaved-bar.js +0 -21
- package/dist/client/pages/agents/detail/unsaved-bar.js.map +0 -1
- package/dist/client/pages/agents/new.d.ts +0 -3
- package/dist/client/pages/agents/new.d.ts.map +0 -1
- package/dist/client/pages/agents/new.js +0 -149
- package/dist/client/pages/agents/new.js.map +0 -1
- package/dist/client/pages/agents/preset-picker.d.ts +0 -8
- package/dist/client/pages/agents/preset-picker.d.ts.map +0 -1
- package/dist/client/pages/agents/preset-picker.js +0 -41
- package/dist/client/pages/agents/preset-picker.js.map +0 -1
- package/dist/server/core/consultations/consultation.service.d.ts +0 -59
- package/dist/server/core/consultations/consultation.service.d.ts.map +0 -1
- package/dist/server/core/consultations/consultation.service.js +0 -195
- package/dist/server/core/consultations/consultation.service.js.map +0 -1
- package/dist/server/core/consultations/index.d.ts +0 -3
- package/dist/server/core/consultations/index.d.ts.map +0 -1
- package/dist/server/core/consultations/index.js +0 -3
- package/dist/server/core/consultations/index.js.map +0 -1
- package/dist/server/core/consultations/prompt.d.ts +0 -41
- package/dist/server/core/consultations/prompt.d.ts.map +0 -1
- package/dist/server/core/consultations/prompt.js +0 -64
- package/dist/server/core/consultations/prompt.js.map +0 -1
- package/dist/server/core/presets/index.d.ts +0 -19
- package/dist/server/core/presets/index.d.ts.map +0 -1
- package/dist/server/core/presets/index.js +0 -28
- package/dist/server/core/presets/index.js.map +0 -1
- package/dist/server/online/cli-command.d.ts +0 -20
- package/dist/server/online/cli-command.d.ts.map +0 -1
- package/dist/server/online/cli-command.js +0 -345
- package/dist/server/online/cli-command.js.map +0 -1
- package/dist/server/online/consult-tool.d.ts +0 -54
- package/dist/server/online/consult-tool.d.ts.map +0 -1
- package/dist/server/online/consult-tool.js +0 -177
- package/dist/server/online/consult-tool.js.map +0 -1
- package/dist/server/online/executor.d.ts +0 -83
- package/dist/server/online/executor.d.ts.map +0 -1
- package/dist/server/online/executor.js +0 -714
- package/dist/server/online/executor.js.map +0 -1
- package/dist/server/online/sandbox.d.ts +0 -32
- package/dist/server/online/sandbox.d.ts.map +0 -1
- package/dist/server/online/sandbox.js +0 -246
- package/dist/server/online/sandbox.js.map +0 -1
- package/dist/server/online/scripted.d.ts +0 -12
- package/dist/server/online/scripted.d.ts.map +0 -1
- package/dist/server/online/scripted.js +0 -176
- package/dist/server/online/scripted.js.map +0 -1
- package/dist/server/online/tools.d.ts +0 -17
- package/dist/server/online/tools.d.ts.map +0 -1
- package/dist/server/online/tools.js +0 -31
- package/dist/server/online/tools.js.map +0 -1
- package/dist/server/vendor/THIRD_PARTY_LICENSES.txt +0 -782
- package/dist/server/vendor/just-bash.d.ts +0 -83
- package/dist/server/vendor/just-bash.js +0 -2102
- package/dist/shared/presets.d.ts +0 -30
- package/dist/shared/presets.d.ts.map +0 -1
- package/dist/shared/presets.js +0 -2
- package/dist/shared/presets.js.map +0 -1
- package/skills/nocobase-app-plugin-agents/references/online-agents.md +0 -31
package/README.md
CHANGED
|
@@ -1,45 +1,47 @@
|
|
|
1
1
|
# @nocobase/app-plugin-agents
|
|
2
2
|
|
|
3
|
-
Agents for NocoBase applications: the agents people
|
|
3
|
+
Agents for NocoBase applications: the agents discovered from the runners people connect, their runs, and people's conversations with agents. Agents run on runners (each a runtime: a runner on a server, a VM or someone's own device), which this plugin registers, hands work to and serves the runner and CLI tarballs for; the wire protocol runners and the application's CLI speak is `@nocobase/agent-protocol`, and the runner is `@nocobase/agent-runner` (`nocobase-runner`).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Workspace cleanup supports optional application bindings for legacy subject keys (`SubjectWorkspaces.resolveKeys`) and trusted merged PR head evidence by repository (`SubjectWorkspaces.commits`). Ownership must be confirmed from saved runs; settlement never bypasses local tracked-change, commit or submodule checks. Runtime diagnostics require the existing machine-information permission and distinguish ended work, allowed cleanup and retained work, with the workspace report's timestamp. See [workspace cleanup integration](https://github.com/nocobase/nocobase/blob/v3-develop/packages/plugins/app-plugin-agents/docs/workspace-cleanup.md) for the protocol, binding rules and compatibility behavior.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Nobody creates an agent. Each coding tool and model a runner reports signed in becomes one agent (`AgentService.syncRunner`, in the transaction of the runner's report), named from the model catalog that ships with the plugin (`shared/model-catalog.ts`: `normalizeModel` makes one model reported under two spellings one agent, and `agentNameOf` names it, such as "Claude · Opus 5.5" for Claude Code's `claude-opus-5-5`; a model the catalog does not know is named after its id), and starts **pending**. Someone who manages agents writes what it is good at, starting from the catalog's suggestion, picks its default reasoning effort and enables it; only **enabled** agents are offered work, and an agent may be disabled again. An application may also keep agents of its own (`ensureSystem`, `source` `system`), such as a project manager, whose name, instructions, business actions and models it writes itself. There are no online agents: the model services this plugin keeps serve the application's own model calls (embeddings, reranking, short texts), not agents.
|
|
8
|
+
|
|
9
|
+
The plugin knows no domain of its own beyond conversations: what agents work on (subjects), the scopes variables are kept in, the business actions an agent may be given and those every discovered agent gets, and the report pages are the application's, which contributes them through the extension points below; the CLI's business commands are the application's own routes, each described with `cliRoute()`. The assembling application does it in `server/agents` and `client/agents`. With nothing contributed, the plugin still runs agents in conversations on runners, with its own commands.
|
|
8
10
|
|
|
9
11
|
## What it does
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
Applications forward the `notice` event of type `run_secrets_not_allowed` to the run's actor and owner: a personal runner left the run because some of its variables are for team runners only. Its subject is the run, its parameters are `runId`, `agentId` and `variables` (in words), and its key is stable per run. `notice.cleared` settles it once a runner takes the run.
|
|
14
|
+
|
|
15
|
+
Repository access providers that mint credentials in `prepare` implement the idempotent `discard(run, prepared)` hook to revoke them when the claim is skipped or rolled back. It runs outside the transaction and receives the same prepared value as `forRun`. The application owns code host credentials and their revocation API; providers without this hook cannot revoke externally issued credentials.
|
|
16
|
+
|
|
17
|
+
- **Agents** (`agAgents`): one for each coding tool and model the runners report (`source` `runner`, its id `runnerAgentId(tool, model)`), and the application's own (`source` `system`). An agent has a name (the catalog's, or the model's id), what it is good at (`description`: the project manager hands it work by this; required to enable it), its `status` (`pending` until someone enables it, `enabled` or `disabled`), its tool and normalized model, one model entry (`modelEntries`: the tool, the model and the default reasoning effort, `medium` when the tool takes it), and when a runner last reported it (`lastReportedAt`, refreshed at most every ten minutes). Its instructions and business actions are the application's, the same for every discovered agent (`agents.setDefaults(provider)`, written to each that differs by `applyDefaults()`; actions marked `defaultOn` otherwise), and it keeps its skills, its variables and its tool policy (of which runners use only the idle timeout and the turn limit: they run agents with full access, see the agent-runner README); it may have as many runs at once as runners' slots allow. An agent no runner reported for 14 days (`AGENT_UNREPORTED_AFTER_MS`) is listed as unreported and left out of the roster until a runner reports it again. Changing an agent (`PATCH /api/agents/:agentId`, `agents.agents` manage) writes only what it is good at, its effort (one its tool takes, else 400 `EFFORT_UNSUPPORTED`) and whether it is enabled (400 `GOOD_AT_REQUIRED` without a description); an application's own agent is changed through the application (400 `AGENT_MANAGED`). Every change raises its `revision`: a patch names the revision it was made against (`expectedRevision`) and is refused with 409 `REVISION_CONFLICT` (`metadata.revision` the current one) when someone changed the agent since, and a patch that changes nothing raises nothing. Every change is kept in its history (`agAgentChanges`, `GET /api/agents/:agentId/history`, with `afterRevision` for what came after a revision): who, when, and the fields that changed with their values before and after, except its variables, which are named with whether they were added, changed or removed, never valued. Disabling an agent withdraws its queued runs at once and announces `agent.removed` (`reason` `disabled`); work for an agent that is not enabled is refused (`AGENT_NOT_ENABLED`). Nobody deletes an agent: the agents an earlier version kept were removed by the `202610240020_ag_runner_agents` migration, their rows kept with `deletedAt` for the names their runs, comments and conversations show (`GET /api/agents/agentNames` answers every agent's name, those included), their queued runs cancelled and their pending run requests withdrawn.
|
|
18
|
+
- **Runners** (`agRunners`), shown as runtimes: registered with a one-time token (`POST /api/agents/runners/registrationTokens`, or `pnpm nocobase agents runner-token`). Anyone may add a personal runner (`ownerOnly`: it runs only work its owner started) and later share it with the team; adding a team runner needs `agents.runners` manage. A runner reports its system, its features, its coding tools with versions and whether each is signed in, and what its owner's local policy lets it take (`policy`); it authenticates with its key (`agRunnerCredentials`), sends heartbeats and long-polls for work. Which of its coding tools it is offered work for is chosen on the web (`enabledTools`, null for every tool), carried from "Add runtime" on the registration token (`agRegistrationTokens`). A runner speaking a protocol this application does not serve is kept connected as `upgrade_required`: it gets no work, has what it holds released, and its owner is told once per protocol through the `notice` event (`runner_upgrade_required`; `notice.cleared` once it no longer holds). Only its owner changes a runner (its name, slots, coding tools and trust), because it is their machine with their tools' sign-ins and credentials; a manager of runners changes only a runner whose owner can no longer act (none recorded, or disabled or deleted in the application's directory, `people.provide({ inactive })`). A manager of runners may still revoke anyone's runner in an emergency, and delete it once revoked: its owner is told (`runner_revoked`) and the application's `security` log records who did it. A runner whose owner can no longer act (`people.provide({ inactive })`) is refused with `RUNNER_OWNER_DISABLED`. A runner fits an agent's run only when its owner's local policy lets it take that agent's runs, on that subject, with those repositories; `availability` and the agents list count only such runners. Every heartbeat answer announces workspace reports (`workspaces`): a runner reports the working directories it keeps for this application (`POST /api/agents/runners/workspaces`, each with the last run that worked there and whether it holds unpushed work, with the free space on the disk holding them) and is told which of those runs belong to subjects whose work is over (`remove`) or goes on (`keep`), as each subject kind's `workspaces.settled` says; a kind without it never counts as over, and only the runner's own runs are answered for. The last report is kept on the runner (`agRunners.workspaceUsage`, `Runner.workspaceUsage`) with each directory's subject and what was decided, for the Runtimes page.
|
|
13
19
|
- **The claim**: one long-poll (`POST /api/agents/runners/claim?wait=true`) answers `jobs` and `runs` together, at most `free` items, from the runner's slots, which jobs and runs share (`slots`): jobs first. A heartbeat reconciles both, releasing what the server no longer thinks the runner holds and asking it to stop what was cancelled.
|
|
14
20
|
- **Jobs** (`agJobs`, `agJobEvents`): only for the off-by-default runner build method (such as an application's `acme.builds.method: runner`): a `build` (check out a commit, run an administrator's command, upload its outputs), of kinds the application registers (`jobs.register(kind, { validate, prepare, onEvent, onDone })`, then `jobs.enqueue`, `get` and `watch`). A runner takes a job only when it reports `jobs.build`, someone turned on "Takes build jobs" (`acceptJobs`), it is shared or belongs to who started the job, and its policy lets it check out the job's repository. Jobs retry `runnerOffline`, `leaseExpired`, `startTimeout`, `checkoutFailed` and `policyRefused` while attempts remain, and open the stored variables they name through this plugin's variables at claim, audited as delivered.
|
|
15
|
-
- **Distribution**: the application serves two products as standalone tarballs that bundle Node, one per platform (`server/distribution`): its CLI (`agents.cli.name`, such as `acme`) and the runner, `nocobase-runner` (`RUNNER_PRODUCT`). `pnpm nocobase cli build` of `@nocobase/app-cli` packs the CLI the application's `package.json` declares under `nocobase.cli`, and `cli build --runner` the runner, each into a directory of its own, `storage/runners/dist/<channel>/<product>/`, with a `manifest.json` of every file's SHA-256 and size, so CI builds them as separate artifacts mounted into storage. The install script installs the CLI under `~/.local/share/<cli>`: by default the CLI alone, with a download token any signed-in person mints (`POST /api/agents/dist/downloadTokens`, `agDownloadTokens`: the CLI for one platform, three downloads within 30 minutes), as `curl -fsSL <server>/api/agents/dist/installScript | sh -s -- --token <token>`; "Add runtime" shows the same line with `--runner --server <server>` and a registration token, which also installs `nocobase-runner` under `~/.local/share/nocobase-runner`, runs `nocobase-runner register` and `nocobase-runner service install` (an application that serves no CLI still gets its runtime). A token of the other kind fails before anything is installed. A runner reports the product it runs as on registration and every heartbeat (`agRunners.product`), and the heartbeat answer carries an `upgrade` notice when the channel serves a newer version of that product for the runner's platform; a runner that reports none (one from before) is offered no update, and the Runtimes page says to install it again.
|
|
21
|
+
- **Distribution**: the application serves two products as standalone tarballs that bundle Node, one per platform, or as one universal tarball (`cli build --universal`) that runs on the machine's Node.js 24 or newer and is served to every platform without one of its own, answered with `universal: true` (`server/distribution`): its CLI (`agents.cli.name`, such as `acme`) and the runner, `nocobase-runner` (`RUNNER_PRODUCT`). `pnpm nocobase cli build` of `@nocobase/app-cli` packs the CLI the application's `package.json` declares under `nocobase.cli`, and `cli build --runner` the runner, each into a directory of its own, `storage/runners/dist/<channel>/<product>/`, with a `manifest.json` of every file's SHA-256 and size, so CI builds them as separate artifacts mounted into storage, or an application builds them into its own build output and points `agents.dist.dir` there, as NocoBase Studio does. The install script installs the CLI under `~/.local/share/<cli>`: by default the CLI alone, with a download token any signed-in person mints (`POST /api/agents/dist/downloadTokens`, `agDownloadTokens`: the CLI for one platform, three downloads within 30 minutes), as `curl -fsSL <server>/api/agents/dist/installScript | sh -s -- --token <token>`; "Add runtime" shows the same line with `--runner --server <server>` and a registration token, which also installs `nocobase-runner` under `~/.local/share/nocobase-runner`, runs `nocobase-runner register` and `nocobase-runner service install` (an application that serves no CLI still gets its runtime). A token of the other kind fails before anything is installed. A runner reports the product it runs as on registration and every heartbeat (`agRunners.product`), and the heartbeat answer carries an `upgrade` notice when the channel serves a newer version of that product for the runner's platform; a runner that reports none (one from before) is offered no update, and the Runtimes page says to install it again. A product the directory has no current version of may be named on npm instead (`agents.dist.npm`: its package and exact version, which a machine installs with the Node.js 24 or later it already has): the resolve route answers `{ kind: 'npm', product, version, package, channel }` to a caller that sends `accept=npm`, and a heartbeat answer carries `npmUpgrade` to a runner with the `npm` feature when it runs an older version. Everyone else is answered as before (404, no update), and a product the directory has is always served from it. The install script, `<cli> update` and the runner's self-update all ask with `accept=npm` (the runner declares `npm`) and install an npm answer with the machine's npm into the same layout as a tarball: `npm install --prefix <prefix>/versions/<version> --no-save --no-audit --no-fund --omit=optional <package>@<version>`, then a launcher at `versions/<version>/bin/<command>` that starts `node_modules/.bin/<command>` on `<prefix>/node` (`npmLauncherScript` of `@nocobase/app-cli-client/install`).
|
|
16
22
|
|
|
17
|
-
- **Runs** (`agRuns`): one agent working on one subject, keyed by (agent, subject, thread)
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
23
|
+
- **Runs** (`agRuns`): one agent working on one subject, keyed by (agent, subject, thread) (`agentType` is `runner`; `online` only on runs earlier versions kept). New work joins the run already on it as the same person (`actorUserId`) while that run can still be told, else that person's queued one, else starts a new run: work woken by different people never shares a run, so it neither borrows another's identity nor waits for a runner that will not take it. Runs of one key are still claimed one at a time, whoever they work as. Queued runs are claimed by `priority` (lower first; 0 by default), then oldest first; a run given a `fireAt` is not claimed before that moment. Work merged into a queued run raises it to the more urgent priority and the earlier moment of the two. A claim hands a run to a runner that fits in one transaction: the agent's tool enabled, installed and signed in there with its model among those the runner reports for the tool and not marked unavailable there (`runsEntry` in `shared/runners.ts`; recorded on the run as `tool` and `model` and passed to the tool; a model the tool's account cannot use fails the run `modelUnavailable` and marks that tool and model unavailable on the runner, `Runner.unavailableModels`, until it reports the tool's models differently), the runner shared with the team or owned by the person who woke the agent, its features covering what the run needs (worked out from the payload: checkouts, directories, skills, secrets), a team runner when one of the variables the run gets is for team runners only (`teamRunnersOnly`), and a free slot within the agent's concurrency. The variables are checked and opened in the claim's transaction, so the runner receives what was checked; a personal runner left out for them notes on the run which variables asked for a team runner (`teamOnlyVariables`, cleared when the run is taken, requeued or given new input), and its wait is `secretsNotAllowed` with those variables. Before a run exists, `eligibility` (`runnersFor`, `canClaim`, `mayQueue`, `teamOnly`) answers by the same rules whether a runner would take an agent's work done as a person, with the scopes and features the caller names; `availability` and `GET /api/agents/available` use it for the caller. A working directory that is a directory on one runner pins the run to that runner, one run at a time per directory. The claim renders the brief (kept per run, `agRunBriefs`), mints a run token, and hands over the working directories, the merged variables, the skills and the CLI to install. Events, usage and branches are recorded as the runner reports them; completing requires every input to be handled. A runner that finds the subject's working directory held by another live run reports `workspaceBusy`: the run goes back to the queue, freeing its slot, and is tried again after 30 seconds, doubling up to two minutes; these waits do not count against the agent's attempts, and the run fails `workspaceBusy` only once it has waited six hours (`WORKSPACE_WAIT_LIMIT_MS`).
|
|
24
|
+
- **Run requests** (`agRunRequests`): work someone asked of an agent on a subject another person answers for, waiting for that person to confirm it (see "Work someone else causes" below).
|
|
25
|
+
- **Workload** (`runs.workload({ subjectKind, limit? })`, `shared/runs.ts`): the open runs on one kind of subject for a board of work, without claiming anything. Held runs come with their runner, the newest input's trigger and their newest text, tool call, status or error (`lastActivity`); queued runs with their place in the claim order (among the runs claimable now, and among the agent's) and why they wait, by the claim's own rules in its order (`RUN_WAIT_REASONS`: the agent not enabled, `agentArchived`, delayed until a moment, no runner online, the agent's named runners offline, its tool not signed in anywhere, only other people's personal runners, missing features, only personal runners whose owner may not receive the run's variables, the same work already held, the agent's concurrency full, every fitting runner busy, preparation retrying, or next). A wait is a code and the values its words need (`params`), never text: the client words it with `formatRunWait(t, wait)` from `client/runs.ts`, in this plugin's namespace (`runWait.reasons.<reason>`), which an application may override in its locale file or replace with its own formatter. It also answers each agent's load (held, queued, its limit, whether a runner could take its work) and the runners' (online, holding work, slots and slots used). It reads a bounded number of tables, never one query per subject; the caller decides what of it a person may see.
|
|
20
26
|
- **Redaction**: what runners report is stored redacted. The runner redacts first; the server redacts every run event (content, output, input and meta), summary and failure detail, and every job event and failure detail again before storing them, with the protocol's redactor (`createRedactor` of `@nocobase/agent-protocol`): the secrets the claim handed out (a run's variables and token, a job's opened variables, repository token and upload headers, remembered in memory for recent claims) and the common secret patterns, each replaced with `[REDACTED]` (`server/kernel/redaction.ts`). After a restart, or on another instance, the patterns and the runner's own redaction still apply.
|
|
21
27
|
- **The sweep** (`server/runners/sweeper.ts`, the `RunnersSweep` schedule every 30 seconds on the application's jobs service, or an in-process timer without one) marks runners not heard from for 150 s offline, takes jobs back from silent runners and fails jobs far past their timeout, and takes runs back from runners that went away, lost their lease or never started, fails runs idle for twice their idle timeout, records unacknowledged cancellations, cancels queued runs of archived agents, and fails a queued run that waited longer than its subject allows (`queuedExpiryMs` on the subject's binding, counted from the run's last change or from its `fireAt`) as `queuedExpired`.
|
|
22
|
-
- **Variables** (`agSecrets`): environment variables for the agent's process, every one a secret sealed with the application's secrets service (`secrets.keys`) and bound to its scope and name, set on an agent, a working directory (`workdir`) or a scope the application registers, merged for a run in the order the subject names its scopes < its working directories < the agent, delivered only to runners with the `secrets` feature. Values are write-only; reading them back and every delivery are audited (`agSecretAudits`).
|
|
23
|
-
- **Skills** (`agSkills`, `agSkillVersions`, `agSkillAttachments`): a library of skills in the open Agent Skills format (https://agentskills.io/specification): a directory of `SKILL.md` and supporting files, conventionally under `scripts/`, `references/` and `assets/`. Only the front matter of `SKILL.md` names and describes a skill: `name` (1–64 lower-case letters, digits and single hyphens) is its slug and directory, so a save that changes it renames the skill, and `description` (1–1024 characters) is required; `license`, `compatibility` (at most 500 characters), `metadata` (string values) and `allowed-tools` are checked when present, and other keys are kept. Every create, save, restore and import is checked against these rules in the browser as it is typed and on the server (`shared/skill-markdown.ts`), which answers 400 with each problem's `field` and `reason` in `metadata.problems` (`taken` for a name another skill has; `mismatch` for an archive whose folder is named otherwise). Files under `scripts/` or marked executable are scripts (`Skill.scripts`): runners may run them
|
|
24
|
-
- **Conversations** (`agConversations`, `agConversationMessages`): a person chatting with an agent
|
|
25
|
-
- **Chat defaults
|
|
28
|
+
- **Variables** (`agSecrets`): environment variables for the agent's process, every one a secret sealed with the application's secrets service (`secrets.keys`) and bound to its scope and name, set on an agent, a working directory (`workdir`) or a scope the application registers, merged for a run in the order the subject names its scopes < its working directories < the agent, delivered only to runners with the `secrets` feature: to whichever runner takes the run, a personal runner of anyone who may use the agent included, since sharing an agent shares the tokens it works with. A variable marked `teamRunnersOnly` (off by default; `PUT /api/agents/variables/...` with `teamRunnersOnly`, and without `value` to change only that) keeps runs and jobs that get it on team runners. Jobs check the exact variables referenced by their prepared spec, including repository credentials, before opening any value in the claim transaction; a personal runner skips such a job without counting a preparation failure, leaving it queued for a team runner and continuing to other jobs. Values are write-only; reading them back and every delivery are audited (`agSecretAudits`).
|
|
29
|
+
- **Skills** (`agSkills`, `agSkillVersions`, `agSkillAttachments`): a library of skills in the open Agent Skills format (https://agentskills.io/specification): a directory of `SKILL.md` and supporting files, conventionally under `scripts/`, `references/` and `assets/`. Only the front matter of `SKILL.md` names and describes a skill: `name` (1–64 lower-case letters, digits and single hyphens) is its slug and directory, so a save that changes it renames the skill, and `description` (1–1024 characters) is required; `license`, `compatibility` (at most 500 characters), `metadata` (string values) and `allowed-tools` are checked when present, and other keys are kept. Every create, save, restore and import is checked against these rules in the browser as it is typed and on the server (`shared/skill-markdown.ts`), which answers 400 with each problem's `field` and `reason` in `metadata.problems` (`taken` for a name another skill has; `mismatch` for an archive whose folder is named otherwise). Files under `scripts/` or marked executable are scripts (`Skill.scripts`): runners may run them. Every save is a new version that runs get at once, with older versions to compare and restore. Skills are attached to agents, and as defaults to a working directory or a registered scope. A skill's revision is its current version: a save or a restore names the version it was made against (`expectedRevision`) and is refused with 409 `REVISION_CONFLICT` when another save came first. A runner fetches a run's skills from `GET /api/agents/runners/runs/:runId/skills/:slug` and places them where the run's coding tool finds them.
|
|
30
|
+
- **Conversations** (`agConversations`, `agConversationMessages`): a person chatting with an enabled agent, from the chat panel. Only the owner reads a conversation, administrators included; its runs are hidden from everyone they do not involve. Each message the owner sends wakes the agent on the `conversation` subject as the owner, or joins the run already working on it; every text the agent writes becomes a message. A run resumes the session its runner kept; on another runner, or after the conversation switched agents, it starts fresh with the last 20 messages and the previous run's summary. When the agent is disabled or gone, no longer available to the owner, has no online runner that would take the owner's work (`noRunner`), or only other people's personal runners have it (`othersPersonal`), messages are still saved and the conversation reports why; the owner may switch it to the system default chat agent and back (`fallbackFrom` names its own agent meanwhile). Availability uses claim eligibility, including required features and variables restricted to team runners. The owner answers for their own conversation, so none of this asks anyone to confirm. `chatAgents` lists the enabled agents, each with its availability for the caller and whether only personal runners have it (`personalOnly`). Conversations an earlier version answered with an online agent keep `mode` `online`, and their notices (`switchedToOnline`, `onlineFallbackUnavailable`, consultation cards) still render; nothing answers them any more. `shared/conversations` is the contract (HTTP API under `/api/agents/conversations` and `/api/agents/chat*`, page context and its limits, the per-user realtime topic `agents:conversations`); `ConversationService` is the interface other code uses, so the storage can move to a shared platform layer later.
|
|
31
|
+
- **Chat defaults**: the system default chat agent (`agSettings`, `PATCH /api/agents/chatSettings` by who manages `agents.agents`, or the application), each person's default chat agent (`agChatPreferences`), and each agent's "confirm before changing data" (`confirmChanges`: `always` or only `larger` changes).
|
|
26
32
|
- **No setup scripts.** Preparing a working directory is the agent's job: its brief tells it to follow each directory's own instructions (AGENTS.md, CLAUDE.md, README), to install what is missing inside the directory, and to say so (the way the subject's guidance tells it) when it cannot. A working directory's optional initialization prompt reaches the agent only when the runner prepared that directory fresh. "Clean working directory" (`POST /api/agents/workspaces/:subjectKind/:subjectId/reset`) makes the next run start from a fresh checkout.
|
|
27
33
|
|
|
28
|
-
##
|
|
34
|
+
## Model services
|
|
29
35
|
|
|
30
|
-
The plugin keeps
|
|
36
|
+
The plugin keeps model services (`agModelServices`, `server/online/services.ts`) for the application's own model calls, such as a knowledge base's embeddings; agents do not use them. A service has a provider type, a name model prices store (made from the title, never changed), a title, a base URL (the provider's default when empty), an API key sealed with the secrets service as variables are, bound to the service's name, an on/off switch, and the models it offers. A provider may have any number of services. The key is write-only: the API answers `apiKeySet`, never the key. Every request to a provider names the plugin first in its user agent (`nocobase-agents/<version>`); a call to an OpenCode base URL (Zen or Go) additionally carries `x-opencode-session`, a new session id for each call. Deleting a service deletes its model prices. A model's kind (chat, embedding or rerank) is guessed from its id only as a default and can always be changed; checking a model checks it as its kind, and when it fails that way but answers as another kind its provider serves, the check says so (`ModelCheck.looksLike`).
|
|
31
37
|
|
|
32
38
|
The providers (`MODEL_PROVIDERS` in `shared/models.ts`, `server/online/providers.ts`) are Vercel AI SDK provider packages: `@ai-sdk/openai`, `@ai-sdk/anthropic`, `@ai-sdk/google`, `@ai-sdk/deepseek`, `@ai-sdk/alibaba` (Qwen), `@ai-sdk/moonshotai` (Kimi), `@ai-sdk/cohere`, `ollama-ai-provider-v2`, and `@ai-sdk/openai-compatible` for every other endpoint that speaks OpenAI's chat completions. A provider's models are read from its own list-models endpoint (`GET /models`; Anthropic's with its version header, Google's `models` that generate content, Cohere's v1 `models`, Ollama's `/tags`); a model can also be added by id.
|
|
33
39
|
|
|
34
|
-
Each model of a service is of one kind (`ModelKind`), chosen in its row of the service's dialog among the kinds its provider serves (`kinds`): `chat` (
|
|
35
|
-
|
|
36
|
-
The model gateway (`online.gateway`, `server/online/gateway.ts`) is what the executor and the admin API call: `catalog()` (the enabled services that offer a model, names only), `check(ref)` (a short `generateText`, 20 seconds, never throws), `languageModel(ref)`, the chat model an online run's loop runs over, and `stream(request)`, one `streamText` call with tools declared without an implementation, which ends at the tool calls the model made. An online run is the SDK's `ToolLoopAgent` over that model: the run's brief is its instructions, its tools are executed by the SDK step by step (a tool answers `{ ok, output }`, and the model reads `output` through `toModelOutput`), each step's usage is recorded as it finishes, and the loop stops when the model answers without a tool call or after `agents.server.maxSteps` steps (`stepLimit`); an entry's reasoning effort is the SDK's `reasoning` option. Usage is mapped to the protocol's non-overlapping counts (input without cached reads and cache writes; output with reasoning). The SDK retries a failed request twice; a failure throws `ModelError` with a code from the provider's status and error body (`config`, `auth`, `quota`, `rateLimit`, `network`, `contextOverflow`, `filtered`, `badResponse`, `aborted`, `unknown`), which become the run's failure reasons as above. A service without a key whose provider needs one fails `auth` before any request. A run's brief, and a system message marked `cache`, carry Anthropic's `cacheControl` (`ephemeral`), so the brief is read from the cache on every model call of a run after the first; OpenAI caches a long prefix by itself.
|
|
40
|
+
Each model of a service is of one kind (`ModelKind`), chosen in its row of the service's dialog among the kinds its provider serves (`kinds`): `chat` (short texts, `generate`), `embedding` (texts to vectors, with an optional vector size, `dimensions`, asked through each provider's own option) or `rerank` (documents ordered by a query). OpenAI, Google, Alibaba and Ollama serve chat and embedding models; Cohere and OpenAI-compatible endpoints serve all three, an OpenAI-compatible endpoint's reranking being `POST <base>/rerank` in the shape Cohere, Jina, vLLM and SiliconFlow share (`compatibleReranking`); Anthropic, DeepSeek and Moonshot serve chat models only. A model without a kind is a chat model. Testing a model tries it as its kind says.
|
|
37
41
|
|
|
38
|
-
The
|
|
42
|
+
The model gateway (`models.gateway` of `agentsToken`, `server/online/gateway.ts`) is what the application and the admin API call: `catalog(kind?)` (the enabled services that offer a model of the kind, names only), `check(ref)` (a short `generateText`, 20 seconds, never throws), and the calls below. Usage is mapped to non-overlapping counts (input without cached reads and cache writes; output with reasoning). The SDK retries a failed request twice; a failure throws `ModelError` with a code from the provider's status and error body (`config`, `auth`, `quota`, `rateLimit`, `network`, `contextOverflow`, `filtered`, `badResponse`, `aborted`, `unknown`). A service without a key whose provider needs one fails `auth` before any request.
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
An online run may consult another online agent synchronously, as the AI SDK's subagent pattern does: the tool `ask_agent` (`{ agent, question, context? }`, `server/online/consult-tool.ts`) is given to a run whose system prompt lists agents it may consult (`Agents you may consult`, name and the first line of the description), and only then. Those are online agents with a model that the person the run acts for may use (their "who may use it"), not already in the run's chain. The answer comes from a run of its own (`server/core/consultations`): a child of the asking run (`parentRunId`), on the subject `{ kind: 'consultation', id: <asking run> }`, one thread per tool call, one attempt, acting for the same person with its own run token. It is never claimed from the queue: the instance holding the asking run takes it at once (`claims.claimChild`) and runs it within the tool call, aborted with the asking run, within `agents.server.consult.timeoutMs` and `tokenBudget`. It only reads: the gate keeps a consultation's run to reading actions (`…/view`, `…/read`) and those the application marks `consultable` (for example, proposing an operation plan, which reaches as far as the agent and person do and is confirmed by the person in the conversation that asked, `conversations.homeOf`). Consultations go `CONSULT_MAX_DEPTH` (2) deep and never back to an agent already asked; a runner agent is refused with "use a task to delegate to a runner agent". The tool streams preliminary results, which the asking conversation shows as a card (a `consultation` notice, rewritten in place); the asking model reads only the final answer and a note of the plans proposed (`toModelOutput`). The child's transcript and usage are its own, and `RunDetail.children` lists a run's consultations.
|
|
44
|
+
The gateway serves the application's own model calls, each naming who asks (`source`, such as `knowledge`): `embed({ model, values, source })` (`embedMany`, two requests at a time, answering the vectors, their size and the tokens read), `rerank({ model, query, documents, topN?, source })` (the SDK's `rerank`, answering each document's index and score, best first) and `generate({ model, system?, prompt, maxOutputTokens?, source })` (one short text from a chat model, `generateText`). Each names a model of the matching kind (`catalog(kind)` lists them) and throws `ModelError` as a run's calls do. What each used is recorded at once in `agModelUsage` (purpose `embedding`, `rerank` or `text`, the source, the model, its tokens and how many texts or documents), priced from the service's model prices, and reported by `reporting.modelUsage(caller, { from, to })` (`GET /api/agents/usage/models`, behind the usage page's grant, rows only for a reader of every run): the usage page shows it below the runs as "Other model use".
|
|
43
45
|
|
|
44
46
|
## Vectors
|
|
45
47
|
|
|
@@ -56,18 +58,18 @@ An online run may consult another online agent synchronously, as the AI SDK's su
|
|
|
56
58
|
|
|
57
59
|
## Layout
|
|
58
60
|
|
|
59
|
-
| Folder | What is there
|
|
60
|
-
| ------------------------------------------------------ |
|
|
61
|
-
| `server/kernel` | Clock, ids, transactions, events, credentials and secret sealing, scopes, redaction, HTTP helpers
|
|
62
|
-
| `server/core` |
|
|
63
|
-
| `server/online` |
|
|
64
|
-
| `server/vectors` | Vector collections, their embedding queue, the vector store registry, and the `sqlite-vec` and `pgvector` stores
|
|
65
|
-
| `server/runners`, `server/jobs`, `server/distribution` | The runners (registration, keys, heartbeats, slots, the sweeper), the build jobs, and the runner and CLI tarballs
|
|
66
|
-
| `server/routes/runners` | The runner protocol (with a run's `runs/:runId/*` endpoints), the tarballs, the install script and the runners' admin API
|
|
67
|
-
| `server/routes` | The admin, chat and CLI endpoints, and where every endpoint is mounted (`index.ts`)
|
|
68
|
-
| `server/providers` | The service providers that assemble and boot the plugin
|
|
69
|
-
| `shared` | The view models the browser and the API exchange (`models.ts` for
|
|
70
|
-
| `client` | The pages and components; `client/online` the model services UI of the Models page; `client/pages/usage/prices` the prices sheet of the Usage page
|
|
61
|
+
| Folder | What is there |
|
|
62
|
+
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `server/kernel` | Clock, ids, transactions, events, credentials and secret sealing, scopes, redaction, HTTP helpers |
|
|
64
|
+
| `server/core` | Agents, runs and the queue (claims, lifecycle, sweeper), briefs, conversations, the custom command registry, usage, prices and reports, skills, variables |
|
|
65
|
+
| `server/online` | The model services, the providers, the model gateway, and the model endpoints of the admin API |
|
|
66
|
+
| `server/vectors` | Vector collections, their embedding queue, the vector store registry, and the `sqlite-vec` and `pgvector` stores |
|
|
67
|
+
| `server/runners`, `server/jobs`, `server/distribution` | The runners (registration, keys, heartbeats, slots, the sweeper), the build jobs, and the runner and CLI tarballs |
|
|
68
|
+
| `server/routes/runners` | The runner protocol (with a run's `runs/:runId/*` endpoints), the tarballs, the install script and the runners' admin API |
|
|
69
|
+
| `server/routes` | The admin, chat and CLI endpoints, and where every endpoint is mounted (`index.ts`) |
|
|
70
|
+
| `server/providers` | The service providers that assemble and boot the plugin |
|
|
71
|
+
| `shared` | The view models the browser and the API exchange (`models.ts` for the model services and their catalog; `model-catalog.ts` for the models agents are named after) |
|
|
72
|
+
| `client` | The pages and components; `client/online` the model services UI of the Models page; `client/pages/usage/prices` the prices sheet of the Usage page |
|
|
71
73
|
|
|
72
74
|
## HTTP API
|
|
73
75
|
|
|
@@ -83,7 +85,7 @@ Every route lives under the plugin's namespace, `/api/agents`, and names its own
|
|
|
83
85
|
| `/api/agents/cli/*` | Run token header, or the application's authentication | The CLI's custom commands (`CLI_ROUTES.command`); the manifest is the application's `GET /api/cli/manifest` |
|
|
84
86
|
| everything else under `/api/agents` | Session and authorization context | Agents and brief previews, variables, skills, runs, the vocabulary, usage, prices, conversations, the model services and their models |
|
|
85
87
|
|
|
86
|
-
Scoped API keys reach only the routes whose every operation is a settings check (
|
|
88
|
+
Scoped API keys reach only the routes whose every operation is a settings check (skills, model services, prices and usage); elsewhere they are refused with `SCOPED_KEY_FORBIDDEN`. The API checks four settings items, which the plugin lists under an Agent team subsection of the permission workspace: `agents.agents` (manage changes agents and their variables; read sees agents' variables, skills and every run, and every runner; anyone signed in reads the agents themselves, `GET /api/agents`, with `canEdit` for a manager), `agents.runners` (read every runner; manage revokes and deletes any runner, changes a runner whose owner can no longer act and adds team runners; anyone signed in adds personal runners and changes, revokes and deletes their own, and only the owner changes a runner), `agents.prices` (the model prices) and `agents.services` (the model services the application calls: read lists them, manage adds, edits, tests and deletes them and sets their keys; a scoped key may only read them). It also declares one business action with three levels (`BUSINESS_ACTIONS` and `RELATIONS` in `shared/access.ts`), registered as the `agents` resource type under an Agent team subsection of business, one action per level (`edit.related`, `edit.all`), whose level the application tells it through `agentsAccessToken` (`scopeOf(identity, key)`; unbound, every level is `none`): `agents.agents/edit` edits skills (saving, restoring a version), every one at `all` and at `related` the skills the caller created; agents are changed only by who manages them. Managing agents reaches every skill whatever the level; creating and deleting skills still need it. A skill answers `canEdit` for the caller. Anyone signed in reads which model services and models are offered (`GET /api/agents/models`, names only, chat models unless `?kind=embedding` or `rerank` asks for another kind; `shared/models.ts`), and anyone who reads agents may test one (`POST /api/agents/checkModel`). Anyone signed in sees, cancels and retries the runs they started or own, and reads the vocabulary (labels only). A working directory's or a registered scope's variables and default skills follow the scope's kind: it decides who reads and who changes them.
|
|
87
89
|
|
|
88
90
|
Realtime announcements carry no content: `agents:runs:<runId>` when a run's status, transcript or input changes and `agents:runners` when a runner changes. A page that hears one fetches through the API.
|
|
89
91
|
|
|
@@ -91,25 +93,26 @@ Realtime announcements carry no content: `agents:runs:<runId>` when a run's stat
|
|
|
91
93
|
|
|
92
94
|
Everything the application contributes goes through `agentsToken` (`server/tokens.ts`) at boot. Text people read is an `I18nText` (`{ key, ns }`, `shared/i18n`) in the contributor's own namespace.
|
|
93
95
|
|
|
94
|
-
| Extension point | What the application gives
|
|
95
|
-
| --------------------------------------------------------------------- |
|
|
96
|
-
| `subjects.register(binding)` | A kind of subject runs work on: `kind`, `title`, `triggers` (what `input.payload.trigger` values mean, for the run panel), `preview` (a `SubjectSample`: the assembly of a made-up subject of the kind, its values marked with `sampleValue`, offered as a scenario of "Preview full prompt"), `context.assemble` (the brief's task and context, the turn, the working directories, the scopes, and `guidance`: the subject's own lines of the rules and of the environment check), `sink.onRunFinished`, `queuedExpiryMs` (how long a run may wait for a runner; forever without it), `reports.describe` (a subject's label, whether the person may see it, and its `group`)
|
|
97
|
-
| `scopes.register(kind)` | A scope of variables and default skills (`key`, `title`, `description`, `access(scopeId, userId)`). `agent` is reserved; `workdir` is a core key the application registers to decide who may see and change a working directory's.
|
|
98
|
-
| `actions.provide(source)` | The business actions an agent may be configured with (`key`, `group`, `title`, `groupTitle`, `description`, `defaultOn` for the
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `conversations.
|
|
103
|
-
| `conversations.
|
|
104
|
-
| `conversations.
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `events.on('
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
96
|
+
| Extension point | What the application gives |
|
|
97
|
+
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `subjects.register(binding)` | A kind of subject runs work on: `kind`, `title`, `triggers` (what `input.payload.trigger` values mean, for the run panel), `preview` (a `SubjectSample`: the assembly of a made-up subject of the kind, its values marked with `sampleValue`, offered as a scenario of "Preview full prompt"), `context.assemble` (the brief's task and context, the turn, the working directories, the scopes, and `guidance`: the subject's own lines of the rules and of the environment check), `sink.onRunFinished`, `queuedExpiryMs` (how long a run may wait for a runner; forever without it), `reports.describe` (a subject's label, whether the person may see it, and its `group`). Name the commands `assemble` mentions with `commandRef(cli, id, flag?)` (`acme issue get`). |
|
|
99
|
+
| `scopes.register(kind)` | A scope of variables and default skills (`key`, `title`, `description`, `access(scopeId, userId)`). `agent` is reserved; `workdir` is a core key the application registers to decide who may see and change a working directory's. |
|
|
100
|
+
| `actions.provide(source)` | The business actions an agent may be configured with (`key`, `group`, `title`, `groupTitle`, `description`, `defaultOn` for the ones every discovered agent gets unless `agents.setDefaults` says otherwise), and those never granted to an agent, listed only to show the boundary (`grantable: false` with a `reason`). |
|
|
101
|
+
| `agents.setDefaults(provider)` | The instructions and business actions every agent discovered from runners gets (`AgentDefaults`), asked whenever one is written; `agents.applyDefaults()` writes them to every one that differs. Returns what removes the provider. |
|
|
102
|
+
| `agents.ensureSystem(input)` | An agent of the application's own (`SystemAgentInput`: its fixed id, name, description, instructions, business actions and the tools and models it runs with, none until it is configured), created the first time, kept as given and enabled; people do not change it. |
|
|
103
|
+
| `gate.set(gate)` | Who holds which business actions: an `ActionGate` answering `allowed(identity)` for a person or a run, and optionally `consultable(action)` for what a consultation may keep besides reading. `gate.allowed` and `gate.reach` answer for a caller; the gate also bounds what a run may do over the API. |
|
|
104
|
+
| `conversations.sources.register(source)` | A place conversations start from besides the panel (`POST …/chat/start` takes `source` and the first message as the agent should read it). |
|
|
105
|
+
| `conversations.contextKinds.register(kind, resolver)` | A kind of object a page context may reference, resolved for the message's owner. |
|
|
106
|
+
| `conversations.rules.provide(rules)` | Rules and sections added to the system layer of conversation runs. |
|
|
107
|
+
| `conversations.deliver(tx, id, news)`, `conversations.lock(conn, id)` | A `news` notice (`type`, English `title`, `params`) written to a conversation, with input that wakes its agent. |
|
|
108
|
+
| `people.provide(source)` | The application's directory: names, whom to pick from, and who can no longer act (`inactive`: their runners stop). |
|
|
109
|
+
| `events.on('agent.removed', listener)` | An agent was disabled (`agentId`, `name` then, `reason` `disabled`, `byUserId`), after the transaction that withdrew its queued runs commits: the application lets go of the work it gave the agent. The assembling application clears it as executor of unfinished issues (`server/agents/removal.ts`). |
|
|
110
|
+
| `events.on('notice', listener)` | People the plugin wants told (`AgentsNotice`: `key`, `type`, `userIds`, `subject`, English `title` and `body`, `params`): runner notices to their owner, `run_secrets_not_allowed` to a run's actor and owner, and `run_request_expired` to its requester. Subjects are `runner`, `run` or `runRequest`; `notice.cleared` names one that no longer holds. |
|
|
111
|
+
| `jobs.register(kind, registration)` | A kind of build job, for the off-by-default runner build method (see Jobs above). |
|
|
112
|
+
| `reporting.usage`, `reporting.runFigures`, `reporting.range` | What runs used and cost, grouped by agent, person, `group`, `subject`, day, model, tool or agent `type`, and how the runs of a range went with their usage by type (`usageByType`) and day by day (`daily`: runs by outcome, cost by type), for the application's report pages. The plugin serves usage over HTTP for its usage page (`GET /api/agents/usage`, behind the `usage` page grant; every run for a reader of agents, else the caller's own; `series=true` breaks each day of `daily` down by the grouping). |
|
|
113
|
+
| `briefs.sections.register(provider)` | Sections added to every brief's context layer after the subject's own context (`key`, `order`, `section(conn, claim, assembly)` answering Markdown or null), in claims and in brief previews. The context layer is outside the session fingerprint, so a section that changes does not end a resumable session. Database reads only. |
|
|
114
|
+
| `mounts.register(provider)` | Directories of files placed beside the agent (`name`, `forRun(conn, { claim, assembly, session, sessionKey })` answering `{ hash, target, note?, resumeNote? }` or null, and `bundle(conn, { runId })`). Offered at claim only to runners announcing the `mounts` feature, never required, so an older runner runs without them; served at `GET /api/agents/runners/runs/:runId/mounts/:name` while the runner holds the run. A mount's hash stays out of the session fingerprint: a resumed run gets its `resumeNote` in the turn instead. |
|
|
115
|
+
| `repoAccess.register(provider)` | Per run, in the claim's transaction: who the run's commits name and the short-lived credentials its checkouts push with (`forRun(conn, { claim, repos, onDemand })` answering `RunGit` or null). It may read from elsewhere in an optional `prepare(run, { onDemand })` before the transaction. For a runner with the `gitCredentials` feature (`onDemand`), a provider that implements `issue(request)` lists its repositories in `RunGit.onDemand` instead of minting credentials at the claim: the runner then asks `POST /api/agents/runners/runs/:runId/gitCredentials` whenever git needs one, and the plugin calls `issue` outside any transaction (15 s at most) only while that runner holds that attempt of the run under a live lease, for a URL the claim listed, compared exactly. `issue` answers `{ username, password, expiresAt }`, null when the repository is not its own, or throws `RepoAccessError('unavailable' \| 'denied', message)` with a message safe to show; with `refresh` it issues a new credential rather than a cached one. Issued credentials are never stored and are redacted from what the run reports. |
|
|
113
116
|
|
|
114
117
|
`GET /api/agents/vocabulary` hands the browser what the application contributed: subjects (title, triggers, preview), conversation sources, and scopes (title, description).
|
|
115
118
|
|
|
@@ -118,21 +121,53 @@ const agents = container.resolve(agentsToken);
|
|
|
118
121
|
agents.subjects.register({
|
|
119
122
|
kind: 'ticket',
|
|
120
123
|
title: { key: 'subjects.ticket', ns: '@acme/app' },
|
|
121
|
-
context: {
|
|
124
|
+
context: {
|
|
125
|
+
// Optional: the subject's current policy, in the claim transaction. Rejecting cancels without consuming a retry.
|
|
126
|
+
// Also asked before input joins a working run or is delivered to it; rejected input is kept from that run.
|
|
127
|
+
admit: (conn, claim) => /* null, or { reason, detail? }; database reads only */,
|
|
128
|
+
// Optional: the inputs a working run should act on; the rest are marked handled instead of delivered.
|
|
129
|
+
selectInputs: (conn, claim) => /* a subset of claim.inputs; database reads only */,
|
|
130
|
+
assemble: (conn, claim) => /* task, context, working directories; database reads only */,
|
|
131
|
+
},
|
|
122
132
|
sink: { onRunFinished: (tx, run) => /* tell people how the run ended */ },
|
|
123
133
|
});
|
|
124
134
|
await agents.runs.enqueue({ agentId, subject: { kind: 'ticket', id }, actorUserId, priority: -2, input });
|
|
125
135
|
// Withdraws the work no runner took yet, keeping why as the run's failure detail.
|
|
126
136
|
await agents.runs.withdrawQueued({ subject: { kind: 'ticket', id }, byUserId: null, detail: 'The ticket is on hold.' });
|
|
137
|
+
|
|
138
|
+
// Work on a subject someone answers for: the ticket's assignee confirms what anyone else causes.
|
|
139
|
+
const result = await agents.runs.enqueue({ agentId, subject, responsibleUserId: assigneeId, requestedByUserId: commenterId, input });
|
|
140
|
+
if (result.outcome === 'pending') {
|
|
141
|
+
// A run request (`agents.runs.requests`) waits for the assignee; nothing is queued.
|
|
142
|
+
}
|
|
143
|
+
// What a run itself causes (a status it changed) keeps that run's source rather than the assignee's.
|
|
144
|
+
await agents.runs.enqueue({ agentId, subject, responsibleUserId: assigneeId, causedByRunId: run.id, input });
|
|
145
|
+
// The assignee changed: pending requests go to the new one (or nowhere, with `toUserId: null`).
|
|
146
|
+
await agents.runs.requests.reassign({ subject, toUserId: newAssigneeId, byUserId });
|
|
127
147
|
```
|
|
128
148
|
|
|
129
149
|
`assemble` runs inside the claim's transaction and must not call a network or a model (nor do brief sections and mounts, which read through the claim's connection only: on SQLite the transaction holds the one connection there is; a section or mount provider reads what it needs from elsewhere, such as a person's permissions, in its optional `prepare(run)`, which runs before the transaction and whose answer it gets back); throwing leaves the run queued, and three failures fail it `setupFailed`. `enqueue` takes an optional outer transaction; inside another plugin's transaction, publish the collected events after that transaction commits.
|
|
130
150
|
|
|
151
|
+
### Work someone else causes
|
|
152
|
+
|
|
153
|
+
Work somebody causes on a subject another person answers for runs only with that person's consent, or on the asker's own account. `enqueue` takes the subject's `responsibleUserId`, the source of the chain of work `requestedByUserId` (the actor by default), or `causedByRunId` for work a run caused, and `execution`:
|
|
154
|
+
|
|
155
|
+
- The source is the responsible, or nobody answers for the subject: the work is queued as before, run as the responsible (or as `actorUserId`).
|
|
156
|
+
- The source is someone else and `execution` is `auto` (the default): nothing is queued. A run request (`agRunRequests`) keeps the input as it was asked and waits for the responsible; `enqueue` answers `outcome: 'pending'` with its `requestId`.
|
|
157
|
+
- `execution: 'mine'`: the work is queued at once as the source, on a runner they may use (their own or a team runner, never the responsible's own). With none online it is refused with `NO_RUNNER_AVAILABLE` instead of waiting unseen.
|
|
158
|
+
- `causedByRunId`: the source is that run's, who confirmed it or else who it was requested by, so a chain somebody else started never runs as the responsible unconfirmed. Runs record it as `requestedByUserId`, and the confirmer as `confirmedByUserId`.
|
|
159
|
+
|
|
160
|
+
Only the request's responsible confirms it (queued as them with the input as it was asked, its actor the asker, joining only a run acting as them while it takes input) or rejects it; not an administrator, a manager of agents or a run acting for them. Confirming checks again that they may still wake the agent. A subject with mutable responsibility should bind `SubjectBinding.responsibleUserId(conn, subjectId)`, which reads the current responsible inside the confirmation or rejection transaction; a changed or null responsible prevents the old responsible from acting even before `reassign` is called. Without that resolver the request uses its recorded responsible, so the application must call `reassign` with the subject's responsibility change. The asker withdraws it, or runs it as themselves. People do this over `GET /api/agents/runRequests` (`role=responsible&status=pending` is an inbox), `GET /api/agents/runRequests/{requestId}`, and `POST …/{requestId}/confirm`, `reject`, `withdraw` and `runAsMe`, by session or unscoped API key only. Concurrent settlement returns 409.
|
|
161
|
+
|
|
162
|
+
A request settles once, and keeps the work's `fireAt` and `maxAttempts` for its run. Nobody settling it within seven days (`RUN_REQUEST_TTL_MS`) expires it on the sweep, and the asker gets a `run_request_expired` notice offering to run it as themselves. A request past its time counts as expired everywhere, before the sweep too. When the responsible changes, `runs.requests.reassign` supersedes the pending requests and asks the new responsible; one already past its time expires instead of being renewed. If the new responsible is null, the agent is unavailable or the new responsible cannot invoke it, the request expires and notifies the asker instead, preserving `runAsMe`. Every change is announced as `runRequest.created`, `confirmed`, `rejected`, `withdrawn`, `superseded` or `expired`, with the request.
|
|
163
|
+
|
|
164
|
+
Creating an `auto` request requires that both the source and the responsible may invoke the agent. Repeated enqueues with identical pending work reuse its request without another creation event or a renewed expiry; comparison includes the input snapshot, execution options, subject, thread and both people. Different input or scheduling options remain separate requests.
|
|
165
|
+
|
|
131
166
|
## The CLI's commands
|
|
132
167
|
|
|
133
168
|
The CLI's commands are the application's API routes: `GET /api/cli/manifest` (`@nocobase/app-server/router`) answers every command the API document describes for the caller, named and shaped by each route's `x-cli` extension, and this plugin tells it who calls (a run by its run token, a person by the application's authentication) and which business actions each holds (`gate.allowed`). A run token is also a credential of the application's authentication (`server/cli/run-credential.ts`): a request carrying it acts for the person who woke the agent, as a scoped session the routes accept only where their security lists `runToken`; the application bounds it by its scope (for example, `server/agents/run-principal.ts`). A route lists `runToken` and gives its `x-cli` an `action` for the commands a run may use.
|
|
134
169
|
|
|
135
|
-
The plugin's own commands are its routes. A run uses `run self`, `run context` and `conversation title set` (`GET /api/agents/runs/current`, `/current/context`, `PATCH /current/conversation`, action `agents.runs/self`), and a run or a person `agent list` (`GET /api/agents/available`, action `agents.agents/view`: the agents the caller may give work to, with what each is good at and whether it can take work now). The rest are a person's: `agent list-all|get|
|
|
170
|
+
The plugin's own commands are its routes. A run uses `run self`, `run context` and `conversation title set` (`GET /api/agents/runs/current`, `/current/context`, `PATCH /current/conversation`, action `agents.runs/self`), and a run or a person `agent list` (`GET /api/agents/available`, action `agents.agents/view`: the agents the caller may give work to, with what each is good at and whether it can take work now). The rest are a person's: `agent list-all|get|update|history|brief`, `agent action list`, `skill …` (with `skill version …` and `skill attachment get|set`), `variable list|set|delete|reveal` and `variable audit list` (positional scope kind and scope), `runtime list|get|update|revoke|delete|work` and `runtime token create`, `model list|check|usage` and `model price get|set`, `service list|create|update|delete|discover|check`, `conversation list|get|create|update|stop|fallback|restore`, `conversation message list|send`, `conversation preferences|settings get|update`, and `run list|get|events|brief|cancel|retry|usage`, `run workspace reset` and `run request list|get|confirm|reject|withdraw|run-as-me`. The runner protocol, the downloads and the browser's helpers (the vocabulary, the people picker, every agent's name, the chat agent picker, starting a conversation from a page, marking one read) stay off the command line. The application's routes and custom commands are the rest.
|
|
136
171
|
|
|
137
172
|
## Workspace
|
|
138
173
|
|
|
@@ -157,10 +192,9 @@ agents:
|
|
|
157
192
|
dir: /srv/runners-dist # relative to the application root; storage/runners/dist by default
|
|
158
193
|
channel: stable
|
|
159
194
|
versions: { acme: 0.1.0 } # pin a product instead of the channel's highest
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
consult: { timeoutMs: 120000, tokenBudget: 200000 } # one agent consulting another (ask_agent)
|
|
195
|
+
npm: # optional; a product with no tarball in dir is named on npm instead, to callers that understand it
|
|
196
|
+
nocobase-runner: { package: '@nocobase/agent-runner', version: 1.0.0 } # an exact version, never a range
|
|
197
|
+
|
|
164
198
|
vectors: # optional; vector collections, apart from the application's database
|
|
165
199
|
store: sqlite-vec # the default; pgvector, or false to turn vectors off
|
|
166
200
|
path: storage/vectors.sqlite # sqlite-vec's file, relative to the application root
|
|
@@ -180,16 +214,22 @@ Model services are not configured here: they are added on the application's page
|
|
|
180
214
|
|
|
181
215
|
The plugin registers no routes of its own: an application mounts its pages and joins them to the pages of the runner agents do. The assembling application puts them under "Agent team" in its sidebar.
|
|
182
216
|
|
|
183
|
-
- `@nocobase/app-plugin-agents/client/routes` exports `agentsRoute` (`/agents
|
|
184
|
-
- Runtimes (on `/api/agents/runners`): one overview row per runtime — its name with its system, its state with the slots in use ("Busy 1/1", "Offline · 3 hours ago"), its coding tools by sign-in, personal or team, its runner version (marked "Upgradable" when a newer version of the product it runs as is served, with `nocobase-runner update`, or `<cli> runner update` for a CLI that carries the runner; the runner also updates itself) and when it was last seen — with a "…" menu (Edit, then revoke or delete). A row opens the runtime's sheet: General (name, concurrent runs, personal or team after a warning, and "Allow build jobs" only when the application gives runners jobs, as an application's off-by-default runner build method does), Tools (a switch per reported tool with its version, sign-in and, when the API sent it, its path as small text), Local policy (read only: what its owner's policy on the machine lets it take) and Recent runs (`GET /agents/runners/:runnerId/runs`). Only its owner
|
|
185
|
-
- Agents
|
|
217
|
+
- `@nocobase/app-plugin-agents/client/routes` exports `agentsRoute` (`/agents`), `runtimesRoute` (`/runtimes`, with the `connect` dialog), `skillsRoute` (`/skills`, with `new` and `:skillId`) and `usageRoute` (`/usage`: what runs used and cost over a date range, filtered by group, agent and person and summed by one of the groupings (`?groupBy=`, agent by default), with a daily chart of tokens or cost above the table, stacked by the top five agents or models when grouped by those (the usage route's `series`), its group and subject named and linked by the vocabulary's `groupTitle`, `path` and `groupPath`; for who reads `agents.prices` a "Set prices" header button opens the prices sheet, `?prices=1`: models by service and model, coding tools by the models their runs report, each tool with its subscription switch and price rules, changed by who manages it; the note on missing prices links to it). Each page renders its own heading, and stands behind a page grant of the same id as its route name (`agents`, `runtimes`, `skills`, `usage`, exported as `PAGES` from `shared/access`); a page grant only opens the page, and what it shows is decided by the admin API on the settings items. It also exports `modelsRoute` (`/models`), which stands behind `agents.services` read instead: the model services (a page header with "Add service", then a table with one row per service: its name and host, provider type, status and a menu to edit it, turn it on or off or delete it; "Add service" and clicking a row open one dialog with a single form saved at once: provider type when adding, name, base URL, the write-only key as a `SecretInput` (`client/components/secret-input.tsx`: a password field whose empty value keeps the saved key), an OpenCode base URL's note on which provider type serves which of its model families (its session header is sent automatically), connection test, models fetched from the provider or added by id and checked, each with its kind, changeable before and after it is checked, and a Test that checks it as that kind, and an on/off switch), changeable by who manages `agents.services`.
|
|
218
|
+
- Runtimes (on `/api/agents/runners`): one overview row per runtime — its name with its system, its state with the slots in use ("Busy 1/1", "Offline · 3 hours ago"), its coding tools by sign-in, personal or team, its runner version (marked "Upgradable" when a newer version of the product it runs as is served, with `nocobase-runner update`, or `<cli> runner update` for a CLI that carries the runner; the runner also updates itself) and when it was last seen — with a "…" menu (Edit, then revoke or delete). A row opens the runtime's sheet: General (name, concurrent runs, personal or team after a warning, and "Allow build jobs" only when the application gives runners jobs, as an application's off-by-default runner build method does), Tools (a switch per reported tool with its version, sign-in and, when the API sent it, its path as small text), Local policy (read only: what its owner's policy on the machine lets it take) and Recent runs (`GET /agents/runners/:runnerId/runs`). Only its owner changes it (the managers of runners only a runner whose owner can no longer act); a manager of runners sees someone else's read only, with revoke or delete as the only menu items. Its owner, the managers of runners and anyone who may use an agent get its host name and its tools' paths from the API, everyone else neither. "Add runtime" asks who it works for (team only for managers of runners), which coding tools it may run (all by default) and its max concurrent runs (1 by default, carried by the token; a runner registered with its own `--slots` keeps that), then shows the one-line install and the `nocobase-runner register` command with a one-time token (copy buttons, expiry), and waits until the runtime connects, then shows the coding tools it reported.
|
|
219
|
+
- Agents (`client/pages/agents`, on `GET /api/agents`): one row per agent discovered from runners, filtered by All, Enabled, To enable and No runner: its name with its tool and model, what it is good at, where it can run now (the team and personal runners online with it, the caller's own counted, with a few of their names; "personal runners only", or when a runner last reported it), its default reasoning effort and its state. For who manages `agents.agents`, a pending agent offers "Fill in and enable" and the others "Edit": one dialog (`agent-dialog.tsx`) with what it is good at (started from the catalog's suggestion in the viewer's language), the effort among those its tool takes, and, when editing, whether it is enabled, saved against the revision it shows. Everyone else reads. Under the table, how to add an agent: connect a runner whose tool has the model. An application that keeps agents of its own composes `RunnerAgentsSection` (from `client/kit`) into its own page instead.
|
|
186
220
|
- Skills: the library (each skill's name, description, compatibility and whether it holds scripts), and a skill as a directory: its files in a tree beside the selected one (`client/pages/skills/workbench/`), SKILL.md rendered, other text shown, images and PDFs previewed. Editing uses the same workbench: files and folders are created (in a folder chosen from the skill's and the conventional `scripts/`, `references/`, `assets/`), uploaded (also by dropping files onto a folder), renamed and deleted from the tree, never by typing a path; SKILL.md and other Markdown are written beside their preview (in tabs on a narrow pane), with the front matter's problems listed above the source as it is typed. A new skill (`/skills/new`, a covering page) starts from a template of front matter and suggested sections. Versions can be compared with the current one and restored, and the page shows where the skill is attached. When someone saved a version while the editor was open, the draft stays and a banner offers to load the latest version. A scope's default skills list the scripts of the chosen skills, which online agents do not run (`SkillScriptsNotice`).
|
|
187
|
-
- The new
|
|
188
|
-
- `@nocobase/app-plugin-agents/client/kit` exports `VariablesSection` and `DefaultSkillsSection` for a scope's settings on the application's pages (`scope` `workdir` or a registered key, with an optional `description`), `useRunnerOptions` for picking the runner a directory is on (with how many runners are `online`), and `useAgentOptions` for picking an agent.
|
|
221
|
+
- The new skill and variable dialogs ask "Discard unsaved changes?" before closing with input in them (NP-200), through `@nocobase/app-client`'s unsaved-changes guard.
|
|
222
|
+
- `@nocobase/app-plugin-agents/client/kit` exports `RunnerAgentsSection` (the Agent page's list, for an application's own page), `VariablesSection` and `DefaultSkillsSection` for a scope's settings on the application's pages (`scope` `workdir` or a registered key, with an optional `description`), `useRunnerOptions` for picking the runner a directory is on (with how many runners are `online`), and `useAgentOptions` for picking an agent.
|
|
189
223
|
- `@nocobase/app-plugin-agents/client/runs` exports the headless parts of a subject's runs, for the application to present (the assembling application uses the UI Library's `agent-run-history`): `useSubjectRuns` and `useAgentNames`, `useRunWithTranscript` (a run and its transcript, fetched after the last `seq` seen when the run's realtime topic announces events, and polled every five seconds while the run is open), `useStopRun`, `useRetryRun`, `useRunBrief` and `useWorkspaceReset`. Each reads and writes the plugin's shared query cache.
|
|
190
224
|
- `@nocobase/app-plugin-agents/client/chat` is the agents' chat without its UI. The UI — the panel beside the content area, one conversation as a page, the history and the header, floating and "Ask agent" launchers — is the UI Library's `agent-chat` block (`@nocobase/agent-chat`, installed with `shadcn add @nocobase/agent-chat` into `client/extensions/nocobase-agent-chat/`; its README is `ui-library/registry/agents/agent-chat/README.md` in the NocoBase repository), which the application owns and builds on this entry. What stays here is what has to stay consistent across upgrades: `ChatProvider` around the application's routes (panel state, ⌘J / Ctrl+J, `?chat=<id|new|history>` links, page context, the one subscription to the per-user conversations topic while the chat is available, and optionally `conversationPath`, the application's full-page route of a conversation), `useChatPanel()` (`available` is false without the provider), `chatLinkRoutes(base)` (links under a path the application chooses that open the panel), `useChatContextSource` / `useChatFilterSource` for pages to say what they show, and `ChatExtensionsContext`, with which the application adds items among a conversation's messages (`useTimelineItems`), renders under a message (`renderMessageExtra`), words the news it delivers (`newsText`) and shows a news notice as a card of its own (`renderNews`).
|
|
191
225
|
- The data hooks `useChatAgents`, `useConversation`, `useConversationMessages` (the newest page first, `loadOlder`, newer messages with `messages?after=<lastSeq>` on each announcement and polled while a run is open, optimistic messages through `dispatch`), `useConversationList(query)` (an infinite query over the viewer's conversations), `useSendMessage`, `useConversationActions` and `useChatApi`, keyed by `chatKeys`; `useLiveRunEvents(runId)` (a run's transcript kept current while it runs) and `useConversationSources()` (where a conversation can start from, translated); the pure models `timelineOrder`, `newConversationAgent`, `noticeText`, `liveStepsView` and `stepLineText`, and `contextChips`, `buildPageContext`, `itemKey`, `selectionPreview`, `filterText` and `SOURCE_ATTRIBUTE` for the context chips; the panel's state helpers (`CHAT_PANEL_STORAGE_KEY`, `CHAT_PARAM`, `CHAT_DOCK_QUERY`, `CHAT_MOBILE_QUERY`, `readPanelState`, `isChatShortcut`, `modifierKeyLabel`); `ChatPanelScope`, `useChatPageTracking`, `CHAT_PANEL_ID` and `CHAT_PANEL_ATTRIBUTE` for a full-page view; and the kit's `AgentAvatar`, `useAgentText` and `useFormatters`. The data hooks read and write this plugin's cache (`agentsQueryClient()`) and word their toasts in its namespace whatever is above them, so a chat UI needs only `ChatProvider` and no `withAgents` wrapper. `client/runs` also exports `useRunEvents`, `useRealtimeTopic` and `useAgentsApi`, and `client/kit` exports `useFormatters`.
|
|
192
|
-
- `@nocobase/app-plugin-agents/client/profile` exports `DefaultAgentPreference`: the person's default chat agent, for the application's preferences page. The
|
|
193
|
-
- `@nocobase/app-plugin-agents/client/config` exports `AgentActionCatalogContext`: the agent
|
|
226
|
+
- `@nocobase/app-plugin-agents/client/profile` exports `DefaultAgentPreference`: the person's default chat agent, for the application's preferences page. The system default chat agent is the application's to set (`PATCH /api/agents/chatSettings`).
|
|
227
|
+
- `@nocobase/app-plugin-agents/client/config` exports `AgentActionCatalogContext`: the business actions an agent can be given, from the server (`GET /api/agents/actions`: what the application offers, none without it) unless an application gives another catalog. No page of the plugin edits an agent's actions any more; they are the application's defaults.
|
|
194
228
|
|
|
195
229
|
Each exported component brings the plugin's translations and its own query cache, so it works inside another plugin's tree.
|
|
230
|
+
|
|
231
|
+
A subject assembly may return `inputs` to select the effective claim inputs. Use the same selection when rendering its task and turn; runner and online claims deliver that selection and pass it to brief sections and mounts. Omitting `inputs` preserves delivery of all queued input. Omitted inputs are resolved in the claim transaction and stay in the audit history; they cannot reappear during polling or prevent completion.
|
|
232
|
+
|
|
233
|
+
### Scoped work summaries
|
|
234
|
+
|
|
235
|
+
`agents.runs.workingOn(subjectKind, subjectIds)` returns each subject/agent pair with a `dispatched` or `running` run once, as `{ subjectId, agentId, working: true }`. Empty scopes return nothing. Reads are restricted to the supplied kind and IDs, without the workload board's global limit; queued and terminal runs are excluded. This service exposes no run details and does not enforce viewer permissions or approval rules: the consuming application must filter visible subjects first and apply its own waiting rules.
|