@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
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
* team or belongs to the person who woke the agent, its features cover what the run requires (worked out from the
|
|
7
7
|
* payload: checkouts, directories, skills, secrets), its owner's local policy (`Runner.policy`) lets it take the
|
|
8
8
|
* agent's runs on the run's subject and repositories, and it has a free slot. A working directory that is a directory
|
|
9
|
-
* on one runner pins the run to that runner, one run at a time per directory.
|
|
9
|
+
* on one runner pins the run to that runner, one run at a time per directory. A run's variables go to the runner that
|
|
10
|
+
* takes it, personal ones included, unless one of them is for team runners only (`teamRunnersOnly`): then only a team
|
|
11
|
+
* runner takes the run, and the variables that asked for one are noted on it (`teamOnlyVariables`), so its wait says
|
|
12
|
+
* which.
|
|
10
13
|
*
|
|
11
14
|
* A slot is free for a run when the runner's total has room and so does the coding tool it runs with: the tool's limit
|
|
12
15
|
* (`Runner.toolSlots`, never above the total) over the runs of that tool the runner holds here, and what the runner
|
|
@@ -14,6 +17,10 @@
|
|
|
14
17
|
* agent's entries whose tool the runner runs and has room for, so an agent listing two tools runs with the second while
|
|
15
18
|
* the first is full; a run none of whose tools has room is passed over for the runs behind it.
|
|
16
19
|
*
|
|
20
|
+
* Variables are checked and opened in the claim's own transaction, on its connection: which ones the assembled payload
|
|
21
|
+
* gets, whether any is for team runners only, and their values, so what the runner receives is what was checked. The
|
|
22
|
+
* names taken from the runner go in `workspace.passthrough`, without values.
|
|
23
|
+
*
|
|
17
24
|
* A claim is one transaction per run. It first writes the agent's row (`lockAgentForClaim`): on databases with row
|
|
18
25
|
* locks, concurrent claims for the same agent wait there, so the concurrency count read next is current. The run is
|
|
19
26
|
* then taken with a guarded update (`status = 'queued'`), so two runners can never take the same run. The payload is
|
|
@@ -22,39 +29,32 @@
|
|
|
22
29
|
*
|
|
23
30
|
* Portable by design: the database layer offers no `FOR UPDATE SKIP LOCKED` or advisory locks, and the guarded update
|
|
24
31
|
* plus the agent-row write give the same guarantees on every dialect (SQLite serializes writers anyway).
|
|
25
|
-
|
|
26
|
-
* Runners take only runner agents' runs. Online agents' runs are taken by the application itself (`claimServer`, for the
|
|
27
|
-
* server executor of each instance), through the same guarded update, so two instances never take the same run: the
|
|
28
|
-
* holder is the instance (`server:<instance>`), there is no per-agent or per-holder limit, and the payload is a brief,
|
|
29
|
-
* the run's token and its skills (read in the run's sandbox, `online/sandbox.ts`), without directories, variables or
|
|
30
|
-
* mounts.
|
|
32
|
+
|
|
31
33
|
*/
|
|
32
|
-
import { policyAllowsAgent, policyAllowsRepo, policyAllowsSubject, TIMINGS, } from '@nocobase/agent-protocol';
|
|
33
|
-
import {
|
|
34
|
+
import { ANNOUNCED_FAILURES, isProtocolSupported, policyAllowsAgent, policyAllowsRepo, policyAllowsSubject, TIMINGS, } from '@nocobase/agent-protocol';
|
|
35
|
+
import { runnerLowOnDisk, runsEntry, toolLimit, supportsWorkspaceKey, } from '../../../shared/runners.js';
|
|
36
|
+
import { queueStart } from './selection.js';
|
|
34
37
|
import { createHash } from 'node:crypto';
|
|
35
|
-
import { onlineEntriesOrDefault, runnerEntries, sameEntry, } from '../../../shared/agents.js';
|
|
36
38
|
import { later } from '../../kernel/clock.js';
|
|
37
39
|
import { notFound } from '../../kernel/errors.js';
|
|
38
40
|
import { runSecretsKey } from '../../kernel/redaction.js';
|
|
39
41
|
import { cleanList, covers } from '../../kernel/values.js';
|
|
40
42
|
import { findAgent, lockAgentForClaim } from '../agents/index.js';
|
|
41
|
-
import {
|
|
42
|
-
import { joinBrief, onlineSkillsSection, renderBrief, } from '../brief/index.js';
|
|
43
|
+
import { joinBrief, renderBrief } from '../brief/index.js';
|
|
43
44
|
import { cliPackageFor } from './cli-package.js';
|
|
45
|
+
import { executionHistory } from './execution.js';
|
|
46
|
+
import { describeVariables, variableRefs, } from '../variables/index.js';
|
|
44
47
|
import { mountsFor, prepareExtensions, repoAccessFor, sessionKeyOf, withSections, } from './extensions.js';
|
|
45
|
-
import { dialectOf, } from './ports.js';
|
|
46
48
|
import { MAX_CLAIM_FAILURES, toolPolicyFor } from './policy.js';
|
|
47
49
|
import { mintRunToken } from './run-tokens.js';
|
|
48
50
|
import { runsHeldByTool } from './runner-view.js';
|
|
49
51
|
import { ACTIVE, countActive, eventsRepo, findRunRecord, markDelivered, pendingInputs, runsOfKey, runsRepo, sessionsRepo, toInput, toRun, } from './run.store.js';
|
|
52
|
+
import { dropInputs } from './input-gate.js';
|
|
50
53
|
import { finishRun } from './transitions.js';
|
|
54
|
+
import { refreshQueuedIdentity } from './identity.js';
|
|
51
55
|
import { consumeReset, saveBrief } from './workspace.store.js';
|
|
52
56
|
/** Queued runs looked at per claim, oldest first by priority. */
|
|
53
57
|
const CANDIDATES = 50;
|
|
54
|
-
/** Whether a run holder id is an application instance's (an online run's), not a runner's. */
|
|
55
|
-
export function isServerHolder(runnerId) {
|
|
56
|
-
return runnerId !== null && runnerId.startsWith('server:');
|
|
57
|
-
}
|
|
58
58
|
class AssemblyError extends Error {
|
|
59
59
|
cause;
|
|
60
60
|
constructor(message, cause) {
|
|
@@ -70,6 +70,15 @@ class NotForThisRunner extends Error {
|
|
|
70
70
|
this.name = 'NotForThisRunner';
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
/** The run gets variables only team runners may receive, and this runner is a personal one. */
|
|
74
|
+
class TeamRunnersOnly extends NotForThisRunner {
|
|
75
|
+
variables;
|
|
76
|
+
constructor(variables) {
|
|
77
|
+
super();
|
|
78
|
+
this.variables = variables;
|
|
79
|
+
this.name = 'TeamRunnersOnly';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
73
82
|
function toolRoom(tools) {
|
|
74
83
|
const left = new Map(Object.entries(tools ?? {}));
|
|
75
84
|
return {
|
|
@@ -82,50 +91,50 @@ function toolRoom(tools) {
|
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
/**
|
|
85
|
-
* The entry `runner` takes a run of `agent` with: the first whose tool it has enabled, installed and signed in
|
|
86
|
-
*
|
|
94
|
+
* The entry `runner` takes a run of `agent` with: the first whose tool it has enabled, installed and signed in, with
|
|
95
|
+
* the entry's model among those it reports (`runsEntry`). Null when it has none of them.
|
|
87
96
|
*/
|
|
88
97
|
export function pickEntry(runner, agent) {
|
|
89
|
-
return
|
|
98
|
+
return agent.modelEntries.find((entry) => runsEntry(runner, entry)) ?? null;
|
|
90
99
|
}
|
|
91
100
|
/**
|
|
92
101
|
* The entry `runner` takes a run of `agent` with when some of its tools are full: the first whose tool it runs and
|
|
93
102
|
* `open` says has room. Null when none has.
|
|
94
103
|
*/
|
|
95
104
|
export function pickOpenEntry(runner, agent, open) {
|
|
96
|
-
return (
|
|
105
|
+
return (agent.modelEntries.find((entry) => runsEntry(runner, entry) && open(entry.tool)) ?? null);
|
|
97
106
|
}
|
|
98
|
-
/** Whether `runner` has one of `agent`'s tools enabled, installed
|
|
107
|
+
/** Whether `runner` has one of `agent`'s tools and models enabled, installed, signed in and reported. */
|
|
99
108
|
export function hasTool(runner, agent) {
|
|
100
109
|
return pickEntry(runner, agent) !== null;
|
|
101
110
|
}
|
|
102
111
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
112
|
+
* Whether `runner` may run work of `agent` as `actorUserId` that needs `requires`, before any lock is taken and before
|
|
113
|
+
* a payload is known: the agent enabled, its tool and model reported there, its owner's policy, and trust.
|
|
105
114
|
*/
|
|
106
|
-
export function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
/** Whether `runner` may run `run` of `agent`, before any lock is taken and before its payload is known. */
|
|
113
|
-
export function fits(runner, agent, run) {
|
|
114
|
-
if (agent.archivedAt || agent.type !== 'runner')
|
|
115
|
+
export function fitsActor(runner, agent, actorUserId, requires) {
|
|
116
|
+
if (agent.status !== 'enabled' || runnerLowOnDisk(runner))
|
|
117
|
+
return false;
|
|
118
|
+
if (!isProtocolSupported(runner.protocolVersion) ||
|
|
119
|
+
runner.status === 'upgrade_required' ||
|
|
120
|
+
runner.status === 'revoked')
|
|
115
121
|
return false;
|
|
116
|
-
if (!covers(runner.features,
|
|
122
|
+
if (!covers(runner.features, requires))
|
|
117
123
|
return false;
|
|
118
124
|
if (!hasTool(runner, agent))
|
|
119
125
|
return false;
|
|
120
126
|
if (!policyAllowsAgent(runner.policy, agent))
|
|
121
127
|
return false;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
return runner.trust === 'team' || runner.ownerUserId === actorUserId;
|
|
129
|
+
}
|
|
130
|
+
/** Whether `runner` may run `run` of `agent`, before any lock is taken and before its payload is known. */
|
|
131
|
+
export function fits(runner, agent, run) {
|
|
132
|
+
return fitsActor(runner, agent, run.actorUserId, toRun(run).requires);
|
|
125
133
|
}
|
|
126
134
|
/** The runner features a payload needs. */
|
|
127
|
-
export function payloadRequires(dirs, skills, variables) {
|
|
135
|
+
export function payloadRequires(dirs, skills, variables, workspaceKey = false) {
|
|
128
136
|
return [
|
|
137
|
+
...(workspaceKey ? ['workspaceKey'] : []),
|
|
129
138
|
...(dirs.some((dir) => dir.kind === 'repo') ? ['checkout'] : []),
|
|
130
139
|
...(dirs.some((dir) => dir.kind === 'directory')
|
|
131
140
|
? ['directories']
|
|
@@ -172,7 +181,6 @@ function fingerprint(agent, entry, layers, skills) {
|
|
|
172
181
|
/** The brief for `assembly`, with the skills a run would get. */
|
|
173
182
|
export function briefOf(agent, assembly, skills, cli, appName) {
|
|
174
183
|
const rendered = renderBrief({
|
|
175
|
-
dialect: dialectOf(agent),
|
|
176
184
|
agentName: agent.name,
|
|
177
185
|
subject: { noun: assembly.subject.noun, key: assembly.subject.key },
|
|
178
186
|
task: assembly.task,
|
|
@@ -192,6 +200,10 @@ export function briefOf(agent, assembly, skills, cli, appName) {
|
|
|
192
200
|
: assembly.turn.prompt;
|
|
193
201
|
return { layers, turn, prompt: joinBrief(layers) };
|
|
194
202
|
}
|
|
203
|
+
/** Whether `runner` asks for repository credentials on demand rather than taking them with the claim. */
|
|
204
|
+
export function asksCredentialsOnDemand(runner) {
|
|
205
|
+
return runner.features.includes('gitCredentials');
|
|
206
|
+
}
|
|
195
207
|
const DIRECTORY_KEY_SEPARATOR = '\n';
|
|
196
208
|
/** The directories a run holds on its runner, as stored in `agRuns.directoryKey`. */
|
|
197
209
|
function directoryKeyOf(runnerId, dirs) {
|
|
@@ -214,8 +226,214 @@ async function directoryBusy(conn, runnerId, runId, key) {
|
|
|
214
226
|
.split(DIRECTORY_KEY_SEPARATOR)
|
|
215
227
|
.some((part) => part !== '' && wanted.has(part)));
|
|
216
228
|
}
|
|
229
|
+
/** Resolve omitted subject input in the claim transaction, keeping it in the audit history. */
|
|
230
|
+
async function settleClaimInputs(conn, pending, effective, now) {
|
|
231
|
+
const ids = new Set(effective.map((input) => input.id));
|
|
232
|
+
await dropInputs(conn, pending.filter((input) => !ids.has(input.id)).map((input) => input.id), now);
|
|
233
|
+
await markDelivered(conn, pending.filter((input) => ids.has(input.id)), now);
|
|
234
|
+
}
|
|
217
235
|
export function createClaimService(deps) {
|
|
218
236
|
const { tx, clock } = deps;
|
|
237
|
+
/** Database reads only; used by the actual claim and ordered-model diagnostics. */
|
|
238
|
+
async function assemblyCompatibility(conn, run, agent, runner, assembly) {
|
|
239
|
+
if (!isProtocolSupported(runner.protocolVersion) ||
|
|
240
|
+
(assembly.workspaceKey && !supportsWorkspaceKey(runner)))
|
|
241
|
+
return 'incompatible';
|
|
242
|
+
const skills = await deps.skills.forRun(conn, skillTargets(agent, assembly), run.id);
|
|
243
|
+
const targets = variableTargets(agent, assembly);
|
|
244
|
+
const names = await deps.variables.namesOf(conn, targets);
|
|
245
|
+
if (!covers(runner.features, [
|
|
246
|
+
...run.requires,
|
|
247
|
+
...payloadRequires(payloadDirs(assembly.dirs), skills.length, names.length, Boolean(assembly.workspaceKey)),
|
|
248
|
+
]))
|
|
249
|
+
return 'incompatible';
|
|
250
|
+
if (!fitsActor(runner, agent, run.actorUserId, run.requires) ||
|
|
251
|
+
!policyAllowsSubject(runner.policy, assembly.subject.key) ||
|
|
252
|
+
assembly.dirs.some((dir) => (dir.kind === 'repo' && !policyAllowsRepo(runner.policy, dir.url)) ||
|
|
253
|
+
(dir.kind === 'directory' && dir.runnerId !== runner.id)))
|
|
254
|
+
return 'restricted';
|
|
255
|
+
if (runner.trust !== 'team' &&
|
|
256
|
+
(await deps.variables.teamOnly(conn, targets)).length > 0)
|
|
257
|
+
return 'restricted';
|
|
258
|
+
return 'ready';
|
|
259
|
+
}
|
|
260
|
+
async function selectionFacts(conn, run, agent, requirePolicy = true) {
|
|
261
|
+
const policy = await deps.selectionPolicies?.forRun(conn, run);
|
|
262
|
+
if ((requirePolicy && !policy) || !deps.runners)
|
|
263
|
+
return null;
|
|
264
|
+
const now = clock.now();
|
|
265
|
+
const start = queueStart(run);
|
|
266
|
+
const registered = await deps.runners.all(conn);
|
|
267
|
+
const binding = deps.subjects.get(run.subject.kind);
|
|
268
|
+
if (!binding)
|
|
269
|
+
throw new Error(`No context provider for ${run.subject.kind}.`);
|
|
270
|
+
const inputs = (await pendingInputs(conn, run.id)).map(toInput);
|
|
271
|
+
const active = await countActive(conn, 'agentId', agent.id);
|
|
272
|
+
const sameWork = (await runsOfKey(conn, {
|
|
273
|
+
agentId: agent.id,
|
|
274
|
+
subjectKind: run.subject.kind,
|
|
275
|
+
subjectId: run.subject.id,
|
|
276
|
+
threadScope: run.threadScope,
|
|
277
|
+
}, ACTIVE)).length > 0;
|
|
278
|
+
const entries = [];
|
|
279
|
+
for (const entry of agent.modelEntries) {
|
|
280
|
+
const single = { ...agent, modelEntries: [entry] };
|
|
281
|
+
const candidates = registered.filter((runner) => runner.status !== 'revoked');
|
|
282
|
+
const connected = candidates.filter((runner) => (runner.status === 'online' ||
|
|
283
|
+
runner.status === 'upgrade_required') &&
|
|
284
|
+
runner.lastSeenAt !== null &&
|
|
285
|
+
new Date(runner.lastSeenAt).getTime() + TIMINGS.offlineAfterMs >
|
|
286
|
+
now.getTime());
|
|
287
|
+
const installed = connected.filter((runner) => runner.tools.some((tool) => tool.kind === entry.tool));
|
|
288
|
+
const usable = installed.filter((runner) => runsEntry(runner, entry));
|
|
289
|
+
const online = usable.filter((runner) => runner.trust === 'team' || runner.ownerUserId === run.actorUserId);
|
|
290
|
+
const compatible = [];
|
|
291
|
+
const loads = [];
|
|
292
|
+
let unknown = false;
|
|
293
|
+
let incompatible = false;
|
|
294
|
+
let ready = false;
|
|
295
|
+
let directoryBlocked = false;
|
|
296
|
+
for (const runner of online) {
|
|
297
|
+
if (!isProtocolSupported(runner.protocolVersion) ||
|
|
298
|
+
runner.status === 'upgrade_required') {
|
|
299
|
+
incompatible = true;
|
|
300
|
+
loads.push({
|
|
301
|
+
name: runner.name,
|
|
302
|
+
ownerUserId: runner.ownerUserId,
|
|
303
|
+
reason: 'incompatible',
|
|
304
|
+
lastSeenAt: runner.lastSeenAt,
|
|
305
|
+
});
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const assembly = await binding.context
|
|
309
|
+
.assemble(conn, {
|
|
310
|
+
run: run,
|
|
311
|
+
agent,
|
|
312
|
+
runner,
|
|
313
|
+
inputs,
|
|
314
|
+
cli: deps.cli.name,
|
|
315
|
+
appName: deps.app.name,
|
|
316
|
+
})
|
|
317
|
+
.catch(() => null);
|
|
318
|
+
if (!assembly) {
|
|
319
|
+
unknown = true;
|
|
320
|
+
loads.push({
|
|
321
|
+
name: runner.name,
|
|
322
|
+
ownerUserId: runner.ownerUserId,
|
|
323
|
+
reason: 'unknown',
|
|
324
|
+
lastSeenAt: runner.lastSeenAt,
|
|
325
|
+
});
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
const reason = await assemblyCompatibility(conn, run, single, runner, assembly);
|
|
329
|
+
if (reason !== 'ready') {
|
|
330
|
+
incompatible ||= reason === 'incompatible';
|
|
331
|
+
loads.push({
|
|
332
|
+
name: runner.name,
|
|
333
|
+
ownerUserId: runner.ownerUserId,
|
|
334
|
+
reason,
|
|
335
|
+
lastSeenAt: runner.lastSeenAt,
|
|
336
|
+
});
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const requiredVariables = await deps.variables.passthroughOf(conn, variableTargets(single, assembly));
|
|
340
|
+
if (requiredVariables.length > 0 && runner.variables == null) {
|
|
341
|
+
unknown = true;
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
if (requiredVariables.some((name) => !runner.variables?.includes(name)))
|
|
345
|
+
continue;
|
|
346
|
+
compatible.push(runner);
|
|
347
|
+
const byTool = await runsHeldByTool(conn, runner.id);
|
|
348
|
+
const used = await deps.slotsUsed(conn, runner.id);
|
|
349
|
+
const directory = directoryKeyOf(runner.id, payloadDirs(assembly.dirs));
|
|
350
|
+
const blockedDirectory = directory !== null &&
|
|
351
|
+
(await directoryBusy(conn, runner.id, run.id, directory));
|
|
352
|
+
directoryBlocked ||= blockedDirectory;
|
|
353
|
+
const hasRoom = !runner.draining &&
|
|
354
|
+
(runner.globalFree ?? 1) > 0 &&
|
|
355
|
+
used < runner.slots &&
|
|
356
|
+
(byTool[entry.tool] ?? 0) < toolLimit(runner, entry.tool) &&
|
|
357
|
+
(runner.toolLoad?.[entry.tool]?.free ?? 1) > 0 &&
|
|
358
|
+
!blockedDirectory;
|
|
359
|
+
ready ||= hasRoom && runner.globalFree !== undefined;
|
|
360
|
+
if (hasRoom && runner.globalFree === undefined)
|
|
361
|
+
unknown = true;
|
|
362
|
+
loads.push({
|
|
363
|
+
name: runner.name,
|
|
364
|
+
ownerUserId: runner.ownerUserId,
|
|
365
|
+
reason: hasRoom
|
|
366
|
+
? runner.globalFree === undefined
|
|
367
|
+
? 'unknown'
|
|
368
|
+
: 'ready'
|
|
369
|
+
: runner.draining
|
|
370
|
+
? runner.draining
|
|
371
|
+
: blockedDirectory
|
|
372
|
+
? 'restricted'
|
|
373
|
+
: 'busy',
|
|
374
|
+
lastSeenAt: runner.lastSeenAt,
|
|
375
|
+
used,
|
|
376
|
+
limit: runner.slots,
|
|
377
|
+
toolUsed: byTool[entry.tool] ?? 0,
|
|
378
|
+
toolLimit: toolLimit(runner, entry.tool),
|
|
379
|
+
reportedFree: runner.toolLoad?.[entry.tool]?.free,
|
|
380
|
+
reportedTotalFree: runner.globalFree,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
let reason = compatible.length
|
|
384
|
+
? ready
|
|
385
|
+
? 'ready'
|
|
386
|
+
: 'busy'
|
|
387
|
+
: online.length
|
|
388
|
+
? incompatible
|
|
389
|
+
? 'incompatible'
|
|
390
|
+
: 'restricted'
|
|
391
|
+
: usable.length
|
|
392
|
+
? 'noSharedRunner'
|
|
393
|
+
: installed.length
|
|
394
|
+
? 'toolUnavailable'
|
|
395
|
+
: connected.length
|
|
396
|
+
? 'toolNotInstalled'
|
|
397
|
+
: 'offline';
|
|
398
|
+
if (directoryBlocked && !ready)
|
|
399
|
+
reason = 'restricted';
|
|
400
|
+
if (!ready &&
|
|
401
|
+
compatible.length > 0 &&
|
|
402
|
+
loads.every((runner) => runner.reason === 'updatePending' || runner.reason === 'pruning'))
|
|
403
|
+
reason = loads.some((runner) => runner.reason === 'updatePending')
|
|
404
|
+
? 'updatePending'
|
|
405
|
+
: 'pruning';
|
|
406
|
+
if (unknown &&
|
|
407
|
+
!ready &&
|
|
408
|
+
!loads.some((runner) => runner.reason === 'busy'))
|
|
409
|
+
reason = 'unknown';
|
|
410
|
+
if (compatible.length && sameWork)
|
|
411
|
+
reason = 'sameWorkActive';
|
|
412
|
+
else if (compatible.length && active >= agent.maxConcurrentRuns)
|
|
413
|
+
reason = 'concurrencyFull';
|
|
414
|
+
else if (start > now.getTime())
|
|
415
|
+
reason = 'delayed';
|
|
416
|
+
entries.push({
|
|
417
|
+
tool: entry.tool,
|
|
418
|
+
model: entry.model,
|
|
419
|
+
reason,
|
|
420
|
+
compatibleCount: compatible.length,
|
|
421
|
+
blockers: [
|
|
422
|
+
...(unknown ? ['unknown'] : []),
|
|
423
|
+
...new Set(loads
|
|
424
|
+
.map((runner) => runner.reason)
|
|
425
|
+
.filter((reason) => reason !== undefined && reason !== 'ready')),
|
|
426
|
+
],
|
|
427
|
+
runners: loads,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
return {
|
|
431
|
+
queueEnteredAt: new Date(start).toISOString(),
|
|
432
|
+
fallbackAfterSeconds: policy?.fallbackAfterSeconds ?? 0,
|
|
433
|
+
sampledAt: now.toISOString(),
|
|
434
|
+
entries,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
219
437
|
async function assemble({ conn }, run, agent, runner, inputs, leaseExpiresAt, prepared, entry) {
|
|
220
438
|
const binding = deps.subjects.get(run.subjectKind);
|
|
221
439
|
if (!binding)
|
|
@@ -228,9 +446,13 @@ export function createClaimService(deps) {
|
|
|
228
446
|
inputs,
|
|
229
447
|
cli: deps.cli.name,
|
|
230
448
|
appName: deps.app.name,
|
|
231
|
-
dialect: 'cli',
|
|
232
449
|
};
|
|
233
|
-
const assembly = await binding.context.assemble(conn, claim);
|
|
450
|
+
const assembly = await binding.context.assemble(conn, claim, prepared.get('subject'));
|
|
451
|
+
// workspace.key is required for coordinating runs; old runners must not silently ignore it.
|
|
452
|
+
if ((await assemblyCompatibility(conn, toRun(run), agent, runner, assembly)) === 'incompatible')
|
|
453
|
+
throw new NotForThisRunner();
|
|
454
|
+
inputs = assembly.inputs ?? inputs;
|
|
455
|
+
const effectiveClaim = { ...claim, inputs };
|
|
234
456
|
// Its owner's local policy keeps this runner off the subject, or off one of the repositories: another runner takes
|
|
235
457
|
// the run.
|
|
236
458
|
if (!policyAllowsSubject(runner.policy, assembly.subject.key) ||
|
|
@@ -249,16 +471,25 @@ export function createClaimService(deps) {
|
|
|
249
471
|
const names = await deps.variables.namesOf(conn, variables);
|
|
250
472
|
const requires = cleanList([
|
|
251
473
|
...view.requires,
|
|
252
|
-
...payloadRequires(dirs, skills.length, names.length),
|
|
474
|
+
...payloadRequires(dirs, skills.length, names.length, Boolean(assembly.workspaceKey)),
|
|
253
475
|
]);
|
|
254
476
|
if (!covers(runner.features, requires))
|
|
255
477
|
throw new NotForThisRunner();
|
|
478
|
+
// A variable for team runners only keeps a personal runner off the run.
|
|
479
|
+
if (names.length > 0 && runner.trust !== 'team') {
|
|
480
|
+
const teamOnly = await deps.variables.teamOnly(conn, variables);
|
|
481
|
+
if (teamOnly.length > 0)
|
|
482
|
+
throw new TeamRunnersOnly(teamOnly);
|
|
483
|
+
}
|
|
256
484
|
const env = names.length > 0
|
|
257
485
|
? await deps.variables.forRun(conn, variables, {
|
|
258
486
|
runId: run.id,
|
|
259
487
|
runnerId: runner.id,
|
|
260
488
|
})
|
|
261
489
|
: [];
|
|
490
|
+
// Variables taken from the runner: names only. A runner that does not provide one fails the run while preparing
|
|
491
|
+
// it, saying how to provide it; runners are not chosen by them.
|
|
492
|
+
const passthrough = await deps.variables.passthroughOf(conn, variables);
|
|
262
493
|
const nowText = clock.now().toISOString();
|
|
263
494
|
const clean = await consumeReset(conn, { kind: run.subjectKind, id: run.subjectId }, run.id, nowText);
|
|
264
495
|
const session = await sessionsRepo(conn).findOne({
|
|
@@ -274,6 +505,7 @@ export function createClaimService(deps) {
|
|
|
274
505
|
const git = await repoAccessFor(conn, deps.repoAccess, {
|
|
275
506
|
claim,
|
|
276
507
|
repos: dirs.filter((dir) => dir.kind === 'repo'),
|
|
508
|
+
onDemand: asksCredentialsOnDemand(runner),
|
|
277
509
|
}, prepared);
|
|
278
510
|
deps.secrets?.remember(runSecretsKey(run.id), [
|
|
279
511
|
...env.map((variable) => variable.value),
|
|
@@ -284,9 +516,10 @@ export function createClaimService(deps) {
|
|
|
284
516
|
filter: { runId: run.id },
|
|
285
517
|
sort: (sort) => sort.field('seq').desc(),
|
|
286
518
|
});
|
|
287
|
-
const brief = briefOf(agent, await withSections(conn, deps.sections,
|
|
519
|
+
const brief = briefOf(agent, await withSections(conn, deps.sections, effectiveClaim, assembly, prepared), skills, deps.cli.name, deps.app.name);
|
|
288
520
|
const briefFingerprint = fingerprint(agent, entry, brief.layers, skills);
|
|
289
|
-
const resume = !
|
|
521
|
+
const resume = !run.freshSession &&
|
|
522
|
+
!clean &&
|
|
290
523
|
session &&
|
|
291
524
|
!session.poisoned &&
|
|
292
525
|
session.fingerprint === briefFingerprint;
|
|
@@ -294,13 +527,23 @@ export function createClaimService(deps) {
|
|
|
294
527
|
// hears what changed in them in its turn instead.
|
|
295
528
|
const { mounts, resumeNotes } = runner.features.includes('mounts')
|
|
296
529
|
? await mountsFor(conn, deps.mounts, {
|
|
297
|
-
claim,
|
|
530
|
+
claim: effectiveClaim,
|
|
298
531
|
assembly,
|
|
299
532
|
session: resume ? 'resume' : 'fresh',
|
|
300
533
|
sessionKey: sessionKeyOf(view),
|
|
301
534
|
}, prepared)
|
|
302
535
|
: { mounts: [], resumeNotes: [] };
|
|
303
|
-
const
|
|
536
|
+
const sessionNote = resume ? assembly.turn.resumed : assembly.turn.fresh;
|
|
537
|
+
const turn = [
|
|
538
|
+
brief.turn,
|
|
539
|
+
...(run.failureReason === 'runnerUpgrade'
|
|
540
|
+
? [
|
|
541
|
+
'The previous attempt was interrupted by a runner upgrade. Continue from the current state.',
|
|
542
|
+
]
|
|
543
|
+
: []),
|
|
544
|
+
...resumeNotes,
|
|
545
|
+
...(sessionNote ? [sessionNote] : []),
|
|
546
|
+
].join('\n\n');
|
|
304
547
|
await saveBrief(conn, () => deps.ids.next(), {
|
|
305
548
|
runId: run.id,
|
|
306
549
|
attempt: Number(run.attempt),
|
|
@@ -319,6 +562,7 @@ export function createClaimService(deps) {
|
|
|
319
562
|
leaseExpiresAt,
|
|
320
563
|
requires,
|
|
321
564
|
firstSeq: (last ? Number(last.seq) : 0) + 1,
|
|
565
|
+
acceptedFailures: Object.keys(ANNOUNCED_FAILURES),
|
|
322
566
|
},
|
|
323
567
|
app: deps.app,
|
|
324
568
|
subject: {
|
|
@@ -340,9 +584,13 @@ export function createClaimService(deps) {
|
|
|
340
584
|
},
|
|
341
585
|
inputs,
|
|
342
586
|
workspace: {
|
|
587
|
+
sessionScope: run.threadScope,
|
|
343
588
|
dirs,
|
|
344
589
|
env,
|
|
590
|
+
...(passthrough.length > 0 ? { passthrough } : {}),
|
|
345
591
|
...(clean ? { clean: true } : {}),
|
|
592
|
+
...(assembly.workspaceKey ? { key: assembly.workspaceKey } : {}),
|
|
593
|
+
...(assembly.readOnly ? { readOnly: true } : {}),
|
|
346
594
|
...(git ? { git } : {}),
|
|
347
595
|
},
|
|
348
596
|
skills,
|
|
@@ -368,75 +616,266 @@ export function createClaimService(deps) {
|
|
|
368
616
|
requires,
|
|
369
617
|
directoryKey,
|
|
370
618
|
entry,
|
|
619
|
+
gitOnDemand: git?.onDemand ?? [],
|
|
371
620
|
};
|
|
372
621
|
}
|
|
622
|
+
/**
|
|
623
|
+
* Notes on a queued run which of its variables kept a personal runner off it, and tells its actor and owner the first
|
|
624
|
+
* time; nothing when that is what it says already.
|
|
625
|
+
*/
|
|
626
|
+
async function noteTeamOnly(candidate, variables) {
|
|
627
|
+
const same = (value) => JSON.stringify(variableRefs(value)) === JSON.stringify(variables);
|
|
628
|
+
if (same(candidate.teamOnlyVariables))
|
|
629
|
+
return;
|
|
630
|
+
await tx.run(async (unit) => {
|
|
631
|
+
const run = await findRunRecord(unit.conn, candidate.id);
|
|
632
|
+
if (!run || run.status !== 'queued' || same(run.teamOnlyVariables))
|
|
633
|
+
return;
|
|
634
|
+
await runsRepo(unit.conn).updateMany({
|
|
635
|
+
filter: (f) => f.and([f.string('id').eq(run.id), f.string('status').eq('queued')]),
|
|
636
|
+
values: { teamOnlyVariables: variables.map((each) => ({ ...each })) },
|
|
637
|
+
});
|
|
638
|
+
unit.emit({ type: 'run.changed', runId: run.id, status: 'queued' });
|
|
639
|
+
if (variableRefs(run.teamOnlyVariables).length === 0)
|
|
640
|
+
unit.emit({
|
|
641
|
+
type: 'notice',
|
|
642
|
+
notice: {
|
|
643
|
+
key: `run-secrets:${run.id}`,
|
|
644
|
+
type: 'run_secrets_not_allowed',
|
|
645
|
+
userIds: [
|
|
646
|
+
...new Set([run.actorUserId, run.ownerUserId].filter((id) => Boolean(id))),
|
|
647
|
+
],
|
|
648
|
+
subject: { kind: 'run', id: run.id, label: run.id },
|
|
649
|
+
title: 'A run waits for a team runtime',
|
|
650
|
+
body: `Some of its variables are for team runtimes only: ${describeVariables(variables)}.`,
|
|
651
|
+
params: {
|
|
652
|
+
runId: run.id,
|
|
653
|
+
agentId: run.agentId,
|
|
654
|
+
variables: describeVariables(variables),
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
async function admit(unit, run, agent, runner, inputs) {
|
|
661
|
+
const rejection = await deps.subjects
|
|
662
|
+
.get(run.subjectKind)
|
|
663
|
+
?.context.admit?.(unit.conn, {
|
|
664
|
+
run: toRun(run),
|
|
665
|
+
agent,
|
|
666
|
+
runner,
|
|
667
|
+
inputs,
|
|
668
|
+
cli: deps.cli.name,
|
|
669
|
+
appName: deps.app.name,
|
|
670
|
+
});
|
|
671
|
+
if (!rejection)
|
|
672
|
+
return true;
|
|
673
|
+
await finishRun(unit, deps, run, {
|
|
674
|
+
status: 'cancelled',
|
|
675
|
+
reason: null,
|
|
676
|
+
detail: `${rejection.reason}${rejection.detail ? `: ${rejection.detail}` : ''}`,
|
|
677
|
+
});
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
373
680
|
async function attempt(runner, agent, candidate, reported) {
|
|
374
|
-
//
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
agent.maxConcurrentRuns)
|
|
383
|
-
return { kind: 'skipped' };
|
|
384
|
-
// Slots are shared with the jobs the runner holds.
|
|
385
|
-
if ((await deps.slotsUsed(conn, runner.id)) >= runner.slots)
|
|
386
|
-
return { kind: 'skipped' };
|
|
387
|
-
// The first of the agent's tools with room, by its limit here and by what the runner said it can take.
|
|
388
|
-
const byTool = await runsHeldByTool(conn, runner.id);
|
|
389
|
-
const entry = pickOpenEntry(runner, agent, (tool) => (byTool[tool] ?? 0) < toolLimit(runner, tool) && reported.has(tool));
|
|
390
|
-
if (!entry)
|
|
391
|
-
return { kind: 'skipped' };
|
|
392
|
-
const busy = await runsOfKey(conn, candidate, ACTIVE);
|
|
393
|
-
if (busy.length > 0)
|
|
394
|
-
return { kind: 'skipped' };
|
|
395
|
-
const leaseExpiresAt = later(now, TIMINGS.leaseMs);
|
|
396
|
-
const taken = await runsRepo(conn).updateMany({
|
|
397
|
-
filter: (f) => f.and([
|
|
398
|
-
f.string('id').eq(candidate.id),
|
|
399
|
-
f.string('status').eq('queued'),
|
|
400
|
-
]),
|
|
401
|
-
values: {
|
|
402
|
-
status: 'dispatched',
|
|
403
|
-
runnerId: runner.id,
|
|
404
|
-
leaseExpiresAt,
|
|
405
|
-
dispatchedAt: nowText,
|
|
406
|
-
lastActivityAt: nowText,
|
|
407
|
-
availableAt: null,
|
|
408
|
-
updatedAt: nowText,
|
|
409
|
-
},
|
|
681
|
+
// Repair pre-upgrade queued work before even checking personal runner ownership.
|
|
682
|
+
if (deps.subjects.get(candidate.subjectKind)?.actsAs) {
|
|
683
|
+
const current = await tx.run(async (unit) => {
|
|
684
|
+
await lockAgentForClaim(unit.conn, agent.id, clock.now().toISOString());
|
|
685
|
+
const run = await findRunRecord(unit.conn, candidate.id);
|
|
686
|
+
return run?.status === 'queued'
|
|
687
|
+
? refreshQueuedIdentity(unit, deps, run)
|
|
688
|
+
: null;
|
|
410
689
|
});
|
|
411
|
-
if (
|
|
690
|
+
if (!current)
|
|
412
691
|
return { kind: 'skipped' };
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
692
|
+
candidate = current;
|
|
693
|
+
}
|
|
694
|
+
// Avoid assembling or asking authorization when a cheap claim rule already rules this work out.
|
|
695
|
+
const conn = tx.read();
|
|
696
|
+
if (!fits(runner, agent, candidate) ||
|
|
697
|
+
(await deps.slotsUsed(conn, runner.id)) >= runner.slots ||
|
|
698
|
+
(await countActive(conn, 'agentId', agent.id)) >=
|
|
699
|
+
agent.maxConcurrentRuns ||
|
|
700
|
+
(await runsOfKey(conn, candidate, ACTIVE)).length > 0)
|
|
701
|
+
return { kind: 'skipped' };
|
|
702
|
+
// Before the transaction: on SQLite it holds the only connection, so the providers read what else they need now.
|
|
703
|
+
const prepared = new Map(await prepareExtensions(toRun(candidate), deps.sections, deps.mounts, (error) => deps.onClaimFailure?.(candidate.id, error), deps.repoAccess, { onDemand: asksCredentialsOnDemand(runner) }));
|
|
704
|
+
const subjectContext = deps.subjects.get(candidate.subjectKind)?.context;
|
|
705
|
+
if (subjectContext?.prepare) {
|
|
416
706
|
try {
|
|
417
|
-
|
|
707
|
+
prepared.set('subject', await subjectContext.prepare(toRun(candidate)));
|
|
418
708
|
}
|
|
419
709
|
catch (error) {
|
|
420
|
-
|
|
421
|
-
throw error;
|
|
422
|
-
throw new AssemblyError(error instanceof Error ? error.message : String(error), error);
|
|
710
|
+
deps.onClaimFailure?.(candidate.id, error);
|
|
423
711
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
712
|
+
}
|
|
713
|
+
let taken;
|
|
714
|
+
try {
|
|
715
|
+
taken = await tx.run(async (unit) => {
|
|
716
|
+
const { conn } = unit;
|
|
717
|
+
const now = clock.now();
|
|
718
|
+
const nowText = now.toISOString();
|
|
719
|
+
await lockAgentForClaim(conn, agent.id, nowText);
|
|
720
|
+
const queuedRun = await findRunRecord(conn, candidate.id);
|
|
721
|
+
if (!queuedRun || queuedRun.status !== 'queued')
|
|
722
|
+
return null;
|
|
723
|
+
const identity = await refreshQueuedIdentity(unit, deps, queuedRun);
|
|
724
|
+
// Providers were prepared for the candidate's identity outside this transaction.
|
|
725
|
+
if (!identity || identity.actorUserId !== candidate.actorUserId)
|
|
726
|
+
return null;
|
|
727
|
+
if ((await countActive(conn, 'agentId', agent.id)) >=
|
|
728
|
+
agent.maxConcurrentRuns)
|
|
729
|
+
return null;
|
|
730
|
+
// Slots are shared with the jobs the runner holds.
|
|
731
|
+
if ((await deps.slotsUsed(conn, runner.id)) >= runner.slots)
|
|
732
|
+
return null;
|
|
733
|
+
// The first of the agent's tools with room, by its limit here and by what the runner said it can take.
|
|
734
|
+
const byTool = await runsHeldByTool(conn, runner.id);
|
|
735
|
+
const current = await findRunRecord(conn, candidate.id);
|
|
736
|
+
if (!current ||
|
|
737
|
+
current.status !== 'queued' ||
|
|
738
|
+
(current.availableAt &&
|
|
739
|
+
new Date(current.availableAt).getTime() > now.getTime()))
|
|
740
|
+
return null;
|
|
741
|
+
const entry = pickOpenEntry(runner, agent, (tool) => (byTool[tool] ?? 0) < toolLimit(runner, tool) && reported.has(tool));
|
|
742
|
+
if (!entry)
|
|
743
|
+
return null;
|
|
744
|
+
const busy = await runsOfKey(conn, candidate, ACTIVE);
|
|
745
|
+
if (busy.length > 0)
|
|
746
|
+
return null;
|
|
747
|
+
const leaseExpiresAt = later(now, TIMINGS.leaseMs);
|
|
748
|
+
const claimed = await runsRepo(conn).updateMany({
|
|
749
|
+
filter: (f) => f.and([
|
|
750
|
+
f.string('id').eq(candidate.id),
|
|
751
|
+
f.string('status').eq('queued'),
|
|
752
|
+
f.string('actorUserId').eq(candidate.actorUserId),
|
|
753
|
+
]),
|
|
754
|
+
values: {
|
|
755
|
+
status: 'dispatched',
|
|
756
|
+
runnerId: runner.id,
|
|
757
|
+
// Brief providers observe this reservation inside the claim transaction.
|
|
758
|
+
// Replace a previous attempt's tool before computing the roster.
|
|
759
|
+
tool: entry.tool,
|
|
760
|
+
leaseExpiresAt,
|
|
761
|
+
dispatchedAt: nowText,
|
|
762
|
+
lastActivityAt: nowText,
|
|
763
|
+
availableAt: null,
|
|
764
|
+
updatedAt: nowText,
|
|
765
|
+
},
|
|
766
|
+
});
|
|
767
|
+
if (claimed.updatedCount !== 1)
|
|
768
|
+
return null;
|
|
769
|
+
const run = (await findRunRecord(conn, candidate.id));
|
|
770
|
+
const pending = await pendingInputs(conn, run.id);
|
|
771
|
+
let assembled;
|
|
772
|
+
let selectionSnapshot;
|
|
773
|
+
try {
|
|
774
|
+
if (!(await admit(unit, run, agent, runner, pending.map(toInput))))
|
|
775
|
+
return null;
|
|
776
|
+
// Admission must precede preflight assembly: a missing or obsolete
|
|
777
|
+
// subject is cancelled normally, rather than counted as setup failure.
|
|
778
|
+
const selection = await selectionFacts(conn, toRun(current), agent);
|
|
779
|
+
const elapsed = Math.max(0, (now.getTime() - queueStart(toRun(current))) / 1000);
|
|
780
|
+
const preferredAvailable = (selection?.entries[0]?.compatibleCount ?? 0) > 0 ||
|
|
781
|
+
selection?.entries[0]?.reason === 'unknown' ||
|
|
782
|
+
selection?.entries[0]?.blockers?.includes('unknown') === true;
|
|
783
|
+
const chosenIndex = agent.modelEntries.indexOf(entry);
|
|
784
|
+
if (selection && chosenIndex > 0) {
|
|
785
|
+
// Throw to roll back the provisional dispatch; the original run keeps
|
|
786
|
+
// waiting for its first choice without consuming an attempt or token.
|
|
787
|
+
if (preferredAvailable && elapsed < selection.fallbackAfterSeconds)
|
|
788
|
+
throw new NotForThisRunner();
|
|
789
|
+
selectionSnapshot = {
|
|
790
|
+
reason: preferredAvailable
|
|
791
|
+
? 'preferredQueued'
|
|
792
|
+
: 'preferredUnavailable',
|
|
793
|
+
preferredTool: agent.modelEntries[0].tool,
|
|
794
|
+
preferredModel: agent.modelEntries[0].model,
|
|
795
|
+
queueEnteredAt: selection.queueEnteredAt,
|
|
796
|
+
waitedSeconds: elapsed,
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
assembled = await assemble(unit, run, agent, runner, pending.map(toInput), leaseExpiresAt, prepared, entry);
|
|
800
|
+
}
|
|
801
|
+
catch (error) {
|
|
802
|
+
if (error instanceof NotForThisRunner)
|
|
803
|
+
throw error;
|
|
804
|
+
throw new AssemblyError(error instanceof Error ? error.message : String(error), error);
|
|
805
|
+
}
|
|
806
|
+
await settleClaimInputs(conn, pending, assembled.payload.inputs, nowText);
|
|
807
|
+
await runsRepo(conn).updateMany({
|
|
808
|
+
filter: { id: run.id },
|
|
809
|
+
values: {
|
|
810
|
+
payloadFingerprint: assembled.fingerprint,
|
|
811
|
+
requires: [...assembled.requires],
|
|
812
|
+
directoryKey: assembled.directoryKey,
|
|
813
|
+
tool: assembled.entry.tool,
|
|
814
|
+
executionHistory: executionHistory(run, {
|
|
815
|
+
...(selectionSnapshot ? { selection: selectionSnapshot } : {}),
|
|
816
|
+
attempt: Number(run.attempt),
|
|
817
|
+
runnerId: runner.id,
|
|
818
|
+
runnerName: runner.name,
|
|
819
|
+
runnerOwnerUserId: runner.ownerUserId,
|
|
820
|
+
runnerOwnerName: runner.ownerUserId
|
|
821
|
+
? ((await deps.people?.names(conn, [runner.ownerUserId]))?.get(runner.ownerUserId) ?? runner.ownerName)
|
|
822
|
+
: null,
|
|
823
|
+
runnerTrust: runner.trust,
|
|
824
|
+
tool: assembled.entry.tool,
|
|
825
|
+
toolVersion: runner.tools.find((tool) => tool.kind === assembled.entry.tool)
|
|
826
|
+
?.version ?? null,
|
|
827
|
+
modelService: null,
|
|
828
|
+
model: assembled.entry.model,
|
|
829
|
+
actualModels: [],
|
|
830
|
+
effort: assembled.entry.effort ?? null,
|
|
831
|
+
dispatchedAt: nowText,
|
|
832
|
+
finishedAt: null,
|
|
833
|
+
failureReason: null,
|
|
834
|
+
}),
|
|
835
|
+
modelService: null,
|
|
836
|
+
model: assembled.entry.model,
|
|
837
|
+
effort: assembled.entry.effort ?? null,
|
|
838
|
+
teamOnlyVariables: null,
|
|
839
|
+
gitCredentialUrls: assembled.gitOnDemand.length > 0
|
|
840
|
+
? [...assembled.gitOnDemand]
|
|
841
|
+
: null,
|
|
842
|
+
},
|
|
843
|
+
});
|
|
844
|
+
unit.emit({ type: 'run.changed', runId: run.id, status: 'dispatched' });
|
|
845
|
+
if (variableRefs(candidate.teamOnlyVariables).length > 0)
|
|
846
|
+
unit.emit({
|
|
847
|
+
type: 'notice.cleared',
|
|
848
|
+
notice: {
|
|
849
|
+
type: 'run_secrets_not_allowed',
|
|
850
|
+
subject: { kind: 'run', id: run.id, label: run.id },
|
|
851
|
+
},
|
|
852
|
+
});
|
|
853
|
+
return assembled.payload;
|
|
436
854
|
});
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
855
|
+
}
|
|
856
|
+
catch (error) {
|
|
857
|
+
await discardRepoAccess(candidate, prepared);
|
|
858
|
+
if (error instanceof TeamRunnersOnly) {
|
|
859
|
+
await noteTeamOnly(candidate, error.variables);
|
|
860
|
+
return { kind: 'skipped' };
|
|
861
|
+
}
|
|
862
|
+
throw error;
|
|
863
|
+
}
|
|
864
|
+
if (!taken) {
|
|
865
|
+
await discardRepoAccess(candidate, prepared);
|
|
866
|
+
return { kind: 'skipped' };
|
|
867
|
+
}
|
|
868
|
+
return { kind: 'claimed', payload: taken };
|
|
869
|
+
}
|
|
870
|
+
async function discardRepoAccess(run, prepared) {
|
|
871
|
+
for (const provider of deps.repoAccess?.list() ?? []) {
|
|
872
|
+
try {
|
|
873
|
+
await provider.discard?.(toRun(run), prepared.get(`repo:${provider.key}`));
|
|
874
|
+
}
|
|
875
|
+
catch (error) {
|
|
876
|
+
deps.onClaimFailure?.(run.id, error);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
440
879
|
}
|
|
441
880
|
/** Counts a failed assembly; the run fails once it has failed too often. */
|
|
442
881
|
async function recordFailure(runId, error) {
|
|
@@ -463,15 +902,12 @@ export function createClaimService(deps) {
|
|
|
463
902
|
});
|
|
464
903
|
});
|
|
465
904
|
}
|
|
466
|
-
/** Queued runs
|
|
467
|
-
async function
|
|
905
|
+
/** Queued runs that may be claimed now, in claim order. */
|
|
906
|
+
async function candidates() {
|
|
468
907
|
const now = clock.now();
|
|
469
908
|
return runsRepo(tx.read()).findMany({
|
|
470
909
|
filter: (f) => f.and([
|
|
471
910
|
f.string('status').eq('queued'),
|
|
472
|
-
f.string('agentType').eq(type),
|
|
473
|
-
// A consultation is taken by the holder of the run that asked it, never from the queue.
|
|
474
|
-
f.string('parentRunId').empty(),
|
|
475
911
|
f.or([
|
|
476
912
|
f.date('availableAt').empty(),
|
|
477
913
|
f.date('availableAt').notAfter(now),
|
|
@@ -485,151 +921,22 @@ export function createClaimService(deps) {
|
|
|
485
921
|
limit: CANDIDATES,
|
|
486
922
|
});
|
|
487
923
|
}
|
|
488
|
-
/** Takes an online run for `holder` in one transaction, or skips it when another holder or run got there first. */
|
|
489
|
-
async function attemptServer(holder, agent, candidate) {
|
|
490
|
-
const prepared = await prepareExtensions(toRun(candidate), deps.sections, undefined, (error) => deps.onClaimFailure?.(candidate.id, error));
|
|
491
|
-
return tx.run(async (unit) => {
|
|
492
|
-
const { conn } = unit;
|
|
493
|
-
const now = clock.now();
|
|
494
|
-
const nowText = now.toISOString();
|
|
495
|
-
// Serializes claims and enqueues of this agent, so one key never has two runs held.
|
|
496
|
-
await lockAgentForClaim(conn, agent.id, nowText);
|
|
497
|
-
if ((await runsOfKey(conn, candidate, ACTIVE)).length > 0)
|
|
498
|
-
return null;
|
|
499
|
-
const leaseExpiresAt = later(now, TIMINGS.leaseMs);
|
|
500
|
-
const taken = await runsRepo(conn).updateMany({
|
|
501
|
-
filter: (f) => f.and([
|
|
502
|
-
f.string('id').eq(candidate.id),
|
|
503
|
-
f.string('status').eq('queued'),
|
|
504
|
-
]),
|
|
505
|
-
values: {
|
|
506
|
-
status: 'dispatched',
|
|
507
|
-
runnerId: holder.id,
|
|
508
|
-
leaseExpiresAt,
|
|
509
|
-
dispatchedAt: nowText,
|
|
510
|
-
lastActivityAt: nowText,
|
|
511
|
-
availableAt: null,
|
|
512
|
-
updatedAt: nowText,
|
|
513
|
-
},
|
|
514
|
-
});
|
|
515
|
-
if (taken.updatedCount !== 1)
|
|
516
|
-
return null;
|
|
517
|
-
const run = (await findRunRecord(conn, candidate.id));
|
|
518
|
-
const pending = await pendingInputs(conn, run.id);
|
|
519
|
-
const inputs = pending.map(toInput);
|
|
520
|
-
let claimed;
|
|
521
|
-
try {
|
|
522
|
-
claimed = await assembleServer(unit, run, agent, holder, inputs, leaseExpiresAt, prepared);
|
|
523
|
-
}
|
|
524
|
-
catch (error) {
|
|
525
|
-
throw new AssemblyError(error instanceof Error ? error.message : String(error), error);
|
|
526
|
-
}
|
|
527
|
-
await markDelivered(conn, pending, nowText);
|
|
528
|
-
await runsRepo(conn).updateMany({
|
|
529
|
-
filter: { id: run.id },
|
|
530
|
-
values: {
|
|
531
|
-
tool: null,
|
|
532
|
-
modelService: claimed.model?.modelService ?? null,
|
|
533
|
-
model: claimed.model?.model ?? null,
|
|
534
|
-
effort: claimed.model?.effort ?? null,
|
|
535
|
-
},
|
|
536
|
-
});
|
|
537
|
-
unit.emit({ type: 'run.changed', runId: run.id, status: 'dispatched' });
|
|
538
|
-
return {
|
|
539
|
-
...claimed,
|
|
540
|
-
run: {
|
|
541
|
-
...claimed.run,
|
|
542
|
-
tool: null,
|
|
543
|
-
modelService: claimed.model?.modelService ?? null,
|
|
544
|
-
model: claimed.model?.model ?? null,
|
|
545
|
-
effort: claimed.model?.effort ?? null,
|
|
546
|
-
},
|
|
547
|
-
};
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
async function assembleServer({ conn }, run, agent, holder, inputs, leaseExpiresAt, prepared) {
|
|
551
|
-
const binding = deps.subjects.get(run.subjectKind);
|
|
552
|
-
if (!binding)
|
|
553
|
-
throw new Error(`No context provider is registered for subjects of kind "${run.subjectKind}".`);
|
|
554
|
-
const view = toRun(run);
|
|
555
|
-
const claim = {
|
|
556
|
-
run: view,
|
|
557
|
-
agent,
|
|
558
|
-
runner: null,
|
|
559
|
-
inputs,
|
|
560
|
-
cli: deps.cli.name,
|
|
561
|
-
appName: deps.app.name,
|
|
562
|
-
dialect: 'tools',
|
|
563
|
-
};
|
|
564
|
-
const assembly = await binding.context.assemble(conn, claim);
|
|
565
|
-
if (assembly.dirs.length > 0)
|
|
566
|
-
throw new Error('An online agent has no working directory, and this work needs one.');
|
|
567
|
-
const skills = await deps.skills.forRun(conn, skillTargets(agent, assembly), run.id);
|
|
568
|
-
const own = new Set(skills.map((skill) => skill.slug));
|
|
569
|
-
const rendered = briefOf(agent, await withSections(conn, deps.sections, claim, assembly, prepared), [], deps.cli.name, deps.app.name);
|
|
570
|
-
// The skills an online run reads through its tools, and the agents it may consult, whatever system layer its
|
|
571
|
-
// subject gives it.
|
|
572
|
-
const consultable = (await deps.consultations?.targets(conn, run, agent)) ?? [];
|
|
573
|
-
const depth = run.parentRunId
|
|
574
|
-
? ((await deps.consultations?.chain(conn, run))?.length ?? 1) - 1
|
|
575
|
-
: 0;
|
|
576
|
-
const section = [
|
|
577
|
-
...onlineSkillsSection([
|
|
578
|
-
...skills,
|
|
579
|
-
...(deps.onlineSkills?.() ?? []).filter((skill) => !own.has(skill.slug)),
|
|
580
|
-
]),
|
|
581
|
-
...(consultable.length > 0 ? ['', ...consultSection(consultable)] : []),
|
|
582
|
-
];
|
|
583
|
-
const layers = section.length > 0
|
|
584
|
-
? {
|
|
585
|
-
...rendered.layers,
|
|
586
|
-
system: [rendered.layers.system, '', ...section].join('\n'),
|
|
587
|
-
}
|
|
588
|
-
: rendered.layers;
|
|
589
|
-
const brief = { ...rendered, layers, prompt: joinBrief(layers) };
|
|
590
|
-
const token = await mintRunToken(conn, deps, run, holder.id);
|
|
591
|
-
deps.secrets?.remember(runSecretsKey(run.id), [token.value]);
|
|
592
|
-
const last = await eventsRepo(conn).findOne({
|
|
593
|
-
filter: { runId: run.id },
|
|
594
|
-
sort: (sort) => sort.field('seq').desc(),
|
|
595
|
-
});
|
|
596
|
-
await saveBrief(conn, () => deps.ids.next(), {
|
|
597
|
-
runId: run.id,
|
|
598
|
-
attempt: Number(run.attempt),
|
|
599
|
-
layers: brief.layers,
|
|
600
|
-
turn: brief.turn,
|
|
601
|
-
prompt: brief.prompt,
|
|
602
|
-
createdAt: clock.now().toISOString(),
|
|
603
|
-
});
|
|
604
|
-
return {
|
|
605
|
-
runId: run.id,
|
|
606
|
-
attempt: Number(run.attempt),
|
|
607
|
-
agent,
|
|
608
|
-
run: view,
|
|
609
|
-
model: onlineEntryOf(agent, assembly.model, (await deps.defaultModel?.(conn)) ?? null),
|
|
610
|
-
system: brief.prompt,
|
|
611
|
-
turn: brief.turn,
|
|
612
|
-
inputs,
|
|
613
|
-
token: token.value,
|
|
614
|
-
skills,
|
|
615
|
-
leaseExpiresAt,
|
|
616
|
-
firstSeq: (last ? Number(last.seq) : 0) + 1,
|
|
617
|
-
consultable,
|
|
618
|
-
depth,
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
924
|
async function claimOne(runner, seen, reported) {
|
|
925
|
+
if (runner.draining)
|
|
926
|
+
return null;
|
|
622
927
|
const conn = tx.read();
|
|
623
|
-
const
|
|
928
|
+
const queued = await candidates();
|
|
624
929
|
const agents = new Map();
|
|
625
|
-
for (const candidate of
|
|
930
|
+
for (const candidate of queued) {
|
|
626
931
|
if (seen.has(candidate.id))
|
|
627
932
|
continue;
|
|
628
933
|
seen.add(candidate.id);
|
|
629
934
|
if (!agents.has(candidate.agentId))
|
|
630
935
|
agents.set(candidate.agentId, await findAgent(conn, candidate.agentId));
|
|
631
936
|
const agent = agents.get(candidate.agentId);
|
|
632
|
-
if (!agent ||
|
|
937
|
+
if (!agent ||
|
|
938
|
+
(!deps.subjects.get(candidate.subjectKind)?.actsAs &&
|
|
939
|
+
!fits(runner, agent, candidate)))
|
|
633
940
|
continue;
|
|
634
941
|
// None of its tools has room on the runner's side: the runs behind it may still fit.
|
|
635
942
|
if (!pickOpenEntry(runner, agent, (tool) => reported.has(tool)))
|
|
@@ -651,8 +958,19 @@ export function createClaimService(deps) {
|
|
|
651
958
|
return null;
|
|
652
959
|
}
|
|
653
960
|
return {
|
|
961
|
+
diagnose: (conn, run, agent) => selectionFacts(conn, run, agent, false),
|
|
962
|
+
async selectionWait(runId) {
|
|
963
|
+
const conn = tx.read();
|
|
964
|
+
const run = await findRunRecord(conn, runId);
|
|
965
|
+
if (!run || run.status !== 'queued')
|
|
966
|
+
return null;
|
|
967
|
+
const agent = await findAgent(conn, run.agentId);
|
|
968
|
+
return agent ? selectionFacts(conn, toRun(run), agent, false) : null;
|
|
969
|
+
},
|
|
654
970
|
async claim(runner, free, tools) {
|
|
655
|
-
if (runner.status !== 'online')
|
|
971
|
+
if (runner.status !== 'online' || runnerLowOnDisk(runner))
|
|
972
|
+
return [];
|
|
973
|
+
if ((await deps.slotsUsed(tx.read(), runner.id)) >= runner.slots)
|
|
656
974
|
return [];
|
|
657
975
|
const payloads = [];
|
|
658
976
|
const seen = new Set();
|
|
@@ -667,64 +985,6 @@ export function createClaimService(deps) {
|
|
|
667
985
|
}
|
|
668
986
|
return payloads;
|
|
669
987
|
},
|
|
670
|
-
async claimServer(holder, limit) {
|
|
671
|
-
const claimed = [];
|
|
672
|
-
const conn = tx.read();
|
|
673
|
-
const agents = new Map();
|
|
674
|
-
for (const candidate of await candidatesOf('online')) {
|
|
675
|
-
if (claimed.length >= limit)
|
|
676
|
-
break;
|
|
677
|
-
if (!agents.has(candidate.agentId))
|
|
678
|
-
agents.set(candidate.agentId, await findAgent(conn, candidate.agentId));
|
|
679
|
-
const agent = agents.get(candidate.agentId);
|
|
680
|
-
if (!agent || agent.archivedAt || agent.type !== 'online')
|
|
681
|
-
continue;
|
|
682
|
-
try {
|
|
683
|
-
const taken = await attemptServer(holder, agent, candidate);
|
|
684
|
-
if (taken)
|
|
685
|
-
claimed.push(taken);
|
|
686
|
-
}
|
|
687
|
-
catch (error) {
|
|
688
|
-
if (!(error instanceof AssemblyError))
|
|
689
|
-
throw error;
|
|
690
|
-
await recordFailure(candidate.id, error);
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
return claimed;
|
|
694
|
-
},
|
|
695
|
-
async claimChild(holder, runId) {
|
|
696
|
-
const conn = tx.read();
|
|
697
|
-
const candidate = await findRunRecord(conn, runId);
|
|
698
|
-
if (!candidate?.parentRunId || candidate.status !== 'queued')
|
|
699
|
-
throw notFound('Run');
|
|
700
|
-
const parent = await findRunRecord(conn, candidate.parentRunId);
|
|
701
|
-
if (parent?.runnerId !== holder.id)
|
|
702
|
-
throw notFound('Run');
|
|
703
|
-
const agent = await findAgent(conn, candidate.agentId);
|
|
704
|
-
if (!agent || agent.archivedAt || agent.type !== 'online')
|
|
705
|
-
throw notFound('Agent');
|
|
706
|
-
try {
|
|
707
|
-
const taken = await attemptServer(holder, agent, candidate);
|
|
708
|
-
if (!taken)
|
|
709
|
-
throw notFound('Run');
|
|
710
|
-
return taken;
|
|
711
|
-
}
|
|
712
|
-
catch (error) {
|
|
713
|
-
if (!(error instanceof AssemblyError))
|
|
714
|
-
throw error;
|
|
715
|
-
// One attempt: a consultation that cannot be assembled fails at once.
|
|
716
|
-
await tx.run(async (unit) => {
|
|
717
|
-
const run = await findRunRecord(unit.conn, runId);
|
|
718
|
-
if (run)
|
|
719
|
-
await finishRun(unit, deps, run, {
|
|
720
|
-
status: 'failed',
|
|
721
|
-
reason: 'setupFailed',
|
|
722
|
-
detail: error.message,
|
|
723
|
-
});
|
|
724
|
-
});
|
|
725
|
-
throw error;
|
|
726
|
-
}
|
|
727
|
-
},
|
|
728
988
|
async runSkills(runner, runId) {
|
|
729
989
|
const conn = tx.read();
|
|
730
990
|
const run = await findRunRecord(conn, runId);
|
|
@@ -741,8 +1001,7 @@ export function createClaimService(deps) {
|
|
|
741
1001
|
inputs: [],
|
|
742
1002
|
cli: deps.cli.name,
|
|
743
1003
|
appName: deps.app.name,
|
|
744
|
-
|
|
745
|
-
});
|
|
1004
|
+
}, await binding.context.prepare?.(toRun(run)));
|
|
746
1005
|
return deps.skills.forRun(conn, skillTargets(agent, assembly), run.id);
|
|
747
1006
|
},
|
|
748
1007
|
};
|