File size: 2,130 Bytes
1f21206
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { dirname, join } from 'node:path'
import type { CuGrantFlags } from '../../vendor/computer-use-mcp/types.js'
import { getClaudeConfigHomeDir } from '../envUtils.js'

export type StoredAuthorizedApp = {
  bundleId: string
  displayName: string
  authorizedAt?: string
}

export type StoredComputerUseConfig = {
  enabled?: boolean
  authorizedApps?: StoredAuthorizedApp[]
  grantFlags?: Partial<CuGrantFlags>
  pythonPath?: string | null
}

export const DEFAULT_COMPUTER_USE_ENABLED = true

export const DEFAULT_DESKTOP_GRANT_FLAGS: CuGrantFlags = {
  clipboardRead: true,
  clipboardWrite: true,
  systemKeyCombos: true,
}

export function getComputerUseConfigPath(): string {
  return join(
    getClaudeConfigHomeDir(),
    'cc-haha',
    'computer-use-config.json',
  )
}

export function resolveStoredComputerUseConfig(
  config?: StoredComputerUseConfig,
): {
  enabled: boolean
  authorizedApps: StoredAuthorizedApp[]
  grantFlags: CuGrantFlags
  pythonPath: string | null
} {
  return {
    enabled: config?.enabled ?? DEFAULT_COMPUTER_USE_ENABLED,
    authorizedApps: config?.authorizedApps ?? [],
    grantFlags: {
      ...DEFAULT_DESKTOP_GRANT_FLAGS,
      ...(config?.grantFlags ?? {}),
    },
    pythonPath: normalizePythonPath(config?.pythonPath),
  }
}

export function normalizePythonPath(value: unknown): string | null {
  if (typeof value !== 'string') return null
  const trimmed = value.trim()
  return trimmed.length > 0 ? trimmed : null
}

export async function loadStoredComputerUseConfig(): Promise<
  ReturnType<typeof resolveStoredComputerUseConfig>
> {
  try {
    const raw = await readFile(getComputerUseConfigPath(), 'utf8')
    return resolveStoredComputerUseConfig(JSON.parse(raw))
  } catch {
    return resolveStoredComputerUseConfig()
  }
}

export async function saveStoredComputerUseConfig(
  config: StoredComputerUseConfig,
): Promise<void> {
  const configPath = getComputerUseConfigPath()
  await mkdir(dirname(configPath), { recursive: true })
  await writeFile(configPath, JSON.stringify(config, null, 2), 'utf8')
}