storagePathManager.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import * as vscode from "vscode"
  2. import * as path from "path"
  3. import * as fs from "fs/promises"
  4. /**
  5. * Gets the base storage path for conversations
  6. * If a custom path is configured, uses that path
  7. * Otherwise uses the default VSCode extension global storage path
  8. */
  9. export async function getStorageBasePath(defaultPath: string): Promise<string> {
  10. // Get user-configured custom storage path
  11. let customStoragePath = ""
  12. try {
  13. // This is the line causing the error in tests
  14. const config = vscode.workspace.getConfiguration("roo-cline")
  15. customStoragePath = config.get<string>("customStoragePath", "")
  16. } catch (error) {
  17. console.warn("Could not access VSCode configuration - using default path")
  18. return defaultPath
  19. }
  20. // If no custom path is set, use default path
  21. if (!customStoragePath) {
  22. return defaultPath
  23. }
  24. try {
  25. // Ensure custom path exists
  26. await fs.mkdir(customStoragePath, { recursive: true })
  27. // Test if path is writable
  28. const testFile = path.join(customStoragePath, ".write_test")
  29. await fs.writeFile(testFile, "test")
  30. await fs.rm(testFile)
  31. return customStoragePath
  32. } catch (error) {
  33. // If path is unusable, report error and fall back to default path
  34. console.error(`Custom storage path is unusable: ${error instanceof Error ? error.message : String(error)}`)
  35. if (vscode.window) {
  36. vscode.window.showErrorMessage(
  37. `Custom storage path "${customStoragePath}" is unusable, will use default path`,
  38. )
  39. }
  40. return defaultPath
  41. }
  42. }
  43. /**
  44. * Gets the storage directory path for a task
  45. */
  46. export async function getTaskDirectoryPath(globalStoragePath: string, taskId: string): Promise<string> {
  47. const basePath = await getStorageBasePath(globalStoragePath)
  48. const taskDir = path.join(basePath, "tasks", taskId)
  49. await fs.mkdir(taskDir, { recursive: true })
  50. return taskDir
  51. }
  52. /**
  53. * Gets the settings directory path
  54. */
  55. export async function getSettingsDirectoryPath(globalStoragePath: string): Promise<string> {
  56. const basePath = await getStorageBasePath(globalStoragePath)
  57. const settingsDir = path.join(basePath, "settings")
  58. await fs.mkdir(settingsDir, { recursive: true })
  59. return settingsDir
  60. }
  61. /**
  62. * Gets the cache directory path
  63. */
  64. export async function getCacheDirectoryPath(globalStoragePath: string): Promise<string> {
  65. const basePath = await getStorageBasePath(globalStoragePath)
  66. const cacheDir = path.join(basePath, "cache")
  67. await fs.mkdir(cacheDir, { recursive: true })
  68. return cacheDir
  69. }
  70. /**
  71. * Prompts the user to set a custom storage path
  72. * Displays an input box allowing the user to enter a custom path
  73. */
  74. export async function promptForCustomStoragePath(): Promise<void> {
  75. if (!vscode.window || !vscode.workspace) {
  76. console.error("VS Code API not available")
  77. return
  78. }
  79. let currentPath = ""
  80. try {
  81. const currentConfig = vscode.workspace.getConfiguration("roo-cline")
  82. currentPath = currentConfig.get<string>("customStoragePath", "")
  83. } catch (error) {
  84. console.error("Could not access configuration")
  85. return
  86. }
  87. const result = await vscode.window.showInputBox({
  88. value: currentPath,
  89. placeHolder: "D:\\RooCodeStorage",
  90. prompt: "Enter custom conversation history storage path, leave empty to use default location",
  91. validateInput: (input) => {
  92. if (!input) {
  93. return null // Allow empty value (use default path)
  94. }
  95. try {
  96. // Validate path format
  97. path.parse(input)
  98. // Check if path is absolute
  99. if (!path.isAbsolute(input)) {
  100. return "Please enter an absolute path (e.g. D:\\RooCodeStorage or /home/user/storage)"
  101. }
  102. return null // Path format is valid
  103. } catch (e) {
  104. return "Please enter a valid path"
  105. }
  106. },
  107. })
  108. // If user canceled the operation, result will be undefined
  109. if (result !== undefined) {
  110. try {
  111. const currentConfig = vscode.workspace.getConfiguration("roo-cline")
  112. await currentConfig.update("customStoragePath", result, vscode.ConfigurationTarget.Global)
  113. if (result) {
  114. try {
  115. // Test if path is accessible
  116. await fs.mkdir(result, { recursive: true })
  117. vscode.window.showInformationMessage(`Custom storage path set: ${result}`)
  118. } catch (error) {
  119. vscode.window.showErrorMessage(
  120. `Cannot access path ${result}: ${error instanceof Error ? error.message : String(error)}`,
  121. )
  122. }
  123. } else {
  124. vscode.window.showInformationMessage("Reverted to using default storage path")
  125. }
  126. } catch (error) {
  127. console.error("Failed to update configuration", error)
  128. }
  129. }
  130. }