mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
refactor: share remote agent command parsing
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { GEMINI_PERMISSION_MODES, OPENCODE_PERMISSION_MODES } from '@hapi/protocol/modes'
|
||||
import { parseRemoteAgentCommandOptions } from './agentCommandOptions'
|
||||
|
||||
describe('parseRemoteAgentCommandOptions', () => {
|
||||
it('parses common remote agent flags', () => {
|
||||
expect(parseRemoteAgentCommandOptions([
|
||||
'--started-by', 'runner',
|
||||
'--hapi-starting-mode', 'remote',
|
||||
'--permission-mode', 'yolo',
|
||||
'--resume', 'session-1',
|
||||
'--model', 'model-a'
|
||||
], GEMINI_PERMISSION_MODES)).toEqual({
|
||||
startedBy: 'runner',
|
||||
startingMode: 'remote',
|
||||
permissionMode: 'yolo',
|
||||
resumeSessionId: 'session-1',
|
||||
model: 'model-a'
|
||||
})
|
||||
})
|
||||
|
||||
it('does not let --yolo override an explicit permission mode that appeared first', () => {
|
||||
expect(parseRemoteAgentCommandOptions([
|
||||
'--permission-mode', 'default',
|
||||
'--yolo'
|
||||
], OPENCODE_PERMISSION_MODES).permissionMode).toBe('default')
|
||||
})
|
||||
|
||||
it('keeps current unknown-arg behavior by ignoring unrecognized flags', () => {
|
||||
expect(parseRemoteAgentCommandOptions([
|
||||
'--unknown',
|
||||
'value',
|
||||
'--model',
|
||||
'model-a'
|
||||
], GEMINI_PERMISSION_MODES)).toEqual({
|
||||
model: 'model-a'
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects invalid constrained values', () => {
|
||||
expect(() => parseRemoteAgentCommandOptions([
|
||||
'--hapi-starting-mode',
|
||||
'sideways'
|
||||
], GEMINI_PERMISSION_MODES)).toThrow('Invalid --hapi-starting-mode')
|
||||
|
||||
expect(() => parseRemoteAgentCommandOptions([
|
||||
'--permission-mode',
|
||||
'bypassPermissions'
|
||||
], GEMINI_PERMISSION_MODES)).toThrow('Invalid --permission-mode value')
|
||||
})
|
||||
|
||||
it('requires values for resume and model flags', () => {
|
||||
expect(() => parseRemoteAgentCommandOptions(['--resume'], OPENCODE_PERMISSION_MODES)).toThrow('Missing --resume value')
|
||||
expect(() => parseRemoteAgentCommandOptions(['--model'], OPENCODE_PERMISSION_MODES)).toThrow('Missing --model value')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,54 @@
|
||||
import type { PermissionMode } from '@hapi/protocol/types'
|
||||
|
||||
export type RemoteAgentCommandOptions<TPermissionMode extends PermissionMode> = {
|
||||
startedBy?: 'runner' | 'terminal'
|
||||
startingMode?: 'local' | 'remote'
|
||||
permissionMode?: TPermissionMode
|
||||
model?: string
|
||||
resumeSessionId?: string
|
||||
}
|
||||
|
||||
export function parseRemoteAgentCommandOptions<TPermissionMode extends PermissionMode>(
|
||||
args: string[],
|
||||
allowedPermissionModes: readonly TPermissionMode[]
|
||||
): RemoteAgentCommandOptions<TPermissionMode> {
|
||||
const options: RemoteAgentCommandOptions<TPermissionMode> = {}
|
||||
let hasExplicitPermissionMode = false
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i]
|
||||
if (arg === '--started-by') {
|
||||
options.startedBy = args[++i] as 'runner' | 'terminal'
|
||||
} else if (arg === '--hapi-starting-mode') {
|
||||
const value = args[++i]
|
||||
if (value === 'local' || value === 'remote') {
|
||||
options.startingMode = value
|
||||
} else {
|
||||
throw new Error('Invalid --hapi-starting-mode (expected local or remote)')
|
||||
}
|
||||
} else if (arg === '--permission-mode') {
|
||||
const mode = args[++i]
|
||||
if (!mode || !(allowedPermissionModes as readonly string[]).includes(mode)) {
|
||||
throw new Error(`Invalid --permission-mode value: ${mode ?? '(missing)'}`)
|
||||
}
|
||||
options.permissionMode = mode as TPermissionMode
|
||||
hasExplicitPermissionMode = true
|
||||
} else if (arg === '--yolo' && !hasExplicitPermissionMode) {
|
||||
options.permissionMode = 'yolo' as TPermissionMode
|
||||
} else if (arg === '--resume') {
|
||||
const sessionId = args[++i]
|
||||
if (!sessionId) {
|
||||
throw new Error('Missing --resume value')
|
||||
}
|
||||
options.resumeSessionId = sessionId
|
||||
} else if (arg === '--model') {
|
||||
const model = args[++i]
|
||||
if (!model) {
|
||||
throw new Error('Missing --model value')
|
||||
}
|
||||
options.model = model
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
@@ -4,57 +4,14 @@ import { initializeToken } from '@/ui/tokenInit'
|
||||
import { maybeAutoStartServer } from '@/utils/autoStartServer'
|
||||
import type { CommandDefinition } from './types'
|
||||
import { GEMINI_PERMISSION_MODES } from '@hapi/protocol/modes'
|
||||
import type { GeminiPermissionMode } from '@hapi/protocol/types'
|
||||
import { parseRemoteAgentCommandOptions } from './agentCommandOptions'
|
||||
|
||||
export const geminiCommand: CommandDefinition = {
|
||||
name: 'gemini',
|
||||
requiresRuntimeAssets: true,
|
||||
run: async ({ commandArgs }) => {
|
||||
try {
|
||||
const options: {
|
||||
startedBy?: 'runner' | 'terminal'
|
||||
startingMode?: 'local' | 'remote'
|
||||
permissionMode?: GeminiPermissionMode
|
||||
model?: string
|
||||
resumeSessionId?: string
|
||||
} = {}
|
||||
|
||||
let hasExplicitPermissionMode = false
|
||||
|
||||
for (let i = 0; i < commandArgs.length; i++) {
|
||||
const arg = commandArgs[i]
|
||||
if (arg === '--started-by') {
|
||||
options.startedBy = commandArgs[++i] as 'runner' | 'terminal'
|
||||
} else if (arg === '--hapi-starting-mode') {
|
||||
const value = commandArgs[++i]
|
||||
if (value === 'local' || value === 'remote') {
|
||||
options.startingMode = value
|
||||
} else {
|
||||
throw new Error('Invalid --hapi-starting-mode (expected local or remote)')
|
||||
}
|
||||
} else if (arg === '--permission-mode') {
|
||||
const mode = commandArgs[++i]
|
||||
if (!mode || !(GEMINI_PERMISSION_MODES as readonly string[]).includes(mode)) {
|
||||
throw new Error(`Invalid --permission-mode value: ${mode ?? '(missing)'}`)
|
||||
}
|
||||
options.permissionMode = mode as GeminiPermissionMode
|
||||
hasExplicitPermissionMode = true
|
||||
} else if (arg === '--yolo' && !hasExplicitPermissionMode) {
|
||||
options.permissionMode = 'yolo'
|
||||
} else if (arg === '--resume') {
|
||||
const sessionId = commandArgs[++i]
|
||||
if (!sessionId) {
|
||||
throw new Error('Missing --resume value')
|
||||
}
|
||||
options.resumeSessionId = sessionId
|
||||
} else if (arg === '--model') {
|
||||
const model = commandArgs[++i]
|
||||
if (!model) {
|
||||
throw new Error('Missing --model value')
|
||||
}
|
||||
options.model = model
|
||||
}
|
||||
}
|
||||
const options = parseRemoteAgentCommandOptions(commandArgs, GEMINI_PERMISSION_MODES)
|
||||
|
||||
await initializeToken()
|
||||
await maybeAutoStartServer()
|
||||
|
||||
@@ -4,57 +4,14 @@ import { initializeToken } from '@/ui/tokenInit'
|
||||
import { maybeAutoStartServer } from '@/utils/autoStartServer'
|
||||
import type { CommandDefinition } from './types'
|
||||
import { OPENCODE_PERMISSION_MODES } from '@hapi/protocol/modes'
|
||||
import type { OpencodePermissionMode } from '@hapi/protocol/types'
|
||||
import { parseRemoteAgentCommandOptions } from './agentCommandOptions'
|
||||
|
||||
export const opencodeCommand: CommandDefinition = {
|
||||
name: 'opencode',
|
||||
requiresRuntimeAssets: true,
|
||||
run: async ({ commandArgs }) => {
|
||||
try {
|
||||
const options: {
|
||||
startedBy?: 'runner' | 'terminal'
|
||||
startingMode?: 'local' | 'remote'
|
||||
permissionMode?: OpencodePermissionMode
|
||||
model?: string
|
||||
resumeSessionId?: string
|
||||
} = {}
|
||||
|
||||
let hasExplicitPermissionMode = false
|
||||
|
||||
for (let i = 0; i < commandArgs.length; i++) {
|
||||
const arg = commandArgs[i]
|
||||
if (arg === '--started-by') {
|
||||
options.startedBy = commandArgs[++i] as 'runner' | 'terminal'
|
||||
} else if (arg === '--hapi-starting-mode') {
|
||||
const value = commandArgs[++i]
|
||||
if (value === 'local' || value === 'remote') {
|
||||
options.startingMode = value
|
||||
} else {
|
||||
throw new Error('Invalid --hapi-starting-mode (expected local or remote)')
|
||||
}
|
||||
} else if (arg === '--permission-mode') {
|
||||
const mode = commandArgs[++i]
|
||||
if (!mode || !(OPENCODE_PERMISSION_MODES as readonly string[]).includes(mode)) {
|
||||
throw new Error(`Invalid --permission-mode value: ${mode ?? '(missing)'}`)
|
||||
}
|
||||
options.permissionMode = mode as OpencodePermissionMode
|
||||
hasExplicitPermissionMode = true
|
||||
} else if (arg === '--yolo' && !hasExplicitPermissionMode) {
|
||||
options.permissionMode = 'yolo'
|
||||
} else if (arg === '--resume') {
|
||||
const sessionId = commandArgs[++i]
|
||||
if (!sessionId) {
|
||||
throw new Error('Missing --resume value')
|
||||
}
|
||||
options.resumeSessionId = sessionId
|
||||
} else if (arg === '--model') {
|
||||
const model = commandArgs[++i]
|
||||
if (!model) {
|
||||
throw new Error('Missing --model value')
|
||||
}
|
||||
options.model = model
|
||||
}
|
||||
}
|
||||
const options = parseRemoteAgentCommandOptions(commandArgs, OPENCODE_PERMISSION_MODES)
|
||||
|
||||
await initializeToken()
|
||||
await maybeAutoStartServer()
|
||||
|
||||
Reference in New Issue
Block a user