feat: add vault ai agent permission modes

This commit is contained in:
lucaronin
2026-04-29 00:52:27 +02:00
parent 91db7c0098
commit d2d4746d5c
31 changed files with 1402 additions and 231 deletions

View File

@@ -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...')

View File

@@ -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()

View 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',
}))
})
})

View File

@@ -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),
}
}