toolroll 0.9.67 → 0.9.69
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 +70 -0
- package/dist/acp-client.js +1 -3
- package/dist/agent-board.d.ts +0 -1
- package/dist/agent-board.js +0 -1
- package/dist/agent-fence.d.ts +58 -0
- package/dist/agent-fence.js +214 -19
- package/dist/agentconfig.d.ts +1 -1
- package/dist/agentconfig.js +6 -2
- package/dist/batch-checks.js +14 -26
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +31 -29
- package/dist/builder.d.ts +9 -0
- package/dist/builder.js +30 -27
- package/dist/canonical-json.d.ts +14 -0
- package/dist/canonical-json.js +36 -0
- package/dist/chat-actions.js +1 -2
- package/dist/chat-admission.d.ts +19 -0
- package/dist/chat-admission.js +22 -0
- package/dist/chat-channel.js +1 -1
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-follow.d.ts +17 -0
- package/dist/chat-follow.js +32 -0
- package/dist/chat-messages.js +0 -1
- package/dist/chat-settings-page.d.ts +23 -0
- package/dist/chat-settings-page.js +41 -0
- package/dist/check-access.d.ts +54 -0
- package/dist/check-access.js +80 -0
- package/dist/claim.js +3 -6
- package/dist/claude-print.d.ts +12 -0
- package/dist/claude-print.js +34 -0
- package/dist/cli-http.d.ts +0 -7
- package/dist/cli-http.js +0 -21
- package/dist/cli.d.ts +3 -10
- package/dist/cli.js +15 -24
- package/dist/coding-provider.js +2 -1
- package/dist/coding-workspace.js +1 -1
- package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
- package/dist/connect-cli.js +331 -0
- package/dist/containment.d.ts +0 -2
- package/dist/containment.js +2 -6
- package/dist/contracts/chat-actions.d.ts +0 -1
- package/dist/contracts/chat-content.d.ts +0 -4
- package/dist/contracts/chat-content.js +0 -2
- package/dist/contracts/chat-tables.d.ts +0 -1
- package/dist/contracts/cli.d.ts +0 -62
- package/dist/contracts/cli.js +0 -4
- package/dist/contracts/coding-workspace.js +1 -1
- package/dist/contracts/console-api.d.ts +1 -0
- package/dist/contracts/console-api.js +1 -0
- package/dist/contracts/contract.js +1 -1
- package/dist/contracts/flow-card.d.ts +0 -1
- package/dist/contracts/flow-propose.d.ts +0 -1
- package/dist/contracts/flow-send.js +1 -1
- package/dist/contracts/gateway-tools.d.ts +0 -1
- package/dist/contracts/integration-metadata.js +1 -1
- package/dist/contracts/lead-tools.d.ts +0 -1
- package/dist/contracts/memory-pass.d.ts +0 -1
- package/dist/contracts/memory-pass.js +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/project-knowledge.js +1 -1
- package/dist/contracts/project-skills.d.ts +0 -1
- package/dist/contracts/proof.js +1 -1
- package/dist/contracts/recipes.js +1 -1
- package/dist/contracts/scope.js +1 -1
- package/dist/contracts/scout-report.js +1 -1
- package/dist/contracts/teams-callback.d.ts +0 -1
- package/dist/converse.d.ts +0 -6
- package/dist/converse.js +0 -19
- package/dist/daemon.js +3 -2
- package/dist/decision.d.ts +1 -3
- package/dist/deprecations.d.ts +12 -4
- package/dist/deprecations.js +27 -4
- package/dist/desktop-update-recovery.js +1 -1
- package/dist/desktop-update.js +3 -2
- package/dist/discord-chat.js +4 -15
- package/dist/discord-settings.d.ts +2 -6
- package/dist/discord-settings.js +10 -38
- package/dist/discord.js +12 -23
- package/dist/evidence.d.ts +0 -1
- package/dist/evidence.js +0 -3
- package/dist/exec.d.ts +0 -9
- package/dist/exec.js +3 -81
- package/dist/flow-actions.js +0 -3
- package/dist/flow-draft.d.ts +1 -3
- package/dist/flow-draft.js +15 -28
- package/dist/flow-scripts.d.ts +1 -8
- package/dist/flow-scripts.js +0 -13
- package/dist/flow-send.js +1 -1
- package/dist/flow-share.d.ts +0 -2
- package/dist/flow-share.js +1 -6
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +0 -1
- package/dist/flow-triggers.js +1 -2
- package/dist/flow-unattended.js +1 -12
- package/dist/flows.js +1 -1
- package/dist/health-cli.d.ts +2 -2
- package/dist/health-cli.js +1 -1
- package/dist/invoke.d.ts +39 -5
- package/dist/invoke.js +181 -24
- package/dist/is-record.d.ts +2 -0
- package/dist/is-record.js +2 -0
- package/dist/lead-doors.d.ts +1 -5
- package/dist/lead-doors.js +0 -4
- package/dist/lead-tools.js +3 -6
- package/dist/live-detail.d.ts +0 -1
- package/dist/live-detail.js +0 -6
- package/dist/live-terminal.js +2 -1
- package/dist/live.d.ts +0 -1
- package/dist/live.js +1 -2
- package/dist/mcp-core.js +0 -2
- package/dist/memory-pass.js +1 -1
- package/dist/model-catalog.js +1 -1
- package/dist/modes.js +1 -12
- package/dist/operate.d.ts +4 -0
- package/dist/operate.js +456 -750
- package/dist/password-bearer.d.ts +0 -2
- package/dist/password-bearer.js +0 -4
- package/dist/peek-cli.js +2 -1
- package/dist/peek.d.ts +2 -26
- package/dist/peek.js +2 -168
- package/dist/phase-routing.d.ts +0 -4
- package/dist/phase-routing.js +2 -21
- package/dist/planner-source.d.ts +2 -1
- package/dist/planner-source.js +2 -12
- package/dist/planner.js +2 -14
- package/dist/process-tree.d.ts +0 -2
- package/dist/process-tree.js +0 -10
- package/dist/project-delete-ui.d.ts +16 -0
- package/dist/project-delete-ui.js +60 -1
- package/dist/project-delete.d.ts +0 -2
- package/dist/project-delete.js +1 -3
- package/dist/project-learning.d.ts +0 -14
- package/dist/project-skills.d.ts +0 -1
- package/dist/project-skills.js +0 -14
- package/dist/project-tools.js +2 -10
- package/dist/provider.d.ts +0 -17
- package/dist/provider.js +0 -26
- package/dist/pulls.d.ts +0 -2
- package/dist/pulls.js +0 -9
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +15 -5
- package/dist/remote-exec.d.ts +3 -2
- package/dist/remote-exec.js +3 -2
- package/dist/repos.d.ts +0 -5
- package/dist/repos.js +2 -10
- package/dist/repository-context.d.ts +0 -2
- package/dist/repository-context.js +0 -4
- package/dist/restart-certification.d.ts +0 -2
- package/dist/restart-certification.js +1 -5
- package/dist/result-follow-ups.d.ts +1 -4
- package/dist/result-follow-ups.js +11 -21
- package/dist/result-review.d.ts +0 -2
- package/dist/result-review.js +0 -2
- package/dist/retention.d.ts +0 -1
- package/dist/retention.js +0 -1
- package/dist/review-context.d.ts +0 -1
- package/dist/review-context.js +1 -12
- package/dist/reviewer.d.ts +0 -16
- package/dist/reviewer.js +0 -18
- package/dist/run-closeout.js +2 -1
- package/dist/scope.d.ts +9 -0
- package/dist/scope.js +13 -18
- package/dist/scout-browser.js +2 -1
- package/dist/serve.js +11 -2
- package/dist/server/console.css +5 -133
- package/dist/server/flows.js +2 -2
- package/dist/server/http.d.ts +4 -0
- package/dist/server/http.js +5 -0
- package/dist/server/pages.js +2 -2
- package/dist/server/people-tokens.js +3 -4
- package/dist/server/remote.js +1 -6
- package/dist/server/render-chat.d.ts +9 -2
- package/dist/server/render-chat.js +53 -7
- package/dist/server/render-results.d.ts +3 -6
- package/dist/server/render-results.js +4 -9
- package/dist/server/render-tasks.js +6 -6
- package/dist/server/route-table.d.ts +0 -4
- package/dist/server/route-table.js +1 -6
- package/dist/server/settings.js +60 -23
- package/dist/server/task-views.js +1 -1
- package/dist/server/tasks.js +5 -3
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills.d.ts +0 -6
- package/dist/skills.js +0 -8
- package/dist/slack-chat.d.ts +1 -7
- package/dist/slack-chat.js +5 -18
- package/dist/slack-settings.d.ts +2 -6
- package/dist/slack-settings.js +10 -38
- package/dist/slack.js +12 -23
- package/dist/sleep.d.ts +2 -0
- package/dist/sleep.js +2 -0
- package/dist/store.d.ts +29 -75
- package/dist/store.js +89 -180
- package/dist/structured-output.d.ts +0 -1
- package/dist/structured-output.js +0 -1
- package/dist/subagent-work.d.ts +0 -2
- package/dist/subagent-work.js +0 -2
- package/dist/subagents.d.ts +1 -3
- package/dist/subagents.js +20 -33
- package/dist/subscription-chat.d.ts +1 -3
- package/dist/subscription-chat.js +2 -3
- package/dist/surface.js +2 -1
- package/dist/task-sizing.d.ts +1 -4
- package/dist/task-sizing.js +3 -10
- package/dist/teams-chat.js +4 -11
- package/dist/teams.js +12 -19
- package/dist/telegram-lead.js +2 -2
- package/dist/telegram.js +1 -1
- package/dist/token-notices.d.ts +0 -11
- package/dist/token-notices.js +1 -5
- package/dist/tool-secret-store.d.ts +0 -3
- package/dist/tool-secret-store.js +2 -11
- package/dist/toolroll-update.d.ts +0 -2
- package/dist/toolroll-update.js +2 -2
- package/dist/verification-evidence.d.ts +0 -1
- package/dist/verification-evidence.js +0 -1
- package/dist/webhooks.d.ts +0 -1
- package/dist/webhooks.js +0 -1
- package/dist/workspace-ui.d.ts +0 -8
- package/dist/workspace-ui.js +1 -6
- package/package.json +1 -1
- package/dist/contracts/native-census.d.ts +0 -42
- package/dist/contracts/native-census.js +0 -36
- package/dist/process-recovery-anchor.d.ts +0 -75
- package/dist/process-recovery-anchor.js +0 -188
- package/dist/process-recovery-coalition.d.ts +0 -25
- package/dist/process-recovery-coalition.js +0 -105
- package/dist/process-recovery-eligibility.d.ts +0 -179
- package/dist/process-recovery-eligibility.js +0 -174
- package/dist/process-recovery-native.d.ts +0 -161
- package/dist/process-recovery-native.js +0 -595
- package/dist/process-recovery-provenance.d.ts +0 -163
- package/dist/process-recovery-provenance.js +0 -292
- package/dist/process-recovery-services.d.ts +0 -56
- package/dist/process-recovery-services.js +0 -191
- package/dist/process-recovery-settlement.d.ts +0 -32
- package/dist/process-recovery-settlement.js +0 -133
- package/dist/process-recovery.d.ts +0 -41
- package/dist/process-recovery.js +0 -91
- package/dist/session-brief.d.ts +0 -8
- package/dist/session-brief.js +0 -24
- package/dist/session-cli.d.ts +0 -42
- package/dist/session-cli.js +0 -271
- package/dist/session-contract.d.ts +0 -183
- package/dist/session-contract.js +0 -122
- package/dist/session-remote.d.ts +0 -19
- package/dist/session-remote.js +0 -86
- package/dist/session-service.d.ts +0 -22
- package/dist/session-service.js +0 -157
- package/dist/team-cli.js +0 -692
package/dist/invoke.d.ts
CHANGED
|
@@ -21,12 +21,11 @@ import { type VersionProbe } from "./attest.js";
|
|
|
21
21
|
import type { Store } from "./store.js";
|
|
22
22
|
import type { RunOptions } from "./exec.js";
|
|
23
23
|
import type { Runner } from "./worktree.js";
|
|
24
|
+
import { type NetworkFence, type SignInGrants } from "./agent-fence.js";
|
|
25
|
+
import { type CheckAccess } from "./check-access.js";
|
|
24
26
|
import { type WritesMode } from "./agent-fence.js";
|
|
25
27
|
import { type NetworkProfile } from "./egress.js";
|
|
26
28
|
export type { ProviderRunner } from "./provider.js";
|
|
27
|
-
/** The claude binary name — kept for the legacy quota rows and tests that
|
|
28
|
-
* describe history; new code carries a resolved AgentSpec instead. */
|
|
29
|
-
export declare const PROVIDER_BINARY = "claude";
|
|
30
29
|
export type ProviderUsage = {
|
|
31
30
|
tokensIn: number | null;
|
|
32
31
|
tokensOut: number | null;
|
|
@@ -120,11 +119,46 @@ export declare function invokeAgent(store: Store, runId: number, spec: AgentSpec
|
|
|
120
119
|
* Their network stays as it was. A machine without an OS fence runs them as before; a fence that can't be prepared
|
|
121
120
|
* (a checkout whose binding no longer proves) runs nothing.
|
|
122
121
|
*/
|
|
123
|
-
export declare function fencedCommands(store: Store, runId: number, writes: WritesMode, inner: Runner, available?: () => boolean): Runner;
|
|
122
|
+
export declare function fencedCommands(store: Store, runId: number, writes: WritesMode, inner: Runner, available?: () => boolean, access?: CheckAccess, network?: NetworkProfile): Runner;
|
|
124
123
|
/**
|
|
125
124
|
* A project's checks run in a checkout of a result's commit made for them (result-follow-ups.ts, batch-checks.ts), in
|
|
126
125
|
* the same fence as a build's commands: Toolroll's state, credentials, other projects and runs denied; under the
|
|
127
126
|
* project's writes setting, only that checkout, its Git data, its own temp folder, the project's caches and its check
|
|
128
127
|
* database writable. Where nothing can confine them, they run only when an instance operator allowed unconfined agents.
|
|
129
128
|
*/
|
|
130
|
-
export declare function fencedCheckoutCommands(store: Store, repo: string, checkout: string, inner: Runner, available?: () => boolean): Runner;
|
|
129
|
+
export declare function fencedCheckoutCommands(store: Store, repo: string, checkout: string, inner: Runner, available?: () => boolean, access?: CheckAccess, network?: NetworkProfile): Runner;
|
|
130
|
+
/**
|
|
131
|
+
* A `sign-ins` check's launch (check-access.ts): its exact sign-in files and its own transcript folder
|
|
132
|
+
* (agent-fence.ts signInGrants), Codex's config and sign-in copied into a home of the launch's own (private, gone with
|
|
133
|
+
* the launch; ~/.codex itself stays fenced), gh pointed at its own folder, and the network the check runs under:
|
|
134
|
+
* open, or its allowlist through a proxy of its own (on Linux, carried in by a bridge). Nothing about it is started
|
|
135
|
+
* unless all of it is.
|
|
136
|
+
*/
|
|
137
|
+
export declare function signInsLaunch(store: Store, own: string, temp: string, checkout: string, policy: NetworkProfile, gitPaths: readonly string[], platform?: NodeJS.Platform): Promise<{
|
|
138
|
+
grants: SignInGrants;
|
|
139
|
+
network: NetworkFence;
|
|
140
|
+
env: Record<string, string>;
|
|
141
|
+
close(): Promise<void>;
|
|
142
|
+
} | {
|
|
143
|
+
problem: string;
|
|
144
|
+
}>;
|
|
145
|
+
/** How a check at `access` actually runs here: unsandboxed where no OS fence exists (and an operator allowed that), else
|
|
146
|
+
* as asked. Recorded on every check's receipt, so a check that ran without a sandbox is never shown as sandboxed. */
|
|
147
|
+
export declare function actualCheckAccess(store: Store, access: CheckAccess): CheckAccess;
|
|
148
|
+
/**
|
|
149
|
+
* A check of saved results, in their own checkout (batch-checks.ts, result-follow-ups.ts), worked out right before each
|
|
150
|
+
* command: never wider than any of those results' own checks ran, nor than the project allows now; under sign-ins, the
|
|
151
|
+
* narrowest of their sealed check networks and the project's current one. A result with no sealed network runs it
|
|
152
|
+
* sandboxed.
|
|
153
|
+
*/
|
|
154
|
+
export declare function checkoutLaunchOf(store: Store, repo: string, runIds: readonly number[], platform?: NodeJS.Platform): {
|
|
155
|
+
access: CheckAccess;
|
|
156
|
+
network: NetworkProfile | undefined;
|
|
157
|
+
};
|
|
158
|
+
/** The widest level a check's commands actually ran at (what its receipt says). */
|
|
159
|
+
export declare const widestRan: (levels: readonly CheckAccess[]) => CheckAccess;
|
|
160
|
+
/** A check log's line for how its commands ran, when wider than sandboxed (shown with the log). */
|
|
161
|
+
export declare const ranAtLine: (level: CheckAccess) => string | null;
|
|
162
|
+
/** A saved result's check command runner (batch-checks.ts, result-follow-ups.ts): its level and network worked out right
|
|
163
|
+
* now (checkoutLaunchOf), and how it actually runs told to `ran`. */
|
|
164
|
+
export declare function checkoutRunner(store: Store, repo: string, checkout: string, inner: Runner, runIds: readonly number[], ran: (level: CheckAccess) => void, platform?: NodeJS.Platform): Runner;
|
package/dist/invoke.js
CHANGED
|
@@ -29,19 +29,17 @@ import { witnessedRunner } from "./process-custody.js";
|
|
|
29
29
|
import { underStopWatch } from "./task-control.js";
|
|
30
30
|
import { childDatabaseEnv, isolatedChildDatabase, removeChildDatabase as removeAgentDatabase } from "./child-database.js";
|
|
31
31
|
import { RunSignInError, noToolsArgs, prepareRunTools } from "./project-tools.js";
|
|
32
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
32
|
+
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
33
33
|
import { homedir, tmpdir } from "node:os";
|
|
34
34
|
import { dirname, join } from "node:path";
|
|
35
35
|
import { poolRootOf } from "./worktree.js";
|
|
36
|
-
import { BRIDGE_DIR } from "./agent-fence.js";
|
|
36
|
+
import { BRIDGE_DIR, checkLaunchRoot, readGrantedFile, SIGN_IN_COPIES_DIR, signInCopiesRoot, signInGrants } from "./agent-fence.js";
|
|
37
|
+
import { CHECK_ACCESS_DEFAULT, checkAccessHere, narrowestAccess, narrowestNetwork, signInsAvailable } from "./check-access.js";
|
|
37
38
|
import { agentFence, buildCacheEnv, buildCacheFolder, grantFolder, writeAllowlist, WRITES_DEFAULT, CheckoutBindingError, trustedWorktreeBinding, checkoutGitEnv, HARDENED_GIT_ARGS, codexFenceArgv, fenceGrants, fencedGitEnv, linuxFenceAvailable, linuxFenced, macosFenceAvailable, macosFenced, NO_GRANTS, runFolders, taskBoundary } from "./agent-fence.js";
|
|
38
|
-
import { proxyEnv, providerOnlyNetwork, startEgressProxy } from "./egress.js";
|
|
39
|
+
import { proxyEnv, providerOnlyNetwork, repositoryEcosystems, resolveNetwork, startEgressProxy } from "./egress.js";
|
|
39
40
|
import { bridgeFits, startEgressBridge } from "./egress-bridge.js";
|
|
40
41
|
import { claudeConfigDir, claudeDefaults, codexDefaults, codexHomeDir, isolatedCodexHome } from "./provider-home.js";
|
|
41
42
|
import { billingOf, claudeBillingFrom, seenBilling } from "./spend.js";
|
|
42
|
-
/** The claude binary name — kept for the legacy quota rows and tests that
|
|
43
|
-
* describe history; new code carries a resolved AgentSpec instead. */
|
|
44
|
-
export const PROVIDER_BINARY = "claude";
|
|
45
43
|
/** "Within seconds": how soon a silent failed run must end for its stderr to
|
|
46
44
|
* be read for the sign-in signal. */
|
|
47
45
|
const AUTH_EARLY_EXIT_MS = 30_000;
|
|
@@ -64,6 +62,11 @@ function claudeSettingsAuthProblem(configDir) {
|
|
|
64
62
|
catch (error) {
|
|
65
63
|
if (error.code === "ENOENT")
|
|
66
64
|
return null;
|
|
65
|
+
// A sandbox around the plane (a project check's fence, say) may hide the file while the CLI still signs in from its
|
|
66
|
+
// keychain. Isolated builds never load it, and a login that needed it fails within seconds and is reported as one.
|
|
67
|
+
const code = error.code;
|
|
68
|
+
if (code === "EPERM" || code === "EACCES")
|
|
69
|
+
return null;
|
|
67
70
|
return "Can't read your Claude settings.json to check sign-in. Restore access to that file and try again. Isolated builds do not load it.";
|
|
68
71
|
}
|
|
69
72
|
let settings;
|
|
@@ -967,21 +970,27 @@ function runFence(store, runId, provider, keyHome, ownTools, writes = WRITES_DEF
|
|
|
967
970
|
* Their network stays as it was. A machine without an OS fence runs them as before; a fence that can't be prepared
|
|
968
971
|
* (a checkout whose binding no longer proves) runs nothing.
|
|
969
972
|
*/
|
|
970
|
-
export function fencedCommands(store, runId, writes, inner, available = () => macosFenceAvailable() || linuxFenceAvailable()) {
|
|
973
|
+
export function fencedCommands(store, runId, writes, inner, available = () => macosFenceAvailable() || linuxFenceAvailable(), access = CHECK_ACCESS_DEFAULT, network) {
|
|
971
974
|
// An injected runner (tests) starts no real command, as an injected agent starts no real agent (invokeAgent).
|
|
972
975
|
if (inner !== runCommand)
|
|
973
976
|
return inner;
|
|
974
977
|
return async (file, args, options) => {
|
|
975
|
-
// As a build itself: where nothing can confine them, they run only when an instance operator allowed unconfined agents
|
|
978
|
+
// As a build itself: where nothing can confine them, they run only when an instance operator allowed unconfined agents
|
|
979
|
+
// (and the run says so: its checks ran without a sandbox, whatever was sealed).
|
|
976
980
|
if (!available()) {
|
|
977
|
-
if (store.unfencedAgentsAllowed())
|
|
981
|
+
if (store.unfencedAgentsAllowed()) {
|
|
982
|
+
store.stampRunCheckAccess(runId, "unsandboxed");
|
|
978
983
|
return inner(file, args, options);
|
|
984
|
+
}
|
|
979
985
|
return { code: 1, stdout: "", stderr: "This machine can't confine the build's commands (no macOS sandbox, no working bubblewrap), so they didn't run. Install bubblewrap, or an instance operator allows unconfined agents with `toolroll config unconfined-agents allow`.\n", timedOut: false, notFound: false };
|
|
980
986
|
}
|
|
981
|
-
const own = realpathSync(mkdtempSync(join(
|
|
987
|
+
const own = realpathSync(mkdtempSync(join(checkLaunchRoot(), "so-cmd-")));
|
|
982
988
|
try {
|
|
983
989
|
const temp = join(own, "tmp");
|
|
984
990
|
mkdirSync(temp, { mode: 0o700 });
|
|
991
|
+
// Not sandboxed (check-access.ts): the project's checks are trusted by the whole instance, as before 0.9.66.
|
|
992
|
+
if (access === "unsandboxed")
|
|
993
|
+
return await inner(file, args, { ...options, env: { ...(options?.env ?? {}), TMPDIR: temp, TMP: temp, TEMP: temp } });
|
|
985
994
|
const fenced = runFence(store, runId, "command", undefined, own, writes);
|
|
986
995
|
if (fenced.problem !== undefined)
|
|
987
996
|
return { code: 1, stdout: "", stderr: `${fenced.problem}\n`, timedOut: false, notFound: false };
|
|
@@ -991,12 +1000,24 @@ export function fencedCommands(store, runId, writes, inner, available = () => ma
|
|
|
991
1000
|
const database = options?.env?.["TOOLROLL_DB"];
|
|
992
1001
|
const checkData = database === undefined || fenced.grants.writes === undefined ? null : grantFolder(dirname(database), false);
|
|
993
1002
|
const grants = checkData === null ? fenced.grants : { ...fenced.grants, writes: { ...fenced.grants.writes, subpaths: [...fenced.grants.writes.subpaths, checkData] } };
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1003
|
+
const checkout = store.getRun(runId)?.worktree ?? null;
|
|
1004
|
+
const signIns = access !== "sign-ins" ? null : checkout === null ? { problem: "The check's checkout is unknown, so its sign-ins can't be granted." }
|
|
1005
|
+
: network === undefined ? { problem: "A check with sign-ins has no network sealed for it, so nothing ran." }
|
|
1006
|
+
: await signInsLaunch(store, own, temp, checkout, network, fenced.gitPaths ?? []);
|
|
1007
|
+
if (signIns !== null && "problem" in signIns)
|
|
1008
|
+
return { code: 1, stdout: "", stderr: `${signIns.problem}\n`, timedOut: false, notFound: false };
|
|
1009
|
+
try {
|
|
1010
|
+
return await inner(file, args, {
|
|
1011
|
+
...options,
|
|
1012
|
+
fence: fenced.fence,
|
|
1013
|
+
fenceGrants: signIns === null ? grants : { ...grants, signIns: signIns.grants, network: signIns.network },
|
|
1014
|
+
env: { ...(options?.env ?? {}), TMPDIR: temp, TMP: temp, TEMP: temp, ...(fenced.cache === undefined || fenced.grants.writes === undefined ? {} : buildCacheEnv(fenced.cache)), ...(signIns?.env ?? {}) },
|
|
1015
|
+
...(signIns === null ? {} : { omitEnv: [...(options?.omitEnv ?? []), ...SIGN_INS_OMITTED_ENV] }),
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
finally {
|
|
1019
|
+
await signIns?.close();
|
|
1020
|
+
}
|
|
1000
1021
|
}
|
|
1001
1022
|
finally {
|
|
1002
1023
|
rmSync(own, { recursive: true, force: true });
|
|
@@ -1009,7 +1030,7 @@ export function fencedCommands(store, runId, writes, inner, available = () => ma
|
|
|
1009
1030
|
* project's writes setting, only that checkout, its Git data, its own temp folder, the project's caches and its check
|
|
1010
1031
|
* database writable. Where nothing can confine them, they run only when an instance operator allowed unconfined agents.
|
|
1011
1032
|
*/
|
|
1012
|
-
export function fencedCheckoutCommands(store, repo, checkout, inner, available = () => macosFenceAvailable() || linuxFenceAvailable()) {
|
|
1033
|
+
export function fencedCheckoutCommands(store, repo, checkout, inner, available = () => macosFenceAvailable() || linuxFenceAvailable(), access = CHECK_ACCESS_DEFAULT, network) {
|
|
1013
1034
|
if (inner !== runCommand)
|
|
1014
1035
|
return inner;
|
|
1015
1036
|
return async (file, args, options) => {
|
|
@@ -1021,10 +1042,13 @@ export function fencedCheckoutCommands(store, repo, checkout, inner, available =
|
|
|
1021
1042
|
const databaseFile = store.databaseFile();
|
|
1022
1043
|
if (databaseFile === null)
|
|
1023
1044
|
return inner(file, args, options);
|
|
1024
|
-
const own = realpathSync(mkdtempSync(join(
|
|
1045
|
+
const own = realpathSync(mkdtempSync(join(checkLaunchRoot(), "so-cmd-")));
|
|
1025
1046
|
try {
|
|
1026
1047
|
const temp = join(own, "tmp");
|
|
1027
1048
|
mkdirSync(temp, { mode: 0o700 });
|
|
1049
|
+
// Not sandboxed (check-access.ts): the project's checks are trusted by the whole instance, as before 0.9.66.
|
|
1050
|
+
if (access === "unsandboxed")
|
|
1051
|
+
return await inner(file, args, { ...options, env: { ...(options?.env ?? {}), TMPDIR: temp, TMP: temp, TEMP: temp } });
|
|
1028
1052
|
let binding;
|
|
1029
1053
|
try {
|
|
1030
1054
|
binding = trustedWorktreeBinding(repo, checkout);
|
|
@@ -1042,12 +1066,24 @@ export function fencedCheckoutCommands(store, repo, checkout, inner, available =
|
|
|
1042
1066
|
const base = fenceGrants({ databaseFile, worktree: checkout, boundary, runFolders: folders, linked: linkedFor(store, checkout), binding, poolRoots });
|
|
1043
1067
|
const grants = allowed === null ? base
|
|
1044
1068
|
: { ...base, readOnly: [...new Set([...base.readOnly, ...allowed.readOnly])].sort(), writes: { ...allowed.writes, subpaths: [...allowed.writes.subpaths, ...(checkData === null ? [] : [checkData])] } };
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1069
|
+
// With sign-ins, under the network its caller proved for it (the narrowest of its results' sealed check networks and
|
|
1070
|
+
// the project's current one): none given, nothing runs.
|
|
1071
|
+
const signIns = access !== "sign-ins" ? null : network === undefined ? { problem: "A check with sign-ins has no network sealed for it, so nothing ran." }
|
|
1072
|
+
: await signInsLaunch(store, own, temp, checkout, network, [binding.gitdir, join(binding.main, ".git")]);
|
|
1073
|
+
if (signIns !== null && "problem" in signIns)
|
|
1074
|
+
return { code: 1, stdout: "", stderr: `${signIns.problem}\n`, timedOut: false, notFound: false };
|
|
1075
|
+
try {
|
|
1076
|
+
return await inner(file, args, {
|
|
1077
|
+
...options,
|
|
1078
|
+
fence: agentFence({ databaseFile, worktree: checkout, boundary, binding, runFolders: folders, extra: allowed?.deny ?? [] }),
|
|
1079
|
+
fenceGrants: signIns === null ? grants : { ...grants, signIns: signIns.grants, network: signIns.network },
|
|
1080
|
+
env: { ...(options?.env ?? {}), TMPDIR: temp, TMP: temp, TEMP: temp, ...(allowed === null ? {} : buildCacheEnv(cache)), ...(signIns?.env ?? {}) },
|
|
1081
|
+
...(signIns === null ? {} : { omitEnv: [...(options?.omitEnv ?? []), ...SIGN_INS_OMITTED_ENV] }),
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
finally {
|
|
1085
|
+
await signIns?.close();
|
|
1086
|
+
}
|
|
1051
1087
|
}
|
|
1052
1088
|
finally {
|
|
1053
1089
|
rmSync(own, { recursive: true, force: true });
|
|
@@ -1116,3 +1152,124 @@ async function codexLoginBilling(binary, omitEnv) {
|
|
|
1116
1152
|
function plainLines(stdout) {
|
|
1117
1153
|
return stdout.split("\n").filter(line => !line.trimStart().startsWith("{")).join("\n");
|
|
1118
1154
|
}
|
|
1155
|
+
/** What a `sign-ins` check never inherits: a caller's choice of Claude's config folder (Claude's keychain sign-in is
|
|
1156
|
+
* keyed to its default one; check-access.ts). gh's and Codex's are set to the granted ones instead. */
|
|
1157
|
+
const SIGN_INS_OMITTED_ENV = ["CLAUDE_CONFIG_DIR"];
|
|
1158
|
+
/**
|
|
1159
|
+
* A `sign-ins` check's launch (check-access.ts): its exact sign-in files and its own transcript folder
|
|
1160
|
+
* (agent-fence.ts signInGrants), Codex's config and sign-in copied into a home of the launch's own (private, gone with
|
|
1161
|
+
* the launch; ~/.codex itself stays fenced), gh pointed at its own folder, and the network the check runs under:
|
|
1162
|
+
* open, or its allowlist through a proxy of its own (on Linux, carried in by a bridge). Nothing about it is started
|
|
1163
|
+
* unless all of it is.
|
|
1164
|
+
*/
|
|
1165
|
+
export async function signInsLaunch(store, own, temp, checkout, policy, gitPaths, platform = process.platform) {
|
|
1166
|
+
// The belt (check-access.ts signInsAvailable, off for now): no sign-in file is read, copied or granted, whatever level
|
|
1167
|
+
// reached this far. Its callers already run such a check sandboxed; anything else that asks runs nothing.
|
|
1168
|
+
if (!signInsAvailable(platform))
|
|
1169
|
+
return { problem: "Sign-ins can't be shared with checks yet, so nothing ran." };
|
|
1170
|
+
const home = homedir();
|
|
1171
|
+
const grants = signInGrants(home, checkout);
|
|
1172
|
+
const cleanup = [];
|
|
1173
|
+
// Codex's files are copied, each read only as the real file it is (readGrantedFile: no link, here or above it).
|
|
1174
|
+
const codex = join(own, "codex");
|
|
1175
|
+
mkdirSync(codex, { mode: 0o700 });
|
|
1176
|
+
for (const name of ["config.toml", "auth.json"]) {
|
|
1177
|
+
const bytes = readGrantedFile(join(realpathSync(home), ".codex", name));
|
|
1178
|
+
if (bytes !== null)
|
|
1179
|
+
writeFileSync(join(codex, name), bytes, { mode: 0o600 });
|
|
1180
|
+
}
|
|
1181
|
+
// On Linux every granted file is bound from a copy of its own, made the same way (bubblewrap binds a source path, and
|
|
1182
|
+
// a link swapped in after validation must never be what it binds). A Mac's sandbox checks the real path itself.
|
|
1183
|
+
// Not reached for now: the belt above refuses until reading these files is race-free.
|
|
1184
|
+
if (process.platform === "linux") {
|
|
1185
|
+
const copies = {};
|
|
1186
|
+
// Under Toolroll's own state folder, which every fence denies whole (a launch's folder in a shared /tmp isn't masked
|
|
1187
|
+
// from a launch already running): bubblewrap binds from the original root, so only this check sees them.
|
|
1188
|
+
const database = store.databaseFile();
|
|
1189
|
+
if (database === null || database === "" || database === ":memory:")
|
|
1190
|
+
return { problem: "A check with sign-ins needs Toolroll's state folder, so nothing ran." };
|
|
1191
|
+
const state = dirname(realpathSync(database));
|
|
1192
|
+
try {
|
|
1193
|
+
mkdirSync(join(state, SIGN_IN_COPIES_DIR), { mode: 0o700 });
|
|
1194
|
+
}
|
|
1195
|
+
catch { /* there already: checked next */ }
|
|
1196
|
+
// Only the real, private folder Toolroll made (this user's, 0700, no link): never a link planted where it should be.
|
|
1197
|
+
const parent = signInCopiesRoot(state);
|
|
1198
|
+
if (parent === null)
|
|
1199
|
+
return { problem: "The sign-in copies folder isn't a private folder of Toolroll's, so nothing ran." };
|
|
1200
|
+
const folder = mkdtempSync(join(parent, `c-${process.pid}-`));
|
|
1201
|
+
cleanup.push(folder);
|
|
1202
|
+
grants.read.forEach((path, index) => {
|
|
1203
|
+
const bytes = readGrantedFile(path);
|
|
1204
|
+
if (bytes === null)
|
|
1205
|
+
return;
|
|
1206
|
+
const copy = join(folder, String(index));
|
|
1207
|
+
writeFileSync(copy, bytes, { mode: 0o600 });
|
|
1208
|
+
copies[path] = copy;
|
|
1209
|
+
});
|
|
1210
|
+
grants.read = grants.read.filter(path => copies[path] !== undefined);
|
|
1211
|
+
grants.copies = copies;
|
|
1212
|
+
}
|
|
1213
|
+
let egress = null;
|
|
1214
|
+
let bridge = null;
|
|
1215
|
+
const close = async () => { await egress?.close(); await bridge?.close(); for (const one of cleanup)
|
|
1216
|
+
rmSync(one, { recursive: true, force: true }); };
|
|
1217
|
+
try {
|
|
1218
|
+
const env = { CODEX_HOME: codex, GH_CONFIG_DIR: join(home, ".config", "gh"), XDG_CONFIG_HOME: join(home, ".config") };
|
|
1219
|
+
if (policy.mode === "open")
|
|
1220
|
+
return { grants, network: { mode: "open" }, env, close };
|
|
1221
|
+
// Exactly the project's network: the services the sign-ins are for are reached only if the operator allowed their
|
|
1222
|
+
// hosts (check-access.ts signInHostsMissing says which are missing; never added here).
|
|
1223
|
+
egress = await startEgressProxy({ hosts: policy.hosts });
|
|
1224
|
+
const network = { mode: "allowlist", proxyPort: egress.port, brokerPorts: [], loopback: policy.loopback, socketRoots: [temp, realpathSync(checkout)] };
|
|
1225
|
+
if (linuxFenceAvailable()) {
|
|
1226
|
+
const database = store.databaseFile();
|
|
1227
|
+
const fenced = database === null || database === "" || database === ":memory:" ? undefined : join(dirname(realpathSync(database)), BRIDGE_DIR);
|
|
1228
|
+
bridge = await startEgressBridge([egress.port], fenced !== undefined && bridgeFits(fenced) ? fenced : undefined);
|
|
1229
|
+
network.bridge = { folder: realpathSync(bridge.folder), forwarder: realpathSync(bridge.forwarder), node: process.execPath };
|
|
1230
|
+
// Its private /tmp gives back its checkout, its launch folder and its checkout's own Git data (as a build's does).
|
|
1231
|
+
network.keep = [realpathSync(checkout), own, ...gitPaths.filter(path => existsSync(path))];
|
|
1232
|
+
}
|
|
1233
|
+
return { grants, network, env: { ...env, ...proxyEnv(egress, policy.loopback) }, close };
|
|
1234
|
+
}
|
|
1235
|
+
catch (error) {
|
|
1236
|
+
await close();
|
|
1237
|
+
return { problem: `The check's network could not be set up, so nothing ran: ${error instanceof Error ? error.message : String(error)}` };
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
/** How a check at `access` actually runs here: unsandboxed where no OS fence exists (and an operator allowed that), else
|
|
1241
|
+
* as asked. Recorded on every check's receipt, so a check that ran without a sandbox is never shown as sandboxed. */
|
|
1242
|
+
export function actualCheckAccess(store, access) {
|
|
1243
|
+
return macosFenceAvailable() || linuxFenceAvailable() || !store.unfencedAgentsAllowed() ? access : "unsandboxed";
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* A check of saved results, in their own checkout (batch-checks.ts, result-follow-ups.ts), worked out right before each
|
|
1247
|
+
* command: never wider than any of those results' own checks ran, nor than the project allows now; under sign-ins, the
|
|
1248
|
+
* narrowest of their sealed check networks and the project's current one. A result with no sealed network runs it
|
|
1249
|
+
* sandboxed.
|
|
1250
|
+
*/
|
|
1251
|
+
export function checkoutLaunchOf(store, repo, runIds, platform = process.platform) {
|
|
1252
|
+
// As checks can get it: sign-ins (off for now; a stamp or setting from before, or another database) run sandboxed.
|
|
1253
|
+
const access = checkAccessHere(narrowestAccess([store.projectCheckAccess(repo), ...runIds.map(id => store.runCheckAccess(id))]), platform);
|
|
1254
|
+
if (access !== "sign-ins")
|
|
1255
|
+
return { access, network: undefined };
|
|
1256
|
+
const sealed = runIds.map(id => store.runCheckNetwork(id));
|
|
1257
|
+
if (sealed.length === 0 || sealed.some(one => one === null))
|
|
1258
|
+
return { access: CHECK_ACCESS_DEFAULT, network: undefined };
|
|
1259
|
+
const live = resolveNetwork("command", store.projectNetwork(repo), repositoryEcosystems(repo));
|
|
1260
|
+
return { access, network: sealed.reduce((low, one) => narrowestNetwork(low, one), live) };
|
|
1261
|
+
}
|
|
1262
|
+
/** The widest level a check's commands actually ran at (what its receipt says). */
|
|
1263
|
+
export const widestRan = (levels) => levels.includes("unsandboxed") ? "unsandboxed" : levels.includes("sign-ins") ? "sign-ins" : CHECK_ACCESS_DEFAULT;
|
|
1264
|
+
/** A check log's line for how its commands ran, when wider than sandboxed (shown with the log). */
|
|
1265
|
+
export const ranAtLine = (level) => level === "sandboxed" ? null
|
|
1266
|
+
: `=== Check access ===\n${level === "unsandboxed" ? "These commands ran without a sandbox." : "These commands ran sandboxed, with model and GitHub sign-ins."}`;
|
|
1267
|
+
/** A saved result's check command runner (batch-checks.ts, result-follow-ups.ts): its level and network worked out right
|
|
1268
|
+
* now (checkoutLaunchOf), and how it actually runs told to `ran`. */
|
|
1269
|
+
export function checkoutRunner(store, repo, checkout, inner, runIds, ran, platform = process.platform) {
|
|
1270
|
+
return (file, args, options) => {
|
|
1271
|
+
const launch = checkoutLaunchOf(store, repo, runIds, platform);
|
|
1272
|
+
ran(actualCheckAccess(store, launch.access));
|
|
1273
|
+
return fencedCheckoutCommands(store, repo, checkout, inner, undefined, launch.access, launch.network)(file, args, options);
|
|
1274
|
+
};
|
|
1275
|
+
}
|
package/dist/lead-doors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type SharedActionOptions } from './chat-actions.js';
|
|
2
|
-
import { type
|
|
2
|
+
import { type LeadProposal, type Store } from "./store.js";
|
|
3
3
|
import type { VerifiedApprover } from "./principal.js";
|
|
4
4
|
import { type TeamChatProviderResolver } from './team-chat-authorization.js';
|
|
5
5
|
export type ProposalKind = LeadProposal["kind"];
|
|
@@ -78,7 +78,3 @@ export declare function dismissLeadProposal(store: Store, who: VerifiedApprover,
|
|
|
78
78
|
*/
|
|
79
79
|
export declare function confirmCoordinatorProposal(store: Store, who: VerifiedApprover, proposalId: number, now: Date, options: DoorOptions): DoorOutcome;
|
|
80
80
|
export declare function dismissCoordinatorProposal(store: Store, who: VerifiedApprover, proposalId: number, now: Date): boolean;
|
|
81
|
-
/** Which door renders a coordinator proposal for this reader: the repo must be admitted. */
|
|
82
|
-
export declare function coordinatorProposalVisible(who: {
|
|
83
|
-
repos: readonly string[];
|
|
84
|
-
}, proposal: CoordinatorProposal): boolean;
|
package/dist/lead-doors.js
CHANGED
|
@@ -260,10 +260,6 @@ export function dismissCoordinatorProposal(store, who, proposalId, now) {
|
|
|
260
260
|
return store.casCoordinatorProposal(proposalId, "pending", "dismissed", who.name, null, now);
|
|
261
261
|
});
|
|
262
262
|
}
|
|
263
|
-
/** Which door renders a coordinator proposal for this reader: the repo must be admitted. */
|
|
264
|
-
export function coordinatorProposalVisible(who, proposal) {
|
|
265
|
-
return who.repos.includes(proposal.repo);
|
|
266
|
-
}
|
|
267
263
|
/**
|
|
268
264
|
* The shared executor: one kind, one payload, the operator's own act
|
|
269
265
|
* through the primitive that owns it. Module-private (v3 review, finding
|
package/dist/lead-tools.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { sweepLine, sweepTable } from "./lead-sweep.js";
|
|
2
|
-
import { TEXT_LIMITS } from "./text-limits.js";
|
|
3
2
|
import { connectionsOf, oneClickOf } from "./mcp-connect.js";
|
|
4
3
|
import { checkLevelFromWords, isCheckLevel } from "./check-levels.js";
|
|
5
4
|
import { policyParts } from "./policy.js";
|
|
@@ -39,9 +38,9 @@ import { CHAT_TASK_ACTIONS, chatTaskRun, chatTaskStamp, isChatTaskAction } from
|
|
|
39
38
|
import { Buffer } from "node:buffer";
|
|
40
39
|
import { LEAD_ASK_OTHER } from "./store.js";
|
|
41
40
|
import { hasDisguisedText, hasForbiddenControls } from "./decision.js";
|
|
42
|
-
import { readVerifiedArtifact,
|
|
41
|
+
import { readVerifiedArtifact, scanForSecrets } from "./evidence.js";
|
|
43
42
|
import { parseAcceptanceCriteria } from "./scope.js";
|
|
44
|
-
import { diagnoseTaskDispatch
|
|
43
|
+
import { diagnoseTaskDispatch } from "./dispatch.js";
|
|
45
44
|
import { agentChoicesFor, routeOfTask, INSTALLATION_SCOPE } from "./agentconfig.js";
|
|
46
45
|
import { isNewModel, modelWords, priceWords, runtimeStates, seenModels } from "./model-catalog.js";
|
|
47
46
|
import { agentsSummary, chosenWords, PHASES, postureWords, routeProblems, sameSpec, sizeSourceWords, sizeWords, specWords } from "./phase-routing.js";
|
|
@@ -55,7 +54,7 @@ import { planInChat } from "./chat-decide.js";
|
|
|
55
54
|
import { flowDecisionAt } from "./telegram-flow.js";
|
|
56
55
|
import { flowPersonOf } from "./flow-send.js";
|
|
57
56
|
import { flowInsights } from "./flow-insights.js";
|
|
58
|
-
import { describeTrigger,
|
|
57
|
+
import { describeTrigger, triggerConfigOf } from "./flow-triggers.js";
|
|
59
58
|
export const LEAD_MAX_PROPOSALS_PER_TURN = 5;
|
|
60
59
|
export { reportSummaryFor } from "./report-summary.js";
|
|
61
60
|
import { reportSummaryFor } from "./report-summary.js";
|
|
@@ -63,8 +62,6 @@ import { labelOf, nameOf, summaryOf, zonesOf } from "./subagent-admin.js";
|
|
|
63
62
|
import { SUBAGENT_TEMPLATES, withSection } from "./subagents.js";
|
|
64
63
|
import { callOutcome, callWords, defaultRule, ruleWords } from "./subagent-tools.js";
|
|
65
64
|
import { deskOf, routinesOf } from "./subagent-desk.js";
|
|
66
|
-
import { KITS } from "./kits.js";
|
|
67
|
-
import { STARTER_IDS } from "./flow-starters.js";
|
|
68
65
|
import { undoFor, weekOf, weekWords } from "./subagent-week.js";
|
|
69
66
|
import { PERSON_ID, personEntry, teamRoomOf } from "./lead-people.js";
|
|
70
67
|
import { aboutYouOf, checkAboutYouLine } from "./lead-about.js";
|
package/dist/live-detail.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ export type LiveDetailSetting = {
|
|
|
10
10
|
};
|
|
11
11
|
/** Whether this project's live conversations show commands. Unknown or absent is off. */
|
|
12
12
|
export declare function liveCommandsShown(store: Store, repo: string | null): boolean;
|
|
13
|
-
export declare function liveDetailSetting(store: Store, repo: string): LiveDetailSetting | null;
|
|
14
13
|
/** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
|
|
15
14
|
export declare function setLiveCommands(store: Store, change: {
|
|
16
15
|
repo: string;
|
package/dist/live-detail.js
CHANGED
|
@@ -26,12 +26,6 @@ export function liveCommandsShown(store, repo) {
|
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
export function liveDetailSetting(store, repo) {
|
|
30
|
-
const row = store.handle.prepare("SELECT repo, commands, updated_by, updated_at FROM live_detail_setting WHERE repo = ?").get(repo);
|
|
31
|
-
if (row === undefined)
|
|
32
|
-
return null;
|
|
33
|
-
return { repo: String(row["repo"]), commands: Number(row["commands"]) === 1, updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]) };
|
|
34
|
-
}
|
|
35
29
|
/** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
|
|
36
30
|
export function setLiveCommands(store, change, now) {
|
|
37
31
|
store.transact(() => {
|
package/dist/live-terminal.js
CHANGED
|
@@ -13,6 +13,7 @@ import { existsSync, mkdirSync, readlinkSync, realpathSync, statSync } from "nod
|
|
|
13
13
|
import { delimiter, isAbsolute, join } from "node:path";
|
|
14
14
|
import { codingEnvironment } from "./coding-provider.js";
|
|
15
15
|
import { teardownGit, refusal } from "./teardown-git.js";
|
|
16
|
+
import { sleep } from "./sleep.js";
|
|
16
17
|
export const TERMINAL_PROGRAMS = ["claude", "codex", "shell"];
|
|
17
18
|
/** At most this many running sessions per console, and this many kept at all (ended ones count until removed). */
|
|
18
19
|
export const MAX_LIVE_TERMINALS = 8;
|
|
@@ -404,7 +405,7 @@ export class TerminalHost {
|
|
|
404
405
|
}
|
|
405
406
|
async sweep(session) {
|
|
406
407
|
const grace = this.options.closeGraceMs ?? CLOSE_GRACE_MS;
|
|
407
|
-
const pause =
|
|
408
|
+
const pause = sleep;
|
|
408
409
|
const leaderGone = () => session.pty === null;
|
|
409
410
|
let readable = true;
|
|
410
411
|
const members = () => {
|
package/dist/live.d.ts
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import { type KeyState, type LiveActivityKind, type LiveRecord, type LiveRecorderOptions } from "./live-records.js";
|
|
17
17
|
export declare const LIVE_LINE_CAP: number;
|
|
18
18
|
export declare const LIVE_FILE_CAP: number;
|
|
19
|
-
export declare const LIVE_CAP_MARKER = "[the live view stopped at its size cap \u2014 the run record continues]";
|
|
20
19
|
export declare const LIVE_REDACTED_LINE = "[a credential-shaped line was redacted]";
|
|
21
20
|
/** Finalized runs keep their live file this long for the final drain. */
|
|
22
21
|
export declare const LIVE_RETAIN_MS: number;
|
package/dist/live.js
CHANGED
|
@@ -16,10 +16,9 @@
|
|
|
16
16
|
import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
import { scanForSecrets } from "./evidence.js";
|
|
19
|
-
import { createLiveRecorder,
|
|
19
|
+
import { createLiveRecorder, parseLiveRecords, redactLiveLines, projectLiveText, serializeLiveRecord } from "./live-records.js";
|
|
20
20
|
export const LIVE_LINE_CAP = 2 * 1024;
|
|
21
21
|
export const LIVE_FILE_CAP = 4 * 1024 * 1024;
|
|
22
|
-
export const LIVE_CAP_MARKER = LIVE_CAP_WORDS;
|
|
23
22
|
export const LIVE_REDACTED_LINE = "[a credential-shaped line was redacted]";
|
|
24
23
|
/** Finalized runs keep their live file this long for the final drain. */
|
|
25
24
|
export const LIVE_RETAIN_MS = 24 * 60 * 60 * 1000;
|
package/dist/mcp-core.js
CHANGED
|
@@ -9,13 +9,11 @@
|
|
|
9
9
|
* `tools/call` results with `isError: true`.
|
|
10
10
|
*/
|
|
11
11
|
import { dirname, join } from 'node:path';
|
|
12
|
-
import { statSync } from 'node:fs';
|
|
13
12
|
import { repositoryContextRead } from './repository-context.js';
|
|
14
13
|
import { ASSIGNMENT_TOOLS, assignmentForCoordinator } from "./assignment-adapters.js";
|
|
15
14
|
import { parseContract, toModelSchema } from "./contracts/contract.js";
|
|
16
15
|
import { GATEWAY_TOOL_INPUTS, GATEWAY_TOOL_OUTPUTS } from "./contracts/gateway-tools.js";
|
|
17
16
|
import { reportToolOutput } from "./contracts/lead-tools.js";
|
|
18
|
-
import { PACKAGE_VERSION } from "./version.js";
|
|
19
17
|
import { authenticateCoordinator, fileCoordinatorProposal, statusFor, listTasksFor, taskDetailFor, } from "./coordinator.js";
|
|
20
18
|
import { ISO_STAMP_RULE, decisionOver, decisionsOver, labelRepos, queueOver, recapOver } from "./lead-tools.js";
|
|
21
19
|
import { proposeAsCoordinator } from "./coordinator-proposals.js";
|
package/dist/memory-pass.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { createHash } from 'node:crypto';
|
|
14
14
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
15
15
|
import { homedir } from 'node:os';
|
|
16
|
-
import {
|
|
16
|
+
import { join } from 'node:path';
|
|
17
17
|
import { scanForSecrets, readVerifiedArtifact } from './evidence.js';
|
|
18
18
|
import { changeKnowledge, knowledgeView } from './project-knowledge.js';
|
|
19
19
|
import { listDecisions, recordDecision } from './project-memory.js';
|
package/dist/model-catalog.js
CHANGED
|
@@ -14,7 +14,7 @@ import { delimiter, join } from "node:path";
|
|
|
14
14
|
import { fetchOpenRouterModels } from "./openrouter-models.js";
|
|
15
15
|
import { codexModelSchema, codexModelsCacheSchema, npmLatestSchema } from "./contracts/model-catalog.js";
|
|
16
16
|
import { readCappedBody } from "./converse.js";
|
|
17
|
-
import {
|
|
17
|
+
import {} from "./provider.js";
|
|
18
18
|
import { activeUpdateWork } from "./desktop-update-gate.js";
|
|
19
19
|
export const MODELS_SCHEMA = `
|
|
20
20
|
CREATE TABLE IF NOT EXISTS model_seen (
|
package/dist/modes.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
17
|
import { CHAT_PROVIDERS, isChatProvider } from "./contracts/chat-tables.js";
|
|
18
|
+
import { canonicalJson } from "./canonical-json.js";
|
|
18
19
|
export const MODE_MAX_DAYS = 7;
|
|
19
20
|
/** The presets are STARTING POINTS the ceremony renders in full — the
|
|
20
21
|
* signature always covers the resolved terms, never a label. */
|
|
@@ -57,18 +58,6 @@ export function presetTerms(name, absoluteExpiry) {
|
|
|
57
58
|
absoluteExpiry,
|
|
58
59
|
};
|
|
59
60
|
}
|
|
60
|
-
function canonicalJson(value) {
|
|
61
|
-
if (Array.isArray(value))
|
|
62
|
-
return `[${value.map(canonicalJson).join(",")}]`;
|
|
63
|
-
if (value !== null && typeof value === "object") {
|
|
64
|
-
const entries = Object.entries(value)
|
|
65
|
-
.filter(([, v]) => v !== undefined)
|
|
66
|
-
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
67
|
-
.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`);
|
|
68
|
-
return `{${entries.join(",")}}`;
|
|
69
|
-
}
|
|
70
|
-
return JSON.stringify(value);
|
|
71
|
-
}
|
|
72
61
|
export function modeTermsJson(terms) {
|
|
73
62
|
return canonicalJson(terms);
|
|
74
63
|
}
|
package/dist/operate.d.ts
CHANGED
|
@@ -67,6 +67,10 @@ export type OperateOptions = {
|
|
|
67
67
|
flowStepIo?: Partial<StepIo>;
|
|
68
68
|
/** Injected by tests: how often a worker's flow passes run beside its builds (default FLOW_EVERY_MS). */
|
|
69
69
|
flowEveryMs?: number;
|
|
70
|
+
/** Injected by tests: the operating system this runs on (check access: no sign-ins on Linux yet). */
|
|
71
|
+
platform?: NodeJS.Platform;
|
|
72
|
+
/** Injected by tests: whether this machine has an OS fence for checks (macOS sandbox or bubblewrap). */
|
|
73
|
+
fenceAvailable?: () => boolean;
|
|
70
74
|
/** Injected by tests: how `flows import` fetches a flow file's address. */
|
|
71
75
|
flowFetch?: FetchLike;
|
|
72
76
|
/** Injected by tests: how `integrations` checks reach services (fetch, gh, sign-in checks, mail servers). */
|