toolroll 0.9.63 → 0.9.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +108 -0
- package/README.md +33 -5
- package/dist/acp-agents.d.ts +43 -0
- package/dist/acp-agents.js +62 -0
- package/dist/acp-attest.d.ts +44 -0
- package/dist/acp-attest.js +269 -0
- package/dist/acp-check.d.ts +28 -0
- package/dist/acp-check.js +410 -0
- package/dist/acp-client.d.ts +163 -0
- package/dist/acp-client.js +738 -0
- package/dist/acp-inspect.d.ts +23 -0
- package/dist/acp-inspect.js +109 -0
- package/dist/agent-board.d.ts +19 -6
- package/dist/agent-board.js +30 -9
- package/dist/agent-fence.d.ts +117 -2
- package/dist/agent-fence.js +439 -12
- package/dist/agent-pulse.js +9 -2
- package/dist/agent-state-words.d.ts +19 -0
- package/dist/agent-state-words.js +20 -0
- package/dist/agent-state.d.ts +65 -0
- package/dist/agent-state.js +229 -0
- package/dist/agentconfig.js +39 -13
- package/dist/agents-board.d.ts +34 -2
- package/dist/agents-board.js +110 -1
- package/dist/approval-rules-ui.js +2 -2
- package/dist/assignment-delivery.d.ts +14 -0
- package/dist/assignment-delivery.js +13 -0
- package/dist/assignment.js +13 -0
- package/dist/attest.js +7 -0
- package/dist/backup-ui.js +2 -2
- package/dist/batch-checks.js +3 -2
- package/dist/browser/THIRD_PARTY_NOTICES.txt +94 -0
- package/dist/browser/terminal.css +37 -0
- package/dist/browser/terminal.js +228 -0
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +42 -38
- package/dist/browser-shell.js +6 -3
- package/dist/browser-workspace.d.ts +235 -1
- package/dist/browser-workspace.js +60 -0
- package/dist/builder.d.ts +10 -1
- package/dist/builder.js +87 -24
- package/dist/chat-actions.d.ts +13 -1
- package/dist/chat-actions.js +197 -15
- package/dist/chat-ask.d.ts +4 -0
- package/dist/chat-ask.js +14 -0
- package/dist/chat-channel.js +20 -0
- package/dist/chat-continuity.js +5 -4
- package/dist/chat-decide.d.ts +0 -14
- package/dist/chat-decide.js +4 -1
- package/dist/chat-delivery.d.ts +9 -0
- package/dist/chat-delivery.js +45 -6
- package/dist/chat-messages.d.ts +8 -0
- package/dist/chat-messages.js +36 -4
- package/dist/check-levels-ui.js +2 -2
- package/dist/checkout-proof.d.ts +28 -0
- package/dist/checkout-proof.js +62 -0
- package/dist/claim.d.ts +12 -0
- package/dist/claim.js +19 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +4 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +21 -2
- package/dist/coding-ui.js +6 -4
- package/dist/console-instance.d.ts +124 -0
- package/dist/console-instance.js +337 -0
- package/dist/contracts/chat-actions.d.ts +16 -0
- package/dist/contracts/chat-actions.js +4 -0
- package/dist/contracts/chat-content.d.ts +19 -0
- package/dist/contracts/chat-content.js +6 -0
- package/dist/contracts/console-api.d.ts +13 -4
- package/dist/contracts/console-api.js +13 -4
- package/dist/contracts/flow-card.d.ts +4 -0
- package/dist/contracts/flow-card.js +3 -0
- package/dist/contracts/flow.d.ts +46 -0
- package/dist/contracts/flow.js +11 -2
- package/dist/contracts/lead-tools.d.ts +92 -0
- package/dist/contracts/lead-tools.js +13 -0
- package/dist/contracts/provider.d.ts +11 -1
- package/dist/contracts/provider.js +1 -1
- package/dist/contracts/route.d.ts +76 -1
- package/dist/contracts/route.js +1 -1
- package/dist/contracts/store-json.d.ts +2 -0
- package/dist/control-setup.d.ts +1 -1
- package/dist/control-ui.js +2 -2
- package/dist/converse.d.ts +16 -0
- package/dist/converse.js +32 -4
- package/dist/demo-chat.js +4 -4
- package/dist/demo.js +2 -2
- package/dist/desktop-update-gate.js +6 -0
- package/dist/desktop-update.d.ts +1 -1
- package/dist/discord-chat.js +4 -1
- package/dist/doctor.js +1 -1
- package/dist/egress-bridge.d.ts +17 -0
- package/dist/egress-bridge.js +111 -0
- package/dist/egress.d.ts +119 -0
- package/dist/egress.js +423 -0
- package/dist/exec.d.ts +78 -0
- package/dist/exec.js +367 -9
- package/dist/export-ui.js +2 -2
- package/dist/flow-engine.js +24 -5
- package/dist/flow-gallery-ui.js +2 -2
- package/dist/flow-gallery.js +27 -8
- package/dist/flow-share.js +16 -5
- package/dist/flow-triggers.d.ts +77 -8
- package/dist/flow-triggers.js +517 -70
- package/dist/flows-cli.js +8 -2
- package/dist/flows-ui.d.ts +0 -2
- package/dist/flows-ui.js +52 -4
- package/dist/flows.d.ts +4 -0
- package/dist/flows.js +9 -1
- package/dist/html.d.ts +9 -0
- package/dist/html.js +11 -0
- package/dist/invoke.d.ts +35 -0
- package/dist/invoke.js +347 -28
- package/dist/keys.d.ts +18 -14
- package/dist/keys.js +5 -0
- package/dist/lead-capabilities.js +3 -2
- package/dist/lead-contract.js +2 -0
- package/dist/lead-doors.d.ts +2 -0
- package/dist/lead-doors.js +7 -0
- package/dist/lead-follow.d.ts +2 -0
- package/dist/lead-follow.js +58 -2
- package/dist/lead-progress.js +1 -0
- package/dist/lead-queue-runtime.d.ts +46 -0
- package/dist/lead-queue-runtime.js +191 -0
- package/dist/lead-queue.d.ts +104 -0
- package/dist/lead-queue.js +187 -0
- package/dist/lead-sweep.d.ts +67 -0
- package/dist/lead-sweep.js +99 -0
- package/dist/lead-tools.d.ts +22 -0
- package/dist/lead-tools.js +152 -1
- package/dist/lead.d.ts +13 -5
- package/dist/lead.js +89 -29
- package/dist/limits-ui.d.ts +8 -1
- package/dist/limits-ui.js +26 -0
- package/dist/live-bus.d.ts +8 -0
- package/dist/live-bus.js +40 -4
- package/dist/live-detail.d.ts +27 -0
- package/dist/live-detail.js +57 -0
- package/dist/live-notes.d.ts +20 -0
- package/dist/live-notes.js +47 -0
- package/dist/live-records.d.ts +140 -0
- package/dist/live-records.js +935 -0
- package/dist/live-terminal.d.ts +269 -0
- package/dist/live-terminal.js +686 -0
- package/dist/live.d.ts +38 -27
- package/dist/live.js +142 -124
- package/dist/mcp-oauth.d.ts +6 -3
- package/dist/mcp-oauth.js +8 -4
- package/dist/memory-pass.js +2 -2
- package/dist/mobile-viewport.d.ts +5 -1
- package/dist/mobile-viewport.js +18 -2
- package/dist/model-catalog.js +4 -0
- package/dist/monitoring-ui.js +2 -2
- package/dist/needs-you.d.ts +1 -1
- package/dist/needs-you.js +11 -4
- package/dist/operate.d.ts +4 -0
- package/dist/operate.js +335 -19
- package/dist/passwordless.d.ts +23 -0
- package/dist/passwordless.js +26 -0
- package/dist/peek-cli.d.ts +12 -4
- package/dist/peek-cli.js +19 -11
- package/dist/phase-routing.js +10 -3
- package/dist/planner-source.d.ts +3 -0
- package/dist/planner-source.js +14 -0
- package/dist/planner.d.ts +2 -1
- package/dist/planner.js +7 -1
- package/dist/policy-ui.js +2 -2
- package/dist/policy.d.ts +1 -20
- package/dist/policy.js +29 -2
- package/dist/project-delete-ui.d.ts +18 -0
- package/dist/project-delete-ui.js +60 -9
- package/dist/project-delete.js +2 -2
- package/dist/project-memory.d.ts +3 -1
- package/dist/project-memory.js +57 -25
- package/dist/project-tools.d.ts +5 -3
- package/dist/project-tools.js +12 -9
- package/dist/provider-auth.d.ts +4 -3
- package/dist/provider-auth.js +5 -4
- package/dist/provider-connection.d.ts +2 -1
- package/dist/provider-connection.js +5 -0
- package/dist/provider.d.ts +25 -2
- package/dist/provider.js +63 -9
- package/dist/pull-request-ui.js +2 -2
- package/dist/push.js +1 -1
- package/dist/quick-start.d.ts +24 -0
- package/dist/quick-start.js +127 -0
- package/dist/release-adapters.d.ts +6 -0
- package/dist/release-adapters.js +70 -3
- package/dist/release.d.ts +10 -1
- package/dist/release.js +34 -15
- package/dist/request-budget-ui.js +2 -2
- package/dist/result-follow-ups.js +3 -2
- package/dist/result-review.d.ts +1 -1
- package/dist/result-review.js +9 -3
- package/dist/retention-ui.js +2 -2
- package/dist/retention.js +10 -1
- package/dist/run-efficiency.d.ts +73 -0
- package/dist/run-efficiency.js +228 -0
- package/dist/runner.d.ts +5 -1
- package/dist/runner.js +22 -1
- package/dist/scope.d.ts +183 -5
- package/dist/scope.js +256 -31
- package/dist/scout-net.d.ts +4 -1
- package/dist/scout-net.js +37 -12
- package/dist/scout.d.ts +20 -6
- package/dist/scout.js +27 -3
- package/dist/serve.js +248 -40
- package/dist/server/chat.d.ts +1 -1
- package/dist/server/chat.js +122 -31
- package/dist/server/chrome.d.ts +16 -2
- package/dist/server/chrome.js +63 -11
- package/dist/server/console.css +107 -42
- package/dist/server/flows.js +38 -8
- package/dist/server/guards.d.ts +1 -0
- package/dist/server/guards.js +23 -9
- package/dist/server/http.d.ts +7 -0
- package/dist/server/http.js +3 -2
- package/dist/server/live.d.ts +34 -1
- package/dist/server/live.js +39 -17
- package/dist/server/pages-assets.js +5 -0
- package/dist/server/pages.js +90 -13
- package/dist/server/people-tokens.d.ts +3 -0
- package/dist/server/people-tokens.js +55 -17
- package/dist/server/remote-hooks.js +12 -6
- package/dist/server/remote.d.ts +2 -1
- package/dist/server/remote.js +14 -5
- package/dist/server/render-chat.d.ts +12 -3
- package/dist/server/render-chat.js +47 -16
- package/dist/server/render-pages.d.ts +32 -4
- package/dist/server/render-pages.js +83 -13
- package/dist/server/render-people.d.ts +3 -2
- package/dist/server/render-people.js +3 -2
- package/dist/server/render-results.d.ts +18 -2
- package/dist/server/render-results.js +37 -28
- package/dist/server/render-settings.js +6 -5
- package/dist/server/render-tasks.d.ts +35 -10
- package/dist/server/render-tasks.js +111 -27
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/request-context.js +2 -1
- package/dist/server/route-table.d.ts +3 -0
- package/dist/server/route-table.js +47 -5
- package/dist/server/runtime.d.ts +33 -2
- package/dist/server/session.d.ts +25 -1
- package/dist/server/session.js +18 -4
- package/dist/server/settings.js +142 -10
- package/dist/server/sweeps.d.ts +4 -0
- package/dist/server/sweeps.js +58 -0
- package/dist/server/task-views.d.ts +2 -1
- package/dist/server/task-views.js +96 -6
- package/dist/server/tasks.js +327 -78
- package/dist/server/terminals.d.ts +31 -0
- package/dist/server/terminals.js +365 -0
- package/dist/setup-guide.js +3 -2
- package/dist/slack-chat.js +4 -1
- package/dist/spend-ui.js +3 -3
- package/dist/spend.js +2 -1
- package/dist/steer-capabilities.d.ts +32 -0
- package/dist/steer-capabilities.js +60 -0
- package/dist/steer-controls.d.ts +14 -0
- package/dist/steer-controls.js +36 -0
- package/dist/steer-status.js +2 -2
- package/dist/storage-ui.js +4 -4
- package/dist/store-baseline.d.ts +1 -1
- package/dist/store-baseline.js +1 -1
- package/dist/store.d.ts +440 -15
- package/dist/store.js +1072 -52
- package/dist/subagent-desk.js +1 -1
- package/dist/summary.js +3 -0
- package/dist/task-source.d.ts +58 -0
- package/dist/task-source.js +93 -0
- package/dist/team-leads.js +1 -1
- package/dist/teams-chat.js +4 -1
- package/dist/teardown-git.d.ts +22 -0
- package/dist/teardown-git.js +136 -2
- package/dist/telegram-lead.d.ts +3 -0
- package/dist/telegram-lead.js +44 -7
- package/dist/telegram.d.ts +11 -2
- package/dist/telegram.js +51 -17
- package/dist/terminal-catalog.d.ts +11 -0
- package/dist/terminal-catalog.js +129 -0
- package/dist/text-limits.d.ts +2 -0
- package/dist/text-limits.js +2 -0
- package/dist/tool-broker.d.ts +14 -0
- package/dist/tool-broker.js +67 -2
- package/dist/toolroll-update-ui.js +2 -2
- package/dist/toolroll-update.js +13 -3
- package/dist/tools-ui.js +2 -2
- package/dist/unfenced-test-support.d.ts +2 -0
- package/dist/unfenced-test-support.js +11 -0
- package/dist/webhook-limits.d.ts +23 -0
- package/dist/webhook-limits.js +30 -0
- package/dist/webhook-readers.d.ts +56 -0
- package/dist/webhook-readers.js +138 -0
- package/dist/webhook-signing.d.ts +27 -0
- package/dist/webhook-signing.js +119 -0
- package/dist/work-index.d.ts +29 -0
- package/dist/work-index.js +16 -2
- package/dist/workspace-revision.js +3 -1
- package/dist/writes-mode.d.ts +9 -0
- package/dist/writes-mode.js +8 -0
- package/package.json +15 -2
package/dist/builder.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { legacyNetwork, repositoryEcosystems } from "./egress.js";
|
|
2
|
+
import { checkoutGit } from "./teardown-git.js";
|
|
3
|
+
import { isAcpProvider } from "./acp-agents.js";
|
|
1
4
|
import { OBSERVATION_MAILBOX, observationBrief, parseObservationCases, collectObservations } from "./observations.js";
|
|
2
5
|
import { checkCommandFor, effectiveCheckLevel, recordRunCheckLevel } from "./check-levels.js";
|
|
3
6
|
import { queueBatchCheck } from "./batch-checks.js";
|
|
@@ -39,15 +42,15 @@ import { PREPARED_EVIDENCE_FILE, PREPARED_EVIDENCE_GIT, preparedScreenshotMatche
|
|
|
39
42
|
* watchdog and a high runaway-turn breaker still stop a pathological loop;
|
|
40
43
|
* repair remains narrowly time-bounded because its job is narrowly scoped.
|
|
41
44
|
*/
|
|
42
|
-
import { existsSync, unlinkSync, writeFileSync } from "node:fs";
|
|
45
|
+
import { existsSync, realpathSync, unlinkSync, writeFileSync } from "node:fs";
|
|
43
46
|
import { homedir } from "node:os";
|
|
44
|
-
import { join } from "node:path";
|
|
47
|
+
import { join, resolve } from "node:path";
|
|
45
48
|
import { run, runClaudeStreamJsonl, runOwnerTag, streamsInput } from "./exec.js";
|
|
46
49
|
import { stopRequestedFor, stopWords, underStopWatch } from "./task-control.js";
|
|
47
50
|
import { witnessedRunner } from "./process-custody.js";
|
|
48
51
|
import { runWithIsolatedDatabase } from "./child-database.js";
|
|
49
52
|
import { recordWorktreeProcess, saveWorkPatch } from "./worktree.js";
|
|
50
|
-
import { approvalOf, digestOf, profileDigestOf, routeParityProblem } from "./scope.js";
|
|
53
|
+
import { approvalOf, digestOf, idleClock, isAcpProfile, profileDigestOf, routeParityProblem, watchdogsOf } from "./scope.js";
|
|
51
54
|
import { legOf, routeDigestOf, routeFromJson } from "./phase-routing.js";
|
|
52
55
|
import { execFileSync } from "node:child_process";
|
|
53
56
|
import { currentClaim, heartbeat, SYNC_MAX_AGE_MS, finalize } from "./claim.js";
|
|
@@ -56,9 +59,10 @@ import { heartbeat as runnerHeartbeat } from "./runner.js";
|
|
|
56
59
|
import { MARKER as LEASE_MARKER } from "./worktree.js";
|
|
57
60
|
import { parseDecision, parseHandoff, repairPrompt, HEADLESS_RULE, HANDOFF_CONCLUSION_CAP, HANDOFF_ITEM_CAP, HANDOFF_LIST_CAP, HANDOFF_PAYLOAD_CAP } from "./decision.js";
|
|
58
61
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
59
|
-
import { invokeAgent } from "./invoke.js";
|
|
62
|
+
import { fencedCommands, invokeAgent } from "./invoke.js";
|
|
60
63
|
import { TELEGRAM_TOKEN_ENVS } from "./names.js";
|
|
61
64
|
import { OPENROUTER_ENV_KEY, auditOf, ALL_CREDENTIAL_ENV } from "./provider.js";
|
|
65
|
+
import { liveLogContext } from "./live-detail.js";
|
|
62
66
|
import { openLiveLog } from "./live.js";
|
|
63
67
|
import { fence } from "./brief-fence.js";
|
|
64
68
|
import { closeSteerMailbox, openSteerMailbox, STEER_HANDLED } from "./steer-mailbox.js";
|
|
@@ -199,12 +203,17 @@ function repairModelOf(profile, request) {
|
|
|
199
203
|
function profileWantsSkip(profile) {
|
|
200
204
|
return ((profile.provider === "claude" && profile.permissionArgv === "bypassPermissions") ||
|
|
201
205
|
((profile.provider === "codex" || profile.provider === "openrouter") && profile.sandboxMode === "danger-full-access") ||
|
|
202
|
-
(profile.provider === "gemini" && profile.approvalArgv === "yolo")
|
|
206
|
+
(profile.provider === "gemini" && profile.approvalArgv === "yolo") ||
|
|
207
|
+
// An ACP agent's only posture is full access inside the fence.
|
|
208
|
+
isAcpProfile(profile));
|
|
203
209
|
}
|
|
204
210
|
const PROVIDER_VERSIONS = new Map();
|
|
205
211
|
/** Provenance only (finding 20): a best-effort `--version` probe, cached
|
|
206
212
|
* per process, null on any failure — never authority, never a refusal. */
|
|
207
213
|
function providerVersionOf(provider) {
|
|
214
|
+
// An ACP agent is never run outside the gateway, not even for --version: its version is what its check recorded.
|
|
215
|
+
if (isAcpProvider(provider))
|
|
216
|
+
return null;
|
|
208
217
|
if (PROVIDER_VERSIONS.has(provider))
|
|
209
218
|
return PROVIDER_VERSIONS.get(provider) ?? null;
|
|
210
219
|
let version = null;
|
|
@@ -221,6 +230,51 @@ function providerVersionOf(provider) {
|
|
|
221
230
|
PROVIDER_VERSIONS.set(provider, version);
|
|
222
231
|
return version;
|
|
223
232
|
}
|
|
233
|
+
/** A build's network (egress.ts): the one its approval sealed, or — sealed before network policies existed — the
|
|
234
|
+
* narrowed legacy one (provider hosts and the repository's registries, nothing added since). */
|
|
235
|
+
export function launchNetworkOf(store, taskRef, profile) {
|
|
236
|
+
if (profile.network !== undefined)
|
|
237
|
+
return { policy: profile.network };
|
|
238
|
+
const repo = store.refForId(taskRef)?.repo ?? null;
|
|
239
|
+
return { policy: legacyNetwork(profile.provider, repo === null ? [] : repositoryEcosystems(repo)) };
|
|
240
|
+
}
|
|
241
|
+
/** Asking a checkout which branch it is on: reads no file a build wrote and runs nothing. */
|
|
242
|
+
const BRANCH_QUERIES = [
|
|
243
|
+
["--no-optional-locks", "rev-parse", "--abbrev-ref", "HEAD"], ["--no-optional-locks", "symbolic-ref", "--short", "-q", "HEAD"],
|
|
244
|
+
];
|
|
245
|
+
/**
|
|
246
|
+
* The plane's git as a build runs it: hardened (teardown-git.ts checkoutGit) for every call, failing closed, but one —
|
|
247
|
+
* asking the project's own main checkout which branch it is on (its config is the operator's, and the query runs
|
|
248
|
+
* nothing). An injected runner (`request.git`: tests only; production always runs git itself) is used as given.
|
|
249
|
+
*/
|
|
250
|
+
function buildCheckoutGit(given, worktree, mainCheckout = null) {
|
|
251
|
+
if (given !== run)
|
|
252
|
+
return given;
|
|
253
|
+
const hardened = checkoutGit(given);
|
|
254
|
+
const real = (path) => { try {
|
|
255
|
+
return realpathSync(resolve(path));
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
} };
|
|
260
|
+
const trusted = mainCheckout === null ? null : real(mainCheckout);
|
|
261
|
+
const own = real(worktree);
|
|
262
|
+
return (file, args, options) => {
|
|
263
|
+
const at = options?.cwd === undefined ? null : real(options.cwd);
|
|
264
|
+
const query = BRANCH_QUERIES.some(one => one.length === args.length && one.every((word, index) => args[index] === word));
|
|
265
|
+
return trusted !== null && at === trusted && at !== own && query ? given(file, args, options) : hardened(file, args, options);
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/** A run's setup and check commands, in its build's fence, writing where the approval this build runs under sealed
|
|
269
|
+
* (never the scope as it may since have been rewritten; invoke.ts fencedCommands). */
|
|
270
|
+
function commandRunner(store, runId, profile, inner) {
|
|
271
|
+
return fencedCommands(store, runId, launchWritesOf(profile), inner);
|
|
272
|
+
}
|
|
273
|
+
/** Where a build may write (writes-mode.ts): what its approval sealed, or — sealed before write allowlists — anywhere
|
|
274
|
+
* its fence allows, as it was approved. */
|
|
275
|
+
export function launchWritesOf(profile) {
|
|
276
|
+
return profile.writes ?? "anywhere";
|
|
277
|
+
}
|
|
224
278
|
export function proveApprovedProfile(scope, given) {
|
|
225
279
|
// The raw terms first (raw authority repair): a scope whose stored terms
|
|
226
280
|
// do not read back exactly proves nothing — not the filtered reading.
|
|
@@ -293,7 +347,7 @@ export function proveApprovedProfile(scope, given) {
|
|
|
293
347
|
if (given.timeoutMs !== undefined && given.timeoutMs !== snapshot.timeoutSeconds * 1000) {
|
|
294
348
|
return {
|
|
295
349
|
ok: false,
|
|
296
|
-
message: `approved with a ${snapshot.timeoutSeconds}s ${snapshot
|
|
350
|
+
message: `approved with a ${snapshot.timeoutSeconds}s ${idleClock(snapshot) ? "no-progress window" : "clock"}, asked for ${Math.round(given.timeoutMs / 1000)}s — re-approve to change it (stale-approval)`,
|
|
297
351
|
};
|
|
298
352
|
}
|
|
299
353
|
return {
|
|
@@ -315,7 +369,9 @@ export function proveApprovedProfile(scope, given) {
|
|
|
315
369
|
* that forgot one is exactly the caller this is protecting against.
|
|
316
370
|
*/
|
|
317
371
|
export async function build(store, request) {
|
|
318
|
-
const { taskId, taskRef, runner, worktree, branch, now, permissionMode = "auto", skipPermissions = false, provider = "claude", model, maxTurns = DEFAULT_MAX_TURNS, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS, agent, git = run, } = request;
|
|
372
|
+
const { taskId, taskRef, runner, worktree, branch, now, permissionMode = "auto", skipPermissions = false, provider = "claude", model, maxTurns = DEFAULT_MAX_TURNS, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS, agent, git: givenGit = run, } = request;
|
|
373
|
+
// The plane's own git on this build's checkout runs hardened, and never where the checkout's config names a command.
|
|
374
|
+
const git = buildCheckoutGit(givenGit, worktree, store.getWorktree(worktree)?.repo ?? null);
|
|
319
375
|
const scope = store.getScope(taskId);
|
|
320
376
|
const approval = approvalOf(scope);
|
|
321
377
|
if (!approval.approved) {
|
|
@@ -609,7 +665,7 @@ export async function build(store, request) {
|
|
|
609
665
|
// Setup runs under the stop watch (v52), owned by this run: an
|
|
610
666
|
// operator's stop ends the setup's process group and the attempt
|
|
611
667
|
// settles as interrupted below, never as a setup failure.
|
|
612
|
-
const made = await underStopWatch(store, request.runId, () => runWithIsolatedDatabase(witnessedRunner(store, request.runId, request.clock ?? (() => now), runSetup), shell.file, shell.args, {
|
|
668
|
+
const made = await underStopWatch(store, request.runId, () => runWithIsolatedDatabase(witnessedRunner(store, request.runId, request.clock ?? (() => now), commandRunner(store, request.runId, effective.profile, runSetup)), shell.file, shell.args, {
|
|
613
669
|
cwd: worktree,
|
|
614
670
|
timeoutMs: setupWanted.timeoutMs,
|
|
615
671
|
processGroup: true,
|
|
@@ -1123,7 +1179,7 @@ export async function build(store, request) {
|
|
|
1123
1179
|
maxTurns: effective.maxTurns ?? maxTurns,
|
|
1124
1180
|
finished: () => handoffFiles.some(name => existsSync(join(worktree, name))),
|
|
1125
1181
|
// A paused build can wait as long as the idle limit allows (live-input.ts idleLimit); a wall-clock profile has none.
|
|
1126
|
-
onOpen: () => store.markLiveInputOpened(request.runId, clock(), effective.profile
|
|
1182
|
+
onOpen: () => store.markLiveInputOpened(request.runId, clock(), idleClock(effective.profile) ? effective.timeoutMs : null),
|
|
1127
1183
|
onClose: () => store.markLiveInputClosed(request.runId, clock()),
|
|
1128
1184
|
onPaused: () => store.markRunPaused(request.runId, clock()),
|
|
1129
1185
|
});
|
|
@@ -1153,7 +1209,7 @@ export async function build(store, request) {
|
|
|
1153
1209
|
// Every streaming transport emits events now (peek); a file that cannot
|
|
1154
1210
|
// open is a null, and a null never costs a build.
|
|
1155
1211
|
// What the agent did last rides the same stream into one row (live tasks).
|
|
1156
|
-
const liveLog = withAgentTurns(withRunActivity(openLiveLog(root, request.runId), store, request.runId, clock), (state, at) => { if (attemptKey !== null)
|
|
1212
|
+
const liveLog = withAgentTurns(withRunActivity(openLiveLog(root, request.runId, liveLogContext(store, taskRef, worktree)), store, request.runId, clock), (state, at) => { if (attemptKey !== null)
|
|
1157
1213
|
recordAgentTurn(store, { run: request.runId, attemptKey, state, at }); }, clock, (open, at) => { if (attemptKey !== null)
|
|
1158
1214
|
noteOpenTool(store, request.runId, attemptKey, open, at); });
|
|
1159
1215
|
// The retry base (steering fix for run 1465's proof): the SAME pinned
|
|
@@ -1291,10 +1347,10 @@ export async function build(store, request) {
|
|
|
1291
1347
|
...(liveSession === null ? {} : { liveInput: liveSession }),
|
|
1292
1348
|
// New approvals bind a no-progress watchdog, not a deadline. Legacy
|
|
1293
1349
|
// snapshots carry no timeoutKind and retain their wall-clock terms.
|
|
1294
|
-
...(effective.profile.
|
|
1295
|
-
? { idleTimeoutMs: effective.timeoutMs }
|
|
1296
|
-
: { timeoutMs: effective.timeoutMs }),
|
|
1350
|
+
...watchdogsOf(effective.profile, effective.timeoutMs),
|
|
1297
1351
|
omitEnv: AGENT_ENV_DENYLIST,
|
|
1352
|
+
network: launchNetworkOf(store, request.taskRef, effective.profile),
|
|
1353
|
+
writes: launchWritesOf(effective.profile),
|
|
1298
1354
|
...(agent === undefined ? {} : { runner: agent }),
|
|
1299
1355
|
onSpawn: (pid) => { spawned = true; request.onProviderSpawn?.(pid); },
|
|
1300
1356
|
onStreamEvent: (event) => liveLog.observe(event),
|
|
@@ -1490,7 +1546,7 @@ export async function settleProviderOutcome(captured, result) {
|
|
|
1490
1546
|
return {
|
|
1491
1547
|
ok: false,
|
|
1492
1548
|
reason: "timeout",
|
|
1493
|
-
message: effective.profile
|
|
1549
|
+
message: idleClock(effective.profile)
|
|
1494
1550
|
? `the builder made no observable progress for ${Math.round(timeoutMs / 60_000)} minutes and was stopped — whatever it wrote is still in ${worktree}`
|
|
1495
1551
|
: `the builder ran past ${Math.round(timeoutMs / 60_000)} minutes and was stopped — whatever it wrote is still in ${worktree}`,
|
|
1496
1552
|
};
|
|
@@ -1759,7 +1815,7 @@ export async function settleProviderOutcome(captured, result) {
|
|
|
1759
1815
|
};
|
|
1760
1816
|
if (!eligible())
|
|
1761
1817
|
throw Error("The observation source or execution authority changed.");
|
|
1762
|
-
const execute = (file, args, options) => underStopWatch(store, request.runId, () => runWithIsolatedDatabase(witnessedRunner(store, request.runId, clock, request.verify ?? run), file, args, {
|
|
1818
|
+
const execute = (file, args, options) => underStopWatch(store, request.runId, () => runWithIsolatedDatabase(witnessedRunner(store, request.runId, clock, commandRunner(store, request.runId, captured.effective.profile, request.verify ?? run)), file, args, {
|
|
1763
1819
|
...options, processGroup: true, owner: runOwnerTag(store, request.runId), beforeSpawn: eligible,
|
|
1764
1820
|
onSpawn: pid => request.onProviderSpawn?.(pid), envAllowlist: SETUP_ENV_ALLOWLIST, omitEnv: SETUP_ENV_DENYLIST,
|
|
1765
1821
|
}));
|
|
@@ -2219,7 +2275,7 @@ async function settleProof(captured, statArtifactId, sealedHead) {
|
|
|
2219
2275
|
const runVerification = async (label) => {
|
|
2220
2276
|
const streamed = { stdout: false, stderr: false };
|
|
2221
2277
|
// The check runs under the stop watch (v52), owned by this run.
|
|
2222
|
-
const result = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, verifyRunner), verifyShell.file, verifyShell.args, {
|
|
2278
|
+
const result = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, commandRunner(store, runId, captured.effective.profile, verifyRunner)), verifyShell.file, verifyShell.args, {
|
|
2223
2279
|
cwd: worktree,
|
|
2224
2280
|
timeoutMs: configured.timeoutMs,
|
|
2225
2281
|
processGroup: true,
|
|
@@ -2261,7 +2317,7 @@ async function settleProof(captured, statArtifactId, sealedHead) {
|
|
|
2261
2317
|
detachShared(worktree, depsRoot);
|
|
2262
2318
|
const label = "Own install · approved project setup (package.json or lockfile changed)";
|
|
2263
2319
|
const setupShell = approvedCommandShell(live.command);
|
|
2264
|
-
const installed = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, request.setup ?? run), setupShell.file, setupShell.args, {
|
|
2320
|
+
const installed = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, commandRunner(store, runId, captured.effective.profile, request.setup ?? run)), setupShell.file, setupShell.args, {
|
|
2265
2321
|
cwd: worktree,
|
|
2266
2322
|
timeoutMs: live.timeoutMs,
|
|
2267
2323
|
processGroup: true,
|
|
@@ -2280,7 +2336,7 @@ async function settleProof(captured, statArtifactId, sealedHead) {
|
|
|
2280
2336
|
checkLog.push(attemptLog(label, live.command, installed));
|
|
2281
2337
|
if (installed.notFound || installed.timedOut || installed.code !== 0)
|
|
2282
2338
|
return "own-install-failed";
|
|
2283
|
-
return await sealedTreeState(request.git ?? run) === "clean" ? null : "setup-changed-files";
|
|
2339
|
+
return await sealedTreeState(buildCheckoutGit(request.git ?? run, worktree)) === "clean" ? null : "setup-changed-files";
|
|
2284
2340
|
};
|
|
2285
2341
|
const ownInstall = await ownInstallIfChanged();
|
|
2286
2342
|
const first = ownInstall === null ? await runVerification("Project check · attempt 1") : null;
|
|
@@ -2324,7 +2380,7 @@ async function settleProof(captured, statArtifactId, sealedHead) {
|
|
|
2324
2380
|
verifyCommand = { configured: true, ran: false, attemptFailed: true, failure: "custody-lost" };
|
|
2325
2381
|
}
|
|
2326
2382
|
else {
|
|
2327
|
-
const gitRunner = request.git ?? run;
|
|
2383
|
+
const gitRunner = buildCheckoutGit(request.git ?? run, worktree);
|
|
2328
2384
|
const beforeSetup = await sealedTreeState(gitRunner);
|
|
2329
2385
|
if (beforeSetup === "head-moved") {
|
|
2330
2386
|
verifyCommand = { configured: true, ran: false, attemptFailed: true, failure: "checkout-moved" };
|
|
@@ -2351,7 +2407,7 @@ async function settleProof(captured, statArtifactId, sealedHead) {
|
|
|
2351
2407
|
else {
|
|
2352
2408
|
const setupRunner = request.setup ?? run;
|
|
2353
2409
|
const setupShell = approvedCommandShell(liveBeforeSetup.command);
|
|
2354
|
-
const restored = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, setupRunner), setupShell.file, setupShell.args, {
|
|
2410
|
+
const restored = await underStopWatch(store, runId, () => runWithIsolatedDatabase(witnessedRunner(store, runId, now, commandRunner(store, runId, captured.effective.profile, setupRunner)), setupShell.file, setupShell.args, {
|
|
2355
2411
|
cwd: worktree,
|
|
2356
2412
|
timeoutMs: liveBeforeSetup.timeoutMs,
|
|
2357
2413
|
processGroup: true,
|
|
@@ -2614,7 +2670,8 @@ async function resumeUnhandedWork(captured, sessionId) {
|
|
|
2614
2670
|
if (request.leaseId !== undefined && !heartbeat(store, request.leaseId, clock()).ok) {
|
|
2615
2671
|
return { ok: false, reason: "fenced", message: `${taskId}'s lease did not survive the resumed turn — the work is still in ${worktree}` };
|
|
2616
2672
|
}
|
|
2617
|
-
|
|
2673
|
+
// An ACP agent's turn bills as its own model's declaration on this runner, never as the attempt it continues.
|
|
2674
|
+
if (store.budgetGate(clock())({ ...store.budgetSubject(request.taskRef), agents: [isAcpProvider(provider) ? store.agentFor(provider, model ?? null, request.runner) : { provider, billing: store.runBilling(request.runId) ?? store.agentsFor([provider])[0].billing }] }).over !== null)
|
|
2618
2675
|
break;
|
|
2619
2676
|
if (store.agentPolicyRefusal(provider, model ?? null) !== null)
|
|
2620
2677
|
break;
|
|
@@ -2634,8 +2691,10 @@ async function resumeUnhandedWork(captured, sessionId) {
|
|
|
2634
2691
|
...(request.maxBudgetUsd === undefined ? {} : { maxBudgetUsd: request.maxBudgetUsd }),
|
|
2635
2692
|
}, {
|
|
2636
2693
|
cwd: worktree,
|
|
2637
|
-
...(effective.profile
|
|
2694
|
+
...watchdogsOf(effective.profile, effective.timeoutMs),
|
|
2638
2695
|
omitEnv: AGENT_ENV_DENYLIST,
|
|
2696
|
+
network: launchNetworkOf(store, request.taskRef, effective.profile),
|
|
2697
|
+
writes: launchWritesOf(effective.profile),
|
|
2639
2698
|
...(agent === undefined ? {} : { runner: agent }),
|
|
2640
2699
|
...(request.onProviderSpawn === undefined ? {} : { onSpawn: request.onProviderSpawn }),
|
|
2641
2700
|
clock,
|
|
@@ -2811,7 +2870,8 @@ async function ingestPark(args) {
|
|
|
2811
2870
|
}
|
|
2812
2871
|
// v105: a repair turn spends too — a budget used up since the build began stops further turns (billed to a key).
|
|
2813
2872
|
// It bills as the attempt it mends did.
|
|
2814
|
-
|
|
2873
|
+
// An ACP repair bills as its own model's declaration on this runner, never as the attempt it mends.
|
|
2874
|
+
if (store.budgetGate(clock())({ ...store.budgetSubject(request.taskRef), agents: [isAcpProvider(repairProvider) ? store.agentFor(repairProvider, repairModel ?? null, request.runner) : { provider: repairProvider, billing: store.runBilling(request.runId) ?? store.agentsFor([repairProvider])[0].billing }] }).over !== null)
|
|
2815
2875
|
break;
|
|
2816
2876
|
// Sprint 8: nor does a repair run on a provider or model the organisation policy doesn't allow.
|
|
2817
2877
|
if (store.agentPolicyRefusal(repairProvider, repairModel ?? null) !== null)
|
|
@@ -2845,8 +2905,11 @@ async function ingestPark(args) {
|
|
|
2845
2905
|
: {}),
|
|
2846
2906
|
}, {
|
|
2847
2907
|
cwd: worktree,
|
|
2848
|
-
|
|
2908
|
+
...(args.profile !== undefined && isAcpProfile(args.profile)
|
|
2909
|
+
? watchdogsOf(args.profile, args.profile.repairTimeoutSeconds * 1000, true)
|
|
2910
|
+
: { timeoutMs: args.profile !== undefined ? args.profile.repairTimeoutSeconds * 1000 : REPAIR_TIMEOUT_MS }),
|
|
2849
2911
|
omitEnv: AGENT_ENV_DENYLIST,
|
|
2912
|
+
...(args.profile === undefined ? {} : { network: launchNetworkOf(store, request.taskRef, args.profile), writes: launchWritesOf(args.profile) }),
|
|
2850
2913
|
...(agent === undefined ? {} : { runner: agent }),
|
|
2851
2914
|
...(request.onProviderSpawn === undefined ? {} : { onSpawn: request.onProviderSpawn }),
|
|
2852
2915
|
clock,
|
package/dist/chat-actions.d.ts
CHANGED
|
@@ -68,6 +68,16 @@ export declare const CHAT_ACTIONS: {
|
|
|
68
68
|
readonly protected: false;
|
|
69
69
|
readonly password: false;
|
|
70
70
|
};
|
|
71
|
+
readonly sweep_file: {
|
|
72
|
+
readonly label: "Start sweep";
|
|
73
|
+
readonly protected: true;
|
|
74
|
+
readonly password: true;
|
|
75
|
+
};
|
|
76
|
+
readonly sweep_cancel_rest: {
|
|
77
|
+
readonly label: "Cancel the rest";
|
|
78
|
+
readonly protected: false;
|
|
79
|
+
readonly password: false;
|
|
80
|
+
};
|
|
71
81
|
readonly flow_edit: {
|
|
72
82
|
readonly label: "Save flow";
|
|
73
83
|
readonly protected: false;
|
|
@@ -256,7 +266,7 @@ export declare function sharedActionReviewPath(id: number): string;
|
|
|
256
266
|
export declare function mintSharedActionReview(store: Store, who: VerifiedApprover, id: number, root: string, now: Date): {
|
|
257
267
|
payload: {
|
|
258
268
|
version: 1;
|
|
259
|
-
operation: "decision_record" | "decision_retire" | "flow_card_add" | "flow_card_approve" | "flow_card_assign" | "flow_card_cancel" | "flow_card_choose" | "flow_card_comment" | "flow_card_move" | "flow_card_send_back" | "flow_card_watch" | "flow_create" | "flow_edit" | "flow_script_save" | "flow_starter" | "flow_trigger_add" | "flow_trigger_pause" | "flow_trigger_remove" | "flow_trigger_resume" | "kit_setup" | "knowledge_instructions" | "knowledge_remove" | "knowledge_restore" | "knowledge_save" | "lead_about_you" | "result_accept" | "scope_approve" | "skill_disable" | "skill_enable" | "skill_import" | "skill_restore" | "skill_test" | "subagent_answer" | "subagent_ask" | "subagent_create" | "subagent_memory" | "subagent_note" | "subagent_routine" | "subagent_soul" | "subagent_state" | "subagent_tools" | "subagent_undo" | "task_cancel" | "task_resume" | "tool_add" | "tool_remove";
|
|
269
|
+
operation: "decision_record" | "decision_retire" | "flow_card_add" | "flow_card_approve" | "flow_card_assign" | "flow_card_cancel" | "flow_card_choose" | "flow_card_comment" | "flow_card_move" | "flow_card_send_back" | "flow_card_watch" | "flow_create" | "flow_edit" | "flow_script_save" | "flow_starter" | "flow_trigger_add" | "flow_trigger_pause" | "flow_trigger_remove" | "flow_trigger_resume" | "kit_setup" | "knowledge_instructions" | "knowledge_remove" | "knowledge_restore" | "knowledge_save" | "lead_about_you" | "result_accept" | "scope_approve" | "skill_disable" | "skill_enable" | "skill_import" | "skill_restore" | "skill_test" | "subagent_answer" | "subagent_ask" | "subagent_create" | "subagent_memory" | "subagent_note" | "subagent_routine" | "subagent_soul" | "subagent_state" | "subagent_tools" | "subagent_undo" | "sweep_cancel_rest" | "sweep_file" | "task_cancel" | "task_resume" | "tool_add" | "tool_remove";
|
|
260
270
|
request: {
|
|
261
271
|
[x: string]: unknown;
|
|
262
272
|
};
|
|
@@ -286,6 +296,8 @@ export declare function executeSharedAction(store: Store, who: VerifiedApprover,
|
|
|
286
296
|
said: string;
|
|
287
297
|
taskId: string | null;
|
|
288
298
|
href?: string;
|
|
299
|
+
awaiting?: true;
|
|
300
|
+
already?: true;
|
|
289
301
|
} | {
|
|
290
302
|
ok: false;
|
|
291
303
|
reason: "needs-confirm" | "stale" | "refused";
|