Files
goodbuddy/src/shared/remote-project-candidate-contracts.ts
T
mesalogo 9c88ca20f3 feat: layer runtime and model selection across conversation, project and global
- Store runtime selection as { provider?, model? } layers and resolve them per
  field (conversation -> project -> global); drop the legacy auto provider.
- Migrate stored selections (database v49) and clear deleted profile ids.
- Re-resolve selections in Main per request and at queue dispatch.
- Add ProjectRuntimeSelector and a two-column RuntimeModelPicker; manage
  link opens model connections; restore per-runtime default model tabs.
- Stop duplicating trusted instructions and history across OpenCode,
  Continue and DeepSeek Harness runtimes.
- Document the layered design, global provider removal plan and planned
  purpose-specific models.
2026-09-29 21:33:06 +08:00

95 lines
2.4 KiB
TypeScript

import { z } from 'zod'
import { assistantIdSchema, projectCreateSchema } from './assistant-contracts'
import {
REMOTE_WORKSPACE_LIMITS,
remoteAbsolutePathSchema
} from './remote-agent-contracts'
import { runtimeSelectionLayerSchema } from './runtime-selection-contracts'
import { sshHostIdSchema } from './ssh-host-contracts'
export const REMOTE_PROJECT_SAVE_LIMITS = {
maximumAbsolutePathBytes:
REMOTE_WORKSPACE_LIMITS.maximumAbsolutePathBytes
} as const
export const remoteProjectRootPathSchema = remoteAbsolutePathSchema
.refine(
(value) => !/[\p{Cc}\p{Cs}\u2028\u2029\ufffd]/u.test(value),
'Remote project root cannot contain control characters'
)
.refine(
(value) =>
!value.includes('//') &&
!value
.split('/')
.some((segment) => segment === '.' || segment === '..'),
'Remote project root cannot contain empty, dot, or parent segments'
)
const commonDraftFields = {
name: projectCreateSchema.shape.name,
description: projectCreateSchema.shape.description,
defaultWorkMode: projectCreateSchema.shape.defaultWorkMode,
runtimeSelection: runtimeSelectionLayerSchema.optional(),
hostId: sshHostIdSchema,
remoteRootPath: remoteProjectRootPathSchema
} as const
export const remoteProjectCreateDraftSchema =
z.object(commonDraftFields).strict()
export const remoteProjectUpdateDraftSchema = z
.object({
projectId: assistantIdSchema,
...commonDraftFields
})
.strict()
export const remoteProjectSaveRequestSchema = z.discriminatedUnion(
'intent',
[
z
.object({
intent: z.literal('create'),
draft: remoteProjectCreateDraftSchema
})
.strict(),
z
.object({
intent: z.literal('update'),
draft: remoteProjectUpdateDraftSchema
})
.strict()
]
)
export const remoteProjectSavePhaseSchema = z.enum([
'host',
'agent',
'workspace',
'runtime',
'saving'
])
export const remoteProjectSaveProgressSchema = z
.object({
phase: remoteProjectSavePhaseSchema
})
.strict()
export type RemoteProjectCreateDraft = z.infer<
typeof remoteProjectCreateDraftSchema
>
export type RemoteProjectUpdateDraft = z.infer<
typeof remoteProjectUpdateDraftSchema
>
export type RemoteProjectSaveRequest = z.infer<
typeof remoteProjectSaveRequestSchema
>
export type RemoteProjectSavePhase = z.infer<
typeof remoteProjectSavePhaseSchema
>
export type RemoteProjectSaveProgress = z.infer<
typeof remoteProjectSaveProgressSchema
>