upstream merge 2026-05-08 PR 11: agents API + onboarding#463
Conversation
…uperset-sh#3914) * feat(host-service): host agent configs (v2 PR 1, argv-array shape) PR 1 of the canonical workspace.create() refactor — see plans/20260425-host-agent-configs-pr1.md. Introduces the V2 host-runtime agent config model. Configs live in host.db, are edited through a new V2 Agents settings page, and are listed via a new settings.agentConfigs.* tRPC router. The V2 modal + launch dispatch are intentionally NOT migrated in this PR; that lands later (PR 5). Backend - New host_agent_configs table (argv-array shape: command, args[], promptTransport, promptArgs[], env) with migration 0004. Storing argv directly avoids shell-quoting bugs and makes prompt injection a list push instead of string concatenation. - Hardcoded AgentPreset catalog (claude, amp, codex, gemini, opencode, pi, copilot, cursor-agent). Default seed = claude/amp/codex/gemini/ copilot. Superset Chat intentionally excluded. - settings.agentConfigs.{list, listPresets, add, update, remove, reorder, resetToDefaults} with seeding on first list, duplicate- presetId support, and reorder integrity validation. - 17 router tests against an in-memory bun:sqlite db. Renderer (desktop) - Under FEATURE_FLAGS.V2_CLOUD, the Agents settings page renders a new V2AgentsSettings component that talks to the active host's settings.agentConfigs.*. Non-V2 keeps the legacy preset UI unchanged. - Single shell-style command input parsed via shell-quote into command + args; separate prompt-only args input; argv/stdin transport toggle. Add (preset picker), remove, up/down reorder, reset-to- defaults wired through tRPC mutations + react-query invalidation. - 8 argv-parsing/joining tests. Launch resolution (consumed in a later PR): argv = prompt ? [command, ...args, ...promptArgs, ...(transport === "argv" ? [prompt] : [])] : [command, ...args] Empty launches drop promptArgs, so codex/opencode/copilot don't carry their prompt-mode flags into promptless sessions. * test(host-service): run agent-configs router tests against real migrations Replaces the hand-rolled CREATE TABLE with the actual drizzle migrate() run. Now every test boots from an empty in-memory db that migrates 0000…0004 in sequence, so any drift between schema.ts and the generated migration SQL would fail every test instead of silently passing. * feat(desktop): polish V2 agents settings UI to match v1 (icons, drag-to-reorder) Restructure V2AgentsSettings to mirror v1's AgentCard look-and-feel: - Each row now shows preset icon + label + description + chevron, matching v1's AgentCardHeader layout. Icons resolve via getPresetIcon by presetId. - Drag-to-reorder via @dnd-kit/sortable replaces the up/down arrow buttons. Reorder mutation has optimistic updates so the row settles immediately on drop and rolls back on error. - Splits the card into its own folder (components/V2AgentCard) per AGENTS.md project structure (one folder per component). Server side: AgentPreset gains a `description` field (read-only, returned by listPresets). Renderer maps presetId → description from listPresets to feed the card. No on-disk schema change — descriptions remain catalog-only, never stored on the user's instance row. * feat(desktop): show preset icons in Add agent dropdown Renders the same getPresetIcon-resolved SVG next to each label in the dropdown. Bundled-asset lookup only, no extra IPC or host-service call. * feat(host-service): add Mastracode preset (--prompt, no suffix) Adds Mastracode as an Add-menu template only (not in default seed, matching v1's includeInDefaultTerminalPresets behavior). Uses `mastracode --prompt <prompt>` for prompt launches and `mastracode` alone for promptless launches. v1's `; mastracode` post-prompt REPL suffix is intentionally dropped — V2 doesn't model shell chaining. * fix(host-service): address review tier 1 + tier 2 on agent configs Backend (agent-configs.ts): - parseArgv/parseEnv wrap JSON.parse in try/catch — a single bad row no longer fails the whole list() response. - Trim label and command via z.string().trim().min(1) so whitespace-only values can't slip through to the UI as blank rows. - Wrap reorder updates in a transaction so a crash mid-loop can't leave display_order half-updated. - Wrap resetToDefaults delete+insert in a transaction so a crash between the two can't leave the table empty. - remove() now reads the row first and throws NOT_FOUND for unknown ids, matching update()'s behavior. Renderer (V2AgentCard.tsx): - Roll back optimistic promptTransport on update error so the toggle doesn't lie about persistence. Renderer (V2AgentsSettings.tsx): - Render an explicit error state (with Retry) when configsQuery fails, so a host-service outage isn't masked as "no agents configured". argv helpers (argv.ts): - Stop trimming/dropping empty tokens; quote command alongside args in joinCommandArgs. Round-trip is now lossless for paths with spaces and empty quoted args. Tests: - 3 new router tests (NOT_FOUND remove, whitespace rejection, trim). - 2 new argv tests (path with spaces, empty quoted arg).
…rset-sh#4052) * feat(desktop): surface v2 host agents at startup and in new workspace modal Prefill v2 host_agent_configs from a top-level hook so Settings → Agents loads instantly instead of fetching only on navigation, and switch the v2 new workspace modal off v1 getAgentPresets onto the same v2 source so custom labels and multiple per-preset configs actually appear in the agent picker. AgentSelect drops its hard dependency on AgentDefinitionId/ResolvedAgentConfig and accepts a structural { id, label, iconId? } so v2 callers can pass UUIDs while keeping the preset-keyed icon. WorkspaceCreateAgent relaxes to string and bumps its localStorage key so persisted v1 slugs don't poison the v2 picker. * fix(setup): skip Node-unsafe ports during port-base allocation Next.js refuses to bind ports Node treats as unsafe (e.g. 5060/sip, 5061/sips), so a workspace that landed on base 5060 couldn't run web/api. Extend SUPERSET_RESERVED_PORTS to cover the Node-unsafe ports that fall in our [3000, ...) allocation window so port_base_is_safe routes around them. * chore(desktop): trim comments on v2-agents wiring * fix(desktop): address PR review on v2 agents wiring P1 — DashboardNewWorkspaceModal latched on "No agent" when opened before the startup prefetch resolved. useAgentLaunchPreferences captured defaultAgent at useState init; once query data arrived, the corrective effect short-circuited because "none" was always in validAgents. Add a one-shot effect that promotes the placeholder to the first configured agent on initial fetch when no stored preference exists. P2 — useV2AgentConfigs had no staleTime, so each consumer would refetch on mount and negate the prefetch. Set staleTime to Infinity since mutations in Settings → Agents already invalidate the key explicitly. * fix(desktop): scope v2 agent picker to the launch host CodeRabbit flagged that the v2 new workspace modal sourced agents from the locally-active host while submitting to draft.hostId (which can target a remote device). Agent UUIDs are host-scoped, so picking on host A and submitting to host B sent a config id host B didn't recognize. useV2AgentConfigs now takes an explicit hostUrl. AgentHooks and V2AgentsSettings keep passing the local active URL; PromptGroup resolves the launch host URL the same way the upload path does and feeds that in. Promote effect updated to react to host switches: it now runs whenever the current selection isn't a real agent and the user hasn't explicitly chosen "none", instead of only on initial mount.
…t-sh#4090) * plan: v2 setup/teardown scripts editor Plan-only. Code changes deferred until the plan is reviewed. Scope is strictly v2 — no v1 ScriptsEditor / electronTrpc config router / v1 SetupScriptCard touches. Per project rule: v1 desktop UI is sunset. * feat(v2): setup/teardown scripts editor + sidebar CTA Adds the v2 equivalent of the v1 project-settings scripts editor and makes v2 workspace creation honor the configured setup array (was only running a literal `<worktree>/.superset/setup.sh`). - host-service config loader resolves `<repoPath>/.superset/config.json` + `~/.superset/projects/<id>/config.json` user override + local `.superset/config.local.json` overlay; no worktree-level read so the main repo stays the single source of truth. - new host-service `config` router: getConfigContent, updateConfig, shouldShowSetupCard. - setup-terminal helper joins resolved setup commands with `&&` and falls back to `bash <repoPath>/.superset/setup.sh` against the main repo. Worktrees reach the canonical .superset/ via $SUPERSET_ROOT_PATH. - V2ScriptsEditor mounts in V2ProjectSettings (Setup/Teardown tabs, blur-only save, multi-line→array, drag-drop import). - V2SetupScriptCard sidebar CTA with a per-machine zustand+persist dismissals store, gated on the active v2 workspace route. v1 paths intentionally untouched. * test(host-service): cover v2 setup config loader, router, terminal resolver Adds integration tests for the v2 setup/teardown work: - config loader: malformed JSON, mixed-type rejection, override precedence, before/after/replace overlay, three-layer stacking, empty-array override clearing base, partial-keys passthrough, path-traversal guard, no worktree consultation. - config router (in-memory drizzle): getConfigContent / updateConfig (preserves run + unrelated keys, overwrites malformed) / shouldShowSetupCard (run-only, teardown-only, all-empty cases). - resolveInitialCommand: && joining, fallback to setup.sh, single-quote escape, config-wins-over-fallback, whitespace filter. Adds optional `homeDir` parameter to loadSetupConfig and resolveInitialCommand to allow test sandboxes without process.env mutation. Production callers don't pass it (defaults to os.homedir()).
* feat(desktop): v2 onboarding setup flow Adds /setup/* with 5 steps (providers, gh-cli, permissions, project, adopt-worktrees), a hard redirect gate in _authenticated/layout.tsx, and a Restart entry point in Settings → Experimental. Reuses existing chat-service auth, permissions, and workspace-import APIs; adds system.detectGhCli for gh detection. * feat(desktop): add posthog events for v2 onboarding flow Tracks onboarding_started, onboarding_step_started, onboarding_step_completed, onboarding_step_skipped, onboarding_provider_connected (provider + method), onboarding_restarted, and onboarding_finished (with outcome + duration_ms). * fix(desktop): address bot review on v2 onboarding setup flow - Reactive store selectors in _authenticated/layout.tsx so the gate re-renders when onboarding state updates (greptile P2, coderabbit major) - selectRequiredStepsComplete only counts completed steps so a stray markSkipped call can't bypass the gate (coderabbit major) - markSkipped also sets completedAt when all steps done (coderabbit minor) - Stabilize finishFlow / skipFlow / navigateAfterFlow with useCallback so AutoAdvance doesn't re-fire each render (greptile P2, coderabbit minor) - Dedupe handleSelectFolder + handleAddAnother into handleSelectNewRepo (greptile P2) - Restart-onboarding dialog copy now matches manualWalkthrough behavior (greptile P1) * fix(desktop): route v2 setup completion to project page, not branch workspace The default workspace auto-created by openNew → ensureMainWorkspace is type "branch" and has no v2 pane layout, so navigating to /v2-workspace/$id renders an empty surface (no terminal, no chat). Project step (Select new repo): in v2 navigate to /project/$projectId so the user creates their first worktree via the v2 workspace creation flow. v1 keeps the previous behavior (branch workspaces work fine in v1). Adopt-worktrees finishFlow/skipFlow: in v2 only consider worktree-type workspaces when picking a navigation target. If none exist, fall back to the project page. * fix(desktop): keep manualWalkthrough false on onboarding reset Clicking "Restart onboarding" now clears completion flags without forcing the user through every step. Auto-advance still applies, so a user with already-configured prerequisites (signed in, provider connected, projects exist) breezes through the same way a fresh user does — just from a clean state.
superset-sh#4109) * feat(desktop): allow skipping every onboarding step and the whole flow - Add `skipAll` action and let skipped steps satisfy the dashboard gate - Always-visible "Skip for now" link on providers, permissions, and project steps - Add "Skip onboarding" button to the setup chrome * fix(desktop): drop misleading "Skip" prefix when providers step is complete
…s_create) (superset-sh#4076) - New agents_run tool: launches an agent inside an existing workspace (mirrors superset agents run / Workspaces.create({ agents }) per-entry). - workspaces_create now accepts an optional agents[] for spawn-on-create, matching the SDK's WorkspaceAgentLaunch shape. Tightened the response type to the discriminated union the host already returns.
…/ MCP (superset-sh#4116) * feat(agents): launch Superset Chat sessions from desktop / CLI / SDK / MCP Folds the built-in Superset Chat agent into the existing `agents` sugar so the same one-call surface spawns terminal *and* chat sessions across every entry point. Picker today shows only the host's terminal-config rows; submitting `superset-chat` 404s on the host because `runAgentInWorkspace` only knows how to spawn PTYs. Plumbing changes: - `agents.ts runAgentInWorkspace` branches on chat-builtin ids: mints a sessionId, registers the cloud `chat_sessions` row, and fires the first turn through `ChatRuntimeManager.startTurn`. Returns a `kind`-tagged result so callers materialize the right pane. - `ChatRuntimeManager.startTurn` boots the runtime and queues the message, but returns as soon as streaming begins instead of awaiting the assistant's full reply (~30s -> ~5-8s for headless callers). - `getSnapshot` cold-start fast path: returns an empty skeleton immediately when no runtime is in memory while creation runs in the background. Renderer's "Loading conversation..." clears on the first poll instead of hanging on the harness boot. - Host's API client carries the bound organizationId via x-superset-organization-id. The session-exchanged JWT only ships organizationIds[]; without the header protectedProcedure middleware can't resolve activeOrganizationId and any host->cloud call hits "No active organization selected". Surface updates: - Desktop v2 picker: new useV2AgentChoices hook overlays builtin chat agents on top of the host's terminal rows. Wired into the new workspace modal and the two task launch pickers. - appendLaunchesToPaneLayout seeds a kind: "chat" pane for chat results. - CLI workspaces create --agent --prompt --attachment and agents run --attachment accept local file paths and upload them to the host's attachment store before launch. - agents list includes Superset Chat. - SDK + MCP-v2 result types gain the kind discriminator. JSDoc and tool descriptions document superset-chat as a valid agent value. * refactor(agents): trim chat launch path, rename superset-chat -> superset - Drop ChatRuntimeManager.startTurn and the cold-start workarounds (peekRuntime, skeleton snapshot). runChatAgent now just void-fires chat.sendMessage and returns the sessionId. CLI agents run goes from ~18s to ~2s; runtime boot finishes async on the host. - Rename superset-chat -> superset (id, type literals, tests, mcp v1, icon map). Label "Superset Chat" -> "Superset" everywhere it appeared (mcp / cli / sdk / agent-card / orchestrator title). - Trim function-level JSDocs that restated the code. * refactor(agents): hardcode 'superset' instead of filtering catalog There's exactly one chat builtin, so iterating BUILTIN_AGENT_DEFINITIONS to filter for chat-kinds is busywork — the id and label are known at the call site. Drops the catalog import + type predicate in CLI agents list, the v2 picker hook, and runAgentInWorkspace. * docs(agents): trim verbose mcp / sdk descriptions Restore the original MCP and SDK descriptions and just add `superset` to the e.g. lists rather than spelling out the chat-vs-terminal split in every docstring. * docs(agents): trim fire-and-forget comment to just the WHY
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (104)
✨ Finishing Touches🧪 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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 75dcf2da51
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| legacy.agentType === "superset" || | ||
| legacy.openChatPane === true || |
There was a problem hiding this comment.
Preserve legacy superset-chat identifier during normalization
normalizeLegacyLaunchRequest now only treats agentType === "superset" as chat, so legacy callers that still send "superset-chat" (without openChatPane/chatLaunchConfig) are misclassified as terminal launches and then fail with the "missing terminal command" error path. This is a backward-compatibility regression in the compatibility shim itself and can break older CLI/MCP/desktop payloads that were valid before this change.
Useful? React with 👍 / 👎.
| port_base_is_safe() { | ||
| local base=$1 | ||
| local range=$2 | ||
| local reserved | ||
| for reserved in $SUPERSET_RESERVED_PORTS; do | ||
| if [ "$reserved" -ge "$base" ] && [ "$reserved" -lt "$((base + range))" ]; then |
There was a problem hiding this comment.
Apply reserved-port guard when selecting port base
This patch introduces SUPERSET_RESERVED_PORTS and port_base_is_safe, but the allocator loop still advances candidates only by checking whether the base is already used, never whether the [base, base+range) window contains reserved ports. As a result, allocations can still land on ranges containing 5000/5060/etc., so the new reserved-port logic is effectively dead code and the startup failures it targets remain possible.
Useful? React with 👍 / 👎.
Recorded as integrated via -s ours after batch PRs #455-#464. Taken via individual PRs: - PR 1 (#455): v2 polish 前半 safe set (9 commits) - PR 2 (#456): v2/host-service polish 中盤 (12 commits) - PR 3 (#457): sidebar polish + jwt API (5 commits) - PR 4 (#458): host-service tRPC retry/cache/timeout (3 commits) - PR 5 (#459): v2 diff pane / file pane polish (2 commits) - PR 7 (#462): host-service v2 canonical workspace.create + attachment store (PR1 superset-sh#3893 + PR2 superset-sh#3916) - PR 11 (#463): agents API + onboarding (7 commits + 1 cleanup) - PR 12 (#464): v1→v2 import flow rewrite (11 commits + 2 follow-ups) - PR 13 (#460): host-service shell env probe + typo (2 commits) - PR 16 (#461): marketplace 19 themes (1 commit) Skipped / deferred (recorded as integrated for behind=0): - PR 6: CLI v1 launch (superset-sh#3898 + 30+ CLI/SDK followups) — defer to dedicated migration - PR 9: v2 PR3 (superset-sh#3940) + revert (superset-sh#4017) — net-zero pair - PR 10: pty-daemon (superset-sh#3896, superset-sh#3971, superset-sh#4054) — fork keeps its terminal-host - PR 14: Slack MCP-v2 (superset-sh#4197, superset-sh#4208) — depends on mcp-v2/sdk divergence - PR 15: onboarding remaining (superset-sh#4115, superset-sh#4125, superset-sh#4214, superset-sh#4213, superset-sh#4222, superset-sh#4225) — depends on fork's deleted setup pages Behind: 0 after this merge.
Summary
upstream 同期バッチ第 11 弾。agents API + onboarding 関連 (7 commits)。
進捗: PR 1-5 + 7 + 13 + 16 マージ済み (合計 36 commits)、本 PR で +7 commits = 43。
取り込み内容 (sub-agent委譲で処理)
Skipped commits
Fork 側のコンフリクト解決 (sub-agent 自律判断)
bun install)Fork 固有機能ヘルスチェック
githubExtendedprocedure 健在Test plan
bun install成功 (lockfile origin/main から取り直し)