@build-astron-co/nimbus 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (469) hide show
  1. package/bin/nimbus +26 -10
  2. package/bin/nimbus.cmd +41 -0
  3. package/bin/nimbus.mjs +70 -0
  4. package/completions/nimbus.bash +38 -0
  5. package/completions/nimbus.fish +48 -0
  6. package/completions/nimbus.zsh +81 -0
  7. package/dist/src/agent/compaction-agent.js +215 -0
  8. package/dist/src/agent/context-manager.js +385 -0
  9. package/dist/src/agent/context.js +322 -0
  10. package/dist/src/agent/deploy-preview.js +395 -0
  11. package/dist/src/agent/expand-files.js +95 -0
  12. package/dist/src/agent/index.js +18 -0
  13. package/dist/src/agent/loop.js +1535 -0
  14. package/dist/src/agent/modes.js +347 -0
  15. package/dist/src/agent/permissions.js +396 -0
  16. package/dist/src/agent/subagents/base.js +67 -0
  17. package/dist/src/agent/subagents/cost.js +45 -0
  18. package/dist/src/agent/subagents/explore.js +36 -0
  19. package/dist/src/agent/subagents/general.js +41 -0
  20. package/dist/src/agent/subagents/index.js +88 -0
  21. package/dist/src/agent/subagents/infra.js +52 -0
  22. package/dist/src/agent/subagents/security.js +60 -0
  23. package/dist/src/agent/system-prompt.js +860 -0
  24. package/dist/src/app.js +152 -0
  25. package/dist/src/audit/activity-log.js +209 -0
  26. package/dist/src/audit/compliance-checker.js +419 -0
  27. package/dist/src/audit/cost-tracker.js +231 -0
  28. package/dist/src/audit/index.js +10 -0
  29. package/dist/src/audit/security-scanner.js +490 -0
  30. package/dist/src/auth/guard.js +64 -0
  31. package/dist/src/auth/index.js +19 -0
  32. package/dist/src/auth/keychain.js +79 -0
  33. package/dist/src/auth/oauth.js +389 -0
  34. package/dist/src/auth/providers.js +415 -0
  35. package/dist/src/auth/sso.js +87 -0
  36. package/dist/src/auth/store.js +424 -0
  37. package/dist/src/auth/types.js +5 -0
  38. package/dist/src/cli/index.js +8 -0
  39. package/dist/src/cli/init.js +1048 -0
  40. package/dist/src/cli/openapi-spec.js +346 -0
  41. package/dist/src/cli/run.js +505 -0
  42. package/dist/src/cli/serve-auth.js +56 -0
  43. package/dist/src/cli/serve.js +432 -0
  44. package/dist/src/cli/web.js +50 -0
  45. package/dist/src/cli.js +1574 -0
  46. package/dist/src/clients/core-engine-client.js +156 -0
  47. package/dist/src/clients/enterprise-client.js +246 -0
  48. package/dist/src/clients/generator-client.js +219 -0
  49. package/dist/src/clients/git-client.js +367 -0
  50. package/dist/src/clients/github-client.js +229 -0
  51. package/dist/src/clients/helm-client.js +299 -0
  52. package/dist/src/clients/index.js +18 -0
  53. package/dist/src/clients/k8s-client.js +270 -0
  54. package/dist/src/clients/llm-client.js +119 -0
  55. package/dist/src/clients/rest-client.js +104 -0
  56. package/dist/src/clients/service-discovery.js +35 -0
  57. package/dist/src/clients/terraform-client.js +302 -0
  58. package/dist/src/clients/tools-client.js +1227 -0
  59. package/dist/src/clients/ws-client.js +93 -0
  60. package/dist/src/commands/alias.js +91 -0
  61. package/dist/src/commands/analyze/index.js +313 -0
  62. package/dist/src/commands/apply/helm.js +375 -0
  63. package/dist/src/commands/apply/index.js +176 -0
  64. package/dist/src/commands/apply/k8s.js +350 -0
  65. package/dist/src/commands/apply/terraform.js +465 -0
  66. package/dist/src/commands/ask.js +137 -0
  67. package/dist/src/commands/audit/index.js +322 -0
  68. package/dist/src/commands/auth-cloud.js +345 -0
  69. package/dist/src/commands/auth-list.js +112 -0
  70. package/dist/src/commands/auth-profile.js +104 -0
  71. package/dist/src/commands/auth-refresh.js +161 -0
  72. package/dist/src/commands/auth-status.js +122 -0
  73. package/dist/src/commands/aws/ec2.js +402 -0
  74. package/dist/src/commands/aws/iam.js +304 -0
  75. package/dist/src/commands/aws/index.js +108 -0
  76. package/dist/src/commands/aws/lambda.js +317 -0
  77. package/dist/src/commands/aws/rds.js +345 -0
  78. package/dist/src/commands/aws/s3.js +346 -0
  79. package/dist/src/commands/aws/vpc.js +302 -0
  80. package/dist/src/commands/aws-discover.js +413 -0
  81. package/dist/src/commands/aws-terraform.js +618 -0
  82. package/dist/src/commands/azure/aks.js +305 -0
  83. package/dist/src/commands/azure/functions.js +200 -0
  84. package/dist/src/commands/azure/index.js +93 -0
  85. package/dist/src/commands/azure/storage.js +378 -0
  86. package/dist/src/commands/azure/vm.js +291 -0
  87. package/dist/src/commands/billing/index.js +224 -0
  88. package/dist/src/commands/chat.js +259 -0
  89. package/dist/src/commands/completions.js +255 -0
  90. package/dist/src/commands/config.js +291 -0
  91. package/dist/src/commands/cost/cloud-cost-estimator.js +211 -0
  92. package/dist/src/commands/cost/estimator.js +73 -0
  93. package/dist/src/commands/cost/index.js +625 -0
  94. package/dist/src/commands/cost/parsers/terraform.js +234 -0
  95. package/dist/src/commands/cost/parsers/types.js +4 -0
  96. package/dist/src/commands/cost/pricing/aws.js +501 -0
  97. package/dist/src/commands/cost/pricing/azure.js +462 -0
  98. package/dist/src/commands/cost/pricing/gcp.js +359 -0
  99. package/dist/src/commands/cost/pricing/index.js +24 -0
  100. package/dist/src/commands/demo.js +196 -0
  101. package/dist/src/commands/deploy.js +215 -0
  102. package/dist/src/commands/doctor.js +1291 -0
  103. package/dist/src/commands/drift/index.js +674 -0
  104. package/dist/src/commands/explain.js +235 -0
  105. package/dist/src/commands/export.js +120 -0
  106. package/dist/src/commands/feedback.js +319 -0
  107. package/dist/src/commands/fix.js +263 -0
  108. package/dist/src/commands/fs/index.js +338 -0
  109. package/dist/src/commands/gcp/compute.js +266 -0
  110. package/dist/src/commands/gcp/functions.js +221 -0
  111. package/dist/src/commands/gcp/gke.js +357 -0
  112. package/dist/src/commands/gcp/iam.js +295 -0
  113. package/dist/src/commands/gcp/index.js +105 -0
  114. package/dist/src/commands/gcp/storage.js +232 -0
  115. package/dist/src/commands/generate-helm.js +1026 -0
  116. package/dist/src/commands/generate-k8s.js +1263 -0
  117. package/dist/src/commands/generate-terraform.js +1058 -0
  118. package/dist/src/commands/gh/index.js +663 -0
  119. package/dist/src/commands/git/index.js +1208 -0
  120. package/dist/src/commands/helm/index.js +985 -0
  121. package/dist/src/commands/help.js +639 -0
  122. package/dist/src/commands/history.js +120 -0
  123. package/dist/src/commands/import.js +782 -0
  124. package/dist/src/commands/incident.js +144 -0
  125. package/dist/src/commands/index.js +109 -0
  126. package/dist/src/commands/init.js +955 -0
  127. package/dist/src/commands/k8s/index.js +979 -0
  128. package/dist/src/commands/login.js +588 -0
  129. package/dist/src/commands/logout.js +61 -0
  130. package/dist/src/commands/logs.js +160 -0
  131. package/dist/src/commands/onboarding.js +382 -0
  132. package/dist/src/commands/pipeline.js +153 -0
  133. package/dist/src/commands/plan/display.js +216 -0
  134. package/dist/src/commands/plan/index.js +525 -0
  135. package/dist/src/commands/plugin.js +325 -0
  136. package/dist/src/commands/preview.js +356 -0
  137. package/dist/src/commands/profile.js +297 -0
  138. package/dist/src/commands/questionnaire.js +1021 -0
  139. package/dist/src/commands/resume.js +35 -0
  140. package/dist/src/commands/rollback.js +259 -0
  141. package/dist/src/commands/rollout.js +74 -0
  142. package/dist/src/commands/runbook.js +307 -0
  143. package/dist/src/commands/schedule.js +202 -0
  144. package/dist/src/commands/status.js +213 -0
  145. package/dist/src/commands/team/index.js +309 -0
  146. package/dist/src/commands/team-context.js +200 -0
  147. package/dist/src/commands/template.js +204 -0
  148. package/dist/src/commands/tf/index.js +989 -0
  149. package/dist/src/commands/upgrade.js +515 -0
  150. package/dist/src/commands/usage/index.js +118 -0
  151. package/dist/src/commands/version.js +145 -0
  152. package/dist/src/commands/watch.js +127 -0
  153. package/dist/src/compat/index.js +2 -0
  154. package/dist/src/compat/runtime.js +10 -0
  155. package/dist/src/compat/sqlite.js +144 -0
  156. package/dist/src/config/index.js +6 -0
  157. package/dist/src/config/manager.js +469 -0
  158. package/dist/src/config/mode-store.js +57 -0
  159. package/dist/src/config/profiles.js +66 -0
  160. package/dist/src/config/safety-policy.js +251 -0
  161. package/dist/src/config/schema.js +107 -0
  162. package/dist/src/config/types.js +311 -0
  163. package/dist/src/config/workspace-state.js +38 -0
  164. package/dist/src/context/context-db.js +138 -0
  165. package/dist/src/demo/index.js +295 -0
  166. package/dist/src/demo/scenarios/full-journey.js +226 -0
  167. package/dist/src/demo/scenarios/getting-started.js +124 -0
  168. package/dist/src/demo/scenarios/helm-release.js +334 -0
  169. package/dist/src/demo/scenarios/k8s-deployment.js +190 -0
  170. package/dist/src/demo/scenarios/terraform-vpc.js +167 -0
  171. package/dist/src/demo/types.js +6 -0
  172. package/dist/src/engine/cost-estimator.js +334 -0
  173. package/dist/src/engine/diagram-generator.js +192 -0
  174. package/dist/src/engine/drift-detector.js +688 -0
  175. package/dist/src/engine/executor.js +832 -0
  176. package/dist/src/engine/index.js +39 -0
  177. package/dist/src/engine/orchestrator.js +436 -0
  178. package/dist/src/engine/planner.js +616 -0
  179. package/dist/src/engine/safety.js +609 -0
  180. package/dist/src/engine/verifier.js +664 -0
  181. package/dist/src/enterprise/audit.js +241 -0
  182. package/dist/src/enterprise/auth.js +189 -0
  183. package/dist/src/enterprise/billing.js +512 -0
  184. package/dist/src/enterprise/index.js +16 -0
  185. package/dist/src/enterprise/teams.js +315 -0
  186. package/dist/src/generator/best-practices.js +1375 -0
  187. package/dist/src/generator/helm.js +495 -0
  188. package/dist/src/generator/index.js +11 -0
  189. package/dist/src/generator/intent-parser.js +420 -0
  190. package/dist/src/generator/kubernetes.js +773 -0
  191. package/dist/src/generator/terraform.js +1472 -0
  192. package/dist/src/history/index.js +6 -0
  193. package/dist/src/history/manager.js +199 -0
  194. package/dist/src/history/types.js +6 -0
  195. package/dist/src/hooks/config.js +318 -0
  196. package/dist/src/hooks/engine.js +317 -0
  197. package/dist/src/hooks/index.js +2 -0
  198. package/dist/src/llm/auth-bridge.js +157 -0
  199. package/dist/src/llm/circuit-breaker.js +116 -0
  200. package/dist/src/llm/config-loader.js +172 -0
  201. package/dist/src/llm/cost-calculator.js +137 -0
  202. package/dist/src/llm/index.js +7 -0
  203. package/dist/src/llm/model-aliases.js +99 -0
  204. package/dist/src/llm/provider-registry.js +57 -0
  205. package/dist/src/llm/providers/anthropic.js +430 -0
  206. package/dist/src/llm/providers/bedrock.js +409 -0
  207. package/dist/src/llm/providers/google.js +344 -0
  208. package/dist/src/llm/providers/ollama.js +661 -0
  209. package/dist/src/llm/providers/openai-compatible.js +289 -0
  210. package/dist/src/llm/providers/openai.js +284 -0
  211. package/dist/src/llm/providers/openrouter.js +293 -0
  212. package/dist/src/llm/router.js +844 -0
  213. package/dist/src/llm/types.js +69 -0
  214. package/dist/src/lsp/client.js +239 -0
  215. package/dist/src/lsp/languages.js +95 -0
  216. package/dist/src/lsp/manager.js +243 -0
  217. package/dist/src/mcp/client.js +289 -0
  218. package/dist/src/mcp/index.js +5 -0
  219. package/dist/src/mcp/manager.js +113 -0
  220. package/dist/src/nimbus.js +212 -0
  221. package/dist/src/plugins/index.js +13 -0
  222. package/dist/src/plugins/loader.js +280 -0
  223. package/dist/src/plugins/manager.js +282 -0
  224. package/dist/src/plugins/types.js +23 -0
  225. package/dist/src/scanners/cicd-scanner.js +230 -0
  226. package/dist/src/scanners/cloud-scanner.js +415 -0
  227. package/dist/src/scanners/framework-scanner.js +430 -0
  228. package/dist/src/scanners/iac-scanner.js +350 -0
  229. package/dist/src/scanners/index.js +454 -0
  230. package/dist/src/scanners/language-scanner.js +258 -0
  231. package/dist/src/scanners/package-manager-scanner.js +252 -0
  232. package/dist/src/scanners/types.js +6 -0
  233. package/dist/src/sessions/manager.js +395 -0
  234. package/dist/src/sessions/types.js +4 -0
  235. package/dist/src/sharing/sync.js +238 -0
  236. package/dist/src/sharing/viewer.js +131 -0
  237. package/dist/src/snapshots/index.js +1 -0
  238. package/dist/src/snapshots/manager.js +432 -0
  239. package/dist/src/state/artifacts.js +94 -0
  240. package/dist/src/state/audit.js +73 -0
  241. package/dist/src/state/billing.js +126 -0
  242. package/dist/src/state/checkpoints.js +81 -0
  243. package/dist/src/state/config.js +58 -0
  244. package/dist/src/state/conversations.js +7 -0
  245. package/dist/src/state/credentials.js +96 -0
  246. package/dist/src/state/db.js +53 -0
  247. package/dist/src/state/index.js +23 -0
  248. package/dist/src/state/messages.js +76 -0
  249. package/dist/src/state/projects.js +92 -0
  250. package/dist/src/state/schema.js +233 -0
  251. package/dist/src/state/sessions.js +79 -0
  252. package/dist/src/state/teams.js +131 -0
  253. package/dist/src/telemetry.js +91 -0
  254. package/dist/src/tools/aws-ops.js +747 -0
  255. package/dist/src/tools/azure-ops.js +491 -0
  256. package/dist/src/tools/file-ops.js +451 -0
  257. package/dist/src/tools/gcp-ops.js +559 -0
  258. package/dist/src/tools/git-ops.js +557 -0
  259. package/dist/src/tools/github-ops.js +460 -0
  260. package/dist/src/tools/helm-ops.js +634 -0
  261. package/dist/src/tools/index.js +16 -0
  262. package/dist/src/tools/k8s-ops.js +579 -0
  263. package/dist/src/tools/schemas/converter.js +129 -0
  264. package/dist/src/tools/schemas/devops.js +3319 -0
  265. package/dist/src/tools/schemas/index.js +19 -0
  266. package/dist/src/tools/schemas/standard.js +966 -0
  267. package/dist/src/tools/schemas/types.js +409 -0
  268. package/dist/src/tools/spawn-exec.js +109 -0
  269. package/dist/src/tools/terraform-ops.js +627 -0
  270. package/dist/src/types/config.js +1 -0
  271. package/dist/src/types/drift.js +4 -0
  272. package/dist/src/types/enterprise.js +5 -0
  273. package/dist/src/types/index.js +14 -0
  274. package/dist/src/types/plan.js +1 -0
  275. package/dist/src/types/request.js +1 -0
  276. package/dist/src/types/response.js +1 -0
  277. package/dist/src/types/service.js +1 -0
  278. package/dist/src/ui/App.js +1672 -0
  279. package/dist/src/ui/DeployPreview.js +60 -0
  280. package/dist/src/ui/FileDiffModal.js +108 -0
  281. package/dist/src/ui/Header.js +46 -0
  282. package/dist/src/ui/HelpModal.js +9 -0
  283. package/dist/src/ui/InputBox.js +408 -0
  284. package/dist/src/ui/MessageList.js +795 -0
  285. package/dist/src/ui/PermissionPrompt.js +72 -0
  286. package/dist/src/ui/StatusBar.js +109 -0
  287. package/dist/src/ui/TerminalPane.js +31 -0
  288. package/dist/src/ui/ToolCallDisplay.js +303 -0
  289. package/dist/src/ui/TreePane.js +83 -0
  290. package/dist/src/ui/chat-ui.js +721 -0
  291. package/dist/src/ui/index.js +11 -0
  292. package/dist/src/ui/ink/index.js +1325 -0
  293. package/dist/src/ui/streaming.js +137 -0
  294. package/dist/src/ui/theme.js +78 -0
  295. package/dist/src/ui/types.js +7 -0
  296. package/dist/src/utils/analytics.js +61 -0
  297. package/dist/src/utils/cost-warning.js +25 -0
  298. package/dist/src/utils/env.js +42 -0
  299. package/dist/src/utils/errors.js +54 -0
  300. package/dist/src/utils/event-bus.js +22 -0
  301. package/dist/src/utils/index.js +16 -0
  302. package/dist/src/utils/logger.js +150 -0
  303. package/dist/src/utils/rate-limiter.js +90 -0
  304. package/dist/src/utils/service-auth.js +36 -0
  305. package/dist/src/utils/validation.js +39 -0
  306. package/dist/src/version.js +3 -0
  307. package/dist/src/watcher/index.js +192 -0
  308. package/dist/src/wizard/approval.js +275 -0
  309. package/dist/src/wizard/index.js +13 -0
  310. package/dist/src/wizard/prompts.js +273 -0
  311. package/dist/src/wizard/types.js +4 -0
  312. package/dist/src/wizard/ui.js +453 -0
  313. package/dist/src/wizard/wizard.js +227 -0
  314. package/package.json +31 -23
  315. package/src/__tests__/alias.test.ts +133 -0
  316. package/src/__tests__/app.test.ts +1 -1
  317. package/src/__tests__/audit.test.ts +1 -1
  318. package/src/__tests__/circuit-breaker.test.ts +1 -1
  319. package/src/__tests__/cli-run.test.ts +237 -1
  320. package/src/__tests__/compat-sqlite.test.ts +68 -0
  321. package/src/__tests__/context-manager.test.ts +131 -1
  322. package/src/__tests__/context.test.ts +1 -1
  323. package/src/__tests__/devops-terminal-gaps.test.ts +718 -0
  324. package/src/__tests__/doctor.test.ts +48 -0
  325. package/src/__tests__/enterprise.test.ts +1 -1
  326. package/src/__tests__/export.test.ts +236 -0
  327. package/src/__tests__/gap-11-18-20.test.ts +958 -0
  328. package/src/__tests__/generator.test.ts +1 -1
  329. package/src/__tests__/helm-streaming.test.ts +127 -0
  330. package/src/__tests__/hooks.test.ts +1 -1
  331. package/src/__tests__/incident.test.ts +179 -0
  332. package/src/__tests__/init.test.ts +55 -4
  333. package/src/__tests__/intent-parser.test.ts +1 -1
  334. package/src/__tests__/llm-router.test.ts +1 -1
  335. package/src/__tests__/logs.test.ts +107 -0
  336. package/src/__tests__/loop-errors.test.ts +244 -0
  337. package/src/__tests__/lsp.test.ts +1 -1
  338. package/src/__tests__/modes.test.ts +1 -1
  339. package/src/__tests__/perf-optimizations.test.ts +847 -0
  340. package/src/__tests__/permissions.test.ts +1 -1
  341. package/src/__tests__/pipeline.test.ts +50 -0
  342. package/src/__tests__/polish-phase3.test.ts +340 -0
  343. package/src/__tests__/profile.test.ts +237 -0
  344. package/src/__tests__/rollback.test.ts +83 -0
  345. package/src/__tests__/runbook.test.ts +219 -0
  346. package/src/__tests__/schedule.test.ts +206 -0
  347. package/src/__tests__/serve.test.ts +1 -1
  348. package/src/__tests__/sessions.test.ts +96 -1
  349. package/src/__tests__/sharing.test.ts +53 -1
  350. package/src/__tests__/snapshots.test.ts +1 -1
  351. package/src/__tests__/standalone-migration.test.ts +199 -0
  352. package/src/__tests__/state-db.test.ts +1 -1
  353. package/src/__tests__/status.test.ts +158 -0
  354. package/src/__tests__/stream-with-tools.test.ts +71 -25
  355. package/src/__tests__/subagents.test.ts +1 -1
  356. package/src/__tests__/system-prompt.test.ts +82 -3
  357. package/src/__tests__/terminal-gap-v2.test.ts +395 -0
  358. package/src/__tests__/terminal-parity.test.ts +393 -0
  359. package/src/__tests__/tf-apply.test.ts +187 -0
  360. package/src/__tests__/tool-converter.test.ts +1 -1
  361. package/src/__tests__/tool-schemas.test.ts +209 -4
  362. package/src/__tests__/tools.test.ts +4 -3
  363. package/src/__tests__/version-json.test.ts +184 -0
  364. package/src/__tests__/version.test.ts +1 -1
  365. package/src/__tests__/watch.test.ts +129 -0
  366. package/src/agent/compaction-agent.ts +40 -1
  367. package/src/agent/context-manager.ts +67 -3
  368. package/src/agent/deploy-preview.ts +62 -1
  369. package/src/agent/expand-files.ts +108 -0
  370. package/src/agent/loop.ts +1312 -31
  371. package/src/agent/permissions.ts +51 -4
  372. package/src/agent/system-prompt.ts +573 -19
  373. package/src/app.ts +58 -0
  374. package/src/audit/security-scanner.ts +45 -0
  375. package/src/auth/keychain.ts +82 -0
  376. package/src/auth/oauth.ts +15 -5
  377. package/src/cli/init.ts +378 -5
  378. package/src/cli/run.ts +407 -16
  379. package/src/cli/serve.ts +78 -1
  380. package/src/cli/web.ts +10 -6
  381. package/src/cli.ts +312 -1
  382. package/src/clients/service-discovery.ts +30 -25
  383. package/src/commands/alias.ts +100 -0
  384. package/src/commands/audit/index.ts +121 -2
  385. package/src/commands/auth-cloud.ts +113 -0
  386. package/src/commands/auth-refresh.ts +187 -0
  387. package/src/commands/aws-discover.ts +144 -251
  388. package/src/commands/aws-terraform.ts +68 -118
  389. package/src/commands/chat.ts +9 -3
  390. package/src/commands/completions.ts +268 -0
  391. package/src/commands/config.ts +26 -0
  392. package/src/commands/cost/index.ts +218 -2
  393. package/src/commands/deploy.ts +260 -0
  394. package/src/commands/doctor.ts +744 -152
  395. package/src/commands/drift/index.ts +371 -23
  396. package/src/commands/export.ts +146 -0
  397. package/src/commands/generate-k8s.ts +9 -61
  398. package/src/commands/generate-terraform.ts +191 -449
  399. package/src/commands/help.ts +212 -36
  400. package/src/commands/history.ts +8 -1
  401. package/src/commands/incident.ts +166 -0
  402. package/src/commands/init.ts +5 -0
  403. package/src/commands/login.ts +86 -1
  404. package/src/commands/logs.ts +167 -0
  405. package/src/commands/onboarding.ts +211 -34
  406. package/src/commands/pipeline.ts +186 -0
  407. package/src/commands/plugin.ts +398 -0
  408. package/src/commands/profile.ts +342 -0
  409. package/src/commands/questionnaire.ts +0 -98
  410. package/src/commands/resume.ts +26 -34
  411. package/src/commands/rollback.ts +315 -0
  412. package/src/commands/rollout.ts +88 -0
  413. package/src/commands/runbook.ts +346 -0
  414. package/src/commands/schedule.ts +236 -0
  415. package/src/commands/status.ts +252 -0
  416. package/src/commands/team-context.ts +220 -0
  417. package/src/commands/template.ts +58 -57
  418. package/src/commands/tf/index.ts +70 -11
  419. package/src/commands/upgrade.ts +57 -0
  420. package/src/commands/version.ts +54 -50
  421. package/src/commands/watch.ts +153 -0
  422. package/src/compat/runtime.ts +1 -1
  423. package/src/compat/sqlite.ts +75 -5
  424. package/src/config/mode-store.ts +62 -0
  425. package/src/config/profiles.ts +84 -0
  426. package/src/config/types.ts +83 -1
  427. package/src/config/workspace-state.ts +53 -0
  428. package/src/engine/cost-estimator.ts +52 -10
  429. package/src/engine/executor.ts +33 -2
  430. package/src/engine/planner.ts +68 -1
  431. package/src/generator/terraform.ts +8 -0
  432. package/src/history/manager.ts +2 -74
  433. package/src/hooks/engine.ts +5 -4
  434. package/src/llm/cost-calculator.ts +2 -2
  435. package/src/llm/providers/anthropic.ts +50 -21
  436. package/src/llm/router.ts +76 -7
  437. package/src/lsp/languages.ts +3 -0
  438. package/src/lsp/manager.ts +21 -5
  439. package/src/nimbus.ts +37 -18
  440. package/src/sessions/manager.ts +108 -1
  441. package/src/sharing/sync.ts +4 -0
  442. package/src/sharing/viewer.ts +66 -0
  443. package/src/tools/file-ops.ts +22 -0
  444. package/src/tools/schemas/devops.ts +3007 -117
  445. package/src/tools/schemas/standard.ts +5 -1
  446. package/src/tools/schemas/types.ts +31 -1
  447. package/src/tools/spawn-exec.ts +148 -0
  448. package/src/ui/App.tsx +1183 -66
  449. package/src/ui/DeployPreview.tsx +62 -57
  450. package/src/ui/FileDiffModal.tsx +162 -0
  451. package/src/ui/Header.tsx +87 -24
  452. package/src/ui/HelpModal.tsx +57 -0
  453. package/src/ui/InputBox.tsx +163 -10
  454. package/src/ui/MessageList.tsx +487 -40
  455. package/src/ui/PermissionPrompt.tsx +17 -5
  456. package/src/ui/StatusBar.tsx +122 -3
  457. package/src/ui/TerminalPane.tsx +84 -0
  458. package/src/ui/ToolCallDisplay.tsx +252 -18
  459. package/src/ui/TreePane.tsx +132 -0
  460. package/src/ui/chat-ui.ts +41 -44
  461. package/src/ui/ink/index.ts +771 -38
  462. package/src/ui/streaming.ts +1 -1
  463. package/src/ui/theme.ts +104 -0
  464. package/src/ui/types.ts +18 -0
  465. package/src/version.ts +1 -1
  466. package/src/watcher/index.ts +66 -15
  467. package/src/wizard/types.ts +1 -0
  468. package/src/wizard/ui.ts +1 -1
  469. package/tsconfig.json +2 -2
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Audit log helpers.
3
+ *
4
+ * Refactored from SQLiteAdapter.logAuditEvent and getAuditLogs.
5
+ */
6
+ import { getDb } from './db';
7
+ // ---------------------------------------------------------------------------
8
+ // Public API
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Persist an audit event.
12
+ */
13
+ export function logAuditEvent(event, db) {
14
+ const d = db || getDb();
15
+ const stmt = d.prepare(`
16
+ INSERT INTO audit_logs (id, timestamp, user_id, action, resource_type, resource_id, input, output, status, duration_ms, metadata)
17
+ VALUES (?, CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?, ?, ?, ?)
18
+ `);
19
+ stmt.run(event.id, event.userId || null, event.action, event.resourceType || null, event.resourceId || null, event.input ? JSON.stringify(event.input) : null, event.output ? JSON.stringify(event.output) : null, event.status, event.durationMs || null, event.metadata ? JSON.stringify(event.metadata) : null);
20
+ }
21
+ /**
22
+ * Query audit logs with optional filters.
23
+ */
24
+ export function getAuditLogs(filter, db) {
25
+ const d = db || getDb();
26
+ let query = 'SELECT * FROM audit_logs';
27
+ const params = [];
28
+ const conditions = [];
29
+ if (filter?.userId) {
30
+ conditions.push('user_id = ?');
31
+ params.push(filter.userId);
32
+ }
33
+ if (filter?.action) {
34
+ conditions.push('action = ?');
35
+ params.push(filter.action);
36
+ }
37
+ if (filter?.resourceType) {
38
+ conditions.push('resource_type = ?');
39
+ params.push(filter.resourceType);
40
+ }
41
+ if (filter?.status) {
42
+ conditions.push('status = ?');
43
+ params.push(filter.status);
44
+ }
45
+ if (filter?.startDate) {
46
+ conditions.push('timestamp >= ?');
47
+ params.push(filter.startDate.toISOString());
48
+ }
49
+ if (filter?.endDate) {
50
+ conditions.push('timestamp <= ?');
51
+ params.push(filter.endDate.toISOString());
52
+ }
53
+ if (conditions.length > 0) {
54
+ query += ` WHERE ${conditions.join(' AND ')}`;
55
+ }
56
+ query += ' ORDER BY timestamp DESC LIMIT ? OFFSET ?';
57
+ params.push(filter?.limit || 100, filter?.offset || 0);
58
+ const stmt = d.prepare(query);
59
+ const rows = stmt.all(...params);
60
+ return rows.map(row => ({
61
+ id: row.id,
62
+ timestamp: row.timestamp,
63
+ userId: row.user_id,
64
+ action: row.action,
65
+ resourceType: row.resource_type,
66
+ resourceId: row.resource_id,
67
+ input: row.input ? JSON.parse(row.input) : null,
68
+ output: row.output ? JSON.parse(row.output) : null,
69
+ status: row.status,
70
+ durationMs: row.duration_ms,
71
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
72
+ }));
73
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Billing / usage tracking helpers.
3
+ *
4
+ * Refactored from the billing-service database adapter
5
+ * (services/billing-service/src/db/adapter.ts) into standalone functions
6
+ * that operate against the unified Nimbus database.
7
+ */
8
+ import { getDb } from './db';
9
+ // ---------------------------------------------------------------------------
10
+ // Subscription helpers
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Create a new subscription.
14
+ */
15
+ export function createSubscription(id, teamId, plan = 'free', status = 'active', currentPeriodStart, currentPeriodEnd, db) {
16
+ const d = db || getDb();
17
+ const stmt = d.prepare(`
18
+ INSERT INTO subscriptions (id, team_id, plan, status, current_period_start, current_period_end, created_at, updated_at)
19
+ VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
20
+ `);
21
+ stmt.run(id, teamId, plan, status, currentPeriodStart || null, currentPeriodEnd || null);
22
+ }
23
+ /**
24
+ * Retrieve a subscription by team id.
25
+ */
26
+ export function getSubscription(teamId, db) {
27
+ const d = db || getDb();
28
+ const stmt = d.prepare('SELECT * FROM subscriptions WHERE team_id = ?');
29
+ const row = stmt.get(teamId);
30
+ if (!row) {
31
+ return null;
32
+ }
33
+ return {
34
+ id: row.id,
35
+ teamId: row.team_id,
36
+ plan: row.plan,
37
+ status: row.status,
38
+ currentPeriodStart: row.current_period_start,
39
+ currentPeriodEnd: row.current_period_end,
40
+ createdAt: row.created_at,
41
+ updatedAt: row.updated_at,
42
+ };
43
+ }
44
+ /**
45
+ * Update plan, status, or period boundaries of an existing subscription.
46
+ */
47
+ export function updateSubscription(teamId, updates, db) {
48
+ const d = db || getDb();
49
+ const stmt = d.prepare(`
50
+ UPDATE subscriptions
51
+ SET plan = COALESCE(?, plan),
52
+ status = COALESCE(?, status),
53
+ current_period_start = COALESCE(?, current_period_start),
54
+ current_period_end = COALESCE(?, current_period_end),
55
+ updated_at = CURRENT_TIMESTAMP
56
+ WHERE team_id = ?
57
+ `);
58
+ stmt.run(updates.plan || null, updates.status || null, updates.currentPeriodStart || null, updates.currentPeriodEnd || null, teamId);
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Usage helpers
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Record a single usage event.
65
+ */
66
+ export function recordUsage(id, type, quantity, unit = 'tokens', costUsd, teamId, userId, metadata, db) {
67
+ const d = db || getDb();
68
+ const stmt = d.prepare(`
69
+ INSERT INTO usage (id, team_id, user_id, type, quantity, unit, cost_usd, metadata, created_at)
70
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
71
+ `);
72
+ stmt.run(id, teamId || null, userId || null, type, quantity, unit, costUsd ?? 0, metadata ? JSON.stringify(metadata) : null);
73
+ }
74
+ /**
75
+ * Retrieve usage records for a team within a date range.
76
+ */
77
+ export function getUsage(teamId, since, until, limit = 100, offset = 0, db) {
78
+ const d = db || getDb();
79
+ const untilDate = until || new Date();
80
+ const stmt = d.prepare(`
81
+ SELECT * FROM usage
82
+ WHERE team_id = ?
83
+ AND created_at >= ?
84
+ AND created_at <= ?
85
+ ORDER BY created_at DESC
86
+ LIMIT ? OFFSET ?
87
+ `);
88
+ const rows = stmt.all(teamId, since.toISOString(), untilDate.toISOString(), limit, offset);
89
+ return rows.map(row => ({
90
+ id: row.id,
91
+ teamId: row.team_id,
92
+ userId: row.user_id,
93
+ type: row.type,
94
+ quantity: row.quantity,
95
+ unit: row.unit,
96
+ costUsd: row.cost_usd,
97
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
98
+ createdAt: row.created_at,
99
+ }));
100
+ }
101
+ /**
102
+ * Aggregate usage by type for a team within a date range.
103
+ */
104
+ export function getUsageSummary(teamId, since, until, db) {
105
+ const d = db || getDb();
106
+ const untilDate = until || new Date();
107
+ const stmt = d.prepare(`
108
+ SELECT
109
+ type,
110
+ SUM(quantity) as total_quantity,
111
+ SUM(cost_usd) as total_cost,
112
+ COUNT(*) as count
113
+ FROM usage
114
+ WHERE team_id = ?
115
+ AND created_at >= ?
116
+ AND created_at <= ?
117
+ GROUP BY type
118
+ `);
119
+ const rows = stmt.all(teamId, since.toISOString(), untilDate.toISOString());
120
+ return rows.map(row => ({
121
+ type: row.type,
122
+ totalQuantity: row.total_quantity,
123
+ totalCost: row.total_cost,
124
+ count: row.count,
125
+ }));
126
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Checkpoint save / restore helpers for resumable operations.
3
+ *
4
+ * Refactored from SQLiteAdapter.saveCheckpoint, getCheckpoint,
5
+ * getLatestCheckpoint, listCheckpoints, and deleteCheckpoints.
6
+ */
7
+ import { getDb } from './db';
8
+ // ---------------------------------------------------------------------------
9
+ // Public API
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Persist or overwrite a checkpoint for a given operation and step.
13
+ */
14
+ export function saveCheckpoint(id, operationId, step, state, db) {
15
+ const d = db || getDb();
16
+ const stmt = d.prepare(`
17
+ INSERT OR REPLACE INTO checkpoints (id, operation_id, step, state, created_at)
18
+ VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
19
+ `);
20
+ stmt.run(id, operationId, step, JSON.stringify(state));
21
+ }
22
+ /**
23
+ * Retrieve a single checkpoint by its id.
24
+ */
25
+ export function getCheckpoint(id, db) {
26
+ const d = db || getDb();
27
+ const stmt = d.prepare('SELECT * FROM checkpoints WHERE id = ?');
28
+ const row = stmt.get(id);
29
+ if (!row) {
30
+ return null;
31
+ }
32
+ return {
33
+ id: row.id,
34
+ operationId: row.operation_id,
35
+ step: row.step,
36
+ state: JSON.parse(row.state),
37
+ createdAt: row.created_at,
38
+ };
39
+ }
40
+ /**
41
+ * Retrieve the most recent checkpoint (highest step) for an operation.
42
+ */
43
+ export function getLatestCheckpoint(operationId, db) {
44
+ const d = db || getDb();
45
+ const stmt = d.prepare(`
46
+ SELECT * FROM checkpoints WHERE operation_id = ? ORDER BY step DESC LIMIT 1
47
+ `);
48
+ const row = stmt.get(operationId);
49
+ if (!row) {
50
+ return null;
51
+ }
52
+ return {
53
+ id: row.id,
54
+ operationId: row.operation_id,
55
+ step: row.step,
56
+ state: JSON.parse(row.state),
57
+ createdAt: row.created_at,
58
+ };
59
+ }
60
+ /**
61
+ * List all checkpoints for an operation ordered by step ascending.
62
+ */
63
+ export function listCheckpoints(operationId, db) {
64
+ const d = db || getDb();
65
+ const stmt = d.prepare(`
66
+ SELECT id, step, created_at FROM checkpoints WHERE operation_id = ? ORDER BY step ASC
67
+ `);
68
+ return stmt.all(operationId).map(row => ({
69
+ id: row.id,
70
+ step: row.step,
71
+ createdAt: row.created_at,
72
+ }));
73
+ }
74
+ /**
75
+ * Delete all checkpoints associated with an operation.
76
+ */
77
+ export function deleteCheckpoints(operationId, db) {
78
+ const d = db || getDb();
79
+ const stmt = d.prepare('DELETE FROM checkpoints WHERE operation_id = ?');
80
+ stmt.run(operationId);
81
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Config key-value store helpers.
3
+ *
4
+ * Refactored from SQLiteAdapter.setConfig, getConfig, and getAllConfig.
5
+ */
6
+ import { getDb } from './db';
7
+ // ---------------------------------------------------------------------------
8
+ // Public API
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Set (insert or replace) a configuration value.
12
+ * The value is JSON-serialised before storage.
13
+ */
14
+ export function setConfig(key, value, db) {
15
+ const d = db || getDb();
16
+ const stmt = d.prepare(`
17
+ INSERT OR REPLACE INTO config (key, value, updated_at)
18
+ VALUES (?, ?, CURRENT_TIMESTAMP)
19
+ `);
20
+ stmt.run(key, JSON.stringify(value));
21
+ }
22
+ /**
23
+ * Retrieve a single configuration value by key.
24
+ * Returns `null` when the key does not exist.
25
+ */
26
+ export function getConfig(key, db) {
27
+ const d = db || getDb();
28
+ const stmt = d.prepare('SELECT value FROM config WHERE key = ?');
29
+ const row = stmt.get(key);
30
+ if (!row) {
31
+ return null;
32
+ }
33
+ try {
34
+ return JSON.parse(row.value);
35
+ }
36
+ catch {
37
+ // Corrupted config value — treat as missing
38
+ return null;
39
+ }
40
+ }
41
+ /**
42
+ * Retrieve every configuration entry as a flat key-value object.
43
+ */
44
+ export function getAllConfig(db) {
45
+ const d = db || getDb();
46
+ const stmt = d.prepare('SELECT key, value FROM config');
47
+ const rows = stmt.all();
48
+ const config = {};
49
+ for (const row of rows) {
50
+ try {
51
+ config[row.key] = JSON.parse(row.value);
52
+ }
53
+ catch {
54
+ // Skip corrupted config entries
55
+ }
56
+ }
57
+ return config;
58
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Re-export conversation helpers from messages.ts for clarity.
3
+ *
4
+ * Consumers can import from either `./messages` or `./conversations`
5
+ * depending on which name reads better at the call-site.
6
+ */
7
+ export { saveConversation, getConversation, listConversations, deleteConversation, } from './messages';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Auth token and device-code management helpers.
3
+ *
4
+ * Refactored from the auth-service database adapter
5
+ * (services/auth-service/src/db/adapter.ts) into standalone functions
6
+ * that operate against the unified Nimbus database.
7
+ */
8
+ import { getDb } from './db';
9
+ // ---------------------------------------------------------------------------
10
+ // Device Code helpers
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Persist a new device code for the OAuth device-authorization flow.
14
+ */
15
+ export function saveDeviceCode(deviceCode, userCode, expiresAt, clientId, scope, db) {
16
+ const d = db || getDb();
17
+ const stmt = d.prepare(`
18
+ INSERT INTO device_codes (device_code, user_code, client_id, scope, status, expires_at)
19
+ VALUES (?, ?, ?, ?, 'pending', ?)
20
+ `);
21
+ stmt.run(deviceCode, userCode, clientId || null, scope || null, expiresAt.toISOString());
22
+ }
23
+ /**
24
+ * Retrieve a device code record by its device_code value.
25
+ */
26
+ export function getDeviceCode(deviceCode, db) {
27
+ const d = db || getDb();
28
+ const stmt = d.prepare('SELECT * FROM device_codes WHERE device_code = ?');
29
+ const row = stmt.get(deviceCode);
30
+ if (!row) {
31
+ return null;
32
+ }
33
+ return {
34
+ deviceCode: row.device_code,
35
+ userCode: row.user_code,
36
+ clientId: row.client_id,
37
+ scope: row.scope,
38
+ status: row.status,
39
+ token: row.token,
40
+ expiresAt: row.expires_at,
41
+ createdAt: row.created_at,
42
+ };
43
+ }
44
+ /**
45
+ * Update the status (and optionally the associated token) of a device code.
46
+ */
47
+ export function updateDeviceCodeStatus(deviceCode, status, token, db) {
48
+ const d = db || getDb();
49
+ const stmt = d.prepare(`
50
+ UPDATE device_codes
51
+ SET status = ?, token = COALESCE(?, token)
52
+ WHERE device_code = ?
53
+ `);
54
+ stmt.run(status, token || null, deviceCode);
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Token helpers
58
+ // ---------------------------------------------------------------------------
59
+ /**
60
+ * Persist an authentication token.
61
+ */
62
+ export function saveToken(id, token, type = 'access', userId, expiresAt, db) {
63
+ const d = db || getDb();
64
+ const stmt = d.prepare(`
65
+ INSERT INTO tokens (id, user_id, token, type, expires_at)
66
+ VALUES (?, ?, ?, ?, ?)
67
+ `);
68
+ stmt.run(id, userId || null, token, type, expiresAt ? expiresAt.toISOString() : null);
69
+ }
70
+ /**
71
+ * Retrieve a token record by its token string value.
72
+ */
73
+ export function getToken(token, db) {
74
+ const d = db || getDb();
75
+ const stmt = d.prepare('SELECT * FROM tokens WHERE token = ?');
76
+ const row = stmt.get(token);
77
+ if (!row) {
78
+ return null;
79
+ }
80
+ return {
81
+ id: row.id,
82
+ userId: row.user_id,
83
+ token: row.token,
84
+ type: row.type,
85
+ expiresAt: row.expires_at,
86
+ createdAt: row.created_at,
87
+ };
88
+ }
89
+ /**
90
+ * Delete a token by its token string value.
91
+ */
92
+ export function deleteToken(token, db) {
93
+ const d = db || getDb();
94
+ const stmt = d.prepare('DELETE FROM tokens WHERE token = ?');
95
+ stmt.run(token);
96
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Database singleton for the Nimbus unified SQLite persistence layer.
3
+ *
4
+ * Provides a lazily-initialized, WAL-mode SQLite database stored at
5
+ * ~/.nimbus/nimbus.db (overridable via NIMBUS_DB_PATH). An in-memory
6
+ * variant is available for tests.
7
+ */
8
+ import { Database } from '../compat/sqlite';
9
+ import * as path from 'path';
10
+ import * as os from 'os';
11
+ import * as fs from 'fs';
12
+ import { runMigrations } from './schema';
13
+ let db = null;
14
+ /**
15
+ * Return the shared Database instance, creating it on first call.
16
+ * The database file lives at `~/.nimbus/nimbus.db` unless the
17
+ * `NIMBUS_DB_PATH` environment variable points elsewhere.
18
+ */
19
+ export function getDb() {
20
+ if (!db) {
21
+ const nimbusDir = path.join(os.homedir(), '.nimbus');
22
+ if (!fs.existsSync(nimbusDir)) {
23
+ fs.mkdirSync(nimbusDir, { recursive: true });
24
+ }
25
+ const dbPath = process.env.NIMBUS_DB_PATH || path.join(nimbusDir, 'nimbus.db');
26
+ db = new Database(dbPath);
27
+ db.exec('PRAGMA journal_mode=WAL');
28
+ db.exec('PRAGMA foreign_keys=ON');
29
+ runMigrations(db);
30
+ }
31
+ return db;
32
+ }
33
+ /**
34
+ * Create a throwaway in-memory database for unit / integration tests.
35
+ * Each call returns a fresh, fully-migrated instance.
36
+ */
37
+ export function getTestDb() {
38
+ const testDb = new Database(':memory:');
39
+ testDb.exec('PRAGMA journal_mode=WAL');
40
+ testDb.exec('PRAGMA foreign_keys=ON');
41
+ runMigrations(testDb);
42
+ return testDb;
43
+ }
44
+ /**
45
+ * Close the shared database connection and clear the singleton so that
46
+ * a subsequent `getDb()` call will re-open it.
47
+ */
48
+ export function closeDb() {
49
+ if (db) {
50
+ db.close();
51
+ db = null;
52
+ }
53
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Nimbus unified SQLite persistence layer.
3
+ *
4
+ * Re-exports every public symbol from the individual domain modules so that
5
+ * consumers can do:
6
+ *
7
+ * import { getDb, saveOperation, setConfig, ... } from '../state';
8
+ */
9
+ // Database lifecycle
10
+ export { getDb, getTestDb, closeDb } from './db';
11
+ // Schema / migrations
12
+ export { runMigrations } from './schema';
13
+ // Domain modules
14
+ export * from './sessions';
15
+ export * from './messages';
16
+ export * from './config';
17
+ export * from './artifacts';
18
+ export * from './audit';
19
+ export * from './credentials';
20
+ export * from './teams';
21
+ export * from './billing';
22
+ export * from './checkpoints';
23
+ export * from './projects';
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Message / conversation CRUD helpers.
3
+ *
4
+ * Refactored from SQLiteAdapter.saveConversation, getConversation,
5
+ * listConversations, and deleteConversation.
6
+ */
7
+ import { getDb } from './db';
8
+ // ---------------------------------------------------------------------------
9
+ // Public API
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Persist or update a conversation. Uses INSERT ... ON CONFLICT to upsert.
13
+ */
14
+ export function saveConversation(id, title, messages, model, metadata, db) {
15
+ const d = db || getDb();
16
+ const stmt = d.prepare(`
17
+ INSERT INTO conversations (id, title, messages, model, created_at, updated_at, metadata)
18
+ VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, ?)
19
+ ON CONFLICT(id) DO UPDATE SET
20
+ title = excluded.title,
21
+ messages = excluded.messages,
22
+ model = excluded.model,
23
+ updated_at = CURRENT_TIMESTAMP,
24
+ metadata = excluded.metadata
25
+ `);
26
+ stmt.run(id, title, JSON.stringify(messages), model || null, metadata ? JSON.stringify(metadata) : null);
27
+ }
28
+ /**
29
+ * Retrieve a single conversation by id.
30
+ */
31
+ export function getConversation(id, db) {
32
+ const d = db || getDb();
33
+ const stmt = d.prepare('SELECT * FROM conversations WHERE id = ?');
34
+ const row = stmt.get(id);
35
+ if (!row) {
36
+ return null;
37
+ }
38
+ return {
39
+ id: row.id,
40
+ title: row.title,
41
+ messages: JSON.parse(row.messages),
42
+ model: row.model,
43
+ createdAt: row.created_at,
44
+ updatedAt: row.updated_at,
45
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
46
+ };
47
+ }
48
+ /**
49
+ * List conversations ordered by most-recently updated first.
50
+ */
51
+ export function listConversations(limit = 50, offset = 0, db) {
52
+ const d = db || getDb();
53
+ const stmt = d.prepare(`
54
+ SELECT * FROM conversations
55
+ ORDER BY updated_at DESC
56
+ LIMIT ? OFFSET ?
57
+ `);
58
+ const rows = stmt.all(limit, offset);
59
+ return rows.map(row => ({
60
+ id: row.id,
61
+ title: row.title,
62
+ messages: JSON.parse(row.messages),
63
+ model: row.model,
64
+ createdAt: row.created_at,
65
+ updatedAt: row.updated_at,
66
+ metadata: row.metadata ? JSON.parse(row.metadata) : null,
67
+ }));
68
+ }
69
+ /**
70
+ * Delete a conversation by id.
71
+ */
72
+ export function deleteConversation(id, db) {
73
+ const d = db || getDb();
74
+ const stmt = d.prepare('DELETE FROM conversations WHERE id = ?');
75
+ stmt.run(id);
76
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Project CRUD helpers.
3
+ *
4
+ * Refactored from SQLiteAdapter.saveProject, getProject, getProjectByPath,
5
+ * listProjects, and deleteProject.
6
+ */
7
+ import { getDb } from './db';
8
+ // ---------------------------------------------------------------------------
9
+ // Public API
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Persist or update a project. Uses INSERT ... ON CONFLICT to upsert.
13
+ */
14
+ export function saveProject(id, name, projectPath, config, db) {
15
+ const d = db || getDb();
16
+ const stmt = d.prepare(`
17
+ INSERT INTO projects (id, name, path, config, last_scanned, created_at, updated_at)
18
+ VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
19
+ ON CONFLICT(id) DO UPDATE SET
20
+ name = excluded.name,
21
+ path = excluded.path,
22
+ config = excluded.config,
23
+ last_scanned = CURRENT_TIMESTAMP,
24
+ updated_at = CURRENT_TIMESTAMP
25
+ `);
26
+ stmt.run(id, name, projectPath, JSON.stringify(config));
27
+ }
28
+ /**
29
+ * Retrieve a project by id.
30
+ */
31
+ export function getProject(id, db) {
32
+ const d = db || getDb();
33
+ const stmt = d.prepare('SELECT * FROM projects WHERE id = ?');
34
+ const row = stmt.get(id);
35
+ if (!row) {
36
+ return null;
37
+ }
38
+ return {
39
+ id: row.id,
40
+ name: row.name,
41
+ path: row.path,
42
+ config: JSON.parse(row.config),
43
+ lastScanned: row.last_scanned,
44
+ createdAt: row.created_at,
45
+ updatedAt: row.updated_at,
46
+ };
47
+ }
48
+ /**
49
+ * Retrieve a project by its filesystem path.
50
+ */
51
+ export function getProjectByPath(projectPath, db) {
52
+ const d = db || getDb();
53
+ const stmt = d.prepare('SELECT * FROM projects WHERE path = ?');
54
+ const row = stmt.get(projectPath);
55
+ if (!row) {
56
+ return null;
57
+ }
58
+ return {
59
+ id: row.id,
60
+ name: row.name,
61
+ path: row.path,
62
+ config: JSON.parse(row.config),
63
+ lastScanned: row.last_scanned,
64
+ createdAt: row.created_at,
65
+ updatedAt: row.updated_at,
66
+ };
67
+ }
68
+ /**
69
+ * List all projects ordered by most-recently updated first.
70
+ */
71
+ export function listProjects(db) {
72
+ const d = db || getDb();
73
+ const stmt = d.prepare('SELECT * FROM projects ORDER BY updated_at DESC');
74
+ const rows = stmt.all();
75
+ return rows.map(row => ({
76
+ id: row.id,
77
+ name: row.name,
78
+ path: row.path,
79
+ config: JSON.parse(row.config),
80
+ lastScanned: row.last_scanned,
81
+ createdAt: row.created_at,
82
+ updatedAt: row.updated_at,
83
+ }));
84
+ }
85
+ /**
86
+ * Delete a project by id.
87
+ */
88
+ export function deleteProject(id, db) {
89
+ const d = db || getDb();
90
+ const stmt = d.prepare('DELETE FROM projects WHERE id = ?');
91
+ stmt.run(id);
92
+ }