@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
|
@@ -115,11 +115,15 @@ export declare class PrismaGatewayLedger {
|
|
|
115
115
|
setDelegation(sessionId: string, callId: string, state: {
|
|
116
116
|
status: "pending" | "waiting_budget";
|
|
117
117
|
childAgentId: string;
|
|
118
|
+
childRepository?: string;
|
|
118
119
|
childRunId?: string;
|
|
119
120
|
}): Promise<void>;
|
|
120
121
|
delegation(sessionId: string, callId: string): Promise<DelegationState | null>;
|
|
121
|
-
/** The sub-agents other delegations of this run
|
|
122
|
-
|
|
122
|
+
/** The sub-agents (and repositories, null = the child's default) other delegations of this run wait on budget to start. */
|
|
123
|
+
waitingDelegations(sessionId: string, exceptCallId: string): Promise<{
|
|
124
|
+
childAgentId: string;
|
|
125
|
+
childRepository: string | null;
|
|
126
|
+
}[]>;
|
|
123
127
|
/** Delegations of this session whose child run is started and not yet reported. */
|
|
124
128
|
openDelegationChildren(sessionId: string): Promise<string[]>;
|
|
125
129
|
}
|
|
@@ -202,6 +202,7 @@ export class PrismaGatewayLedger {
|
|
|
202
202
|
data: {
|
|
203
203
|
status: state.status,
|
|
204
204
|
childAgentId: state.childAgentId,
|
|
205
|
+
...(state.childRepository ? { childRepository: state.childRepository } : {}),
|
|
205
206
|
...(state.childRunId ? { childRunId: state.childRunId } : {}),
|
|
206
207
|
},
|
|
207
208
|
});
|
|
@@ -213,13 +214,13 @@ export class PrismaGatewayLedger {
|
|
|
213
214
|
const status = row.status === "waiting_budget" ? "waiting_budget" : row.status === "completed" ? "completed" : "pending";
|
|
214
215
|
return { status, childRunId: row.childRunId, childAgentId: row.childAgentId, createdAt: row.createdAt };
|
|
215
216
|
}
|
|
216
|
-
/** The sub-agents other delegations of this run
|
|
217
|
-
async
|
|
217
|
+
/** The sub-agents (and repositories, null = the child's default) other delegations of this run wait on budget to start. */
|
|
218
|
+
async waitingDelegations(sessionId, exceptCallId) {
|
|
218
219
|
const rows = await this.db.nativeGatewayCall.findMany({
|
|
219
220
|
where: { sessionId, status: "waiting_budget", callId: { not: exceptCallId }, childAgentId: { not: null } },
|
|
220
|
-
select: { childAgentId: true },
|
|
221
|
+
select: { childAgentId: true, childRepository: true },
|
|
221
222
|
});
|
|
222
|
-
return rows.map((row) => row.childAgentId);
|
|
223
|
+
return rows.map((row) => ({ childAgentId: row.childAgentId, childRepository: row.childRepository }));
|
|
223
224
|
}
|
|
224
225
|
/** Delegations of this session whose child run is started and not yet reported. */
|
|
225
226
|
async openDelegationChildren(sessionId) {
|
|
@@ -145,6 +145,7 @@ export declare const WorkerInputSchema: z.ZodObject<{
|
|
|
145
145
|
userTools: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
146
146
|
code: z.ZodString;
|
|
147
147
|
paramsZod: z.ZodString;
|
|
148
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
148
149
|
}, z.core.$strict>>;
|
|
149
150
|
runsConcurrently: z.ZodArray<z.ZodString>;
|
|
150
151
|
pricing: z.ZodObject<{
|
|
@@ -125,7 +125,10 @@ const LoadedToolSchema = z
|
|
|
125
125
|
.object({ name: z.string(), description: z.string(), jsonSchema: z.record(z.string(), z.unknown()) })
|
|
126
126
|
.strict();
|
|
127
127
|
/** A user tool as the worker runs it: code and schema only. Capabilities stay on the gateway. */
|
|
128
|
-
|
|
128
|
+
/** `timeoutMs`: the tool's time limit for this run, already capped by the server; absent = the default. */
|
|
129
|
+
const WorkerUserToolSchema = z
|
|
130
|
+
.object({ code: z.string(), paramsZod: z.string(), timeoutMs: z.number().int().positive().optional() })
|
|
131
|
+
.strict();
|
|
129
132
|
const PricingSchema = z
|
|
130
133
|
.object({
|
|
131
134
|
provider: z.string(),
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The coding proxy's /mcp route (remote MCP servers, phase 2): the worker's MCP server URL. It
|
|
3
|
+
* checks the run's MCP token (`rmt_…`, WARDBY_MCP_TOKEN in the worker) against the proxy session,
|
|
4
|
+
* then forwards the JSON-RPC body unchanged, with the same Authorization, to the native gateway's
|
|
5
|
+
* /coding-mcp route (WARDBY_MCP_GATEWAY_URL), which checks the token again and runs the call. The
|
|
6
|
+
* proxy never sees an MCP server URL or secret; the gateway redacts results before they get here.
|
|
7
|
+
*
|
|
8
|
+
* Secrets: the token is only hashed and forwarded, never logged or echoed. The route's log line
|
|
9
|
+
* carries the session id, a sanitized JSON-RPC method, the status and a fixed reason code only:
|
|
10
|
+
* never the body, the token or an error's text. Every body this route writes is fixed text or the
|
|
11
|
+
* gateway's answer, unchanged.
|
|
12
|
+
*/
|
|
13
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
14
|
+
import type { ProxyLedger } from "./types.js";
|
|
15
|
+
export declare const MCP_ROUTE_PATH = "/mcp";
|
|
16
|
+
/** The longest a forwarded call may take, when the session's deadline is later. */
|
|
17
|
+
export declare const MCP_FORWARD_MAX_MS: number;
|
|
18
|
+
export declare const MCP_UNAVAILABLE_MESSAGE = "MCP tools aren't available on this server.";
|
|
19
|
+
/**
|
|
20
|
+
* A JSON-RPC method as the log may carry it: its first 64 characters when they are letters, `/`
|
|
21
|
+
* and `_` only, else "other". Anything that starts like an MCP token is "other" too.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mcpLogMethod(value: unknown): string;
|
|
24
|
+
export interface McpRouteOptions {
|
|
25
|
+
ledger: Pick<ProxyLedger, "findSessionByMcpTokenHash">;
|
|
26
|
+
/** The native gateway's base URL; without one, /mcp answers 503 mcp_unavailable. */
|
|
27
|
+
gatewayUrl: string | undefined;
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
now?: () => Date;
|
|
30
|
+
log?: {
|
|
31
|
+
info(fields: Record<string, unknown>, message: string): void;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare function createMcpRoute(options: McpRouteOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { isMcpToken, mcpTokenHash, MCP_TOKEN_REQUIRED_MESSAGE } from "../../coding/mcp-token.js";
|
|
2
|
+
import { logger } from "../../core/logger.js";
|
|
3
|
+
import { HTTP_LIMITS, HttpBoundaryError, readBodyBytes } from "../../mcp/transport/http-limits.js";
|
|
4
|
+
export const MCP_ROUTE_PATH = "/mcp";
|
|
5
|
+
/** The gateway's route this one forwards to. */
|
|
6
|
+
const GATEWAY_PATH = "/coding-mcp";
|
|
7
|
+
/** The longest a forwarded call may take, when the session's deadline is later. */
|
|
8
|
+
export const MCP_FORWARD_MAX_MS = 5 * 60_000;
|
|
9
|
+
/** The largest gateway answer relayed (a tool result is text the model reads; same as a model request). */
|
|
10
|
+
const MAX_GATEWAY_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
11
|
+
export const MCP_UNAVAILABLE_MESSAGE = "MCP tools aren't available on this server.";
|
|
12
|
+
const MCP_UNREACHABLE_MESSAGE = "MCP tools can't be reached right now.";
|
|
13
|
+
const LOG_METHOD = /^[A-Za-z/_]+$/;
|
|
14
|
+
/**
|
|
15
|
+
* A JSON-RPC method as the log may carry it: its first 64 characters when they are letters, `/`
|
|
16
|
+
* and `_` only, else "other". Anything that starts like an MCP token is "other" too.
|
|
17
|
+
*/
|
|
18
|
+
export function mcpLogMethod(value) {
|
|
19
|
+
if (typeof value !== "string")
|
|
20
|
+
return "other";
|
|
21
|
+
const method = value.slice(0, 64);
|
|
22
|
+
return LOG_METHOD.test(method) && !method.includes("rmt_") ? method : "other";
|
|
23
|
+
}
|
|
24
|
+
function methodOf(body) {
|
|
25
|
+
try {
|
|
26
|
+
const message = JSON.parse(body.toString("utf8"));
|
|
27
|
+
return mcpLogMethod(message?.method);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return "other";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
class GatewayError extends Error {
|
|
34
|
+
reason;
|
|
35
|
+
constructor(reason) {
|
|
36
|
+
super(reason);
|
|
37
|
+
this.reason = reason;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const JSON_HEADERS = { "content-type": "application/json", "cache-control": "no-store" };
|
|
41
|
+
const rpcError = (code, message) => JSON.stringify({ jsonrpc: "2.0", id: null, error: { code, message } });
|
|
42
|
+
async function readGatewayBody(response) {
|
|
43
|
+
const chunks = [];
|
|
44
|
+
let size = 0;
|
|
45
|
+
if (!response.body)
|
|
46
|
+
return Buffer.alloc(0);
|
|
47
|
+
for await (const chunk of response.body) {
|
|
48
|
+
size += chunk.byteLength;
|
|
49
|
+
if (size > MAX_GATEWAY_RESPONSE_BYTES) {
|
|
50
|
+
void response.body.cancel().catch(() => undefined);
|
|
51
|
+
throw new GatewayError("gateway_response_too_large");
|
|
52
|
+
}
|
|
53
|
+
chunks.push(Buffer.from(chunk));
|
|
54
|
+
}
|
|
55
|
+
return Buffer.concat(chunks, size);
|
|
56
|
+
}
|
|
57
|
+
export function createMcpRoute(options) {
|
|
58
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
59
|
+
const now = options.now ?? (() => new Date());
|
|
60
|
+
const log = options.log ?? logger.child({ module: "coding-proxy" });
|
|
61
|
+
const gatewayUrl = options.gatewayUrl?.replace(/\/+$/, "");
|
|
62
|
+
return async (req, res) => {
|
|
63
|
+
const startedAt = performance.now();
|
|
64
|
+
const seen = {};
|
|
65
|
+
/** Refused before the body was read: close the connection rather than read what is still coming. */
|
|
66
|
+
const closeIfBodyUnread = () => {
|
|
67
|
+
if (!req.complete && !res.headersSent)
|
|
68
|
+
res.setHeader("connection", "close");
|
|
69
|
+
};
|
|
70
|
+
const send = (status, body, headers = JSON_HEADERS) => {
|
|
71
|
+
res.writeHead(status, headers).end(body);
|
|
72
|
+
};
|
|
73
|
+
try {
|
|
74
|
+
if (req.method !== "POST") {
|
|
75
|
+
closeIfBodyUnread();
|
|
76
|
+
res.setHeader("allow", "POST");
|
|
77
|
+
if (req.method === "HEAD")
|
|
78
|
+
res.writeHead(405, JSON_HEADERS).end();
|
|
79
|
+
else
|
|
80
|
+
send(405, rpcError(-32600, "Use POST."));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!gatewayUrl) {
|
|
84
|
+
closeIfBodyUnread();
|
|
85
|
+
send(503, JSON.stringify({ error: "mcp_unavailable", message: MCP_UNAVAILABLE_MESSAGE }));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const token = /^Bearer (\S+)$/.exec(req.headers.authorization ?? "")?.[1];
|
|
89
|
+
const session = isMcpToken(token)
|
|
90
|
+
? await options.ledger.findSessionByMcpTokenHash(mcpTokenHash(token))
|
|
91
|
+
: undefined;
|
|
92
|
+
const at = now().getTime();
|
|
93
|
+
if (!session || session.status !== "active" || at >= session.deadlineAt.getTime()) {
|
|
94
|
+
// No WWW-Authenticate: a client must not start OAuth discovery against this route.
|
|
95
|
+
closeIfBodyUnread();
|
|
96
|
+
send(401, rpcError(-32001, MCP_TOKEN_REQUIRED_MESSAGE));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
seen.sessionId = session.id;
|
|
100
|
+
if (req.headers["content-type"]?.split(";", 1)[0].trim().toLowerCase() !== "application/json") {
|
|
101
|
+
closeIfBodyUnread();
|
|
102
|
+
send(415, rpcError(-32600, "Send one JSON-RPC message as application/json."));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
let body;
|
|
106
|
+
try {
|
|
107
|
+
body = await readBodyBytes(req, HTTP_LIMITS.json, AbortSignal.timeout(HTTP_LIMITS.requestMs));
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
closeIfBodyUnread();
|
|
111
|
+
send(error instanceof HttpBoundaryError ? error.status : 400, rpcError(-32600, "The request body could not be read."));
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
seen.method = methodOf(body);
|
|
115
|
+
// The call may take as long as it needs, up to the run's deadline or MCP_FORWARD_MAX_MS. The
|
|
116
|
+
// server's requestTimeout covers receiving the request only, which is over by now.
|
|
117
|
+
const controller = new AbortController();
|
|
118
|
+
const timer = setTimeout(() => controller.abort(new GatewayError("gateway_timeout")), Math.min(MCP_FORWARD_MAX_MS, session.deadlineAt.getTime() - at));
|
|
119
|
+
const clientGone = () => {
|
|
120
|
+
if (!res.writableFinished)
|
|
121
|
+
controller.abort(new GatewayError("client_disconnected"));
|
|
122
|
+
};
|
|
123
|
+
res.once("close", clientGone);
|
|
124
|
+
try {
|
|
125
|
+
const upstream = await fetchImpl(`${gatewayUrl}${GATEWAY_PATH}`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: { authorization: req.headers.authorization, "content-type": "application/json" },
|
|
128
|
+
body: new Uint8Array(body),
|
|
129
|
+
redirect: "error",
|
|
130
|
+
signal: controller.signal,
|
|
131
|
+
});
|
|
132
|
+
const answer = await readGatewayBody(upstream);
|
|
133
|
+
send(upstream.status, answer, {
|
|
134
|
+
"content-type": upstream.headers.get("content-type") ?? "application/json",
|
|
135
|
+
"cache-control": "no-store",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
const reason = controller.signal.reason instanceof GatewayError ? controller.signal.reason.reason : undefined;
|
|
140
|
+
throw error instanceof GatewayError ? error : new GatewayError(reason ?? "gateway_unreachable");
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
clearTimeout(timer);
|
|
144
|
+
res.off("close", clientGone);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
// Nothing of the error's text leaves or is logged: only a fixed reason code.
|
|
149
|
+
seen.reason = error instanceof GatewayError ? error.reason : "gateway_unreachable";
|
|
150
|
+
if (!res.headersSent)
|
|
151
|
+
send(502, JSON.stringify({ error: "mcp_unavailable", message: MCP_UNREACHABLE_MESSAGE }));
|
|
152
|
+
else
|
|
153
|
+
res.destroy();
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
log.info({
|
|
157
|
+
event: "mcp.request",
|
|
158
|
+
...(seen.sessionId ? { sessionId: seen.sessionId } : {}),
|
|
159
|
+
...(seen.method ? { method: seen.method } : {}),
|
|
160
|
+
status: res.statusCode,
|
|
161
|
+
...(seen.reason ? { reason: seen.reason } : {}),
|
|
162
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
163
|
+
}, "coding proxy mcp request");
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -4,6 +4,7 @@ export declare class MemoryProxyLedger implements ProxyLedger {
|
|
|
4
4
|
private readonly options;
|
|
5
5
|
private readonly sessions;
|
|
6
6
|
private readonly sessionByCapability;
|
|
7
|
+
private readonly sessionByMcpToken;
|
|
7
8
|
private readonly requests;
|
|
8
9
|
private readonly requestBySessionKey;
|
|
9
10
|
private readonly startedAt;
|
|
@@ -11,6 +12,7 @@ export declare class MemoryProxyLedger implements ProxyLedger {
|
|
|
11
12
|
now?: () => Date;
|
|
12
13
|
});
|
|
13
14
|
createSession(input: CreateProxySessionInput): Promise<void>;
|
|
15
|
+
findSessionByMcpTokenHash(mcpTokenHash: string): Promise<ProxySession | undefined>;
|
|
14
16
|
findSessionByCapabilityHash(capabilityHash: string): Promise<ProxySession | null>;
|
|
15
17
|
reserve(input: ReserveProxyRequestInput): Promise<ReserveProxyRequestResult>;
|
|
16
18
|
complete(requestId: string, usage: ProxyUsage, actualCostUsd: number, upstreamStatus: number): Promise<ProxyRequest>;
|
|
@@ -10,6 +10,7 @@ function cloneSession(session) {
|
|
|
10
10
|
terms: session.terms
|
|
11
11
|
? { version: session.terms.version, entry: { ...session.terms.entry, efforts: [...session.terms.entry.efforts] } }
|
|
12
12
|
: null,
|
|
13
|
+
mcpTools: session.mcpTools ? structuredClone(session.mcpTools) : null,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
function cloneRequest(request) {
|
|
@@ -24,6 +25,7 @@ export class MemoryProxyLedger {
|
|
|
24
25
|
options;
|
|
25
26
|
sessions = new Map();
|
|
26
27
|
sessionByCapability = new Map();
|
|
28
|
+
sessionByMcpToken = new Map();
|
|
27
29
|
requests = new Map();
|
|
28
30
|
requestBySessionKey = new Map();
|
|
29
31
|
startedAt = new Map();
|
|
@@ -36,14 +38,28 @@ export class MemoryProxyLedger {
|
|
|
36
38
|
}
|
|
37
39
|
if (this.sessionByCapability.has(input.capabilityHash))
|
|
38
40
|
throw new Error("proxy_capability_collision");
|
|
41
|
+
if (input.mcpTokenHash !== undefined && this.sessionByMcpToken.has(input.mcpTokenHash)) {
|
|
42
|
+
throw new Error("proxy_mcp_token_collision");
|
|
43
|
+
}
|
|
39
44
|
const session = {
|
|
40
45
|
...input,
|
|
41
46
|
allowedModels: [...input.allowedModels],
|
|
42
47
|
status: "active",
|
|
43
48
|
terms: input.terms ? normalizeProxyModelTerms(input.terms) : null,
|
|
49
|
+
mcpTools: input.mcpTools ? structuredClone(input.mcpTools) : null,
|
|
50
|
+
mcpTokenHash: input.mcpTokenHash ?? null,
|
|
51
|
+
mcpCallCount: 0,
|
|
52
|
+
runStepsLevel: input.runStepsLevel ?? null,
|
|
44
53
|
};
|
|
45
54
|
this.sessions.set(session.id, session);
|
|
46
55
|
this.sessionByCapability.set(session.capabilityHash, session.id);
|
|
56
|
+
if (session.mcpTokenHash !== null)
|
|
57
|
+
this.sessionByMcpToken.set(session.mcpTokenHash, session.id);
|
|
58
|
+
}
|
|
59
|
+
async findSessionByMcpTokenHash(mcpTokenHash) {
|
|
60
|
+
const id = this.sessionByMcpToken.get(mcpTokenHash);
|
|
61
|
+
const session = id ? this.sessions.get(id) : undefined;
|
|
62
|
+
return session ? cloneSession(session) : undefined;
|
|
47
63
|
}
|
|
48
64
|
async findSessionByCapabilityHash(capabilityHash) {
|
|
49
65
|
const id = this.sessionByCapability.get(capabilityHash);
|
|
@@ -20,6 +20,7 @@ export declare class PrismaProxyLedger implements ProxyLedger {
|
|
|
20
20
|
private transaction;
|
|
21
21
|
createSession(input: CreateProxySessionInput): Promise<void>;
|
|
22
22
|
findSessionByCapabilityHash(capabilityHash: string): Promise<ProxySession | null>;
|
|
23
|
+
findSessionByMcpTokenHash(mcpTokenHash: string): Promise<ProxySession | undefined>;
|
|
23
24
|
reserve(input: ReserveProxyRequestInput): Promise<ReserveProxyRequestResult>;
|
|
24
25
|
complete(requestId: string, usage: ProxyUsage, actualCostUsd: number, upstreamStatus: number): Promise<ProxyRequest>;
|
|
25
26
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RUN_STEPS_LEVELS } from "../../core/run-steps/config.js";
|
|
1
2
|
import { logger } from "../../core/logger.js";
|
|
2
3
|
import { normalizeProxyModelTerms } from "./types.js";
|
|
3
4
|
const log = logger.child({ module: "coding-proxy-ledger" });
|
|
@@ -14,6 +15,9 @@ export const LEDGER_TRANSACTION_MAX_WAIT_MS = 5_000;
|
|
|
14
15
|
* the model request. The row lock it holds is per session, so a longer
|
|
15
16
|
* window only delays that run's own next request. */
|
|
16
17
|
export const LEDGER_TRANSACTION_TIMEOUT_MS = 20_000;
|
|
18
|
+
function isRunStepsLevel(value) {
|
|
19
|
+
return typeof value === "string" && RUN_STEPS_LEVELS.includes(value);
|
|
20
|
+
}
|
|
17
21
|
function sessionFromRow(row) {
|
|
18
22
|
if (!Array.isArray(row.allowedModels) || !row.allowedModels.every((model) => typeof model === "string")) {
|
|
19
23
|
throw new Error("invalid_proxy_session_models");
|
|
@@ -35,8 +39,27 @@ function sessionFromRow(row) {
|
|
|
35
39
|
budgetExhaustedAt: row.budgetExhaustedAt ?? null,
|
|
36
40
|
upstreamFailure: row.upstreamFailure ?? null,
|
|
37
41
|
terms: sessionTerms(row),
|
|
42
|
+
mcpTools: sessionMcpTools(row),
|
|
43
|
+
mcpTokenHash: row.mcpTokenHash ?? null,
|
|
44
|
+
mcpCallCount: Number(row.mcpCallCount ?? 0),
|
|
45
|
+
runStepsLevel: isRunStepsLevel(row.runStepsLevel) ? row.runStepsLevel : null,
|
|
38
46
|
};
|
|
39
47
|
}
|
|
48
|
+
/** The session's pinned MCP tools; null when it has none. Anything but a list of pins refuses the session. */
|
|
49
|
+
function sessionMcpTools(row) {
|
|
50
|
+
const stored = row.mcpTools ?? null;
|
|
51
|
+
if (stored === null)
|
|
52
|
+
return null;
|
|
53
|
+
if (!Array.isArray(stored) ||
|
|
54
|
+
!stored.every((pin) => typeof pin === "object" &&
|
|
55
|
+
pin !== null &&
|
|
56
|
+
typeof pin.exposedName === "string" &&
|
|
57
|
+
typeof pin.toolName === "string" &&
|
|
58
|
+
typeof pin.serverId === "string")) {
|
|
59
|
+
throw new Error("invalid_proxy_session_mcp_tools");
|
|
60
|
+
}
|
|
61
|
+
return stored;
|
|
62
|
+
}
|
|
40
63
|
/**
|
|
41
64
|
* The session's stored model terms. Null only when both columns are null (a session from before
|
|
42
65
|
* the catalog, which prices from the shipped fallback); terms that are partly present or cannot be
|
|
@@ -109,22 +132,33 @@ export class PrismaProxyLedger {
|
|
|
109
132
|
await this.db.$executeRaw `
|
|
110
133
|
INSERT INTO "CodingProxySession"
|
|
111
134
|
("id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt",
|
|
112
|
-
"budgetUsd", "status", "registryTokenHash", "pricingVersion", "catalogEntry", "
|
|
135
|
+
"budgetUsd", "status", "registryTokenHash", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "runStepsLevel",
|
|
136
|
+
"createdAt", "updatedAt")
|
|
113
137
|
VALUES
|
|
114
138
|
(${input.id}, ${input.runId}, ${input.capabilityHash}, ${input.credentialRef}, ${input.protocol}, ${models}::jsonb,
|
|
115
139
|
${input.deadlineAt}, ${input.budgetUsd}, 'active', ${input.registryTokenHash},
|
|
116
140
|
${terms?.version ?? null}, ${terms ? JSON.stringify(terms.entry) : null}::jsonb,
|
|
141
|
+
${input.mcpTools ? JSON.stringify(input.mcpTools) : null}::jsonb, ${input.mcpTokenHash ?? null},
|
|
142
|
+
${input.runStepsLevel ?? null}::"RunStepsLevel",
|
|
117
143
|
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
118
144
|
`;
|
|
119
145
|
}
|
|
120
146
|
async findSessionByCapabilityHash(capabilityHash) {
|
|
121
147
|
const rows = await this.db.$queryRaw `
|
|
122
148
|
SELECT "id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt", "budgetUsd", "status", "registryTokenHash",
|
|
123
|
-
"budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry"
|
|
149
|
+
"budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "mcpCallCount", "runStepsLevel"
|
|
124
150
|
FROM "CodingProxySession" WHERE "capabilityHash" = ${capabilityHash}
|
|
125
151
|
`;
|
|
126
152
|
return rows[0] ? sessionFromRow(rows[0]) : null;
|
|
127
153
|
}
|
|
154
|
+
async findSessionByMcpTokenHash(mcpTokenHash) {
|
|
155
|
+
const rows = await this.db.$queryRaw `
|
|
156
|
+
SELECT "id", "runId", "capabilityHash", "credentialRef", "protocol", "allowedModels", "deadlineAt", "budgetUsd", "status", "registryTokenHash",
|
|
157
|
+
"budgetExhaustedAt", "upstreamFailure", "pricingVersion", "catalogEntry", "mcpTools", "mcpTokenHash", "mcpCallCount", "runStepsLevel"
|
|
158
|
+
FROM "CodingProxySession" WHERE "mcpTokenHash" = ${mcpTokenHash}
|
|
159
|
+
`;
|
|
160
|
+
return rows[0] ? sessionFromRow(rows[0]) : undefined;
|
|
161
|
+
}
|
|
128
162
|
async reserve(input) {
|
|
129
163
|
return this.transaction(async (tx) => {
|
|
130
164
|
const sessions = await tx.$queryRaw `
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { ModelPricing } from "../llm/pricing-core.js";
|
|
2
|
+
import { capabilityHash } from "./capability-hash.js";
|
|
3
|
+
import type { McpToolPin } from "../../core/mcp-tools.js";
|
|
4
|
+
import { type StepCaptureOptions, type StreamStepExtractor } from "../../core/run-steps/extract.js";
|
|
5
|
+
import { type RunStepsLevel } from "../../core/run-steps/config.js";
|
|
6
|
+
import type { RunStepSubmitter } from "../../core/run-steps/types.js";
|
|
2
7
|
import type { CredentialResolver, ProxyAuditSink, ProxyLedger, ProxyModelTerms, ProxyProtocol, ProxyRefusalRecord } from "./types.js";
|
|
3
8
|
export declare const PROXY_MAX_BODY_BYTES: number;
|
|
4
9
|
export declare const PROXY_MAX_OUTPUT_TOKENS = 1000000;
|
|
@@ -43,6 +48,12 @@ export interface CreateCodingProxySession {
|
|
|
43
48
|
budgetUsd: number;
|
|
44
49
|
/** The run's catalog entry recorded at dispatch; the session then prices and shapes requests from it. */
|
|
45
50
|
terms?: ProxyModelTerms;
|
|
51
|
+
/** The run's pinned MCP tools (no URLs or secrets); only with mcpTokenHash, and only when there is one. */
|
|
52
|
+
mcpTools?: McpToolPin[];
|
|
53
|
+
/** SHA-256 (base64url) of the run's MCP token; the control plane mints and delivers the token itself. */
|
|
54
|
+
mcpTokenHash?: string;
|
|
55
|
+
/** The run's level (Run.runStepsLevel), fixed at dispatch; absent counts as summary. */
|
|
56
|
+
runStepsLevel?: RunStepsLevel;
|
|
46
57
|
}
|
|
47
58
|
export interface CreatedCodingProxySession {
|
|
48
59
|
id: string;
|
|
@@ -69,8 +80,21 @@ export interface CodingProxyOptions {
|
|
|
69
80
|
* dependency cache's seal, ModelRequestSeal). Awaited; a failure is ignored, never the request's.
|
|
70
81
|
*/
|
|
71
82
|
onModelRequest?: (runId: string) => Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Where coding runs' steps go (RunStepForwarder, to the control plane's run-steps listener);
|
|
85
|
+
* absent, no step is extracted. Steps are read from frames after they are relayed and handed over
|
|
86
|
+
* unmasked (the control plane redacts them by exact value before writing). Extraction never fails,
|
|
87
|
+
* delays or alters a relay, and nothing of it is logged or written to the proxy's database.
|
|
88
|
+
* Tool-result output (its end) is sent only for a session at detail under a detail ceiling; at off
|
|
89
|
+
* nothing is read.
|
|
90
|
+
*/
|
|
91
|
+
steps?: RunStepSubmitter;
|
|
92
|
+
/** The proxy's own WARDBY_RUN_STEPS: a session captures detail only when this is detail too. Default summary. */
|
|
93
|
+
runStepsCeiling?: RunStepsLevel;
|
|
94
|
+
/** Tests only: replaces the stream step extractor. */
|
|
95
|
+
createStepExtractor?: (protocol: ProxyProtocol, options?: StepCaptureOptions) => StreamStepExtractor;
|
|
72
96
|
}
|
|
73
|
-
export
|
|
97
|
+
export { capabilityHash };
|
|
74
98
|
export declare class CodingProxy {
|
|
75
99
|
private readonly ledger;
|
|
76
100
|
private readonly credentials;
|
|
@@ -82,6 +106,11 @@ export declare class CodingProxy {
|
|
|
82
106
|
private readonly priceVersion;
|
|
83
107
|
private readonly activeRequests;
|
|
84
108
|
private readonly onModelRequest?;
|
|
109
|
+
private readonly steps?;
|
|
110
|
+
private readonly createStepExtractor?;
|
|
111
|
+
private readonly runStepsCeiling;
|
|
112
|
+
/** Results already handed over, per session: each request resends the history. */
|
|
113
|
+
private readonly seenResults;
|
|
85
114
|
constructor(options: CodingProxyOptions);
|
|
86
115
|
createSession(input: CreateCodingProxySession): Promise<CreatedCodingProxySession>;
|
|
87
116
|
cancelSession(sessionId: string): Promise<void>;
|
|
@@ -100,6 +129,9 @@ export declare class CodingProxy {
|
|
|
100
129
|
private complete;
|
|
101
130
|
private forwardJson;
|
|
102
131
|
private forwardStream;
|
|
132
|
+
/** Queues a step batch for the control plane. Best effort: any failure drops the steps, never the request. */
|
|
133
|
+
private submitSteps;
|
|
134
|
+
private newStepExtractor;
|
|
103
135
|
/** Best effort: the executor reads it to name the failure; it must never break the relay. */
|
|
104
136
|
private recordUpstreamFailure;
|
|
105
137
|
private markUncertain;
|