[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
104
application/state/useAIPermissionGrantsState.ts
Normal file
104
application/state/useAIPermissionGrantsState.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { localStorageAdapter } from '../../infrastructure/persistence/localStorageAdapter';
|
||||
import { STORAGE_KEY_AI_PERMISSION_GRANTS } from '../../infrastructure/config/storageKeys';
|
||||
import {
|
||||
sanitizePermissionGrants,
|
||||
setActivePermissionGrants,
|
||||
type PermissionGrantRule,
|
||||
} from '../../infrastructure/ai/harness/permissionGrants';
|
||||
import { getAIBridge } from './aiStateSnapshots';
|
||||
import { AI_STATE_CHANGED_EVENT, emitAIStateChanged } from './aiStateEvents';
|
||||
|
||||
function readPermissionGrants(): PermissionGrantRule[] {
|
||||
return sanitizePermissionGrants(localStorageAdapter.read<unknown>(STORAGE_KEY_AI_PERMISSION_GRANTS));
|
||||
}
|
||||
|
||||
function syncPermissionGrantsToMainProcess(rules: PermissionGrantRule[]): void {
|
||||
void getAIBridge()?.aiMcpSyncPermissionGrants?.(rules)?.catch(() => {});
|
||||
}
|
||||
|
||||
function writePermissionGrants(rules: PermissionGrantRule[]): void {
|
||||
localStorageAdapter.write(STORAGE_KEY_AI_PERMISSION_GRANTS, rules);
|
||||
setActivePermissionGrants(rules);
|
||||
syncPermissionGrantsToMainProcess(rules);
|
||||
emitAIStateChanged(STORAGE_KEY_AI_PERMISSION_GRANTS);
|
||||
}
|
||||
|
||||
export function useAIPermissionGrantsState() {
|
||||
const [rules, setRulesRaw] = useState<PermissionGrantRule[]>(() => {
|
||||
const initial = readPermissionGrants();
|
||||
setActivePermissionGrants(initial);
|
||||
return initial;
|
||||
});
|
||||
|
||||
const setRules = useCallback((value: PermissionGrantRule[] | ((prev: PermissionGrantRule[]) => PermissionGrantRule[])) => {
|
||||
setRulesRaw((prev) => {
|
||||
const next = typeof value === 'function' ? value(prev) : value;
|
||||
writePermissionGrants(next);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const addGrant = useCallback((rule: PermissionGrantRule) => {
|
||||
setRules((prev) => [...prev, rule]);
|
||||
}, [setRules]);
|
||||
|
||||
const updateGrant = useCallback((
|
||||
id: string,
|
||||
updates: Partial<Omit<PermissionGrantRule, 'id' | 'createdAt'>>,
|
||||
) => {
|
||||
setRules((prev) => prev.map((rule) => (
|
||||
rule.id === id ? { ...rule, ...updates } : rule
|
||||
)));
|
||||
}, [setRules]);
|
||||
|
||||
const removeGrant = useCallback((id: string) => {
|
||||
setRules((prev) => prev.filter((rule) => rule.id !== id));
|
||||
}, [setRules]);
|
||||
|
||||
const importGrants = useCallback((raw: unknown, mode: 'merge' | 'replace' = 'replace') => {
|
||||
const imported = sanitizePermissionGrants(raw);
|
||||
setRules((prev) => (mode === 'merge' ? [...prev, ...imported] : imported));
|
||||
}, [setRules]);
|
||||
|
||||
const exportGrants = useCallback((): PermissionGrantRule[] => {
|
||||
return readPermissionGrants();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const syncFromStorageKey = (key: string | null) => {
|
||||
if (key !== STORAGE_KEY_AI_PERMISSION_GRANTS) return;
|
||||
const next = readPermissionGrants();
|
||||
setActivePermissionGrants(next);
|
||||
syncPermissionGrantsToMainProcess(next);
|
||||
setRulesRaw(next);
|
||||
};
|
||||
|
||||
const handleStorage = (event: StorageEvent) => syncFromStorageKey(event.key);
|
||||
const handleLocalStateChanged = (event: Event) => {
|
||||
syncFromStorageKey((event as CustomEvent<{ key?: string }>).detail?.key ?? null);
|
||||
};
|
||||
|
||||
window.addEventListener('storage', handleStorage);
|
||||
window.addEventListener(AI_STATE_CHANGED_EVENT, handleLocalStateChanged);
|
||||
return () => {
|
||||
window.removeEventListener('storage', handleStorage);
|
||||
window.removeEventListener(AI_STATE_CHANGED_EVENT, handleLocalStateChanged);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const bridge = getAIBridge();
|
||||
bridge?.aiMcpSyncPermissionGrants?.(rules);
|
||||
}, [rules]);
|
||||
|
||||
return useMemo(() => ({
|
||||
permissionGrants: rules,
|
||||
setPermissionGrants: setRules,
|
||||
addGrant,
|
||||
updateGrant,
|
||||
removeGrant,
|
||||
importGrants,
|
||||
exportGrants,
|
||||
}), [rules, setRules, addGrant, updateGrant, removeGrant, importGrants, exportGrants]);
|
||||
}
|
||||
Reference in New Issue
Block a user