@clipboard-health/groundcrew 4.5.0 → 4.7.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 +60 -483
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +23 -3
- package/dist/commands/dispatcher.d.ts.map +1 -1
- package/dist/commands/dispatcher.js +17 -8
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +24 -8
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +181 -14
- package/dist/commands/resumeWorkspace.d.ts.map +1 -1
- package/dist/commands/resumeWorkspace.js +2 -1
- package/dist/commands/setupWorkspace.d.ts.map +1 -1
- package/dist/commands/setupWorkspace.js +26 -11
- package/dist/commands/teardownReporter.js +4 -4
- package/dist/lib/adapters/linear/fetch.d.ts.map +1 -1
- package/dist/lib/adapters/linear/fetch.js +4 -4
- package/dist/lib/adapters/linear/writeback.js +2 -2
- package/dist/lib/adapters/shell/invoke.js +2 -2
- package/dist/lib/agentLaunch.d.ts +1 -0
- package/dist/lib/agentLaunch.d.ts.map +1 -1
- package/dist/lib/agentLaunch.js +24 -16
- package/dist/lib/cmuxAdapter.js +5 -5
- package/dist/lib/config.js +2 -2
- package/dist/lib/localRunner.d.ts.map +1 -1
- package/dist/lib/localRunner.js +2 -2
- package/dist/lib/runStateCleanup.js +2 -2
- package/dist/lib/tmuxAdapter.js +2 -2
- package/dist/lib/usage.d.ts.map +1 -1
- package/dist/lib/usage.js +7 -5
- package/dist/lib/util.d.ts +13 -0
- package/dist/lib/util.d.ts.map +1 -1
- package/dist/lib/util.js +54 -5
- package/dist/lib/worktrees.d.ts.map +1 -1
- package/dist/lib/worktrees.js +30 -20
- package/docs/adr/0001-groundcrew-uses-but-does-not-provision-sandboxes.md +17 -0
- package/docs/adr/0002-one-ticket-source-path-linear-is-an-adapter.md +17 -0
- package/docs/commands.md +68 -0
- package/docs/configuration.md +121 -0
- package/docs/credentials.md +81 -0
- package/docs/runners.md +45 -0
- package/docs/setup-hook-agent-prompt.md +62 -0
- package/docs/setup-hooks.md +46 -0
- package/docs/ticket-sources.md +45 -0
- package/docs/troubleshooting.md +48 -0
- package/package.json +2 -1
- package/static/demo.gif +0 -0
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { resumeWorkspaceCli } from "./commands/resumeWorkspace.js";
|
|
|
8
8
|
import { setupWorkspaceCli } from "./commands/setupWorkspace.js";
|
|
9
9
|
import { statusCli } from "./commands/status.js";
|
|
10
10
|
import { createDefaultUpgradeCliOptions, upgradeCli } from "./commands/upgrade.js";
|
|
11
|
-
import { errorMessage, parseDryRunPositionals, readTicketArgument, writeError, writeOutput, } from "./lib/util.js";
|
|
11
|
+
import { errorMessage, parseDryRunPositionals, readEnvironmentVariable, readTicketArgument, setVerbose, writeError, writeOutput, } from "./lib/util.js";
|
|
12
12
|
const REMOVED_SANDBOX_COMMAND_MESSAGE = [
|
|
13
13
|
"`crew sandbox` is no longer supported.",
|
|
14
14
|
"Groundcrew now launches agents inside existing sbx sandboxes but does not list, create, regenerate, authenticate, or remove them.",
|
|
@@ -110,7 +110,7 @@ async function doctorCli(argv) {
|
|
|
110
110
|
const SUBCOMMANDS = {
|
|
111
111
|
init: {
|
|
112
112
|
summary: "Create a crew.config.ts in the cwd (or --global into the XDG config dir)",
|
|
113
|
-
usage: "[--global | --local] [--force] [--dry-run]",
|
|
113
|
+
usage: "[--global | --local] [--force] [--dry-run] [--project-dir <dir>] [--repo <repo>]... [--runner <runner>] [--model <model>]",
|
|
114
114
|
invoke: initConfigCli,
|
|
115
115
|
},
|
|
116
116
|
run: {
|
|
@@ -176,6 +176,7 @@ function printHelp() {
|
|
|
176
176
|
writeOutput("Options:");
|
|
177
177
|
writeOutput(" -h, --help Show help");
|
|
178
178
|
writeOutput(" -v, --version Print version");
|
|
179
|
+
writeOutput(" --verbose Show diagnostic output (or set GROUNDCREW_VERBOSE)");
|
|
179
180
|
writeOutput("");
|
|
180
181
|
writeOutput("Commands:");
|
|
181
182
|
for (const [name, command] of visibleCommands) {
|
|
@@ -192,8 +193,27 @@ function packageMetadata() {
|
|
|
192
193
|
function packageVersion() {
|
|
193
194
|
return packageMetadata().version;
|
|
194
195
|
}
|
|
196
|
+
const VERBOSE_FLAG = "--verbose";
|
|
197
|
+
function environmentVerbose() {
|
|
198
|
+
const raw = readEnvironmentVariable("GROUNDCREW_VERBOSE");
|
|
199
|
+
return raw !== undefined && raw !== "" && raw !== "0" && raw.toLowerCase() !== "false";
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Pulls the global `--verbose` flag out of argv before subcommand dispatch so
|
|
203
|
+
* every command supports it and the strict per-command parsers never see it.
|
|
204
|
+
* GROUNDCREW_VERBOSE enables it without the flag.
|
|
205
|
+
*/
|
|
206
|
+
function extractVerbose(argv) {
|
|
207
|
+
const commandArgv = argv.filter((argument) => argument !== VERBOSE_FLAG);
|
|
208
|
+
const verbose = commandArgv.length !== argv.length || environmentVerbose();
|
|
209
|
+
return { verbose, commandArgv };
|
|
210
|
+
}
|
|
195
211
|
export async function run(argv) {
|
|
196
|
-
const
|
|
212
|
+
const { verbose, commandArgv } = extractVerbose(argv);
|
|
213
|
+
if (verbose) {
|
|
214
|
+
setVerbose(true);
|
|
215
|
+
}
|
|
216
|
+
const [subcommand, ...rest] = commandArgv;
|
|
197
217
|
if (subcommand === undefined || subcommand === "-h" || subcommand === "--help") {
|
|
198
218
|
printHelp();
|
|
199
219
|
if (subcommand === undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/commands/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EACL,KAAK,UAAU,EAGf,KAAK,KAAK,EAEX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAWzD,UAAU,cAAc;IACtB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,UAAU,EAAE;QAClB,KAAK,EAAE,UAAU,CAAC;QAClB,eAAe,EAAE,SAAS,aAAa,EAAE,CAAC;QAC1C,+FAA+F;QAC/F,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACvD,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB;;;;WAIG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/commands/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EACL,KAAK,UAAU,EAGf,KAAK,KAAK,EAEX,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAWzD,UAAU,cAAc;IACtB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC;CACd;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,UAAU,EAAE;QAClB,KAAK,EAAE,UAAU,CAAC;QAClB,eAAe,EAAE,SAAS,aAAa,EAAE,CAAC;QAC1C,+FAA+F;QAC/F,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;QACvD,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB;;;;WAIG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAwNjE;AAsBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAQrE"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { dispatchableRepository } from "../lib/repositoryValidation.js";
|
|
10
10
|
import { isGroundcrewIssue, naturalIdFromCanonical, } from "../lib/ticketSource.js";
|
|
11
|
-
import { errorMessage, log, logEvent } from "../lib/util.js";
|
|
11
|
+
import { errorMessage, failMark, log, logEvent } from "../lib/util.js";
|
|
12
12
|
import { workspaces } from "../lib/workspaces.js";
|
|
13
13
|
import { classifyBlockers, classifyEligibility, classifyUsageExhaustion, } from "./eligibility.js";
|
|
14
14
|
import { setupWorkspace } from "./setupWorkspace.js";
|
|
@@ -79,7 +79,7 @@ export function createDispatcher(deps) {
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
catch (error) {
|
|
82
|
-
log(
|
|
82
|
+
log(`${failMark()} Failed to start ${ticketId}: ${errorMessage(error)}`);
|
|
83
83
|
logEvent("dispatch", {
|
|
84
84
|
outcome: "failed",
|
|
85
85
|
ticket: ticketId,
|
|
@@ -145,18 +145,21 @@ export function createDispatcher(deps) {
|
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
147
|
// usage() is an HTTP call; workspaces.probe shells tmux/cmux. Kick off
|
|
148
|
-
// usage first so
|
|
148
|
+
// usage first so any necessary workspace probe can overlap with the
|
|
149
|
+
// in-flight request.
|
|
149
150
|
const usagePromise = usage(signal);
|
|
150
151
|
// Snapshot live workspace names once per iteration so eligibility can
|
|
151
152
|
// distinguish "worktree exists AND its agent is still running" (resume)
|
|
152
153
|
// from "worktree exists but the workspace is gone" (ambiguous — don't
|
|
153
|
-
// auto-recover).
|
|
154
|
-
//
|
|
154
|
+
// auto-recover). Skip the shell-out entirely for fresh-start-only ticks:
|
|
155
|
+
// if none of the candidates has a matching worktree, classifyRecovery()
|
|
156
|
+
// will never read the probe.
|
|
155
157
|
let workspaceProbe;
|
|
156
158
|
try {
|
|
157
|
-
workspaceProbe =
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
workspaceProbe =
|
|
160
|
+
dryRun || !hasRecoverableCandidate(dispatchableUnblocked, worktreeEntries)
|
|
161
|
+
? { kind: "ok", names: new Set() }
|
|
162
|
+
: await workspaces.probe(config, signal);
|
|
160
163
|
}
|
|
161
164
|
catch (error) {
|
|
162
165
|
usagePromise.catch(() => "ignored");
|
|
@@ -196,6 +199,12 @@ export function createDispatcher(deps) {
|
|
|
196
199
|
}
|
|
197
200
|
return { runOnce };
|
|
198
201
|
}
|
|
202
|
+
function hasRecoverableCandidate(issues, worktreeEntries) {
|
|
203
|
+
return issues.some((issue) => {
|
|
204
|
+
const naturalId = naturalIdFromCanonical(issue.id);
|
|
205
|
+
return worktreeEntries.some((entry) => entry.repository === issue.repository && entry.ticket === naturalId);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
199
208
|
function formatUsageExhaustion(exhaustion) {
|
|
200
209
|
if (exhaustion.kind === "session") {
|
|
201
210
|
const mins = exhaustion.resetMinutes ?? "?";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyKH,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CA8E/C"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -14,6 +14,7 @@ import { resolveWorkspaceKind } from "../lib/workspaces.js";
|
|
|
14
14
|
// Tokenization stops after this many non-flag tokens. Two is enough to
|
|
15
15
|
// catch wrapper + wrapped CLI commands like `safehouse claude --foo`.
|
|
16
16
|
const MAX_TOKENS_PER_CMD = 2;
|
|
17
|
+
const SHIPPED_DEFAULT_MODEL_NAMES = ["claude", "codex"];
|
|
17
18
|
async function checkCmd(cmd, required, hint) {
|
|
18
19
|
const path = await which(cmd);
|
|
19
20
|
const resolvedHint = path ?? hint;
|
|
@@ -103,14 +104,29 @@ function commandTokensToCheck(cmd) {
|
|
|
103
104
|
}
|
|
104
105
|
return result;
|
|
105
106
|
}
|
|
106
|
-
function
|
|
107
|
-
const all = new
|
|
108
|
-
for (const definition of Object.
|
|
107
|
+
function gatherToolTargets(config) {
|
|
108
|
+
const all = new Map();
|
|
109
|
+
for (const [modelName, definition] of Object.entries(config.models.definitions)) {
|
|
109
110
|
for (const token of commandTokensToCheck(definition.cmd)) {
|
|
110
|
-
|
|
111
|
+
const hint = modelCliHint(modelName, token);
|
|
112
|
+
if (!all.has(token) || all.get(token) === undefined) {
|
|
113
|
+
all.set(token, hint);
|
|
114
|
+
}
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
|
-
return [...all];
|
|
117
|
+
return [...all].map(([token, hint]) => (hint === undefined ? { token } : { token, hint }));
|
|
118
|
+
}
|
|
119
|
+
function modelCliHint(modelName, token) {
|
|
120
|
+
if (token !== modelName) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
if (!isShippedDefaultModelName(modelName)) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
return `install ${token} or disable it in crew.config.ts: \`models.definitions.${modelName} = { disabled: true }\``;
|
|
127
|
+
}
|
|
128
|
+
function isShippedDefaultModelName(value) {
|
|
129
|
+
return value === "claude" || value === "codex";
|
|
114
130
|
}
|
|
115
131
|
function format(check) {
|
|
116
132
|
let tag;
|
|
@@ -163,11 +179,11 @@ export async function doctor() {
|
|
|
163
179
|
checkDir(config.workspace.projectDir, "workspace.projectDir"),
|
|
164
180
|
localCapability,
|
|
165
181
|
];
|
|
166
|
-
const
|
|
167
|
-
for (const token of
|
|
182
|
+
const toolTargets = gatherToolTargets(config);
|
|
183
|
+
for (const { token, hint } of toolTargets) {
|
|
168
184
|
const required = localCapability.ok;
|
|
169
185
|
// oxlint-disable-next-line no-await-in-loop -- doctor reports tools in deterministic order
|
|
170
|
-
const check = await checkCmd(token, required, required ?
|
|
186
|
+
const check = await checkCmd(token, required, required ? hint : "required for local runs");
|
|
171
187
|
checks.push(check);
|
|
172
188
|
}
|
|
173
189
|
const usageGatedModels = gatedModels(config);
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* the shipped `crew.config.example.ts` so a fresh install skips the manual
|
|
5
5
|
* `cp` dance documented in the README.
|
|
6
6
|
*/
|
|
7
|
+
import { type LocalRunnerSetting } from "../lib/config.ts";
|
|
8
|
+
declare const INIT_MODELS: readonly ["claude", "codex"];
|
|
7
9
|
type InitConfigScope = "global" | "local";
|
|
10
|
+
type InitModel = (typeof INIT_MODELS)[number];
|
|
8
11
|
interface InitConfigOptions {
|
|
9
12
|
/** Where to write the config. Defaults to "local" (cwd). */
|
|
10
13
|
scope?: InitConfigScope;
|
|
@@ -14,6 +17,16 @@ interface InitConfigOptions {
|
|
|
14
17
|
dryRun?: boolean;
|
|
15
18
|
/** Override for the working directory; defaults to `process.cwd()`. */
|
|
16
19
|
cwd?: string;
|
|
20
|
+
/** Pre-fill workspace.projectDir in the generated config. */
|
|
21
|
+
projectDir?: string;
|
|
22
|
+
/** Pre-fill workspace.knownRepositories in the generated config. */
|
|
23
|
+
repositories?: string[];
|
|
24
|
+
/** Pre-fill local.runner in the generated config. */
|
|
25
|
+
runner?: LocalRunnerSetting;
|
|
26
|
+
/** Keep one shipped default model enabled and disable the other. */
|
|
27
|
+
model?: InitModel;
|
|
28
|
+
/** Override the source template path. */
|
|
29
|
+
examplePath?: string;
|
|
17
30
|
}
|
|
18
31
|
type InitConfigOutcome = "dry-run-would-write" | "exists" | "wrote";
|
|
19
32
|
interface InitConfigResult {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAUlF,QAAA,MAAM,WAAW,YAAI,QAAQ,EAAE,OAAO,CAAU,CAAC;AAEjD,KAAK,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1C,KAAK,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,UAAU,iBAAiB;IACzB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,yCAAyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qDAAqD;IACrD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpE,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAoB5E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjE"}
|
package/dist/commands/init.js
CHANGED
|
@@ -4,16 +4,21 @@
|
|
|
4
4
|
* the shipped `crew.config.example.ts` so a fresh install skips the manual
|
|
5
5
|
* `cp` dance documented in the README.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
|
+
import { LOCAL_RUNNER_SETTINGS } from "../lib/config.js";
|
|
10
|
+
import { shellSingleQuote } from "../lib/shell.js";
|
|
9
11
|
import { log, writeOutput } from "../lib/util.js";
|
|
10
12
|
import { xdgConfigPath } from "../lib/xdg.js";
|
|
11
13
|
const CONFIG_FILE_NAME = "crew.config.ts";
|
|
12
14
|
const EXAMPLE_FILE_NAME = "crew.config.example.ts";
|
|
15
|
+
const DEFAULT_EXAMPLE_PROJECT_DIR = "~/dev/groundcrew";
|
|
16
|
+
const INIT_USAGE = "Usage: crew init [--global | --local] [--force] [--dry-run] [--project-dir <dir>] [--repo <owner/repo>]... [--runner <auto|safehouse|sdx|none>] [--model <claude|codex>]";
|
|
17
|
+
const INIT_MODELS = ["claude", "codex"];
|
|
13
18
|
export function initConfig(options = {}) {
|
|
14
19
|
const scope = options.scope ?? "local";
|
|
15
20
|
const cwd = options.cwd ?? process.cwd();
|
|
16
|
-
const source = resolveExamplePath();
|
|
21
|
+
const source = options.examplePath ?? resolveExamplePath();
|
|
17
22
|
const destination = destinationFor({ scope, cwd });
|
|
18
23
|
if (existsSync(destination) && options.force !== true) {
|
|
19
24
|
log(`[exists] ${destination} — pass --force to overwrite`);
|
|
@@ -24,7 +29,7 @@ export function initConfig(options = {}) {
|
|
|
24
29
|
return { destination, outcome: "dry-run-would-write" };
|
|
25
30
|
}
|
|
26
31
|
mkdirSync(dirname(destination), { recursive: true });
|
|
27
|
-
|
|
32
|
+
writeFileSync(destination, renderConfig(source, options));
|
|
28
33
|
log(`[wrote] ${destination}`);
|
|
29
34
|
return { destination, outcome: "wrote" };
|
|
30
35
|
}
|
|
@@ -36,24 +41,27 @@ export async function initConfigCli(argv) {
|
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
38
43
|
if (result.outcome === "wrote") {
|
|
39
|
-
|
|
40
|
-
writeOutput("Next steps:");
|
|
41
|
-
writeOutput(` - Edit ${result.destination}`);
|
|
42
|
-
writeOutput(" - Set workspace.projectDir, workspace.knownRepositories");
|
|
43
|
-
writeOutput(" - Export GROUNDCREW_LINEAR_API_KEY (or LINEAR_API_KEY)");
|
|
44
|
-
writeOutput(" - Assign Linear tickets to yourself and add an agent-* label to opt them in");
|
|
45
|
-
writeOutput(" - Verify with `crew doctor`");
|
|
44
|
+
writeInitGuidance(result.destination, options);
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
function parseArguments(argv) {
|
|
49
48
|
let scope;
|
|
50
49
|
let force = false;
|
|
51
50
|
let dryRun = false;
|
|
52
|
-
|
|
51
|
+
let projectDir;
|
|
52
|
+
const repositories = [];
|
|
53
|
+
let runner;
|
|
54
|
+
let model;
|
|
55
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
56
|
+
const argument = argv[index];
|
|
57
|
+
/* v8 ignore next 3 @preserve -- loop bounds keep argv[index] defined */
|
|
58
|
+
if (argument === undefined) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
53
61
|
if (argument === "--global" || argument === "--local") {
|
|
54
62
|
const next = argument === "--global" ? "global" : "local";
|
|
55
63
|
if (scope !== undefined && scope !== next) {
|
|
56
|
-
throw new Error(
|
|
64
|
+
throw new Error(`crew init: --global and --local are mutually exclusive.\n${INIT_USAGE}`);
|
|
57
65
|
}
|
|
58
66
|
scope = next;
|
|
59
67
|
continue;
|
|
@@ -66,9 +74,44 @@ function parseArguments(argv) {
|
|
|
66
74
|
dryRun = true;
|
|
67
75
|
continue;
|
|
68
76
|
}
|
|
69
|
-
|
|
77
|
+
if (argument === "--project-dir") {
|
|
78
|
+
projectDir = readOptionValue(argv, index, argument);
|
|
79
|
+
index += 1;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (argument === "--repo") {
|
|
83
|
+
repositories.push(readOptionValue(argv, index, argument));
|
|
84
|
+
index += 1;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (argument === "--runner") {
|
|
88
|
+
runner = parseRunner(readOptionValue(argv, index, argument));
|
|
89
|
+
index += 1;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (argument === "--model") {
|
|
93
|
+
model = parseModel(readOptionValue(argv, index, argument));
|
|
94
|
+
index += 1;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
throw new Error(`Unknown option: ${argument}\n${INIT_USAGE}`);
|
|
98
|
+
}
|
|
99
|
+
const parsed = {
|
|
100
|
+
scope: scope ?? "local",
|
|
101
|
+
force,
|
|
102
|
+
dryRun,
|
|
103
|
+
repositories,
|
|
104
|
+
};
|
|
105
|
+
if (projectDir !== undefined) {
|
|
106
|
+
parsed.projectDir = projectDir;
|
|
70
107
|
}
|
|
71
|
-
|
|
108
|
+
if (runner !== undefined) {
|
|
109
|
+
parsed.runner = runner;
|
|
110
|
+
}
|
|
111
|
+
if (model !== undefined) {
|
|
112
|
+
parsed.model = model;
|
|
113
|
+
}
|
|
114
|
+
return parsed;
|
|
72
115
|
}
|
|
73
116
|
function destinationFor(args) {
|
|
74
117
|
if (args.scope === "global") {
|
|
@@ -81,3 +124,127 @@ function resolveExamplePath() {
|
|
|
81
124
|
// after build; the example ships at the package root in both cases.
|
|
82
125
|
return resolve(import.meta.dirname, "..", "..", EXAMPLE_FILE_NAME);
|
|
83
126
|
}
|
|
127
|
+
function readOptionValue(argv, index, flag) {
|
|
128
|
+
const value = argv[index + 1];
|
|
129
|
+
if (value === undefined || value.length === 0 || value.startsWith("-")) {
|
|
130
|
+
throw new Error(`crew init ${flag}: value is required\n${INIT_USAGE}`);
|
|
131
|
+
}
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
function parseRunner(value) {
|
|
135
|
+
if (isLocalRunnerSetting(value)) {
|
|
136
|
+
return value;
|
|
137
|
+
}
|
|
138
|
+
throw new Error(`crew init --runner must be one of ${LOCAL_RUNNER_SETTINGS.join(", ")}`);
|
|
139
|
+
}
|
|
140
|
+
function parseModel(value) {
|
|
141
|
+
if (isInitModel(value)) {
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
throw new Error(`crew init --model must be one of ${INIT_MODELS.join(", ")}`);
|
|
145
|
+
}
|
|
146
|
+
function isLocalRunnerSetting(value) {
|
|
147
|
+
return value === "auto" || value === "safehouse" || value === "sdx" || value === "none";
|
|
148
|
+
}
|
|
149
|
+
function isInitModel(value) {
|
|
150
|
+
return value === "claude" || value === "codex";
|
|
151
|
+
}
|
|
152
|
+
function tsString(value) {
|
|
153
|
+
return JSON.stringify(value);
|
|
154
|
+
}
|
|
155
|
+
function renderConfig(source, options) {
|
|
156
|
+
let contents = readFileSync(source, "utf8");
|
|
157
|
+
if (options.projectDir !== undefined) {
|
|
158
|
+
contents = replaceRequired(contents, `projectDir: ${tsString(DEFAULT_EXAMPLE_PROJECT_DIR)}`, `projectDir: ${tsString(options.projectDir)}`, "--project-dir");
|
|
159
|
+
}
|
|
160
|
+
if (options.repositories !== undefined && options.repositories.length > 0) {
|
|
161
|
+
contents = replaceRequired(contents, 'knownRepositories: ["your-org/your-repo"]', `knownRepositories: [${options.repositories.map(tsString).join(", ")}]`, "--repo");
|
|
162
|
+
}
|
|
163
|
+
if (options.runner !== undefined) {
|
|
164
|
+
contents = replaceRequired(contents, ` // local: { runner: "auto" },`, ` local: { runner: ${tsString(options.runner)} },`, "--runner");
|
|
165
|
+
}
|
|
166
|
+
if (options.model !== undefined) {
|
|
167
|
+
contents = replaceRequired(contents, " // prompts: {", `${modelBlock(options.model)}\n // prompts: {`, "--model");
|
|
168
|
+
}
|
|
169
|
+
return contents;
|
|
170
|
+
}
|
|
171
|
+
function replaceRequired(contents, search, replacement, flag) {
|
|
172
|
+
if (!contents.includes(search)) {
|
|
173
|
+
throw new Error(`crew init ${flag}: template anchor not found in ${EXAMPLE_FILE_NAME}`);
|
|
174
|
+
}
|
|
175
|
+
return contents.replace(search, replacement);
|
|
176
|
+
}
|
|
177
|
+
function modelBlock(model) {
|
|
178
|
+
const disabled = model === "claude" ? "codex" : "claude";
|
|
179
|
+
return [
|
|
180
|
+
" models: {",
|
|
181
|
+
` default: ${tsString(model)},`,
|
|
182
|
+
" definitions: {",
|
|
183
|
+
` ${disabled}: { disabled: true },`,
|
|
184
|
+
" },",
|
|
185
|
+
" },",
|
|
186
|
+
"",
|
|
187
|
+
].join("\n");
|
|
188
|
+
}
|
|
189
|
+
function writeInitGuidance(destination, options) {
|
|
190
|
+
writeOutput("");
|
|
191
|
+
writeOutput("Next steps:");
|
|
192
|
+
writeOutput(` - Review ${destination}`);
|
|
193
|
+
if (options.projectDir === undefined ||
|
|
194
|
+
options.repositories === undefined ||
|
|
195
|
+
options.repositories.length === 0) {
|
|
196
|
+
writeOutput(" - Set workspace.projectDir and workspace.knownRepositories");
|
|
197
|
+
}
|
|
198
|
+
writeCloneGuidance(options);
|
|
199
|
+
writeOutput(" - If using Linear, export your API key:");
|
|
200
|
+
writeOutput(' export GROUNDCREW_LINEAR_API_KEY="lin_api_..."');
|
|
201
|
+
writeOutput(" - In Linear, assign tickets to yourself and add an agent-* label to opt them in");
|
|
202
|
+
writeOutput(" - Validate and start:");
|
|
203
|
+
writeOutput(" crew doctor");
|
|
204
|
+
writeOutput(" crew run --watch");
|
|
205
|
+
}
|
|
206
|
+
function writeCloneGuidance(options) {
|
|
207
|
+
if (options.repositories === undefined || options.repositories.length === 0) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
writeOutput(" - Clone configured repositories:");
|
|
211
|
+
writeOutput(` ${projectDirAssignment(options.projectDir ?? DEFAULT_EXAMPLE_PROJECT_DIR)}`);
|
|
212
|
+
for (const repository of options.repositories) {
|
|
213
|
+
for (const command of cloneCommands(repository)) {
|
|
214
|
+
writeOutput(` ${command}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function projectDirAssignment(projectDir) {
|
|
219
|
+
if (projectDir === "~") {
|
|
220
|
+
return 'PROJECT_DIR="$HOME"';
|
|
221
|
+
}
|
|
222
|
+
if (projectDir.startsWith("~/")) {
|
|
223
|
+
return `PROJECT_DIR="$HOME/${escapeDoubleQuotedShellValue(projectDir.slice(2))}"`;
|
|
224
|
+
}
|
|
225
|
+
return `PROJECT_DIR=${shellSingleQuote(projectDir)}`;
|
|
226
|
+
}
|
|
227
|
+
function cloneCommands(repository) {
|
|
228
|
+
const parts = repository.split("/");
|
|
229
|
+
const [owner, name, extra] = parts;
|
|
230
|
+
if (owner !== undefined && name !== undefined && extra === undefined) {
|
|
231
|
+
return [
|
|
232
|
+
`mkdir -p "$PROJECT_DIR/${owner}"`,
|
|
233
|
+
`git clone git@github.com:${owner}/${name}.git "$PROJECT_DIR/${owner}/${name}"`,
|
|
234
|
+
];
|
|
235
|
+
}
|
|
236
|
+
return [
|
|
237
|
+
'mkdir -p "$PROJECT_DIR"',
|
|
238
|
+
`git clone <REMOTE_URL_FOR_${repository}> "$PROJECT_DIR/${repository}"`,
|
|
239
|
+
];
|
|
240
|
+
}
|
|
241
|
+
function escapeDoubleQuotedShellValue(value) {
|
|
242
|
+
let escaped = "";
|
|
243
|
+
for (const character of value) {
|
|
244
|
+
escaped +=
|
|
245
|
+
character === '"' || character === "\\" || character === "$" || character === "`"
|
|
246
|
+
? `\\${character}`
|
|
247
|
+
: character;
|
|
248
|
+
}
|
|
249
|
+
return escaped;
|
|
250
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAEA,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":"AAEA,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,CA6Df;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
|
|
@@ -106,12 +106,13 @@ export async function resumeWorkspace(config, options) {
|
|
|
106
106
|
if (definition === undefined) {
|
|
107
107
|
throw new Error(`Unknown model: ${context.model}`);
|
|
108
108
|
}
|
|
109
|
-
const { runner, sandboxName } = await prepareAgentLaunch({
|
|
109
|
+
const { runner, sandboxName, ensureReady } = await prepareAgentLaunch({
|
|
110
110
|
config,
|
|
111
111
|
model: context.model,
|
|
112
112
|
definition,
|
|
113
113
|
purpose: "resumes",
|
|
114
114
|
});
|
|
115
|
+
await ensureReady();
|
|
115
116
|
const stagedPrompt = stagePromptText({
|
|
116
117
|
prefix: "groundcrew-resume",
|
|
117
118
|
ticket,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,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":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAiBnE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAuBD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,qBAAqB,EAC9B,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CA+Gf;AAyID,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
|
|
@@ -7,7 +7,7 @@ import { buildLaunchCommand } from "../lib/launchCommand.js";
|
|
|
7
7
|
import { recordRunState } from "../lib/runState.js";
|
|
8
8
|
import { stageBuildSecrets, stagePromptFromTemplate, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
|
|
9
9
|
import { naturalIdFromCanonical } from "../lib/ticketSource.js";
|
|
10
|
-
import { errorMessage, log } from "../lib/util.js";
|
|
10
|
+
import { debug, errorMessage, log, okMark } from "../lib/util.js";
|
|
11
11
|
import { workspaces } from "../lib/workspaces.js";
|
|
12
12
|
import { isWorktreeAlreadyExistsError, worktrees } from "../lib/worktrees.js";
|
|
13
13
|
function stagePrompt(input) {
|
|
@@ -31,7 +31,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
31
31
|
if (!definition) {
|
|
32
32
|
throw new Error(`Unknown model: ${model}`);
|
|
33
33
|
}
|
|
34
|
-
const { runner, sandboxName } = await prepareAgentLaunch({
|
|
34
|
+
const { runner, sandboxName, ensureReady } = await prepareAgentLaunch({
|
|
35
35
|
config,
|
|
36
36
|
model,
|
|
37
37
|
definition,
|
|
@@ -40,11 +40,10 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
40
40
|
});
|
|
41
41
|
const spec = { repository, ticket };
|
|
42
42
|
let created;
|
|
43
|
+
const createdPromise = signal === undefined ? worktrees.create(config, spec) : worktrees.create(config, spec, signal);
|
|
44
|
+
const readinessPromise = startLaunchReadiness(ensureReady);
|
|
43
45
|
try {
|
|
44
|
-
created =
|
|
45
|
-
signal === undefined
|
|
46
|
-
? await worktrees.create(config, spec)
|
|
47
|
-
: await worktrees.create(config, spec, signal);
|
|
46
|
+
created = await createdPromise;
|
|
48
47
|
}
|
|
49
48
|
catch (error) {
|
|
50
49
|
if (isWorktreeAlreadyExistsError(error)) {
|
|
@@ -63,6 +62,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
63
62
|
// the ticket strands forever.
|
|
64
63
|
let promptDir;
|
|
65
64
|
try {
|
|
65
|
+
await assertLaunchReady(readinessPromise);
|
|
66
66
|
const ticketDetails = options.details;
|
|
67
67
|
const accessHint = await workspaces.accessHint(config, ticket, signal);
|
|
68
68
|
const stagedPrompt = stagePrompt({
|
|
@@ -83,7 +83,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
83
83
|
sandboxName,
|
|
84
84
|
});
|
|
85
85
|
const launchCmd = stageWorkspaceLaunchCommand(promptDir, launchCommand);
|
|
86
|
-
|
|
86
|
+
debug("Opening workspace...");
|
|
87
87
|
await openAgentWorkspace({
|
|
88
88
|
config,
|
|
89
89
|
name: ticket,
|
|
@@ -105,9 +105,9 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
105
105
|
title: ticketDetails.title,
|
|
106
106
|
...(ticketDetails.url === undefined ? {} : { url: ticketDetails.url }),
|
|
107
107
|
});
|
|
108
|
-
log(
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
log(`${okMark()} "${ticket}" launched (${model}) worktree ${worktreeName}`);
|
|
109
|
+
debug(` Worktree: ${launchDir}`);
|
|
110
|
+
debug(` Branch: ${branchName}`);
|
|
111
111
|
if (accessHint !== undefined) {
|
|
112
112
|
logAccessHint(accessHint);
|
|
113
113
|
}
|
|
@@ -130,6 +130,21 @@ export async function setupWorkspace(config, options, runOptions = {}) {
|
|
|
130
130
|
throw error;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
|
+
async function startLaunchReadiness(ensureReady) {
|
|
134
|
+
try {
|
|
135
|
+
await ensureReady();
|
|
136
|
+
return { kind: "ready" };
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
return { kind: "failed", error };
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async function assertLaunchReady(readinessPromise) {
|
|
143
|
+
const readiness = await readinessPromise;
|
|
144
|
+
if (readiness.kind === "failed") {
|
|
145
|
+
throw readiness.error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
133
148
|
/**
|
|
134
149
|
* Probe the workspace backend and, if a workspace for `ticket` is still
|
|
135
150
|
* live, log the access hint. Used on the pre-launch error path (e.g. the
|
|
@@ -151,7 +166,7 @@ async function logAccessHintForExistingWorkspace(arguments_) {
|
|
|
151
166
|
logAccessHint(accessHint);
|
|
152
167
|
}
|
|
153
168
|
function logAccessHint(accessHint) {
|
|
154
|
-
|
|
169
|
+
debug(` Attach: ${accessHint.command}`);
|
|
155
170
|
}
|
|
156
171
|
function renderWorkspaceContinuationInstruction(accessHint) {
|
|
157
172
|
if (accessHint === undefined) {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { errorMessage, log, logEvent } from "../lib/util.js";
|
|
1
|
+
import { debug, errorMessage, log, logEvent, okMark } from "../lib/util.js";
|
|
2
2
|
export function logTeardown(result) {
|
|
3
3
|
if (result.workspaceProbe.kind === "unavailable" && result.workspaceProbe.error !== undefined) {
|
|
4
4
|
log(`workspace list failed: ${errorMessage(result.workspaceProbe.error)}`);
|
|
5
5
|
}
|
|
6
6
|
for (const ticket of result.closed) {
|
|
7
|
-
|
|
7
|
+
debug(`Closed workspace ${ticket}`);
|
|
8
8
|
}
|
|
9
9
|
for (const entry of result.removed) {
|
|
10
|
-
log(
|
|
11
|
-
|
|
10
|
+
log(`${okMark()} Cleanup complete for ${entry.ticket} (${entry.kind})`);
|
|
11
|
+
debug(` Worktree: ${entry.dir} (removed)`);
|
|
12
12
|
}
|
|
13
13
|
for (const failure of result.failures) {
|
|
14
14
|
const message = errorMessage(failure.error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/linear/fetch.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/linear/fetch.ts"],"names":[],"mappings":"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"}
|