@clipboard-health/groundcrew 4.34.3 → 4.35.1

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.
Files changed (41) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +2 -2
  3. package/dist/commands/dispatcher.d.ts.map +1 -1
  4. package/dist/commands/dispatcher.js +1 -0
  5. package/dist/commands/doctor.d.ts.map +1 -1
  6. package/dist/commands/doctor.js +88 -18
  7. package/dist/commands/orchestrator.d.ts.map +1 -1
  8. package/dist/commands/orchestrator.js +6 -1
  9. package/dist/commands/resumeWorkspace.d.ts.map +1 -1
  10. package/dist/commands/resumeWorkspace.js +6 -1
  11. package/dist/commands/setupWorkspace.d.ts +2 -0
  12. package/dist/commands/setupWorkspace.d.ts.map +1 -1
  13. package/dist/commands/setupWorkspace.js +7 -0
  14. package/dist/commands/task.d.ts.map +1 -1
  15. package/dist/commands/task.js +87 -0
  16. package/dist/lib/adapters/shell/factory.d.ts.map +1 -1
  17. package/dist/lib/adapters/shell/factory.js +13 -3
  18. package/dist/lib/adapters/shell/parseOutput.d.ts +23 -0
  19. package/dist/lib/adapters/shell/parseOutput.d.ts.map +1 -0
  20. package/dist/lib/adapters/shell/parseOutput.js +67 -0
  21. package/dist/lib/agentLaunch.d.ts +2 -0
  22. package/dist/lib/agentLaunch.d.ts.map +1 -1
  23. package/dist/lib/agentLaunch.js +5 -0
  24. package/dist/lib/config.d.ts.map +1 -1
  25. package/dist/lib/config.js +1 -0
  26. package/dist/lib/launchCommand.d.ts +9 -0
  27. package/dist/lib/launchCommand.d.ts.map +1 -1
  28. package/dist/lib/launchCommand.js +38 -7
  29. package/dist/lib/runState.d.ts +6 -0
  30. package/dist/lib/runState.d.ts.map +1 -1
  31. package/dist/lib/runState.js +4 -0
  32. package/dist/lib/taskSource.d.ts +13 -0
  33. package/dist/lib/taskSource.d.ts.map +1 -1
  34. package/dist/lib/taskSource.js +16 -0
  35. package/docs/commands.md +42 -4
  36. package/docs/configuration.md +25 -25
  37. package/docs/credentials.md +2 -2
  38. package/docs/runners.md +3 -3
  39. package/docs/task-sources.md +9 -3
  40. package/docs/troubleshooting.md +8 -6
  41. package/package.json +3 -3
package/README.md CHANGED
@@ -94,6 +94,7 @@ crew source list|verify [<source>] # inspect configured ta
94
94
  crew task list [--source <name>] # list tasks across sources
95
95
  crew task get <TASK> [--source <name>] [--prompt] # inspect one task or its prompt
96
96
  crew task create "Title" --source <name> [--agent <name>] # create a source task
97
+ crew task done <TASK> [--allow-dirty] # mark a no-PR task done
97
98
  crew task validate [<source>] # validate task content
98
99
  crew status [<TASK>] # inspect current state or one task
99
100
  crew run [--watch] # one-shot or --watch forever
package/dist/cli.js CHANGED
@@ -136,8 +136,8 @@ const SUBCOMMANDS = {
136
136
  invoke: sourceCli,
137
137
  },
138
138
  task: {
139
- summary: "List, get, and create tasks across configured sources",
140
- usage: "<list|get|create> [...]",
139
+ summary: "List, get, create, and complete tasks across configured sources",
140
+ usage: "<list|get|create|done|validate> [...]",
141
141
  invoke: taskCli,
142
142
  },
143
143
  status: {
@@ -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,sBAAsB,CAAC;AAC9B,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,EAAE,CAAC,UAAU,EAAE;QACpB,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,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAiCD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAmOjE;AA2BD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAQrE"}
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,sBAAsB,CAAC;AAC9B,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,EAAE,CAAC,UAAU,EAAE;QACpB,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,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAiCD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,cAAc,GAAG,UAAU,CAoOjE;AA2BD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAQrE"}
@@ -70,6 +70,7 @@ export function createDispatcher(deps) {
70
70
  const setupOptions = {
71
71
  repository: issue.repository,
72
72
  task: taskId,
73
+ completionTaskId: issue.id,
73
74
  agent: issue.agent,
74
75
  details: {
75
76
  title: issue.title,
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyLH,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAmF/C"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAuQH,wBAAsB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,CAmF/C"}
@@ -3,12 +3,12 @@
3
3
  * Returns true if every required check passes; false otherwise.
4
4
  */
5
5
  import { existsSync, statSync } from "node:fs";
6
- import { createBoard } from "../lib/board.js";
7
6
  import { buildSources, sourcesFromConfig } from "../lib/buildSources.js";
8
7
  import { loadConfigWithSource, worktreeBaseDir, } from "../lib/config.js";
9
8
  import { detectHostCapabilities, which } from "../lib/host.js";
10
9
  import { isEnvironmentAssignment } from "../lib/launchCommand.js";
11
10
  import { resolveLocalRunner } from "../lib/localRunner.js";
11
+ import { naturalIdFromCanonical } from "../lib/taskSource.js";
12
12
  import { gatedAgents } from "../lib/usage.js";
13
13
  import { errorMessage, writeOutput } from "../lib/util.js";
14
14
  import { resolveWorkspaceKind } from "../lib/workspaces.js";
@@ -34,27 +34,97 @@ async function checkCmd(cmd, required, hint) {
34
34
  }
35
35
  return result;
36
36
  }
37
+ function isRecord(value) {
38
+ return typeof value === "object" && value !== null;
39
+ }
37
40
  /**
38
- * Source-agnostic reachability check: build every configured task source
39
- * and run the Board's `verify()` fan-out. Replaces the old Linear-only
40
- * "api key + reachability" probe so a misconfigured shell (or future Jira)
41
- * source surfaces here too. A missing Linear API key still fails verify with
42
- * its own user-facing message, so the prior behavior is preserved.
41
+ * True when a raw source config entry declares `kind: "shell"`. Gates the
42
+ * shell-only read probe.
43
43
  */
44
- async function checkSourceProbe(config) {
44
+ function isShellSource(raw) {
45
+ if (!isRecord(raw)) {
46
+ return false;
47
+ }
48
+ const { kind } = raw;
49
+ return kind === "shell";
50
+ }
51
+ function hasExplicitGetTaskCommand(raw) {
52
+ const { commands } = raw;
53
+ if (!isRecord(commands)) {
54
+ return false;
55
+ }
56
+ const { getTask, resolveOne } = commands;
57
+ return typeof getTask === "string" || typeof resolveOne === "string";
58
+ }
59
+ function shellReadProbeFor(raw) {
60
+ if (!isShellSource(raw)) {
61
+ return "none";
62
+ }
63
+ return hasExplicitGetTaskCommand(raw) ? "listTasksAndGetTask" : "listTasks";
64
+ }
65
+ /**
66
+ * Probe each configured task source independently and emit one `Check` per
67
+ * source (named `source: <name>`), so a single broken source is attributable
68
+ * instead of hidden behind an aggregate "N source(s) verified" line.
69
+ *
70
+ * Every source runs its `verify()`. Shell sources are additionally deep-probed
71
+ * via `listTasks()`: their `verify` command can discard stdout (e.g.
72
+ * `... fetch >/dev/null`), so a malformed task payload sails through verify and
73
+ * only blows up later in `crew run`. Running listTasks here surfaces a
74
+ * wrong-shape payload (a `TaskSourceOutputError` with a readable message) at
75
+ * doctor time. Non-shell sources (Linear) are left to `verify()` alone — their
76
+ * fetch is an expensive network call that verify already exercises.
77
+ */
78
+ async function checkSourceProbes(config) {
79
+ const rawSources = sourcesFromConfig(config);
80
+ let sources;
45
81
  try {
46
- const sources = await buildSources(sourcesFromConfig(config), { globalConfig: config });
47
- const board = createBoard(sources);
48
- await board.verify();
49
- return {
50
- name: "source probe",
51
- ok: true,
52
- required: true,
53
- hint: `${sources.length} source(s) verified`,
54
- };
82
+ sources = await buildSources(rawSources, { globalConfig: config });
83
+ }
84
+ catch (error) {
85
+ // Building sources failed before any individual probe (bad config / unknown
86
+ // kind). Surface it as a single failed check rather than per-source.
87
+ return [{ name: "sources", ok: false, required: true, hint: errorMessage(error) }];
88
+ }
89
+ if (sources.length === 0) {
90
+ return [{ name: "sources", ok: false, required: true, hint: "no task sources configured" }];
91
+ }
92
+ const checks = [];
93
+ for (const [index, source] of sources.entries()) {
94
+ const shellReadProbe = shellReadProbeFor(rawSources[index]);
95
+ // oxlint-disable-next-line no-await-in-loop -- sequential keeps each verdict attributable to one source
96
+ checks.push(await probeSource(source, shellReadProbe));
97
+ }
98
+ return checks;
99
+ }
100
+ async function probeSource(source, shellReadProbe) {
101
+ const name = `source: ${source.name}`;
102
+ try {
103
+ await source.verify();
104
+ if (shellReadProbe === "none") {
105
+ return { name, ok: true, required: true, hint: "verified" };
106
+ }
107
+ const tasks = await source.listTasks();
108
+ const parts = [`fetched ${tasks.length} task(s)`];
109
+ // Read-path symmetry: an id listTasks emitted must resolve via getTask.
110
+ // Skipped when getTask is only the adapter's listTasks fallback, since that
111
+ // would just re-run listTasks and can race changing source output.
112
+ const [first] = tasks;
113
+ if (first !== undefined && shellReadProbe === "listTasksAndGetTask") {
114
+ const naturalId = naturalIdFromCanonical(first.id);
115
+ const resolved = await source.getTask(naturalId);
116
+ if (resolved === null) {
117
+ throw new Error(`getTask("${naturalId}") returned nothing, but listTasks emitted it`);
118
+ }
119
+ if (resolved.id !== first.id) {
120
+ throw new Error(`getTask("${naturalId}") resolved "${resolved.id}", but listTasks emitted "${first.id}"`);
121
+ }
122
+ parts.push("getTask round-trips");
123
+ }
124
+ return { name, ok: true, required: true, hint: `verified; ${parts.join("; ")}` };
55
125
  }
56
126
  catch (error) {
57
- return { name: "source probe", ok: false, required: true, hint: errorMessage(error) };
127
+ return { name, ok: false, required: true, hint: errorMessage(error) };
58
128
  }
59
129
  }
60
130
  function checkDir(path, label) {
@@ -190,7 +260,7 @@ export async function doctor() {
190
260
  const workspaceOutcome = resolveWorkspaceOutcome(config, host);
191
261
  reportWorkspaceKind(config, workspaceOutcome);
192
262
  const checks = [
193
- await checkSourceProbe(config),
263
+ ...(await checkSourceProbes(config)),
194
264
  await checkCmd("git", true, "https://git-scm.com/"),
195
265
  ...(await workspaceChecks(workspaceOutcome)),
196
266
  checkDir(config.workspace.projectDir, "workspace.projectDir"),
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/commands/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2DH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAiBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE7E"}
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/commands/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoEH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACjB;AAiBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE7E"}
@@ -8,7 +8,7 @@ import { createBoard } from "../lib/board.js";
8
8
  import { buildSources, sourcesFromConfig } from "../lib/buildSources.js";
9
9
  import { loadConfigWithSource } from "../lib/config.js";
10
10
  import { findPullRequestsForBranch } from "../lib/pullRequests.js";
11
- import { RepositoryResolutionError } from "../lib/taskSource.js";
11
+ import { RepositoryResolutionError, TaskSourceOutputError, } from "../lib/taskSource.js";
12
12
  import { getUsageByAgent } from "../lib/usage.js";
13
13
  import { errorMessage, log, sleep, writeOutput } from "../lib/util.js";
14
14
  import { worktrees } from "../lib/worktrees.js";
@@ -30,6 +30,11 @@ async function withRetry(function_, signal, maxRetries = RETRY_MAX_ATTEMPTS, bas
30
30
  if (error instanceof RepositoryResolutionError) {
31
31
  throw error;
32
32
  }
33
+ // A source returned unparseable output — deterministic, so retrying just
34
+ // delays a guaranteed failure behind confusing "Retrying in Ns" lines.
35
+ if (error instanceof TaskSourceOutputError) {
36
+ throw error;
37
+ }
33
38
  if (attempt === maxRetries) {
34
39
  throw error;
35
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAcnE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AAuID,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA2Ef;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
1
+ {"version":3,"file":"resumeWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/resumeWorkspace.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAenE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;CACd;AA0ID,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Ef;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtE"}
@@ -3,9 +3,10 @@ import { getLinearClient } from "../lib/adapters/linear/client.js";
3
3
  import { isLinearEnabled } from "../lib/buildSources.js";
4
4
  import { loadConfig } from "../lib/config.js";
5
5
  import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
6
+ import { workerEnvironmentForTask } from "../lib/launchCommand.js";
6
7
  import { readRunState, recordRunState } from "../lib/runState.js";
7
8
  import { removeStagedPrompt, stageBuildSecrets, stagePromptText, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
8
- import { naturalIdFromCanonical } from "../lib/taskSource.js";
9
+ import { naturalIdFromCanonical, toCanonicalId } from "../lib/taskSource.js";
9
10
  import { errorMessage, log } from "../lib/util.js";
10
11
  import { workspaces } from "../lib/workspaces.js";
11
12
  import { resolveLaunchDir, worktrees } from "../lib/worktrees.js";
@@ -38,6 +39,7 @@ async function contextFromLinear(config, task, worktree) {
38
39
  worktree,
39
40
  title: resolved.title,
40
41
  description: resolved.description,
42
+ completionTaskId: toCanonicalId("linear", task),
41
43
  resumeCount: 0,
42
44
  };
43
45
  }
@@ -53,6 +55,7 @@ async function contextFromState(config, task, state, worktree) {
53
55
  worktree,
54
56
  title: details?.title ?? task.toUpperCase(),
55
57
  description: details?.description ?? "",
58
+ completionTaskId: state.completionTaskId ?? task,
56
59
  ...(state.reason === undefined ? {} : { reason: state.reason }),
57
60
  resumeCount: state.resumeCount,
58
61
  };
@@ -147,6 +150,7 @@ export async function resumeWorkspace(config, options) {
147
150
  workingDir: launchDir,
148
151
  secretsFile,
149
152
  sandboxName,
153
+ workerEnvironment: workerEnvironmentForTask(context.completionTaskId),
150
154
  }));
151
155
  const launchCmd = stageWorkspaceLaunchCommand(stagedPrompt.directory, launchCommand);
152
156
  await openAgentWorkspace({
@@ -178,6 +182,7 @@ export async function resumeWorkspace(config, options) {
178
182
  workspaceName: task,
179
183
  state: "resumed",
180
184
  resumeCount: context.resumeCount + 1,
185
+ completionTaskId: context.completionTaskId,
181
186
  ...(context.reason === undefined ? {} : { reason: context.reason }),
182
187
  },
183
188
  });
@@ -7,6 +7,8 @@ export interface TaskDetails {
7
7
  }
8
8
  export interface SetupWorkspaceOptions {
9
9
  task: string;
10
+ /** Canonical source id for worker self-completion; falls back to `task`. */
11
+ completionTaskId?: string;
10
12
  repository: string;
11
13
  agent: string;
12
14
  details: TaskDetails;
@@ -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;AAsBnE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;CACtB;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,CA0Hf;AA8ID,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA4Cf"}
1
+ {"version":3,"file":"setupWorkspace.d.ts","sourceRoot":"","sources":["../../src/commands/setupWorkspace.ts"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAuBnE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,CAAC;CACtB;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,CA8Hf;AAgJD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
@@ -3,6 +3,7 @@ import { loadConfig } from "../lib/config.js";
3
3
  import { composeAgentLaunch, openAgentWorkspace, prepareAgentLaunch } from "../lib/agentLaunch.js";
4
4
  import { createBoard } from "../lib/board.js";
5
5
  import { buildSources, sourcesFromConfig } from "../lib/buildSources.js";
6
+ import { workerEnvironmentForTask } from "../lib/launchCommand.js";
6
7
  import { resolvePrepareWorktreeCommand } from "../lib/repositoryHooks.js";
7
8
  import { recordRunState } from "../lib/runState.js";
8
9
  import { stageBuildSecrets, stagePromptFromTemplate, stageWorkspaceLaunchCommand, } from "../lib/stagedLaunch.js";
@@ -80,6 +81,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
80
81
  defaultHooks: config.defaults.hooks,
81
82
  });
82
83
  const secretsFile = prepareWorktreeCommand === undefined ? undefined : stageBuildSecrets(promptDir);
84
+ const completionTaskId = options.completionTaskId ?? task;
83
85
  const { launchCommand, srtSettingsDir: stagedSrtSettingsDir } = composeAgentLaunch({
84
86
  runner,
85
87
  task,
@@ -90,6 +92,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
90
92
  secretsFile,
91
93
  prepareWorktreeCommand,
92
94
  sandboxName,
95
+ workerEnvironment: workerEnvironmentForTask(completionTaskId),
93
96
  });
94
97
  srtSettingsDir = stagedSrtSettingsDir;
95
98
  const launchCmd = stageWorkspaceLaunchCommand(promptDir, launchCommand);
@@ -113,6 +116,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
113
116
  workspaceName: task,
114
117
  state: "running",
115
118
  title: taskDetails.title,
119
+ completionTaskId,
116
120
  ...(taskDetails.url === undefined ? {} : { url: taskDetails.url }),
117
121
  });
118
122
  log(`${okMark()} "${task}" launched (${agent}) worktree ${worktreeName}`);
@@ -135,6 +139,7 @@ export async function setupWorkspace(config, options, runOptions = {}) {
135
139
  state: "failed-to-launch",
136
140
  detail: errorMessage(error),
137
141
  title: options.details.title,
142
+ completionTaskId: options.completionTaskId ?? task,
138
143
  ...(options.details.url === undefined ? {} : { url: options.details.url }),
139
144
  });
140
145
  throw error;
@@ -197,6 +202,7 @@ function recordRunStateBestEffort(arguments_) {
197
202
  workspaceName: arguments_.workspaceName,
198
203
  state: arguments_.state,
199
204
  title: arguments_.title,
205
+ completionTaskId: arguments_.completionTaskId,
200
206
  ...(arguments_.detail === undefined ? {} : { detail: arguments_.detail }),
201
207
  ...(arguments_.url === undefined ? {} : { url: arguments_.url }),
202
208
  },
@@ -275,6 +281,7 @@ export async function setupWorkspaceCli(task, options = {}) {
275
281
  const naturalId = naturalIdFromCanonical(resolved.id);
276
282
  await setupWorkspace(config, {
277
283
  task: naturalId,
284
+ completionTaskId: resolved.id,
278
285
  repository: resolved.repository,
279
286
  agent: resolved.agent,
280
287
  details: {
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAmrBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB3D"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/commands/task.ts"],"names":[],"mappings":"AAoyBA,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB3D"}
@@ -1,13 +1,17 @@
1
+ import { createBoard } from "../lib/board.js";
1
2
  import { buildSources, sourcesFromConfig } from "../lib/buildSources.js";
2
3
  import { AGENT_ANY, loadConfig } from "../lib/config.js";
4
+ import { findPullRequestsForBranch } from "../lib/pullRequests.js";
3
5
  import { naturalIdFromCanonical, } from "../lib/taskSource.js";
4
6
  import { parseSourceFilterArgs, writeOutput } from "../lib/util.js";
7
+ import { worktrees } from "../lib/worktrees.js";
5
8
  const TASK_USAGE = `Usage: crew task <subcommand>
6
9
 
7
10
  Subcommands:
8
11
  list [options] List tasks across configured sources
9
12
  get <task-id> [options] Get one task
10
13
  create "Short title" [options] Create one task
14
+ done <task-id> [options] Mark one task done
11
15
  validate [source] [options] Validate task content`;
12
16
  const LIST_USAGE = `Usage: crew task list [options]
13
17
 
@@ -27,6 +31,7 @@ Options:
27
31
  --json Print normalized task JSON.
28
32
  --prompt Print only the task description/prompt.`;
29
33
  const CREATE_USAGE = `Usage: crew task create "Short title" --source <source> [--agent <agent>] [options]`;
34
+ const DONE_USAGE = `Usage: crew task done <task-id> [--allow-dirty]`;
30
35
  const CANONICAL_STATUSES = [
31
36
  "todo",
32
37
  "in-progress",
@@ -251,10 +256,34 @@ function parseCreateOptions(argv) {
251
256
  };
252
257
  return { title, sourceName: state.sourceName, input, json: state.json };
253
258
  }
259
+ function parseDoneOptions(argv) {
260
+ const positionals = [];
261
+ let allowDirty = false;
262
+ for (const argument of argv) {
263
+ if (argument === "--allow-dirty") {
264
+ allowDirty = true;
265
+ continue;
266
+ }
267
+ if (argument.startsWith("-")) {
268
+ throw new Error(`crew task done: unknown option: ${argument}\n${DONE_USAGE}`);
269
+ }
270
+ positionals.push(argument);
271
+ }
272
+ const [taskId, ...extras] = positionals;
273
+ if (taskId === undefined || taskId.length === 0 || extras.length > 0) {
274
+ throw new Error(DONE_USAGE);
275
+ }
276
+ return { taskId, allowDirty };
277
+ }
254
278
  async function loadTaskSources() {
255
279
  const config = await loadConfig();
256
280
  return await buildSources(sourcesFromConfig(config), { globalConfig: config });
257
281
  }
282
+ async function loadTaskBoard() {
283
+ const config = await loadConfig();
284
+ const sources = await buildSources(sourcesFromConfig(config), { globalConfig: config });
285
+ return { config, board: createBoard(sources) };
286
+ }
258
287
  function findSource(sources, sourceName) {
259
288
  const source = sources.find((candidate) => candidate.name === sourceName);
260
289
  if (source === undefined) {
@@ -472,6 +501,60 @@ async function taskCreateCli(argv) {
472
501
  }
473
502
  writeOutput(created.id);
474
503
  }
504
+ function matchingWorktreeEntries(arguments_) {
505
+ const task = naturalIdFromCanonical(arguments_.issue.id);
506
+ return worktrees
507
+ .findByTask(arguments_.config, task)
508
+ .filter((entry) => arguments_.issue.repository === undefined ||
509
+ entry.repository === arguments_.issue.repository);
510
+ }
511
+ function describeDirtiness(dirtiness) {
512
+ if (dirtiness.kind === "dirty") {
513
+ return `${dirtiness.modified} modified, ${dirtiness.untracked} untracked`;
514
+ }
515
+ return "unknown git status";
516
+ }
517
+ async function worktreeHasPullRequest(entry) {
518
+ const pullRequests = await findPullRequestsForBranch({
519
+ cwd: entry.dir,
520
+ branchName: entry.branchName,
521
+ });
522
+ return pullRequests.length > 0;
523
+ }
524
+ async function assertCanMarkDone(arguments_) {
525
+ if (arguments_.allowDirty) {
526
+ return;
527
+ }
528
+ for (const entry of matchingWorktreeEntries({
529
+ config: arguments_.config,
530
+ issue: arguments_.issue,
531
+ })) {
532
+ // oxlint-disable-next-line no-await-in-loop -- one git status per matching worktree keeps diagnostics deterministic.
533
+ const dirtiness = await worktrees.probeWorkingTree({ worktreeDir: entry.dir });
534
+ if (dirtiness.kind === "clean") {
535
+ continue;
536
+ }
537
+ // oxlint-disable-next-line no-await-in-loop -- only dirty/unknown worktrees need the PR lookup.
538
+ if (dirtiness.kind === "dirty" && (await worktreeHasPullRequest(entry))) {
539
+ continue;
540
+ }
541
+ throw new Error(`crew task done: refusing to mark ${arguments_.issue.id} done because ${entry.dir} has ${describeDirtiness(dirtiness)} and no matching PR. Commit or stash the work, open a PR, or rerun with --allow-dirty.`);
542
+ }
543
+ }
544
+ async function taskDoneCli(argv) {
545
+ const options = parseDoneOptions(argv);
546
+ const { config, board } = await loadTaskBoard();
547
+ const issue = await board.resolveOne(options.taskId);
548
+ if (issue === undefined) {
549
+ throw new Error(`Task ${options.taskId} not found across configured sources.`);
550
+ }
551
+ await assertCanMarkDone({ config, issue, allowDirty: options.allowDirty });
552
+ const result = await board.markDone(issue);
553
+ if (result.outcome === "unsupported") {
554
+ throw new Error(`crew task done: ${result.reason}`);
555
+ }
556
+ writeOutput(`Marked ${issue.id} done.`);
557
+ }
475
558
  const VALIDATE_USAGE = `Usage: crew task validate [source]
476
559
 
477
560
  Options:
@@ -536,6 +619,10 @@ export async function taskCli(argv) {
536
619
  await taskCreateCli(rest);
537
620
  return;
538
621
  }
622
+ if (verb === "done") {
623
+ await taskDoneCli(rest);
624
+ return;
625
+ }
539
626
  if (verb === "validate") {
540
627
  await taskValidateCli(rest);
541
628
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/shell/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAIL,KAAK,KAAK,IAAI,cAAc,EAG5B,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAC;AAyErB,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAuB3F;AA8BD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,cAAc,GACvB,UAAU,CA6LZ"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/shell/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAIL,KAAK,KAAK,IAAI,cAAc,EAG5B,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,KAAK,kBAAkB,EAEvB,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAC;AAyErB,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAuB3F;AA8BD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,cAAc,GACvB,UAAU,CAsMZ"}
@@ -22,6 +22,7 @@
22
22
  import { toCanonicalId, } from "../../taskSource.js";
23
23
  import { errorMessage, writeError } from "../../util.js";
24
24
  import { invokeShellCommand } from "./invoke.js";
25
+ import { parseShellJson } from "./parseOutput.js";
25
26
  import { shellFetchOutputSchema, shellIssueSchema, shellValidateOutputSchema, } from "./schema.js";
26
27
  const DEFAULT_TIMEOUTS = {
27
28
  verify: 10_000,
@@ -134,7 +135,10 @@ export function createShellTaskSource(config, _context) {
134
135
  env: config.env,
135
136
  sourceName,
136
137
  });
137
- const parsed = shellFetchOutputSchema.parse(JSON.parse(stdout));
138
+ const parsed = parseShellJson(shellFetchOutputSchema, stdout, {
139
+ sourceName,
140
+ command: "listTasks",
141
+ });
138
142
  return parsed.map((si) => toCanonicalIssue(si, sourceName));
139
143
  }
140
144
  async function getTask(naturalId) {
@@ -158,7 +162,10 @@ export function createShellTaskSource(config, _context) {
158
162
  if (result.exitCode === 3 || result.stdout.trim().length === 0) {
159
163
  return null;
160
164
  }
161
- const parsed = shellIssueSchema.parse(JSON.parse(result.stdout));
165
+ const parsed = parseShellJson(shellIssueSchema, result.stdout, {
166
+ sourceName,
167
+ command: "getTask",
168
+ });
162
169
  return toCanonicalIssue(parsed, sourceName);
163
170
  }
164
171
  // Shared by markInProgress / markInReview: both pipe the canonical issue's
@@ -259,7 +266,10 @@ export function createShellTaskSource(config, _context) {
259
266
  if (trimmed.length === 0) {
260
267
  throw new Error(`shell source "${sourceName}" createTask command produced no output (expected one ShellIssue JSON)`);
261
268
  }
262
- const parsed = shellIssueSchema.parse(JSON.parse(trimmed));
269
+ const parsed = parseShellJson(shellIssueSchema, trimmed, {
270
+ sourceName,
271
+ command: "createTask",
272
+ });
263
273
  return toCanonicalIssue(parsed, sourceName);
264
274
  };
265
275
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Friendly stdout parsing for the shell adapter. A shell source emits JSON on
3
+ * stdout; both `JSON.parse` and the Zod schema can reject it. A raw `ZodError`
4
+ * stringifies to a JSON array of issues — cryptic, unattributed, and (for a
5
+ * fetch array) repeated once per task. This module collapses that into a
6
+ * single user-facing `TaskSourceOutputError` that names the source, the
7
+ * command, and the offending field(s), with a targeted hint for the common
8
+ * "missing `agent`" mistake.
9
+ */
10
+ import type { z } from "zod";
11
+ export interface ShellParseContext {
12
+ /** The source's configured `name`, surfaced so the user knows which source broke. */
13
+ sourceName: string;
14
+ /** The contract method that produced the output, e.g. `"listTasks"` or `"getTask"`. */
15
+ command: string;
16
+ }
17
+ /**
18
+ * Parse `stdout` as JSON and validate it against `schema`. On any failure,
19
+ * throws a `TaskSourceOutputError` with a readable, source-attributed message
20
+ * instead of a raw `SyntaxError` / `ZodError`.
21
+ */
22
+ export declare function parseShellJson<T>(schema: z.ZodType<T>, stdout: string, context: ShellParseContext): T;
23
+ //# sourceMappingURL=parseOutput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseOutput.d.ts","sourceRoot":"","sources":["../../../../src/lib/adapters/shell/parseOutput.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAK7B,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,UAAU,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EACpB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,iBAAiB,GACzB,CAAC,CAcH"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Friendly stdout parsing for the shell adapter. A shell source emits JSON on
3
+ * stdout; both `JSON.parse` and the Zod schema can reject it. A raw `ZodError`
4
+ * stringifies to a JSON array of issues — cryptic, unattributed, and (for a
5
+ * fetch array) repeated once per task. This module collapses that into a
6
+ * single user-facing `TaskSourceOutputError` that names the source, the
7
+ * command, and the offending field(s), with a targeted hint for the common
8
+ * "missing `agent`" mistake.
9
+ */
10
+ import { TaskSourceOutputError } from "../../taskSource.js";
11
+ import { errorMessage } from "../../util.js";
12
+ /**
13
+ * Parse `stdout` as JSON and validate it against `schema`. On any failure,
14
+ * throws a `TaskSourceOutputError` with a readable, source-attributed message
15
+ * instead of a raw `SyntaxError` / `ZodError`.
16
+ */
17
+ export function parseShellJson(schema, stdout, context) {
18
+ let json;
19
+ try {
20
+ json = JSON.parse(stdout);
21
+ }
22
+ catch (error) {
23
+ throw new TaskSourceOutputError(`source "${context.sourceName}": the ${context.command} command did not return valid JSON (${errorMessage(error)}).`);
24
+ }
25
+ const result = schema.safeParse(json);
26
+ if (result.success) {
27
+ return result.data;
28
+ }
29
+ throw new TaskSourceOutputError(formatSchemaError(result.error, context));
30
+ }
31
+ /** The last string segment of an issue path — the field name, ignoring array indices. */
32
+ function fieldName(path) {
33
+ for (let index = path.length - 1; index >= 0; index -= 1) {
34
+ const segment = path[index];
35
+ if (typeof segment === "string") {
36
+ return segment;
37
+ }
38
+ }
39
+ return undefined;
40
+ }
41
+ /** One human-readable phrase describing what's wrong with a single issue. */
42
+ function describeIssue(issue) {
43
+ const field = fieldName(issue.path);
44
+ const label = field === undefined ? "field" : `"${field}"`;
45
+ // Zod v4 reports a missing required key as an `invalid_type` whose message
46
+ // ends in "received undefined"; there is no separate `received` property to
47
+ // branch on, so we match the message.
48
+ if (issue.code === "invalid_type" && issue.message.includes("received undefined")) {
49
+ return `are missing the required ${label} field`;
50
+ }
51
+ return `have an invalid ${label} field: ${issue.message}`;
52
+ }
53
+ function formatSchemaError(error, context) {
54
+ // A fetch array yields one issue per task (48 tasks missing `agent` → 48
55
+ // identical issues). Collapse identical phrasings into a single counted line,
56
+ // preserving first-seen order via the Map's insertion order.
57
+ const counts = new Map();
58
+ for (const issue of error.issues) {
59
+ const description = describeIssue(issue);
60
+ counts.set(description, (counts.get(description) ?? 0) + 1);
61
+ }
62
+ const lines = [...counts].map(([description, count]) => ` • ${count} issue(s) ${description}`);
63
+ return [
64
+ `source "${context.sourceName}": the ${context.command} command returned task JSON that doesn't match the expected shape:`,
65
+ ...lines,
66
+ ].join("\n");
67
+ }
@@ -1,4 +1,5 @@
1
1
  import { type LocalRunner, type AgentDefinition, type ResolvedConfig } from "./config.ts";
2
+ import { type WorkerEnvironment } from "./launchCommand.ts";
2
3
  /**
3
4
  * Stage any srt settings and build the workspace launch command — the assembly
4
5
  * shared verbatim by `setupWorkspace` (fresh runs) and `resumeWorkspace`
@@ -16,6 +17,7 @@ export declare function composeAgentLaunch(input: {
16
17
  secretsFile?: string | undefined;
17
18
  prepareWorktreeCommand?: string | undefined;
18
19
  sandboxName?: string | undefined;
20
+ workerEnvironment?: WorkerEnvironment | undefined;
19
21
  }): {
20
22
  launchCommand: string;
21
23
  srtSettingsDir: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AASrB;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CA0BhE;AAsBD,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;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,CA+C/B;AAwBD,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"}
1
+ {"version":3,"file":"agentLaunch.d.ts","sourceRoot":"","sources":["../../src/lib/agentLaunch.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAsB,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAOhF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,sBAAsB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACnD,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CA2BhE;AAsBD,UAAU,mBAAmB;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;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,CAqD/B;AAwBD,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"}