@wardby/cli 0.7.0 → 0.8.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 +6 -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 +61 -0
- package/dist/claude-plugin/command.js +376 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +2 -1
- package/dist/cli.js +47 -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 +1 -1
- 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 +36 -11
- package/dist/core/error-code.js +1 -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/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/related-pull-requests.js +26 -10
- package/dist/core/review-fix.js +2 -2
- package/dist/core/review-host-tools.js +3 -1
- package/dist/core/runner.d.ts +66 -16
- package/dist/core/runner.js +281 -73
- 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 +31 -0
- package/dist/generated/prisma/client.d.ts +31 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +50 -50
- package/dist/generated/prisma/internal/class.d.ts +66 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +530 -1
- package/dist/generated/prisma/internal/prismaNamespace.js +75 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +79 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +75 -2
- package/dist/generated/prisma/models/Agent.d.ts +271 -0
- 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 +119 -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/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +6 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +719 -47
- 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/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 +3 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/tools/agents.js +100 -15
- 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/repositories.js +50 -10
- package/dist/mcp/tools/runs.js +178 -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 +14 -0
- package/dist/native-worker/gateway-server.js +28 -7
- package/dist/native-worker/gateway.d.ts +2 -0
- package/dist/native-worker/gateway.js +5 -1
- package/dist/native-worker/http-server.d.ts +4 -0
- package/dist/native-worker/http-server.js +51 -0
- 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 +15 -0
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +1 -0
- package/dist/providers/coding-proxy/prisma-ledger.js +30 -2
- package/dist/providers/coding-proxy/proxy.d.ts +7 -1
- package/dist/providers/coding-proxy/proxy.js +134 -34
- package/dist/providers/coding-proxy/runtime.d.ts +6 -0
- package/dist/providers/coding-proxy/runtime.js +32 -1
- 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 +13 -0
- package/dist/providers/executor/composition.js +5 -0
- package/dist/providers/executor/container.d.ts +33 -1
- package/dist/providers/executor/container.js +76 -7
- 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 +5 -0
- package/dist/providers/jobs/kubernetes.js +6 -1
- 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/viewer/graph.js +2 -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 +164 -0
- package/docs/code-review-agents.md +6 -0
- package/docs/coding-agent-setup.md +77 -1
- package/docs/coding-worker-byo-images.md +4 -2
- package/docs/coding-worker-isolation.md +78 -7
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +5 -4
- 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 +254 -0
- package/docs/native-sandbox.md +25 -9
- package/docs/security-deployment.md +110 -31
- package/docs/tool-secrets.md +3 -0
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +4 -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 +40 -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/mcp-servers.md +73 -0
- package/help/mcp.md +7 -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 +3 -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/schema.prisma +159 -14
- package/scripts/git-askpass.sh +1 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* compilation/validation is pure computation, no host I/O at all).
|
|
7
7
|
*/
|
|
8
8
|
import type { QuickJSContext, QuickJSRuntime } from "quickjs-emscripten";
|
|
9
|
-
export type SandboxErrorKind = "thrown" | "timeout" | "memory" | "cpu" | "non_serializable";
|
|
9
|
+
export type SandboxErrorKind = "thrown" | "timeout" | "memory" | "cpu" | "non_serializable" | "cancelled";
|
|
10
10
|
export type SandboxResult = {
|
|
11
11
|
ok: true;
|
|
12
12
|
value: unknown;
|
|
@@ -34,4 +34,14 @@ export declare function classifyEvalError(dumped: {
|
|
|
34
34
|
name?: string;
|
|
35
35
|
message?: string;
|
|
36
36
|
}): SandboxResult;
|
|
37
|
-
export
|
|
37
|
+
export interface EvalOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Ends the evaluation early when it aborts (a stopped run): the result is `aborted(reason)`,
|
|
40
|
+
* and every host call still in flight is aborted with it.
|
|
41
|
+
*/
|
|
42
|
+
signal?: AbortSignal;
|
|
43
|
+
aborted?: (reason: unknown) => SandboxResult;
|
|
44
|
+
/** The wall-time error's text; defaults to naming the limit. */
|
|
45
|
+
timeoutMessage?: (limitMs: number) => string;
|
|
46
|
+
}
|
|
47
|
+
export declare function evalToJson(code: string, limitsOverride: Partial<SandboxLimits> | undefined, installExtras: (context: QuickJSContext, runtime: QuickJSRuntime, signal: AbortSignal) => void, options?: EvalOptions): Promise<SandboxResult>;
|
|
@@ -56,9 +56,14 @@ export function classifyEvalError(dumped) {
|
|
|
56
56
|
errorMessage: dumped.message ? `${dumped.name ?? "Error"}: ${dumped.message}` : JSON.stringify(dumped),
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
const defaultAborted = () => ({ ok: false, errorKind: "cancelled", errorMessage: "Cancelled." });
|
|
60
|
+
export async function evalToJson(code, limitsOverride, installExtras, options = {}) {
|
|
60
61
|
const limits = { ...DEFAULT_SANDBOX_LIMITS, ...limitsOverride };
|
|
62
|
+
const aborted = options.aborted ?? defaultAborted;
|
|
63
|
+
if (options.signal?.aborted)
|
|
64
|
+
return aborted(options.signal.reason);
|
|
61
65
|
const controller = new AbortController();
|
|
66
|
+
let onAbort;
|
|
62
67
|
let timer;
|
|
63
68
|
const deadline = Date.now() + limits.wallTimeLimitMs;
|
|
64
69
|
const qjsModule = await getQuickJsModule();
|
|
@@ -68,7 +73,7 @@ export async function evalToJson(code, limitsOverride, installExtras) {
|
|
|
68
73
|
let steps = 0;
|
|
69
74
|
runtime.setInterruptHandler(() => {
|
|
70
75
|
steps += 1;
|
|
71
|
-
return steps > limits.maxInterruptChecks || Date.now() >= deadline;
|
|
76
|
+
return steps > limits.maxInterruptChecks || Date.now() >= deadline || options.signal?.aborted === true;
|
|
72
77
|
});
|
|
73
78
|
const context = runtime.newContext();
|
|
74
79
|
let disposed = false;
|
|
@@ -139,10 +144,19 @@ export async function evalToJson(code, limitsOverride, installExtras) {
|
|
|
139
144
|
timer = setTimeout(() => resolve({
|
|
140
145
|
ok: false,
|
|
141
146
|
errorKind: "timeout",
|
|
142
|
-
errorMessage:
|
|
147
|
+
errorMessage: options.timeoutMessage
|
|
148
|
+
? options.timeoutMessage(limits.wallTimeLimitMs)
|
|
149
|
+
: `Exceeded the ${limits.wallTimeLimitMs}ms wall-time limit.`,
|
|
143
150
|
}), limits.wallTimeLimitMs);
|
|
144
151
|
});
|
|
145
|
-
|
|
152
|
+
const external = options.signal;
|
|
153
|
+
const abortPromise = new Promise((resolve) => {
|
|
154
|
+
if (!external)
|
|
155
|
+
return;
|
|
156
|
+
onAbort = () => resolve(aborted(external.reason));
|
|
157
|
+
external.addEventListener("abort", onAbort, { once: true });
|
|
158
|
+
});
|
|
159
|
+
return await Promise.race([runPromise, timeoutPromise, abortPromise]);
|
|
146
160
|
}
|
|
147
161
|
catch (err) {
|
|
148
162
|
return {
|
|
@@ -153,6 +167,8 @@ export async function evalToJson(code, limitsOverride, installExtras) {
|
|
|
153
167
|
}
|
|
154
168
|
finally {
|
|
155
169
|
clearTimeout(timer);
|
|
170
|
+
if (onAbort)
|
|
171
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
156
172
|
controller.abort();
|
|
157
173
|
disposeAll();
|
|
158
174
|
}
|
|
@@ -43,6 +43,8 @@ export interface HostFunctionOptions {
|
|
|
43
43
|
redactSecretValues?: readonly string[];
|
|
44
44
|
/** Overrides the network call — tests only. */
|
|
45
45
|
fetchImpl?: typeof safeFetch;
|
|
46
|
+
/** Each fetch's timeout (fetchTimeoutFor the tool's limit); the default fetch timeout when absent. */
|
|
47
|
+
fetchTimeoutMs?: number;
|
|
46
48
|
}
|
|
47
49
|
/** One host bridge: JSON-string arguments in, a JSON-serializable value out (bridge.ts). */
|
|
48
50
|
export type HostBridge = (argsJson: string) => Promise<unknown>;
|
|
@@ -63,6 +65,8 @@ export declare function createPrivilegedHost(options: PrivilegedHostOptions): Pr
|
|
|
63
65
|
export interface SandboxApiOptions {
|
|
64
66
|
privileged: PrivilegedHost;
|
|
65
67
|
signal?: AbortSignal;
|
|
68
|
+
/** The tool's time limit, which also caps sleep(); the default wall-time cap when absent. */
|
|
69
|
+
wallTimeLimitMs?: number;
|
|
66
70
|
/** Overrides the shared default parser-worker pool — mainly for tests. */
|
|
67
71
|
parserPool?: ParserWorkerPool;
|
|
68
72
|
}
|
|
@@ -95,7 +95,11 @@ export function createPrivilegedHost(options) {
|
|
|
95
95
|
},
|
|
96
96
|
async __bridge_fetch(argsJson) {
|
|
97
97
|
const [url, init = {}, secretNames] = args(argsJson);
|
|
98
|
-
const policy = {
|
|
98
|
+
const policy = {
|
|
99
|
+
...sandboxFetchPolicy(allowedFetchHosts ?? []),
|
|
100
|
+
signal,
|
|
101
|
+
...(options.fetchTimeoutMs !== undefined ? { timeoutMs: options.fetchTimeoutMs } : {}),
|
|
102
|
+
};
|
|
99
103
|
if (secretNames === undefined || (Array.isArray(secretNames) && secretNames.length === 0)) {
|
|
100
104
|
return fetchImpl(url, init, policy);
|
|
101
105
|
}
|
|
@@ -177,13 +181,14 @@ export function createPrivilegedHost(options) {
|
|
|
177
181
|
/** Registers the whole sandbox API: the local bridges directly, the privileged ones through `privileged`. */
|
|
178
182
|
export function installSandboxApi(context, runtime, options) {
|
|
179
183
|
const { privileged, signal } = options;
|
|
184
|
+
const sleepLimitMs = options.wallTimeLimitMs ?? WALL_TIME_LIMIT_MS;
|
|
180
185
|
const register = (name, fn) => registerJsonAsyncFunction(context, runtime, name, fn, signal);
|
|
181
186
|
const parserPool = options.parserPool ?? (sharedParserPool ??= createParserWorkerPool());
|
|
182
187
|
for (const name of PRIVILEGED_BRIDGE_NAMES)
|
|
183
188
|
register(name, (argsJson) => privileged[name](argsJson));
|
|
184
189
|
register("__bridge_sleep", async (argsJson) => {
|
|
185
190
|
const [ms] = args(argsJson);
|
|
186
|
-
if (!Number.isFinite(ms) || ms < 0 || ms >
|
|
191
|
+
if (!Number.isFinite(ms) || ms < 0 || ms > sleepLimitMs)
|
|
187
192
|
throw new Error("sleep_limit");
|
|
188
193
|
await sleep(ms, undefined, { signal });
|
|
189
194
|
return null;
|
package/dist/sandbox/limits.d.ts
CHANGED
|
@@ -15,7 +15,10 @@ export declare const MAX_INTERRUPT_CHECKS = 20000000;
|
|
|
15
15
|
* awaiting a host async call (e.g. a slow `fetch`) — this does.
|
|
16
16
|
*/
|
|
17
17
|
export declare const WALL_TIME_LIMIT_MS = 10000;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* safeFetch's timeout when its caller gives none. A sandboxed tool's fetches get
|
|
20
|
+
* fetchTimeoutFor(the tool's limit) instead (tool-timeout.ts), just past its wall time.
|
|
21
|
+
*/
|
|
19
22
|
export declare const FETCH_TIMEOUT_MS = 8000;
|
|
20
23
|
/** QuickJS interpreter stack size cap (bytes). */
|
|
21
24
|
export declare const MAX_STACK_SIZE_BYTES: number;
|
package/dist/sandbox/limits.js
CHANGED
|
@@ -15,7 +15,10 @@ export const MAX_INTERRUPT_CHECKS = 20_000_000;
|
|
|
15
15
|
* awaiting a host async call (e.g. a slow `fetch`) — this does.
|
|
16
16
|
*/
|
|
17
17
|
export const WALL_TIME_LIMIT_MS = 10_000;
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* safeFetch's timeout when its caller gives none. A sandboxed tool's fetches get
|
|
20
|
+
* fetchTimeoutFor(the tool's limit) instead (tool-timeout.ts), just past its wall time.
|
|
21
|
+
*/
|
|
19
22
|
export const FETCH_TIMEOUT_MS = 8_000;
|
|
20
23
|
/** QuickJS interpreter stack size cap (bytes). */
|
|
21
24
|
export const MAX_STACK_SIZE_BYTES = 1024 * 1024; // 1 MiB
|
|
@@ -27,6 +27,8 @@ export interface SandboxInvocation {
|
|
|
27
27
|
toolName: string;
|
|
28
28
|
/** Overrides the default limits (limits.ts) — mainly for fast, deterministic tests. */
|
|
29
29
|
limits?: Partial<SandboxLimits>;
|
|
30
|
+
/** The tool's time limit (effectiveToolTimeoutMs); its fetches time out just before it. Overrides limits.wallTimeLimitMs. */
|
|
31
|
+
timeoutMs?: number;
|
|
30
32
|
/** Omitted for a dry run (no real agent) — secrets.get always resolves undefined. */
|
|
31
33
|
secrets?: SecretsAccessor;
|
|
32
34
|
/** Overrides the default shared logger — mainly for tests that need to capture forwarded console output. */
|
|
@@ -42,12 +44,16 @@ export interface ToolCodeInvocation {
|
|
|
42
44
|
code: string;
|
|
43
45
|
params: unknown;
|
|
44
46
|
limits?: Partial<SandboxLimits>;
|
|
47
|
+
/** Stops the call early (its run was stopped): it fails as `cancelled`, and its host calls are aborted. */
|
|
48
|
+
signal?: AbortSignal;
|
|
45
49
|
/** Built once per invocation, with that invocation's abort signal (fetch needs it). */
|
|
46
50
|
privileged: (signal: AbortSignal) => PrivilegedHost;
|
|
47
51
|
parserPool?: ParserWorkerPool;
|
|
48
52
|
}
|
|
49
53
|
/** Evaluates one tool body in a fresh QuickJS context against the given privileged host. */
|
|
50
54
|
export declare function runToolCode(invocation: ToolCodeInvocation): Promise<SandboxResult>;
|
|
55
|
+
/** The sandbox limits for a tool whose time limit is `timeoutMs` (absent: the defaults). */
|
|
56
|
+
export declare function toolLimits(timeoutMs: number | undefined, base?: Partial<SandboxLimits>): Partial<SandboxLimits>;
|
|
51
57
|
/** The in-process privileged host for a sandbox invocation. */
|
|
52
58
|
export declare function privilegedHostFor(invocation: SandboxInvocation, signal: AbortSignal): PrivilegedHost;
|
|
53
59
|
export declare function runInSandbox(invocation: SandboxInvocation): Promise<SandboxResult>;
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { createPrivilegedHost, installSandboxApi } from "./host-functions.js";
|
|
11
11
|
import { SANDBOX_PRELUDE } from "./prelude.js";
|
|
12
|
-
import { evalToJson, NON_SERIALIZABLE_MARKER } from "./eval-core.js";
|
|
12
|
+
import { DEFAULT_SANDBOX_LIMITS, evalToJson, NON_SERIALIZABLE_MARKER, } from "./eval-core.js";
|
|
13
|
+
import { fetchTimeoutFor, TOOL_RUN_STOPPED_MESSAGE, toolTimeoutMessage } from "./tool-timeout.js";
|
|
13
14
|
import { boundedJson, boundedString } from "./bounded-json.js";
|
|
14
15
|
import { BRIDGE_INPUT_BYTES } from "./limits.js";
|
|
15
16
|
/** Evaluates one tool body in a fresh QuickJS context against the given privileged host. */
|
|
@@ -39,14 +40,24 @@ export async function runToolCode(invocation) {
|
|
|
39
40
|
throw new Error("${NON_SERIALIZABLE_MARKER}" + (__serializeErr && __serializeErr.message));
|
|
40
41
|
}
|
|
41
42
|
})()`;
|
|
43
|
+
const wallTimeLimitMs = invocation.limits?.wallTimeLimitMs ?? DEFAULT_SANDBOX_LIMITS.wallTimeLimitMs;
|
|
42
44
|
return evalToJson(code, invocation.limits, (context, runtime, signal) => {
|
|
43
45
|
installSandboxApi(context, runtime, {
|
|
44
46
|
privileged: invocation.privileged(signal),
|
|
45
47
|
signal,
|
|
46
48
|
parserPool: invocation.parserPool,
|
|
49
|
+
wallTimeLimitMs,
|
|
47
50
|
});
|
|
51
|
+
}, {
|
|
52
|
+
signal: invocation.signal,
|
|
53
|
+
aborted: () => ({ ok: false, errorKind: "cancelled", errorMessage: TOOL_RUN_STOPPED_MESSAGE }),
|
|
54
|
+
timeoutMessage: toolTimeoutMessage,
|
|
48
55
|
});
|
|
49
56
|
}
|
|
57
|
+
/** The sandbox limits for a tool whose time limit is `timeoutMs` (absent: the defaults). */
|
|
58
|
+
export function toolLimits(timeoutMs, base) {
|
|
59
|
+
return timeoutMs === undefined ? { ...base } : { ...base, wallTimeLimitMs: timeoutMs };
|
|
60
|
+
}
|
|
50
61
|
/** The in-process privileged host for a sandbox invocation. */
|
|
51
62
|
export function privilegedHostFor(invocation, signal) {
|
|
52
63
|
return createPrivilegedHost({
|
|
@@ -59,13 +70,14 @@ export function privilegedHostFor(invocation, signal) {
|
|
|
59
70
|
allowedFetchHosts: invocation.allowedFetchHosts,
|
|
60
71
|
fetchImpl: invocation.fetchImpl,
|
|
61
72
|
signal,
|
|
73
|
+
fetchTimeoutMs: fetchTimeoutFor(invocation.timeoutMs ?? invocation.limits?.wallTimeLimitMs ?? DEFAULT_SANDBOX_LIMITS.wallTimeLimitMs),
|
|
62
74
|
});
|
|
63
75
|
}
|
|
64
76
|
export async function runInSandbox(invocation) {
|
|
65
77
|
return runToolCode({
|
|
66
78
|
code: invocation.code,
|
|
67
79
|
params: invocation.params,
|
|
68
|
-
limits: invocation.limits,
|
|
80
|
+
limits: toolLimits(invocation.timeoutMs, invocation.limits),
|
|
69
81
|
privileged: (signal) => privilegedHostFor(invocation, signal),
|
|
70
82
|
});
|
|
71
83
|
}
|
|
@@ -11,6 +11,8 @@ export declare function pinnedLookup(destination: Destination): LookupFunction;
|
|
|
11
11
|
export declare function requestPinned(destination: Destination, init: SafeFetchInit, signal: AbortSignal): Promise<IncomingMessage>;
|
|
12
12
|
export interface SafeFetchOptions extends FetchPolicyOptions {
|
|
13
13
|
signal?: AbortSignal;
|
|
14
|
+
/** This fetch's own timeout; FETCH_TIMEOUT_MS when absent. */
|
|
15
|
+
timeoutMs?: number;
|
|
14
16
|
connect?: typeof requestPinned;
|
|
15
17
|
/** False: a 3xx is returned to the caller as-is (brokered requests re-check every hop themselves). */
|
|
16
18
|
followRedirects?: boolean;
|
|
@@ -39,7 +39,7 @@ async function untilAbort(promise, signal) {
|
|
|
39
39
|
}
|
|
40
40
|
export async function safeFetch(input, init = {}, options = {}) {
|
|
41
41
|
const abort = new AbortController();
|
|
42
|
-
const timer = setTimeout(() => abort.abort(new Error("fetch_timeout")), FETCH_TIMEOUT_MS);
|
|
42
|
+
const timer = setTimeout(() => abort.abort(new Error("fetch_timeout")), options.timeoutMs ?? FETCH_TIMEOUT_MS);
|
|
43
43
|
const signal = options.signal ? AbortSignal.any([options.signal, abort.signal]) : abort.signal;
|
|
44
44
|
let url = input;
|
|
45
45
|
let method = init.method ?? "GET";
|
|
@@ -26,6 +26,7 @@ export declare function consoleRedactionValues(entry: {
|
|
|
26
26
|
value: string;
|
|
27
27
|
broker: SecretBrokerConfig | null;
|
|
28
28
|
}): string[];
|
|
29
|
+
export declare function encodedForms(value: string): string[];
|
|
29
30
|
export declare function scrubBrokeredResponse<T extends {
|
|
30
31
|
headers: Record<string, string>;
|
|
31
32
|
bodyBase64: string;
|
|
@@ -121,7 +121,7 @@ export function consoleRedactionValues(entry) {
|
|
|
121
121
|
return [entry.value];
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
|
-
function encodedForms(value) {
|
|
124
|
+
export function encodedForms(value) {
|
|
125
125
|
const buf = Buffer.from(value, "utf8");
|
|
126
126
|
// Query placement goes through URLSearchParams, which encodes ~ ! ' ( ) differently and space as "+",
|
|
127
127
|
// so both percent-encodings are scrubbed, each also in lowercase-hex form (a response may echo either).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sandboxed tool's time limit. A tool may ask for its own `timeoutMs`; the operator's
|
|
3
|
+
* WARDBY_TOOL_MAX_TIMEOUT_MS (config/tool-timeout.ts) caps it. Without one a tool keeps the
|
|
4
|
+
* default wall-time cap (limits.ts). Pure and worker-safe: no configuration is read here.
|
|
5
|
+
*/
|
|
6
|
+
/** A tool that sets no `timeoutMs`. */
|
|
7
|
+
export declare const DEFAULT_TOOL_TIMEOUT_MS = 10000;
|
|
8
|
+
/** The shortest `timeoutMs` a tool may ask for. */
|
|
9
|
+
export declare const MIN_TOOL_TIMEOUT_MS = 1000;
|
|
10
|
+
/** WARDBY_TOOL_MAX_TIMEOUT_MS when unset: five minutes. */
|
|
11
|
+
export declare const DEFAULT_TOOL_MAX_TIMEOUT_MS = 300000;
|
|
12
|
+
/**
|
|
13
|
+
* How far past the tool's limit each fetch's own timeout lies. The wall time ends the call (and
|
|
14
|
+
* aborts its fetches) first, so a slow request fails with the wall-time error that names the
|
|
15
|
+
* limit, not a fetch error.
|
|
16
|
+
*/
|
|
17
|
+
export declare const FETCH_TIMEOUT_MARGIN_MS = 1000;
|
|
18
|
+
/** The fetch timeout for a tool limit of `wallTimeLimitMs`. */
|
|
19
|
+
export declare function fetchTimeoutFor(wallTimeLimitMs: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* The limit a run uses for a tool: its own `timeoutMs` (or the default when it has none), never
|
|
22
|
+
* above the current ceiling, so lowering the ceiling also covers tools that already exist.
|
|
23
|
+
*/
|
|
24
|
+
export declare function effectiveToolTimeoutMs(timeoutMs: number | null | undefined, ceilingMs: number): number;
|
|
25
|
+
/** Why `timeoutMs` can't be stored on a tool under `ceilingMs`, or undefined when it can. */
|
|
26
|
+
export declare function toolTimeoutProblem(timeoutMs: unknown, ceilingMs: number): string | undefined;
|
|
27
|
+
/** The model-facing text for a tool that ran out of time. */
|
|
28
|
+
export declare function toolTimeoutMessage(limitMs: number): string;
|
|
29
|
+
/** The model-facing text for a tool call cut off at its run's deadline. */
|
|
30
|
+
export declare const TOOL_RUN_DEADLINE_MESSAGE = "Stopped at the run's deadline while this tool call was still running.";
|
|
31
|
+
/** The model-facing text for a tool call aborted because its run was stopped. */
|
|
32
|
+
export declare const TOOL_RUN_STOPPED_MESSAGE = "The run was stopped while this tool call was running.";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sandboxed tool's time limit. A tool may ask for its own `timeoutMs`; the operator's
|
|
3
|
+
* WARDBY_TOOL_MAX_TIMEOUT_MS (config/tool-timeout.ts) caps it. Without one a tool keeps the
|
|
4
|
+
* default wall-time cap (limits.ts). Pure and worker-safe: no configuration is read here.
|
|
5
|
+
*/
|
|
6
|
+
import { WALL_TIME_LIMIT_MS } from "./limits.js";
|
|
7
|
+
/** A tool that sets no `timeoutMs`. */
|
|
8
|
+
export const DEFAULT_TOOL_TIMEOUT_MS = WALL_TIME_LIMIT_MS;
|
|
9
|
+
/** The shortest `timeoutMs` a tool may ask for. */
|
|
10
|
+
export const MIN_TOOL_TIMEOUT_MS = 1_000;
|
|
11
|
+
/** WARDBY_TOOL_MAX_TIMEOUT_MS when unset: five minutes. */
|
|
12
|
+
export const DEFAULT_TOOL_MAX_TIMEOUT_MS = 300_000;
|
|
13
|
+
/**
|
|
14
|
+
* How far past the tool's limit each fetch's own timeout lies. The wall time ends the call (and
|
|
15
|
+
* aborts its fetches) first, so a slow request fails with the wall-time error that names the
|
|
16
|
+
* limit, not a fetch error.
|
|
17
|
+
*/
|
|
18
|
+
export const FETCH_TIMEOUT_MARGIN_MS = 1_000;
|
|
19
|
+
/** The fetch timeout for a tool limit of `wallTimeLimitMs`. */
|
|
20
|
+
export function fetchTimeoutFor(wallTimeLimitMs) {
|
|
21
|
+
return wallTimeLimitMs + FETCH_TIMEOUT_MARGIN_MS;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The limit a run uses for a tool: its own `timeoutMs` (or the default when it has none), never
|
|
25
|
+
* above the current ceiling, so lowering the ceiling also covers tools that already exist.
|
|
26
|
+
*/
|
|
27
|
+
export function effectiveToolTimeoutMs(timeoutMs, ceilingMs) {
|
|
28
|
+
if (timeoutMs === null || timeoutMs === undefined)
|
|
29
|
+
return DEFAULT_TOOL_TIMEOUT_MS;
|
|
30
|
+
return Math.min(timeoutMs, ceilingMs);
|
|
31
|
+
}
|
|
32
|
+
/** Why `timeoutMs` can't be stored on a tool under `ceilingMs`, or undefined when it can. */
|
|
33
|
+
export function toolTimeoutProblem(timeoutMs, ceilingMs) {
|
|
34
|
+
if (typeof timeoutMs !== "number" || !Number.isSafeInteger(timeoutMs)) {
|
|
35
|
+
return "timeoutMs must be a whole number of milliseconds.";
|
|
36
|
+
}
|
|
37
|
+
if (timeoutMs < MIN_TOOL_TIMEOUT_MS)
|
|
38
|
+
return `timeoutMs must be at least ${MIN_TOOL_TIMEOUT_MS} ms.`;
|
|
39
|
+
if (timeoutMs > ceilingMs) {
|
|
40
|
+
return `timeoutMs ${timeoutMs} is above this server's ceiling of ${ceilingMs} ms (WARDBY_TOOL_MAX_TIMEOUT_MS).`;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
/** The model-facing text for a tool that ran out of time. */
|
|
45
|
+
export function toolTimeoutMessage(limitMs) {
|
|
46
|
+
return (`Exceeded the ${limitMs}ms wall-time limit. A tool that needs longer can set timeoutMs ` +
|
|
47
|
+
"(create_tool or update_tool), up to the server's WARDBY_TOOL_MAX_TIMEOUT_MS.");
|
|
48
|
+
}
|
|
49
|
+
/** The model-facing text for a tool call cut off at its run's deadline. */
|
|
50
|
+
export const TOOL_RUN_DEADLINE_MESSAGE = "Stopped at the run's deadline while this tool call was still running.";
|
|
51
|
+
/** The model-facing text for a tool call aborted because its run was stopped. */
|
|
52
|
+
export const TOOL_RUN_STOPPED_MESSAGE = "The run was stopped while this tool call was running.";
|
|
@@ -10,5 +10,12 @@ import type { SandboxLimits } from "./eval-core.js";
|
|
|
10
10
|
export interface UserToolDefinition {
|
|
11
11
|
code: string;
|
|
12
12
|
paramsZod: string;
|
|
13
|
+
/** The time limit this run gives the tool (effectiveToolTimeoutMs); absent = the default. */
|
|
14
|
+
timeoutMs?: number;
|
|
13
15
|
}
|
|
14
|
-
export
|
|
16
|
+
export interface UserToolCallOptions {
|
|
17
|
+
limits?: Partial<SandboxLimits>;
|
|
18
|
+
/** Aborts the call when its run is stopped. */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}
|
|
21
|
+
export declare function runUserToolCall(tool: UserToolDefinition, argsJson: string, privileged: (signal: AbortSignal) => PrivilegedHost, options?: UserToolCallOptions): Promise<string>;
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* JSON error result. Worker-safe: it touches no database or provider, only the
|
|
6
6
|
* privileged host it is given, so the native sandbox worker runs it as is.
|
|
7
7
|
*/
|
|
8
|
-
import { runToolCode } from "./run-in-sandbox.js";
|
|
8
|
+
import { runToolCode, toolLimits } from "./run-in-sandbox.js";
|
|
9
9
|
import { validateParams } from "./zod-params.js";
|
|
10
|
-
export async function runUserToolCall(tool, argsJson, privileged,
|
|
10
|
+
export async function runUserToolCall(tool, argsJson, privileged, options = {}) {
|
|
11
11
|
let parsedArgs;
|
|
12
12
|
try {
|
|
13
13
|
// Some providers stream no JSON delta at all for a zero-parameter
|
|
@@ -24,7 +24,13 @@ export async function runUserToolCall(tool, argsJson, privileged, limits) {
|
|
|
24
24
|
if (!validation.ok) {
|
|
25
25
|
return JSON.stringify({ error: "validation_failed", message: validation.errorMessage });
|
|
26
26
|
}
|
|
27
|
-
const result = await runToolCode({
|
|
27
|
+
const result = await runToolCode({
|
|
28
|
+
code: tool.code,
|
|
29
|
+
params: validation.value,
|
|
30
|
+
limits: toolLimits(tool.timeoutMs, options.limits),
|
|
31
|
+
signal: options.signal,
|
|
32
|
+
privileged,
|
|
33
|
+
});
|
|
28
34
|
if (!result.ok) {
|
|
29
35
|
return JSON.stringify({ error: result.errorKind, message: result.errorMessage });
|
|
30
36
|
}
|
package/dist/viewer/graph.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { periodStart } from "../core/budget-groups.js";
|
|
2
|
+
import { codeProviderOf } from "../coding/code-host.js";
|
|
2
3
|
import { publicCodingRunResult } from "../coding/protocol.js";
|
|
3
4
|
const DEFAULT_SINCE_MS = 60 * 60 * 1000;
|
|
4
5
|
const RELATIVE_SINCE_MS = {
|
|
@@ -102,7 +103,7 @@ function outcomesFor(row, pullRequests, sites) {
|
|
|
102
103
|
!pullRequests.some((pr) => pr.url === result.pullRequestUrl)) {
|
|
103
104
|
outcomes.push({
|
|
104
105
|
kind: "pull_request",
|
|
105
|
-
provider:
|
|
106
|
+
provider: codeProviderOf(result.repository),
|
|
106
107
|
repository: result.repository,
|
|
107
108
|
number: result.pullRequestNumber,
|
|
108
109
|
url: result.pullRequestUrl,
|
package/dist/wardby-bin.js
CHANGED
|
@@ -52,6 +52,11 @@ async function main() {
|
|
|
52
52
|
const { resumeToolsCommand } = await import("./coding/transcript/resume/stand-in.js");
|
|
53
53
|
await resumeToolsCommand(process.argv.slice(3));
|
|
54
54
|
}
|
|
55
|
+
else if (command === "claude-plugin") {
|
|
56
|
+
// Sets up the Claude Code plugin on this machine: no environment, database, or server runtime.
|
|
57
|
+
const { claudePluginCommand } = await import("./claude-plugin/command.js");
|
|
58
|
+
process.exitCode = await claudePluginCommand(process.argv.slice(3));
|
|
59
|
+
}
|
|
55
60
|
else if (command === "knowledge") {
|
|
56
61
|
// Offline bundle validation: no environment, database, or HTTP runtime.
|
|
57
62
|
const { knowledgeCommand } = await import("./knowledge/cli.js");
|
package/docs/README.md
CHANGED
|
@@ -13,16 +13,26 @@
|
|
|
13
13
|
runs are billed.
|
|
14
14
|
- [Agent recipes](agent-recipes.md) gives two copyable setups, an architecture
|
|
15
15
|
keeper and a per-language builder, with the prerequisites each needs.
|
|
16
|
+
- [Debugging an agent run](debugging-agent-runs.md) triages a run that failed,
|
|
17
|
+
opened no pull request, or missed what you expected.
|
|
16
18
|
- [Coding-agent setup](coding-agent-setup.md) configures the local trusted proxy
|
|
17
19
|
and isolated Codex or Claude Code workers.
|
|
20
|
+
- [Claude Code plugin](claude-code-plugin.md) (0.8.0+) installs the `wardby-runs`
|
|
21
|
+
pane: your runs beside the chat, grouped by pull request, with run details and
|
|
22
|
+
Continue locally.
|
|
18
23
|
- [Architecture knowledge bundles](knowledge.md) covers `docs/knowledge/`: the
|
|
19
24
|
concept format, how coding runs and reviewers use it, `wardby knowledge check`,
|
|
20
25
|
and the scheduled architecture agent.
|
|
21
|
-
- [Native sandbox](native-sandbox.md) (0.
|
|
26
|
+
- [Native sandbox](native-sandbox.md) (0.6.0+) runs a native agent's turn loop and user
|
|
22
27
|
tools in a single-use, credential-free container behind a native gateway.
|
|
23
28
|
- [Secrets and tools](tool-secrets.md) covers readable and brokered secrets
|
|
24
29
|
(brokered secrets require 0.6.0+):
|
|
25
30
|
attaching secrets to tools, `set_secret_broker`, placements, and errors.
|
|
31
|
+
- [Remote MCP servers](mcp-servers.md) (0.8.0+) registers a remote MCP server and
|
|
32
|
+
attaches an allowlist of its tools to a native agent.
|
|
33
|
+
- [Host providers](host-providers.md) (0.8.0+) covers adding a code host with
|
|
34
|
+
your own custom tools: registering, approving, testing and removing a
|
|
35
|
+
provider.
|
|
26
36
|
- [Coding-worker isolation](coding-worker-isolation.md) documents the threat
|
|
27
37
|
model and enforced worker boundary.
|
|
28
38
|
- [Bring-your-own worker images](coding-worker-byo-images.md) explains how to
|
package/docs/agent-recipes.md
CHANGED
|
@@ -383,8 +383,9 @@ the lead's `maxDelegationsPerRun` (1 to 20) with `create_agent` or
|
|
|
383
383
|
{ "id": "<lead agent id>", "maxDelegationsPerRun": 6 }
|
|
384
384
|
```
|
|
385
385
|
|
|
386
|
-
-
|
|
387
|
-
|
|
386
|
+
- A run delegates to each sub-agent and repository at most once: a second call
|
|
387
|
+
to the same sub-agent in the same run (for a coding sub-agent with a list of
|
|
388
|
+
repositories, in the same repository) is refused with `already_dispatched`.
|
|
388
389
|
A delegation waiting for budget (see below) also holds its place against
|
|
389
390
|
`maxDelegationsPerRun`: a call beyond the limit is refused with
|
|
390
391
|
`already_dispatched` and a message naming both counts, e.g. "This run
|
|
@@ -507,6 +508,37 @@ the lead's `maxDelegationsPerRun` (1 to 20) with `create_agent` or
|
|
|
507
508
|
repositories, keep that work in separate requests (separate Jira issues, or
|
|
508
509
|
separate lead agents).
|
|
509
510
|
|
|
511
|
+
#### One coding agent, several repositories
|
|
512
|
+
|
|
513
|
+
Instead of one builder per repository, give one coding builder a list: its default in
|
|
514
|
+
`codingProfile.repository`, and each other repository with `link_repository`
|
|
515
|
+
(`access: "write"`, no triggers). The lead then names the repository on each
|
|
516
|
+
call, and may delegate to the same builder once per repository:
|
|
517
|
+
|
|
518
|
+
```json
|
|
519
|
+
{ "task": "Add the /quotes endpoint the client will call.", "repository": "your-org/api", "mergeOrder": 1 }
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
```json
|
|
523
|
+
{ "task": "Add the quotes page that calls /quotes.", "repository": "your-org/web", "mergeOrder": 2 }
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
Set `maxDelegationsPerRun` (up to 20) for the number of calls, and use
|
|
527
|
+
`mergeOrder` where the pull requests must land in order. A call without
|
|
528
|
+
`repository` is refused with `repository_required` when the builder has extra
|
|
529
|
+
repositories (unless it continues a prior run with `continuePriorRun`), and a
|
|
530
|
+
repository not on the list with `repository_not_listed`. A native sub-agent
|
|
531
|
+
refuses `repository` with `repository_requires_coding_agent`. The lead sees the
|
|
532
|
+
list in the tool definition only when it has the same owner as the builder, or
|
|
533
|
+
another owner with execute access to a builder that sets
|
|
534
|
+
`allowWebhookTaskOverride`. All repositories share the builder's toolchain,
|
|
535
|
+
budget and prompt.
|
|
536
|
+
|
|
537
|
+
Being on the list lets a run work in a repository; it starts nothing there. Link
|
|
538
|
+
the lead and the reviewer on each listed GitHub repository with the triggers
|
|
539
|
+
they need, or a pull request opened there gets no review, mention follow-up, fix
|
|
540
|
+
round or mark-ready.
|
|
541
|
+
|
|
510
542
|
#### Follow-ups across the set
|
|
511
543
|
|
|
512
544
|
A human-triggered follow-up task (an `@<app-slug>` mention, or a Jira issue
|
|
@@ -520,8 +552,9 @@ too:
|
|
|
520
552
|
repository that already has an open sibling for this request.
|
|
521
553
|
|
|
522
554
|
The usual delegation rails still apply on top of this: `maxDelegationsPerRun`
|
|
523
|
-
caps calls per run; a
|
|
524
|
-
|
|
555
|
+
caps calls per run; a run delegates to each sub-agent and repository at most
|
|
556
|
+
once, and a second such call is refused with `already_dispatched`; dispatch
|
|
557
|
+
re-checks every
|
|
525
558
|
`continuePriorRun` id (refusing with `continuation_refused` when this
|
|
526
559
|
deployment can't continue the run it names — for example it belongs to a
|
|
527
560
|
different owner's agent); every push to a sibling pull request still gets its
|
|
@@ -95,7 +95,7 @@ and GKE Autopilot overlays.
|
|
|
95
95
|
|
|
96
96
|
### Native agents in a sandbox
|
|
97
97
|
|
|
98
|
-
Native sandbox requires Wardby 0.
|
|
98
|
+
Native sandbox requires Wardby 0.6.0 or later.
|
|
99
99
|
|
|
100
100
|
Native agents run in the server process by default. A native agent set to
|
|
101
101
|
`nativeExecutionMode=sandbox` instead runs its turn loop and user tools in a
|