mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
Unify agent flavor definitions
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
|
import type { AgentFlavor } from '@hapi/protocol'
|
||||||
|
|
||||||
export interface SpawnSessionOptions {
|
export interface SpawnSessionOptions {
|
||||||
machineId?: string
|
machineId?: string
|
||||||
directory: string
|
directory: string
|
||||||
sessionId?: string
|
sessionId?: string
|
||||||
resumeSessionId?: string
|
resumeSessionId?: string
|
||||||
approvedNewDirectoryCreation?: boolean
|
approvedNewDirectoryCreation?: boolean
|
||||||
agent?: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode'
|
agent?: AgentFlavor
|
||||||
model?: string
|
model?: string
|
||||||
effort?: string
|
effort?: string
|
||||||
modelReasoningEffort?: string
|
modelReasoningEffort?: string
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CodexCollaborationMode, PermissionMode } from '@hapi/protocol/types'
|
import type { AgentFlavor, CodexCollaborationMode, PermissionMode } from '@hapi/protocol/types'
|
||||||
import type { Server } from 'socket.io'
|
import type { Server } from 'socket.io'
|
||||||
import type { RpcRegistry } from '../socket/rpcRegistry'
|
import type { RpcRegistry } from '../socket/rpcRegistry'
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ export class RpcGateway {
|
|||||||
async spawnSession(
|
async spawnSession(
|
||||||
machineId: string,
|
machineId: string,
|
||||||
directory: string,
|
directory: string,
|
||||||
agent: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode' = 'claude',
|
agent: AgentFlavor = 'claude',
|
||||||
model?: string,
|
model?: string,
|
||||||
modelReasoningEffort?: string,
|
modelReasoningEffort?: string,
|
||||||
yolo?: boolean,
|
yolo?: boolean,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* - No E2E encryption; data is stored as JSON in SQLite
|
* - No E2E encryption; data is stored as JSON in SQLite
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { LocalResumeTarget, ResumableSession } from '@hapi/protocol'
|
import { isKnownFlavor, type LocalResumeTarget, type ResumableSession } from '@hapi/protocol'
|
||||||
import type { AgentFlavor, CodexCollaborationMode, DecryptedMessage, PermissionMode, Session, SyncEvent } from '@hapi/protocol/types'
|
import type { AgentFlavor, CodexCollaborationMode, DecryptedMessage, PermissionMode, Session, SyncEvent } from '@hapi/protocol/types'
|
||||||
import { unwrapRoleWrappedRecordEnvelope } from '@hapi/protocol/messages'
|
import { unwrapRoleWrappedRecordEnvelope } from '@hapi/protocol/messages'
|
||||||
import type { Server } from 'socket.io'
|
import type { Server } from 'socket.io'
|
||||||
@@ -459,7 +459,7 @@ export class SyncEngine {
|
|||||||
async spawnSession(
|
async spawnSession(
|
||||||
machineId: string,
|
machineId: string,
|
||||||
directory: string,
|
directory: string,
|
||||||
agent: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode' = 'claude',
|
agent: AgentFlavor = 'claude',
|
||||||
model?: string,
|
model?: string,
|
||||||
modelReasoningEffort?: string,
|
modelReasoningEffort?: string,
|
||||||
yolo?: boolean,
|
yolo?: boolean,
|
||||||
@@ -486,9 +486,7 @@ export class SyncEngine {
|
|||||||
|
|
||||||
private resolveFlavor(session: Session): AgentFlavor {
|
private resolveFlavor(session: Session): AgentFlavor {
|
||||||
const flavor = session.metadata?.flavor
|
const flavor = session.metadata?.flavor
|
||||||
return flavor === 'codex' || flavor === 'gemini' || flavor === 'opencode' || flavor === 'cursor'
|
return isKnownFlavor(flavor) ? flavor : 'claude'
|
||||||
? flavor
|
|
||||||
: 'claude'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private resolveAgentResumeId(session: Session, namespace: string): string | null {
|
private resolveAgentResumeId(session: Session, namespace: string): string | null {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AgentFlavorSchema } from '@hapi/protocol'
|
||||||
import { Hono } from 'hono'
|
import { Hono } from 'hono'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import type { SyncEngine } from '../../sync/syncEngine'
|
import type { SyncEngine } from '../../sync/syncEngine'
|
||||||
@@ -6,7 +7,7 @@ import { requireMachine } from './guards'
|
|||||||
|
|
||||||
const spawnBodySchema = z.object({
|
const spawnBodySchema = z.object({
|
||||||
directory: z.string().min(1),
|
directory: z.string().min(1),
|
||||||
agent: z.enum(['claude', 'codex', 'cursor', 'gemini', 'opencode']).optional(),
|
agent: AgentFlavorSchema.optional(),
|
||||||
model: z.string().optional(),
|
model: z.string().optional(),
|
||||||
effort: z.string().optional(),
|
effort: z.string().optional(),
|
||||||
modelReasoningEffort: z.string().optional(),
|
modelReasoningEffort: z.string().optional(),
|
||||||
|
|||||||
+6
-2
@@ -1,3 +1,5 @@
|
|||||||
|
import { z } from 'zod'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description The legacy payload type identifier used for all generic agent messages.
|
* @description The legacy payload type identifier used for all generic agent messages.
|
||||||
* Changing this value will affect the communication schema between CLI, Hub, and Web.
|
* Changing this value will affect the communication schema between CLI, Hub, and Web.
|
||||||
@@ -5,6 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
export const AGENT_MESSAGE_PAYLOAD_TYPE = 'codex' as const
|
export const AGENT_MESSAGE_PAYLOAD_TYPE = 'codex' as const
|
||||||
|
|
||||||
|
export const AGENT_FLAVORS = ['claude', 'codex', 'cursor', 'gemini', 'opencode'] as const
|
||||||
|
export type AgentFlavor = typeof AGENT_FLAVORS[number]
|
||||||
|
export const AgentFlavorSchema = z.enum(AGENT_FLAVORS)
|
||||||
|
|
||||||
export const CLAUDE_PERMISSION_MODES = ['default', 'acceptEdits', 'bypassPermissions', 'plan'] as const
|
export const CLAUDE_PERMISSION_MODES = ['default', 'acceptEdits', 'bypassPermissions', 'plan'] as const
|
||||||
export type ClaudePermissionMode = typeof CLAUDE_PERMISSION_MODES[number]
|
export type ClaudePermissionMode = typeof CLAUDE_PERMISSION_MODES[number]
|
||||||
|
|
||||||
@@ -35,8 +41,6 @@ export const PERMISSION_MODES = [
|
|||||||
] as const
|
] as const
|
||||||
export type PermissionMode = typeof PERMISSION_MODES[number]
|
export type PermissionMode = typeof PERMISSION_MODES[number]
|
||||||
|
|
||||||
export type AgentFlavor = 'claude' | 'codex' | 'gemini' | 'opencode' | 'cursor'
|
|
||||||
|
|
||||||
export const PERMISSION_MODE_LABELS: Record<PermissionMode, string> = {
|
export const PERMISSION_MODE_LABELS: Record<PermissionMode, string> = {
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
acceptEdits: 'Accept Edits',
|
acceptEdits: 'Accept Edits',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { CodexCollaborationModeSchema, PermissionModeSchema } from './schemas'
|
import { CodexCollaborationModeSchema, PermissionModeSchema } from './schemas'
|
||||||
|
import { AgentFlavorSchema } from './modes'
|
||||||
export const AgentFlavorSchema = z.enum(['claude', 'codex', 'gemini', 'opencode', 'cursor'])
|
|
||||||
|
|
||||||
export const LocalResumeTargetSchema = z.object({
|
export const LocalResumeTargetSchema = z.object({
|
||||||
sessionId: z.string().min(1),
|
sessionId: z.string().min(1),
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import type {
|
|||||||
SessionResponse,
|
SessionResponse,
|
||||||
SessionsResponse
|
SessionsResponse
|
||||||
} from '@/types/api'
|
} from '@/types/api'
|
||||||
|
import type { AgentFlavor } from '@hapi/protocol'
|
||||||
import type { CancelMessageResponse } from '@hapi/protocol/schemas'
|
import type { CancelMessageResponse } from '@hapi/protocol/schemas'
|
||||||
|
|
||||||
type ApiClientOptions = {
|
type ApiClientOptions = {
|
||||||
@@ -459,7 +460,7 @@ export class ApiClient {
|
|||||||
async spawnSession(
|
async spawnSession(
|
||||||
machineId: string,
|
machineId: string,
|
||||||
directory: string,
|
directory: string,
|
||||||
agent?: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode',
|
agent?: AgentFlavor,
|
||||||
model?: string,
|
model?: string,
|
||||||
modelReasoningEffort?: string,
|
modelReasoningEffort?: string,
|
||||||
yolo?: boolean,
|
yolo?: boolean,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { AGENT_FLAVORS } from '@hapi/protocol'
|
||||||
import type { AgentType } from './types'
|
import type { AgentType } from './types'
|
||||||
import { useTranslation } from '@/lib/use-translation'
|
import { useTranslation } from '@/lib/use-translation'
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ export function AgentSelector(props: {
|
|||||||
{t('newSession.agent')}
|
{t('newSession.agent')}
|
||||||
</label>
|
</label>
|
||||||
<div className="flex flex-wrap gap-x-3 gap-y-2">
|
<div className="flex flex-wrap gap-x-3 gap-y-2">
|
||||||
{(['claude', 'codex', 'cursor', 'gemini', 'opencode'] as const).map((agentType) => (
|
{AGENT_FLAVORS.map((agentType) => (
|
||||||
<label
|
<label
|
||||||
key={agentType}
|
key={agentType}
|
||||||
className="flex items-center gap-1.5 cursor-pointer"
|
className="flex items-center gap-1.5 cursor-pointer"
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import { AGENT_FLAVORS } from '@hapi/protocol'
|
||||||
import type { AgentType } from './types'
|
import type { AgentType } from './types'
|
||||||
|
|
||||||
const AGENT_STORAGE_KEY = 'hapi:newSession:agent'
|
const AGENT_STORAGE_KEY = 'hapi:newSession:agent'
|
||||||
const YOLO_STORAGE_KEY = 'hapi:newSession:yolo'
|
const YOLO_STORAGE_KEY = 'hapi:newSession:yolo'
|
||||||
|
|
||||||
const VALID_AGENTS: AgentType[] = ['claude', 'codex', 'cursor', 'gemini', 'opencode']
|
const VALID_AGENTS = AGENT_FLAVORS
|
||||||
|
|
||||||
export function loadPreferredAgent(): AgentType {
|
export function loadPreferredAgent(): AgentType {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { GEMINI_MODEL_PRESETS, GEMINI_MODEL_LABELS } from '@hapi/protocol'
|
import { GEMINI_MODEL_PRESETS, GEMINI_MODEL_LABELS } from '@hapi/protocol'
|
||||||
|
import type { AgentFlavor } from '@hapi/protocol'
|
||||||
|
|
||||||
export type AgentType = 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode'
|
export type AgentType = AgentFlavor
|
||||||
export type SessionType = 'simple' | 'worktree'
|
export type SessionType = 'simple' | 'worktree'
|
||||||
export type CodexReasoningEffort = 'default' | 'low' | 'medium' | 'high' | 'xhigh'
|
export type CodexReasoningEffort = 'default' | 'low' | 'medium' | 'high' | 'xhigh'
|
||||||
export type ClaudeEffort = 'auto' | 'medium' | 'high' | 'max'
|
export type ClaudeEffort = 'auto' | 'medium' | 'high' | 'max'
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||||
|
import type { AgentFlavor } from '@hapi/protocol'
|
||||||
import type { ApiClient } from '@/api/client'
|
import type { ApiClient } from '@/api/client'
|
||||||
import type { SpawnResponse } from '@/types/api'
|
import type { SpawnResponse } from '@/types/api'
|
||||||
import { queryKeys } from '@/lib/query-keys'
|
import { queryKeys } from '@/lib/query-keys'
|
||||||
@@ -6,7 +7,7 @@ import { queryKeys } from '@/lib/query-keys'
|
|||||||
type SpawnInput = {
|
type SpawnInput = {
|
||||||
machineId: string
|
machineId: string
|
||||||
directory: string
|
directory: string
|
||||||
agent?: 'claude' | 'codex' | 'cursor' | 'gemini' | 'opencode'
|
agent?: AgentFlavor
|
||||||
model?: string
|
model?: string
|
||||||
effort?: string
|
effort?: string
|
||||||
modelReasoningEffort?: string
|
modelReasoningEffort?: string
|
||||||
|
|||||||
Reference in New Issue
Block a user