feat(agents): add agents list and demote presets to UI configuration#4097
feat(agents): add agents list and demote presets to UI configuration#4097saddlepaddle merged 2 commits intomainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdd end-to-end agent support: shared host presets, host-service agent-config schema and endpoints, MCP host-call refactor and new tools (agents_list), SDK Agents resource, CLI agents list command, desktop settings UI updates, and tests adapted for the new add flow. ChangesAgent List / Run (single cohesive change DAG)
Sequence DiagramsequenceDiagram
participant CLI as CLI / MCP Tool
participant SDK as SDK Client (Agents)
participant Host as Host Service (TRPC)
participant Desktop as Desktop UI
CLI->>SDK: Agents.list(hostId, orgId)
SDK->>Host: GET /trpc/settings.agentConfigs.list?input=... (host query)
Host-->>SDK: HostAgentConfig[]
SDK-->>CLI: AgentListResponse
Desktop->>Desktop: load HOST_AGENT_PRESETS, build map
Desktop->>SDK: Agents.run(workspaceId, agent, prompt, orgId)
SDK->>Host: GET /trpc/v2Workspace.getFromHost?input=... (resolve host/workspace)
Host-->>SDK: workspace (with hostId)
SDK->>Host: POST /trpc/agents.run (mutation with body)
Host-->>SDK: AgentRunResult
SDK-->>Desktop: sessionId, label
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile Summary
Confidence Score: 4/5Safe to merge; the only issue is a display edge case with empty preset results. P2-only finding: display headers are wrong when --presets returns an empty list, but this doesn't affect correctness of the data or the common case. Core routing and auth logic mirrors existing commands. packages/cli/src/commands/agents/list/command.ts — display mode-detection heuristic
|
| Filename | Overview |
|---|---|
| packages/cli/src/commands/agents/list/command.ts | New command wiring requireHostTarget/resolveHostTarget correctly; display mode detection inferred from data shape rather than options flag, causing wrong headers for empty preset results. |
| packages/cli/src/commands/agents/meta.ts | Trivial description update to 'Manage and run agents' to reflect the new list subcommand. |
Sequence Diagram
sequenceDiagram
participant User
participant CLI as agents list command
participant HT as requireHostTarget / resolveHostTarget
participant HS as Host Service (tRPC)
User->>CLI: superset agents list [--local|--host id] [--presets]
CLI->>CLI: check organizationId
CLI->>HT: requireHostTarget({ host, local })
HT-->>CLI: hostId (or throw CLIError)
CLI->>HT: resolveHostTarget({ hostId, orgId, jwt })
HT-->>CLI: ResolvedHostTarget (local or remote client)
alt --presets flag
CLI->>HS: settings.agentConfigs.listPresets.query()
HS-->>CLI: [{ label, presetId, command }]
else no --presets flag
CLI->>HS: settings.agentConfigs.list.query()
HS-->>CLI: [{ label, presetId, command, id }]
end
CLI->>User: table output
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 1
packages/cli/src/commands/agents/list/command.ts:15-26
**Fragile preset-mode detection in `display`**
`isPresetMode` is inferred from the absence of an `id` field in the first row rather than from the `options.presets` flag, which is not forwarded to `display`. This works today because the two tRPC procedures return differently-shaped objects, but it silently breaks in two edge cases: (1) `--presets` is passed and the server returns an empty list → `isPresetMode` is `false` → the 4-column table (including the "ID" header) is rendered instead of the correct 3-column preset table; (2) if the presets schema ever gains an `id` field, both branches would render the same 4-column layout.
Consider passing mode intent explicitly (e.g. a tagged union `{ kind: "presets"; rows: … } | { kind: "agents"; rows: … }`) or moving the column selection into the `run` handler's return value so `display` doesn't have to reverse-engineer it.
Reviews (1): Last reviewed commit: "feat(cli/agents): add agents list comman..." | Re-trigger Greptile
| const rows = (data ?? []) as Record<string, unknown>[]; | ||
| const isPresetMode = rows.length > 0 && !("id" in rows[0]!); | ||
| return isPresetMode | ||
| ? table( | ||
| rows, | ||
| ["label", "presetId", "command"], | ||
| ["LABEL", "PRESET", "COMMAND"], | ||
| ) | ||
| : table( | ||
| rows, | ||
| ["label", "presetId", "command", "id"], | ||
| ["LABEL", "PRESET", "COMMAND", "ID"], |
There was a problem hiding this comment.
Fragile preset-mode detection in
display
isPresetMode is inferred from the absence of an id field in the first row rather than from the options.presets flag, which is not forwarded to display. This works today because the two tRPC procedures return differently-shaped objects, but it silently breaks in two edge cases: (1) --presets is passed and the server returns an empty list → isPresetMode is false → the 4-column table (including the "ID" header) is rendered instead of the correct 3-column preset table; (2) if the presets schema ever gains an id field, both branches would render the same 4-column layout.
Consider passing mode intent explicitly (e.g. a tagged union { kind: "presets"; rows: … } | { kind: "agents"; rows: … }) or moving the column selection into the run handler's return value so display doesn't have to reverse-engineer it.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/cli/src/commands/agents/list/command.ts
Line: 15-26
Comment:
**Fragile preset-mode detection in `display`**
`isPresetMode` is inferred from the absence of an `id` field in the first row rather than from the `options.presets` flag, which is not forwarded to `display`. This works today because the two tRPC procedures return differently-shaped objects, but it silently breaks in two edge cases: (1) `--presets` is passed and the server returns an empty list → `isPresetMode` is `false` → the 4-column table (including the "ID" header) is rendered instead of the correct 3-column preset table; (2) if the presets schema ever gains an `id` field, both branches would render the same 4-column layout.
Consider passing mode intent explicitly (e.g. a tagged union `{ kind: "presets"; rows: … } | { kind: "agents"; rows: … }`) or moving the column selection into the `run` handler's return value so `display` doesn't have to reverse-engineer it.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/commands/agents/list/command.ts`:
- Around line 15-27: The column selection currently infers preset mode from
rows[0] (isPresetMode) which breaks for empty results; instead propagate the
--presets flag from the command's run into the display logic and use that
boolean to decide columns: modify the command's run to pass a explicit
isPresetMode (e.g., derived from options.presets) into the display/table chooser
and update the display code that currently computes isPresetMode from rows to
use that passed boolean when present, keeping the fallback to the original
shape-based check only if the flag is undefined.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 19e66c93-faff-48f7-9e25-1884acaa3ef2
📒 Files selected for processing (2)
packages/cli/src/commands/agents/list/command.tspackages/cli/src/commands/agents/meta.ts
| const rows = (data ?? []) as Record<string, unknown>[]; | ||
| const isPresetMode = rows.length > 0 && !("id" in rows[0]!); | ||
| return isPresetMode | ||
| ? table( | ||
| rows, | ||
| ["label", "presetId", "command"], | ||
| ["LABEL", "PRESET", "COMMAND"], | ||
| ) | ||
| : table( | ||
| rows, | ||
| ["label", "presetId", "command", "id"], | ||
| ["LABEL", "PRESET", "COMMAND", "ID"], | ||
| ); |
There was a problem hiding this comment.
Use the --presets flag to drive columns; current shape-based inference is wrong for empty results.
On Line 16, mode is inferred from rows[0]. If --presets returns [], the command falls back to configured-agent headers (ID column), so output no longer reflects the selected mode.
Proposed fix (carry mode from run to display)
export default command({
@@
- display: (data) => {
- const rows = (data ?? []) as Record<string, unknown>[];
- const isPresetMode = rows.length > 0 && !("id" in rows[0]!);
+ display: (data) => {
+ const payload = (data ?? {
+ rows: [],
+ isPresetMode: false,
+ }) as { rows: Record<string, unknown>[]; isPresetMode: boolean };
+ const { rows, isPresetMode } = payload;
return isPresetMode
@@
run: async ({ ctx, options }) => {
@@
- if (options.presets) {
- return target.client.settings.agentConfigs.listPresets.query();
- }
- return target.client.settings.agentConfigs.list.query();
+ if (options.presets) {
+ const rows = await target.client.settings.agentConfigs.listPresets.query();
+ return { rows, isPresetMode: true };
+ }
+ const rows = await target.client.settings.agentConfigs.list.query();
+ return { rows, isPresetMode: false };
},
});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/cli/src/commands/agents/list/command.ts` around lines 15 - 27, The
column selection currently infers preset mode from rows[0] (isPresetMode) which
breaks for empty results; instead propagate the --presets flag from the
command's run into the display logic and use that boolean to decide columns:
modify the command's run to pass a explicit isPresetMode (e.g., derived from
options.presets) into the display/table chooser and update the display code that
currently computes isPresetMode from rows to use that passed boolean when
present, keeping the fallback to the original shape-based check only if the flag
is undefined.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/mcp-v2/src/host-service-client.ts (1)
124-155: ⚡ Quick winExtract shared tRPC response decode/error handling to avoid drift
hostServiceQuerynow duplicates the same JSON parse/envelope validation/deserialization branch already present inhostServiceMutation. Pulling this into a shared helper would reduce divergence risk when relay error handling evolves.Refactor sketch
+function decodeTrpcData<TOutput>( + rawBody: string, + responseStatus: number, + hostId: string, + procedure: string, +): TOutput { + type TrpcEnvelope = { result?: { data?: unknown } }; + let parsed: TrpcEnvelope; + try { + parsed = JSON.parse(rawBody) as TrpcEnvelope; + } catch { + throw new HostServiceCallError( + `invalid JSON from relay: ${rawBody.slice(0, 200)}`, + responseStatus, + rawBody, + ); + } + const data = parsed.result?.data; + if (data === undefined || data === null) { + throw new HostServiceCallError( + `Malformed response from host ${hostId} for ${procedure}`, + responseStatus, + rawBody, + ); + } + return SuperJSON.deserialize( + data as Parameters<typeof SuperJSON.deserialize>[0], + ) as TOutput; +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mcp-v2/src/host-service-client.ts` around lines 124 - 155, hostServiceQuery duplicates the JSON parse/envelope validation/deserialization logic that's also in hostServiceMutation; extract that shared logic into a single helper (e.g., parseTrpcEnvelope or decodeTrpcResponse) that takes rawBody, response.status, options.hostId, procedure and returns the deserialized data or throws HostServiceCallError with the same messages (including describeRelayFailure usage for non-ok responses and JSON parse/ malformed response messages), then replace the inlined blocks in both hostServiceQuery and hostServiceMutation to call the new helper and return SuperJSON.deserialize(...) on the helper result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/mcp-v2/src/host-service-client.ts`:
- Around line 124-155: hostServiceQuery duplicates the JSON parse/envelope
validation/deserialization logic that's also in hostServiceMutation; extract
that shared logic into a single helper (e.g., parseTrpcEnvelope or
decodeTrpcResponse) that takes rawBody, response.status, options.hostId,
procedure and returns the deserialized data or throws HostServiceCallError with
the same messages (including describeRelayFailure usage for non-ok responses and
JSON parse/ malformed response messages), then replace the inlined blocks in
both hostServiceQuery and hostServiceMutation to call the new helper and return
SuperJSON.deserialize(...) on the helper result.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1da44cdc-32df-43b3-a993-1638c45ab839
📒 Files selected for processing (8)
packages/mcp-v2/src/host-service-client.tspackages/mcp-v2/src/tools/agents/list.tspackages/mcp-v2/src/tools/agents/list_presets.tspackages/mcp-v2/src/tools/register.tspackages/sdk/src/client.tspackages/sdk/src/index.tspackages/sdk/src/resources/agents.tspackages/sdk/src/resources/index.ts
✅ Files skipped from review due to trivial changes (1)
- packages/sdk/src/index.ts
95b0db0 to
e732061
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/host-service/src/trpc/router/settings/agent-configs.ts (1)
157-206:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
settings.agentConfigs.listPresetsis missing from the router surface.The settings router no longer exposes a
listPresetsquery, but the PR objective calls out preset listing via this route (--presets/MCP presets tooling). This is a runtime contract break (procedure not found) for those consumers.Suggested patch
import { + HOST_AGENT_PRESETS, getDefaultSeedPresets, type HostAgentPreset, } from "@superset/shared/host-agent-presets"; export const agentConfigsRouter = router({ + listPresets: protectedProcedure.query(() => + HOST_AGENT_PRESETS.map((preset) => ({ + ...preset, + args: [...preset.args], + promptArgs: [...preset.promptArgs], + env: { ...preset.env }, + })), + ), + /** * List configured host agents in persisted order. Seeds bundled defaults * on first call when no configs exist. */ list: protectedProcedure.query(({ ctx }) => {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/host-service/src/trpc/router/settings/agent-configs.ts` around lines 157 - 206, The router dropped the listPresets procedure — re-add a protectedProcedure named listPresets to agentConfigsRouter so callers can list bundled presets; implement it to return the same preset data used when seeding defaults (e.g. reuse seedDefaultsIfEmpty or the helper that constructs bundled presets) and ensure its output shape matches the consumers' expectation (the same toOutput/DTO structure or a dedicated preset output). Reference: agentConfigsRouter, listPresets, seedDefaultsIfEmpty, toOutput.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/src/commands/agents/list/command.ts`:
- Around line 7-16: Add a new boolean option "presets" to the command's options
(alongside host and local), ensure run reads that flag and calls
settings.agentConfigs.listPresets when presets is true (falling back to
settings.agentConfigs.list otherwise), and pass the explicit presets mode into
display so it does not infer mode from results; update display/table invocation
to use columns ["label","presetId","command"] with headers
["LABEL","PRESET","COMMAND"] when presets is true (omit "id"), and keep the
existing four-column display when presets is false.
In `@packages/sdk/src/resources/agents.ts`:
- Around line 13-31: The Agents SDK class is missing a listPresets() method to
mirror server API parity; add a new public method Agents.listPresets(params:
AgentListParams, options?: RequestOptions) that calls this._requireOrgId() then
returns this._client.hostQuery<AgentListResponse>(params.hostId,
"settings.agentConfigs.listPresets", undefined, options) (following the existing
list() pattern) so SDK consumers can retrieve the preset catalog; ensure the new
method name is Agents.listPresets and matches the hostQuery namespace
"settings.agentConfigs.listPresets".
---
Outside diff comments:
In `@packages/host-service/src/trpc/router/settings/agent-configs.ts`:
- Around line 157-206: The router dropped the listPresets procedure — re-add a
protectedProcedure named listPresets to agentConfigsRouter so callers can list
bundled presets; implement it to return the same preset data used when seeding
defaults (e.g. reuse seedDefaultsIfEmpty or the helper that constructs bundled
presets) and ensure its output shape matches the consumers' expectation (the
same toOutput/DTO structure or a dedicated preset output). Reference:
agentConfigsRouter, listPresets, seedDefaultsIfEmpty, toOutput.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c0cc5edf-f8e4-479e-8c90-5e085656d822
📒 Files selected for processing (17)
apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/V2AgentsSettings.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentDetail/AgentDetail.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentsSettingsSidebar/AgentsSettingsSidebar.tsxpackages/cli/src/commands/agents/list/command.tspackages/cli/src/commands/agents/meta.tspackages/host-service/src/trpc/router/settings/agent-configs.test.tspackages/host-service/src/trpc/router/settings/agent-configs.tspackages/host-service/src/trpc/router/settings/index.tspackages/mcp-v2/src/host-service-client.tspackages/mcp-v2/src/tools/agents/list.tspackages/mcp-v2/src/tools/register.tspackages/sdk/src/client.tspackages/sdk/src/index.tspackages/sdk/src/resources/agents.tspackages/sdk/src/resources/index.tspackages/shared/package.jsonpackages/shared/src/host-agent-presets.ts
💤 Files with no reviewable changes (1)
- packages/host-service/src/trpc/router/settings/index.ts
✅ Files skipped from review due to trivial changes (3)
- packages/cli/src/commands/agents/meta.ts
- apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentDetail/AgentDetail.tsx
- packages/sdk/src/client.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/mcp-v2/src/tools/agents/list.ts
- packages/mcp-v2/src/tools/register.ts
- packages/mcp-v2/src/host-service-client.ts
| options: { | ||
| host: string().desc("Target host machineId"), | ||
| local: boolean().desc("Target this machine"), | ||
| }, | ||
| display: (data) => | ||
| table( | ||
| (data ?? []) as Record<string, unknown>[], | ||
| ["label", "presetId", "command", "id"], | ||
| ["LABEL", "PRESET", "COMMAND", "ID"], | ||
| ), |
There was a problem hiding this comment.
--presets / listPresets flag is absent — contradicts the PR objective.
The PR description explicitly specifies that superset agents list --presets should switch to settings.agentConfigs.listPresets with columns LABEL | PRESET | COMMAND (no ID column). The current implementation only exposes settings.agentConfigs.list and has no --presets option at all.
The previous commit included a --presets flag but contained a bug where preset mode was inferred from rows[0], which broke on empty results. The current commit resolves the bug by removing the feature entirely. If --presets is intentionally deferred, please note it in the PR; otherwise the flag needs to be reinstated with the mode flag propagated explicitly from run to display.
💡 Proposed fix to reinstate --presets with explicit mode propagation
export default command({
description: "List agents configured on a host",
options: {
host: string().desc("Target host machineId"),
local: boolean().desc("Target this machine"),
+ presets: boolean().desc("List available agent presets"),
},
- display: (data) =>
- table(
- (data ?? []) as Record<string, unknown>[],
- ["label", "presetId", "command", "id"],
- ["LABEL", "PRESET", "COMMAND", "ID"],
- ),
+ display: (data) => {
+ const payload = (data ?? { rows: [], isPresetMode: false }) as {
+ rows: Record<string, unknown>[];
+ isPresetMode: boolean;
+ };
+ return payload.isPresetMode
+ ? table(payload.rows, ["label", "presetId", "command"], ["LABEL", "PRESET", "COMMAND"])
+ : table(payload.rows, ["label", "presetId", "command", "id"], ["LABEL", "PRESET", "COMMAND", "ID"]);
+ },
run: async ({ ctx, options }) => {
// ... existing organizationId guard and host resolution ...
- return target.client.settings.agentConfigs.list.query();
+ if (options.presets) {
+ const rows = await target.client.settings.agentConfigs.listPresets.query();
+ return { rows, isPresetMode: true };
+ }
+ const rows = await target.client.settings.agentConfigs.list.query();
+ return { rows, isPresetMode: false };
},
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| options: { | |
| host: string().desc("Target host machineId"), | |
| local: boolean().desc("Target this machine"), | |
| }, | |
| display: (data) => | |
| table( | |
| (data ?? []) as Record<string, unknown>[], | |
| ["label", "presetId", "command", "id"], | |
| ["LABEL", "PRESET", "COMMAND", "ID"], | |
| ), | |
| export default command({ | |
| description: "List agents configured on a host", | |
| options: { | |
| host: string().desc("Target host machineId"), | |
| local: boolean().desc("Target this machine"), | |
| presets: boolean().desc("List available agent presets"), | |
| }, | |
| display: (data) => { | |
| const payload = (data ?? { rows: [], isPresetMode: false }) as { | |
| rows: Record<string, unknown>[]; | |
| isPresetMode: boolean; | |
| }; | |
| return payload.isPresetMode | |
| ? table(payload.rows, ["label", "presetId", "command"], ["LABEL", "PRESET", "COMMAND"]) | |
| : table(payload.rows, ["label", "presetId", "command", "id"], ["LABEL", "PRESET", "COMMAND", "ID"]); | |
| }, | |
| run: async ({ ctx, options }) => { | |
| // ... existing organizationId guard and host resolution ... | |
| if (options.presets) { | |
| const rows = await target.client.settings.agentConfigs.listPresets.query(); | |
| return { rows, isPresetMode: true }; | |
| } | |
| const rows = await target.client.settings.agentConfigs.list.query(); | |
| return { rows, isPresetMode: false }; | |
| }, | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/cli/src/commands/agents/list/command.ts` around lines 7 - 16, Add a
new boolean option "presets" to the command's options (alongside host and
local), ensure run reads that flag and calls settings.agentConfigs.listPresets
when presets is true (falling back to settings.agentConfigs.list otherwise), and
pass the explicit presets mode into display so it does not infer mode from
results; update display/table invocation to use columns
["label","presetId","command"] with headers ["LABEL","PRESET","COMMAND"] when
presets is true (omit "id"), and keep the existing four-column display when
presets is false.
| export class Agents extends APIResource { | ||
| /** | ||
| * List agents configured on a host — the rows that drive the agent picker | ||
| * inside workspaces, in persisted display order. Includes user edits to | ||
| * label/command/args/env. First call on a fresh host seeds bundled | ||
| * defaults. | ||
| * | ||
| * Mirrors `superset agents list --host <id>`. | ||
| */ | ||
| list(params: AgentListParams, options?: RequestOptions) { | ||
| this._requireOrgId(); | ||
| return this._client.hostQuery<AgentListResponse>( | ||
| params.hostId, | ||
| "settings.agentConfigs.list", | ||
| undefined, | ||
| options, | ||
| ); | ||
| } | ||
|
|
There was a problem hiding this comment.
SDK Agents resource is missing listPresets() API parity.
This class exposes list() and run() only, but the PR objective includes SDK preset catalog listing. Without listPresets(), SDK consumers can’t access the same preset-list feature exposed in other surfaces.
Suggested patch
export class Agents extends APIResource {
@@
list(params: AgentListParams, options?: RequestOptions) {
this._requireOrgId();
return this._client.hostQuery<AgentListResponse>(
params.hostId,
"settings.agentConfigs.list",
undefined,
options,
);
}
+
+ listPresets(params: AgentListPresetsParams, options?: RequestOptions) {
+ this._requireOrgId();
+ return this._client.hostQuery<AgentListPresetsResponse>(
+ params.hostId,
+ "settings.agentConfigs.listPresets",
+ undefined,
+ options,
+ );
+ }
@@
export interface AgentListParams {
/** Host machineId to query (see `hosts.list()`). */
hostId: string;
}
+
+export interface AgentPreset {
+ presetId: string;
+ label: string;
+ description: string;
+ command: string;
+ args: string[];
+ promptTransport: PromptTransport;
+ promptArgs: string[];
+ env: Record<string, string>;
+}
+
+export interface AgentListPresetsParams {
+ hostId: string;
+}
+
+export type AgentListPresetsResponse = Array<AgentPreset>;
@@
export type {
HostAgentConfig,
AgentListResponse,
AgentListParams,
+ AgentPreset,
+ AgentListPresetsParams,
+ AgentListPresetsResponse,
AgentRunParams,
AgentRunResult,
PromptTransport,
};
}Also applies to: 92-129
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/sdk/src/resources/agents.ts` around lines 13 - 31, The Agents SDK
class is missing a listPresets() method to mirror server API parity; add a new
public method Agents.listPresets(params: AgentListParams, options?:
RequestOptions) that calls this._requireOrgId() then returns
this._client.hostQuery<AgentListResponse>(params.hostId,
"settings.agentConfigs.listPresets", undefined, options) (following the existing
list() pattern) so SDK consumers can retrieve the preset catalog; ensure the new
method name is Agents.listPresets and matches the hostQuery namespace
"settings.agentConfigs.listPresets".
e732061 to
5ba5a49
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/mcp-v2/src/host-service-client.ts`:
- Around line 40-44: The unified fetch call (the response = await fetch(url, {
... })) no longer uses a timeout so host relay requests can hang indefinitely;
restore support for the timeoutMs option by creating an AbortSignal (preferably
using AbortSignal.timeout(timeoutMs) if available, falling back to an
AbortController with setTimeout) and pass it as signal to the fetch call, ensure
the signal is aborted on timeout and that the thrown error propagates so callers
can handle timeouts (update the code that constructs headers/body/method around
response = await fetch(...) to include signal and preserve existing behavior).
- Around line 35-38: In the mutation branch where you currently do
headers["content-type"] = "application/json"; body =
JSON.stringify(SuperJSON.serialize(input)); guard against serializing undefined
by only setting the content-type and body when input is actually provided (e.g.
if (typeof input !== "undefined") { headers["content-type"] =
"application/json"; body = JSON.stringify(SuperJSON.serialize(input)); }).
Reference the existing use of SuperJSON.serialize(input) and the mutation branch
logic to locate where to add the check so void/omitted inputs produce no JSON
body.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e2bb27ee-c513-4eae-aea7-e8373c56239a
📒 Files selected for processing (20)
apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/V2AgentsSettings.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentDetail/AgentDetail.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentsSettingsSidebar/AgentsSettingsSidebar.tsxpackages/cli/src/commands/agents/list/command.tspackages/cli/src/commands/agents/meta.tspackages/host-service/src/trpc/router/settings/agent-configs.test.tspackages/host-service/src/trpc/router/settings/agent-configs.tspackages/host-service/src/trpc/router/settings/index.tspackages/mcp-v2/src/host-service-client.tspackages/mcp-v2/src/tools/agents/list.tspackages/mcp-v2/src/tools/agents/run.tspackages/mcp-v2/src/tools/register.tspackages/mcp-v2/src/tools/workspaces/create.tspackages/mcp-v2/src/tools/workspaces/delete.tspackages/sdk/src/client.tspackages/sdk/src/index.tspackages/sdk/src/resources/agents.tspackages/sdk/src/resources/index.tspackages/shared/package.jsonpackages/shared/src/host-agent-presets.ts
💤 Files with no reviewable changes (1)
- packages/host-service/src/trpc/router/settings/index.ts
✅ Files skipped from review due to trivial changes (4)
- apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentDetail/AgentDetail.tsx
- packages/sdk/src/client.ts
- packages/cli/src/commands/agents/meta.ts
- packages/sdk/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- packages/sdk/src/resources/index.ts
- packages/cli/src/commands/agents/list/command.ts
- apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/V2AgentsSettings.tsx
- packages/host-service/src/trpc/router/settings/agent-configs.test.ts
- packages/sdk/src/resources/agents.ts
- packages/mcp-v2/src/tools/register.ts
| } else { | ||
| headers["content-type"] = "application/json"; | ||
| body = JSON.stringify(SuperJSON.serialize(input)); | ||
| } |
There was a problem hiding this comment.
Guard against serializing undefined in the mutation branch
When input is omitted (allowed by input?: unknown), SuperJSON.serialize(undefined) is called unconditionally. The resulting JSON body ({} after JSON.stringify drops the undefined json field) will surprise any future mutation procedure that accepts void/no input, and will likely produce a cryptic TRPC validation error.
🛡️ Proposed fix
} else {
headers["content-type"] = "application/json";
- body = JSON.stringify(SuperJSON.serialize(input));
+ if (input !== undefined) {
+ body = JSON.stringify(SuperJSON.serialize(input));
+ }
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/mcp-v2/src/host-service-client.ts` around lines 35 - 38, In the
mutation branch where you currently do headers["content-type"] =
"application/json"; body = JSON.stringify(SuperJSON.serialize(input)); guard
against serializing undefined by only setting the content-type and body when
input is actually provided (e.g. if (typeof input !== "undefined") {
headers["content-type"] = "application/json"; body =
JSON.stringify(SuperJSON.serialize(input)); }). Reference the existing use of
SuperJSON.serialize(input) and the mutation branch logic to locate where to add
the check so void/omitted inputs produce no JSON body.
| const response = await fetch(url, { | ||
| method: method === "query" ? "GET" : "POST", | ||
| headers, | ||
| body, | ||
| }); |
There was a problem hiding this comment.
Missing fetch timeout leaves MCP tool calls exposed to indefinite hangs
The previous implementation accepted a timeoutMs option and wired it to an AbortController. The new unified function removes this entirely, meaning a slow or unresponsive host relay will stall the MCP tool call forever — blocking the AI session with no recovery path.
AbortSignal.timeout() returns an AbortSignal that automatically aborts after a specified time, throwing a TimeoutError on expiry. Node.js was the first runtime to add support for AbortSignal.timeout(), backported to the v16 Active LTS release line.
⏱️ Proposed fix
+const DEFAULT_TIMEOUT_MS = 30_000;
export interface HostServiceCallOptions {
relayUrl: string;
organizationId: string;
hostId: string;
jwt: string;
+ timeoutMs?: number;
}
...
const response = await fetch(url, {
method: method === "query" ? "GET" : "POST",
headers,
body,
+ signal: AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS),
});🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/mcp-v2/src/host-service-client.ts` around lines 40 - 44, The unified
fetch call (the response = await fetch(url, { ... })) no longer uses a timeout
so host relay requests can hang indefinitely; restore support for the timeoutMs
option by creating an AbortSignal (preferably using
AbortSignal.timeout(timeoutMs) if available, falling back to an AbortController
with setTimeout) and pass it as signal to the fetch call, ensure the signal is
aborted on timeout and that the thrown error propagates so callers can handle
timeouts (update the code that constructs headers/body/method around response =
await fetch(...) to include signal and preserve existing behavior).
Adds `superset agents list` for the CLI/SDK/MCP and reshapes how the
host service exposes terminal-agent presets.
**Why.** The host service was exposing two parallel concepts as runtime
data: configured rows (`hostAgentConfigs`) and a hardcoded preset
catalog (`AGENT_PRESETS`). The catalog isn't actually data — it's
static configuration that ships with the host-service binary, version-
locked to whatever desktop release the user has installed. Treating it
as a runtime API resource forced the desktop detail view to fetch the
catalog separately just to render row descriptions, made `add` validate
`presetId` against an enum that blocks truly custom agents, and bloated
the CLI/SDK/MCP with a parallel `listPresets` surface.
**Changes.**
- Move `AGENT_PRESETS` (V2 host-service preset list) from the host
service into `packages/shared/src/host-agent-presets.ts` as
`HOST_AGENT_PRESETS` / `HostAgentPreset` (named distinctly from V1's
`AgentPresetField` / `AgentPresetOverride` types in the V1 desktop
agent settings system, which is untouched).
- Drop `settings.agentConfigs.listPresets` from the host service. The
desktop V2 agents picker now reads the bundled const directly.
- Reshape `settings.agentConfigs.add` to accept the full launch row
(`{ label, command, args, promptTransport, promptArgs, env,
presetId? }`). `presetId` is now free-form metadata used by the
client for icon and description lookup, defaulting to `"custom"`
when omitted. Truly custom agents are now possible at the API level.
- Add `superset agents list` for configured rows (no `--presets` flag —
the catalog isn't runtime data).
- Add `Agents` resource to the SDK (`agents.list`, `agents.run` —
routes the run through the cloud workspace lookup like the CLI does).
- Add `agents_list` MCP tool, plus a new `hostServiceQuery` GET helper
in `packages/mcp-v2/src/host-service-client.ts` (the existing helper
only handled mutations).
**Out of scope.** "Custom agent" form in the desktop picker (UI to enter
a label/command/args/env), `agents add` in the CLI/SDK/MCP for headless
custom installs, and unifying the V1 (`BUILTIN_TERMINAL_AGENTS`) and V2
(`HOST_AGENT_PRESETS`) catalogs into one. Those each deserve their own
PR.
**Verification.**
- `bun run lint` and `bun run typecheck` (turbo, full repo) clean.
- `bun test packages/host-service/src/trpc/router/settings/agent-configs.test.ts` — 21 pass, including the new "accepts a fully custom row" and "preserves an arbitrary presetId tag" cases.
- `bun run build` in `packages/sdk` clean.
- `superset agents list --local` prints the configured-row table.
- `superset agents list --local --presets` errors with "Unknown option".
# Conflicts: # apps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/V2AgentsSettings.tsx # packages/mcp-v2/src/host-service-client.ts
5ba5a49 to
3aca0f4
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/mcp-v2/src/host-service-client.ts (1)
4-9:⚠️ Potential issue | 🟠 Major | ⚡ Quick winReintroduce a timeout on relay calls.
fetchno longer has any abort path here, so a wedged relay/host can hangagents_run,agents_list,workspaces_create, andworkspaces_deleteindefinitely. Please restoretimeoutMsonHostServiceCallOptionsand pass a signal intofetch; verify the target runtime before choosingAbortSignal.timeout()versus anAbortControllerfallback.Also applies to: 40-44
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mcp-v2/src/host-service-client.ts` around lines 4 - 9, The HostServiceCallOptions interface lost timeout support causing fetch calls in HostServiceClient paths (e.g., agents_run, agents_list, workspaces_create, workspaces_delete) to hang; restore a numeric timeoutMs on HostServiceCallOptions, create an AbortSignal for each call and pass it into fetch via the signal option, and detect the environment to use AbortSignal.timeout(timeoutMs) when available or fall back to creating an AbortController and setTimeout to abort after timeoutMs, ensuring you clear the timer when the request finishes.
🧹 Nitpick comments (1)
packages/host-service/src/trpc/router/settings/agent-configs.ts (1)
173-206: 💤 Low valueOptional: wrap insert + read-back in a transaction.
The
addmutation issues anINSERTfollowed by a separateSELECTto read the row back. Other procedures in this file (reorder,resetToDefaults) intentionally usectx.db.transactionto avoid intermediate observable states. While SQLite's default isolation makes this safe in practice for a freshly-inserted UUID, wrapping the two statements in a single transaction would make the pattern consistent with the rest of the router and is cheap to do.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/host-service/src/trpc/router/settings/agent-configs.ts` around lines 173 - 206, The add mutation currently does an insert then a separate select; wrap those two operations in a single ctx.db.transaction to match other procedures (like reorder and resetToDefaults) and avoid intermediate observable states: inside the transaction call perform ctx.db.insert(...).values({...}).run(), then ctx.db.select().from(hostAgentConfigs).where(eq(hostAgentConfigs.id, id)).get(), check for created and throw the same TRPCError if missing, and finally return toOutput(created); keep existing use of listOrdered, randomUUID, and the hostAgentConfigs identifiers unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@packages/mcp-v2/src/host-service-client.ts`:
- Around line 4-9: The HostServiceCallOptions interface lost timeout support
causing fetch calls in HostServiceClient paths (e.g., agents_run, agents_list,
workspaces_create, workspaces_delete) to hang; restore a numeric timeoutMs on
HostServiceCallOptions, create an AbortSignal for each call and pass it into
fetch via the signal option, and detect the environment to use
AbortSignal.timeout(timeoutMs) when available or fall back to creating an
AbortController and setTimeout to abort after timeoutMs, ensuring you clear the
timer when the request finishes.
---
Nitpick comments:
In `@packages/host-service/src/trpc/router/settings/agent-configs.ts`:
- Around line 173-206: The add mutation currently does an insert then a separate
select; wrap those two operations in a single ctx.db.transaction to match other
procedures (like reorder and resetToDefaults) and avoid intermediate observable
states: inside the transaction call perform
ctx.db.insert(...).values({...}).run(), then
ctx.db.select().from(hostAgentConfigs).where(eq(hostAgentConfigs.id, id)).get(),
check for created and throw the same TRPCError if missing, and finally return
toOutput(created); keep existing use of listOrdered, randomUUID, and the
hostAgentConfigs identifiers unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4b14299f-6fef-413e-84ca-b3c9b3929a59
📒 Files selected for processing (22)
apps/desktop/src/renderer/hooks/useV2AgentConfigs/useV2AgentConfigs.tsapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/V2AgentsSettings.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentDetail/AgentDetail.tsxapps/desktop/src/renderer/routes/_authenticated/settings/agents/components/V2AgentsSettings/components/AgentsSettingsSidebar/AgentsSettingsSidebar.tsxapps/desktop/src/renderer/routes/_authenticated/settings/terminal/components/TerminalSettings/components/PresetsSection/components/PresetEditorDialog/PresetEditorDialog.tsxpackages/cli/src/commands/agents/list/command.tspackages/cli/src/commands/agents/meta.tspackages/host-service/src/trpc/router/settings/agent-configs.test.tspackages/host-service/src/trpc/router/settings/agent-configs.tspackages/host-service/src/trpc/router/settings/index.tspackages/mcp-v2/src/host-service-client.tspackages/mcp-v2/src/tools/agents/list.tspackages/mcp-v2/src/tools/agents/run.tspackages/mcp-v2/src/tools/register.tspackages/mcp-v2/src/tools/workspaces/create.tspackages/mcp-v2/src/tools/workspaces/delete.tspackages/sdk/src/client.tspackages/sdk/src/index.tspackages/sdk/src/resources/agents.tspackages/sdk/src/resources/index.tspackages/shared/package.jsonpackages/shared/src/host-agent-presets.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/mcp-v2/src/tools/register.ts
- packages/cli/src/commands/agents/list/command.ts
- packages/sdk/src/resources/agents.ts
Changes since v0.2.8: - `superset agents list` (and demoted "presets" to a UI-only concept). CLI now reads canonical agents from host-service. (#4097) - Host-service: refresh stale OAuth access tokens on remote workspace ops instead of failing the request. (#4106) - Host-service: workspace.create now adopts an existing worktree at any path, not just the canonical one. (#4096) - Host-service: AI workspace naming times out after 5s and falls back to a deterministic name. (#4102) Push cli-v0.2.9 after this lands to fire the release pipeline.
…4111) Catches the docs and skill up to PR #4097 (which added `superset agents list`, the SDK `Agents` resource, and the `agents_list` MCP tool, and demoted listPresets to a static UI const). - skills/superset/SKILL.md: drop the `superset agents list --local --presets` line — that flag was removed when the catalog stopped being a runtime API resource. - apps/docs/content/docs/cli/cli-reference.mdx: add a new `### agents` section with `superset agents list` and `superset agents run` Command blocks (the run command was never documented). - apps/docs/content/docs/mcp.mdx: add a new `### Agents` table row covering `agents_list` and `agents_run`; remove the spurious `projects_create` row (no such MCP tool exists in `register.ts`). - apps/docs/content/docs/sdk/reference.mdx: drop the stale `**TODO**` Callout in `workspaces.create` that claimed the SDK sends a minimal `agentConfig: { id: 'claude', kind: 'terminal' }`. The SDK now uses the v2 host-service launch shape directly. Add a new `## agents` section documenting `client.agents.list` and `client.agents.run`. - apps/docs/content/docs/sdk/advanced.mdx: drop the same stale `**TODO**` Callout above the Sentry recipe. Style notes for the new entries: CLI Command `output` blocks use inline structural literals (matches `hosts list` / `workspaces list`), MCP table descriptions are terse single-clauses (matches `tasks_*` / `workspaces_*`).
…4097) Adds `superset agents list` for the CLI/SDK/MCP and reshapes how the host service exposes terminal-agent presets. **Why.** The host service was exposing two parallel concepts as runtime data: configured rows (`hostAgentConfigs`) and a hardcoded preset catalog (`AGENT_PRESETS`). The catalog isn't actually data — it's static configuration that ships with the host-service binary, version- locked to whatever desktop release the user has installed. Treating it as a runtime API resource forced the desktop detail view to fetch the catalog separately just to render row descriptions, made `add` validate `presetId` against an enum that blocks truly custom agents, and bloated the CLI/SDK/MCP with a parallel `listPresets` surface. **Changes.** - Move `AGENT_PRESETS` (V2 host-service preset list) from the host service into `packages/shared/src/host-agent-presets.ts` as `HOST_AGENT_PRESETS` / `HostAgentPreset` (named distinctly from V1's `AgentPresetField` / `AgentPresetOverride` types in the V1 desktop agent settings system, which is untouched). - Drop `settings.agentConfigs.listPresets` from the host service. The desktop V2 agents picker now reads the bundled const directly. - Reshape `settings.agentConfigs.add` to accept the full launch row (`{ label, command, args, promptTransport, promptArgs, env, presetId? }`). `presetId` is now free-form metadata used by the client for icon and description lookup, defaulting to `"custom"` when omitted. Truly custom agents are now possible at the API level. - Add `superset agents list` for configured rows (no `--presets` flag — the catalog isn't runtime data). - Add `Agents` resource to the SDK (`agents.list`, `agents.run` — routes the run through the cloud workspace lookup like the CLI does). - Add `agents_list` MCP tool, plus a new `hostServiceQuery` GET helper in `packages/mcp-v2/src/host-service-client.ts` (the existing helper only handled mutations). **Out of scope.** "Custom agent" form in the desktop picker (UI to enter a label/command/args/env), `agents add` in the CLI/SDK/MCP for headless custom installs, and unifying the V1 (`BUILTIN_TERMINAL_AGENTS`) and V2 (`HOST_AGENT_PRESETS`) catalogs into one. Those each deserve their own PR. **Verification.** - `bun run lint` and `bun run typecheck` (turbo, full repo) clean. - `bun test packages/host-service/src/trpc/router/settings/agent-configs.test.ts` — 21 pass, including the new "accepts a fully custom row" and "preserves an arbitrary presetId tag" cases. - `bun run build` in `packages/sdk` clean. - `superset agents list --local` prints the configured-row table. - `superset agents list --local --presets` errors with "Unknown option".
Changes since v0.2.8: - `superset agents list` (and demoted "presets" to a UI-only concept). CLI now reads canonical agents from host-service. (#4097) - Host-service: refresh stale OAuth access tokens on remote workspace ops instead of failing the request. (#4106) - Host-service: workspace.create now adopts an existing worktree at any path, not just the canonical one. (#4096) - Host-service: AI workspace naming times out after 5s and falls back to a deterministic name. (#4102) Push cli-v0.2.9 after this lands to fire the release pipeline.
…4111) Catches the docs and skill up to PR #4097 (which added `superset agents list`, the SDK `Agents` resource, and the `agents_list` MCP tool, and demoted listPresets to a static UI const). - skills/superset/SKILL.md: drop the `superset agents list --local --presets` line — that flag was removed when the catalog stopped being a runtime API resource. - apps/docs/content/docs/cli/cli-reference.mdx: add a new `### agents` section with `superset agents list` and `superset agents run` Command blocks (the run command was never documented). - apps/docs/content/docs/mcp.mdx: add a new `### Agents` table row covering `agents_list` and `agents_run`; remove the spurious `projects_create` row (no such MCP tool exists in `register.ts`). - apps/docs/content/docs/sdk/reference.mdx: drop the stale `**TODO**` Callout in `workspaces.create` that claimed the SDK sends a minimal `agentConfig: { id: 'claude', kind: 'terminal' }`. The SDK now uses the v2 host-service launch shape directly. Add a new `## agents` section documenting `client.agents.list` and `client.agents.run`. - apps/docs/content/docs/sdk/advanced.mdx: drop the same stale `**TODO**` Callout above the Sentry recipe. Style notes for the new entries: CLI Command `output` blocks use inline structural literals (matches `hosts list` / `workspaces list`), MCP table descriptions are terse single-clauses (matches `tasks_*` / `workspaces_*`).
npm has alpha.6 as the most recent published; alpha.7 was bumped in 71bf008 but never `npm publish`-ed. Skip alpha.7 on the registry and ship the current repo state as alpha.8. Changes since alpha.6: - workspaces.create adopts the canonical host-service shape (#3893) - automations.list accepts --name filter (#3952) - automations.prompt split into automations.prompt.get / .set (#3959) - agents.list (presets demoted to UI-only configuration) (#4097) - agents.run / workspaces.create gain `superset-chat` agent + `kind` discriminator on launch results (terminal vs chat) (#4116) - type adjustments for v2 workspace render path (#4141) - redact x-api-key in debug-log header dumps (#3956, was alpha.7) After merge: `cd packages/sdk && bun run build && cd dist && npm publish --access public`.
Summary
Adds
superset agents listfor the CLI/SDK/MCP and reshapes how the host service exposes terminal-agent presets.Why this design. The host service was exposing two parallel concepts as runtime data: configured rows (
hostAgentConfigs) and a hardcoded preset catalog (AGENT_PRESETS). The catalog isn't actually data — it's static configuration that ships with the host-service binary, version-locked to whatever desktop release the user has installed. Treating it as a runtime API resource forced the desktop detail view to fetch the catalog separately just to render row descriptions, madeaddvalidatepresetIdagainst an enum that blocks truly custom agents, and bloated the CLI/SDK/MCP with a parallellistPresetssurface.Changes
Shared:
packages/shared/src/host-agent-presets.tsexportingHOST_AGENT_PRESETSandHostAgentPreset(V2 host-service preset list, moved out of the host service so the desktop renderer can import it directly). Named distinctly from V1'sAgentPresetField/AgentPresetOverridetypes inpackages/shared/src/agent-settings.ts— the V1 desktop agent settings system is untouched.Host service (
packages/host-service/src/trpc/router/settings/agent-configs.ts):settings.agentConfigs.listPresetsprocedure entirely.presetIdSchemaenum validation.addnow accepts{ label, command, args, promptTransport, promptArgs, env, presetId? }— the full launch row.presetIdis free-form metadata used by clients for icon/description lookup, defaulting to"custom"when omitted. Truly custom agents are now possible at the API level.getDefaultSeedPresets) imported from@superset/shared/host-agent-presets.listPresetsexporter on the host-servicesettingsbarrel removed.Desktop (
apps/desktop/...V2AgentsSettings/...):V2AgentsSettings.tsxno longer fetcheslistPresets. Reads the bundledHOST_AGENT_PRESETSconst from shared and builds the description map locally.addMutationsends the full row body (preset minusdescription).AgentsSettingsSidebartyped againstHostAgentPresetfrom shared. Picker click hands the full preset object up to the parent.AgentDetail.tsxswitchesPromptTransportimport from@superset/host-service/settings→@superset/shared/agent-prompt-launch.CLI:
superset agents listcommand (packages/cli/src/commands/agents/list/command.ts) with--host <id>/--local(mutually exclusive). Returns configured rows; columnsLABEL | PRESET | COMMAND | ID. No--presetsflag — the catalog isn't runtime data.SDK:
Agentsresource exposinglist({ hostId })andrun({ workspaceId, agent, prompt, attachmentIds? }, { hostId? }).runresolves the host via the cloud workspace lookup whenhostIdis omitted, matching the CLI ergonomics.MCP:
agents_listtool. NewhostServiceQueryGET helper inpackages/mcp-v2/src/host-service-client.ts(the existing helper only handled mutations).Out of scope
agents addin the CLI / SDK / MCP for headless custom installs.packages/shared/src/builtin-terminal-agents.ts) and V2 (packages/shared/src/host-agent-presets.ts) catalogs into one. The codebase had two parallel preset lists for the same 9 agents in different shapes before this PR; merging them is a separate refactor.Verification
bun run lintandbun run typecheck(turbo, full repo) clean.bun test src/trpc/router/settings/agent-configs.test.tsinpackages/host-service— 21 pass, including new "accepts a fully custom row" and "preserves an arbitrary presetId tag" cases.bun run buildinpackages/sdkclean.Test plan
agent-configs.test.tsrewritten for newaddshape and passingagents list --localprints configured rows--presetsflag is gone (errors with "Unknown option")presetId: "custom", verify icon fallback and description fallback render correctly. Left for the next reviewer with a desktop checkout.Summary by CodeRabbit
New Features
User-facing Changes