@launch11/srgical 0.0.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LaunchEleven
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # srgical
2
+
3
+ `srgical` is a local-first orchestration CLI for the workflow you have already been using manually:
4
+
5
+ 1. talk to an AI until the plan is sharp,
6
+ 2. write a four-file planning pack into the repo,
7
+ 3. repeatedly execute the next eligible step,
8
+ 4. force validation and handoff updates every time.
9
+
10
+ The current launch slice supports both local `codex` and local `claude` CLI installs through the same `.srgical/`
11
+ workflow. `srgical` detects which supported tools are actually installed, keeps the planning pack agent-neutral, and
12
+ lets you choose the active agent for the current workspace session.
13
+
14
+ ## Why This Exists
15
+
16
+ The reference system in `G:\code\Launch11Projects\Writr\migrations-part-5` is strong because it does not just create a
17
+ plan. It creates momentum:
18
+
19
+ - a stable architecture file,
20
+ - a current-context handoff log,
21
+ - a step-by-step tracker,
22
+ - and a repeatable next-agent prompt that keeps execution disciplined.
23
+
24
+ `srgical` turns that from a repeated copy-paste ritual into a product.
25
+
26
+ ## Current Slice
27
+
28
+ This repo currently ships the foundation for:
29
+
30
+ - `srgical doctor`
31
+ Reports whether the current workspace has a planning pack, which supported agent is active, and which supported
32
+ agents are available locally.
33
+ - `srgical init`
34
+ Creates a local `.srgical/` planning pack from built-in templates.
35
+ - `srgical studio`
36
+ Opens a full-screen planning studio where you can plan against the repo, inspect supported tools with `/agents`,
37
+ switch the session agent with `/agent <id>`, and explicitly trigger pack writes or execution.
38
+ - `srgical run-next`
39
+ Replays the generated next-agent prompt through the active agent, with `--dry-run` for safe preview and
40
+ `--agent <id>` for a one-run override that does not change the stored workspace choice.
41
+
42
+ ## Supported Agents
43
+
44
+ - `codex`
45
+ Supported in the current launch slice for planning, pack writing, and `run-next` execution.
46
+ - `claude`
47
+ Supported through the same adapter seam for planning, pack writing, and execution when the local Claude Code CLI is
48
+ installed and available on `PATH`.
49
+
50
+ If only one supported agent is installed, `srgical` can auto-select it for the workspace session. If both are
51
+ installed, you can keep the stored choice in the studio and still override a single execution with
52
+ `srgical run-next --agent <id>`.
53
+
54
+ ## Design Direction
55
+
56
+ The product should feel closer to a creative control room than a grey enterprise shell:
57
+
58
+ - dark graphite base
59
+ - hot coral and amber accents
60
+ - crisp cyan status treatment
61
+ - large, cinematic panel framing
62
+ - transcript-first layout instead of command soup
63
+
64
+ The first TUI pass already leans in that direction, and we can keep pushing it.
65
+
66
+ ## Distribution
67
+
68
+ The first production channels are GitHub Packages, the public npm registry, and GitHub Releases for downloadable
69
+ release assets. Version intent stays in git, and GitHub Actions bumps `package.json`, writes `CHANGELOG.md`, pushes
70
+ that release commit back to `main`, publishes the GitHub-scoped package, publishes the npm org package, and creates a
71
+ GitHub Release with the built tarballs attached.
72
+
73
+ For a local production-style packaging check:
74
+
75
+ ```bash
76
+ npm run release:pack
77
+ ```
78
+
79
+ The release bundle lands under `.artifacts/release/`. The broader distribution path, including standalone binaries and
80
+ wrapper package-manager installs, is documented in `docs/distribution.md`.
81
+
82
+ For release work, add a changeset in your feature branch:
83
+
84
+ ```bash
85
+ npm run changeset
86
+ ```
87
+
88
+ When that branch reaches `main`, the release workflow versions the package, publishes `@launcheleven/srgical` to
89
+ GitHub Packages, publishes `@launch11/srgical` to npm, and opens a matching GitHub Release entry with the packaged
90
+ artifacts.
91
+
92
+ ## Install Prerequisites
93
+
94
+ Install `srgical`, then install at least one supported local agent CLI separately.
95
+
96
+ ```bash
97
+ npm install
98
+ npm run build
99
+ node dist/index.js doctor
100
+ ```
101
+
102
+ `doctor` is the source of truth for local availability. If an agent CLI is missing, `srgical` reports it as missing
103
+ instead of pretending it can run that path anyway.
104
+
105
+ The package publishes in two install channels:
106
+
107
+ - GitHub Packages: `@launcheleven/srgical`
108
+ - npm public registry: `@launch11/srgical`
109
+
110
+ For GitHub Packages installs, consumers need an `.npmrc` entry for `@launcheleven` plus a token before running:
111
+
112
+ ```bash
113
+ npm install -g @launcheleven/srgical
114
+ ```
115
+
116
+ For npm installs, consumers can use:
117
+
118
+ ```bash
119
+ npm install -g @launch11/srgical
120
+ ```
121
+
122
+ ## Getting Started
123
+
124
+ ```bash
125
+ npm install
126
+ npm run build
127
+ node dist/index.js doctor
128
+ node dist/index.js studio
129
+ ```
130
+
131
+ During development:
132
+
133
+ ```bash
134
+ npm run dev -- studio
135
+ ```
136
+
137
+ Typical flow once a workspace has a pack:
138
+
139
+ ```bash
140
+ node dist/index.js doctor
141
+ node dist/index.js run-next --dry-run
142
+ node dist/index.js run-next
143
+ ```
144
+
145
+ To override the active workspace agent for one execution only:
146
+
147
+ ```bash
148
+ node dist/index.js run-next --agent codex
149
+ node dist/index.js run-next --agent claude
150
+ ```
151
+
152
+ ## Current Claude Caveat
153
+
154
+ Claude support is real, but it is not treated as interchangeable with Codex. The current non-interactive Claude path
155
+ uses `plan` mode for planner replies and `acceptEdits` with allowlisted local tools for pack-writing and execution.
156
+
157
+ If the Claude CLI is not installed locally, `doctor`, the studio, and `run-next --agent claude` all report that
158
+ honestly instead of falling back to a fake Claude path.
159
+
160
+ ## Planned Next Steps
161
+
162
+ - deepen the studio experience without weakening the terminal-first workflow
163
+ - keep dual-agent docs and validation honest as Claude runtime behavior gets more live coverage
164
+ - expand release outputs from npm tarballs into standalone binaries and wrapper package-manager installers
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runDoctorCommand = runDoctorCommand;
7
+ const node_process_1 = __importDefault(require("node:process"));
8
+ const agent_1 = require("../core/agent");
9
+ const planning_pack_state_1 = require("../core/planning-pack-state");
10
+ const workspace_1 = require("../core/workspace");
11
+ async function runDoctorCommand(workspaceArg) {
12
+ const workspace = (0, workspace_1.resolveWorkspace)(workspaceArg);
13
+ const [resolvedAgent, packState, gitRepo] = await Promise.all([
14
+ (0, agent_1.resolvePrimaryAgent)(workspace),
15
+ (0, planning_pack_state_1.readPlanningPackState)(workspace),
16
+ (0, workspace_1.isGitRepo)(workspace)
17
+ ]);
18
+ const { status: activeAgent, statuses } = resolvedAgent;
19
+ const lines = [
20
+ `Workspace: ${workspace}`,
21
+ `Git repo: ${gitRepo ? "yes" : "no"}`,
22
+ `Planning pack: ${packState.packPresent ? "present" : "missing"}`,
23
+ `Active agent: ${activeAgent.label} (${activeAgent.id}) - ${formatAgentAvailability(activeAgent)}`,
24
+ "",
25
+ ...renderSupportedAgentLines(statuses, activeAgent.id),
26
+ ];
27
+ if (packState.packPresent) {
28
+ lines.push("", ...renderNextStepLines(packState.nextStepSummary, packState.currentPosition.nextRecommended));
29
+ }
30
+ lines.push("", packState.packPresent
31
+ ? packState.nextStepSummary || packState.currentPosition.nextRecommended
32
+ ? "Next move: run `srgical studio` to refine the plan or `srgical run-next` to execute the next step."
33
+ : "Next move: run `srgical studio` to queue more work or update the tracker with a new recommended step."
34
+ : "Next move: run `srgical init` for a local scaffold or `srgical studio` to plan with the primary agent first.");
35
+ node_process_1.default.stdout.write(`${lines.join("\n")}\n`);
36
+ }
37
+ function renderSupportedAgentLines(statuses, activeAgentId) {
38
+ const lines = ["Supported agents:"];
39
+ for (const status of statuses) {
40
+ lines.push(`- ${status.label} (${status.id})${status.id === activeAgentId ? " [active]" : ""}: ${formatAgentAvailability(status)} via ${status.command}`);
41
+ }
42
+ return lines;
43
+ }
44
+ function formatAgentAvailability(status) {
45
+ return status.available
46
+ ? `available (${status.version ?? "version unknown"})`
47
+ : `missing (${status.error ?? "unknown error"})`;
48
+ }
49
+ function renderNextStepLines(nextStepSummary, nextRecommended) {
50
+ if (!nextStepSummary) {
51
+ return [
52
+ "Next Step: unavailable",
53
+ nextRecommended
54
+ ? `Tracker points to \`${nextRecommended}\`, but its table row could not be summarized.`
55
+ : "Tracker does not currently expose a next recommended step."
56
+ ];
57
+ }
58
+ const lines = [
59
+ `Next Step: ${nextStepSummary.id}${nextStepSummary.phase ? ` (${nextStepSummary.phase})` : ""}`,
60
+ ` Scope: ${nextStepSummary.scope || "unknown"}`,
61
+ ` Acceptance: ${nextStepSummary.acceptance || "unknown"}`,
62
+ ` Status: ${nextStepSummary.status || "unknown"}`
63
+ ];
64
+ if (nextStepSummary.notes) {
65
+ lines.push(` Notes: ${nextStepSummary.notes}`);
66
+ }
67
+ return lines;
68
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runInitCommand = runInitCommand;
7
+ const node_process_1 = __importDefault(require("node:process"));
8
+ const templates_1 = require("../core/templates");
9
+ const workspace_1 = require("../core/workspace");
10
+ async function runInitCommand(workspaceArg, force = false) {
11
+ const workspace = (0, workspace_1.resolveWorkspace)(workspaceArg);
12
+ const exists = await (0, workspace_1.planningPackExists)(workspace);
13
+ if (exists && !force) {
14
+ throw new Error("A .srgical planning pack already exists. Re-run with --force to overwrite it.");
15
+ }
16
+ const paths = await (0, workspace_1.ensurePlanningDir)(workspace);
17
+ const templates = (0, templates_1.getInitialTemplates)(paths);
18
+ await Promise.all(Object.entries(templates).map(([filePath, content]) => (0, workspace_1.writeText)(filePath, content)));
19
+ node_process_1.default.stdout.write([
20
+ `Created planning pack in ${paths.dir}`,
21
+ `- ${paths.plan}`,
22
+ `- ${paths.context}`,
23
+ `- ${paths.tracker}`,
24
+ `- ${paths.nextPrompt}`
25
+ ].join("\n") + "\n");
26
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runRunNextCommand = runRunNextCommand;
7
+ const node_process_1 = __importDefault(require("node:process"));
8
+ const agent_1 = require("../core/agent");
9
+ const execution_state_1 = require("../core/execution-state");
10
+ const execution_controls_1 = require("../core/execution-controls");
11
+ const planning_pack_state_1 = require("../core/planning-pack-state");
12
+ const workspace_1 = require("../core/workspace");
13
+ async function runRunNextCommand(workspaceArg, options = {}) {
14
+ const workspace = (0, workspace_1.resolveWorkspace)(workspaceArg);
15
+ const packState = await (0, planning_pack_state_1.readPlanningPackState)(workspace);
16
+ if (!packState.packPresent) {
17
+ throw new Error("No .srgical planning pack found. Run `srgical init` or `srgical studio` first.");
18
+ }
19
+ if (!options.dryRun && !(0, execution_controls_1.hasQueuedNextStep)(packState.currentPosition.nextRecommended)) {
20
+ throw new Error((0, execution_controls_1.formatNoQueuedNextStepMessage)("run-next"));
21
+ }
22
+ await (0, agent_1.resolveExecutionAgent)(workspace, options.agent);
23
+ const paths = (0, workspace_1.getPlanningPackPaths)(workspace);
24
+ const prompt = await (0, workspace_1.readText)(paths.nextPrompt);
25
+ const previewLines = options.dryRun
26
+ ? (0, execution_controls_1.renderDryRunPreview)(prompt, packState.nextStepSummary, packState.currentPosition.nextRecommended)
27
+ : (0, execution_controls_1.renderExecutionStepLines)(packState.nextStepSummary, packState.currentPosition.nextRecommended);
28
+ for (const line of previewLines) {
29
+ node_process_1.default.stdout.write(`${line}\n`);
30
+ }
31
+ if (options.dryRun) {
32
+ return;
33
+ }
34
+ node_process_1.default.stdout.write("\n");
35
+ node_process_1.default.stdout.write(`Running the current next-agent prompt through ${(0, agent_1.getPrimaryAgentAdapter)().label}...\n`);
36
+ try {
37
+ const result = await (0, agent_1.runNextPrompt)(workspace, prompt, {
38
+ agentId: options.agent
39
+ });
40
+ await (0, execution_state_1.saveExecutionState)(workspace, "success", "run-next", result);
41
+ await (0, execution_state_1.appendExecutionLog)(workspace, "success", "run-next", result, {
42
+ stepLabel: (0, execution_controls_1.formatStepLabel)(packState.nextStepSummary, packState.currentPosition.nextRecommended)
43
+ });
44
+ node_process_1.default.stdout.write(`${result}\n`);
45
+ }
46
+ catch (error) {
47
+ const message = error instanceof Error ? error.message : String(error);
48
+ await (0, execution_state_1.saveExecutionState)(workspace, "failure", "run-next", message);
49
+ await (0, execution_state_1.appendExecutionLog)(workspace, "failure", "run-next", message, {
50
+ stepLabel: (0, execution_controls_1.formatStepLabel)(packState.nextStepSummary, packState.currentPosition.nextRecommended)
51
+ });
52
+ throw new Error((0, execution_controls_1.formatExecutionFailureMessage)(message, packState.nextStepSummary, packState.currentPosition.nextRecommended, "run-next"));
53
+ }
54
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runStudioCommand = runStudioCommand;
4
+ const studio_1 = require("../ui/studio");
5
+ async function runStudioCommand(workspaceArg) {
6
+ await (0, studio_1.launchStudio)({ workspace: workspaceArg });
7
+ }
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSupportedAgentAdapters = getSupportedAgentAdapters;
4
+ exports.getPrimaryAgentAdapter = getPrimaryAgentAdapter;
5
+ exports.detectSupportedAgents = detectSupportedAgents;
6
+ exports.resolvePrimaryAgent = resolvePrimaryAgent;
7
+ exports.detectPrimaryAgent = detectPrimaryAgent;
8
+ exports.resolveExecutionAgent = resolveExecutionAgent;
9
+ exports.requestPlannerReply = requestPlannerReply;
10
+ exports.writePlanningPack = writePlanningPack;
11
+ exports.runNextPrompt = runNextPrompt;
12
+ exports.selectPrimaryAgent = selectPrimaryAgent;
13
+ exports.resetAgentAdaptersForTesting = resetAgentAdaptersForTesting;
14
+ exports.setAgentAdaptersForTesting = setAgentAdaptersForTesting;
15
+ const claude_1 = require("./claude");
16
+ const codex_1 = require("./codex");
17
+ const studio_session_1 = require("./studio-session");
18
+ const codexAdapter = {
19
+ id: "codex",
20
+ label: "Codex",
21
+ async detectStatus() {
22
+ const status = await (0, codex_1.detectCodex)();
23
+ return {
24
+ id: "codex",
25
+ label: "Codex",
26
+ available: status.available,
27
+ command: status.command,
28
+ version: status.version,
29
+ error: status.error
30
+ };
31
+ },
32
+ requestPlannerReply: codex_1.requestPlannerReply,
33
+ writePlanningPack: codex_1.writePlanningPack,
34
+ runNextPrompt: codex_1.runNextPrompt
35
+ };
36
+ const claudeAdapter = {
37
+ id: "claude",
38
+ label: "Claude Code",
39
+ async detectStatus() {
40
+ const status = await (0, claude_1.detectClaude)();
41
+ return {
42
+ id: "claude",
43
+ label: "Claude Code",
44
+ available: status.available,
45
+ command: status.command,
46
+ version: status.version,
47
+ error: status.error
48
+ };
49
+ },
50
+ requestPlannerReply: claude_1.requestPlannerReply,
51
+ writePlanningPack: claude_1.writePlanningPack,
52
+ runNextPrompt: claude_1.runNextPrompt
53
+ };
54
+ const defaultAgentAdapters = [codexAdapter, claudeAdapter];
55
+ let registeredAgentAdapters = [...defaultAgentAdapters];
56
+ let primaryAgentId = registeredAgentAdapters[0].id;
57
+ function getSupportedAgentAdapters() {
58
+ return [...registeredAgentAdapters];
59
+ }
60
+ function getPrimaryAgentAdapter() {
61
+ return getAgentAdapterById(primaryAgentId) ?? getSupportedAgentAdapters()[0];
62
+ }
63
+ async function detectSupportedAgents(workspaceRoot) {
64
+ const statuses = await collectAgentStatuses();
65
+ syncPrimaryAgent((await resolvePrimaryAgentStatus(statuses, workspaceRoot)).id);
66
+ return statuses;
67
+ }
68
+ async function resolvePrimaryAgent(workspaceRoot) {
69
+ const statuses = await collectAgentStatuses();
70
+ const status = await resolvePrimaryAgentStatus(statuses, workspaceRoot);
71
+ const adapter = getAgentAdapterById(status.id) ?? getSupportedAgentAdapters()[0];
72
+ syncPrimaryAgent(adapter.id);
73
+ return {
74
+ adapter,
75
+ status,
76
+ statuses
77
+ };
78
+ }
79
+ async function detectPrimaryAgent(workspaceRoot) {
80
+ return (await resolvePrimaryAgent(workspaceRoot)).status;
81
+ }
82
+ async function resolveExecutionAgent(workspaceRoot, overrideId) {
83
+ const normalizedOverrideId = overrideId?.trim().toLowerCase();
84
+ if (!normalizedOverrideId) {
85
+ return resolvePrimaryAgent(workspaceRoot);
86
+ }
87
+ const statuses = await collectAgentStatuses();
88
+ const status = statuses.find((candidate) => candidate.id === normalizedOverrideId);
89
+ if (!status) {
90
+ throw new Error(`Unknown agent \`${overrideId}\`. Supported agents: ${getSupportedAgentAdapters().map((adapter) => adapter.id).join(", ")}.`);
91
+ }
92
+ if (!status.available) {
93
+ throw new Error(`Cannot use ${status.label} for this run: ${status.error ?? `${status.command} is not available`}.`);
94
+ }
95
+ const adapter = getAgentAdapterById(status.id) ?? getSupportedAgentAdapters()[0];
96
+ syncPrimaryAgent(adapter.id);
97
+ return {
98
+ adapter,
99
+ status,
100
+ statuses
101
+ };
102
+ }
103
+ async function requestPlannerReply(workspaceRoot, messages) {
104
+ const { adapter } = await resolvePrimaryAgent(workspaceRoot);
105
+ return adapter.requestPlannerReply(workspaceRoot, messages);
106
+ }
107
+ async function writePlanningPack(workspaceRoot, messages) {
108
+ const { adapter } = await resolvePrimaryAgent(workspaceRoot);
109
+ return adapter.writePlanningPack(workspaceRoot, messages);
110
+ }
111
+ async function runNextPrompt(workspaceRoot, prompt, options = {}) {
112
+ const { adapter } = await resolveExecutionAgent(workspaceRoot, options.agentId);
113
+ return adapter.runNextPrompt(workspaceRoot, prompt);
114
+ }
115
+ async function selectPrimaryAgent(workspaceRoot, id) {
116
+ const normalizedId = id.trim().toLowerCase();
117
+ const statuses = await collectAgentStatuses();
118
+ const status = statuses.find((candidate) => candidate.id === normalizedId);
119
+ if (!status) {
120
+ throw new Error(`Unknown agent \`${id}\`. Supported agents: ${getSupportedAgentAdapters().map((adapter) => adapter.id).join(", ")}.`);
121
+ }
122
+ if (!status.available) {
123
+ throw new Error(`Cannot activate ${status.label}: ${status.error ?? `${status.command} is not available`}.`);
124
+ }
125
+ await (0, studio_session_1.saveStoredActiveAgentId)(workspaceRoot, status.id);
126
+ const adapter = getAgentAdapterById(status.id) ?? getSupportedAgentAdapters()[0];
127
+ syncPrimaryAgent(adapter.id);
128
+ return {
129
+ adapter,
130
+ status,
131
+ statuses
132
+ };
133
+ }
134
+ function resetAgentAdaptersForTesting() {
135
+ registeredAgentAdapters = [...defaultAgentAdapters];
136
+ primaryAgentId = registeredAgentAdapters[0].id;
137
+ }
138
+ function setAgentAdaptersForTesting(adapters) {
139
+ registeredAgentAdapters = adapters.length > 0 ? [...adapters] : [...defaultAgentAdapters];
140
+ primaryAgentId = registeredAgentAdapters[0].id;
141
+ }
142
+ async function collectAgentStatuses() {
143
+ return Promise.all(getSupportedAgentAdapters().map((adapter) => adapter.detectStatus()));
144
+ }
145
+ async function resolvePrimaryAgentStatus(statuses, workspaceRoot) {
146
+ const storedId = workspaceRoot ? await (0, studio_session_1.loadStoredActiveAgentId)(workspaceRoot) : null;
147
+ if (storedId) {
148
+ const storedStatus = statuses.find((status) => status.id === storedId);
149
+ if (storedStatus) {
150
+ return storedStatus;
151
+ }
152
+ if (workspaceRoot) {
153
+ await (0, studio_session_1.saveStoredActiveAgentId)(workspaceRoot, null);
154
+ }
155
+ }
156
+ return statuses.find((status) => status.available) ?? statuses[0];
157
+ }
158
+ function getAgentAdapterById(id) {
159
+ return registeredAgentAdapters.find((adapter) => adapter.id === id);
160
+ }
161
+ function syncPrimaryAgent(id) {
162
+ const adapter = getAgentAdapterById(id) ?? getSupportedAgentAdapters()[0];
163
+ primaryAgentId = adapter.id;
164
+ }