@clipboard-health/groundcrew 4.0.3 → 4.1.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 +12 -4
- package/crew.config.example.ts +5 -18
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -7
- package/dist/commands/resumeWorkspace.d.ts.map +1 -1
- package/dist/commands/resumeWorkspace.js +1 -2
- package/dist/commands/setupWorkspace.d.ts.map +1 -1
- package/dist/commands/setupWorkspace.js +1 -7
- package/dist/lib/agentLaunch.d.ts +0 -6
- package/dist/lib/agentLaunch.d.ts.map +1 -1
- package/dist/lib/agentLaunch.js +1 -12
- package/dist/lib/cmuxAdapter.d.ts +8 -0
- package/dist/lib/cmuxAdapter.d.ts.map +1 -0
- package/dist/lib/cmuxAdapter.js +163 -0
- package/dist/lib/config.d.ts +2 -76
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +29 -102
- package/dist/lib/launchCommand.d.ts +3 -3
- package/dist/lib/sandboxName.d.ts +9 -0
- package/dist/lib/sandboxName.d.ts.map +1 -0
- package/dist/lib/sandboxName.js +12 -0
- package/dist/lib/tmuxAdapter.d.ts +9 -0
- package/dist/lib/tmuxAdapter.d.ts.map +1 -0
- package/dist/lib/tmuxAdapter.js +156 -0
- package/dist/lib/workspaceAdapter.d.ts +79 -0
- package/dist/lib/workspaceAdapter.d.ts.map +1 -0
- package/dist/lib/workspaceAdapter.js +17 -0
- package/dist/lib/workspaces.d.ts +7 -55
- package/dist/lib/workspaces.d.ts.map +1 -1
- package/dist/lib/workspaces.js +8 -404
- package/package.json +1 -2
- package/dist/commands/sandbox/auth.d.ts +0 -3
- package/dist/commands/sandbox/auth.d.ts.map +0 -1
- package/dist/commands/sandbox/auth.js +0 -227
- package/dist/commands/sandbox/index.d.ts +0 -2
- package/dist/commands/sandbox/index.d.ts.map +0 -1
- package/dist/commands/sandbox/index.js +0 -47
- package/dist/commands/sandbox/inspect.d.ts +0 -2
- package/dist/commands/sandbox/inspect.d.ts.map +0 -1
- package/dist/commands/sandbox/inspect.js +0 -18
- package/dist/commands/sandbox/lifecycle.d.ts +0 -7
- package/dist/commands/sandbox/lifecycle.d.ts.map +0 -1
- package/dist/commands/sandbox/lifecycle.js +0 -68
- package/dist/commands/sandbox/model.d.ts +0 -10
- package/dist/commands/sandbox/model.d.ts.map +0 -1
- package/dist/commands/sandbox/model.js +0 -37
- package/dist/commands/sandbox/picker.d.ts +0 -20
- package/dist/commands/sandbox/picker.d.ts.map +0 -1
- package/dist/commands/sandbox/picker.js +0 -23
- package/dist/lib/dockerSandbox.d.ts +0 -43
- package/dist/lib/dockerSandbox.d.ts.map +0 -1
- package/dist/lib/dockerSandbox.js +0 -69
- package/dist/lib/sandboxGitDefaults.d.ts +0 -10
- package/dist/lib/sandboxGitDefaults.d.ts.map +0 -1
- package/dist/lib/sandboxGitDefaults.js +0 -31
package/README.md
CHANGED
|
@@ -143,7 +143,7 @@ Resolution order: `GROUNDCREW_CONFIG` → cosmiconfig project-walk from cwd (any
|
|
|
143
143
|
| `models.definitions.<name>.cmd` | — | Shell command launched for the model. Runs in the worktree through the resolved `local.runner`. `{{worktree}}` is replaced before launch; `{{sandbox}}` expands to the sbx sandbox name under the sdx runner and an empty string otherwise. |
|
|
144
144
|
| `models.definitions.<name>.color` | — | Color for the workspace status pill (cmux only; tmux silently drops it). |
|
|
145
145
|
| `models.definitions.<name>.usage` | optional | If set, codexbar usage is fetched for this model and gated by `sessionLimitPercentage`. Falls back to default when unset, with gating enabled for known models. When `usage.codexbar.source` is omitted, groundcrew uses `oauth` for Codex/Claude on macOS, `auto` for other macOS providers, and `cli` elsewhere. Set to `{ disabled: true }` to disable usage gating. |
|
|
146
|
-
| `models.definitions.<name>.sandbox` | optional | Docker Sandboxes binding for the model. Required at launch when `local.runner` resolves to `sdx`. Fields: `agent` (required sbx agent name)
|
|
146
|
+
| `models.definitions.<name>.sandbox` | optional | Docker Sandboxes binding for the model. Required at launch when `local.runner` resolves to `sdx`. Fields: `agent` (required sbx agent name) and `setupCommand` (override for the inside-sandbox setup script). Groundcrew assumes the `groundcrew-<agent>` sandbox already exists. |
|
|
147
147
|
| `models.definitions.<name>.disabled` | optional | When set to exactly `true`, drops the named shipped default (`claude` or `codex`). Doctor skips probing it; `agent-<name>` labels fall back to `models.default` with a warning. |
|
|
148
148
|
| `prompts.initial` | unattended template | First message sent to the agent. Placeholders: `{{ticket}}`, `{{worktree}}`, `{{title}}`, `{{description}}`. Override this from `crew.config.ts` for team-specific statuses, tools, plugins, or review loops. |
|
|
149
149
|
| `workspaceKind` | `"auto"` | Terminal session manager. `"auto"` picks `cmux` when on PATH, else `tmux`. Set to `"cmux"` or `"tmux"` to fail loudly when the chosen backend is missing. |
|
|
@@ -188,9 +188,17 @@ Watch `${XDG_CACHE_HOME:-$HOME/.cache}/clearance/clearance.log` for `DENY` lines
|
|
|
188
188
|
<details>
|
|
189
189
|
<summary>Docker Sandboxes (sdx) setup</summary>
|
|
190
190
|
|
|
191
|
-
Each model that runs under `sdx` needs a `sandbox: { agent: "<sbx-agent>" }` block in `crew.config.ts`. Groundcrew
|
|
191
|
+
Each model that runs under `sdx` needs a `sandbox: { agent: "<sbx-agent>" }` block in `crew.config.ts`. Groundcrew addresses the sandbox as `groundcrew-<agent>` (e.g. `groundcrew-claude`) and reuses one existing sandbox per agent across repos and tickets.
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
First-time setup is manual:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
sbx create --name groundcrew-claude claude <projectDir>
|
|
197
|
+
sbx exec -it groundcrew-claude claude auth login
|
|
198
|
+
sbx exec -it groundcrew-claude gh auth login
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Replace `claude` with the sbx agent for the model and `<projectDir>` with `workspace.projectDir` from `crew.config.ts`. Manage lifecycle and auth with `sbx` directly (`sbx ls`, `sbx exec`, `sbx rm`). Groundcrew does not create, authenticate, regenerate, list, or remove sandboxes.
|
|
194
202
|
|
|
195
203
|
</details>
|
|
196
204
|
|
|
@@ -238,7 +246,7 @@ In Progress (state.type=started) — Multi-event extractor: year inference can p
|
|
|
238
246
|
|
|
239
247
|
### `crew start <TICKET>`
|
|
240
248
|
|
|
241
|
-
|
|
249
|
+
Launches one ticket immediately, bypassing orchestrator eligibility. Use it to dispatch a specific ticket on demand — including unlabeled tickets that `crew run` ignores. (Replaces the deprecated `crew run --ticket <TICKET>`.)
|
|
242
250
|
|
|
243
251
|
```bash
|
|
244
252
|
crew start HRD-442
|
package/crew.config.example.ts
CHANGED
|
@@ -73,24 +73,11 @@ export default {
|
|
|
73
73
|
// // macOS when you need an agent to use Docker safely.
|
|
74
74
|
// local: { runner: "auto" },
|
|
75
75
|
//
|
|
76
|
-
// //
|
|
77
|
-
// //
|
|
78
|
-
// //
|
|
79
|
-
// //
|
|
80
|
-
// //
|
|
81
|
-
// // tools that should appear in every sandbox's picker; set
|
|
82
|
-
// // `kind: "agent"` to scope a recipe to a single sbx agent.
|
|
83
|
-
// sandbox: {
|
|
84
|
-
// authRecipes: {
|
|
85
|
-
// gcloud: {
|
|
86
|
-
// displayName: "gcloud",
|
|
87
|
-
// binary: "gcloud",
|
|
88
|
-
// loginArgs: ["auth", "login", "--no-launch-browser"],
|
|
89
|
-
// statusArgs: ["auth", "list", "--filter=status:ACTIVE", "--format=value(account)"],
|
|
90
|
-
// authenticatedPattern: /@/,
|
|
91
|
-
// },
|
|
92
|
-
// },
|
|
93
|
-
// },
|
|
76
|
+
// // Groundcrew does not create or authenticate sdx sandboxes. For an sdx
|
|
77
|
+
// // model, create the matching sandbox yourself before first launch:
|
|
78
|
+
// // sbx create --name groundcrew-claude claude ~/dev/groundcrew
|
|
79
|
+
// // sbx exec -it groundcrew-claude claude auth login
|
|
80
|
+
// // sbx exec -it groundcrew-claude gh auth login
|
|
94
81
|
//
|
|
95
82
|
// prompts: {
|
|
96
83
|
// // Keep personal workflow instructions next to this config, for example
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAuQA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CvD"}
|
package/dist/cli.js
CHANGED
|
@@ -5,7 +5,6 @@ import { initConfigCli } from "./commands/init.js";
|
|
|
5
5
|
import { interruptWorkspaceCli } from "./commands/interruptWorkspace.js";
|
|
6
6
|
import { orchestrate } from "./commands/orchestrator.js";
|
|
7
7
|
import { resumeWorkspaceCli } from "./commands/resumeWorkspace.js";
|
|
8
|
-
import { sandboxCli } from "./commands/sandbox/index.js";
|
|
9
8
|
import { setupReposCli } from "./commands/setupRepos.js";
|
|
10
9
|
import { setupWorkspaceCli } from "./commands/setupWorkspace.js";
|
|
11
10
|
import { statusCli } from "./commands/status.js";
|
|
@@ -14,6 +13,11 @@ import { computeUpgradeNudge, defaultUpgradeCheckCachePath, fetchLatestVersion,
|
|
|
14
13
|
import { errorMessage, parseDryRunPositionals, readEnvironmentVariable, readTicketArgument, writeError, writeOutput, } from "./lib/util.js";
|
|
15
14
|
const NUDGE_TTL_MS = 6 * 60 * 60 * 1000;
|
|
16
15
|
const NUDGE_FETCH_TIMEOUT_MS = 1000;
|
|
16
|
+
const REMOVED_SANDBOX_COMMAND_MESSAGE = [
|
|
17
|
+
"`crew sandbox` is no longer supported.",
|
|
18
|
+
"Groundcrew now launches agents inside existing sbx sandboxes but does not list, create, regenerate, authenticate, or remove them.",
|
|
19
|
+
"Use the manual `sbx` workflow in README.md#docker-sandboxes-sdx-setup, then keep `models.definitions.<model>.sandbox.agent` in crew.config.ts so launches can address the existing sandbox.",
|
|
20
|
+
].join("\n");
|
|
17
21
|
const requireFromCli = createRequire(import.meta.url);
|
|
18
22
|
/**
|
|
19
23
|
* Prints a deprecation warning to stderr naming the canonical command and that
|
|
@@ -132,7 +136,7 @@ const SUBCOMMANDS = {
|
|
|
132
136
|
invoke: runCli,
|
|
133
137
|
},
|
|
134
138
|
start: {
|
|
135
|
-
summary: "
|
|
139
|
+
summary: "Launch one ticket immediately, bypassing eligibility",
|
|
136
140
|
usage: "<ticket> [--dry-run]",
|
|
137
141
|
invoke: startCli,
|
|
138
142
|
},
|
|
@@ -170,11 +174,6 @@ const SUBCOMMANDS = {
|
|
|
170
174
|
usage: "<ticket>",
|
|
171
175
|
invoke: resumeWorkspaceCli,
|
|
172
176
|
},
|
|
173
|
-
sandbox: {
|
|
174
|
-
summary: "Manage Docker Sandboxes (sbx) for configured models",
|
|
175
|
-
usage: "<list|ensure|regenerate|auth|rm> [...args]",
|
|
176
|
-
invoke: sandboxCli,
|
|
177
|
-
},
|
|
178
177
|
setup: {
|
|
179
178
|
summary: "Project-level setup commands (currently: repos)",
|
|
180
179
|
usage: "repos [--dry-run] [<repo>...]",
|
|
@@ -224,6 +223,11 @@ export async function run(argv) {
|
|
|
224
223
|
writeOutput(packageVersion());
|
|
225
224
|
return;
|
|
226
225
|
}
|
|
226
|
+
if (subcommand === "sandbox") {
|
|
227
|
+
writeError(REMOVED_SANDBOX_COMMAND_MESSAGE);
|
|
228
|
+
process.exitCode = 1;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
227
231
|
const command = SUBCOMMANDS[subcommand];
|
|
228
232
|
if (!command) {
|
|
229
233
|
writeError(`Unknown command: ${subcommand}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAcnE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AA6HD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAcnE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB;AA6HD,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchResolvedIssue } from "../lib/boardSource.js";
|
|
2
2
|
import { loadConfig } from "../lib/config.js";
|
|
3
|
-
import {
|
|
3
|
+
import { openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
|
|
4
4
|
import { buildLaunchCommand } from "../lib/launchCommand.js";
|
|
5
5
|
import { readRunState, recordRunState } from "../lib/runState.js";
|
|
6
6
|
import { removeStagedPrompt, stageBuildSecrets, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
|
|
@@ -117,7 +117,6 @@ export async function resumeWorkspace(config, options) {
|
|
|
117
117
|
text: renderResumePrompt(context),
|
|
118
118
|
});
|
|
119
119
|
const secretsFile = stageBuildSecrets(stagedPrompt.directory);
|
|
120
|
-
await ensureAgentSandbox({ config, definition, sandboxName });
|
|
121
120
|
const launchCommand = buildLaunchCommand({
|
|
122
121
|
definition,
|
|
123
122
|
promptFile: stagedPrompt.file,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAenE,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAWD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAqBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAenE,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAWD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAqBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CAsGf;AAwHD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CAoBf"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { rmSync } from "node:fs";
|
|
2
2
|
import { fetchResolvedIssue } from "../lib/boardSource.js";
|
|
3
3
|
import { loadConfig } from "../lib/config.js";
|
|
4
|
-
import {
|
|
4
|
+
import { openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
|
|
5
5
|
import { buildLaunchCommand } from "../lib/launchCommand.js";
|
|
6
6
|
import { createLinearIssueStatusUpdater } from "../lib/linearIssueStatus.js";
|
|
7
7
|
import { recordRunState } from "../lib/runState.js";
|
|
@@ -80,12 +80,6 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
80
80
|
const stagedPrompt = stagePrompt({ config, ticket, ticketDetails, worktreeName });
|
|
81
81
|
promptDir = stagedPrompt.directory;
|
|
82
82
|
const secretsFile = stageBuildSecrets(promptDir);
|
|
83
|
-
await ensureAgentSandbox({
|
|
84
|
-
config,
|
|
85
|
-
definition,
|
|
86
|
-
sandboxName,
|
|
87
|
-
...(signal === undefined ? {} : { signal }),
|
|
88
|
-
});
|
|
89
83
|
const launchCommand = buildLaunchCommand({
|
|
90
84
|
definition,
|
|
91
85
|
promptFile: stagedPrompt.file,
|
|
@@ -10,12 +10,6 @@ export declare function prepareAgentLaunch(input: {
|
|
|
10
10
|
purpose: "runs" | "resumes";
|
|
11
11
|
signal?: AbortSignal;
|
|
12
12
|
}): Promise<PreparedAgentLaunch>;
|
|
13
|
-
export declare function ensureAgentSandbox(input: {
|
|
14
|
-
config: ResolvedConfig;
|
|
15
|
-
definition: ModelDefinition;
|
|
16
|
-
sandboxName: string | undefined;
|
|
17
|
-
signal?: AbortSignal;
|
|
18
|
-
}): Promise<void>;
|
|
19
13
|
export declare function openAgentWorkspace(input: {
|
|
20
14
|
config: ResolvedConfig;
|
|
21
15
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOhF,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,eAAe,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6B/B;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUhB"}
|
package/dist/lib/agentLaunch.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
1
|
import { ensureClearance } from "@clipboard-health/clearance";
|
|
3
|
-
import { ensureSandbox, sandboxNameFor } from "./dockerSandbox.js";
|
|
4
2
|
import { detectHostCapabilities } from "./host.js";
|
|
5
3
|
import { assertLocalRunnerRequirements, resolveLocalRunner } from "./localRunner.js";
|
|
4
|
+
import { sandboxNameFor } from "./sandboxName.js";
|
|
6
5
|
import { log, sleep } from "./util.js";
|
|
7
6
|
import { workspaces } from "./workspaces.js";
|
|
8
7
|
export async function prepareAgentLaunch(input) {
|
|
@@ -31,16 +30,6 @@ export async function prepareAgentLaunch(input) {
|
|
|
31
30
|
: undefined;
|
|
32
31
|
return { runner, sandboxName };
|
|
33
32
|
}
|
|
34
|
-
export async function ensureAgentSandbox(input) {
|
|
35
|
-
if (input.sandboxName !== undefined && input.definition.sandbox !== undefined) {
|
|
36
|
-
await ensureSandbox({
|
|
37
|
-
sandboxName: input.sandboxName,
|
|
38
|
-
sandbox: input.definition.sandbox,
|
|
39
|
-
mountPath: resolve(input.config.workspace.projectDir),
|
|
40
|
-
gitDefaults: input.config.sandbox.gitDefaults,
|
|
41
|
-
}, input.signal);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
33
|
export async function openAgentWorkspace(input) {
|
|
45
34
|
const spec = {
|
|
46
35
|
name: input.name,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cmux Workspace backend. cmux is the macOS TUI; workspaces surface in its
|
|
3
|
+
* own app, so `accessHint` has nothing concise to emit. cmux can paint a
|
|
4
|
+
* per-workspace status pill, which `open` applies best-effort.
|
|
5
|
+
*/
|
|
6
|
+
import { type Adapter } from "./workspaceAdapter.ts";
|
|
7
|
+
export declare const cmuxAdapter: Adapter;
|
|
8
|
+
//# sourceMappingURL=cmuxAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cmuxAdapter.d.ts","sourceRoot":"","sources":["../../src/lib/cmuxAdapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,OAAO,EAIb,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,WAAW,EAAE,OA6EzB,CAAC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* cmux Workspace backend. cmux is the macOS TUI; workspaces surface in its
|
|
3
|
+
* own app, so `accessHint` has nothing concise to emit. cmux can paint a
|
|
4
|
+
* per-workspace status pill, which `open` applies best-effort.
|
|
5
|
+
*/
|
|
6
|
+
import { isSignalAborted, runWorkspaceCommand, } from "./workspaceAdapter.js";
|
|
7
|
+
import { errorMessage, log } from "./util.js";
|
|
8
|
+
export const cmuxAdapter = {
|
|
9
|
+
async open(spec, signal) {
|
|
10
|
+
const output = await runWorkspaceCommand("cmux", [
|
|
11
|
+
"--json",
|
|
12
|
+
"new-workspace",
|
|
13
|
+
"--name",
|
|
14
|
+
spec.name,
|
|
15
|
+
"--cwd",
|
|
16
|
+
spec.cwd,
|
|
17
|
+
"--command",
|
|
18
|
+
spec.command,
|
|
19
|
+
], signal);
|
|
20
|
+
const workspaceId = extractCmuxOpenId(output);
|
|
21
|
+
if (workspaceId === undefined) {
|
|
22
|
+
log(`cmux new-workspace returned unrecognized output for ${spec.name}; if a workspace was created, run \`cmux close-workspace\` manually.`);
|
|
23
|
+
throw new Error(`Unexpected cmux output: ${output}`);
|
|
24
|
+
}
|
|
25
|
+
if (spec.status !== undefined) {
|
|
26
|
+
try {
|
|
27
|
+
await applyCmuxStatus(workspaceId, spec.status, signal);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
// Status pills are best-effort. cmux v2+ dropped `set-status` entirely,
|
|
31
|
+
// so swallow that specific gap silently; surface anything else so a real
|
|
32
|
+
// regression doesn't hide behind the same swallow.
|
|
33
|
+
if (!isCmuxSetStatusUnsupported(error)) {
|
|
34
|
+
log(`cmux set-status failed for ${spec.name} (continuing): ${errorMessage(error)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
async list(signal) {
|
|
40
|
+
const raw = await listCmuxRaw(signal);
|
|
41
|
+
return raw?.map((ws) => ({ name: ws.title }));
|
|
42
|
+
},
|
|
43
|
+
async close(name, signal) {
|
|
44
|
+
const raw = await listCmuxRaw(signal);
|
|
45
|
+
if (raw === undefined) {
|
|
46
|
+
// cmux v2 `workspace.close` rejects titles, so forwarding `name`
|
|
47
|
+
// would always fail. The list failure has already been logged by
|
|
48
|
+
// `listCmuxRaw`; bail rather than guarantee a downstream error.
|
|
49
|
+
log(`cmux close-workspace skipped for ${name}: list-workspaces failed, no usable id`);
|
|
50
|
+
return { kind: "unavailable" };
|
|
51
|
+
}
|
|
52
|
+
const match = raw.find((ws) => ws.title === name);
|
|
53
|
+
if (match === undefined) {
|
|
54
|
+
return { kind: "missing" };
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await closeCmuxWorkspace(match.id, signal);
|
|
58
|
+
return { kind: "closed" };
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (isSignalAborted(signal)) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
const remaining = await listCmuxRaw(signal);
|
|
65
|
+
if (remaining === undefined) {
|
|
66
|
+
return { kind: "unavailable", error };
|
|
67
|
+
}
|
|
68
|
+
const isStillPresent = remaining.some((ws) => ws.title === name);
|
|
69
|
+
if (!isStillPresent) {
|
|
70
|
+
return { kind: "closed" };
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
accessHint(_name) {
|
|
76
|
+
// cmux is a TUI; users surface workspaces by launching the cmux app,
|
|
77
|
+
// not a shell command. No useful hint to emit.
|
|
78
|
+
// oxlint-disable-next-line unicorn/no-useless-undefined -- explicit signal that the backend has no hint
|
|
79
|
+
return undefined;
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
function parseCmuxList(output) {
|
|
83
|
+
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- cmux --json list-workspaces always emits this shape
|
|
84
|
+
const parsed = JSON.parse(output);
|
|
85
|
+
const items = [];
|
|
86
|
+
/* v8 ignore next @preserve -- cmux always emits a workspaces field; default keeps the loop safe */
|
|
87
|
+
for (const ws of parsed.workspaces ?? []) {
|
|
88
|
+
if (typeof ws.title !== "string" || ws.title.length === 0) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const id = pickCmuxId(ws);
|
|
92
|
+
if (id === undefined) {
|
|
93
|
+
log(`cmux list-workspaces returned workspace "${ws.title}" without a usable id or ref; skipping`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
items.push({ title: ws.title, id });
|
|
97
|
+
}
|
|
98
|
+
return items;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The stable workspace handle cmux v2 expects in JSON-RPC params. Prefer
|
|
102
|
+
* the UUID; fall back to the legacy `workspace:N` short ref when older
|
|
103
|
+
* cmux builds don't surface it. Returns `undefined` when neither is
|
|
104
|
+
* available — cmux v2 `workspace.close` rejects titles, so we must never
|
|
105
|
+
* forward `title` as a workspace handle.
|
|
106
|
+
*/
|
|
107
|
+
function pickCmuxId(ws) {
|
|
108
|
+
if (typeof ws.id === "string" && ws.id.length > 0) {
|
|
109
|
+
return ws.id;
|
|
110
|
+
}
|
|
111
|
+
if (typeof ws.ref === "string" && ws.ref.length > 0) {
|
|
112
|
+
return ws.ref;
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
async function listCmuxRaw(signal) {
|
|
117
|
+
try {
|
|
118
|
+
return parseCmuxList(await runWorkspaceCommand("cmux", ["--json", "list-workspaces"], signal));
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
if (isSignalAborted(signal)) {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
log(`cmux list-workspaces failed: ${errorMessage(error)}`);
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function extractCmuxOpenId(output) {
|
|
129
|
+
try {
|
|
130
|
+
// oxlint-disable-next-line typescript/no-unsafe-type-assertion -- cmux --json prints a workspace_id/ref object
|
|
131
|
+
const parsed = JSON.parse(output);
|
|
132
|
+
const uuid = parsed.workspace_id ?? parsed.id ?? "";
|
|
133
|
+
if (uuid.length > 0) {
|
|
134
|
+
return uuid;
|
|
135
|
+
}
|
|
136
|
+
const ref = parsed.workspace_ref ?? parsed.ref ?? "";
|
|
137
|
+
if (ref.length > 0) {
|
|
138
|
+
return ref;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
/* not JSON; fall through to regex */
|
|
143
|
+
}
|
|
144
|
+
const match = /workspace:\d+/.exec(output);
|
|
145
|
+
return match ? match[0] : undefined;
|
|
146
|
+
}
|
|
147
|
+
async function applyCmuxStatus(workspaceId, status, signal) {
|
|
148
|
+
const arguments_ = ["set-status", "model", status.text];
|
|
149
|
+
if (status.icon !== undefined) {
|
|
150
|
+
arguments_.push("--icon", status.icon);
|
|
151
|
+
}
|
|
152
|
+
if (status.color !== undefined) {
|
|
153
|
+
arguments_.push("--color", status.color);
|
|
154
|
+
}
|
|
155
|
+
arguments_.push("--workspace", workspaceId);
|
|
156
|
+
await runWorkspaceCommand("cmux", arguments_, signal);
|
|
157
|
+
}
|
|
158
|
+
async function closeCmuxWorkspace(workspaceId, signal) {
|
|
159
|
+
await runWorkspaceCommand("cmux", ["close-workspace", "--workspace", workspaceId], signal);
|
|
160
|
+
}
|
|
161
|
+
function isCmuxSetStatusUnsupported(error) {
|
|
162
|
+
return errorMessage(error).includes('unknown command "set-status"');
|
|
163
|
+
}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -41,16 +41,12 @@ export type LocalRunnerSetting = LocalRunner | "auto";
|
|
|
41
41
|
export declare const LOCAL_RUNNER_SETTINGS: readonly LocalRunnerSetting[];
|
|
42
42
|
/**
|
|
43
43
|
* Per-model Docker Sandboxes (sdx) binding. Required at launch when
|
|
44
|
-
* `local.runner` resolves to `sdx` so groundcrew knows which
|
|
45
|
-
*
|
|
44
|
+
* `local.runner` resolves to `sdx` so groundcrew knows which existing
|
|
45
|
+
* sbx sandbox to address.
|
|
46
46
|
*/
|
|
47
47
|
export interface SandboxDefinition {
|
|
48
48
|
/** sbx agent name (e.g. "claude", "codex"). */
|
|
49
49
|
agent: string;
|
|
50
|
-
/** Optional `sbx run --template` value. */
|
|
51
|
-
template?: string;
|
|
52
|
-
/** Optional `sbx run --kit` values (each passed as a separate flag). */
|
|
53
|
-
kits?: string[];
|
|
54
50
|
/**
|
|
55
51
|
* Setup command run **inside** the sandbox before the agent exec.
|
|
56
52
|
* Defaults to the shared `.groundcrew/setup.sh --deps-only` convention
|
|
@@ -58,42 +54,6 @@ export interface SandboxDefinition {
|
|
|
58
54
|
*/
|
|
59
55
|
setupCommand?: string;
|
|
60
56
|
}
|
|
61
|
-
/**
|
|
62
|
-
* Recipe used by `crew sandbox auth <model>` to drive an interactive
|
|
63
|
-
* login flow inside a sbx sandbox and then verify it. The flow is
|
|
64
|
-
* picker-driven — no positional `<tool>` argument; the picker lists
|
|
65
|
-
* every recipe visible to the current sandbox.
|
|
66
|
-
*
|
|
67
|
-
* `binary` defaults to the recipe key (typically the agent or CLI name).
|
|
68
|
-
* `authenticatedPattern` matches against combined stdout+stderr from
|
|
69
|
-
* `statusArgs` — exit code alone isn't reliable because some CLIs
|
|
70
|
-
* report "not logged in" while still exiting 0.
|
|
71
|
-
* `kind` controls visibility in the interactive picker: `"agent"`
|
|
72
|
-
* recipes are scoped to a specific sbx agent and only appear when you
|
|
73
|
-
* `auth` against that agent's sandbox; `"tool"` recipes (default)
|
|
74
|
-
* appear in every sandbox's picker because they're cross-cutting
|
|
75
|
-
* (github, npm, gcloud, …). Defaults to `"tool"` when omitted.
|
|
76
|
-
*
|
|
77
|
-
* Ship-side recipes for `claude`, `codex`, and `cursor` live in
|
|
78
|
-
* `src/commands/sandbox/auth.ts`; users register additional tools
|
|
79
|
-
* under `sandbox.authRecipes` in their config.
|
|
80
|
-
*/
|
|
81
|
-
export interface AuthRecipe {
|
|
82
|
-
displayName: string;
|
|
83
|
-
binary?: string;
|
|
84
|
-
loginArgs: readonly string[];
|
|
85
|
-
statusArgs: readonly string[];
|
|
86
|
-
authenticatedPattern: RegExp;
|
|
87
|
-
kind?: "agent" | "tool";
|
|
88
|
-
/**
|
|
89
|
-
* Environment variables passed to `sbx exec` for both the login and
|
|
90
|
-
* status calls. Use this for CLIs whose default flow assumes a
|
|
91
|
-
* browser or other host-only feature — e.g. cursor-agent wants
|
|
92
|
-
* `NO_OPEN_BROWSER=1` to print a device code instead of trying to
|
|
93
|
-
* launch a browser inside the sandbox.
|
|
94
|
-
*/
|
|
95
|
-
env?: Record<string, string>;
|
|
96
|
-
}
|
|
97
57
|
export interface ModelDefinition {
|
|
98
58
|
/**
|
|
99
59
|
* Shell command launched for the model. Wrapped with Safehouse/clearance
|
|
@@ -201,32 +161,6 @@ export interface Config {
|
|
|
201
161
|
local?: {
|
|
202
162
|
runner?: LocalRunnerSetting;
|
|
203
163
|
};
|
|
204
|
-
/**
|
|
205
|
-
* Sandbox-wide settings. `authRecipes` lets users register additional
|
|
206
|
-
* tools (github, npm, gcloud, …) for `crew sandbox auth <model>` to
|
|
207
|
-
* authenticate inside the sandbox. The auth flow is picker-driven —
|
|
208
|
-
* registered recipes show up in the picker alongside the shipped ones,
|
|
209
|
-
* and a user recipe under the same key (e.g. "claude") overrides the
|
|
210
|
-
* shipped one.
|
|
211
|
-
*/
|
|
212
|
-
sandbox?: {
|
|
213
|
-
authRecipes?: Record<string, AuthRecipe>;
|
|
214
|
-
/**
|
|
215
|
-
* When true (default), every `crew sandbox ensure` / `auth` run applies
|
|
216
|
-
* a small set of git defaults inside the sandbox so robot commits push
|
|
217
|
-
* over `gh`-managed HTTPS regardless of how the user cloned the repo:
|
|
218
|
-
*
|
|
219
|
-
* - disable GPG signing for commits and tags
|
|
220
|
-
* - rewrite `git@github.com:` and `ssh://git@github.com/` URLs to
|
|
221
|
-
* `https://github.com/` so push uses gh's credential helper
|
|
222
|
-
* - after a successful `github` auth recipe login, run
|
|
223
|
-
* `gh auth setup-git` inside the sandbox
|
|
224
|
-
*
|
|
225
|
-
* Set `false` to skip both the git-config block and the post-login
|
|
226
|
-
* `gh auth setup-git` step.
|
|
227
|
-
*/
|
|
228
|
-
gitDefaults?: boolean;
|
|
229
|
-
};
|
|
230
164
|
logging?: {
|
|
231
165
|
/**
|
|
232
166
|
* Append-mode log file destination. `log()` and `logEvent()` tee here
|
|
@@ -281,14 +215,6 @@ export interface ResolvedConfig {
|
|
|
281
215
|
local: {
|
|
282
216
|
runner: LocalRunnerSetting;
|
|
283
217
|
};
|
|
284
|
-
/**
|
|
285
|
-
* Sandbox-wide settings. Always present after defaults; `authRecipes`
|
|
286
|
-
* is `{}` when the user provides none.
|
|
287
|
-
*/
|
|
288
|
-
sandbox: {
|
|
289
|
-
authRecipes: Record<string, AuthRecipe>;
|
|
290
|
-
gitDefaults: boolean;
|
|
291
|
-
};
|
|
292
218
|
logging: {
|
|
293
219
|
file: string;
|
|
294
220
|
};
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAIrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5D,eAAO,MAAM,uBAAuB,EAAE,SAAS,oBAAoB,EAIzD,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,KAAK,GAAG,MAAM,CAAC;AAEvD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEtD,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAKrD,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|