mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 16:03:17 +00:00
304 lines
11 KiB
TypeScript
304 lines
11 KiB
TypeScript
import { z } from 'zod'
|
|
import {
|
|
isFeatureInteractionId,
|
|
type FeatureInteractionId
|
|
} from '../../../../shared/feature-interactions'
|
|
import { isFeatureTipId } from '../../../../shared/feature-tips'
|
|
import {
|
|
normalizeTuiAgentArgsRecord,
|
|
normalizeTuiAgentEnvRecord
|
|
} from '../../../../shared/tui-agent-launch-defaults'
|
|
import { isTuiAgent } from '../../../../shared/tui-agent-config'
|
|
import { isTaskProvider } from '../../../../shared/task-providers'
|
|
import { normalizeDisabledTuiAgents } from '../../../../shared/tui-agent-selection'
|
|
import { normalizePRBotAuthorOverrides } from '../../../../shared/pr-bot-author-overrides'
|
|
import { normalizeWorktreeCardProperties } from '../../../../shared/worktree-card-properties'
|
|
import type { PersistedUIState, TaskProvider } from '../../../../shared/types'
|
|
import { defineMethod, type RpcMethod } from '../core'
|
|
|
|
const NullableString = z.string().nullable()
|
|
const StringArray = z.array(z.string())
|
|
const TaskProviderParam = z.custom<TaskProvider>(isTaskProvider, {
|
|
message: 'Unknown task provider'
|
|
})
|
|
const FeatureTipIds = z.array(z.custom(isFeatureTipId, { message: 'Unknown feature tip id' }))
|
|
const UnknownRecord = z.record(z.string(), z.unknown())
|
|
const UnknownRecordArray = z.array(UnknownRecord)
|
|
const LegacyWorktreeCardProperty = z.enum([
|
|
'status',
|
|
'unread',
|
|
'ci',
|
|
'branch',
|
|
'issue',
|
|
'linear-issue',
|
|
'pr',
|
|
'automation',
|
|
'comment',
|
|
'ports',
|
|
'inline-agents'
|
|
])
|
|
const WorktreeCardProperties = z
|
|
.array(LegacyWorktreeCardProperty)
|
|
.transform((value) => normalizeWorktreeCardProperties(value))
|
|
const AgentActivityDisplayMode = z.enum(['compact', 'full'])
|
|
const StatusBarItem = z.enum([
|
|
'claude',
|
|
'codex',
|
|
'gemini',
|
|
'antigravity',
|
|
'opencode-go',
|
|
'kimi',
|
|
'minimax',
|
|
'grok',
|
|
'ssh',
|
|
'resource-usage',
|
|
'ports'
|
|
])
|
|
const WorkspaceStatusDefinition = z.object({
|
|
id: z.string(),
|
|
label: z.string(),
|
|
color: z.string().optional(),
|
|
icon: z.string().optional()
|
|
})
|
|
const TaskResumeState = z
|
|
.object({
|
|
githubMode: z.enum(['items', 'project']).optional(),
|
|
githubItemsPreset: z.string().nullable().optional(),
|
|
githubItemsQuery: z.string().optional(),
|
|
githubProjectHiddenFieldIdsByView: z.record(z.string(), z.array(z.string())).optional(),
|
|
linearPreset: z.enum(['assigned', 'created', 'all', 'completed']).optional(),
|
|
linearQuery: z.string().optional()
|
|
})
|
|
.strict()
|
|
const WorkspaceCleanupDismissal = z
|
|
.object({
|
|
worktreeId: z.string(),
|
|
dismissedAt: z.number().finite(),
|
|
fingerprint: z.string(),
|
|
classifierVersion: z.number().finite()
|
|
})
|
|
.strict()
|
|
const WorkspaceCleanup = z
|
|
.object({
|
|
dismissals: z.record(z.string(), WorkspaceCleanupDismissal)
|
|
})
|
|
.strict()
|
|
const FeatureInteractionRecord = z
|
|
.object({
|
|
firstInteractedAt: z.number().finite().nonnegative(),
|
|
interactionCount: z.number().int().positive().optional()
|
|
})
|
|
.strict()
|
|
const FeatureInteractions = z
|
|
.record(z.string(), FeatureInteractionRecord)
|
|
.superRefine((value, ctx) => {
|
|
for (const id of Object.keys(value)) {
|
|
if (!isFeatureInteractionId(id)) {
|
|
ctx.addIssue({
|
|
code: z.ZodIssueCode.custom,
|
|
message: `Unknown feature interaction id: ${id}`,
|
|
path: [id]
|
|
})
|
|
}
|
|
}
|
|
})
|
|
const FeatureInteractionIdParam = z.custom<FeatureInteractionId>(isFeatureInteractionId, {
|
|
message: 'Unknown feature interaction id'
|
|
})
|
|
const PRBotAuthorOverrideUpdate = z.object({ author: z.string(), isBot: z.boolean() }).strict()
|
|
const GitHubProjectRef = z
|
|
.object({
|
|
owner: z.string(),
|
|
ownerType: z.enum(['organization', 'user']),
|
|
number: z.number().int()
|
|
})
|
|
.strict()
|
|
const GitHubProjectSettings = z
|
|
.object({
|
|
pinned: z.array(GitHubProjectRef),
|
|
recent: z.array(
|
|
GitHubProjectRef.extend({
|
|
lastOpenedAt: z.string()
|
|
}).strict()
|
|
),
|
|
lastViewByProject: z.record(z.string(), z.object({ viewId: z.string() }).strict()),
|
|
activeProject: GitHubProjectRef.nullable()
|
|
})
|
|
.strict()
|
|
|
|
const SettingsUpdate = z
|
|
.object({
|
|
defaultTuiAgent: z
|
|
.unknown()
|
|
.transform((value) =>
|
|
value === null || value === 'blank' || isTuiAgent(value) ? value : undefined
|
|
)
|
|
.optional(),
|
|
disabledTuiAgents: z
|
|
.unknown()
|
|
.transform((value) => normalizeDisabledTuiAgents(value))
|
|
.optional(),
|
|
agentDefaultArgs: z
|
|
.unknown()
|
|
.transform((value) => normalizeTuiAgentArgsRecord(value))
|
|
.optional(),
|
|
agentDefaultEnv: z
|
|
.unknown()
|
|
.transform((value) => normalizeTuiAgentEnvRecord(value))
|
|
.optional(),
|
|
defaultTaskSource: TaskProviderParam.optional(),
|
|
visibleTaskProviders: z.array(TaskProviderParam).optional(),
|
|
defaultTaskViewPreset: z
|
|
.enum(['issues', 'my-issues', 'prs', 'my-prs', 'review', 'all'])
|
|
.optional(),
|
|
experimentalNewWorktreeCardStyle: z.boolean().optional(),
|
|
agentStatusHooksEnabled: z.boolean().optional(),
|
|
defaultRepoSelection: z.array(z.string()).nullable().optional(),
|
|
defaultLinearTeamSelection: z.array(z.string()).nullable().optional(),
|
|
compactWorktreeCards: z.boolean().optional(),
|
|
minimaxGroupId: z.string().optional(),
|
|
minimaxUsageModels: z.string().optional(),
|
|
githubProjects: GitHubProjectSettings.optional(),
|
|
prBotAuthorOverrides: z
|
|
.unknown()
|
|
.transform((value) => normalizePRBotAuthorOverrides(value))
|
|
.optional()
|
|
})
|
|
.strict()
|
|
.default({})
|
|
|
|
const UiUpdate = z
|
|
.object({
|
|
lastActiveRepoId: NullableString.optional(),
|
|
lastActiveWorktreeId: NullableString.optional(),
|
|
sidebarWidth: z.number().finite().optional(),
|
|
rightSidebarOpen: z.boolean().optional(),
|
|
rightSidebarTab: z
|
|
.enum(['explorer', 'search', 'vault', 'source-control', 'checks', 'ports'])
|
|
.optional(),
|
|
rightSidebarExplorerView: z.enum(['files', 'search']).optional(),
|
|
rightSidebarWidth: z.number().finite().optional(),
|
|
markdownTocPanelWidth: z.number().finite().optional(),
|
|
groupBy: z.enum(['none', 'workspace-status', 'repo', 'pr-status']).optional(),
|
|
showWorkspaceLineage: z.boolean().optional(),
|
|
sortBy: z.enum(['name', 'smart', 'recent', 'repo', 'manual']).optional(),
|
|
projectOrderBy: z.enum(['manual', 'recent']).optional(),
|
|
showActiveOnly: z.boolean().optional(),
|
|
hideSleepingWorkspaces: z.boolean().optional(),
|
|
showSleepingWorkspaces: z.boolean().optional(),
|
|
showInactiveWorkspaces: z.boolean().optional(),
|
|
workspaceHostScope: z.string().optional(),
|
|
visibleWorkspaceHostIds: z.array(z.string()).nullable().optional(),
|
|
workspaceHostOrder: z.array(z.string()).optional(),
|
|
hideDefaultBranchWorkspace: z.boolean().optional(),
|
|
hideAutomationGeneratedWorkspaces: z.boolean().optional(),
|
|
filterRepoIds: StringArray.optional(),
|
|
collapsedGroups: StringArray.optional(),
|
|
uiZoomLevel: z.number().finite().optional(),
|
|
editorFontZoomLevel: z.number().finite().optional(),
|
|
worktreeCardProperties: WorktreeCardProperties.optional(),
|
|
_worktreeCardModeDefaulted: z.boolean().optional(),
|
|
agentActivityDisplayMode: AgentActivityDisplayMode.optional(),
|
|
workspaceStatuses: z.array(WorkspaceStatusDefinition).optional(),
|
|
workspaceBoardOpacity: z.number().finite().optional(),
|
|
workspaceBoardColumnWidth: z.number().finite().optional(),
|
|
syncTaskStatusFromWorkspaceBoard: z.boolean().optional(),
|
|
_workspaceStatusesDefaultOrderMigrated: z.boolean().optional(),
|
|
_workspaceStatusesReorderedDefaultRepaired: z.boolean().optional(),
|
|
_workspaceStatusesDefaultWorkflowMigrated: z.boolean().optional(),
|
|
_workspaceStatusesDefaultVisualsMigrated: z.boolean().optional(),
|
|
statusBarItems: z.array(StatusBarItem).optional(),
|
|
_portsStatusBarDefaultAdded: z.boolean().optional(),
|
|
_kimiStatusBarDefaultAdded: z.boolean().optional(),
|
|
_minimaxStatusBarDefaultAdded: z.boolean().optional(),
|
|
_antigravityStatusBarDefaultAdded: z.boolean().optional(),
|
|
_grokStatusBarDefaultAdded: z.boolean().optional(),
|
|
statusBarVisible: z.boolean().optional(),
|
|
usagePercentageDisplay: z.enum(['used', 'remaining']).optional(),
|
|
dismissedUpdateVersion: NullableString.optional(),
|
|
lastUpdateCheckAt: z.number().finite().nullable().optional(),
|
|
pendingUpdateNudgeId: NullableString.optional(),
|
|
dismissedUpdateNudgeId: NullableString.optional(),
|
|
notificationPermissionRequested: z.boolean().optional(),
|
|
updateReassuranceSeen: z.boolean().optional(),
|
|
acknowledgedAgentsByPaneKey: z.record(z.string(), z.number().finite()).optional(),
|
|
browserDefaultUrl: NullableString.optional(),
|
|
browserDefaultSearchEngine: z
|
|
.enum(['google', 'duckduckgo', 'bing', 'kagi'])
|
|
.nullable()
|
|
.optional(),
|
|
browserDefaultZoomLevel: z.number().finite().optional(),
|
|
browserKagiSessionLink: NullableString.optional(),
|
|
windowBounds: z
|
|
.object({
|
|
x: z.number().finite(),
|
|
y: z.number().finite(),
|
|
width: z.number().finite(),
|
|
height: z.number().finite()
|
|
})
|
|
.nullable()
|
|
.optional(),
|
|
windowMaximized: z.boolean().optional(),
|
|
_sortBySmartMigrated: z.boolean().optional(),
|
|
_inlineAgentsDefaultedForExperiment: z.boolean().optional(),
|
|
_inlineAgentsDefaultedForAllUsers: z.boolean().optional(),
|
|
trustedOrcaHooks: z.record(z.string(), z.unknown()).optional(),
|
|
setupScriptPromptDismissedRepoIds: StringArray.optional(),
|
|
projectOrderManualDefaultNoticeDismissed: z.boolean().optional(),
|
|
usagePercentageDisplayChangeNoticeDismissed: z.boolean().optional(),
|
|
usageEmptyStateDismissed: z.boolean().optional(),
|
|
petVisible: z.boolean().optional(),
|
|
petId: z.string().optional(),
|
|
customPets: UnknownRecordArray.optional(),
|
|
petSize: z.number().finite().optional(),
|
|
sidekickVisible: z.boolean().optional(),
|
|
sidekickId: z.string().optional(),
|
|
customSidekicks: UnknownRecordArray.optional(),
|
|
sidekickSize: z.number().finite().optional(),
|
|
taskResumeState: TaskResumeState.optional(),
|
|
workspaceCleanup: WorkspaceCleanup.optional(),
|
|
featureTipsSeenIds: FeatureTipIds.optional(),
|
|
featureInteractions: FeatureInteractions.optional(),
|
|
contextualToursSeenIds: StringArray.optional(),
|
|
contextualToursAutoEligible: z.boolean().optional()
|
|
})
|
|
.strict()
|
|
.default({})
|
|
|
|
export const CLIENT_UI_METHODS: RpcMethod[] = [
|
|
defineMethod({
|
|
name: 'settings.get',
|
|
params: null,
|
|
handler: (_params, { runtime }) => ({ settings: runtime.getClientSettings() })
|
|
}),
|
|
defineMethod({
|
|
name: 'settings.update',
|
|
params: SettingsUpdate,
|
|
handler: (params, { runtime }) => ({ settings: runtime.updateClientSettings(params) })
|
|
}),
|
|
defineMethod({
|
|
name: 'settings.updatePRBotAuthorOverride',
|
|
params: PRBotAuthorOverrideUpdate,
|
|
handler: (params, { runtime }) => ({ settings: runtime.updateClientPRBotAuthorOverride(params) })
|
|
}),
|
|
defineMethod({
|
|
name: 'ui.get',
|
|
params: null,
|
|
handler: (_params, { runtime }) => ({ ui: runtime.getUIState() })
|
|
}),
|
|
defineMethod({
|
|
name: 'ui.set',
|
|
params: UiUpdate,
|
|
handler: (params, { runtime }) => ({
|
|
ui: runtime.updateUIState(params as Partial<PersistedUIState>)
|
|
})
|
|
}),
|
|
defineMethod({
|
|
name: 'ui.recordFeatureInteraction',
|
|
params: FeatureInteractionIdParam,
|
|
handler: (params, { runtime }) => ({
|
|
ui: runtime.recordFeatureInteraction(params)
|
|
})
|
|
})
|
|
]
|