Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
efbe3ca
fix: enable swipe-back suspension on more drawer and remove unused va…
chriswritescode-dev May 3, 2026
93fd219
refactor(frontend): improve dialog component and settings navigation
chriswritescode-dev May 3, 2026
f50df39
fix: disable route swipe suspension in MoreDrawer to prevent unintend…
chriswritescode-dev May 3, 2026
abd54e9
fix(frontend): enable swipe-back suspension on more drawer route
chriswritescode-dev May 3, 2026
bc82be5
refactor(frontend): improve mobile navigation drawer and tab bar
chriswritescode-dev May 3, 2026
0f6f13c
feat: add schedules service and workspace hook with navigation updates
chriswritescode-dev May 4, 2026
6e8bc78
chore: add workspace hook, schedules library, and tests
chriswritescode-dev May 4, 2026
5178ea6
fix: prevent MoreDrawer sentinel from undoing navigation
chriswritescode-dev May 4, 2026
93fe4d6
feat: per-agent model selection and UI refinements (#217)
chriswritescode-dev May 5, 2026
68f303b
feat: add repo management skill and internal repos API
chriswritescode-dev May 5, 2026
9fc317e
fix: improve assistant session launcher and UI components
chriswritescode-dev May 5, 2026
3cf4bc3
fix: update atomic-json test assertions
chriswritescode-dev May 5, 2026
286f9fb
refactor: split Assistant Mode instructions between AGENTS.md and ass…
chriswritescode-dev May 5, 2026
84d5b18
loop: todo-header-mobile completed after 3 iterations (#218)
chriswritescode-dev May 5, 2026
92da06e
loop: stt-perf-1 completed after 5 iterations
chriswritescode-dev May 5, 2026
a0b010d
fix: load audio worklet per recording context
chriswritescode-dev May 5, 2026
c0e9ac8
fix: canonicalize assistant navigation routes
chriswritescode-dev May 6, 2026
f9f3730
merge main into dev
chriswritescode-dev May 6, 2026
6d12eb4
fix: adjust scroll-up threshold for header visibility
chriswritescode-dev May 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build": "bun build src/index.ts --outdir=dist --target=bun",
"typecheck": "tsc --noEmit",
"test": "pnpm run test:bun && pnpm run test:vitest",
"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",
"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",
"test:vitest": "vitest run",
"test:ui": "vitest --ui",
"test:watch": "vitest --watch",
Expand Down
2 changes: 2 additions & 0 deletions backend/src/routes/internal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createScheduleRoutes } from '../schedules'
import { createInternalTokenMiddleware } from '../../auth/internal-token-middleware'
import { createInternalNotificationRoutes } from './notifications'
import { createInternalSettingsRoutes } from './settings'
import { createInternalRepoRoutes } from './repos'

export function createInternalRoutes(
db: Database,
Expand All @@ -20,6 +21,7 @@ export function createInternalRoutes(
app.route('/notifications', createInternalNotificationRoutes(notificationService))
app.route('/settings', createInternalSettingsRoutes(settingsService))
const repos = new Hono()
repos.route('/', createInternalRepoRoutes(db, settingsService))
repos.route('/:id/schedules', createScheduleRoutes(scheduleService))
app.route('/repos', repos)
return app
Expand Down
23 changes: 23 additions & 0 deletions backend/src/routes/internal/repos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Hono } from 'hono'
import type { Database } from 'bun:sqlite'
import type { SettingsService } from '../../services/settings'
import { listRepos } from '../../db/queries'
import { logger } from '../../utils/logger'
import { getErrorMessage } from '../../utils/error-utils'

export function createInternalRepoRoutes(db: Database, settingsService: SettingsService) {
const app = new Hono()

app.get('/', (c) => {
try {
const settings = settingsService.getSettings()
const repos = listRepos(db, settings.preferences.repoOrder)
return c.json({ repos })
} catch (error) {
logger.error('Failed to list internal repos:', error)
return c.json({ error: getErrorMessage(error) }, 500)
}
})

return app
}
76 changes: 71 additions & 5 deletions backend/src/routes/repos.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Hono } from 'hono'
import type { ContentfulStatusCode } from 'hono/utils/http-status'
import type { Database } from 'bun:sqlite'
import type { Repo } from '@opencode-manager/shared/types'
import { DiscoverReposRequestSchema, AssistantModeInitRequestSchema } from '@opencode-manager/shared/schemas'
import { listRepos, getRepoById, updateLastAccessed, updateRepoConfigName } from '../db/queries'
import * as repoService from '../services/repo'
Expand All @@ -17,7 +18,7 @@ import { createRepoGitRoutes } from './repo-git'
import { createScheduleRoutes } from './schedules'
import type { GitAuthService } from '../services/git-auth'
import { ScheduleService } from '../services/schedules'
import { ensureAssistantMode, getAssistantModeStatus } from '../services/assistant-mode'
import { ensureAssistantMode, getAssistantModeStatus, getAssistantModeDirectory } from '../services/assistant-mode'
import path from 'path'

async function restartOpenCode(openCodeSupervisor?: OpenCodeSupervisor): Promise<void> {
Expand Down Expand Up @@ -155,13 +156,36 @@ app.get('/', async (c) => {
app.get('/:id', async (c) => {
try {
const id = parseInt(c.req.param('id'))
const repo = getRepoById(database, id)

let repo: Repo | null
let isAssistant = false
if (id === 0) {
isAssistant = true
repo = {
id: 0,
repoUrl: undefined,
localPath: 'assistant',
sourcePath: undefined,
fullPath: getAssistantModeDirectory(),
branch: undefined,
defaultBranch: 'main',
cloneStatus: 'ready',
clonedAt: Date.now(),
lastPulled: undefined,
lastAccessedAt: undefined,
openCodeConfigName: undefined,
isWorktree: false,
isLocal: false,
}
} else {
repo = getRepoById(database, id)
}

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

const currentBranch = await repoService.getCurrentBranch(repo, gitAuthService.getGitEnvironment())
const currentBranch = isAssistant ? undefined : await repoService.getCurrentBranch(repo, gitAuthService.getGitEnvironment())

return c.json({ ...repo, currentBranch })
} catch (error: unknown) {
Expand Down Expand Up @@ -397,7 +421,28 @@ app.get('/', async (c) => {
app.get('/:id/assistant-mode', async (c) => {
try {
const id = parseInt(c.req.param('id'))
const repo = getRepoById(database, id)

let repo: Repo | null
if (id === 0) {
repo = {
id: 0,
repoUrl: undefined,
localPath: 'assistant',
sourcePath: undefined,
fullPath: '',
branch: undefined,
defaultBranch: 'main',
cloneStatus: 'ready',
clonedAt: Date.now(),
lastPulled: undefined,
lastAccessedAt: undefined,
openCodeConfigName: undefined,
isWorktree: false,
isLocal: false,
}
} else {
repo = getRepoById(database, id)
}

if (!repo) {
return c.json({ error: 'Repo not found' }, 404)
Expand All @@ -414,7 +459,28 @@ app.get('/', async (c) => {
app.post('/:id/assistant-mode', async (c) => {
try {
const id = parseInt(c.req.param('id'))
const repo = getRepoById(database, id)

let repo: Repo | null
if (id === 0) {
repo = {
id: 0,
repoUrl: undefined,
localPath: 'assistant',
sourcePath: undefined,
fullPath: '',
branch: undefined,
defaultBranch: 'main',
cloneStatus: 'ready',
clonedAt: Date.now(),
lastPulled: undefined,
lastAccessedAt: undefined,
openCodeConfigName: undefined,
isWorktree: false,
isLocal: false,
}
} else {
repo = getRepoById(database, id)
}

if (!repo) {
return c.json({ error: 'Repo not found' }, 404)
Expand Down
Loading
Loading