@build-astron-co/nimbus 0.4.2 → 0.4.3

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 (430) hide show
  1. package/dist/src/agent/compaction-agent.js +24 -12
  2. package/dist/src/agent/context-manager.js +2 -1
  3. package/dist/src/agent/expand-files.js +2 -1
  4. package/dist/src/agent/loop.js +71 -33
  5. package/dist/src/agent/permissions.js +4 -2
  6. package/dist/src/agent/system-prompt.js +34 -17
  7. package/dist/src/app.js +1 -1
  8. package/dist/src/auth/keychain.js +8 -4
  9. package/dist/src/auth/store.js +70 -107
  10. package/dist/src/cli/init.js +35 -19
  11. package/dist/src/cli/run.js +18 -10
  12. package/dist/src/cli/serve.js +4 -2
  13. package/dist/src/cli.js +52 -11
  14. package/dist/src/commands/alias.js +5 -3
  15. package/dist/src/commands/audit/index.js +2 -1
  16. package/dist/src/commands/aws-terraform.js +36 -18
  17. package/dist/src/commands/completions.js +1 -1
  18. package/dist/src/commands/config.js +3 -2
  19. package/dist/src/commands/connect-github.js +92 -0
  20. package/dist/src/commands/cost/index.js +3 -2
  21. package/dist/src/commands/deploy.js +15 -10
  22. package/dist/src/commands/doctor.js +6 -3
  23. package/dist/src/commands/drift/index.js +2 -1
  24. package/dist/src/commands/export.js +5 -3
  25. package/dist/src/commands/generate-terraform.js +110 -2
  26. package/dist/src/commands/import.js +3 -3
  27. package/dist/src/commands/incident.js +10 -5
  28. package/dist/src/commands/login.js +8 -93
  29. package/dist/src/commands/logs.js +16 -8
  30. package/dist/src/commands/onboarding.js +6 -4
  31. package/dist/src/commands/pipeline.js +6 -3
  32. package/dist/src/commands/plugin.js +3 -2
  33. package/dist/src/commands/profile.js +27 -14
  34. package/dist/src/commands/questionnaire.js +1 -1
  35. package/dist/src/commands/rollback.js +3 -2
  36. package/dist/src/commands/rollout.js +5 -3
  37. package/dist/src/commands/runbook.js +17 -10
  38. package/dist/src/commands/schedule.js +10 -5
  39. package/dist/src/commands/status.js +2 -1
  40. package/dist/src/commands/team-context.js +12 -7
  41. package/dist/src/commands/template.js +1 -1
  42. package/dist/src/commands/tf/index.js +6 -3
  43. package/dist/src/commands/version.js +6 -3
  44. package/dist/src/commands/watch.js +6 -3
  45. package/dist/src/compat/sqlite.js +5 -3
  46. package/dist/src/config/mode-store.js +2 -1
  47. package/dist/src/config/profiles.js +4 -2
  48. package/dist/src/config/types.js +2 -1
  49. package/dist/src/engine/executor.js +8 -4
  50. package/dist/src/engine/planner.js +9 -5
  51. package/dist/src/llm/providers/anthropic.js +6 -3
  52. package/dist/src/llm/providers/ollama.js +1 -1
  53. package/dist/src/llm/router.js +22 -7
  54. package/dist/src/sessions/manager.js +6 -3
  55. package/dist/src/sharing/viewer.js +2 -1
  56. package/dist/src/tools/file-ops.js +1 -2
  57. package/dist/src/tools/schemas/devops.js +197 -108
  58. package/dist/src/tools/schemas/standard.js +1 -1
  59. package/dist/src/ui/App.js +25 -13
  60. package/dist/src/ui/FileDiffModal.js +22 -11
  61. package/dist/src/ui/HelpModal.js +2 -1
  62. package/dist/src/ui/InputBox.js +6 -3
  63. package/dist/src/ui/MessageList.js +40 -20
  64. package/dist/src/ui/TerminalPane.js +2 -1
  65. package/dist/src/ui/ToolCallDisplay.js +12 -6
  66. package/dist/src/ui/TreePane.js +2 -1
  67. package/dist/src/ui/ink/index.js +37 -21
  68. package/dist/src/watcher/index.js +8 -4
  69. package/package.json +3 -5
  70. package/src/__tests__/alias.test.ts +0 -133
  71. package/src/__tests__/app.test.ts +0 -76
  72. package/src/__tests__/audit.test.ts +0 -877
  73. package/src/__tests__/circuit-breaker.test.ts +0 -116
  74. package/src/__tests__/cli-run.test.ts +0 -351
  75. package/src/__tests__/compat-sqlite.test.ts +0 -68
  76. package/src/__tests__/context-manager.test.ts +0 -632
  77. package/src/__tests__/context.test.ts +0 -242
  78. package/src/__tests__/devops-terminal-gaps.test.ts +0 -718
  79. package/src/__tests__/doctor.test.ts +0 -48
  80. package/src/__tests__/enterprise.test.ts +0 -401
  81. package/src/__tests__/export.test.ts +0 -236
  82. package/src/__tests__/gap-11-18-20.test.ts +0 -958
  83. package/src/__tests__/generator.test.ts +0 -433
  84. package/src/__tests__/helm-streaming.test.ts +0 -127
  85. package/src/__tests__/hooks.test.ts +0 -582
  86. package/src/__tests__/incident.test.ts +0 -179
  87. package/src/__tests__/init.test.ts +0 -487
  88. package/src/__tests__/intent-parser.test.ts +0 -229
  89. package/src/__tests__/llm-router.test.ts +0 -209
  90. package/src/__tests__/logs.test.ts +0 -107
  91. package/src/__tests__/loop-errors.test.ts +0 -244
  92. package/src/__tests__/lsp.test.ts +0 -293
  93. package/src/__tests__/modes.test.ts +0 -336
  94. package/src/__tests__/perf-optimizations.test.ts +0 -847
  95. package/src/__tests__/permissions.test.ts +0 -338
  96. package/src/__tests__/pipeline.test.ts +0 -50
  97. package/src/__tests__/polish-phase3.test.ts +0 -340
  98. package/src/__tests__/profile.test.ts +0 -237
  99. package/src/__tests__/rollback.test.ts +0 -83
  100. package/src/__tests__/runbook.test.ts +0 -219
  101. package/src/__tests__/schedule.test.ts +0 -206
  102. package/src/__tests__/serve.test.ts +0 -275
  103. package/src/__tests__/sessions.test.ts +0 -322
  104. package/src/__tests__/sharing.test.ts +0 -340
  105. package/src/__tests__/snapshots.test.ts +0 -581
  106. package/src/__tests__/standalone-migration.test.ts +0 -199
  107. package/src/__tests__/state-db.test.ts +0 -334
  108. package/src/__tests__/status.test.ts +0 -158
  109. package/src/__tests__/stream-with-tools.test.ts +0 -778
  110. package/src/__tests__/subagents.test.ts +0 -176
  111. package/src/__tests__/system-prompt.test.ts +0 -248
  112. package/src/__tests__/terminal-gap-v2.test.ts +0 -395
  113. package/src/__tests__/terminal-parity.test.ts +0 -393
  114. package/src/__tests__/tf-apply.test.ts +0 -187
  115. package/src/__tests__/tool-converter.test.ts +0 -256
  116. package/src/__tests__/tool-schemas.test.ts +0 -602
  117. package/src/__tests__/tools.test.ts +0 -144
  118. package/src/__tests__/version-json.test.ts +0 -184
  119. package/src/__tests__/version.test.ts +0 -49
  120. package/src/__tests__/watch.test.ts +0 -129
  121. package/src/agent/compaction-agent.ts +0 -266
  122. package/src/agent/context-manager.ts +0 -499
  123. package/src/agent/context.ts +0 -427
  124. package/src/agent/deploy-preview.ts +0 -487
  125. package/src/agent/expand-files.ts +0 -108
  126. package/src/agent/index.ts +0 -68
  127. package/src/agent/loop.ts +0 -1998
  128. package/src/agent/modes.ts +0 -429
  129. package/src/agent/permissions.ts +0 -513
  130. package/src/agent/subagents/base.ts +0 -116
  131. package/src/agent/subagents/cost.ts +0 -51
  132. package/src/agent/subagents/explore.ts +0 -42
  133. package/src/agent/subagents/general.ts +0 -54
  134. package/src/agent/subagents/index.ts +0 -102
  135. package/src/agent/subagents/infra.ts +0 -59
  136. package/src/agent/subagents/security.ts +0 -69
  137. package/src/agent/system-prompt.ts +0 -990
  138. package/src/app.ts +0 -180
  139. package/src/audit/activity-log.ts +0 -290
  140. package/src/audit/compliance-checker.ts +0 -540
  141. package/src/audit/cost-tracker.ts +0 -318
  142. package/src/audit/index.ts +0 -23
  143. package/src/audit/security-scanner.ts +0 -641
  144. package/src/auth/guard.ts +0 -75
  145. package/src/auth/index.ts +0 -56
  146. package/src/auth/keychain.ts +0 -82
  147. package/src/auth/oauth.ts +0 -465
  148. package/src/auth/providers.ts +0 -470
  149. package/src/auth/sso.ts +0 -113
  150. package/src/auth/store.ts +0 -505
  151. package/src/auth/types.ts +0 -187
  152. package/src/build.ts +0 -141
  153. package/src/cli/index.ts +0 -16
  154. package/src/cli/init.ts +0 -1227
  155. package/src/cli/openapi-spec.ts +0 -356
  156. package/src/cli/run.ts +0 -628
  157. package/src/cli/serve-auth.ts +0 -80
  158. package/src/cli/serve.ts +0 -539
  159. package/src/cli/web.ts +0 -71
  160. package/src/cli.ts +0 -1728
  161. package/src/clients/core-engine-client.ts +0 -227
  162. package/src/clients/enterprise-client.ts +0 -334
  163. package/src/clients/generator-client.ts +0 -351
  164. package/src/clients/git-client.ts +0 -627
  165. package/src/clients/github-client.ts +0 -410
  166. package/src/clients/helm-client.ts +0 -504
  167. package/src/clients/index.ts +0 -80
  168. package/src/clients/k8s-client.ts +0 -497
  169. package/src/clients/llm-client.ts +0 -161
  170. package/src/clients/rest-client.ts +0 -130
  171. package/src/clients/service-discovery.ts +0 -38
  172. package/src/clients/terraform-client.ts +0 -482
  173. package/src/clients/tools-client.ts +0 -1843
  174. package/src/clients/ws-client.ts +0 -115
  175. package/src/commands/alias.ts +0 -100
  176. package/src/commands/analyze/index.ts +0 -352
  177. package/src/commands/apply/helm.ts +0 -473
  178. package/src/commands/apply/index.ts +0 -213
  179. package/src/commands/apply/k8s.ts +0 -454
  180. package/src/commands/apply/terraform.ts +0 -582
  181. package/src/commands/ask.ts +0 -167
  182. package/src/commands/audit/index.ts +0 -357
  183. package/src/commands/auth-cloud.ts +0 -407
  184. package/src/commands/auth-list.ts +0 -134
  185. package/src/commands/auth-profile.ts +0 -121
  186. package/src/commands/auth-refresh.ts +0 -187
  187. package/src/commands/auth-status.ts +0 -141
  188. package/src/commands/aws/ec2.ts +0 -501
  189. package/src/commands/aws/iam.ts +0 -397
  190. package/src/commands/aws/index.ts +0 -133
  191. package/src/commands/aws/lambda.ts +0 -396
  192. package/src/commands/aws/rds.ts +0 -439
  193. package/src/commands/aws/s3.ts +0 -439
  194. package/src/commands/aws/vpc.ts +0 -393
  195. package/src/commands/aws-discover.ts +0 -542
  196. package/src/commands/aws-terraform.ts +0 -755
  197. package/src/commands/azure/aks.ts +0 -376
  198. package/src/commands/azure/functions.ts +0 -253
  199. package/src/commands/azure/index.ts +0 -116
  200. package/src/commands/azure/storage.ts +0 -478
  201. package/src/commands/azure/vm.ts +0 -355
  202. package/src/commands/billing/index.ts +0 -256
  203. package/src/commands/chat.ts +0 -320
  204. package/src/commands/completions.ts +0 -268
  205. package/src/commands/config.ts +0 -372
  206. package/src/commands/cost/cloud-cost-estimator.ts +0 -266
  207. package/src/commands/cost/estimator.ts +0 -79
  208. package/src/commands/cost/index.ts +0 -810
  209. package/src/commands/cost/parsers/terraform.ts +0 -273
  210. package/src/commands/cost/parsers/types.ts +0 -25
  211. package/src/commands/cost/pricing/aws.ts +0 -544
  212. package/src/commands/cost/pricing/azure.ts +0 -499
  213. package/src/commands/cost/pricing/gcp.ts +0 -396
  214. package/src/commands/cost/pricing/index.ts +0 -40
  215. package/src/commands/demo.ts +0 -250
  216. package/src/commands/deploy.ts +0 -260
  217. package/src/commands/doctor.ts +0 -1386
  218. package/src/commands/drift/index.ts +0 -787
  219. package/src/commands/explain.ts +0 -277
  220. package/src/commands/export.ts +0 -146
  221. package/src/commands/feedback.ts +0 -389
  222. package/src/commands/fix.ts +0 -324
  223. package/src/commands/fs/index.ts +0 -402
  224. package/src/commands/gcp/compute.ts +0 -325
  225. package/src/commands/gcp/functions.ts +0 -271
  226. package/src/commands/gcp/gke.ts +0 -438
  227. package/src/commands/gcp/iam.ts +0 -344
  228. package/src/commands/gcp/index.ts +0 -129
  229. package/src/commands/gcp/storage.ts +0 -284
  230. package/src/commands/generate-helm.ts +0 -1249
  231. package/src/commands/generate-k8s.ts +0 -1508
  232. package/src/commands/generate-terraform.ts +0 -1202
  233. package/src/commands/gh/index.ts +0 -863
  234. package/src/commands/git/index.ts +0 -1343
  235. package/src/commands/helm/index.ts +0 -1126
  236. package/src/commands/help.ts +0 -715
  237. package/src/commands/history.ts +0 -149
  238. package/src/commands/import.ts +0 -868
  239. package/src/commands/incident.ts +0 -166
  240. package/src/commands/index.ts +0 -367
  241. package/src/commands/init.ts +0 -1051
  242. package/src/commands/k8s/index.ts +0 -1137
  243. package/src/commands/login.ts +0 -716
  244. package/src/commands/logout.ts +0 -83
  245. package/src/commands/logs.ts +0 -167
  246. package/src/commands/onboarding.ts +0 -405
  247. package/src/commands/pipeline.ts +0 -186
  248. package/src/commands/plan/display.ts +0 -279
  249. package/src/commands/plan/index.ts +0 -599
  250. package/src/commands/plugin.ts +0 -398
  251. package/src/commands/preview.ts +0 -452
  252. package/src/commands/profile.ts +0 -342
  253. package/src/commands/questionnaire.ts +0 -1172
  254. package/src/commands/resume.ts +0 -47
  255. package/src/commands/rollback.ts +0 -315
  256. package/src/commands/rollout.ts +0 -88
  257. package/src/commands/runbook.ts +0 -346
  258. package/src/commands/schedule.ts +0 -236
  259. package/src/commands/status.ts +0 -252
  260. package/src/commands/team/index.ts +0 -346
  261. package/src/commands/team-context.ts +0 -220
  262. package/src/commands/template.ts +0 -233
  263. package/src/commands/tf/index.ts +0 -1093
  264. package/src/commands/upgrade.ts +0 -609
  265. package/src/commands/usage/index.ts +0 -134
  266. package/src/commands/version.ts +0 -174
  267. package/src/commands/watch.ts +0 -153
  268. package/src/compat/index.ts +0 -2
  269. package/src/compat/runtime.ts +0 -12
  270. package/src/compat/sqlite.ts +0 -177
  271. package/src/config/index.ts +0 -17
  272. package/src/config/manager.ts +0 -530
  273. package/src/config/mode-store.ts +0 -62
  274. package/src/config/profiles.ts +0 -84
  275. package/src/config/safety-policy.ts +0 -358
  276. package/src/config/schema.ts +0 -125
  277. package/src/config/types.ts +0 -609
  278. package/src/config/workspace-state.ts +0 -53
  279. package/src/context/context-db.ts +0 -199
  280. package/src/demo/index.ts +0 -349
  281. package/src/demo/scenarios/full-journey.ts +0 -229
  282. package/src/demo/scenarios/getting-started.ts +0 -127
  283. package/src/demo/scenarios/helm-release.ts +0 -341
  284. package/src/demo/scenarios/k8s-deployment.ts +0 -194
  285. package/src/demo/scenarios/terraform-vpc.ts +0 -170
  286. package/src/demo/types.ts +0 -92
  287. package/src/engine/cost-estimator.ts +0 -480
  288. package/src/engine/diagram-generator.ts +0 -256
  289. package/src/engine/drift-detector.ts +0 -902
  290. package/src/engine/executor.ts +0 -1066
  291. package/src/engine/index.ts +0 -76
  292. package/src/engine/orchestrator.ts +0 -636
  293. package/src/engine/planner.ts +0 -787
  294. package/src/engine/safety.ts +0 -743
  295. package/src/engine/verifier.ts +0 -770
  296. package/src/enterprise/audit.ts +0 -348
  297. package/src/enterprise/auth.ts +0 -270
  298. package/src/enterprise/billing.ts +0 -822
  299. package/src/enterprise/index.ts +0 -17
  300. package/src/enterprise/teams.ts +0 -443
  301. package/src/generator/best-practices.ts +0 -1608
  302. package/src/generator/helm.ts +0 -630
  303. package/src/generator/index.ts +0 -37
  304. package/src/generator/intent-parser.ts +0 -514
  305. package/src/generator/kubernetes.ts +0 -976
  306. package/src/generator/terraform.ts +0 -1875
  307. package/src/history/index.ts +0 -8
  308. package/src/history/manager.ts +0 -250
  309. package/src/history/types.ts +0 -34
  310. package/src/hooks/config.ts +0 -432
  311. package/src/hooks/engine.ts +0 -392
  312. package/src/hooks/index.ts +0 -4
  313. package/src/llm/auth-bridge.ts +0 -198
  314. package/src/llm/circuit-breaker.ts +0 -140
  315. package/src/llm/config-loader.ts +0 -201
  316. package/src/llm/cost-calculator.ts +0 -171
  317. package/src/llm/index.ts +0 -8
  318. package/src/llm/model-aliases.ts +0 -115
  319. package/src/llm/provider-registry.ts +0 -63
  320. package/src/llm/providers/anthropic.ts +0 -462
  321. package/src/llm/providers/bedrock.ts +0 -477
  322. package/src/llm/providers/google.ts +0 -405
  323. package/src/llm/providers/ollama.ts +0 -767
  324. package/src/llm/providers/openai-compatible.ts +0 -340
  325. package/src/llm/providers/openai.ts +0 -328
  326. package/src/llm/providers/openrouter.ts +0 -338
  327. package/src/llm/router.ts +0 -1104
  328. package/src/llm/types.ts +0 -232
  329. package/src/lsp/client.ts +0 -298
  330. package/src/lsp/languages.ts +0 -119
  331. package/src/lsp/manager.ts +0 -294
  332. package/src/mcp/client.ts +0 -402
  333. package/src/mcp/index.ts +0 -5
  334. package/src/mcp/manager.ts +0 -133
  335. package/src/nimbus.ts +0 -234
  336. package/src/plugins/index.ts +0 -27
  337. package/src/plugins/loader.ts +0 -334
  338. package/src/plugins/manager.ts +0 -376
  339. package/src/plugins/types.ts +0 -284
  340. package/src/scanners/cicd-scanner.ts +0 -258
  341. package/src/scanners/cloud-scanner.ts +0 -466
  342. package/src/scanners/framework-scanner.ts +0 -469
  343. package/src/scanners/iac-scanner.ts +0 -388
  344. package/src/scanners/index.ts +0 -539
  345. package/src/scanners/language-scanner.ts +0 -276
  346. package/src/scanners/package-manager-scanner.ts +0 -277
  347. package/src/scanners/types.ts +0 -172
  348. package/src/sessions/manager.ts +0 -472
  349. package/src/sessions/types.ts +0 -44
  350. package/src/sharing/sync.ts +0 -300
  351. package/src/sharing/viewer.ts +0 -163
  352. package/src/snapshots/index.ts +0 -2
  353. package/src/snapshots/manager.ts +0 -530
  354. package/src/state/artifacts.ts +0 -147
  355. package/src/state/audit.ts +0 -137
  356. package/src/state/billing.ts +0 -240
  357. package/src/state/checkpoints.ts +0 -117
  358. package/src/state/config.ts +0 -67
  359. package/src/state/conversations.ts +0 -14
  360. package/src/state/credentials.ts +0 -154
  361. package/src/state/db.ts +0 -58
  362. package/src/state/index.ts +0 -26
  363. package/src/state/messages.ts +0 -115
  364. package/src/state/projects.ts +0 -123
  365. package/src/state/schema.ts +0 -236
  366. package/src/state/sessions.ts +0 -147
  367. package/src/state/teams.ts +0 -200
  368. package/src/telemetry.ts +0 -108
  369. package/src/tools/aws-ops.ts +0 -952
  370. package/src/tools/azure-ops.ts +0 -579
  371. package/src/tools/file-ops.ts +0 -615
  372. package/src/tools/gcp-ops.ts +0 -625
  373. package/src/tools/git-ops.ts +0 -773
  374. package/src/tools/github-ops.ts +0 -799
  375. package/src/tools/helm-ops.ts +0 -943
  376. package/src/tools/index.ts +0 -17
  377. package/src/tools/k8s-ops.ts +0 -819
  378. package/src/tools/schemas/converter.ts +0 -184
  379. package/src/tools/schemas/devops.ts +0 -3502
  380. package/src/tools/schemas/index.ts +0 -73
  381. package/src/tools/schemas/standard.ts +0 -1148
  382. package/src/tools/schemas/types.ts +0 -735
  383. package/src/tools/spawn-exec.ts +0 -148
  384. package/src/tools/terraform-ops.ts +0 -862
  385. package/src/types/ambient.d.ts +0 -193
  386. package/src/types/config.ts +0 -83
  387. package/src/types/drift.ts +0 -116
  388. package/src/types/enterprise.ts +0 -335
  389. package/src/types/index.ts +0 -20
  390. package/src/types/plan.ts +0 -44
  391. package/src/types/request.ts +0 -65
  392. package/src/types/response.ts +0 -54
  393. package/src/types/service.ts +0 -51
  394. package/src/ui/App.tsx +0 -2114
  395. package/src/ui/DeployPreview.tsx +0 -174
  396. package/src/ui/FileDiffModal.tsx +0 -162
  397. package/src/ui/Header.tsx +0 -131
  398. package/src/ui/HelpModal.tsx +0 -57
  399. package/src/ui/InputBox.tsx +0 -503
  400. package/src/ui/MessageList.tsx +0 -1032
  401. package/src/ui/PermissionPrompt.tsx +0 -163
  402. package/src/ui/StatusBar.tsx +0 -277
  403. package/src/ui/TerminalPane.tsx +0 -84
  404. package/src/ui/ToolCallDisplay.tsx +0 -643
  405. package/src/ui/TreePane.tsx +0 -132
  406. package/src/ui/chat-ui.ts +0 -850
  407. package/src/ui/index.ts +0 -33
  408. package/src/ui/ink/index.ts +0 -1444
  409. package/src/ui/streaming.ts +0 -176
  410. package/src/ui/theme.ts +0 -104
  411. package/src/ui/types.ts +0 -75
  412. package/src/utils/analytics.ts +0 -72
  413. package/src/utils/cost-warning.ts +0 -27
  414. package/src/utils/env.ts +0 -46
  415. package/src/utils/errors.ts +0 -69
  416. package/src/utils/event-bus.ts +0 -38
  417. package/src/utils/index.ts +0 -24
  418. package/src/utils/logger.ts +0 -171
  419. package/src/utils/rate-limiter.ts +0 -121
  420. package/src/utils/service-auth.ts +0 -49
  421. package/src/utils/validation.ts +0 -53
  422. package/src/version.ts +0 -4
  423. package/src/watcher/index.ts +0 -214
  424. package/src/wizard/approval.ts +0 -383
  425. package/src/wizard/index.ts +0 -25
  426. package/src/wizard/prompts.ts +0 -338
  427. package/src/wizard/types.ts +0 -172
  428. package/src/wizard/ui.ts +0 -556
  429. package/src/wizard/wizard.ts +0 -304
  430. package/tsconfig.json +0 -24
@@ -1,244 +0,0 @@
1
- /**
2
- * Agent Loop Error Classification Tests — G3 + G24
3
- *
4
- * The `classifyDevOpsError` function is not exported from loop.ts, so we test:
5
- * 1. The install-hint patterns by parsing the source directly and validating
6
- * the INSTALL_HINTS mapping is present for expected CLI tools.
7
- * 2. Network error handling (G24) — ECONNREFUSED + _nimbusNetworkError sentinel.
8
- *
9
- * For install-hint logic we also inline a minimal reproduction so we can
10
- * verify the matching logic behaves correctly without coupling to internals.
11
- */
12
-
13
- import { describe, it, expect } from 'vitest';
14
- import { readFileSync } from 'node:fs';
15
- import { join } from 'node:path';
16
-
17
- const LOOP_SRC = readFileSync(join(__dirname, '..', 'agent', 'loop.ts'), 'utf-8');
18
-
19
- // ---------------------------------------------------------------------------
20
- // Inline reproduction of classifyDevOpsError install-hint logic (G3)
21
- // This mirrors exactly what the source implements so we can unit-test it.
22
- // ---------------------------------------------------------------------------
23
-
24
- const INSTALL_HINTS: Record<string, string> = {
25
- terraform: 'brew install terraform OR https://developer.hashicorp.com/terraform/install',
26
- kubectl: 'brew install kubectl OR https://kubernetes.io/docs/tasks/tools/',
27
- helm: 'brew install helm OR https://helm.sh/docs/intro/install/',
28
- docker: 'brew install --cask docker OR https://docs.docker.com/get-docker/',
29
- aws: 'brew install awscli OR pip install awscli',
30
- gcloud: 'brew install --cask google-cloud-sdk',
31
- az: 'brew install azure-cli',
32
- };
33
-
34
- function classifyInstallHint(toolName: string, errorOutput: string): string | null {
35
- const e = errorOutput.toLowerCase();
36
- if (/command not found|not found|no such file or directory/i.test(errorOutput)) {
37
- for (const [cmd, hint] of Object.entries(INSTALL_HINTS)) {
38
- if (toolName.includes(cmd) || e.includes(`'${cmd}'`) || e.includes(`"${cmd}"`)) {
39
- return `\`${cmd}\` is not installed.\n\nInstall: ${hint}`;
40
- }
41
- }
42
- }
43
- return null;
44
- }
45
-
46
- // ---------------------------------------------------------------------------
47
- // G3: install-hint tests
48
- // ---------------------------------------------------------------------------
49
-
50
- describe('classifyDevOpsError install hints (G3)', () => {
51
- it('returns brew install terraform for "terraform: command not found"', () => {
52
- const result = classifyInstallHint('terraform', 'terraform: command not found');
53
- expect(result).not.toBeNull();
54
- expect(result).toContain('brew install terraform');
55
- });
56
-
57
- it('returns brew install kubectl for kubectl not found', () => {
58
- const result = classifyInstallHint('kubectl', 'kubectl: No such file or directory');
59
- expect(result).not.toBeNull();
60
- expect(result).toContain('brew install kubectl');
61
- });
62
-
63
- it('returns brew install helm for helm not found', () => {
64
- const result = classifyInstallHint('helm', 'helm not found');
65
- expect(result).not.toBeNull();
66
- expect(result).toContain('brew install helm');
67
- });
68
-
69
- it('returns brew install docker for docker command not found', () => {
70
- const result = classifyInstallHint('docker', 'docker: command not found');
71
- expect(result).not.toBeNull();
72
- expect(result).toContain('brew install');
73
- });
74
-
75
- it('returns null for a normal error that is not a "not found" error', () => {
76
- const result = classifyInstallHint('kubectl', 'context deadline exceeded');
77
- expect(result).toBeNull();
78
- });
79
-
80
- it('returns null for an unrecognised tool with a random error', () => {
81
- const result = classifyInstallHint('myapp', 'connection refused');
82
- expect(result).toBeNull();
83
- });
84
- });
85
-
86
- // ---------------------------------------------------------------------------
87
- // G24: network error sentinel in loop.ts source
88
- // ---------------------------------------------------------------------------
89
-
90
- describe('network error handling exists in loop.ts (G24)', () => {
91
- it('source contains ECONNREFUSED detection', () => {
92
- expect(LOOP_SRC).toContain('ECONNREFUSED');
93
- });
94
-
95
- it('source contains _nimbusNetworkError sentinel property', () => {
96
- expect(LOOP_SRC).toContain('_nimbusNetworkError');
97
- });
98
-
99
- it('source detects ETIMEDOUT in network errors', () => {
100
- expect(LOOP_SRC).toContain('ETIMEDOUT');
101
- });
102
-
103
- it('source detects ENOTFOUND in network errors', () => {
104
- expect(LOOP_SRC).toContain('ENOTFOUND');
105
- });
106
- });
107
-
108
- // ---------------------------------------------------------------------------
109
- // G3: source-level assertions that INSTALL_HINTS map exists
110
- // ---------------------------------------------------------------------------
111
-
112
- describe('INSTALL_HINTS map present in loop.ts source (G3)', () => {
113
- it('source defines INSTALL_HINTS with terraform entry', () => {
114
- expect(LOOP_SRC).toContain('brew install terraform');
115
- });
116
-
117
- it('source defines INSTALL_HINTS with kubectl entry', () => {
118
- expect(LOOP_SRC).toContain('brew install kubectl');
119
- });
120
-
121
- it('source defines INSTALL_HINTS with helm entry', () => {
122
- expect(LOOP_SRC).toContain('brew install helm');
123
- });
124
-
125
- it('source defines INSTALL_HINTS with docker entry', () => {
126
- expect(LOOP_SRC).toContain('brew install --cask docker');
127
- });
128
- });
129
-
130
- // ---------------------------------------------------------------------------
131
- // L3: NIMBUS.md custom error hints
132
- // ---------------------------------------------------------------------------
133
-
134
- describe('NIMBUS.md custom error hints (L3)', () => {
135
- // Inline a minimal reproduction of the custom hints parsing logic
136
- function parseCustomHints(nimbusInstructions: string, errorOutput: string): string | null {
137
- const hintsMatch = nimbusInstructions.match(/##\s*Custom Error Hints\s*\n([\s\S]*?)(?=\n##|\n$|$)/i);
138
- if (!hintsMatch) return null;
139
- const hintsSection = hintsMatch[1];
140
- const hintLines = hintsSection.split('\n').filter((l: string) => l.trim().startsWith('-'));
141
- for (const line of hintLines) {
142
- const colonIdx = line.indexOf(':');
143
- if (colonIdx > 0) {
144
- const pattern = line.slice(1, colonIdx).trim();
145
- const hint = line.slice(colonIdx + 1).trim();
146
- if (pattern && hint && errorOutput.toLowerCase().includes(pattern.toLowerCase())) {
147
- return `HINT: ${hint}`;
148
- }
149
- }
150
- }
151
- return null;
152
- }
153
-
154
- it('returns custom hint when pattern matches error output', () => {
155
- const instructions = `## Custom Error Hints\n- registry.internal: Run docker login registry.internal first\n`;
156
- const result = parseCustomHints(instructions, 'Error: registry.internal: connection refused');
157
- expect(result).toBe('HINT: Run docker login registry.internal first');
158
- });
159
-
160
- it('returns null when no matching pattern', () => {
161
- const instructions = `## Custom Error Hints\n- registry.internal: Run docker login registry.internal first\n`;
162
- const result = parseCustomHints(instructions, 'Error: some unrelated error');
163
- expect(result).toBeNull();
164
- });
165
-
166
- it('returns null when no Custom Error Hints section', () => {
167
- const instructions = `## Other Section\n- some content\n`;
168
- const result = parseCustomHints(instructions, 'Error: registry.internal: connection refused');
169
- expect(result).toBeNull();
170
- });
171
-
172
- it('pattern matching is case-insensitive', () => {
173
- const instructions = `## Custom Error Hints\n- VPN Required: Connect to corporate VPN\n`;
174
- const result = parseCustomHints(instructions, 'error: vpn required - connection blocked');
175
- expect(result).toBe('HINT: Connect to corporate VPN');
176
- });
177
-
178
- it('loop.ts source contains custom error hints parsing', () => {
179
- const { readFileSync } = require('node:fs');
180
- const { join } = require('node:path');
181
- const src = readFileSync(join(process.cwd(), 'src/agent/loop.ts'), 'utf-8');
182
- expect(src).toContain('Custom Error Hints');
183
- });
184
-
185
- it('multiple hints in section — first match wins', () => {
186
- const instructions = [
187
- '## Custom Error Hints',
188
- '- alpha: Hint for alpha',
189
- '- beta: Hint for beta',
190
- '- gamma: Hint for gamma',
191
- '',
192
- ].join('\n');
193
- const result = parseCustomHints(instructions, 'Error: beta failure occurred');
194
- expect(result).toBe('HINT: Hint for beta');
195
- });
196
-
197
- it('hint with colon in hint text is preserved', () => {
198
- const instructions = `## Custom Error Hints\n- timeout: Run: kubectl describe pod <name>\n`;
199
- const result = parseCustomHints(instructions, 'Error: timeout waiting for pod');
200
- expect(result).toBe('HINT: Run: kubectl describe pod <name>');
201
- });
202
-
203
- it('returns null when instructions is empty string', () => {
204
- const result = parseCustomHints('', 'Error: timeout');
205
- expect(result).toBeNull();
206
- });
207
-
208
- it('loop.ts source passes nimbusInstructions to classifyDevOpsError', () => {
209
- const { readFileSync } = require('node:fs');
210
- const { join } = require('node:path');
211
- const src = readFileSync(join(process.cwd(), 'src/agent/loop.ts'), 'utf-8');
212
- expect(src).toContain('nimbusInstructions');
213
- });
214
-
215
- it('source contains READ_ONLY_TOOLS set', () => {
216
- const { readFileSync } = require('node:fs');
217
- const { join } = require('node:path');
218
- const src = readFileSync(join(process.cwd(), 'src/agent/loop.ts'), 'utf-8');
219
- expect(src).toContain('READ_ONLY_TOOLS');
220
- });
221
- });
222
-
223
- // ---------------------------------------------------------------------------
224
- // C4: TUI error hint propagation — hint appears in result.output (not just LLM context)
225
- // ---------------------------------------------------------------------------
226
-
227
- describe('C4 — tool error hints propagated to TUI (result.output)', () => {
228
- it('loop.ts source augments result.output with the install hint', () => {
229
- expect(LOOP_SRC).toContain('result.output +=');
230
- });
231
-
232
- it('loop.ts C4 comment exists to document the change', () => {
233
- expect(LOOP_SRC).toContain('C4: Also show hint in TUI error output');
234
- });
235
-
236
- it('hint augmentation happens after toolContent augmentation', () => {
237
- // The toolContent line should appear before result.output in source
238
- const toolContentIdx = LOOP_SRC.indexOf('toolContent += `\\n\\n${hint}`');
239
- const resultOutputIdx = LOOP_SRC.indexOf('result.output += `\\n\\n${hint}`');
240
- expect(toolContentIdx).toBeGreaterThanOrEqual(0);
241
- expect(resultOutputIdx).toBeGreaterThanOrEqual(0);
242
- expect(toolContentIdx).toBeLessThan(resultOutputIdx);
243
- });
244
- });
@@ -1,293 +0,0 @@
1
- /**
2
- * Tests for LSP Manager, Client, Language configs, and Agent Loop integration.
3
- */
4
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
5
- import { getLanguageForFile, getLanguagePriority, LANGUAGE_CONFIGS } from '../lsp/languages';
6
- import { LSPManager, resetLSPManager } from '../lsp/manager';
7
- import { severityLabel } from '../lsp/client';
8
-
9
- describe('Language Configs', () => {
10
- describe('getLanguageForFile', () => {
11
- it('should match TypeScript files', () => {
12
- expect(getLanguageForFile('src/index.ts')?.id).toBe('typescript');
13
- expect(getLanguageForFile('component.tsx')?.id).toBe('typescript');
14
- expect(getLanguageForFile('index.js')?.id).toBe('typescript');
15
- expect(getLanguageForFile('config.mjs')?.id).toBe('typescript');
16
- });
17
-
18
- it('should match Go files', () => {
19
- expect(getLanguageForFile('main.go')?.id).toBe('go');
20
- expect(getLanguageForFile('pkg/server/handler.go')?.id).toBe('go');
21
- });
22
-
23
- it('should match Python files', () => {
24
- expect(getLanguageForFile('app.py')?.id).toBe('python');
25
- expect(getLanguageForFile('types.pyi')?.id).toBe('python');
26
- });
27
-
28
- it('should match Terraform files', () => {
29
- expect(getLanguageForFile('main.tf')?.id).toBe('terraform');
30
- expect(getLanguageForFile('variables.tfvars')?.id).toBe('terraform');
31
- expect(getLanguageForFile('config.hcl')?.id).toBe('terraform');
32
- });
33
-
34
- it('should match YAML files', () => {
35
- expect(getLanguageForFile('config.yaml')?.id).toBe('yaml');
36
- expect(getLanguageForFile('deployment.yml')?.id).toBe('yaml');
37
- });
38
-
39
- it('should match Dockerfile', () => {
40
- expect(getLanguageForFile('Dockerfile')?.id).toBe('docker');
41
- expect(getLanguageForFile('app.dockerfile')?.id).toBe('docker');
42
- });
43
-
44
- it('should return undefined for unknown extensions', () => {
45
- expect(getLanguageForFile('README.md')).toBeUndefined();
46
- expect(getLanguageForFile('Makefile')).toBeUndefined();
47
- expect(getLanguageForFile('data.csv')).toBeUndefined();
48
- });
49
- });
50
-
51
- describe('getLanguagePriority', () => {
52
- it('should return all configs in priority order', () => {
53
- const priority = getLanguagePriority();
54
- expect(priority).toHaveLength(LANGUAGE_CONFIGS.length);
55
- expect(priority[0].id).toBe('typescript');
56
- });
57
- });
58
-
59
- describe('LANGUAGE_CONFIGS', () => {
60
- it('should have command and installHint for all configs', () => {
61
- for (const config of LANGUAGE_CONFIGS) {
62
- expect(config.command).toBeTruthy();
63
- expect(config.installHint).toBeTruthy();
64
- expect(config.extensions.length).toBeGreaterThan(0);
65
- }
66
- });
67
- });
68
- });
69
-
70
- describe('severityLabel', () => {
71
- it('should return correct labels', () => {
72
- expect(severityLabel(1)).toBe('Error');
73
- expect(severityLabel(2)).toBe('Warning');
74
- expect(severityLabel(3)).toBe('Info');
75
- expect(severityLabel(4)).toBe('Hint');
76
- });
77
- });
78
-
79
- describe('LSPManager', () => {
80
- let manager: LSPManager;
81
-
82
- beforeEach(() => {
83
- resetLSPManager();
84
- manager = new LSPManager('/tmp/test-project');
85
- });
86
-
87
- afterEach(async () => {
88
- await manager.stopAll();
89
- resetLSPManager();
90
- });
91
-
92
- describe('setEnabled', () => {
93
- it('should disable LSP integration', () => {
94
- manager.setEnabled(false);
95
- // touchFile should be a no-op when disabled
96
- });
97
-
98
- it('should re-enable LSP integration', () => {
99
- manager.setEnabled(false);
100
- manager.setEnabled(true);
101
- });
102
- });
103
-
104
- describe('getDiagnostics', () => {
105
- it('should return empty array when disabled', async () => {
106
- manager.setEnabled(false);
107
- const diags = await manager.getDiagnostics('/tmp/test.ts');
108
- expect(diags).toEqual([]);
109
- });
110
-
111
- it('should return empty array for unsupported file types', async () => {
112
- const diags = await manager.getDiagnostics('/tmp/file.csv');
113
- expect(diags).toEqual([]);
114
- });
115
-
116
- it('should return empty array when server is not running', async () => {
117
- const diags = await manager.getDiagnostics('/tmp/test.ts', 100);
118
- expect(diags).toEqual([]);
119
- });
120
- });
121
-
122
- describe('getErrors', () => {
123
- it('should return empty array when no errors', async () => {
124
- const errors = await manager.getErrors('/tmp/test.ts');
125
- expect(errors).toEqual([]);
126
- });
127
- });
128
-
129
- describe('formatDiagnosticsForAgent', () => {
130
- it('should return null for empty diagnostics', () => {
131
- expect(manager.formatDiagnosticsForAgent([])).toBeNull();
132
- });
133
-
134
- it('should format error diagnostics', () => {
135
- const diagnostics = [
136
- {
137
- file: '/src/server.ts',
138
- line: 23,
139
- column: 5,
140
- severity: 1 as const,
141
- message: "Property 'origin' does not exist on type 'CorsConfig'",
142
- source: 'ts',
143
- },
144
- ];
145
- const result = manager.formatDiagnosticsForAgent(diagnostics);
146
- expect(result).toContain('[LSP Diagnostics]');
147
- expect(result).toContain('Error: /src/server.ts:23:5');
148
- expect(result).toContain("Property 'origin'");
149
- });
150
-
151
- it('should truncate warnings after 5', () => {
152
- const diagnostics = Array.from({ length: 10 }, (_, i) => ({
153
- file: '/src/file.ts',
154
- line: i + 1,
155
- column: 1,
156
- severity: 2 as const,
157
- message: `Warning ${i + 1}`,
158
- }));
159
- const result = manager.formatDiagnosticsForAgent(diagnostics);
160
- expect(result).toContain('5 more warnings');
161
- });
162
-
163
- it('should return null for only info/hint diagnostics', () => {
164
- const diagnostics = [
165
- { file: '/src/file.ts', line: 1, column: 1, severity: 3 as const, message: 'Info' },
166
- { file: '/src/file.ts', line: 2, column: 1, severity: 4 as const, message: 'Hint' },
167
- ];
168
- expect(manager.formatDiagnosticsForAgent(diagnostics)).toBeNull();
169
- });
170
- });
171
-
172
- describe('getStatus', () => {
173
- it('should return status for all configured languages', async () => {
174
- const statuses = await manager.getStatus();
175
- expect(statuses.length).toBe(LANGUAGE_CONFIGS.length);
176
- for (const status of statuses) {
177
- expect(status.language).toBeTruthy();
178
- expect(typeof status.active).toBe('boolean');
179
- expect(typeof status.available).toBe('boolean');
180
- }
181
- });
182
- });
183
-
184
- describe('stopAll', () => {
185
- it('should not throw when no clients running', async () => {
186
- await expect(manager.stopAll()).resolves.toBeUndefined();
187
- });
188
- });
189
- });
190
-
191
- // ---------------------------------------------------------------------------
192
- // Agent Loop LSP Integration
193
- // ---------------------------------------------------------------------------
194
-
195
- describe('Agent Loop LSP Integration', () => {
196
- it('should identify file-editing tools correctly', () => {
197
- // Verify the tools that should trigger LSP diagnostics
198
- const fileEditingTools = ['edit_file', 'multi_edit', 'write_file'];
199
- const nonFileEditingTools = ['read_file', 'bash', 'glob', 'grep', 'terraform', 'kubectl'];
200
-
201
- for (const tool of fileEditingTools) {
202
- // These tools have a `path` parameter that LSP integration uses
203
- expect(['edit_file', 'multi_edit', 'write_file']).toContain(tool);
204
- }
205
-
206
- for (const tool of nonFileEditingTools) {
207
- expect(['edit_file', 'multi_edit', 'write_file']).not.toContain(tool);
208
- }
209
- });
210
-
211
- it('should extract file path from edit_file input', () => {
212
- const input = { path: '/src/server.ts', old_string: 'foo', new_string: 'bar' };
213
- expect(input.path).toBe('/src/server.ts');
214
- });
215
-
216
- it('should extract file path from write_file input', () => {
217
- const input = { path: '/src/new-file.ts', content: 'console.log("hello")' };
218
- expect(input.path).toBe('/src/new-file.ts');
219
- });
220
-
221
- it('should extract file path from multi_edit input', () => {
222
- const input = { path: '/src/app.ts', edits: [{ old_string: 'a', new_string: 'b' }] };
223
- expect(input.path).toBe('/src/app.ts');
224
- });
225
-
226
- it('should format diagnostics for agent conversation injection', () => {
227
- const manager = new LSPManager('/tmp/test');
228
- const diagnostics = [
229
- {
230
- file: '/src/server.ts',
231
- line: 23,
232
- column: 5,
233
- severity: 1 as const,
234
- message: "Property 'origin' does not exist on type 'CorsConfig'",
235
- source: 'ts',
236
- },
237
- {
238
- file: '/src/server.ts',
239
- line: 45,
240
- column: 10,
241
- severity: 2 as const,
242
- message: 'Unused variable',
243
- source: 'ts',
244
- },
245
- ];
246
-
247
- const formatted = manager.formatDiagnosticsForAgent(diagnostics);
248
- expect(formatted).not.toBeNull();
249
- expect(formatted).toContain('[LSP Diagnostics]');
250
- expect(formatted).toContain('Error:');
251
- expect(formatted).toContain('Warning:');
252
- // Verify the formatting includes enough info for the LLM to self-correct
253
- expect(formatted).toContain('/src/server.ts:23:5');
254
- expect(formatted).toContain("Property 'origin'");
255
- resetLSPManager();
256
- });
257
-
258
- it('should append diagnostics to tool output when errors exist', () => {
259
- // Simulate the behavior of the agent loop's LSP injection
260
- const originalOutput = 'File edited successfully.';
261
- const diagnosticText = '[LSP Diagnostics]\n Error: /src/server.ts:23:5 — Type error (ts)';
262
-
263
- // This mirrors the logic in executeToolCall
264
- const combined = `${originalOutput}\n\n${diagnosticText}`;
265
- expect(combined).toContain(originalOutput);
266
- expect(combined).toContain('[LSP Diagnostics]');
267
- expect(combined).toContain('Type error');
268
- });
269
-
270
- it('should not append diagnostics when there are no errors', () => {
271
- const manager = new LSPManager('/tmp/test');
272
- const formatted = manager.formatDiagnosticsForAgent([]);
273
- expect(formatted).toBeNull();
274
- resetLSPManager();
275
- });
276
-
277
- it('should not inject diagnostics for non-file-editing tools', () => {
278
- // read_file, bash, grep etc. should not trigger LSP
279
- const nonEditTools = ['read_file', 'bash', 'glob', 'grep', 'list_dir', 'terraform'];
280
- for (const tool of nonEditTools) {
281
- // These should not have file path extraction attempted
282
- const isFileEditing = ['edit_file', 'multi_edit', 'write_file'].includes(tool);
283
- expect(isFileEditing).toBe(false);
284
- }
285
- });
286
-
287
- it('should gracefully handle missing path in input', () => {
288
- // If somehow the input doesn't have a path field, extraction returns null
289
- const input = { content: 'some content' };
290
- const hasPath = 'path' in input;
291
- expect(hasPath).toBe(false);
292
- });
293
- });