Skip to content

Commit 74cdeb3

Browse files
fix: update settings and skills handling with assistant redirect (#220)
* fix: enable swipe-back suspension on more drawer and remove unused variable * refactor(frontend): improve dialog component and settings navigation * fix: disable route swipe suspension in MoreDrawer to prevent unintended navigation * fix(frontend): enable swipe-back suspension on more drawer route * refactor(frontend): improve mobile navigation drawer and tab bar * feat: add schedules service and workspace hook with navigation updates * chore: add workspace hook, schedules library, and tests * fix: prevent MoreDrawer sentinel from undoing navigation * feat: per-agent model selection and UI refinements (#217) * feat: per-agent model selection and UI refinements - Add agentModels store with setAgentModel/getAgentModel - PromptInput uses session model priority and stores agent model on change - useContextUsage derives model from assistant message instead of global - Migrate sub-agent/subtask badges from purple to blue with refined styling - Fix MoreDrawer sentinel to skip history-back on navigation * refactor: improve per-agent model selection and task tool call status indicators * feat: add repo management skill and internal repos API * fix: improve assistant session launcher and UI components * fix: update atomic-json test assertions * refactor: split Assistant Mode instructions between AGENTS.md and assistant.md * loop: todo-header-mobile completed after 3 iterations (#218) * loop: stt-perf-1 completed after 5 iterations * fix: load audio worklet per recording context * fix: canonicalize assistant navigation routes * fix: adjust scroll-up threshold for header visibility * fix: update settings and skills handling with assistant redirect * refactor: simplify context usage indicator and extract token sum helper * feat: add currently selected model row to popover and fix responsive truncate
1 parent c729151 commit 74cdeb3

73 files changed

Lines changed: 4072 additions & 631 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"build": "bun build src/index.ts --outdir=dist --target=bun",
1010
"typecheck": "tsc --noEmit",
1111
"test": "pnpm run test:bun && pnpm run test:vitest",
12-
"test:bun": "bun test test/services/assistant-mode.test.ts test/services/internal-token.test.ts test/auth/internal-token-middleware.test.ts test/routes/internal-schedules.test.ts test/routes/internal-notifications.test.ts test/routes/internal-settings.test.ts src/db/model-state.test.ts src/routes/providers.test.ts",
12+
"test:bun": "bun test test/services/assistant-mode.test.ts test/services/internal-token.test.ts test/auth/internal-token-middleware.test.ts test/routes/internal-schedules.test.ts test/routes/internal-notifications.test.ts test/routes/internal-settings.test.ts test/routes/internal-repos.test.ts src/db/model-state.test.ts src/routes/providers.test.ts",
1313
"test:vitest": "vitest run",
1414
"test:ui": "vitest --ui",
1515
"test:watch": "vitest --watch",

backend/src/routes/internal/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { createScheduleRoutes } from '../schedules'
77
import { createInternalTokenMiddleware } from '../../auth/internal-token-middleware'
88
import { createInternalNotificationRoutes } from './notifications'
99
import { createInternalSettingsRoutes } from './settings'
10+
import { createInternalRepoRoutes } from './repos'
1011

1112
export function createInternalRoutes(
1213
db: Database,
@@ -20,6 +21,7 @@ export function createInternalRoutes(
2021
app.route('/notifications', createInternalNotificationRoutes(notificationService))
2122
app.route('/settings', createInternalSettingsRoutes(settingsService))
2223
const repos = new Hono()
24+
repos.route('/', createInternalRepoRoutes(db, settingsService))
2325
repos.route('/:id/schedules', createScheduleRoutes(scheduleService))
2426
app.route('/repos', repos)
2527
return app
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Hono } from 'hono'
2+
import type { Database } from 'bun:sqlite'
3+
import type { SettingsService } from '../../services/settings'
4+
import { listRepos } from '../../db/queries'
5+
import { logger } from '../../utils/logger'
6+
import { getErrorMessage } from '../../utils/error-utils'
7+
8+
export function createInternalRepoRoutes(db: Database, settingsService: SettingsService) {
9+
const app = new Hono()
10+
11+
app.get('/', (c) => {
12+
try {
13+
const settings = settingsService.getSettings()
14+
const repos = listRepos(db, settings.preferences.repoOrder)
15+
return c.json({ repos })
16+
} catch (error) {
17+
logger.error('Failed to list internal repos:', error)
18+
return c.json({ error: getErrorMessage(error) }, 500)
19+
}
20+
})
21+
22+
return app
23+
}

backend/src/routes/repos.ts

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Hono } from 'hono'
22
import type { ContentfulStatusCode } from 'hono/utils/http-status'
33
import type { Database } from 'bun:sqlite'
4+
import type { Repo } from '@opencode-manager/shared/types'
45
import { DiscoverReposRequestSchema, AssistantModeInitRequestSchema } from '@opencode-manager/shared/schemas'
56
import { listRepos, getRepoById, updateLastAccessed, updateRepoConfigName } from '../db/queries'
67
import * as repoService from '../services/repo'
@@ -17,7 +18,7 @@ import { createRepoGitRoutes } from './repo-git'
1718
import { createScheduleRoutes } from './schedules'
1819
import type { GitAuthService } from '../services/git-auth'
1920
import { ScheduleService } from '../services/schedules'
20-
import { ensureAssistantMode, getAssistantModeStatus } from '../services/assistant-mode'
21+
import { ensureAssistantMode, getAssistantModeStatus, getAssistantModeDirectory } from '../services/assistant-mode'
2122
import path from 'path'
2223

2324
async function restartOpenCode(openCodeSupervisor?: OpenCodeSupervisor): Promise<void> {
@@ -155,13 +156,36 @@ app.get('/', async (c) => {
155156
app.get('/:id', async (c) => {
156157
try {
157158
const id = parseInt(c.req.param('id'))
158-
const repo = getRepoById(database, id)
159+
160+
let repo: Repo | null
161+
let isAssistant = false
162+
if (id === 0) {
163+
isAssistant = true
164+
repo = {
165+
id: 0,
166+
repoUrl: undefined,
167+
localPath: 'assistant',
168+
sourcePath: undefined,
169+
fullPath: getAssistantModeDirectory(),
170+
branch: undefined,
171+
defaultBranch: 'main',
172+
cloneStatus: 'ready',
173+
clonedAt: Date.now(),
174+
lastPulled: undefined,
175+
lastAccessedAt: undefined,
176+
openCodeConfigName: undefined,
177+
isWorktree: false,
178+
isLocal: false,
179+
}
180+
} else {
181+
repo = getRepoById(database, id)
182+
}
159183

160184
if (!repo) {
161185
return c.json({ error: 'Repo not found' }, 404)
162186
}
163187

164-
const currentBranch = await repoService.getCurrentBranch(repo, gitAuthService.getGitEnvironment())
188+
const currentBranch = isAssistant ? undefined : await repoService.getCurrentBranch(repo, gitAuthService.getGitEnvironment())
165189

166190
return c.json({ ...repo, currentBranch })
167191
} catch (error: unknown) {
@@ -397,7 +421,28 @@ app.get('/', async (c) => {
397421
app.get('/:id/assistant-mode', async (c) => {
398422
try {
399423
const id = parseInt(c.req.param('id'))
400-
const repo = getRepoById(database, id)
424+
425+
let repo: Repo | null
426+
if (id === 0) {
427+
repo = {
428+
id: 0,
429+
repoUrl: undefined,
430+
localPath: 'assistant',
431+
sourcePath: undefined,
432+
fullPath: '',
433+
branch: undefined,
434+
defaultBranch: 'main',
435+
cloneStatus: 'ready',
436+
clonedAt: Date.now(),
437+
lastPulled: undefined,
438+
lastAccessedAt: undefined,
439+
openCodeConfigName: undefined,
440+
isWorktree: false,
441+
isLocal: false,
442+
}
443+
} else {
444+
repo = getRepoById(database, id)
445+
}
401446

402447
if (!repo) {
403448
return c.json({ error: 'Repo not found' }, 404)
@@ -414,7 +459,28 @@ app.get('/', async (c) => {
414459
app.post('/:id/assistant-mode', async (c) => {
415460
try {
416461
const id = parseInt(c.req.param('id'))
417-
const repo = getRepoById(database, id)
462+
463+
let repo: Repo | null
464+
if (id === 0) {
465+
repo = {
466+
id: 0,
467+
repoUrl: undefined,
468+
localPath: 'assistant',
469+
sourcePath: undefined,
470+
fullPath: '',
471+
branch: undefined,
472+
defaultBranch: 'main',
473+
cloneStatus: 'ready',
474+
clonedAt: Date.now(),
475+
lastPulled: undefined,
476+
lastAccessedAt: undefined,
477+
openCodeConfigName: undefined,
478+
isWorktree: false,
479+
isLocal: false,
480+
}
481+
} else {
482+
repo = getRepoById(database, id)
483+
}
418484

419485
if (!repo) {
420486
return c.json({ error: 'Repo not found' }, 404)

backend/src/routes/settings.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,8 +1126,9 @@ export function createSettingsRoutes(db: Database, gitAuthService: GitAuthServic
11261126
if (repoId !== undefined && isNaN(repoId)) {
11271127
return c.json({ error: 'Invalid repoId' }, 400)
11281128
}
1129+
const directory = c.req.query('directory')
11291130

1130-
const skills = await listManagedSkills(db, openCodeClient, repoId)
1131+
const skills = await listManagedSkills(db, openCodeClient, repoId, directory)
11311132
return c.json(skills)
11321133
} catch (error) {
11331134
logger.error('Failed to list skills:', error)

0 commit comments

Comments
 (0)