@wardby/cli 0.7.0 → 0.9.0
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/.env.example +5 -5
- package/README.md +6 -1
- package/deploy/local/docker-compose.quickstart-coding.yml +11 -0
- package/dist/claude-coding-worker/driver.d.ts +12 -0
- package/dist/claude-coding-worker/driver.js +29 -7
- package/dist/claude-coding-worker/main.js +5 -1
- package/dist/claude-coding-worker/sdk.js +17 -1
- package/dist/claude-plugin/command.d.ts +64 -0
- package/dist/claude-plugin/command.js +379 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +2 -1
- package/dist/cli.js +71 -3
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/protocol.js +2 -0
- package/dist/coding/redact.js +6 -1
- package/dist/coding/transcript/recorder.d.ts +5 -4
- package/dist/coding/transcript/recorder.js +3 -9
- package/dist/coding-worker/debug-trace.d.ts +3 -1
- package/dist/coding-worker/debug-trace.js +4 -2
- package/dist/coding-worker/driver.js +8 -1
- package/dist/coding-worker/main.js +5 -1
- package/dist/coding-worker/mcp-config.d.ts +27 -0
- package/dist/coding-worker/mcp-config.js +32 -0
- package/dist/coding-worker/sdk.d.ts +36 -0
- package/dist/coding-worker/sdk.js +28 -1
- package/dist/coding-worker/types.d.ts +4 -0
- package/dist/config/mcp-call-limit.d.ts +8 -0
- package/dist/config/mcp-call-limit.js +18 -0
- package/dist/config/mcp-servers.d.ts +8 -0
- package/dist/config/mcp-servers.js +12 -0
- package/dist/config/test-simulators.d.ts +10 -0
- package/dist/config/test-simulators.js +28 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +6 -2
- package/dist/core/dispatch.js +39 -11
- package/dist/core/engine-native.d.ts +2 -0
- package/dist/core/engine-native.js +13 -0
- package/dist/core/error-code.js +2 -0
- package/dist/core/grants.d.ts +28 -3
- package/dist/core/grants.js +46 -4
- package/dist/core/host-events.js +7 -3
- package/dist/core/host-status.js +2 -2
- package/dist/core/issue-status.js +4 -3
- package/dist/core/listen-address.d.ts +10 -0
- package/dist/core/listen-address.js +14 -0
- package/dist/core/mark-ready.d.ts +1 -1
- package/dist/core/mark-ready.js +1 -1
- package/dist/core/mcp-client/client.d.ts +47 -0
- package/dist/core/mcp-client/client.js +141 -0
- package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
- package/dist/core/mcp-client/jsonrpc.js +54 -0
- package/dist/core/mcp-client/results.d.ts +13 -0
- package/dist/core/mcp-client/results.js +42 -0
- package/dist/core/mcp-servers.d.ts +90 -0
- package/dist/core/mcp-servers.js +230 -0
- package/dist/core/mcp-tools.d.ts +108 -0
- package/dist/core/mcp-tools.js +287 -0
- package/dist/core/merge-order-check.js +38 -19
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/power-idle.d.ts +8 -2
- package/dist/core/power-idle.js +17 -3
- package/dist/core/power.d.ts +5 -0
- package/dist/core/power.js +5 -0
- package/dist/core/related-pull-requests.js +26 -10
- package/dist/core/retention-days.d.ts +5 -0
- package/dist/core/retention-days.js +14 -0
- package/dist/core/review-fix.js +2 -2
- package/dist/core/review-host-tools.js +3 -1
- package/dist/core/run-steps/config.d.ts +25 -0
- package/dist/core/run-steps/config.js +40 -0
- package/dist/core/run-steps/control-chars.d.ts +16 -0
- package/dist/core/run-steps/control-chars.js +26 -0
- package/dist/core/run-steps/detail.d.ts +32 -0
- package/dist/core/run-steps/detail.js +240 -0
- package/dist/core/run-steps/extract.d.ts +52 -0
- package/dist/core/run-steps/extract.js +467 -0
- package/dist/core/run-steps/ingress.d.ts +51 -0
- package/dist/core/run-steps/ingress.js +160 -0
- package/dist/core/run-steps/last-step.d.ts +15 -0
- package/dist/core/run-steps/last-step.js +35 -0
- package/dist/core/run-steps/native.d.ts +48 -0
- package/dist/core/run-steps/native.js +164 -0
- package/dist/core/run-steps/seen.d.ts +16 -0
- package/dist/core/run-steps/seen.js +35 -0
- package/dist/core/run-steps/summarize.d.ts +57 -0
- package/dist/core/run-steps/summarize.js +304 -0
- package/dist/core/run-steps/sweep.d.ts +21 -0
- package/dist/core/run-steps/sweep.js +41 -0
- package/dist/core/run-steps/types.d.ts +89 -0
- package/dist/core/run-steps/types.js +39 -0
- package/dist/core/run-steps/wire.d.ts +35 -0
- package/dist/core/run-steps/wire.js +47 -0
- package/dist/core/run-steps/writer.d.ts +49 -0
- package/dist/core/run-steps/writer.js +279 -0
- package/dist/core/runner.d.ts +70 -16
- package/dist/core/runner.js +296 -74
- package/dist/core/secret-broker-config.d.ts +2 -0
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +5 -2
- package/dist/core/secret-guard.js +22 -7
- package/dist/core/secrets.d.ts +11 -1
- package/dist/core/secrets.js +27 -1
- package/dist/core/serializable-retry.d.ts +18 -0
- package/dist/core/serializable-retry.js +43 -0
- package/dist/core/tool-admin.d.ts +5 -1
- package/dist/core/tool-admin.js +7 -2
- package/dist/core/tool-names.d.ts +13 -0
- package/dist/core/tool-names.js +20 -0
- package/dist/core/webhooks.d.ts +4 -0
- package/dist/core/webhooks.js +68 -49
- package/dist/core/workflow-run-events.js +2 -1
- package/dist/generated/prisma/browser.d.ts +39 -0
- package/dist/generated/prisma/client.d.ts +39 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +80 -50
- package/dist/generated/prisma/enums.d.ts +6 -0
- package/dist/generated/prisma/enums.js +5 -0
- package/dist/generated/prisma/internal/class.d.ts +77 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +632 -1
- package/dist/generated/prisma/internal/prismaNamespace.js +94 -3
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +98 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +94 -3
- package/dist/generated/prisma/models/Agent.d.ts +372 -1
- package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
- package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +40 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +0 -7
- package/dist/generated/prisma/models/CodingProxySession.d.ts +159 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +76 -1
- package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
- package/dist/generated/prisma/models/HostProvider.js +1 -0
- package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
- package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
- package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
- package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
- package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +39 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- package/dist/generated/prisma/models/Run.d.ts +503 -1
- package/dist/generated/prisma/models/RunStep.d.ts +1453 -0
- package/dist/generated/prisma/models/RunStep.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +7 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +812 -52
- package/dist/import/create.js +16 -1
- package/dist/import/neutral-schema.d.ts +1 -0
- package/dist/import/neutral-schema.js +2 -0
- package/dist/mcp/auth/access.d.ts +1 -0
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/context.d.ts +6 -0
- package/dist/mcp/index.js +21 -0
- package/dist/mcp/tools/agents.js +135 -20
- package/dist/mcp/tools/grants.js +66 -28
- package/dist/mcp/tools/host-providers.d.ts +2 -0
- package/dist/mcp/tools/host-providers.js +215 -0
- package/dist/mcp/tools/mcp-servers.d.ts +26 -0
- package/dist/mcp/tools/mcp-servers.js +481 -0
- package/dist/mcp/tools/power.js +2 -2
- package/dist/mcp/tools/repositories.js +50 -10
- package/dist/mcp/tools/run-access.d.ts +7 -0
- package/dist/mcp/tools/run-access.js +14 -0
- package/dist/mcp/tools/run-steps.d.ts +16 -0
- package/dist/mcp/tools/run-steps.js +85 -0
- package/dist/mcp/tools/runs.js +186 -18
- package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
- package/dist/mcp/tools/secret-elicitation.js +25 -2
- package/dist/mcp/tools/secrets.js +38 -4
- package/dist/mcp/tools/tools.d.ts +6 -4
- package/dist/mcp/tools/tools.js +40 -8
- package/dist/mcp/tools/trigger.js +28 -6
- package/dist/mcp/transport/http-limits.d.ts +2 -0
- package/dist/mcp/transport/http-limits.js +6 -2
- package/dist/mcp/webhooks/ingress.js +10 -0
- package/dist/native-worker/gateway-server.d.ts +18 -1
- package/dist/native-worker/gateway-server.js +38 -9
- package/dist/native-worker/gateway.d.ts +5 -0
- package/dist/native-worker/gateway.js +13 -1
- package/dist/native-worker/http-server.d.ts +6 -4
- package/dist/native-worker/http-server.js +53 -8
- package/dist/native-worker/ledger.d.ts +6 -2
- package/dist/native-worker/ledger.js +5 -4
- package/dist/native-worker/protocol.d.ts +1 -0
- package/dist/native-worker/protocol.js +4 -1
- package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
- package/dist/providers/coding-proxy/capability-hash.js +5 -0
- package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
- package/dist/providers/coding-proxy/mcp-route.js +166 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +2 -0
- package/dist/providers/coding-proxy/memory-ledger.js +16 -0
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +1 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +36 -2
- package/dist/providers/coding-proxy/proxy.d.ts +33 -1
- package/dist/providers/coding-proxy/proxy.js +266 -75
- package/dist/providers/coding-proxy/run-step-forwarder.d.ts +42 -0
- package/dist/providers/coding-proxy/run-step-forwarder.js +206 -0
- package/dist/providers/coding-proxy/runtime.d.ts +13 -0
- package/dist/providers/coding-proxy/runtime.js +87 -4
- package/dist/providers/coding-proxy/server.d.ts +3 -0
- package/dist/providers/coding-proxy/server.js +10 -0
- package/dist/providers/coding-proxy/types.d.ts +18 -0
- package/dist/providers/engine/types.d.ts +26 -0
- package/dist/providers/executor/composition.js +5 -0
- package/dist/providers/executor/container.d.ts +47 -1
- package/dist/providers/executor/container.js +84 -8
- package/dist/providers/host-tools/invoke.d.ts +37 -0
- package/dist/providers/host-tools/invoke.js +117 -0
- package/dist/providers/host-tools/operations.d.ts +65 -0
- package/dist/providers/host-tools/operations.js +149 -0
- package/dist/providers/host-tools/registry.d.ts +79 -0
- package/dist/providers/host-tools/registry.js +362 -0
- package/dist/providers/host-tools/request-guard.d.ts +17 -0
- package/dist/providers/host-tools/request-guard.js +99 -0
- package/dist/providers/host-tools/self-test.d.ts +64 -0
- package/dist/providers/host-tools/self-test.js +142 -0
- package/dist/providers/jobs/docker-isolation.d.ts +2 -2
- package/dist/providers/jobs/docker-isolation.js +30 -8
- package/dist/providers/jobs/docker.d.ts +8 -0
- package/dist/providers/jobs/docker.js +33 -9
- package/dist/providers/jobs/kubernetes-isolation.d.ts +3 -1
- package/dist/providers/jobs/kubernetes-isolation.js +15 -2
- package/dist/providers/jobs/kubernetes.d.ts +13 -0
- package/dist/providers/jobs/kubernetes.js +28 -5
- package/dist/providers/jobs/types.d.ts +6 -0
- package/dist/providers/review-host/types.d.ts +6 -4
- package/dist/providers/review-host/types.js +1 -1
- package/dist/providers/vcs/git.d.ts +6 -2
- package/dist/providers/vcs/git.js +15 -4
- package/dist/providers/vcs/github.d.ts +2 -71
- package/dist/providers/vcs/github.js +8 -11
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +1 -1
- package/dist/providers/vcs/remote.d.ts +4 -0
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +12 -6
- package/dist/providers/vcs/routing.js +21 -6
- package/dist/providers/vcs/types.d.ts +71 -3
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/eval-core.d.ts +12 -2
- package/dist/sandbox/eval-core.js +20 -4
- package/dist/sandbox/host-functions.d.ts +4 -0
- package/dist/sandbox/host-functions.js +7 -2
- package/dist/sandbox/limits.d.ts +4 -1
- package/dist/sandbox/limits.js +4 -1
- package/dist/sandbox/run-in-sandbox.d.ts +6 -0
- package/dist/sandbox/run-in-sandbox.js +14 -2
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +1 -1
- package/dist/sandbox/secret-broker.d.ts +1 -0
- package/dist/sandbox/secret-broker.js +1 -1
- package/dist/sandbox/tool-timeout.d.ts +32 -0
- package/dist/sandbox/tool-timeout.js +52 -0
- package/dist/sandbox/user-tool.d.ts +8 -1
- package/dist/sandbox/user-tool.js +9 -3
- package/dist/serve.js +26 -18
- package/dist/viewer/api-schema.d.ts +66 -0
- package/dist/viewer/api-schema.js +31 -0
- package/dist/viewer/graph.js +2 -1
- package/dist/viewer/openapi.js +2 -1
- package/dist/viewer/run-detail.d.ts +2 -0
- package/dist/viewer/run-detail.js +26 -1
- package/dist/wardby-bin.js +5 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +37 -4
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +208 -0
- package/docs/code-review-agents.md +6 -0
- package/docs/coding-agent-setup.md +94 -1
- package/docs/coding-worker-byo-images.md +4 -2
- package/docs/coding-worker-isolation.md +94 -7
- package/docs/debugging-agent-runs.md +354 -0
- package/docs/getting-started-gke.md +33 -11
- package/docs/getting-started-identity-provider.md +43 -37
- package/docs/getting-started.md +8 -0
- package/docs/host-providers.md +294 -0
- package/docs/mcp-servers.md +263 -0
- package/docs/native-sandbox.md +31 -9
- package/docs/security-deployment.md +161 -31
- package/docs/tool-secrets.md +3 -0
- package/docs/viewer-api.md +27 -12
- package/docs/viewer-api.openapi.yml +78 -2
- package/help/admin-viewer.md +5 -0
- package/help/agent-recipes.md +33 -2
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/claude-code-run-pane.md +63 -0
- package/help/deploy-gke.md +5 -0
- package/help/errors/coding-mcp-gateway-unavailable.md +46 -0
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/database-auth-invalid.md +1 -1
- package/help/errors/host-provider-error.md +40 -0
- package/help/errors/host-tool-failed.md +36 -0
- package/help/errors/mcp-call-limit.md +22 -0
- package/help/errors/mcp-call-timeout.md +22 -0
- package/help/errors/mcp-server-auth-failed.md +22 -0
- package/help/errors/mcp-server-credentials-unavailable.md +45 -0
- package/help/errors/mcp-server-error.md +28 -0
- package/help/errors/mcp-server-unreachable.md +22 -0
- package/help/errors/mcp-servers-off.md +21 -0
- package/help/errors/mcp-tool-not-allowed.md +26 -0
- package/help/errors/mcp-tool-removed.md +22 -0
- package/help/errors/mcp-unavailable.md +25 -0
- package/help/errors/native-sandbox-capacity.md +1 -1
- package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
- package/help/errors/native-sandbox-docker-failed.md +1 -1
- package/help/errors/native-sandbox-gateway-error.md +1 -1
- package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
- package/help/errors/native-sandbox-image-not-pinned.md +1 -1
- package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
- package/help/errors/native-sandbox-network-unenforced.md +1 -1
- package/help/errors/native-sandbox-requires-catalog.md +1 -1
- package/help/errors/native-sandbox-unavailable.md +1 -1
- package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
- package/help/errors/native-sandbox-worker-exited.md +1 -1
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +4 -1
- package/help/low-power-mode.md +19 -8
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +9 -2
- package/help/native-capabilities.md +27 -1
- package/help/native-sandbox.md +1 -1
- package/help/operating-agents.md +16 -0
- package/help/related-pull-requests.md +7 -3
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +7 -0
- package/help/run-steps.md +140 -0
- package/help/stop-run.md +1 -1
- package/help/troubleshooting/coding-workers.md +9 -1
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +2 -1
- package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
- package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
- package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
- package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
- package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
- package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
- package/prisma/migrations/20261110000000_run_steps/migration.sql +26 -0
- package/prisma/migrations/20261111000000_run_steps_viewer_notify/migration.sql +59 -0
- package/prisma/migrations/20261112000000_run_steps_detail/migration.sql +9 -0
- package/prisma/schema.prisma +211 -14
- package/scripts/git-askpass.sh +1 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one writer of RunStep rows. Every source hands it batches (RunStepSink). Before anything is
|
|
3
|
+
* stored, each step's text is redacted by exact value against the secret values the loader covers:
|
|
4
|
+
* the agent's secrets (readable and brokered) and its attached MCP servers' secrets, the same source
|
|
5
|
+
* the transcript recorder uses; run capabilities are masked by token shape. The native-sandbox
|
|
6
|
+
* gateway capability is passed by the gateway as `extraSecretValues` and redacted the same way. A batch whose run's secret values
|
|
7
|
+
* can't be read writes nothing (fail closed). A step whose kind is unknown, whose callId is invalid or
|
|
8
|
+
* would change under redaction is dropped and not counted in stepsDropped; only steps past the cap are
|
|
9
|
+
* counted, once per callId. One run's batches are written in arrival order, within one process only
|
|
10
|
+
* (step/result ordering across processes is not guaranteed), under a row lock on the run, so seq has
|
|
11
|
+
* no gaps or duplicates whichever process writes. Known limits: a dropped step may be counted again
|
|
12
|
+
* after a process restart, after its run is evicted from the remembered set, past the per-run id
|
|
13
|
+
* limit, or when two processes write the same run. A result is matched only to a stored callId, which
|
|
14
|
+
* is already clean, so a result's callId is never persisted. At the detail level (the run's
|
|
15
|
+
* Run.runStepsLevel, fixed at dispatch), each step's detail text is redacted the same way
|
|
16
|
+
* (stepDetailer) before it is cut and stored; below it, detail material in a batch is dropped
|
|
17
|
+
* unread. Step text, input and output lose terminal control sequences and control characters
|
|
18
|
+
* (plainText: exact values masked on the raw text first, then stripControlSequences, then the full
|
|
19
|
+
* redaction), so no reader is sent an escape sequence. Log lines
|
|
20
|
+
* carry the run id, a fixed event code and an error's name: never text, never an error's message.
|
|
21
|
+
*/
|
|
22
|
+
import { createHash } from "node:crypto";
|
|
23
|
+
import { REDACTED, redactSecrets } from "../../coding/redact.js";
|
|
24
|
+
import { logger } from "../logger.js";
|
|
25
|
+
import { loadAgentSecretValues } from "../secret-guard.js";
|
|
26
|
+
import { MIN_REDACTABLE_SECRET_LENGTH } from "../secret-spans.js";
|
|
27
|
+
import { loadRunStepRetentionDays, loadRunStepsLevel, recordedRunStepsLevel } from "./config.js";
|
|
28
|
+
import { stripControlSequences } from "./control-chars.js";
|
|
29
|
+
import { joinDetail, stepDetailer } from "./detail.js";
|
|
30
|
+
import { stepSummarizer } from "./summarize.js";
|
|
31
|
+
import { MAX_RUN_STEPS, MAX_STEP_DETAIL_CHARS, STEP_CALL_ID, STEP_STATUS, STEP_TOOL_NAME, tailOf, } from "./types.js";
|
|
32
|
+
const stepsLog = logger.child({ module: "run-steps" });
|
|
33
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
34
|
+
const TX = { maxWait: 5_000, timeout: 10_000 };
|
|
35
|
+
/** How long flush() waits for queued writes at shutdown. */
|
|
36
|
+
export const FLUSH_TIMEOUT_MS = 5_000;
|
|
37
|
+
/** Over-cap callIds remembered (as 32-character hashes): at most this many per run and in all. */
|
|
38
|
+
const DROPPED_PER_RUN = 10_000;
|
|
39
|
+
const DROPPED_TOTAL = 200_000;
|
|
40
|
+
const callKey = (callId) => createHash("sha256").update(callId).digest("hex").slice(0, 32);
|
|
41
|
+
function uniqueByCallId(steps) {
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
return steps.filter((step) => {
|
|
44
|
+
if (!STEP_CALL_ID.test(step.callId) || seen.has(step.callId))
|
|
45
|
+
return false;
|
|
46
|
+
seen.add(step.callId);
|
|
47
|
+
return true;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** A private-use character: stands in for a masked value while control sequences are stripped. */
|
|
51
|
+
const HELD = "\uE000";
|
|
52
|
+
/**
|
|
53
|
+
* Untrusted text as plain text, safely: every secret value is masked on the raw text first, whole
|
|
54
|
+
* and partial (StepDetailer.premask: the text's edges and every line and ellipsis boundary), then
|
|
55
|
+
* control sequences are stripped (stripControlSequences), and only then does the full redaction
|
|
56
|
+
* run. Stripping first could take a secret's first character as a malformed sequence's final byte
|
|
57
|
+
* (`ESC Z` + value) and leave the rest of it matching nothing; the full redaction after the strip
|
|
58
|
+
* still masks a value that only the strip joined (one split by colour codes). The mask is a
|
|
59
|
+
* placeholder no sequence pattern can take as a byte of its own (a sequence before `[REDACTED]`
|
|
60
|
+
* would eat its "["), swapped for the marker after the strip.
|
|
61
|
+
*/
|
|
62
|
+
function plainText(raw, premask, headWasCut = false) {
|
|
63
|
+
if (!premask)
|
|
64
|
+
return stripControlSequences(raw);
|
|
65
|
+
const held = premask(raw.replaceAll(HELD, ""), headWasCut, HELD);
|
|
66
|
+
return stripControlSequences(held).replaceAll(HELD, REDACTED);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A result's detail suffix: its end taken from the raw output first (tailOf), so the premask's head
|
|
70
|
+
* check runs at the cut the detailer will see, then plainText, then the detailer.
|
|
71
|
+
*/
|
|
72
|
+
function plainOutput(raw, outputCut, premask, detailer) {
|
|
73
|
+
const source = tailOf(raw);
|
|
74
|
+
const cut = outputCut || source.cut;
|
|
75
|
+
return detailer.output({ output: plainText(source.text, premask, cut), outputCut: cut });
|
|
76
|
+
}
|
|
77
|
+
/** `step` without its detail-only input. */
|
|
78
|
+
function withoutInput(step) {
|
|
79
|
+
if (step.kind !== "tool" || step.input === undefined)
|
|
80
|
+
return step;
|
|
81
|
+
const { input: _input, inputTruncated: _inputTruncated, ...rest } = step;
|
|
82
|
+
return rest;
|
|
83
|
+
}
|
|
84
|
+
/** A step's text and input as plainText. */
|
|
85
|
+
function plainStep(step, premask) {
|
|
86
|
+
if (step.kind === "said")
|
|
87
|
+
return { ...step, text: plainText(step.text, premask) };
|
|
88
|
+
const input = step.input === undefined ? {} : { input: plainText(step.input, premask) };
|
|
89
|
+
return { ...step, text: plainText(step.text, premask), ...input };
|
|
90
|
+
}
|
|
91
|
+
function safeToolName(tool, secretValues) {
|
|
92
|
+
const shown = redactSecrets(tool, secretValues);
|
|
93
|
+
return STEP_TOOL_NAME.test(shown) ? shown : "tool";
|
|
94
|
+
}
|
|
95
|
+
export class RunStepWriter {
|
|
96
|
+
deps;
|
|
97
|
+
queues = new Map();
|
|
98
|
+
/**
|
|
99
|
+
* Hashes of the callIds already counted in stepsDropped, so history resent past the cap is not
|
|
100
|
+
* counted again. Least recently used run first; bounded in total, whatever the ids' length.
|
|
101
|
+
*/
|
|
102
|
+
droppedIds = new Map();
|
|
103
|
+
constructor(deps) {
|
|
104
|
+
this.deps = deps;
|
|
105
|
+
}
|
|
106
|
+
record(runId, batch, extraSecretValues = []) {
|
|
107
|
+
if (this.deps.level === "off")
|
|
108
|
+
return Promise.resolve();
|
|
109
|
+
if (batch.steps.length === 0 && batch.results.length === 0)
|
|
110
|
+
return Promise.resolve();
|
|
111
|
+
const previous = this.queues.get(runId) ?? Promise.resolve();
|
|
112
|
+
const next = previous
|
|
113
|
+
.then(() => this.write(runId, batch, extraSecretValues))
|
|
114
|
+
.catch((err) => {
|
|
115
|
+
(this.deps.log ?? stepsLog).warn({ runId, event: "run_steps_write_failed", errorName: err instanceof Error ? err.name : typeof err }, "could not record a run's steps; they were dropped");
|
|
116
|
+
});
|
|
117
|
+
this.queues.set(runId, next);
|
|
118
|
+
void next.then(() => {
|
|
119
|
+
if (this.queues.get(runId) === next)
|
|
120
|
+
this.queues.delete(runId);
|
|
121
|
+
});
|
|
122
|
+
return next;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Resolves when every write queued so far has settled, or after `timeoutMs`: called before the
|
|
126
|
+
* process disconnects from the database, so a run's last steps are not cut off. Never rejects.
|
|
127
|
+
*/
|
|
128
|
+
async flush(timeoutMs = FLUSH_TIMEOUT_MS) {
|
|
129
|
+
const pending = [...this.queues.values()];
|
|
130
|
+
if (pending.length === 0)
|
|
131
|
+
return;
|
|
132
|
+
let timer;
|
|
133
|
+
const bound = new Promise((resolve) => {
|
|
134
|
+
timer = setTimeout(resolve, timeoutMs);
|
|
135
|
+
});
|
|
136
|
+
try {
|
|
137
|
+
await Promise.race([Promise.allSettled(pending), bound]);
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
now() {
|
|
144
|
+
return (this.deps.now ?? (() => new Date()))();
|
|
145
|
+
}
|
|
146
|
+
async write(runId, batch, extraSecretValues) {
|
|
147
|
+
const { db } = this.deps;
|
|
148
|
+
const run = await db.run.findUnique({ where: { id: runId }, select: { agentId: true, runStepsLevel: true } });
|
|
149
|
+
if (!run)
|
|
150
|
+
return;
|
|
151
|
+
const level = recordedRunStepsLevel(run.runStepsLevel, this.deps.level);
|
|
152
|
+
if (level === "off")
|
|
153
|
+
return;
|
|
154
|
+
const detailed = level === "detail";
|
|
155
|
+
// Below detail a tool's input is never stored, so it is dropped here, before any redaction.
|
|
156
|
+
const extracted = uniqueByCallId(batch.steps.filter((step) => step.kind === "tool" || step.kind === "said")).map((step) => (detailed ? step : withoutInput(step)));
|
|
157
|
+
const results = batch.results.filter((r) => STEP_CALL_ID.test(r.callId) && STEP_STATUS.test(r.status));
|
|
158
|
+
const outputs = detailed && results.some((r) => typeof r.output === "string");
|
|
159
|
+
// Read fresh for every batch that stores text (steps, or outputs at detail), never cached: a
|
|
160
|
+
// rotated or newly attached secret must be covered. Rejects (and the batch is dropped) when the
|
|
161
|
+
// values can't be read: never an unredacted write.
|
|
162
|
+
const needsValues = extracted.length > 0 || outputs;
|
|
163
|
+
const own = needsValues ? await this.deps.secretValues(run.agentId) : [];
|
|
164
|
+
const extras = needsValues ? extraSecretValues.filter(Boolean) : [];
|
|
165
|
+
const rawValues = [...own, ...extras];
|
|
166
|
+
// Each value also as plain text, as the step text is: a value holding a control character
|
|
167
|
+
// (never a stripped form too short to redact safely).
|
|
168
|
+
const values = [
|
|
169
|
+
...new Set(rawValues.flatMap((value) => {
|
|
170
|
+
const plain = stripControlSequences(value);
|
|
171
|
+
return plain.length >= MIN_REDACTABLE_SECRET_LENGTH ? [value, plain] : [value];
|
|
172
|
+
})),
|
|
173
|
+
];
|
|
174
|
+
// The summary forms are built once per batch, on the first row; the detailer (whose premask
|
|
175
|
+
// every text goes through first) once per batch that has any secret value.
|
|
176
|
+
let summarize;
|
|
177
|
+
let detailer;
|
|
178
|
+
const detailOf = () => (detailer ??= stepDetailer(values));
|
|
179
|
+
const premask = values.length > 0 ? (raw, headWasCut, marker) => detailOf().premask(raw, headWasCut, marker) : undefined;
|
|
180
|
+
const steps = extracted.map((step) => plainStep(step, premask));
|
|
181
|
+
const at = this.now();
|
|
182
|
+
const expiresAt = new Date(at.getTime() + this.deps.retentionDays * DAY_MS);
|
|
183
|
+
// callId is stored as text: a step whose callId holds a secret value is not stored at all.
|
|
184
|
+
const clean = steps.filter((step) => redactSecrets(step.callId, values) === step.callId);
|
|
185
|
+
const rows = clean.map((step) => ({
|
|
186
|
+
kind: step.kind,
|
|
187
|
+
tool: step.kind === "tool" ? safeToolName(step.tool, values) : null,
|
|
188
|
+
callId: step.callId,
|
|
189
|
+
summary: (summarize ??= stepSummarizer(values))(step),
|
|
190
|
+
detail: detailed ? detailOf().step(step).slice(0, MAX_STEP_DETAIL_CHARS) : null,
|
|
191
|
+
at,
|
|
192
|
+
expiresAt,
|
|
193
|
+
}));
|
|
194
|
+
const maxSteps = this.deps.maxSteps ?? MAX_RUN_STEPS;
|
|
195
|
+
const counted = this.droppedIds.get(runId) ?? new Set();
|
|
196
|
+
if (this.droppedIds.has(runId)) {
|
|
197
|
+
this.droppedIds.delete(runId);
|
|
198
|
+
this.droppedIds.set(runId, counted);
|
|
199
|
+
}
|
|
200
|
+
// Each result's detail suffix, computed before the transaction: redaction is CPU work, and the
|
|
201
|
+
// transaction holds the run's row lock.
|
|
202
|
+
const suffixes = results.map((result) => outputs && typeof result.output === "string"
|
|
203
|
+
? plainOutput(result.output, result.outputCut === true, premask, detailOf())
|
|
204
|
+
: undefined);
|
|
205
|
+
const newlyDropped = [];
|
|
206
|
+
await db.$transaction(async (tx) => {
|
|
207
|
+
await tx.$queryRaw `SELECT 1 FROM "Run" WHERE "id" = ${runId} FOR UPDATE`;
|
|
208
|
+
if (rows.length > 0) {
|
|
209
|
+
const existing = await tx.runStep.findMany({
|
|
210
|
+
where: { runId, callId: { in: rows.map((row) => row.callId) } },
|
|
211
|
+
select: { callId: true },
|
|
212
|
+
});
|
|
213
|
+
const known = new Set(existing.map((row) => row.callId));
|
|
214
|
+
const fresh = rows.filter((row) => !known.has(row.callId));
|
|
215
|
+
const last = await tx.runStep.findFirst({ where: { runId }, orderBy: { seq: "desc" }, select: { seq: true } });
|
|
216
|
+
const start = last?.seq ?? 0;
|
|
217
|
+
const kept = fresh.slice(0, Math.max(0, maxSteps - start));
|
|
218
|
+
if (kept.length > 0) {
|
|
219
|
+
await tx.runStep.createMany({ data: kept.map((row, index) => ({ ...row, runId, seq: start + index + 1 })) });
|
|
220
|
+
}
|
|
221
|
+
const over = fresh.slice(kept.length).filter((row) => !counted.has(callKey(row.callId)));
|
|
222
|
+
newlyDropped.push(...over.map((row) => row.callId));
|
|
223
|
+
const dropped = over.length;
|
|
224
|
+
if (dropped > 0)
|
|
225
|
+
await tx.run.update({ where: { id: runId }, data: { stepsDropped: { increment: dropped } } });
|
|
226
|
+
}
|
|
227
|
+
for (const [index, result] of results.entries()) {
|
|
228
|
+
const suffix = suffixes[index];
|
|
229
|
+
if (suffix === undefined) {
|
|
230
|
+
// The first status wins: a result resent with the history, or replayed, changes nothing.
|
|
231
|
+
await tx.runStep.updateMany({
|
|
232
|
+
where: { runId, callId: result.callId, kind: "tool", status: null },
|
|
233
|
+
data: { status: result.status },
|
|
234
|
+
});
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const open = await tx.runStep.findFirst({
|
|
238
|
+
where: { runId, callId: result.callId, kind: "tool", status: null },
|
|
239
|
+
select: { id: true, detail: true },
|
|
240
|
+
});
|
|
241
|
+
if (!open)
|
|
242
|
+
continue;
|
|
243
|
+
await tx.runStep.update({
|
|
244
|
+
where: { id: open.id },
|
|
245
|
+
data: { status: result.status, detail: joinDetail(open.detail, suffix) },
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}, TX);
|
|
249
|
+
if (newlyDropped.length > 0)
|
|
250
|
+
this.rememberDropped(runId, counted, newlyDropped);
|
|
251
|
+
}
|
|
252
|
+
rememberDropped(runId, counted, ids) {
|
|
253
|
+
const limits = this.deps.droppedLimits ?? { perRun: DROPPED_PER_RUN, total: DROPPED_TOTAL };
|
|
254
|
+
for (const id of ids)
|
|
255
|
+
if (counted.size < limits.perRun)
|
|
256
|
+
counted.add(callKey(id));
|
|
257
|
+
this.droppedIds.delete(runId);
|
|
258
|
+
this.droppedIds.set(runId, counted);
|
|
259
|
+
while (this.rememberedDroppedCount() > limits.total && this.droppedIds.size > 1) {
|
|
260
|
+
this.droppedIds.delete(this.droppedIds.keys().next().value);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** How many dropped callIds are remembered in all (tests). */
|
|
264
|
+
rememberedDroppedCount() {
|
|
265
|
+
let total = 0;
|
|
266
|
+
for (const set of this.droppedIds.values())
|
|
267
|
+
total += set.size;
|
|
268
|
+
return total;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/** The process's writer: settings from the environment (an invalid value throws, naming it). */
|
|
272
|
+
export function buildRunStepWriter(db, cipher, env = process.env) {
|
|
273
|
+
return new RunStepWriter({
|
|
274
|
+
db,
|
|
275
|
+
level: loadRunStepsLevel(env),
|
|
276
|
+
retentionDays: loadRunStepRetentionDays(env),
|
|
277
|
+
secretValues: async (agentId) => (await loadAgentSecretValues(db, cipher, agentId)).flatMap((entry) => entry.values),
|
|
278
|
+
});
|
|
279
|
+
}
|
package/dist/core/runner.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { Prisma, type PrismaClient, type Run, type RunTrigger } from "#prisma";
|
|
|
21
21
|
import type { ProviderRegistry } from "../providers/index.js";
|
|
22
22
|
import type { EngineProgress, EngineResult, LoadedTool } from "../providers/engine/types.js";
|
|
23
23
|
import { RunOwnershipLostError, type StepRunner } from "../providers/engine/types.js";
|
|
24
|
+
import type { RunStepSink } from "./run-steps/types.js";
|
|
24
25
|
import { type PrivilegedHost } from "../sandbox/host-functions.js";
|
|
25
26
|
import type { safeFetch } from "../sandbox/safe-fetch.js";
|
|
26
27
|
import { type RunDrivability, type WorkerLauncher } from "../native-worker/gateway.js";
|
|
@@ -36,6 +37,42 @@ import { ReviewReadLedger } from "./review-reads.js";
|
|
|
36
37
|
import { type RepoAccessGate } from "./repo-access.js";
|
|
37
38
|
import { type BudgetEventView } from "./budget-events.js";
|
|
38
39
|
export declare const runnerLog: import("pino").Logger<never, boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* Sub-agent dispatch uses one synthetic tool per declared child, named by the
|
|
42
|
+
* boundName it's attached
|
|
43
|
+
* under. The parent's tool call blocks until the child run reaches a
|
|
44
|
+
* terminal state, and its result comes back as this tool call's result.
|
|
45
|
+
* A run delegates at most maxDelegationsPerRun times (default one: a
|
|
46
|
+
* classifier deciding plan-vs-implement commits to exactly one child) and to
|
|
47
|
+
* each child at most once. With Agent.parallelDelegations, the delegate_to_*
|
|
48
|
+
* calls of one turn run at the same time (NativeEngine.runToolCalls); their
|
|
49
|
+
* admission (the checks below plus the child row) is still one at a time,
|
|
50
|
+
* through the run's delegation gate, and a child refused for budget while a
|
|
51
|
+
* sibling runs waits for that sibling to finish (delegation-siblings.ts).
|
|
52
|
+
*
|
|
53
|
+
* Two execution paths depending on the child's `kind`:
|
|
54
|
+
* - `native`: calls `executeRun` directly, bypassing any `Executor` — the
|
|
55
|
+
* created Run row is never marked `executionManaged`, so the reconciler
|
|
56
|
+
* leaves it alone even if it runs long, the same way an attended
|
|
57
|
+
* `wardby run` foreground execution does. Fast, in-process, no durability
|
|
58
|
+
* machinery needed for a native turn loop.
|
|
59
|
+
* - `coding`: a coding-kind child needs a real Docker container (Codex),
|
|
60
|
+
* which `executeRun` explicitly refuses to drive itself. Goes through
|
|
61
|
+
* `dispatchRun` (the same persistence path webhooks/trigger_agent use)
|
|
62
|
+
* with `awaitExecution: true`, so the already-existing `RoutingExecutor`
|
|
63
|
+
* sends it to the container backend and this call blocks until it's
|
|
64
|
+
* terminal — reusing proven infrastructure rather than re-implementing
|
|
65
|
+
* container dispatch. Marked `executionManaged: true` here (unlike the
|
|
66
|
+
* native path) since a long-running container crash mid-dispatch is
|
|
67
|
+
* exactly the case the reconciler exists for. Under the coding
|
|
68
|
+
* concurrency cap `Executor.start` can resolve with the child merely
|
|
69
|
+
* queued (still pending), so the call then polls the child row until it
|
|
70
|
+
* is terminal — see `waitForCodingChild`.
|
|
71
|
+
*
|
|
72
|
+
* The `delegate_to_` prefix lives in core/tool-names.ts, which reserves it
|
|
73
|
+
* so no user tool can be created under a name this dispatch would shadow.
|
|
74
|
+
*/
|
|
75
|
+
export declare function delegateToolDef(boundName: string, parallel: boolean, repositories?: readonly string[]): LoadedTool;
|
|
39
76
|
declare const DelegateArgs: z.ZodObject<{
|
|
40
77
|
task: z.ZodString;
|
|
41
78
|
datastoreRef: z.ZodOptional<z.ZodObject<{
|
|
@@ -45,6 +82,7 @@ declare const DelegateArgs: z.ZodObject<{
|
|
|
45
82
|
grantParentMemoryKeys: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
83
|
continuePriorRun: z.ZodOptional<z.ZodString>;
|
|
47
84
|
mergeOrder: z.ZodOptional<z.ZodNumber>;
|
|
85
|
+
repository: z.ZodOptional<z.ZodString>;
|
|
48
86
|
}, z.core.$strict>;
|
|
49
87
|
/** A delegate_to_* call's arguments, or the tool result refusing them. */
|
|
50
88
|
export declare function parseDelegateArgs(argsJson: string): {
|
|
@@ -52,18 +90,6 @@ export declare function parseDelegateArgs(argsJson: string): {
|
|
|
52
90
|
} | {
|
|
53
91
|
refusal: string;
|
|
54
92
|
};
|
|
55
|
-
/**
|
|
56
|
-
* At most `limit` dispatches per run (default one: a classifier deciding plan-vs-implement
|
|
57
|
-
* commits to exactly one child), and never the same child twice, so a retry can't leave two
|
|
58
|
-
* children racing on the same task. A delegation waiting for budget holds its place.
|
|
59
|
-
*/
|
|
60
|
-
export declare function delegationLimitRefusal(input: {
|
|
61
|
-
priorChildAgentIds: readonly string[];
|
|
62
|
-
waitingChildAgentIds: readonly string[];
|
|
63
|
-
childAgentId: string;
|
|
64
|
-
boundName: string;
|
|
65
|
-
limit: number;
|
|
66
|
-
}): string | null;
|
|
67
93
|
declare const DELEGATION_CHILD_SELECT: {
|
|
68
94
|
readonly id: true;
|
|
69
95
|
readonly kind: true;
|
|
@@ -71,10 +97,13 @@ declare const DELEGATION_CHILD_SELECT: {
|
|
|
71
97
|
readonly budgetUsd: true;
|
|
72
98
|
readonly ownerId: true;
|
|
73
99
|
readonly nativeExecutionMode: true;
|
|
100
|
+
readonly runSteps: true;
|
|
74
101
|
readonly codingProfile: {
|
|
75
102
|
readonly select: {
|
|
76
103
|
readonly allowWebhookTaskOverride: true;
|
|
77
104
|
readonly timeoutSec: true;
|
|
105
|
+
readonly repository: true;
|
|
106
|
+
readonly baseRef: true;
|
|
78
107
|
};
|
|
79
108
|
};
|
|
80
109
|
};
|
|
@@ -105,7 +134,7 @@ export declare function nativeChildResult(run: Pick<Run, "status" | "finalText"
|
|
|
105
134
|
* also satisfies `dispatch.ts`'s `DispatchDb`, needed for dispatching a
|
|
106
135
|
* coding-kind sub-agent from inside a running native turn loop.
|
|
107
136
|
*/
|
|
108
|
-
export type RunnerDb = Pick<PrismaClient, "agent" | "run" | "agentTool" | "agentSecret" | "agentDatastore" | "budgetGroup" | "agentSubAgent" | "resourceGrant" | "codingRun" | "registryFetch" | "registryAuditRecord" | "task" | "webhook" | "$transaction" | "$queryRaw" | "agentRepository" | "runModelUsage" | "runHostCheck" | "runBudgetEvent" | "runHostStatus" | "hostIdentity" | "agentIssueProject" | "issuePullRequest" | "runIssueStatus" | "issueFingerprint" | "workItem" | "deferredReview" | "runAttribution">;
|
|
137
|
+
export type RunnerDb = Pick<PrismaClient, "agent" | "run" | "agentTool" | "agentSecret" | "agentMcpServer" | "secret" | "agentDatastore" | "budgetGroup" | "agentSubAgent" | "resourceGrant" | "codingRun" | "registryFetch" | "registryAuditRecord" | "task" | "webhook" | "$transaction" | "$queryRaw" | "agentRepository" | "runModelUsage" | "runHostCheck" | "runBudgetEvent" | "runHostStatus" | "hostIdentity" | "agentIssueProject" | "issuePullRequest" | "runIssueStatus" | "issueFingerprint" | "workItem" | "deferredReview" | "runAttribution">;
|
|
109
138
|
/** The providers a native run needs; `executor`, `reviewHosts` and `issueTrackers` are optional capabilities. */
|
|
110
139
|
export type NativeRunProviders = Pick<ProviderRegistry, "llm" | "engine" | "datastore" | "secrets" | "memory"> & {
|
|
111
140
|
executor?: ProviderRegistry["executor"];
|
|
@@ -121,6 +150,8 @@ export type NativeRunProviders = Pick<ProviderRegistry, "llm" | "engine" | "data
|
|
|
121
150
|
nativeSandbox?: WorkerLauncher;
|
|
122
151
|
/** Overrides the sandbox's outbound network call — tests only. */
|
|
123
152
|
sandboxFetch?: typeof safeFetch;
|
|
153
|
+
/** Records runs' steps (src/core/run-steps/writer.ts); absent = no steps are recorded. */
|
|
154
|
+
runSteps?: RunStepSink;
|
|
124
155
|
};
|
|
125
156
|
/**
|
|
126
157
|
* Raised when a run's step boundary observed a cancellation (DbosExecutor's
|
|
@@ -262,8 +293,6 @@ export interface LoadNativeRunOptions {
|
|
|
262
293
|
* order diverges from the record.
|
|
263
294
|
*/
|
|
264
295
|
export declare function loadNativeRun(options: LoadNativeRunOptions): Promise<{
|
|
265
|
-
repositoryLinks: RepositoryLink[];
|
|
266
|
-
issueProjectLinks: IssueProjectLink[];
|
|
267
296
|
agent: {
|
|
268
297
|
untrustedContext?: string | undefined;
|
|
269
298
|
effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
@@ -275,6 +304,7 @@ export declare function loadNativeRun(options: LoadNativeRunOptions): Promise<{
|
|
|
275
304
|
tools: LoadedTool[];
|
|
276
305
|
toolsByName: {
|
|
277
306
|
[k: string]: {
|
|
307
|
+
timeoutMs?: number | undefined;
|
|
278
308
|
code: string;
|
|
279
309
|
paramsZod: string;
|
|
280
310
|
allowedSecrets: string[];
|
|
@@ -283,6 +313,9 @@ export declare function loadNativeRun(options: LoadNativeRunOptions): Promise<{
|
|
|
283
313
|
allowedSharedDatastorePrefixes: Record<string, string[]>;
|
|
284
314
|
};
|
|
285
315
|
};
|
|
316
|
+
mcpTools?: import("./mcp-tools.js").McpToolPin[] | undefined;
|
|
317
|
+
repositoryLinks: RepositoryLink[];
|
|
318
|
+
issueProjectLinks: IssueProjectLink[];
|
|
286
319
|
parallelDelegations?: boolean | undefined;
|
|
287
320
|
maxDelegationsPerRun?: number | undefined;
|
|
288
321
|
agentId: string;
|
|
@@ -311,6 +344,8 @@ export interface NativeRunToolsOptions {
|
|
|
311
344
|
issueTrackers: IssueTrackerRegistry | undefined;
|
|
312
345
|
/** What earlier requests of this run read (a sandbox run's gateway restores it per request); fresh otherwise. */
|
|
313
346
|
reviewReads?: ReviewReadLedger;
|
|
347
|
+
/** A sandboxed run's session deadline (the gateway's); an MCP tool call never runs past it. */
|
|
348
|
+
deadlineAt?: Date;
|
|
314
349
|
}
|
|
315
350
|
/** An attached user tool as the load step pinned it: its code, schema, and consented capabilities. */
|
|
316
351
|
export type LoadedUserTool = LoadedNativeRun["toolsByName"][string];
|
|
@@ -336,6 +371,7 @@ export declare function readRedactionValues(accessor: SecretsAccessor, names: re
|
|
|
336
371
|
*/
|
|
337
372
|
export declare function createNativeRunTools(options: NativeRunToolsOptions): {
|
|
338
373
|
toolsByName: Map<string, {
|
|
374
|
+
timeoutMs?: number | undefined;
|
|
339
375
|
code: string;
|
|
340
376
|
paramsZod: string;
|
|
341
377
|
allowedSecrets: string[];
|
|
@@ -348,6 +384,13 @@ export declare function createNativeRunTools(options: NativeRunToolsOptions): {
|
|
|
348
384
|
readableSecretValues: (name: string) => Promise<string[]>;
|
|
349
385
|
runUserTool: (name: string, argsJson: string) => Promise<string>;
|
|
350
386
|
runSandboxTool: (name: string, argsJson: string, callId?: string) => Promise<string>;
|
|
387
|
+
toolTimeoutMs: (name: string) => number | undefined;
|
|
388
|
+
watchStop: () => {
|
|
389
|
+
signal: AbortSignal;
|
|
390
|
+
done: () => void;
|
|
391
|
+
};
|
|
392
|
+
/** Every secret value of the agent's attached MCP servers (never handed to a worker; redaction only). */
|
|
393
|
+
mcpSecretValues: () => Promise<string[]>;
|
|
351
394
|
};
|
|
352
395
|
/**
|
|
353
396
|
* Live progress for observers (MCP get_run, the viewer). Absolute totals, so a DBOS replay
|
|
@@ -374,6 +417,17 @@ export declare function finishNativeRun(ctx: NativeRunFinishContext, model: stri
|
|
|
374
417
|
export declare function failNativeRun(ctx: NativeRunFinishContext, err: unknown): Promise<Run>;
|
|
375
418
|
/** The terminal write for a run that cannot continue (it ends `lost` with `reason`), then the same settle path. */
|
|
376
419
|
export declare function loseNativeRun(ctx: NativeRunFinishContext, reason: string): Promise<Run>;
|
|
420
|
+
/** How often a user tool call in progress checks whether its run was stopped. */
|
|
421
|
+
export declare const TOOL_STOP_POLL_MS = 2000;
|
|
422
|
+
/**
|
|
423
|
+
* Aborts `signal` once the run is no longer drivable (stop_run, a cancelled task, a parent's
|
|
424
|
+
* stop). Polls every `intervalMs`, starting one interval in, so a quick call reads nothing; a
|
|
425
|
+
* failed read changes nothing and the next tick reads again. `done()` stops the polling.
|
|
426
|
+
*/
|
|
427
|
+
export declare function watchRunStop(db: RunnerDb, runId: string, intervalMs?: number): {
|
|
428
|
+
signal: AbortSignal;
|
|
429
|
+
done: () => void;
|
|
430
|
+
};
|
|
377
431
|
/** Where a run stands for the native gateway: still drivable, cancelled (its task), or otherwise ended. */
|
|
378
432
|
export declare function runDrivability(db: RunnerDb, runId: string): Promise<RunDrivability>;
|
|
379
433
|
/**
|
|
@@ -383,7 +437,7 @@ export declare function runDrivability(db: RunnerDb, runId: string): Promise<Run
|
|
|
383
437
|
*/
|
|
384
438
|
export declare function sandboxWorkerInput(runId: string, loaded: LoadedNativeRun, tools: Pick<ReturnType<typeof createNativeRunTools>, "builtinHandler" | "toolsByName">): WorkerInput;
|
|
385
439
|
/** What the durable delegation needs from the gateway ledger (src/native-worker/ledger.ts). */
|
|
386
|
-
export type DelegationLedger = Pick<PrismaGatewayLedger, "claim" | "recordResult" | "setDelegation" | "delegation" | "
|
|
440
|
+
export type DelegationLedger = Pick<PrismaGatewayLedger, "claim" | "recordResult" | "setDelegation" | "delegation" | "waitingDelegations">;
|
|
387
441
|
export interface DurableDelegationContext {
|
|
388
442
|
runId: string;
|
|
389
443
|
existingRun: Run;
|