@h-rig/runtime 0.0.6-alpha.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 +27 -0
- package/dist/bin/rig-agent-dispatch.js +9615 -0
- package/dist/bin/rig-agent.js +9512 -0
- package/dist/bin/rig-browser-tool.js +269 -0
- package/dist/src/agent-mode.js +48 -0
- package/dist/src/baked-secrets.js +121 -0
- package/dist/src/binary-build-worker.js +312 -0
- package/dist/src/binary-run.js +540 -0
- package/dist/src/boundaries.js +1 -0
- package/dist/src/build-time-config.js +25 -0
- package/dist/src/control-plane/agent-roles.js +27 -0
- package/dist/src/control-plane/agent-wrapper.js +9621 -0
- package/dist/src/control-plane/authority-files.js +582 -0
- package/dist/src/control-plane/browser-contract.js +135 -0
- package/dist/src/control-plane/controlled-bash.js +1111 -0
- package/dist/src/control-plane/errors.js +13 -0
- package/dist/src/control-plane/harness-main.js +10828 -0
- package/dist/src/control-plane/hook-materializer.js +75 -0
- package/dist/src/control-plane/hooks/audit-trail.js +353 -0
- package/dist/src/control-plane/hooks/completion-verification.js +7552 -0
- package/dist/src/control-plane/hooks/import-guard.js +890 -0
- package/dist/src/control-plane/hooks/inject-context.js +4189 -0
- package/dist/src/control-plane/hooks/post-edit-lint.js +43 -0
- package/dist/src/control-plane/hooks/safety-guard.js +910 -0
- package/dist/src/control-plane/hooks/scope-guard.js +907 -0
- package/dist/src/control-plane/hooks/shared.js +44 -0
- package/dist/src/control-plane/hooks/submodule-branch.js +7797 -0
- package/dist/src/control-plane/hooks/task-runtime-start.js +7799 -0
- package/dist/src/control-plane/hooks/test-integrity-guard.js +891 -0
- package/dist/src/control-plane/materialize-task-config.js +453 -0
- package/dist/src/control-plane/memory-sync/cli.js +2019 -0
- package/dist/src/control-plane/memory-sync/db.js +753 -0
- package/dist/src/control-plane/memory-sync/embed.js +281 -0
- package/dist/src/control-plane/memory-sync/index.js +2049 -0
- package/dist/src/control-plane/memory-sync/query.js +294 -0
- package/dist/src/control-plane/memory-sync/read.js +784 -0
- package/dist/src/control-plane/memory-sync/types.js +6 -0
- package/dist/src/control-plane/memory-sync/write.js +1547 -0
- package/dist/src/control-plane/native/git-native.js +490 -0
- package/dist/src/control-plane/native/git-ops.js +2860 -0
- package/dist/src/control-plane/native/harness-cli.js +9721 -0
- package/dist/src/control-plane/native/pr-automation.js +373 -0
- package/dist/src/control-plane/native/profile-ops.js +481 -0
- package/dist/src/control-plane/native/repo-ops.js +2342 -0
- package/dist/src/control-plane/native/root-resolver.js +66 -0
- package/dist/src/control-plane/native/run-ops.js +3281 -0
- package/dist/src/control-plane/native/runtime-native-sidecar.js +299 -0
- package/dist/src/control-plane/native/runtime-native.js +392 -0
- package/dist/src/control-plane/native/scope-rules.js +17 -0
- package/dist/src/control-plane/native/task-ops.js +6320 -0
- package/dist/src/control-plane/native/task-state.js +1512 -0
- package/dist/src/control-plane/native/utils.js +535 -0
- package/dist/src/control-plane/native/validator-binaries.js +889 -0
- package/dist/src/control-plane/native/validator.js +2197 -0
- package/dist/src/control-plane/native/verifier.js +3249 -0
- package/dist/src/control-plane/native/workspace-ops.js +1635 -0
- package/dist/src/control-plane/plugin-host-context.js +334 -0
- package/dist/src/control-plane/project-main-pre-run-sync.js +630 -0
- package/dist/src/control-plane/provider/claude-stream-records.js +158 -0
- package/dist/src/control-plane/provider/codex-app-server.js +885 -0
- package/dist/src/control-plane/provider/codex-exec-records.js +203 -0
- package/dist/src/control-plane/provider/rig-task-run-skill.js +39 -0
- package/dist/src/control-plane/provider/runtime-instructions.js +96 -0
- package/dist/src/control-plane/remote.js +854 -0
- package/dist/src/control-plane/repos/index.js +473 -0
- package/dist/src/control-plane/repos/layout.js +124 -0
- package/dist/src/control-plane/repos/mirror/bootstrap.js +268 -0
- package/dist/src/control-plane/repos/mirror/refresh.js +398 -0
- package/dist/src/control-plane/repos/mirror/state.js +167 -0
- package/dist/src/control-plane/repos/registry.js +77 -0
- package/dist/src/control-plane/repos/types.js +1 -0
- package/dist/src/control-plane/runtime/agent-mode.js +48 -0
- package/dist/src/control-plane/runtime/baked-secrets.js +120 -0
- package/dist/src/control-plane/runtime/claude-tool-router-binary.js +343 -0
- package/dist/src/control-plane/runtime/claude-tool-router.js +520 -0
- package/dist/src/control-plane/runtime/context.js +216 -0
- package/dist/src/control-plane/runtime/events.js +218 -0
- package/dist/src/control-plane/runtime/guard-types.js +6 -0
- package/dist/src/control-plane/runtime/guard.js +880 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +1194 -0
- package/dist/src/control-plane/runtime/image/index.js +2255 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +1191 -0
- package/dist/src/control-plane/runtime/image.js +2255 -0
- package/dist/src/control-plane/runtime/index.js +8511 -0
- package/dist/src/control-plane/runtime/isolation/discovery.js +599 -0
- package/dist/src/control-plane/runtime/isolation/home.js +1217 -0
- package/dist/src/control-plane/runtime/isolation/index.js +8193 -0
- package/dist/src/control-plane/runtime/isolation/runner.js +2651 -0
- package/dist/src/control-plane/runtime/isolation/shared.js +501 -0
- package/dist/src/control-plane/runtime/isolation/toolchain.js +1892 -0
- package/dist/src/control-plane/runtime/isolation/types.js +1 -0
- package/dist/src/control-plane/runtime/isolation/worktree.js +509 -0
- package/dist/src/control-plane/runtime/isolation.js +8193 -0
- package/dist/src/control-plane/runtime/overlay.js +67 -0
- package/dist/src/control-plane/runtime/plugin-mode.js +41 -0
- package/dist/src/control-plane/runtime/plugins.js +1131 -0
- package/dist/src/control-plane/runtime/provisioning-env.js +220 -0
- package/dist/src/control-plane/runtime/queue.js +8358 -0
- package/dist/src/control-plane/runtime/rig-shell.js +205 -0
- package/dist/src/control-plane/runtime/rig-tools.js +182 -0
- package/dist/src/control-plane/runtime/runner-context.js +1 -0
- package/dist/src/control-plane/runtime/runtime-paths.js +184 -0
- package/dist/src/control-plane/runtime/sandbox/backend-bwrap.js +311 -0
- package/dist/src/control-plane/runtime/sandbox/backend-none.js +21 -0
- package/dist/src/control-plane/runtime/sandbox/backend-seatbelt.js +268 -0
- package/dist/src/control-plane/runtime/sandbox/backend.js +1718 -0
- package/dist/src/control-plane/runtime/sandbox/orchestrator.js +1745 -0
- package/dist/src/control-plane/runtime/sandbox/utils.js +137 -0
- package/dist/src/control-plane/runtime/sandbox-backend-bwrap.js +311 -0
- package/dist/src/control-plane/runtime/sandbox-backend-none.js +21 -0
- package/dist/src/control-plane/runtime/sandbox-backend-seatbelt.js +268 -0
- package/dist/src/control-plane/runtime/sandbox-backend.js +1718 -0
- package/dist/src/control-plane/runtime/sandbox-orchestrator.js +1745 -0
- package/dist/src/control-plane/runtime/sandbox-utils.js +137 -0
- package/dist/src/control-plane/runtime/snapshot/index.js +454 -0
- package/dist/src/control-plane/runtime/snapshot/sidecar.js +502 -0
- package/dist/src/control-plane/runtime/snapshot/task-run.js +1578 -0
- package/dist/src/control-plane/runtime/snapshot-sidecar.js +498 -0
- package/dist/src/control-plane/runtime/snapshot.js +454 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +1578 -0
- package/dist/src/control-plane/runtime/tool-gateway.js +422 -0
- package/dist/src/control-plane/runtime/tooling/browser-tools.js +32 -0
- package/dist/src/control-plane/runtime/tooling/claude-router-binary.js +343 -0
- package/dist/src/control-plane/runtime/tooling/claude-router.js +524 -0
- package/dist/src/control-plane/runtime/tooling/file-tools.js +182 -0
- package/dist/src/control-plane/runtime/tooling/gateway.js +422 -0
- package/dist/src/control-plane/runtime/tooling/index.js +1290 -0
- package/dist/src/control-plane/runtime/tooling/shell.js +205 -0
- package/dist/src/control-plane/runtime/types.js +1 -0
- package/dist/src/control-plane/setup-version.js +14 -0
- package/dist/src/control-plane/state-sync/index.js +1509 -0
- package/dist/src/control-plane/state-sync/read.js +856 -0
- package/dist/src/control-plane/state-sync/reconcile.js +260 -0
- package/dist/src/control-plane/state-sync/repo.js +302 -0
- package/dist/src/control-plane/state-sync/types.js +111 -0
- package/dist/src/control-plane/state-sync/write.js +1469 -0
- package/dist/src/control-plane/task-fields.js +38 -0
- package/dist/src/control-plane/task-source-bootstrap.js +46 -0
- package/dist/src/control-plane/task-source.js +30 -0
- package/dist/src/control-plane/tasks/legacy-task-config-source.js +130 -0
- package/dist/src/control-plane/tasks/plugin-task-source.js +103 -0
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +611 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +1093 -0
- package/dist/src/control-plane/tasks/task-record-reader.js +9 -0
- package/dist/src/control-plane/validators/boundary/public-apis.js +107 -0
- package/dist/src/control-plane/validators/integration/_shared.js +51 -0
- package/dist/src/control-plane/validators/integration/adm-audit-http.js +85 -0
- package/dist/src/control-plane/validators/integration/adm-auth-http.js +78 -0
- package/dist/src/control-plane/validators/integration/adm-issuer-http.js +80 -0
- package/dist/src/control-plane/validators/integration/adm-migration.js +78 -0
- package/dist/src/control-plane/validators/integration/adm-scaffold.js +78 -0
- package/dist/src/control-plane/validators/runtime-registration.js +64 -0
- package/dist/src/control-plane/validators/shared.js +683 -0
- package/dist/src/events.js +218 -0
- package/dist/src/execution.js +35 -0
- package/dist/src/index.js +1633 -0
- package/dist/src/layout.js +145 -0
- package/dist/src/local-server.js +202 -0
- package/dist/src/plugins.js +329 -0
- package/dist/src/remote-http.js +83 -0
- package/dist/src/runtime-context.js +216 -0
- package/dist/src/types.js +1 -0
- package/native/darwin-arm64/bin/rig-git +0 -0
- package/native/darwin-arm64/bin/rig-shell +0 -0
- package/native/darwin-arm64/bin/rig-tools +0 -0
- package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
- package/native/darwin-arm64/lib/runtime-native.dylib +0 -0
- package/native/darwin-arm64/manifest.json +1 -0
- package/native/linux-x64/bin/rig-git +0 -0
- package/native/linux-x64/bin/rig-shell +0 -0
- package/native/linux-x64/bin/rig-tools +0 -0
- package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
- package/native/linux-x64/lib/runtime-native.so +0 -0
- package/native/linux-x64/manifest.json +1 -0
- package/package.json +74 -0
- package/skills/rig-task-run.md +71 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/runtime/src/control-plane/authority-files.ts
|
|
3
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, appendFileSync, copyFileSync, statSync, readdirSync, chmodSync } from "fs";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { dirname as dirname2, join, relative, resolve as resolve2 } from "path";
|
|
6
|
+
import { randomUUID } from "crypto";
|
|
7
|
+
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
8
|
+
|
|
9
|
+
// packages/runtime/src/layout.ts
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
import { basename, dirname, resolve } from "path";
|
|
12
|
+
function resolveMonorepoRoot(projectRoot) {
|
|
13
|
+
const normalizedProjectRoot = resolve(projectRoot);
|
|
14
|
+
const explicit = process.env.MONOREPO_ROOT?.trim();
|
|
15
|
+
if (explicit) {
|
|
16
|
+
const explicitRoot = resolve(explicit);
|
|
17
|
+
const explicitParent = dirname(explicitRoot);
|
|
18
|
+
if (basename(explicitParent) === ".worktrees") {
|
|
19
|
+
const owner = dirname(explicitParent);
|
|
20
|
+
const ownerHasGit = existsSync(resolve(owner, ".git"));
|
|
21
|
+
const ownerHasTaskConfig = existsSync(resolve(owner, ".rig", "task-config.json"));
|
|
22
|
+
const ownerHasRigConfig = existsSync(resolve(owner, "rig.config.ts"));
|
|
23
|
+
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
24
|
+
return owner;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
|
|
27
|
+
}
|
|
28
|
+
if (!existsSync(resolve(explicitRoot, ".git"))) {
|
|
29
|
+
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
|
|
30
|
+
}
|
|
31
|
+
const hasTaskConfig = existsSync(resolve(explicitRoot, ".rig", "task-config.json"));
|
|
32
|
+
const hasRigConfig = existsSync(resolve(explicitRoot, "rig.config.ts"));
|
|
33
|
+
if (!hasTaskConfig && !hasRigConfig) {
|
|
34
|
+
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
|
|
35
|
+
}
|
|
36
|
+
return explicitRoot;
|
|
37
|
+
}
|
|
38
|
+
const projectParent = dirname(normalizedProjectRoot);
|
|
39
|
+
if (basename(projectParent) === ".worktrees") {
|
|
40
|
+
const worktreeOwner = dirname(projectParent);
|
|
41
|
+
const ownerHasGit = existsSync(resolve(worktreeOwner, ".git"));
|
|
42
|
+
const ownerHasTaskConfig = existsSync(resolve(worktreeOwner, ".rig", "task-config.json"));
|
|
43
|
+
const ownerHasRigConfig = existsSync(resolve(worktreeOwner, "rig.config.ts"));
|
|
44
|
+
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
45
|
+
return worktreeOwner;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return normalizedProjectRoot;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// packages/runtime/src/control-plane/authority-files.ts
|
|
52
|
+
function readTomlFile(path, fallback) {
|
|
53
|
+
if (!existsSync2(path))
|
|
54
|
+
return fallback;
|
|
55
|
+
const raw = readFileSync(path, "utf8");
|
|
56
|
+
if (!raw.trim())
|
|
57
|
+
return fallback;
|
|
58
|
+
return parseToml(raw);
|
|
59
|
+
}
|
|
60
|
+
function writeTomlFile(path, value) {
|
|
61
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
62
|
+
writeFileSync(path, `${stringifyToml(value).trimEnd()}
|
|
63
|
+
`, "utf8");
|
|
64
|
+
}
|
|
65
|
+
function normalizeString(value) {
|
|
66
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
67
|
+
}
|
|
68
|
+
function normalizeStringArray(value) {
|
|
69
|
+
if (!Array.isArray(value))
|
|
70
|
+
return [];
|
|
71
|
+
return value.map((entry) => normalizeString(entry)).filter((entry) => entry !== null);
|
|
72
|
+
}
|
|
73
|
+
function normalizePort(value) {
|
|
74
|
+
const port = typeof value === "number" ? value : Number(value);
|
|
75
|
+
return Number.isInteger(port) && port > 0 && port <= 65535 ? port : 7890;
|
|
76
|
+
}
|
|
77
|
+
function loadRemoteEndpointsToml(projectRoot) {
|
|
78
|
+
const paths = resolveAuthorityPaths(projectRoot);
|
|
79
|
+
const parsed = readTomlFile(paths.remoteEndpointsPath, { version: 1, endpoints: {} });
|
|
80
|
+
return {
|
|
81
|
+
version: parsed.version ?? 1,
|
|
82
|
+
endpoints: parsed.endpoints ?? {}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function loadRemoteSecretsToml(projectRoot) {
|
|
86
|
+
const paths = resolveAuthorityPaths(projectRoot);
|
|
87
|
+
const parsed = readTomlFile(paths.remoteSecretsPath, { version: 1, secrets: {} });
|
|
88
|
+
return {
|
|
89
|
+
version: parsed.version ?? 1,
|
|
90
|
+
secrets: parsed.secrets ?? {}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function saveRemoteEndpointsToml(projectRoot, payload) {
|
|
94
|
+
const paths = resolveAuthorityPaths(projectRoot);
|
|
95
|
+
writeTomlFile(paths.remoteEndpointsPath, payload);
|
|
96
|
+
}
|
|
97
|
+
function saveRemoteSecretsToml(projectRoot, payload) {
|
|
98
|
+
const paths = resolveAuthorityPaths(projectRoot);
|
|
99
|
+
writeTomlFile(paths.remoteSecretsPath, payload);
|
|
100
|
+
try {
|
|
101
|
+
chmodSync(paths.remoteSecretsPath, 384);
|
|
102
|
+
} catch {}
|
|
103
|
+
}
|
|
104
|
+
function resolveAuthorityPaths(projectRoot) {
|
|
105
|
+
const normalizedRoot = resolve2(projectRoot);
|
|
106
|
+
const stateRoot = resolveAuthorityStateRoot(normalizedRoot);
|
|
107
|
+
const stateDir = resolveAuthorityStateDir(normalizedRoot);
|
|
108
|
+
return {
|
|
109
|
+
projectRoot: normalizedRoot,
|
|
110
|
+
harnessRoot: resolve2(normalizedRoot, "rig"),
|
|
111
|
+
runsDir: resolve2(stateRoot, "runs"),
|
|
112
|
+
remoteDir: resolve2(stateRoot, "remote"),
|
|
113
|
+
stateDir,
|
|
114
|
+
remoteEndpointsPath: resolve2(stateRoot, "remote", "endpoints.toml"),
|
|
115
|
+
remoteSecretsPath: resolve2(stateDir, "remote-secrets.toml")
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function resolveAuthorityStateRoot(projectRoot) {
|
|
119
|
+
const normalizedRoot = resolve2(projectRoot);
|
|
120
|
+
const taskWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
121
|
+
if (taskWorkspace) {
|
|
122
|
+
return resolve2(taskWorkspace, ".rig");
|
|
123
|
+
}
|
|
124
|
+
const stateDir = process.env.RIG_STATE_DIR?.trim();
|
|
125
|
+
if (stateDir) {
|
|
126
|
+
return dirname2(resolve2(stateDir));
|
|
127
|
+
}
|
|
128
|
+
const logsDir = process.env.RIG_LOGS_DIR?.trim();
|
|
129
|
+
if (logsDir) {
|
|
130
|
+
return dirname2(resolve2(logsDir));
|
|
131
|
+
}
|
|
132
|
+
const sessionFile = process.env.RIG_SESSION_FILE?.trim();
|
|
133
|
+
if (sessionFile) {
|
|
134
|
+
return dirname2(dirname2(resolve2(sessionFile)));
|
|
135
|
+
}
|
|
136
|
+
const projectStateRoot = resolve2(normalizedRoot, ".rig");
|
|
137
|
+
if (existsSync2(projectStateRoot)) {
|
|
138
|
+
return projectStateRoot;
|
|
139
|
+
}
|
|
140
|
+
return resolve2(normalizedRoot, ".rig");
|
|
141
|
+
}
|
|
142
|
+
function resolveAuthorityStateDir(projectRoot) {
|
|
143
|
+
const explicit = process.env.RIG_STATE_DIR?.trim();
|
|
144
|
+
if (explicit) {
|
|
145
|
+
return resolve2(explicit);
|
|
146
|
+
}
|
|
147
|
+
return resolve2(resolveAuthorityStateRoot(projectRoot), "state");
|
|
148
|
+
}
|
|
149
|
+
function resolveAuthorityProjectStateDir(projectRoot) {
|
|
150
|
+
const explicit = process.env.RIG_STATE_DIR?.trim();
|
|
151
|
+
if (explicit) {
|
|
152
|
+
return resolve2(explicit);
|
|
153
|
+
}
|
|
154
|
+
return resolve2(resolve2(projectRoot), ".rig", "state");
|
|
155
|
+
}
|
|
156
|
+
function readJsonAtPath(path, fallback) {
|
|
157
|
+
if (!existsSync2(path)) {
|
|
158
|
+
return fallback;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
162
|
+
} catch {
|
|
163
|
+
return fallback;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function writeJsonAtPath(path, value) {
|
|
167
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
168
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
169
|
+
`, "utf8");
|
|
170
|
+
return path;
|
|
171
|
+
}
|
|
172
|
+
function readAuthorityStateJson(projectRoot, relativePath, fallback) {
|
|
173
|
+
return readJsonAtPath(resolve2(resolveAuthorityStateDir(projectRoot), relativePath), fallback);
|
|
174
|
+
}
|
|
175
|
+
function writeAuthorityStateJson(projectRoot, relativePath, value) {
|
|
176
|
+
return writeJsonAtPath(resolve2(resolveAuthorityStateDir(projectRoot), relativePath), value);
|
|
177
|
+
}
|
|
178
|
+
function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
|
|
179
|
+
return readJsonAtPath(resolve2(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
|
|
180
|
+
}
|
|
181
|
+
function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
|
|
182
|
+
return writeJsonAtPath(resolve2(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
|
|
183
|
+
}
|
|
184
|
+
function resolveAuthorityArtifactsRoot(projectRoot) {
|
|
185
|
+
const explicit = process.env.ARTIFACTS_DIR?.trim();
|
|
186
|
+
if (explicit) {
|
|
187
|
+
return resolve2(explicit);
|
|
188
|
+
}
|
|
189
|
+
const projectArtifactsRoot = resolve2(projectRoot, "artifacts");
|
|
190
|
+
if (existsSync2(projectArtifactsRoot)) {
|
|
191
|
+
return projectArtifactsRoot;
|
|
192
|
+
}
|
|
193
|
+
const taskWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
194
|
+
if (taskWorkspace) {
|
|
195
|
+
return resolve2(taskWorkspace, "artifacts");
|
|
196
|
+
}
|
|
197
|
+
if (process.env.MONOREPO_ROOT?.trim()) {
|
|
198
|
+
return resolve2(resolveMonorepoRoot(projectRoot), "artifacts");
|
|
199
|
+
}
|
|
200
|
+
const normalizedRoot = resolve2(projectRoot);
|
|
201
|
+
const projectLooksLikeMonorepo = existsSync2(resolve2(normalizedRoot, ".git")) && existsSync2(resolve2(normalizedRoot, ".rig", "task-config.json"));
|
|
202
|
+
if (!projectLooksLikeMonorepo) {
|
|
203
|
+
return projectArtifactsRoot;
|
|
204
|
+
}
|
|
205
|
+
return resolve2(resolveMonorepoRoot(projectRoot), "artifacts");
|
|
206
|
+
}
|
|
207
|
+
function resolveAuthorityRuntimeDir(projectRoot) {
|
|
208
|
+
return resolve2(resolveAuthorityStateRoot(projectRoot), "runtime");
|
|
209
|
+
}
|
|
210
|
+
function uniquePaths(paths) {
|
|
211
|
+
const seen = new Set;
|
|
212
|
+
const result = [];
|
|
213
|
+
for (const value of paths) {
|
|
214
|
+
const normalized = normalizeString(value);
|
|
215
|
+
if (!normalized || seen.has(normalized))
|
|
216
|
+
continue;
|
|
217
|
+
seen.add(normalized);
|
|
218
|
+
result.push(normalized);
|
|
219
|
+
}
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
function listAuthorityRunRoots(projectRoot) {
|
|
223
|
+
const normalizedRoot = resolve2(projectRoot);
|
|
224
|
+
const monorepoRoot = resolveMonorepoRoot(normalizedRoot);
|
|
225
|
+
return uniquePaths([
|
|
226
|
+
resolve2(resolveAuthorityStateRoot(normalizedRoot), "runs"),
|
|
227
|
+
resolve2(monorepoRoot, ".rig", "runs")
|
|
228
|
+
]);
|
|
229
|
+
}
|
|
230
|
+
function listAuthorityArtifactRoots(projectRoot) {
|
|
231
|
+
return uniquePaths([
|
|
232
|
+
resolveAuthorityArtifactsRoot(projectRoot)
|
|
233
|
+
]);
|
|
234
|
+
}
|
|
235
|
+
function listAuthorityRuntimeAgentsRoots(projectRoot) {
|
|
236
|
+
return uniquePaths([
|
|
237
|
+
resolve2(resolveAuthorityRuntimeDir(projectRoot), "agents")
|
|
238
|
+
]);
|
|
239
|
+
}
|
|
240
|
+
function listAuthorityRemoteEndpoints(projectRoot) {
|
|
241
|
+
const endpoints = loadRemoteEndpointsToml(projectRoot).endpoints ?? {};
|
|
242
|
+
const secrets = loadRemoteSecretsToml(projectRoot).secrets ?? {};
|
|
243
|
+
return Object.values(endpoints).map((entry) => {
|
|
244
|
+
const token = secrets[entry.secret_ref] ?? "";
|
|
245
|
+
return {
|
|
246
|
+
id: entry.id,
|
|
247
|
+
alias: entry.alias,
|
|
248
|
+
host: entry.host,
|
|
249
|
+
port: normalizePort(entry.port),
|
|
250
|
+
token,
|
|
251
|
+
autoConnect: Boolean(entry.auto_connect),
|
|
252
|
+
addedAt: entry.created_at,
|
|
253
|
+
updatedAt: entry.updated_at,
|
|
254
|
+
lastConnectedAt: normalizeString(entry.last_connected_at) ?? null,
|
|
255
|
+
labels: normalizeStringArray(entry.labels),
|
|
256
|
+
capabilities: normalizeStringArray(entry.capabilities),
|
|
257
|
+
transport: normalizeString(entry.transport) ?? "websocket",
|
|
258
|
+
secretRef: entry.secret_ref
|
|
259
|
+
};
|
|
260
|
+
}).sort((left, right) => left.alias.localeCompare(right.alias));
|
|
261
|
+
}
|
|
262
|
+
function nextRemoteEndpointRecord(input) {
|
|
263
|
+
const timestamp = new Date().toISOString();
|
|
264
|
+
const secretRef = input.existing?.secret_ref ?? randomUUID();
|
|
265
|
+
return {
|
|
266
|
+
record: {
|
|
267
|
+
id: input.endpointId ?? input.existing?.id ?? randomUUID(),
|
|
268
|
+
alias: input.alias,
|
|
269
|
+
host: input.host,
|
|
270
|
+
port: normalizePort(input.port),
|
|
271
|
+
transport: normalizeString(input.transport) ?? normalizeString(input.existing?.transport) ?? "websocket",
|
|
272
|
+
auto_connect: input.autoConnect ?? input.existing?.auto_connect ?? false,
|
|
273
|
+
labels: input.labels ?? normalizeStringArray(input.existing?.labels),
|
|
274
|
+
capabilities: input.capabilities ?? normalizeStringArray(input.existing?.capabilities),
|
|
275
|
+
secret_ref: secretRef,
|
|
276
|
+
created_at: input.existing?.created_at ?? timestamp,
|
|
277
|
+
updated_at: timestamp,
|
|
278
|
+
last_connected_at: input.existing?.last_connected_at ?? null
|
|
279
|
+
},
|
|
280
|
+
secretRef
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function upsertAuthorityRemoteEndpoint(projectRoot, input) {
|
|
284
|
+
const endpointsToml = loadRemoteEndpointsToml(projectRoot);
|
|
285
|
+
const secretsToml = loadRemoteSecretsToml(projectRoot);
|
|
286
|
+
const existing = Object.values(endpointsToml.endpoints ?? {}).find((entry) => entry.alias === input.alias) ?? null;
|
|
287
|
+
const { record, secretRef } = nextRemoteEndpointRecord({
|
|
288
|
+
endpointId: input.endpointId,
|
|
289
|
+
existing,
|
|
290
|
+
alias: input.alias,
|
|
291
|
+
host: input.host,
|
|
292
|
+
port: input.port,
|
|
293
|
+
token: input.token,
|
|
294
|
+
autoConnect: input.autoConnect,
|
|
295
|
+
transport: input.transport,
|
|
296
|
+
labels: input.labels,
|
|
297
|
+
capabilities: input.capabilities
|
|
298
|
+
});
|
|
299
|
+
endpointsToml.endpoints = {
|
|
300
|
+
...endpointsToml.endpoints ?? {},
|
|
301
|
+
[record.id]: record
|
|
302
|
+
};
|
|
303
|
+
secretsToml.secrets = {
|
|
304
|
+
...secretsToml.secrets ?? {},
|
|
305
|
+
[secretRef]: input.token
|
|
306
|
+
};
|
|
307
|
+
saveRemoteEndpointsToml(projectRoot, endpointsToml);
|
|
308
|
+
saveRemoteSecretsToml(projectRoot, secretsToml);
|
|
309
|
+
return listAuthorityRemoteEndpoints(projectRoot).find((entry) => entry.id === record.id);
|
|
310
|
+
}
|
|
311
|
+
function updateAuthorityRemoteEndpoint(projectRoot, input) {
|
|
312
|
+
const endpointsToml = loadRemoteEndpointsToml(projectRoot);
|
|
313
|
+
const secretsToml = loadRemoteSecretsToml(projectRoot);
|
|
314
|
+
const current = Object.values(endpointsToml.endpoints ?? {}).find((entry) => input.endpointId && entry.id === input.endpointId || input.alias && entry.alias === input.alias);
|
|
315
|
+
if (!current)
|
|
316
|
+
return null;
|
|
317
|
+
const record = {
|
|
318
|
+
...current,
|
|
319
|
+
alias: normalizeString(input.alias) ?? current.alias,
|
|
320
|
+
host: normalizeString(input.host) ?? current.host,
|
|
321
|
+
port: input.port !== undefined ? normalizePort(input.port) : current.port,
|
|
322
|
+
auto_connect: input.autoConnect ?? current.auto_connect,
|
|
323
|
+
transport: normalizeString(input.transport) ?? current.transport,
|
|
324
|
+
labels: input.labels ?? normalizeStringArray(current.labels),
|
|
325
|
+
capabilities: input.capabilities ?? normalizeStringArray(current.capabilities),
|
|
326
|
+
updated_at: new Date().toISOString()
|
|
327
|
+
};
|
|
328
|
+
endpointsToml.endpoints = {
|
|
329
|
+
...endpointsToml.endpoints ?? {},
|
|
330
|
+
[record.id]: record
|
|
331
|
+
};
|
|
332
|
+
if (input.token !== undefined) {
|
|
333
|
+
secretsToml.secrets = {
|
|
334
|
+
...secretsToml.secrets ?? {},
|
|
335
|
+
[record.secret_ref]: input.token
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
saveRemoteEndpointsToml(projectRoot, endpointsToml);
|
|
339
|
+
saveRemoteSecretsToml(projectRoot, secretsToml);
|
|
340
|
+
return listAuthorityRemoteEndpoints(projectRoot).find((entry) => entry.id === record.id) ?? null;
|
|
341
|
+
}
|
|
342
|
+
function removeAuthorityRemoteEndpoint(projectRoot, endpointIdOrAlias) {
|
|
343
|
+
const endpointsToml = loadRemoteEndpointsToml(projectRoot);
|
|
344
|
+
const secretsToml = loadRemoteSecretsToml(projectRoot);
|
|
345
|
+
const entry = Object.values(endpointsToml.endpoints ?? {}).find((candidate) => candidate.id === endpointIdOrAlias || candidate.alias === endpointIdOrAlias);
|
|
346
|
+
if (!entry)
|
|
347
|
+
return false;
|
|
348
|
+
const nextEndpoints = { ...endpointsToml.endpoints ?? {} };
|
|
349
|
+
delete nextEndpoints[entry.id];
|
|
350
|
+
const nextSecrets = { ...secretsToml.secrets ?? {} };
|
|
351
|
+
delete nextSecrets[entry.secret_ref];
|
|
352
|
+
saveRemoteEndpointsToml(projectRoot, { version: endpointsToml.version ?? 1, endpoints: nextEndpoints });
|
|
353
|
+
saveRemoteSecretsToml(projectRoot, { version: secretsToml.version ?? 1, secrets: nextSecrets });
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
function markAuthorityRemoteEndpointConnected(projectRoot, endpointId, connectedAt = new Date().toISOString()) {
|
|
357
|
+
const endpointsToml = loadRemoteEndpointsToml(projectRoot);
|
|
358
|
+
const entry = endpointsToml.endpoints?.[endpointId];
|
|
359
|
+
if (!entry)
|
|
360
|
+
return;
|
|
361
|
+
endpointsToml.endpoints = {
|
|
362
|
+
...endpointsToml.endpoints ?? {},
|
|
363
|
+
[endpointId]: {
|
|
364
|
+
...entry,
|
|
365
|
+
last_connected_at: connectedAt,
|
|
366
|
+
updated_at: connectedAt
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
saveRemoteEndpointsToml(projectRoot, endpointsToml);
|
|
370
|
+
}
|
|
371
|
+
function importLegacyRemoteEndpoints(projectRoot, legacyPath = join(homedir(), ".config", "rig", "remotes.toml")) {
|
|
372
|
+
if (!existsSync2(legacyPath)) {
|
|
373
|
+
return { imported: 0, skipped: 0, sourcePath: legacyPath };
|
|
374
|
+
}
|
|
375
|
+
const parsed = readTomlFile(legacyPath, { version: 1, remotes: {} });
|
|
376
|
+
let imported = 0;
|
|
377
|
+
let skipped = 0;
|
|
378
|
+
for (const [alias, entry] of Object.entries(parsed.remotes ?? {})) {
|
|
379
|
+
const host = normalizeString(entry.host);
|
|
380
|
+
const token = normalizeString(entry.token);
|
|
381
|
+
if (!host || !token) {
|
|
382
|
+
skipped += 1;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
upsertAuthorityRemoteEndpoint(projectRoot, {
|
|
386
|
+
alias,
|
|
387
|
+
host,
|
|
388
|
+
port: normalizePort(entry.port),
|
|
389
|
+
token
|
|
390
|
+
});
|
|
391
|
+
imported += 1;
|
|
392
|
+
}
|
|
393
|
+
return { imported, skipped, sourcePath: legacyPath };
|
|
394
|
+
}
|
|
395
|
+
function doctorAuthorityRemoteEndpoints(projectRoot) {
|
|
396
|
+
const paths = resolveAuthorityPaths(projectRoot);
|
|
397
|
+
const endpoints = loadRemoteEndpointsToml(projectRoot).endpoints ?? {};
|
|
398
|
+
const secrets = loadRemoteSecretsToml(projectRoot).secrets ?? {};
|
|
399
|
+
const missingSecrets = Object.values(endpoints).filter((entry) => !normalizeString(secrets[entry.secret_ref])).map((entry) => entry.alias);
|
|
400
|
+
const warnings = [];
|
|
401
|
+
if (!existsSync2(paths.remoteEndpointsPath)) {
|
|
402
|
+
warnings.push("Remote endpoint manifest is missing.");
|
|
403
|
+
}
|
|
404
|
+
if (!existsSync2(paths.remoteSecretsPath)) {
|
|
405
|
+
warnings.push("Remote secret store is missing.");
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
manifestPath: paths.remoteEndpointsPath,
|
|
409
|
+
secretsPath: paths.remoteSecretsPath,
|
|
410
|
+
endpointCount: Object.keys(endpoints).length,
|
|
411
|
+
missingSecrets,
|
|
412
|
+
warnings
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
function resolveAuthorityRunDir(projectRoot, runId) {
|
|
416
|
+
const roots = listAuthorityRunRoots(projectRoot);
|
|
417
|
+
for (const runsDir of roots) {
|
|
418
|
+
const candidate = resolve2(runsDir, runId);
|
|
419
|
+
if (existsSync2(candidate)) {
|
|
420
|
+
return candidate;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return resolve2(roots[0] ?? resolveAuthorityPaths(projectRoot).runsDir, runId);
|
|
424
|
+
}
|
|
425
|
+
function appendJsonlRecord(path, value) {
|
|
426
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
427
|
+
appendFileSync(path, `${JSON.stringify(value)}
|
|
428
|
+
`, "utf8");
|
|
429
|
+
}
|
|
430
|
+
function writeJsonFile(path, value) {
|
|
431
|
+
mkdirSync(dirname2(path), { recursive: true });
|
|
432
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
433
|
+
`, "utf8");
|
|
434
|
+
}
|
|
435
|
+
function readJsonFile(path, fallback) {
|
|
436
|
+
if (!existsSync2(path))
|
|
437
|
+
return fallback;
|
|
438
|
+
try {
|
|
439
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
440
|
+
} catch {
|
|
441
|
+
return fallback;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
function listAuthorityRuns(projectRoot) {
|
|
445
|
+
const runs = new Map;
|
|
446
|
+
for (const runsDir of listAuthorityRunRoots(projectRoot)) {
|
|
447
|
+
if (!existsSync2(runsDir))
|
|
448
|
+
continue;
|
|
449
|
+
for (const runId of readDirRuns(runsDir)) {
|
|
450
|
+
if (runs.has(runId))
|
|
451
|
+
continue;
|
|
452
|
+
const entry = readJsonFile(resolve2(runsDir, runId, "run.json"), null);
|
|
453
|
+
if (entry && runBelongsToProject(projectRoot, entry, runsDir)) {
|
|
454
|
+
runs.set(runId, entry);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return [...runs.values()].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
459
|
+
}
|
|
460
|
+
function runBelongsToProject(projectRoot, run, runsDir) {
|
|
461
|
+
const normalizedRoot = resolve2(projectRoot);
|
|
462
|
+
const record = run;
|
|
463
|
+
const recordedProjectRoot = normalizeString(record.projectRoot);
|
|
464
|
+
if (recordedProjectRoot) {
|
|
465
|
+
return resolve2(recordedProjectRoot) === normalizedRoot;
|
|
466
|
+
}
|
|
467
|
+
const projectLocalRunsDir = resolve2(normalizedRoot, ".rig", "runs");
|
|
468
|
+
if (isPathWithin(projectLocalRunsDir, resolve2(runsDir))) {
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
const pathFields = [
|
|
472
|
+
run.worktreePath,
|
|
473
|
+
run.artifactRoot,
|
|
474
|
+
run.logRoot,
|
|
475
|
+
run.sessionPath,
|
|
476
|
+
run.sessionLogPath
|
|
477
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
478
|
+
if (pathFields.length === 0) {
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
return pathFields.some((value) => isPathWithin(normalizedRoot, resolve2(value)));
|
|
482
|
+
}
|
|
483
|
+
function isPathWithin(root, candidate) {
|
|
484
|
+
const relativePath = relative(root, candidate);
|
|
485
|
+
return relativePath === "" || !relativePath.startsWith("..") && !relativePath.startsWith(`/`) && !relativePath.startsWith(`\\`);
|
|
486
|
+
}
|
|
487
|
+
function readDirRuns(runsDir) {
|
|
488
|
+
try {
|
|
489
|
+
return readdirSync(runsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
490
|
+
} catch {
|
|
491
|
+
return [];
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function readAuthorityRun(projectRoot, runId) {
|
|
495
|
+
for (const runsDir of listAuthorityRunRoots(projectRoot)) {
|
|
496
|
+
const entry = readJsonFile(resolve2(runsDir, runId, "run.json"), null);
|
|
497
|
+
if (entry) {
|
|
498
|
+
return entry;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
function resolveTaskArtifactDirs(projectRoot, taskId) {
|
|
504
|
+
const candidates = [];
|
|
505
|
+
const seen = new Set;
|
|
506
|
+
const add = (value) => {
|
|
507
|
+
const normalized = normalizeString(value);
|
|
508
|
+
if (!normalized || seen.has(normalized))
|
|
509
|
+
return;
|
|
510
|
+
seen.add(normalized);
|
|
511
|
+
candidates.push(normalized);
|
|
512
|
+
};
|
|
513
|
+
for (const run of listAuthorityRuns(projectRoot)) {
|
|
514
|
+
if (run.taskId !== taskId)
|
|
515
|
+
continue;
|
|
516
|
+
add(run.artifactRoot);
|
|
517
|
+
if (run.worktreePath) {
|
|
518
|
+
add(resolve2(run.worktreePath, "artifacts", taskId));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
for (const artifactsRoot of listAuthorityArtifactRoots(projectRoot)) {
|
|
522
|
+
add(resolve2(artifactsRoot, taskId));
|
|
523
|
+
}
|
|
524
|
+
return candidates;
|
|
525
|
+
}
|
|
526
|
+
function readJsonlFile(path) {
|
|
527
|
+
if (!existsSync2(path))
|
|
528
|
+
return [];
|
|
529
|
+
return readFileSync(path, "utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).flatMap((line) => {
|
|
530
|
+
try {
|
|
531
|
+
return [JSON.parse(line)];
|
|
532
|
+
} catch {
|
|
533
|
+
return [];
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
function copyFileIfPresent(sourcePath, targetPath) {
|
|
538
|
+
if (!existsSync2(sourcePath))
|
|
539
|
+
return false;
|
|
540
|
+
mkdirSync(dirname2(targetPath), { recursive: true });
|
|
541
|
+
copyFileSync(sourcePath, targetPath);
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
function fileSizeIfPresent(path) {
|
|
545
|
+
try {
|
|
546
|
+
return statSync(path).size;
|
|
547
|
+
} catch {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
export {
|
|
552
|
+
writeJsonFile,
|
|
553
|
+
writeAuthorityStateJson,
|
|
554
|
+
writeAuthorityProjectStateJson,
|
|
555
|
+
upsertAuthorityRemoteEndpoint,
|
|
556
|
+
updateAuthorityRemoteEndpoint,
|
|
557
|
+
resolveTaskArtifactDirs,
|
|
558
|
+
resolveAuthorityStateRoot,
|
|
559
|
+
resolveAuthorityStateDir,
|
|
560
|
+
resolveAuthorityRuntimeDir,
|
|
561
|
+
resolveAuthorityRunDir,
|
|
562
|
+
resolveAuthorityProjectStateDir,
|
|
563
|
+
resolveAuthorityPaths,
|
|
564
|
+
resolveAuthorityArtifactsRoot,
|
|
565
|
+
removeAuthorityRemoteEndpoint,
|
|
566
|
+
readJsonlFile,
|
|
567
|
+
readJsonFile,
|
|
568
|
+
readAuthorityStateJson,
|
|
569
|
+
readAuthorityRun,
|
|
570
|
+
readAuthorityProjectStateJson,
|
|
571
|
+
markAuthorityRemoteEndpointConnected,
|
|
572
|
+
listAuthorityRuntimeAgentsRoots,
|
|
573
|
+
listAuthorityRuns,
|
|
574
|
+
listAuthorityRunRoots,
|
|
575
|
+
listAuthorityRemoteEndpoints,
|
|
576
|
+
listAuthorityArtifactRoots,
|
|
577
|
+
importLegacyRemoteEndpoints,
|
|
578
|
+
fileSizeIfPresent,
|
|
579
|
+
doctorAuthorityRemoteEndpoints,
|
|
580
|
+
copyFileIfPresent,
|
|
581
|
+
appendJsonlRecord
|
|
582
|
+
};
|