Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 2 additions & 4 deletions backend/src/services/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
getPermissionDetail,
getFormText,
getGoalOutcomeTitle,
getGoalStopReasonLabel,
getGoalOutcomeReason,
} from "@opencode-manager/shared/notifications";
import { SettingsService } from "./settings";
import { sseAggregator, type SSEEvent } from "./sse-aggregator";
Expand Down Expand Up @@ -84,9 +84,7 @@ function truncateWithEllipsis(text: string, maxLength: number): string {
}

function buildGoalOutcomeBody(goal: SessionGoal, repoName: string | undefined): string {
const reason = goal.stopReason
? getGoalStopReasonLabel(goal.stopReason)
: goal.lastReason?.trim() || undefined;
const reason = getGoalOutcomeReason(goal)?.trim() || undefined;
const prefix = repoName ? `${repoName} · ` : "";
const separator = " — ";

Expand Down
34 changes: 34 additions & 0 deletions backend/test/helpers/internal-test-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createInternalRoutes } from '../../src/routes/internal'
import { createStubOpenCodeClient } from './stub-opencode-client'

type CreateInternalRoutesParams = Parameters<typeof createInternalRoutes>

type InternalTestAppOverrides = Partial<{
scheduleService: CreateInternalRoutesParams[1]
notificationService: CreateInternalRoutesParams[2]
settingsService: CreateInternalRoutesParams[3]
openCodeClient: CreateInternalRoutesParams[4]
permissionModes: CreateInternalRoutesParams[5]
repoWorkspaces: CreateInternalRoutesParams[6]
gitAuthService: CreateInternalRoutesParams[7]
sessionGoals: CreateInternalRoutesParams[8]
multiRuns: CreateInternalRoutesParams[9]
}>

export function createInternalTestApp(
db: CreateInternalRoutesParams[0],
overrides: InternalTestAppOverrides = {},
) {
return createInternalRoutes(
db,
overrides.scheduleService ?? ({} as CreateInternalRoutesParams[1]),
overrides.notificationService ?? ({} as CreateInternalRoutesParams[2]),
overrides.settingsService ?? ({} as CreateInternalRoutesParams[3]),
overrides.openCodeClient ?? createStubOpenCodeClient(),
overrides.permissionModes ?? ({} as CreateInternalRoutesParams[5]),
overrides.repoWorkspaces ?? ({} as CreateInternalRoutesParams[6]),
overrides.gitAuthService ?? ({} as CreateInternalRoutesParams[7]),
overrides.sessionGoals ?? ({} as CreateInternalRoutesParams[8]),
overrides.multiRuns ?? ({} as CreateInternalRoutesParams[9]),
)
}
20 changes: 2 additions & 18 deletions backend/test/routes/internal-assistant.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { createInternalRoutes } from '../../src/routes/internal'
import { ScheduleService } from '../../src/services/schedules'
import { NotificationService } from '../../src/services/notification'
import { SettingsService } from '../../src/services/settings'
import { allMigrations } from '../../src/db/migrations'
import { getOrCreateInternalToken } from '../../src/services/internal-token'
import { migrate } from '../../src/db/migration-runner'
import type { OpenCodeClient } from '../../src/services/opencode/client'
import type { ScheduleWorktreeManager } from '../../src/services/schedule-worktree'
import { createInternalTestApp } from '../helpers/internal-test-app'

const readOpenCodeConfigFileMock = vi.hoisted(() => vi.fn())

Expand All @@ -25,9 +16,6 @@ vi.mock('../../src/services/opencode-config-file', async (importOriginal) => ({

describe('internal/assistant routes', () => {
let db: Database
let scheduleService: ScheduleService
let notificationService: NotificationService
let settingsService: SettingsService
let app: Hono
let token: string
let reloadMock: ReturnType<typeof vi.fn>
Expand All @@ -43,12 +31,8 @@ describe('internal/assistant routes', () => {
forwardRaw: vi.fn(),
} as unknown as OpenCodeClient

const stubWorktreeManager = { prepare: () => Promise.resolve(null), finalize: () => Promise.resolve({ commitHash: null }) } as unknown as ScheduleWorktreeManager
scheduleService = new ScheduleService(db, openCodeClient, stubWorktreeManager)
notificationService = new NotificationService(db)
settingsService = new SettingsService(db)
app = new Hono()
app.route('/api/internal', createInternalRoutes(db, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(db, { openCodeClient }))
token = getOrCreateInternalToken(db)
})

Expand Down
26 changes: 2 additions & 24 deletions backend/test/routes/internal-multi-runs.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { createInternalRoutes } from '../../src/routes/internal'
import type { ScheduleService } from '../../src/services/schedules'
import type { NotificationService } from '../../src/services/notification'
import type { SettingsService } from '../../src/services/settings'
import type { OpenCodeClient } from '../../src/services/opencode/client'
import { allMigrations } from '../../src/db/migrations'
import { createInternalTestApp } from '../helpers/internal-test-app'
import { getOrCreateInternalToken } from '../../src/services/internal-token'
import { migrate } from '../../src/db/migration-runner'

Expand Down Expand Up @@ -59,21 +51,7 @@ describe('internal-multi-runs routes', () => {
migrate(db, allMigrations)
multiRuns = createMultiRunStub()
app = new Hono()
app.route(
'/api/internal',
createInternalRoutes(
db,
{} as ScheduleService,
{} as NotificationService,
{} as SettingsService,
{} as OpenCodeClient,
{} as SessionPermissionModeService,
{} as unknown as RepoWorkspaceService,
{} as unknown as GitAuthService,
{} as unknown as SessionGoalService,
multiRuns as unknown as MultiRunService,
),
)
app.route('/api/internal', createInternalTestApp(db, { multiRuns: multiRuns as unknown as MultiRunService }))
token = getOrCreateInternalToken(db)
})

Expand Down
19 changes: 2 additions & 17 deletions backend/test/routes/internal-notifications.test.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,25 @@
import { describe, it, expect, beforeEach, vi } from 'bun:test'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { createInternalRoutes } from '../../src/routes/internal'
import { ScheduleService } from '../../src/services/schedules'
import { NotificationService } from '../../src/services/notification'
import { SettingsService } from '../../src/services/settings'
import { createOpenCodeClient } from '../../src/services/opencode/client'
import { allMigrations } from '../../src/db/migrations'
import { getOrCreateInternalToken } from '../../src/services/internal-token'
import { migrate } from '../../src/db/migration-runner'
import { createScheduleRun, updateScheduleRunMetadata } from '../../src/db/schedules'
import type { ScheduleWorktreeManager } from '../../src/services/schedule-worktree'
import { createInternalTestApp } from '../helpers/internal-test-app'

describe('internal/notifications routes', () => {
let db: Database
let scheduleService: ScheduleService
let notificationService: NotificationService
let settingsService: SettingsService
let app: Hono
let token: string

beforeEach(() => {
db = new Database(':memory:')
migrate(db, allMigrations)
const openCodeClient = createOpenCodeClient()
const stubWorktreeManager = { prepare: () => Promise.resolve(null), finalize: () => Promise.resolve({ commitHash: null }) } as unknown as ScheduleWorktreeManager
scheduleService = new ScheduleService(db, openCodeClient, stubWorktreeManager)
notificationService = new NotificationService(db)
settingsService = new SettingsService(db)
app = new Hono()
app.route('/api/internal', createInternalRoutes(db, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(db, { notificationService }))
token = getOrCreateInternalToken(db)
})

Expand Down
15 changes: 2 additions & 13 deletions backend/test/routes/internal-opencode-config.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
import { describe, it, expect, beforeEach, afterEach, vi } from 'bun:test'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { readFile, writeFile } from 'fs/promises'
import path from 'path'
import { createInternalRoutes } from '../../src/routes/internal'
import { ScheduleService } from '../../src/services/schedules'
import { NotificationService } from '../../src/services/notification'
import { SettingsService } from '../../src/services/settings'
import { ClientError } from '@opencode-manager/shared/opencode'
import type { OpenCodeClient } from '../../src/services/opencode/client'
Expand All @@ -19,7 +11,7 @@ import { getOrCreateInternalToken } from '../../src/services/internal-token'
import { migrate } from '../../src/db/migration-runner'
import { OPENCODE_CONFIG_SEED, readOpenCodeConfigFile, writeOpenCodeConfigFile } from '../../src/services/opencode-config-file'
import { createTempAssistantWorkspace } from '../helpers/assistant-workspace'
import type { ScheduleWorktreeManager } from '../../src/services/schedule-worktree'
import { createInternalTestApp } from '../helpers/internal-test-app'

describe('internal/opencode-config routes', () => {
let db: Database
Expand Down Expand Up @@ -59,12 +51,9 @@ describe('internal/opencode-config routes', () => {
},
forwardRaw: forwardRawMock,
} as unknown as OpenCodeClient
const stubWorktreeManager = { prepare: () => Promise.resolve(null), finalize: () => Promise.resolve({ commitHash: null }) } as unknown as ScheduleWorktreeManager
const scheduleService = new ScheduleService(db, openCodeClient, stubWorktreeManager)
const notificationService = new NotificationService(db)
const settingsService = new SettingsService(db)
app = new Hono()
app.route('/api/internal', createInternalRoutes(db, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(db, { settingsService, openCodeClient }))
token = getOrCreateInternalToken(db)
})

Expand Down
19 changes: 2 additions & 17 deletions backend/test/routes/internal-opencode-workspaces.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import { describe, it, expect, beforeEach, vi } from 'vitest'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import type { Database } from 'bun:sqlite'
import { createInternalRoutes } from '../../src/routes/internal'
import type { ScheduleService } from '../../src/services/schedules'
import type { NotificationService } from '../../src/services/notification'
import type { SettingsService } from '../../src/services/settings'
import type { OpenCodeClient } from '../../src/services/opencode/client'
import type { Repo } from '../../src/types/repo'
import { createInternalTestApp } from '../helpers/internal-test-app'

const mockDb = {
prepare: vi.fn().mockReturnValue({
Expand Down Expand Up @@ -80,14 +71,8 @@ describe('internal-opencode-workspaces routes', () => {
beforeEach(() => {
vi.clearAllMocks()
mockListRepos.mockReturnValue([])
const scheduleService = {} as ScheduleService
const notificationService = {} as NotificationService
const settingsService = {} as SettingsService
const openCodeClient = {
forwardRaw: vi.fn(),
} as unknown as OpenCodeClient
app = new Hono()
app.route('/api/internal', createInternalRoutes(mockDb, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(mockDb))
token = 'test-internal-token'
})

Expand Down
12 changes: 2 additions & 10 deletions backend/test/routes/internal-repos.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { describe, it, expect, beforeEach } from 'vitest'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { createInternalRoutes } from '../../src/routes/internal'
import { ScheduleService } from '../../src/services/schedules'
import { NotificationService } from '../../src/services/notification'
import { SettingsService } from '../../src/services/settings'
import { createOpenCodeClient } from '../../src/services/opencode/client'
import { allMigrations } from '../../src/db/migrations'
Expand All @@ -17,11 +10,11 @@ import { migrate } from '../../src/db/migration-runner'
import { createRepo } from '../../src/db/queries'
import type { CreateRepoInput } from '../../src/types/repo'
import type { ScheduleWorktreeManager } from '../../src/services/schedule-worktree'
import { createInternalTestApp } from '../helpers/internal-test-app'

describe('internal-repos routes', () => {
let db: Database
let scheduleService: ScheduleService
let notificationService: NotificationService
let settingsService: SettingsService
let app: Hono
let token: string
Expand All @@ -32,10 +25,9 @@ describe('internal-repos routes', () => {
const openCodeClient = createOpenCodeClient()
const stubWorktreeManager = { prepare: () => Promise.resolve(null), finalize: () => Promise.resolve({ commitHash: null }) } as unknown as ScheduleWorktreeManager
scheduleService = new ScheduleService(db, openCodeClient, stubWorktreeManager)
notificationService = new NotificationService(db)
settingsService = new SettingsService(db)
app = new Hono()
app.route('/api/internal', createInternalRoutes(db, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(db, { scheduleService, settingsService }))
token = getOrCreateInternalToken(db)
})

Expand Down
17 changes: 2 additions & 15 deletions backend/test/routes/internal-sandbox.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import { afterEach, beforeEach, describe, expect, it, mock, vi } from 'bun:test'
import type { SessionPermissionModeService } from '../../src/services/session-permission-modes'
import type { RepoWorkspaceService } from '../../src/services/repo-workspace'
import type { GitAuthService } from '../../src/services/git-auth'
import type { SessionGoalService } from '../../src/services/session-goals'
import type { MultiRunService } from '../../src/services/multi-runs'
import { Hono } from 'hono'
import { Database } from 'bun:sqlite'
import { mkdirSync, rmSync } from 'node:fs'
import path from 'node:path'
import { createInternalRoutes } from '../../src/routes/internal'
import { ScheduleService } from '../../src/services/schedules'
import { NotificationService } from '../../src/services/notification'
import { SettingsService } from '../../src/services/settings'
import { createOpenCodeClient } from '../../src/services/opencode/client'
import { allMigrations } from '../../src/db/migrations'
import { getOrCreateInternalToken } from '../../src/services/internal-token'
import { migrate } from '../../src/db/migration-runner'
Expand All @@ -26,7 +17,7 @@ import { executeCommand } from '../../src/utils/process'
import { detectSandboxCapability } from '../../src/services/sandbox/capability'
import { forceProcessAttestation } from '../../src/services/opencode/process-identity'
import { getReposPath, ENV } from '@opencode-manager/shared/config/env'
import type { ScheduleWorktreeManager } from '../../src/services/schedule-worktree'
import { createInternalTestApp } from '../helpers/internal-test-app'

function trustedRunningInspect(): { exitCode: number; stdout: string; stderr: string } {
const canonical = buildCanonicalSandboxSpec()
Expand Down Expand Up @@ -92,13 +83,9 @@ describe('internal sandbox routes', () => {
forceProcessAttestation(true)
db = new Database(':memory:')
migrate(db, allMigrations)
const openCodeClient = createOpenCodeClient()
const stubWorktreeManager = { prepare: () => Promise.resolve(null), finalize: () => Promise.resolve({ commitHash: null }) } as unknown as ScheduleWorktreeManager
const scheduleService = new ScheduleService(db, openCodeClient, stubWorktreeManager)
const notificationService = new NotificationService(db)
settingsService = new SettingsService(db)
app = new Hono()
app.route('/api/internal', createInternalRoutes(db, scheduleService, notificationService, settingsService, openCodeClient, {} as SessionPermissionModeService, {} as unknown as RepoWorkspaceService, {} as unknown as GitAuthService, {} as unknown as SessionGoalService, {} as unknown as MultiRunService))
app.route('/api/internal', createInternalTestApp(db))
token = getOrCreateInternalToken(db)
repoDir = path.join(getReposPath(), 'sandbox-route-test')
mkdirSync(repoDir, { recursive: true })
Expand Down
Loading