Skip to content

feat: session-aware profile selection#43

Merged
A-Souhei merged 6 commits intomainfrom
feat/session-profile
Mar 14, 2026
Merged

feat: session-aware profile selection#43
A-Souhei merged 6 commits intomainfrom
feat/session-profile

Conversation

@A-Souhei
Copy link
Owner

@A-Souhei A-Souhei commented Mar 14, 2026

Summary

  • Added profile column to session DB table + migration
  • Session.setProfile() and PATCH /session/:id accept profile (with name validation via regex)
  • Prompt resolution uses session profile at inference time
  • New /profile/session-active and /profile/session-switch routes (with Identifier.schema validation and documented 400/404 responses)
  • --profile flag on CLI run command
  • Web UI prompt-input is session-aware (shows/switches per-session profile, with optimistic update and proper auth/directory headers)
  • TUI prompt footer shows session-specific profile when switching sessions
  • TUI profile picker persists selection to the current session
  • JS SDK regenerated to include new types and methods

Note on included commit

This branch also includes commit f58128e80 (fix: add confirmation dialogs for memory/biblion deletion and improve error handling) from the fix/sidebar-delete-confirmation branch, which was accidentally inherited when the feature branch was cut. That commit removes the Session Tasks/Todo section from session-info-panel.tsx and adds confirmation dialogs for memory/biblion deletion — it is intentional UI cleanup from a separate fix branch and will be merged as part of this PR.

… error handling

- Add yes/no confirmation modals before clearing memory and biblion
- Fix delete operations to pass directory parameter for proper functionality
- Add error handling with detailed error messages in toasts
- Add double-click guard to prevent multiple simultaneous deletion attempts
- Remove TODO list from sidebar panel and SessionTodoDock import
- Clean up unused signal and role state variables
…ch to session

Switching sessions now correctly shows that session's profile in the
prompt footer instead of always showing the global active profile.
Selecting a profile from the picker while in a session also saves it
to that specific session, so each session remembers its own profile.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds session-scoped profile selection so model/prompt resolution can vary per session (DB + API + UI/CLI), and regenerates the JS SDK to expose the new endpoints/types.

Changes:

  • Add profile to sessions (DB schema + migration) and expose it via Session APIs (Session.setProfile, PATCH /session/:id).
  • Resolve agent model settings using the session’s profile at inference time.
  • Add profile session endpoints (/profile/session-active, /profile/session-switch) and update CLI/TUI/Web UI to switch/display per-session profiles (plus SDK regen).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/sdk/js/src/v2/gen/types.gen.ts Regenerated types: adds session profile, new profile/bridge event + endpoint types.
packages/sdk/js/src/v2/gen/sdk.gen.ts Regenerated client: adds profile + bridge namespaces and new calls.
packages/opencode/src/session/session.sql.ts Adds nullable profile column to Session table schema.
packages/opencode/src/session/prompt.ts Uses session profile to resolve saved agent model settings at prompt creation time.
packages/opencode/src/session/index.ts Plumbs profile through Session info + adds Session.setProfile.
packages/opencode/src/server/routes/session.ts Allows PATCH /session/:id to update profile.
packages/opencode/src/server/routes/profile.ts Adds session profile routes (session-active, session-switch).
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx Persists profile picker selection to the current session.
packages/opencode/src/cli/cmd/run.ts Adds --profile flag for new session creation.
packages/opencode/migration/20260314104937_add_session_profile/snapshot.json Migration snapshot updated for new session column.
packages/opencode/migration/20260314104937_add_session_profile/migration.sql Adds profile column via ALTER TABLE session.
packages/app/src/pages/session/session-info-panel.tsx Adds confirm dialogs for destructive actions; removes Tasks section.
packages/app/src/components/prompt-input.tsx Makes prompt input profile picker session-aware and switches session profile via PATCH.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 101 to 109
validator("json", z.object({ sessionID: z.string(), name: z.string() })),
async (c) => {
const body = c.req.valid("json")
if (!/^[A-Za-z0-9_\-.]+$/.test(body.name)) {
return c.json({ error: `Invalid profile name: ${body.name}` }, 400)
}
await Session.setProfile({ sessionID: body.sessionID, profile: body.name })
return c.json({ success: true })
},
Comment on lines +1032 to +1037
public switch<ThrowOnError extends boolean = false>(
parameters?: {
query_directory?: string
name?: string
body_directory?: string
},
Comment on lines +1104 to +1107
parameters?: {
directory?: string
sessionID?: string
name?: string
Comment on lines 361 to 366
</div>
</div>
</div>

{/* Tasks */}
<Show when={todos().length > 0}>
<div class="border-b border-border-weak-base">
<div class="px-4 pt-3 pb-1 flex items-center gap-2">
<Icon name="checklist" size="small" class="text-icon-base shrink-0" />
<span class="text-12-medium text-text-strong">Tasks</span>
</div>
<SessionTodoDock todos={todos()} title="Tasks" collapseLabel="Collapse tasks" expandLabel="Expand tasks" />
</div>
</Show>
</div>
</div>
)
import type { Provider } from "@/provider/provider"
import { PermissionNext } from "@/permission/next"
import { Global } from "@/global"
import { VuHitraSettings } from "@/project/vuhitra-settings"
Comment on lines +125 to +129
if (params.id) {
const res = await fetch(`${globalSDK.url}/session/${params.id}`, {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ profile: name }),
method: "POST",
headers: {
"Content-Type": "application/json",
"x-opencode-directory": dir,
Comment on lines +79 to +83
validator("query", z.object({ sessionID: z.string() })),
async (c) => {
const session = await Session.get(c.req.valid("query").sessionID)
return c.json(session.profile ?? null)
},
… in web selector

Add regex validation to PATCH /session/:id so profile names are
restricted to the same pattern as /profile/session-switch, preventing
arbitrary strings from being stored. Also add optimistic pending signal
in prompt-input so the profile selector dedup guard works correctly
during the SSE sync window.
- Add Identifier.schema("session") validation to sessionID in profile.ts
  session-active and session-switch routes
- Document 400/404 error responses in those routes via ...errors()
- Remove unused VuHitraSettings import from session/index.ts
- Add x-opencode-directory and auth headers to profile fetch calls
  in prompt-input.tsx so they work with password-protected servers
- Regenerate JS SDK to pick up updated OpenAPI schema
@A-Souhei A-Souhei merged commit a05166f into main Mar 14, 2026
2 checks passed
@A-Souhei A-Souhei deleted the feat/session-profile branch March 14, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants