glimmervoid 0.33.0 → 0.34.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/README.md +1 -1
- package/dist/bin/glimmervoid.js +5 -5
- package/dist/chunks/{adapters-CUBEhjOR.js → adapters-BY8slY95.js} +1 -1
- package/dist/chunks/{adapters-C9gI2MHS.js → adapters-_HwpLy0R.js} +1 -1
- package/dist/chunks/{config-Cneb8Ujj.js → config-DTwMFUjx.js} +13 -9
- package/dist/chunks/config-store-BmdXeUz1.js +2 -0
- package/dist/chunks/{config-store-DYsZJDux.js → config-store-CggAQLUB.js} +17 -9
- package/dist/chunks/{contracts-DWv6q8ir.js → contracts-D1wLN5iO.js} +1 -1
- package/dist/chunks/{knowledge-graph-cli-C7G-x5sY.js → knowledge-graph-cli-BBE3R9DJ.js} +1 -1
- package/dist/chunks/{main-J6y2RTri.js → main-Dh4udE7P.js} +175 -112
- package/dist/chunks/{pair-cli-BuyzST-U.js → pair-cli-Nnrd0il_.js} +2 -2
- package/dist/chunks/{remote-config-DJHVb-HU.js → remote-config-DKMQEIZh.js} +1 -1
- package/dist/chunks/{sandbox-deps-DuaNFq7n.js → sandbox-deps-C63o3mZs.js} +4 -4
- package/dist/client/assets/{index-CoFsm_PF.js → index-BiTwrj1H.js} +15 -15
- package/dist/client/index.html +1 -1
- package/dist/scripts/postinstall-path-check.js +1 -1
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/config-store-DaRS2c2d.js +0 -2
|
@@ -4,8 +4,8 @@ import { a as isPathInside, c as sanitizeWorktreeName, n as caseFoldedPathKey, o
|
|
|
4
4
|
import { a as packageRoot, n as cliPath, o as relayPath, r as clientDir, s as resolvePackageBin, t as bundled } from "./runtime-paths-BPoxENmK.js";
|
|
5
5
|
import { A as KILLABLE_STATES, C as SshSignRequest, E as isSamePromptQuestion, M as RESTARTABLE_STATES, N as STATES, T as TaskTitle, _ as SIGN_URL_ENV, a as AgentDispatchRequest, c as AgentTicketRequest, h as SESSION_DOC_BODY_CAP_BYTES, j as MERGEABLE_LIVE_STATES, k as toolDetailLine, l as ORCHESTRATOR_AGENT_VERBS, m as RefinedTaskTitle, n as AGENT_URL_ENV, r as ASK_USER_QUESTION_TOOL_NAME, v as SSH_SIGN_BODY_CAP_BYTES, w as TASK_TITLE_CONTROL_CHARACTERS } from "./session-C7rstCmA.js";
|
|
6
6
|
import { n as execFileAsync, o as spawn, r as execFileSync, t as execFile } from "./child-process-safe-DDELk9XC.js";
|
|
7
|
-
import { n as glimmervoidHomeDir } from "./config-path-core-DFt-TemS.js";
|
|
8
|
-
import { n as checkSandboxDependencies, t as allowSandboxedSpawn } from "./sandbox-deps-
|
|
7
|
+
import { n as glimmervoidHomeDir, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
|
|
8
|
+
import { n as checkSandboxDependencies, t as allowSandboxedSpawn } from "./sandbox-deps-C63o3mZs.js";
|
|
9
9
|
import { n as warnWhenGitIsTooOld } from "./git-version-CrLW4a6r.js";
|
|
10
10
|
import { t as HOOK_URL_ENV } from "./hook-relay-core-DA_bz2KA.js";
|
|
11
11
|
import { t as HOOK_VIA_SANDBOX_PROXY_ENV } from "./sandbox-proxy-core-hnQgKR0T.js";
|
|
@@ -19,13 +19,13 @@ import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.j
|
|
|
19
19
|
import { a as decideTicketAction, i as decideSpawnAllowance, l as isOrchestratorAgentVerb, n as REFUSAL_REASON, o as deriveChildSessionName, r as decideAgentRequest, s as describePushLanding, t as PUSH_UNAVAILABLE_REASON, u as parseAgentVerb } from "./agent-api-core-Ddg15j2j.js";
|
|
20
20
|
import { s as GLIMMERVOID_SECRET_KEYS } from "./grok-BYKnBgdr.js";
|
|
21
21
|
import { _ as isQueueAdmissionTimeout, a as jsonStateLoadError, c as loadedJsonValue, d as writeJsonAtomicSync, f as writeTextAtomic, g as createSpawnGate, h as createSerialQueue, i as createJsonStateWriter, m as createKeyedSerialQueue, n as appendJsonLines, o as loadJsonStateFile, p as writeTextAtomicSync, r as createJsonStateStore, s as loadJsonStateFileSync, t as appendJsonLine, u as writeJsonAtomic } from "./json-file-oEH9vt-0.js";
|
|
22
|
-
import { $ as TeamReviewCompareFiles, A as MyPrSearchResponse, At as CoherenceWorkInspect, B as PostingPlan, C as MyPrMergeMethod, Ct as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, D as MyPrMergeWhenReadyRequest, E as MyPrMergeStateResponse, F as CommitSha, G as ReviewDraft, H as QueuedReview, I as DECIDING_REVIEW_STATES, J as ReviewThreadId, K as ReviewFinding, L as FindingSeverity, M as MyPrThreadsResponse, N as MyPrsState, Ot as CoherenceTicketCreated, P as MyPrsStatus, R as GithubReviewDecision, Tt as CoherenceOrient, U as ReviewChecksState, V as PrDetail, W as ReviewComment, X as SearchedPr, Y as ReviewVerdict, Z as TeamReviewActionRequest, _ as WorkflowSearchNode, a as ConfigUpdate, at as TeamReviewThreadsRepository, b as MyPrAutoRebase, bt as USAGE_COST_MODES, c as TASK_TITLE_SOURCE_PRIORITY, ct as hasStandingViewerApproval, d as BRANCH_GC_CONTROL_NUMERIC_KEYS, dt as shortSha$1, et as TeamReviewResolveResponse, ft as GH_SEGMENT, g as WorkflowLabelName, h as WorkflowCommentBody, ht as repoParts, it as TeamReviewThreadResult, j as MyPrThreadNode, k as MyPrSearchNode, kt as CoherenceWorkCreated, l as configIssueMessage, lt as FULL_SHA_RE, m as DEFAULT_FACTORY_PROTECTED_PATHS, mt as REPO_SLUG_RE, nt as TeamReviewStatus, o as PersistedTaskTitle, ot as canApproveAfterComment, p as DEFAULT_FACTORY_CHECKS, pt as NODE_ID_RE, q as ReviewResult, r as BrowserConfig, rt as TeamReviewThreadCommentsResponse, s as RUNTIME_CONFIG_SCALAR_KEYS, st as decisionAsIfApprovalRequired, tt as TeamReviewStateEntry, u as BRANCH_GC_CONTROL_BOOLEAN_KEYS, ut as HEX_SHA_RE, v as WorkflowsSettings, w as MyPrMergeRequest, wt as USAGE_INTEGER_RANGES, x as MyPrKeepMergeableRequest, xt as USAGE_VENDOR_KEYS, y as WorkflowsState, yt as USAGE_BUDGET_KEYS, z as GithubReviewState } from "./config-
|
|
23
|
-
import { $ as sessionIdFromBranch, A as snapshotEvents, B as classifySessionExit, C as createIngestStore, D as resolveIngestConfig, E as publishEvent, F as adapterBucket, G as nodeMajorVersion, H as decideRemoteTelemetryState, I as buildAiGenerationEvents, J as stableConfigKey, K as parsePosthogReleaseId, L as buildBrowserExceptionProperties, M as FIRST_RUN_NOTICE, N as TELEMETRY_BATCH_URL, O as ringStats, P as TELEMETRY_FLAGS_URL, Q as planWorktreeGc, R as buildExceptionProperties, S as buildContextDigest, T as latestSeq, U as decideTelemetryConsent, V as decideIsDevInstall, W as exceptionFingerprint, X as matchedPrefix, Y as DEFAULT_BRANCH_GC_PREFIXES, Z as planBranchGc, _ as INGEST_SPEC, a as ensureProjectIds, b as DEFAULT_DIGEST_BUDGET_CHARS, d as assetForPlatform, et as usablePrefixes, f as decideRtkInstall, g as verifyDigest, h as isRtkBinaryName, i as createConfigStore, j as localDayKey, k as scrubText, m as installTargetPath, n as DEFAULT_CONFIG, o as generateProjectId, p as findEscapingArchiveMember, q as resolveProjectToken, s as glimmervoidHomeDir$1, t as ABORT_CONFIG_SAVE, tt as worktreeIntegrationTips, v as mergeSettingsBlock, w as enabledSourceNames, x as SOURCE_DEFAULTS, y as validateSettingsBlock, z as buildFactoryDecisionEvent } from "./config-store-
|
|
24
|
-
import { $ as FactoryHarnessVerdict, A as BenchmarkActionRequest, B as PrCheckoutCaseInput, C as IssueKey, D as IssuesStatus, E as IssuesState, F as BenchmarkStatus, G as TelemetryState, H as PendingCrashReport, I as BenchmarkSuite, J as FACTORY_ERROR_MAX_CHARS, K as FACTORY_DECISION_OUTPUT_MAX_BYTES, L as CommitComparison, M as BenchmarkId, N as BenchmarkJudgement, O as ChangeMap, P as BenchmarkRun, Q as FactoryHarnessStateLine, R as MergedPrListing, S as GithubIssueResponse, T as IssuesSearchResponse, U as TELEMETRY_EVENT_SCHEMAS, X as FactoryConsequences, Y as FACTORY_PROTECTED_PATH_FLOOR, Z as FactoryControlRequest, _ as PlanDecision, a as ClientMessage, at as FactoryWorkerEvent, b as planTitle, c as UpdateJournal, d as TraceRecord, et as FactoryLaneState, f as PLAN_BODY_CAP_BYTES, g as PLAN_TOOL_NAME, h as PLAN_RESULT_HOOK_EVENT, i as CONTROL_FRAME_MAX_BYTES, it as FactoryReviewerOutput, j as BenchmarkCase, k as changeMapFactId, l as MAX_RAW_LINE_CHARS, m as PLAN_HOOK_OUTPUT_MAX_CHARS, n as HookEnvelope, nt as FactoryQueueIntentRequest, o as DIFF_ANNOTATION_NOTE_MAX_CHARS, ot as isSingleFactoryPathSegment, p as PLAN_HOOK_EVENT, q as FactoryDecisionLogLine, r as parseDataClientMessage, rt as FactoryReviewVerdict, s as InstallFlavor, t as HTTP_URL_RE, tt as FactoryProjectState, u as TraceCheckpoint, v as PlanRevision, w as IssueUpdate, x as GithubIssuePullRequestsRepository, y as parseExitPlanModeHookPayload, z as MinedPrReviewData } from "./contracts-
|
|
25
|
-
import { a as describeAgentResolvability, c as isKnownAgentId, d as setCustomAgents, f as claudeCode, i as customAgentFingerprint, l as listAgentIds, n as cachedAgentResolvability, o as getAdapter, r as commandFor, s as hookProfileOf, t as DEFAULT_AGENT_ID, u as resolveAdapter } from "./adapters-
|
|
22
|
+
import { $ as TeamReviewCompareFiles, A as MyPrSearchResponse, At as CoherenceWorkInspect, B as PostingPlan, C as MyPrMergeMethod, Ct as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, D as MyPrMergeWhenReadyRequest, E as MyPrMergeStateResponse, F as CommitSha, G as ReviewDraft, H as QueuedReview, I as DECIDING_REVIEW_STATES, J as ReviewThreadId, K as ReviewFinding, L as FindingSeverity, M as MyPrThreadsResponse, N as MyPrsState, Ot as CoherenceTicketCreated, P as MyPrsStatus, R as GithubReviewDecision, Tt as CoherenceOrient, U as ReviewChecksState, V as PrDetail, W as ReviewComment, X as SearchedPr, Y as ReviewVerdict, Z as TeamReviewActionRequest, _ as WorkflowSearchNode, a as ConfigUpdate, at as TeamReviewThreadsRepository, b as MyPrAutoRebase, bt as USAGE_COST_MODES, c as TASK_TITLE_SOURCE_PRIORITY, ct as hasStandingViewerApproval, d as BRANCH_GC_CONTROL_NUMERIC_KEYS, dt as shortSha$1, et as TeamReviewResolveResponse, ft as GH_SEGMENT, g as WorkflowLabelName, h as WorkflowCommentBody, ht as repoParts, it as TeamReviewThreadResult, j as MyPrThreadNode, k as MyPrSearchNode, kt as CoherenceWorkCreated, l as configIssueMessage, lt as FULL_SHA_RE, m as DEFAULT_FACTORY_PROTECTED_PATHS, mt as REPO_SLUG_RE, nt as TeamReviewStatus, o as PersistedTaskTitle, ot as canApproveAfterComment, p as DEFAULT_FACTORY_CHECKS, pt as NODE_ID_RE, q as ReviewResult, r as BrowserConfig, rt as TeamReviewThreadCommentsResponse, s as RUNTIME_CONFIG_SCALAR_KEYS, st as decisionAsIfApprovalRequired, tt as TeamReviewStateEntry, u as BRANCH_GC_CONTROL_BOOLEAN_KEYS, ut as HEX_SHA_RE, v as WorkflowsSettings, w as MyPrMergeRequest, wt as USAGE_INTEGER_RANGES, x as MyPrKeepMergeableRequest, xt as USAGE_VENDOR_KEYS, y as WorkflowsState, yt as USAGE_BUDGET_KEYS, z as GithubReviewState } from "./config-DTwMFUjx.js";
|
|
23
|
+
import { $ as sessionIdFromBranch, A as snapshotEvents, B as classifySessionExit, C as createIngestStore, D as resolveIngestConfig, E as publishEvent, F as adapterBucket, G as nodeMajorVersion, H as decideRemoteTelemetryState, I as buildAiGenerationEvents, J as stableConfigKey, K as parsePosthogReleaseId, L as buildBrowserExceptionProperties, M as FIRST_RUN_NOTICE, N as TELEMETRY_BATCH_URL, O as ringStats, P as TELEMETRY_FLAGS_URL, Q as planWorktreeGc, R as buildExceptionProperties, S as buildContextDigest, T as latestSeq, U as decideTelemetryConsent, V as decideIsDevInstall, W as exceptionFingerprint, X as matchedPrefix, Y as DEFAULT_BRANCH_GC_PREFIXES, Z as planBranchGc, _ as INGEST_SPEC, a as ensureProjectIds, b as DEFAULT_DIGEST_BUDGET_CHARS, d as assetForPlatform, et as usablePrefixes, f as decideRtkInstall, g as verifyDigest, h as isRtkBinaryName, i as createConfigStore, j as localDayKey, k as scrubText, m as installTargetPath, n as DEFAULT_CONFIG, o as generateProjectId, p as findEscapingArchiveMember, q as resolveProjectToken, s as glimmervoidHomeDir$1, t as ABORT_CONFIG_SAVE, tt as worktreeIntegrationTips, v as mergeSettingsBlock, w as enabledSourceNames, x as SOURCE_DEFAULTS, y as validateSettingsBlock, z as buildFactoryDecisionEvent } from "./config-store-CggAQLUB.js";
|
|
24
|
+
import { $ as FactoryHarnessVerdict, A as BenchmarkActionRequest, B as PrCheckoutCaseInput, C as IssueKey, D as IssuesStatus, E as IssuesState, F as BenchmarkStatus, G as TelemetryState, H as PendingCrashReport, I as BenchmarkSuite, J as FACTORY_ERROR_MAX_CHARS, K as FACTORY_DECISION_OUTPUT_MAX_BYTES, L as CommitComparison, M as BenchmarkId, N as BenchmarkJudgement, O as ChangeMap, P as BenchmarkRun, Q as FactoryHarnessStateLine, R as MergedPrListing, S as GithubIssueResponse, T as IssuesSearchResponse, U as TELEMETRY_EVENT_SCHEMAS, X as FactoryConsequences, Y as FACTORY_PROTECTED_PATH_FLOOR, Z as FactoryControlRequest, _ as PlanDecision, a as ClientMessage, at as FactoryWorkerEvent, b as planTitle, c as UpdateJournal, d as TraceRecord, et as FactoryLaneState, f as PLAN_BODY_CAP_BYTES, g as PLAN_TOOL_NAME, h as PLAN_RESULT_HOOK_EVENT, i as CONTROL_FRAME_MAX_BYTES, it as FactoryReviewerOutput, j as BenchmarkCase, k as changeMapFactId, l as MAX_RAW_LINE_CHARS, m as PLAN_HOOK_OUTPUT_MAX_CHARS, n as HookEnvelope, nt as FactoryQueueIntentRequest, o as DIFF_ANNOTATION_NOTE_MAX_CHARS, ot as isSingleFactoryPathSegment, p as PLAN_HOOK_EVENT, q as FactoryDecisionLogLine, r as parseDataClientMessage, rt as FactoryReviewVerdict, s as InstallFlavor, t as HTTP_URL_RE, tt as FactoryProjectState, u as TraceCheckpoint, v as PlanRevision, w as IssueUpdate, x as GithubIssuePullRequestsRepository, y as parseExitPlanModeHookPayload, z as MinedPrReviewData } from "./contracts-D1wLN5iO.js";
|
|
25
|
+
import { a as describeAgentResolvability, c as isKnownAgentId, d as setCustomAgents, f as claudeCode, i as customAgentFingerprint, l as listAgentIds, n as cachedAgentResolvability, o as getAdapter, r as commandFor, s as hookProfileOf, t as DEFAULT_AGENT_ID, u as resolveAdapter } from "./adapters-BY8slY95.js";
|
|
26
26
|
import { t as HOOK_TOOLS } from "./hook-tools-UX2fmt81.js";
|
|
27
27
|
import { a as formatSshPublicKey, c as orderAgentSockets, i as commitSigningShimText, l as parseSshPublicKey, n as NO_AGENT_HOLDS_KEY, o as isForwardedAgentDirName, r as agentListsKey, s as isSignableGitObject, t as COMMIT_SIGNING_SHIM_NAME } from "./ssh-signing-core-CRhVVWNW.js";
|
|
28
|
-
import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-
|
|
28
|
+
import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-DKMQEIZh.js";
|
|
29
29
|
import { _ as escapeMarkup, g as createLaneLog, n as createVisionsSetup } from "./visions-setup-CfgNHiG3.js";
|
|
30
30
|
import { t as getRtkPath } from "./rtk-resolver-jJxy_Mrt.js";
|
|
31
31
|
import { createRequire } from "node:module";
|
|
@@ -37,7 +37,7 @@ import { z } from "zod";
|
|
|
37
37
|
import http from "node:http";
|
|
38
38
|
import { WebSocketServer } from "ws";
|
|
39
39
|
import crypto, { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
40
|
-
import fsp, { access, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm,
|
|
40
|
+
import fsp, { access, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, symlink } from "node:fs/promises";
|
|
41
41
|
import { pipeline } from "node:stream";
|
|
42
42
|
import express from "express";
|
|
43
43
|
import pty from "node-pty";
|
|
@@ -2039,7 +2039,6 @@ function projectSessionSnapshots(source) {
|
|
|
2039
2039
|
//#region server/core/sandbox-roles-core.ts
|
|
2040
2040
|
var SESSION_VENDORS = Object.freeze(["claude", "codex"]);
|
|
2041
2041
|
var CONFINED_SESSION_VENDORS = Object.freeze(["claude"]);
|
|
2042
|
-
var UNSHARED_WORKTREE_ENTRIES = Object.freeze([".claude"]);
|
|
2043
2042
|
var LANE_CREDENTIAL_ENV = Object.freeze({
|
|
2044
2043
|
SSH_AUTH_SOCK: "",
|
|
2045
2044
|
SSH_ASKPASS: "",
|
|
@@ -2088,14 +2087,16 @@ function workRole({ vendor, cwd, checkout, readablePaths, writablePaths = [], ag
|
|
|
2088
2087
|
readableWithinDenied: [...readablePaths]
|
|
2089
2088
|
};
|
|
2090
2089
|
}
|
|
2091
|
-
function sessionRole({
|
|
2090
|
+
function sessionRole({ writableRoots, readDenied, readablePaths, blockedPaths }) {
|
|
2092
2091
|
return {
|
|
2092
|
+
guardrailLevel: "standard",
|
|
2093
|
+
blockedPaths: [...blockedPaths],
|
|
2093
2094
|
vendors: SESSION_VENDORS,
|
|
2094
2095
|
vendorHome: { scope: "state" },
|
|
2095
2096
|
network: { access: "open" },
|
|
2096
2097
|
writableRoots: [...new Set(writableRoots)],
|
|
2097
2098
|
lockedCheckouts: [],
|
|
2098
|
-
commitCheckouts,
|
|
2099
|
+
commitCheckouts: [],
|
|
2099
2100
|
readDenied: [...readDenied],
|
|
2100
2101
|
readableWithinDenied: [...readablePaths]
|
|
2101
2102
|
};
|
|
@@ -2298,7 +2299,7 @@ function createAgentApiWiring({ config, agentSessions, listAllSessions, listBoar
|
|
|
2298
2299
|
name,
|
|
2299
2300
|
path: parent.path,
|
|
2300
2301
|
dangerouslySkipPermissions: parent.dangerouslySkipPermissions,
|
|
2301
|
-
|
|
2302
|
+
unguarded: !parent.isConfined
|
|
2302
2303
|
};
|
|
2303
2304
|
let child = null;
|
|
2304
2305
|
let released = false;
|
|
@@ -3975,7 +3976,7 @@ function runGh(args, options = {}) {
|
|
|
3975
3976
|
}
|
|
3976
3977
|
//#endregion
|
|
3977
3978
|
//#region server/post-turn-checker.ts
|
|
3978
|
-
var GIT_TIMEOUT_MS$
|
|
3979
|
+
var GIT_TIMEOUT_MS$1 = 5e3;
|
|
3979
3980
|
var DEFAULTS = Object.freeze({
|
|
3980
3981
|
enabled: true,
|
|
3981
3982
|
mode: "report",
|
|
@@ -4077,7 +4078,7 @@ var GIT_MAX_BUFFER_BYTES$1 = 8388608;
|
|
|
4077
4078
|
async function execGit(args, cwd) {
|
|
4078
4079
|
const result = await runGit(args, {
|
|
4079
4080
|
cwd,
|
|
4080
|
-
timeoutMs: GIT_TIMEOUT_MS$
|
|
4081
|
+
timeoutMs: GIT_TIMEOUT_MS$1,
|
|
4081
4082
|
maxBuffer: GIT_MAX_BUFFER_BYTES$1,
|
|
4082
4083
|
trim: false
|
|
4083
4084
|
});
|
|
@@ -14108,6 +14109,51 @@ var SANDBOX_PLACEHOLDER_NAMES = Object.freeze([
|
|
|
14108
14109
|
".zprofile",
|
|
14109
14110
|
".zshrc"
|
|
14110
14111
|
]);
|
|
14112
|
+
var WHOLE_FILESYSTEM = "/";
|
|
14113
|
+
var GLIMMERVOID_CONFIG_SIBLING_ENTRIES = Object.freeze([
|
|
14114
|
+
"bin",
|
|
14115
|
+
"pairings.json",
|
|
14116
|
+
"pairings-seen.json",
|
|
14117
|
+
"plans",
|
|
14118
|
+
"telegram-outbox.json",
|
|
14119
|
+
"traces",
|
|
14120
|
+
"uploads",
|
|
14121
|
+
"usage-budget-state.json",
|
|
14122
|
+
"usage-lanes.json",
|
|
14123
|
+
"usage-warehouse.json",
|
|
14124
|
+
"visions-intent.json"
|
|
14125
|
+
]);
|
|
14126
|
+
var GLIMMERVOID_HOME_STATE_ENTRIES = Object.freeze([
|
|
14127
|
+
"benchmark-runs",
|
|
14128
|
+
"benchmarks",
|
|
14129
|
+
"config.json",
|
|
14130
|
+
"factory",
|
|
14131
|
+
"issues-cache.json",
|
|
14132
|
+
"knowledge-graph",
|
|
14133
|
+
"litellm-pricing.json",
|
|
14134
|
+
"my-prs-state.json",
|
|
14135
|
+
"my-prs-work",
|
|
14136
|
+
"posthog-reports",
|
|
14137
|
+
"posthog-state.json",
|
|
14138
|
+
"posthog-work",
|
|
14139
|
+
"recordings",
|
|
14140
|
+
"sandbox-homes",
|
|
14141
|
+
"sandbox-policies",
|
|
14142
|
+
"sane-yolo",
|
|
14143
|
+
"scratch",
|
|
14144
|
+
"sounds",
|
|
14145
|
+
"team-review-repos",
|
|
14146
|
+
"team-review-state.json",
|
|
14147
|
+
"team-review-work",
|
|
14148
|
+
"team-review-worktrees",
|
|
14149
|
+
"telemetry-pending-crash.json",
|
|
14150
|
+
"telemetry.json",
|
|
14151
|
+
"tmp",
|
|
14152
|
+
"update-check.json",
|
|
14153
|
+
"update-journal.json",
|
|
14154
|
+
"workflows-state.json",
|
|
14155
|
+
"workflows-work"
|
|
14156
|
+
]);
|
|
14111
14157
|
var RUNTIME_MANDATORY_CLAUDE_DENY_FOLDERS = Object.freeze(["commands", "agents"]);
|
|
14112
14158
|
var SANDBOXED_PROXY_BYPASS = "localhost,::1,169.254.0.0/16,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16";
|
|
14113
14159
|
var HOOK_LOOPBACK_HOST = "127.0.0.1";
|
|
@@ -14226,6 +14272,36 @@ function relocatedXdgConfigPaths(host, homeEntries) {
|
|
|
14226
14272
|
if (xdgConfigHome === null) return [];
|
|
14227
14273
|
return homeEntries.filter((entry) => entry.startsWith(XDG_CONFIG_DEFAULT_HOME_PREFIX)).map((entry) => path.join(xdgConfigHome, entry.slice(8)));
|
|
14228
14274
|
}
|
|
14275
|
+
function isStandardLevel(role) {
|
|
14276
|
+
return role.guardrailLevel === "standard";
|
|
14277
|
+
}
|
|
14278
|
+
function credentialWriteBlocks(host) {
|
|
14279
|
+
const credentialHomeEntries = [...CREDENTIAL_HOME_ENTRIES, ...CLOUD_CREDENTIAL_HOME_ENTRIES];
|
|
14280
|
+
return [...homePaths(host, credentialHomeEntries), ...relocatedXdgConfigPaths(host, credentialHomeEntries)];
|
|
14281
|
+
}
|
|
14282
|
+
function glimmervoidStateWriteBlocks(role, host) {
|
|
14283
|
+
const keptWritable = alwaysWritablePaths(role, host);
|
|
14284
|
+
const configFolder = path.dirname(host.glimmervoidConfigFile);
|
|
14285
|
+
const homeEntries = [
|
|
14286
|
+
...GLIMMERVOID_HOME_STATE_ENTRIES,
|
|
14287
|
+
...GLIMMERVOID_CONFIG_SIBLING_ENTRIES,
|
|
14288
|
+
...host.glimmervoidHomeEntryNames
|
|
14289
|
+
].map((entryName) => path.join(host.glimmervoidHome, entryName));
|
|
14290
|
+
const configSiblings = GLIMMERVOID_CONFIG_SIBLING_ENTRIES.map((entryName) => path.join(configFolder, entryName));
|
|
14291
|
+
return unique([
|
|
14292
|
+
host.glimmervoidConfigFile,
|
|
14293
|
+
...homeEntries,
|
|
14294
|
+
...configSiblings
|
|
14295
|
+
]).filter((entryPath) => !keptWritable.some((writable) => isPathInside(entryPath, writable)));
|
|
14296
|
+
}
|
|
14297
|
+
function standardWriteBlockCandidates(role, host) {
|
|
14298
|
+
if (!isStandardLevel(role)) return [];
|
|
14299
|
+
return unique([
|
|
14300
|
+
...credentialWriteBlocks(host),
|
|
14301
|
+
...glimmervoidStateWriteBlocks(role, host),
|
|
14302
|
+
...role.blockedPaths ?? []
|
|
14303
|
+
]);
|
|
14304
|
+
}
|
|
14229
14305
|
function readDeniedPaths(role, host) {
|
|
14230
14306
|
const otherVendors = SANDBOX_VENDORS.filter((vendor) => !role.vendors.includes(vendor));
|
|
14231
14307
|
const otherVendorHomeEntries = [...otherVendors.flatMap((vendor) => VENDOR_PROFILES[vendor].homeEntries), ...UNWRAPPED_VENDOR_HOME_ENTRIES];
|
|
@@ -14259,6 +14335,7 @@ function hostNamedPaths(host) {
|
|
|
14259
14335
|
return [
|
|
14260
14336
|
host.homeDir,
|
|
14261
14337
|
host.glimmervoidHome,
|
|
14338
|
+
host.glimmervoidConfigFile,
|
|
14262
14339
|
host.tempDir,
|
|
14263
14340
|
host.launchHomeDir,
|
|
14264
14341
|
...relocatedXdgConfigHomes,
|
|
@@ -14317,6 +14394,17 @@ function sandboxedEnvFor(role, host) {
|
|
|
14317
14394
|
if (role.network.access === "open") return { TMPDIR: host.tempDir };
|
|
14318
14395
|
return {};
|
|
14319
14396
|
}
|
|
14397
|
+
function filesystemWrites(role, host, writablePaths) {
|
|
14398
|
+
if (isStandardLevel(role)) return {
|
|
14399
|
+
allowWrite: literalEntries([WHOLE_FILESYSTEM, ...writablePaths]),
|
|
14400
|
+
denyWrite: literalEntries(host.writeBlockedPaths)
|
|
14401
|
+
};
|
|
14402
|
+
const isPresent = (candidate) => host.existingPaths.has(candidate);
|
|
14403
|
+
return {
|
|
14404
|
+
allowWrite: literalEntries(writablePaths),
|
|
14405
|
+
denyWrite: literalEntries([...writeDeniesWhenPresent(role, host).filter(isPresent), ...lockedCheckoutWriteDenies(role)])
|
|
14406
|
+
};
|
|
14407
|
+
}
|
|
14320
14408
|
function buildSandboxLaunchPlan(role, host) {
|
|
14321
14409
|
const refusal = sandboxRoleRefusal(role, host);
|
|
14322
14410
|
if (refusal !== null) return {
|
|
@@ -14336,8 +14424,7 @@ function buildSandboxLaunchPlan(role, host) {
|
|
|
14336
14424
|
filesystem: {
|
|
14337
14425
|
denyRead: literalEntries(readDenied),
|
|
14338
14426
|
allowRead: literalEntries([...writableWithinDenied, ...role.readableWithinDenied]),
|
|
14339
|
-
|
|
14340
|
-
denyWrite: literalEntries([...writeDeniesWhenPresent(role, host).filter(isPresent), ...lockedCheckoutWriteDenies(role)])
|
|
14427
|
+
...filesystemWrites(role, host, writablePaths)
|
|
14341
14428
|
}
|
|
14342
14429
|
},
|
|
14343
14430
|
launchEnv: Object.assign({ CLAUDE_CODE_TMPDIR: host.tempDir }, ...role.vendors.map((vendor) => VENDOR_PROFILES[vendor].launchEnv), launchHomeEnv(role, host)),
|
|
@@ -18935,8 +19022,8 @@ var KILL_MAX_WAIT_MS = 3e3;
|
|
|
18935
19022
|
var KILL_REAP_MAX_WAIT_MS = 2400;
|
|
18936
19023
|
var SLEEP_KILL_TIMEOUT_MS = 9e5;
|
|
18937
19024
|
var MAX_PENDING_ATTENTION_NOTES = 5;
|
|
18938
|
-
var SANDBOX_UNAPPLIED_ERROR = "
|
|
18939
|
-
var SANDBOX_REFUSED_PREFIX = "session not started, the
|
|
19025
|
+
var SANDBOX_UNAPPLIED_ERROR = "guardrail settings could not be applied, session not started";
|
|
19026
|
+
var SANDBOX_REFUSED_PREFIX = "session not started, the guardrails refused: ";
|
|
18940
19027
|
var INNER_SANDBOX_OFF = Object.freeze({ enabled: false });
|
|
18941
19028
|
function settingsSandboxForHooks(adapter, hasOuterSandbox, requestedSettingsSandbox) {
|
|
18942
19029
|
if (!hasOuterSandbox) return requestedSettingsSandbox;
|
|
@@ -20128,7 +20215,7 @@ var Session = class extends EventEmitter {
|
|
|
20128
20215
|
if (!launch || launch !== this._sandboxLaunch) return;
|
|
20129
20216
|
this._sandboxLaunch = null;
|
|
20130
20217
|
launch.dispose().catch((error) => {
|
|
20131
|
-
console.warn(`[session ${this.id}]
|
|
20218
|
+
console.warn(`[session ${this.id}] guardrails cleanup failed: ${errorMessage(error)}`);
|
|
20132
20219
|
});
|
|
20133
20220
|
}
|
|
20134
20221
|
_guardPtyInputSocket() {
|
|
@@ -20689,6 +20776,7 @@ var LAUNCH_HOME_FOLDER = "sandbox-homes";
|
|
|
20689
20776
|
var START_FOLDER = "start";
|
|
20690
20777
|
var ENTER_FOLDER_SCRIPT = "cd \"$1\" && shift && exec \"$@\"";
|
|
20691
20778
|
var LOGIN_FILE_MODE = 384;
|
|
20779
|
+
var ABSENT_PATH_DENY_PLATFORM = "darwin";
|
|
20692
20780
|
async function isPresent(candidate) {
|
|
20693
20781
|
try {
|
|
20694
20782
|
await access(candidate);
|
|
@@ -20714,6 +20802,32 @@ async function realPathWhenPresent(candidate) {
|
|
|
20714
20802
|
function realPathsWhenPresent(candidates) {
|
|
20715
20803
|
return Promise.all(candidates.map(realPathWhenPresent));
|
|
20716
20804
|
}
|
|
20805
|
+
async function symlinkTargetsInside(folder) {
|
|
20806
|
+
const symlinkEntries = (await readdir(folder, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isSymbolicLink());
|
|
20807
|
+
return (await Promise.all(symlinkEntries.map((entry) => realpath(path.join(folder, entry.name)).catch(() => null)))).filter((target) => target !== null);
|
|
20808
|
+
}
|
|
20809
|
+
async function blockedPathsWithRealTargets(candidates, operatorBlockedPaths) {
|
|
20810
|
+
const resolved = await Promise.all(candidates.map(async (candidate) => {
|
|
20811
|
+
const isPresentEntry = await lstat(candidate).then(() => true, (error) => !isMissingFileError(error));
|
|
20812
|
+
const isKeptWhenAbsent = process.platform === ABSENT_PATH_DENY_PLATFORM || operatorBlockedPaths.includes(candidate);
|
|
20813
|
+
if (!isPresentEntry) return isKeptWhenAbsent ? [candidate] : [];
|
|
20814
|
+
const realCandidate = await realpath(candidate).catch(() => candidate);
|
|
20815
|
+
return [
|
|
20816
|
+
candidate,
|
|
20817
|
+
realCandidate,
|
|
20818
|
+
...await symlinkTargetsInside(realCandidate)
|
|
20819
|
+
];
|
|
20820
|
+
}));
|
|
20821
|
+
return [...new Set(resolved.flat())];
|
|
20822
|
+
}
|
|
20823
|
+
async function configuredConfigFile(glimmervoidHome) {
|
|
20824
|
+
const { envPath, homePath } = decideConfigPath({
|
|
20825
|
+
env: process.env,
|
|
20826
|
+
homeDir: glimmervoidHome
|
|
20827
|
+
}, () => false);
|
|
20828
|
+
const configFile = envPath ?? homePath;
|
|
20829
|
+
return path.join(await realPathWhenPresent(path.dirname(configFile)), path.basename(configFile));
|
|
20830
|
+
}
|
|
20717
20831
|
function scannedClaudeHomes(env, homeDir) {
|
|
20718
20832
|
return [env, {
|
|
20719
20833
|
...env,
|
|
@@ -20858,20 +20972,30 @@ async function prepareSandboxLaunch({ role, launchId, tempDir, enterDir }) {
|
|
|
20858
20972
|
reason: "CODEX_HOME names no folder"
|
|
20859
20973
|
};
|
|
20860
20974
|
const xdgConfigHomeOverride = rawTextOr(process.env.XDG_CONFIG_HOME, null);
|
|
20861
|
-
const
|
|
20975
|
+
const stableHostPaths = {
|
|
20862
20976
|
homeDir,
|
|
20863
20977
|
glimmervoidHome,
|
|
20978
|
+
glimmervoidConfigFile: await configuredConfigFile(glimmervoidHome),
|
|
20864
20979
|
tempDir: launchTempDir,
|
|
20865
20980
|
launchHomeDir,
|
|
20866
|
-
homeEntryNames: await readdir(homeDir),
|
|
20867
20981
|
vendorLocations,
|
|
20868
20982
|
unwrappedVendorHomes: await realPathsWhenPresent(grokHomes(process.env, homeDir)),
|
|
20869
20983
|
relocatedXdgConfigHome: xdgConfigHomeOverride === null ? null : await realPathWhenPresent(xdgConfigHomeOverride)
|
|
20870
20984
|
};
|
|
20871
|
-
const buildPlanFromCurrentDisk = async () =>
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20985
|
+
const buildPlanFromCurrentDisk = async () => {
|
|
20986
|
+
const [homeEntryNames, glimmervoidHomeEntryNames] = await Promise.all([readdir(homeDir), readdir(glimmervoidHome)]);
|
|
20987
|
+
const hostPaths = {
|
|
20988
|
+
...stableHostPaths,
|
|
20989
|
+
homeEntryNames,
|
|
20990
|
+
glimmervoidHomeEntryNames
|
|
20991
|
+
};
|
|
20992
|
+
const [existingPaths, writeBlockedPaths] = await Promise.all([presentPaths$1(sandboxPolicyProbePaths(realRole, hostPaths)), blockedPathsWithRealTargets(standardWriteBlockCandidates(realRole, hostPaths), realRole.blockedPaths ?? [])]);
|
|
20993
|
+
return buildSandboxLaunchPlan(realRole, {
|
|
20994
|
+
...hostPaths,
|
|
20995
|
+
existingPaths,
|
|
20996
|
+
writeBlockedPaths
|
|
20997
|
+
});
|
|
20998
|
+
};
|
|
20875
20999
|
const built = await buildPlanFromCurrentDisk();
|
|
20876
21000
|
if (!built.ok) return built;
|
|
20877
21001
|
const { plan } = built;
|
|
@@ -46850,7 +46974,7 @@ function computeCrossRepoLinks(repos) {
|
|
|
46850
46974
|
}
|
|
46851
46975
|
//#endregion
|
|
46852
46976
|
//#region server/change-map-wiring.ts
|
|
46853
|
-
var GIT_TIMEOUT_MS
|
|
46977
|
+
var GIT_TIMEOUT_MS = 15e3;
|
|
46854
46978
|
var GIT_MAX_BUFFER_BYTES = 67108864;
|
|
46855
46979
|
var FILE_READ_BATCH = 64;
|
|
46856
46980
|
var MAX_CACHED_FILES = 5e4;
|
|
@@ -46862,11 +46986,11 @@ var MAX_MEMOIZED_REPO_FACTS = 64;
|
|
|
46862
46986
|
async function runGitAsync(args, cwd) {
|
|
46863
46987
|
const result = await runGit(args, {
|
|
46864
46988
|
cwd,
|
|
46865
|
-
timeoutMs: GIT_TIMEOUT_MS
|
|
46989
|
+
timeoutMs: GIT_TIMEOUT_MS,
|
|
46866
46990
|
maxBuffer: GIT_MAX_BUFFER_BYTES,
|
|
46867
46991
|
trim: false
|
|
46868
46992
|
});
|
|
46869
|
-
if (!result.ok) throw gitCommandFailure(args, result, GIT_TIMEOUT_MS
|
|
46993
|
+
if (!result.ok) throw gitCommandFailure(args, result, GIT_TIMEOUT_MS);
|
|
46870
46994
|
return result.out;
|
|
46871
46995
|
}
|
|
46872
46996
|
function yieldToEventLoop() {
|
|
@@ -47371,9 +47495,9 @@ Object.freeze([
|
|
|
47371
47495
|
...USAGE_BUDGET_KEYS.map((key) => `usage.budget.${key}`),
|
|
47372
47496
|
...TELEGRAM_STRING_KEYS.map((key) => `telegram.${key}`),
|
|
47373
47497
|
"agentApi.enabled",
|
|
47374
|
-
"
|
|
47375
|
-
"
|
|
47376
|
-
"
|
|
47498
|
+
"guardrails.unguardedRepos",
|
|
47499
|
+
"guardrails.blockedPaths",
|
|
47500
|
+
"guardrails.unreadablePaths",
|
|
47377
47501
|
"telemetry.enabled"
|
|
47378
47502
|
]);
|
|
47379
47503
|
var USAGE_REPORT_MAX_DAYS = 3650;
|
|
@@ -47954,7 +48078,7 @@ function registerControlHandlers(controlWss, deps) {
|
|
|
47954
48078
|
if (incoming.ingest != null) cfg.ingest = mergeSettingsBlock(cfg.ingest, incoming.ingest, INGEST_SPEC);
|
|
47955
48079
|
if (s.telegram != null) cfg.telegram = mergeSettingsBlockOverStored(cfg.telegram, s.telegram);
|
|
47956
48080
|
if (s.agentApi != null) cfg.agentApi = mergeSettingsBlockOverStored(cfg.agentApi, s.agentApi);
|
|
47957
|
-
if (s.
|
|
48081
|
+
if (s.guardrails != null) cfg.guardrails = mergeSettingsBlockOverStored(cfg.guardrails, s.guardrails);
|
|
47958
48082
|
if (s.telemetry != null) cfg.telemetry = mergeSettingsBlockOverStored(cfg.telemetry, s.telemetry);
|
|
47959
48083
|
if (!workflowsUpdate) return void 0;
|
|
47960
48084
|
const storedWorkflowsMerge = mergeWorkflowsUpdateOverStored(cfg.workflows, workflowsUpdate);
|
|
@@ -48108,7 +48232,7 @@ function registerControlHandlers(controlWss, deps) {
|
|
|
48108
48232
|
};
|
|
48109
48233
|
if (workspaceRepos) project.repos = workspaceRepos;
|
|
48110
48234
|
if (typeof dangerouslySkipPermissions === "boolean") project.dangerouslySkipPermissions = dangerouslySkipPermissions;
|
|
48111
|
-
if (unconfined) project.
|
|
48235
|
+
if (unconfined) project.unguarded = true;
|
|
48112
48236
|
if (agent) project.agent = agent;
|
|
48113
48237
|
const freshConfig = configStore.save((cfg) => {
|
|
48114
48238
|
cfg.projects.push(project);
|
|
@@ -48222,7 +48346,7 @@ function registerControlHandlers(controlWss, deps) {
|
|
|
48222
48346
|
path: project.path,
|
|
48223
48347
|
agent: project.agent,
|
|
48224
48348
|
dangerouslySkipPermissions: project.dangerouslySkipPermissions,
|
|
48225
|
-
unconfined: project.
|
|
48349
|
+
unconfined: project.unguarded
|
|
48226
48350
|
});
|
|
48227
48351
|
if (!created.ok) {
|
|
48228
48352
|
reply({ error: created.error });
|
|
@@ -50769,10 +50893,10 @@ function createSessionFactory(dependencies) {
|
|
|
50769
50893
|
}
|
|
50770
50894
|
function defaultSandboxFor(project, config, overrides) {
|
|
50771
50895
|
if (!dependencies.sessionSandbox) return null;
|
|
50772
|
-
const unconfinedRepos = (config.
|
|
50896
|
+
const unconfinedRepos = (config.guardrails?.unguardedRepos ?? []).map((repo) => expandTilde(repo, process.env, dependencies.homeDir ?? null));
|
|
50773
50897
|
return isSessionConfined({
|
|
50774
50898
|
usageVendor: getAdapter(overrides.agent ?? project.agent)?.usageVendor ?? null,
|
|
50775
|
-
isMarkedUnconfined: project.
|
|
50899
|
+
isMarkedUnconfined: project.unguarded === true,
|
|
50776
50900
|
sessionFolders: [project.path, ...project.repos ?? []],
|
|
50777
50901
|
unconfinedRepos
|
|
50778
50902
|
}) ? dependencies.sessionSandbox.prepareFor({
|
|
@@ -50829,8 +50953,7 @@ function createSessionFactory(dependencies) {
|
|
|
50829
50953
|
//#region server/session-sandbox.ts
|
|
50830
50954
|
var UNWRAPPED_PLATFORM = "win32";
|
|
50831
50955
|
var GITHUB_TOKEN_TIMEOUT_MS = 5e3;
|
|
50832
|
-
var
|
|
50833
|
-
var OPT_OUT_HINT = "Mark the session or its repository unconfined to start it outside the sandbox.";
|
|
50956
|
+
var OPT_OUT_HINT = "Mark the session or its repository unguarded to start it without guardrails.";
|
|
50834
50957
|
async function readGithubCliToken(env) {
|
|
50835
50958
|
if (rawTextOr(env.GH_TOKEN, null) || rawTextOr(env.GITHUB_TOKEN, null)) return null;
|
|
50836
50959
|
return await execFileAsync("gh", ["auth", "token"], {
|
|
@@ -50838,65 +50961,9 @@ async function readGithubCliToken(env) {
|
|
|
50838
50961
|
encoding: "utf8"
|
|
50839
50962
|
}).then(({ stdout }) => stdout.trim(), () => "") || null;
|
|
50840
50963
|
}
|
|
50841
|
-
async function
|
|
50842
|
-
const
|
|
50843
|
-
|
|
50844
|
-
timeout: GIT_TIMEOUT_MS
|
|
50845
|
-
}).then(({ stdout }) => stdout.trim(), () => "");
|
|
50846
|
-
if (!toplevel) return null;
|
|
50847
|
-
const checkout = await existingRealPath(toplevel);
|
|
50848
|
-
if (checkout === null || !isPathInside(checkout, startFolder)) return null;
|
|
50849
|
-
return checkout;
|
|
50850
|
-
}
|
|
50851
|
-
async function isRegisteredGitEntry(gitEntry, worktreeAdminDir) {
|
|
50852
|
-
return await readFile(path.join(worktreeAdminDir, "gitdir"), "utf8").then((registeredPath) => realpath(path.resolve(worktreeAdminDir, registeredPath.trim()))).catch(() => null) === gitEntry;
|
|
50853
|
-
}
|
|
50854
|
-
async function ownGitDirOf(checkout, startFolder) {
|
|
50855
|
-
const gitDirs = await readGitDirsOfOwnCheckout(startFolder).catch(() => null);
|
|
50856
|
-
if (gitDirs === null) return null;
|
|
50857
|
-
const { commonGitDir, worktreeAdminDir } = gitDirs;
|
|
50858
|
-
const gitEntry = path.join(checkout, ".git");
|
|
50859
|
-
const gitEntryStats = await lstat(gitEntry).catch(() => null);
|
|
50860
|
-
if (gitEntryStats?.isDirectory()) return worktreeAdminDir === gitEntry && commonGitDir === gitEntry ? commonGitDir : null;
|
|
50861
|
-
const isLinkedWorktree = worktreeAdminDir !== commonGitDir;
|
|
50862
|
-
if (!gitEntryStats?.isFile() || !isLinkedWorktree) return null;
|
|
50863
|
-
if ((checkout === startFolder ? gitDirs : await readGitDirsOfOwnCheckout(checkout).catch(() => null))?.worktreeAdminDir !== worktreeAdminDir) return null;
|
|
50864
|
-
return await isRegisteredGitEntry(gitEntry, worktreeAdminDir) ? commonGitDir : null;
|
|
50865
|
-
}
|
|
50866
|
-
async function commitCheckoutOf(startFolder) {
|
|
50867
|
-
const checkout = await gitCheckoutOf(startFolder);
|
|
50868
|
-
if (checkout === null) return null;
|
|
50869
|
-
const gitDir = await ownGitDirOf(checkout, startFolder);
|
|
50870
|
-
return gitDir === null ? null : {
|
|
50871
|
-
checkout,
|
|
50872
|
-
gitDir
|
|
50873
|
-
};
|
|
50874
|
-
}
|
|
50875
|
-
async function memberCommitCheckoutOf(memberFolder) {
|
|
50876
|
-
const commitCheckout = await commitCheckoutOf(memberFolder);
|
|
50877
|
-
return commitCheckout?.checkout === memberFolder ? commitCheckout : null;
|
|
50878
|
-
}
|
|
50879
|
-
async function workspaceMemberCheckouts(workspaceFolder) {
|
|
50880
|
-
const memberFolders = (await readdir(workspaceFolder, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => path.join(workspaceFolder, entry.name));
|
|
50881
|
-
const gitPointers = await Promise.all(memberFolders.map((memberFolder) => existingRealPath(path.join(memberFolder, ".git"))));
|
|
50882
|
-
return (await Promise.all(memberFolders.filter((_memberFolder, index) => gitPointers[index] !== null).map(memberCommitCheckoutOf))).filter((commitCheckout) => commitCheckout !== null);
|
|
50883
|
-
}
|
|
50884
|
-
async function sessionCheckouts(cwd, isWorkspace) {
|
|
50885
|
-
if (isWorkspace) return workspaceMemberCheckouts(cwd);
|
|
50886
|
-
const commitCheckout = await commitCheckoutOf(cwd);
|
|
50887
|
-
return commitCheckout === null ? [] : [commitCheckout];
|
|
50888
|
-
}
|
|
50889
|
-
async function sharedFolderBehind(linkPath, repositoryFolder) {
|
|
50890
|
-
if (!(await lstat(linkPath).catch(() => null))?.isSymbolicLink()) return null;
|
|
50891
|
-
const sharedPath = await existingRealPath(linkPath);
|
|
50892
|
-
if (sharedPath !== repositoryFolder) return null;
|
|
50893
|
-
return (await stat(sharedPath)).isDirectory() ? sharedPath : null;
|
|
50894
|
-
}
|
|
50895
|
-
async function sharedFoldersOf({ checkout, gitDir }, worktreeShare) {
|
|
50896
|
-
const repositoryRoot = repositoryRootOfCommonGitDir(gitDir);
|
|
50897
|
-
if (repositoryRoot === null) return [];
|
|
50898
|
-
const sharedEntries = worktreeShare.filter((entry) => !UNSHARED_WORKTREE_ENTRIES.includes(entry));
|
|
50899
|
-
return (await Promise.all(sharedEntries.map((entry) => sharedFolderBehind(path.join(checkout, entry), path.resolve(path.join(repositoryRoot, entry)))))).filter((sharedFolder) => sharedFolder !== null);
|
|
50964
|
+
async function repositoryRootOf(cwd) {
|
|
50965
|
+
const gitDirs = await readGitDirsOfOwnCheckout(cwd).catch(() => null);
|
|
50966
|
+
return gitDirs === null ? null : repositoryRootOfCommonGitDir(gitDirs.commonGitDir);
|
|
50900
50967
|
}
|
|
50901
50968
|
function createSessionSandbox({ getSettings, uploadsRoot, sandboxRefusal = allowSandboxedSpawn, prepareSandbox = prepareSandboxLaunch, trustClaudeFolder, platform = process.platform, homeDir = os.homedir(), env = process.env, readGithubToken = () => readGithubCliToken(env), log = console }) {
|
|
50902
50969
|
const expandHome = (candidates) => candidates.map((candidate) => expandTilde(candidate.trim(), env, homeDir)).filter(Boolean);
|
|
@@ -50906,27 +50973,24 @@ function createSessionSandbox({ getSettings, uploadsRoot, sandboxRefusal = allow
|
|
|
50906
50973
|
const sessionUploads = path.join(uploadsRoot, sessionId);
|
|
50907
50974
|
await mkdir(sessionUploads, { recursive: true });
|
|
50908
50975
|
const cwd = await realpath(facts.cwd);
|
|
50909
|
-
const
|
|
50910
|
-
const
|
|
50911
|
-
const
|
|
50976
|
+
const ownRepositoryRoot = isWorkspace ? null : await repositoryRootOf(cwd);
|
|
50977
|
+
const expandedBlockedPaths = expandHome(settings.blockedPaths);
|
|
50978
|
+
const ignoredBlockedPaths = expandedBlockedPaths.filter((blockedPath) => !path.isAbsolute(blockedPath));
|
|
50979
|
+
if (ignoredBlockedPaths.length > 0) log.warn(`[guardrails] ignoring guardrails.blockedPaths entries that are not absolute paths: ${ignoredBlockedPaths.join(", ")}`);
|
|
50912
50980
|
return {
|
|
50913
50981
|
cwd,
|
|
50914
|
-
trustFolder:
|
|
50982
|
+
trustFolder: ownRepositoryRoot ?? cwd,
|
|
50915
50983
|
role: sessionRole({
|
|
50916
|
-
|
|
50917
|
-
writableRoots: [
|
|
50918
|
-
...startFolderRoots,
|
|
50919
|
-
...sharedFolders,
|
|
50920
|
-
...await existingRealPaths([...expandHome(settings.writablePaths), ...facts.writablePaths])
|
|
50921
|
-
],
|
|
50984
|
+
writableRoots: await existingRealPaths(facts.writablePaths),
|
|
50922
50985
|
readDenied: expandHome(settings.unreadablePaths).filter((unreadablePath) => path.isAbsolute(unreadablePath)),
|
|
50986
|
+
blockedPaths: expandedBlockedPaths.filter((blockedPath) => path.isAbsolute(blockedPath)),
|
|
50923
50987
|
readablePaths: [...facts.readablePaths, ...await existingRealPaths([sessionUploads, githubCliConfigDir()])]
|
|
50924
50988
|
})
|
|
50925
50989
|
};
|
|
50926
50990
|
}
|
|
50927
50991
|
async function recordClaudeFolderTrust(folder) {
|
|
50928
50992
|
if (!trustClaudeFolder) return;
|
|
50929
|
-
await trustClaudeFolder(folder).catch((error) => log.warn(`[
|
|
50993
|
+
await trustClaudeFolder(folder).catch((error) => log.warn(`[guardrails] ${errorMessage(error)}`));
|
|
50930
50994
|
}
|
|
50931
50995
|
function prepareFor(request) {
|
|
50932
50996
|
if (platform === UNWRAPPED_PLATFORM) return null;
|
|
@@ -51023,11 +51087,10 @@ function createBackendSessionRuntime(dependencies) {
|
|
|
51023
51087
|
getUserHooks: (projectId) => hooksForProject(dependencies.config.hooks, projectId),
|
|
51024
51088
|
sessionSandbox: createSessionSandbox({
|
|
51025
51089
|
getSettings: () => {
|
|
51026
|
-
const {
|
|
51090
|
+
const { guardrails } = dependencies.configStore.config;
|
|
51027
51091
|
return {
|
|
51028
|
-
|
|
51029
|
-
unreadablePaths:
|
|
51030
|
-
worktreeShare: worktreeShare ?? DEFAULT_CONFIG.worktreeShare
|
|
51092
|
+
blockedPaths: guardrails?.blockedPaths ?? DEFAULT_CONFIG.guardrails.blockedPaths,
|
|
51093
|
+
unreadablePaths: guardrails?.unreadablePaths ?? DEFAULT_CONFIG.guardrails.unreadablePaths
|
|
51031
51094
|
};
|
|
51032
51095
|
},
|
|
51033
51096
|
uploadsRoot: configSiblingPath(dependencies.configStore.configPath, "uploads"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as errorMessage } from "./text-DoirglWV.js";
|
|
2
|
-
import { l as resolveConfigPath } from "./config-store-
|
|
3
|
-
import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-
|
|
2
|
+
import { l as resolveConfigPath } from "./config-store-CggAQLUB.js";
|
|
3
|
+
import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-DKMQEIZh.js";
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
//#region server/text-format.ts
|
|
6
6
|
function trimIso(iso) {
|
|
@@ -3,7 +3,7 @@ import { i as equalsIgnoringCaseOnWindows, t as canonicalizePath } from "./paths
|
|
|
3
3
|
import { n as isRecord } from "./coerce-NSst8oRP.js";
|
|
4
4
|
import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.js";
|
|
5
5
|
import { a as jsonStateLoadError, d as writeJsonAtomicSync, l as sleepSync, s as loadJsonStateFileSync, u as writeJsonAtomic } from "./json-file-oEH9vt-0.js";
|
|
6
|
-
import { s as glimmervoidHomeDir } from "./config-store-
|
|
6
|
+
import { s as glimmervoidHomeDir } from "./config-store-CggAQLUB.js";
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import crypto from "node:crypto";
|
|
@@ -8,7 +8,7 @@ var LINUX_SANDBOX_BINARIES = Object.freeze([
|
|
|
8
8
|
]);
|
|
9
9
|
var NO_SANDBOX_BINARIES = Object.freeze([]);
|
|
10
10
|
var SANDBOX_INSTALL_HINT = "Install bubblewrap, socat and ripgrep, for example: sudo apt install bubblewrap socat ripgrep";
|
|
11
|
-
var SANDBOXED_WORK = "
|
|
11
|
+
var SANDBOXED_WORK = "guarded sessions and factory checks";
|
|
12
12
|
function requiredSandboxBinaries(platform) {
|
|
13
13
|
return platform === "linux" ? LINUX_SANDBOX_BINARIES : NO_SANDBOX_BINARIES;
|
|
14
14
|
}
|
|
@@ -31,14 +31,14 @@ function missingBinariesPhrase(report) {
|
|
|
31
31
|
}
|
|
32
32
|
function sandboxSpawnRefusal(report) {
|
|
33
33
|
if (report.missingBinaries.length === 0) return null;
|
|
34
|
-
return `not started: the
|
|
34
|
+
return `not started: the guardrails need ${namesList(report.requiredBinaries)}, and ${missingBinariesPhrase(report)}. ${report.installHint}`;
|
|
35
35
|
}
|
|
36
36
|
function sandboxBootWarning(report) {
|
|
37
37
|
if (report.missingBinaries.length === 0) return null;
|
|
38
|
-
return `[
|
|
38
|
+
return `[guardrails] ${missingBinariesPhrase(report)}, so ${SANDBOXED_WORK} will refuse to start. ${report.installHint}`;
|
|
39
39
|
}
|
|
40
40
|
function sandboxDoctorRows(report) {
|
|
41
|
-
if (report.requiredBinaries.length === 0) return [["
|
|
41
|
+
if (report.requiredBinaries.length === 0) return [["guardrails", `nothing to check on ${report.platform}`]];
|
|
42
42
|
const binaryRows = report.requiredBinaries.map((binary) => [binary, report.missingBinaries.includes(binary) ? "MISSING" : "found"]);
|
|
43
43
|
if (report.installHint === null) return binaryRows;
|
|
44
44
|
return [...binaryRows, ["hint", report.installHint]];
|