feat: add vault ai agent permission modes
This commit is contained in:
@@ -104,6 +104,7 @@ describe('streamAiAgent', () => {
|
||||
message: 'Explain this',
|
||||
systemPrompt: 'SYSTEM',
|
||||
vaultPath: '/vault',
|
||||
permissionMode: 'power_user',
|
||||
callbacks,
|
||||
})
|
||||
|
||||
@@ -116,6 +117,7 @@ describe('streamAiAgent', () => {
|
||||
message: 'Explain this',
|
||||
system_prompt: 'SYSTEM',
|
||||
vault_path: '/vault',
|
||||
permission_mode: 'power_user',
|
||||
},
|
||||
})
|
||||
expect(callbacks.onThinking).toHaveBeenCalledWith('thinking...')
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { isTauri } from '../mock-tauri'
|
||||
import { getAiAgentDefinition, type AiAgentId } from '../lib/aiAgents'
|
||||
import {
|
||||
normalizeAiAgentPermissionMode,
|
||||
type AiAgentPermissionMode,
|
||||
} from '../lib/aiAgentPermissionMode'
|
||||
|
||||
type AiAgentStreamEvent =
|
||||
| { kind: 'Init'; session_id: string }
|
||||
@@ -24,6 +28,7 @@ export interface StreamAiAgentRequest {
|
||||
message: string
|
||||
systemPrompt?: string
|
||||
vaultPath: string
|
||||
permissionMode?: AiAgentPermissionMode
|
||||
callbacks: AgentStreamCallbacks
|
||||
}
|
||||
|
||||
@@ -70,6 +75,7 @@ export async function streamAiAgent(
|
||||
message,
|
||||
systemPrompt,
|
||||
vaultPath,
|
||||
permissionMode,
|
||||
callbacks,
|
||||
} = request
|
||||
|
||||
@@ -107,6 +113,7 @@ export async function streamAiAgent(
|
||||
message,
|
||||
system_prompt: systemPrompt || null,
|
||||
vault_path: vaultPath,
|
||||
permission_mode: normalizeAiAgentPermissionMode(permissionMode),
|
||||
},
|
||||
})
|
||||
closeStream()
|
||||
|
||||
60
src/utils/vaultConfigStore.test.ts
Normal file
60
src/utils/vaultConfigStore.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { VaultConfig } from '../types'
|
||||
import {
|
||||
bindVaultConfigStore,
|
||||
getVaultConfig,
|
||||
resetVaultConfigStore,
|
||||
updateVaultConfigField,
|
||||
} from './vaultConfigStore'
|
||||
|
||||
function vaultConfig(overrides: Partial<VaultConfig> = {}): VaultConfig {
|
||||
return {
|
||||
zoom: null,
|
||||
view_mode: null,
|
||||
editor_mode: null,
|
||||
note_layout: null,
|
||||
tag_colors: null,
|
||||
status_colors: null,
|
||||
property_display_modes: null,
|
||||
inbox: null,
|
||||
allNotes: null,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
describe('vaultConfigStore', () => {
|
||||
beforeEach(() => {
|
||||
resetVaultConfigStore()
|
||||
})
|
||||
|
||||
it('normalizes missing, null, and unknown AI agent permission modes to safe', () => {
|
||||
bindVaultConfigStore(vaultConfig(), vi.fn())
|
||||
expect(getVaultConfig().ai_agent_permission_mode).toBe('safe')
|
||||
|
||||
bindVaultConfigStore(vaultConfig({ ai_agent_permission_mode: null }), vi.fn())
|
||||
expect(getVaultConfig().ai_agent_permission_mode).toBe('safe')
|
||||
|
||||
bindVaultConfigStore({
|
||||
...vaultConfig(),
|
||||
ai_agent_permission_mode: 'danger' as VaultConfig['ai_agent_permission_mode'],
|
||||
}, vi.fn())
|
||||
expect(getVaultConfig().ai_agent_permission_mode).toBe('safe')
|
||||
})
|
||||
|
||||
it('persists normalized AI agent permission mode updates', () => {
|
||||
const save = vi.fn()
|
||||
bindVaultConfigStore(vaultConfig(), save)
|
||||
|
||||
updateVaultConfigField('ai_agent_permission_mode', 'power_user')
|
||||
expect(getVaultConfig().ai_agent_permission_mode).toBe('power_user')
|
||||
expect(save).toHaveBeenLastCalledWith(expect.objectContaining({
|
||||
ai_agent_permission_mode: 'power_user',
|
||||
}))
|
||||
|
||||
updateVaultConfigField('ai_agent_permission_mode', null)
|
||||
expect(getVaultConfig().ai_agent_permission_mode).toBe('safe')
|
||||
expect(save).toHaveBeenLastCalledWith(expect.objectContaining({
|
||||
ai_agent_permission_mode: 'safe',
|
||||
}))
|
||||
})
|
||||
})
|
||||
@@ -1,12 +1,17 @@
|
||||
import type { VaultConfig } from '../types'
|
||||
import {
|
||||
DEFAULT_AI_AGENT_PERMISSION_MODE,
|
||||
normalizeAiAgentPermissionMode,
|
||||
} from '../lib/aiAgentPermissionMode'
|
||||
|
||||
type SaveFn = (config: VaultConfig) => void
|
||||
type Listener = () => void
|
||||
|
||||
const DEFAULT_CONFIG: VaultConfig = {
|
||||
zoom: null, view_mode: null, editor_mode: null, note_layout: null,
|
||||
ai_agent_permission_mode: DEFAULT_AI_AGENT_PERMISSION_MODE,
|
||||
tag_colors: null, status_colors: null, property_display_modes: null,
|
||||
inbox: null,
|
||||
inbox: null, allNotes: null,
|
||||
}
|
||||
|
||||
let config: VaultConfig = DEFAULT_CONFIG
|
||||
@@ -18,7 +23,7 @@ export function getVaultConfig(): VaultConfig {
|
||||
}
|
||||
|
||||
export function bindVaultConfigStore(initial: VaultConfig, save: SaveFn): void {
|
||||
config = initial
|
||||
config = normalizeVaultConfig(initial)
|
||||
saveFn = save
|
||||
notify()
|
||||
}
|
||||
@@ -29,7 +34,7 @@ export function resetVaultConfigStore(): void {
|
||||
}
|
||||
|
||||
export function updateVaultConfigField<K extends keyof VaultConfig>(key: K, value: VaultConfig[K]): void {
|
||||
config = { ...config, [key]: value }
|
||||
config = normalizeVaultConfig({ ...config, [key]: value })
|
||||
saveFn?.(config)
|
||||
notify()
|
||||
}
|
||||
@@ -42,3 +47,11 @@ export function subscribeVaultConfig(listener: Listener): () => void {
|
||||
function notify(): void {
|
||||
for (const fn of listeners) fn()
|
||||
}
|
||||
|
||||
function normalizeVaultConfig(next: VaultConfig): VaultConfig {
|
||||
return {
|
||||
...DEFAULT_CONFIG,
|
||||
...next,
|
||||
ai_agent_permission_mode: normalizeAiAgentPermissionMode(next.ai_agent_permission_mode),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user