devvami 1.4.2 → 1.5.1

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 (96) hide show
  1. package/README.md +72 -0
  2. package/oclif.manifest.json +275 -235
  3. package/package.json +2 -1
  4. package/src/commands/auth/login.js +20 -16
  5. package/src/commands/changelog.js +12 -12
  6. package/src/commands/costs/get.js +14 -24
  7. package/src/commands/costs/trend.js +13 -24
  8. package/src/commands/create/repo.js +72 -54
  9. package/src/commands/docs/list.js +29 -25
  10. package/src/commands/docs/projects.js +58 -24
  11. package/src/commands/docs/read.js +56 -39
  12. package/src/commands/docs/search.js +37 -25
  13. package/src/commands/doctor.js +37 -35
  14. package/src/commands/dotfiles/add.js +51 -39
  15. package/src/commands/dotfiles/setup.js +62 -33
  16. package/src/commands/dotfiles/status.js +18 -18
  17. package/src/commands/dotfiles/sync.js +62 -46
  18. package/src/commands/init.js +143 -132
  19. package/src/commands/logs/index.js +10 -16
  20. package/src/commands/open.js +12 -12
  21. package/src/commands/pipeline/logs.js +8 -11
  22. package/src/commands/pipeline/rerun.js +21 -16
  23. package/src/commands/pipeline/status.js +28 -24
  24. package/src/commands/pr/create.js +40 -27
  25. package/src/commands/pr/detail.js +9 -7
  26. package/src/commands/pr/review.js +18 -19
  27. package/src/commands/pr/status.js +27 -21
  28. package/src/commands/prompts/browse.js +15 -15
  29. package/src/commands/prompts/download.js +15 -16
  30. package/src/commands/prompts/install-speckit.js +11 -12
  31. package/src/commands/prompts/list.js +12 -12
  32. package/src/commands/prompts/run.js +16 -19
  33. package/src/commands/repo/list.js +57 -41
  34. package/src/commands/search.js +20 -18
  35. package/src/commands/security/setup.js +38 -34
  36. package/src/commands/sync-config-ai/index.js +257 -0
  37. package/src/commands/tasks/assigned.js +43 -33
  38. package/src/commands/tasks/list.js +43 -33
  39. package/src/commands/tasks/today.js +32 -30
  40. package/src/commands/upgrade.js +18 -17
  41. package/src/commands/vuln/detail.js +8 -8
  42. package/src/commands/vuln/scan.js +39 -20
  43. package/src/commands/vuln/search.js +23 -18
  44. package/src/commands/welcome.js +2 -2
  45. package/src/commands/whoami.js +19 -23
  46. package/src/formatters/ai-config.js +215 -0
  47. package/src/formatters/charts.js +6 -23
  48. package/src/formatters/cost.js +1 -7
  49. package/src/formatters/dotfiles.js +48 -19
  50. package/src/formatters/markdown.js +11 -6
  51. package/src/formatters/openapi.js +7 -9
  52. package/src/formatters/prompts.js +69 -78
  53. package/src/formatters/security.js +2 -2
  54. package/src/formatters/status.js +1 -1
  55. package/src/formatters/table.js +1 -3
  56. package/src/formatters/vuln.js +33 -20
  57. package/src/help.js +162 -164
  58. package/src/hooks/init.js +1 -3
  59. package/src/hooks/postrun.js +5 -7
  60. package/src/index.js +1 -1
  61. package/src/services/ai-config-store.js +349 -0
  62. package/src/services/ai-env-deployer.js +650 -0
  63. package/src/services/ai-env-scanner.js +983 -0
  64. package/src/services/audit-detector.js +2 -2
  65. package/src/services/audit-runner.js +40 -31
  66. package/src/services/auth.js +9 -9
  67. package/src/services/awesome-copilot.js +7 -4
  68. package/src/services/aws-costs.js +22 -22
  69. package/src/services/clickup.js +26 -26
  70. package/src/services/cloudwatch-logs.js +5 -9
  71. package/src/services/config.js +13 -13
  72. package/src/services/docs.js +19 -20
  73. package/src/services/dotfiles.js +149 -51
  74. package/src/services/github.js +22 -24
  75. package/src/services/nvd.js +21 -31
  76. package/src/services/platform.js +2 -2
  77. package/src/services/prompts.js +23 -35
  78. package/src/services/security.js +135 -61
  79. package/src/services/shell.js +4 -4
  80. package/src/services/skills-sh.js +3 -9
  81. package/src/services/speckit.js +4 -7
  82. package/src/services/version-check.js +10 -10
  83. package/src/types.js +117 -0
  84. package/src/utils/aws-vault.js +18 -41
  85. package/src/utils/banner.js +5 -7
  86. package/src/utils/errors.js +42 -46
  87. package/src/utils/frontmatter.js +4 -4
  88. package/src/utils/gradient.js +18 -16
  89. package/src/utils/open-browser.js +3 -3
  90. package/src/utils/tui/form.js +1184 -0
  91. package/src/utils/tui/modal.js +15 -14
  92. package/src/utils/tui/navigable-table.js +16 -16
  93. package/src/utils/tui/tab-tui.js +1089 -0
  94. package/src/utils/typewriter.js +3 -3
  95. package/src/utils/welcome.js +18 -21
  96. package/src/validators/repo-name.js +2 -2
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk'
2
- import { NVD_ATTRIBUTION } from '../../services/nvd.js'
2
+ import {NVD_ATTRIBUTION} from '../../services/nvd.js'
3
3
 
4
4
  // ──────────────────────────────────────────────────────────────────────────────
5
5
  // ANSI escape sequences (re-declared locally — avoids cross-module coupling)
@@ -49,7 +49,7 @@ function centerText(text, width) {
49
49
  * @returns {string}
50
50
  */
51
51
  export function buildModalScreen(state) {
52
- const { modalContent, modalScrollOffset, termRows, termCols, firstRefUrl } = state
52
+ const {modalContent, modalScrollOffset, termRows, termCols, firstRefUrl} = state
53
53
 
54
54
  const lines = []
55
55
 
@@ -84,7 +84,9 @@ export function buildModalScreen(state) {
84
84
 
85
85
  // ── Footer ─────────────────────────────────────────────────────────────────
86
86
  lines.push(chalk.bold.cyan('╠' + '═'.repeat(innerWidth + 2) + '╣'))
87
- lines.push(chalk.bold.cyan('║ ') + chalk.dim(NVD_ATTRIBUTION).slice(0, innerWidth).padEnd(innerWidth) + chalk.bold.cyan(' ║'))
87
+ lines.push(
88
+ chalk.bold.cyan('║ ') + chalk.dim(NVD_ATTRIBUTION).slice(0, innerWidth).padEnd(innerWidth) + chalk.bold.cyan(' ║'),
89
+ )
88
90
 
89
91
  const scrollHint = content.length > contentViewport ? ' ↑↓/PgUp/PgDn scroll' : ''
90
92
  const openHint = firstRefUrl ? ' o open ref' : ''
@@ -159,8 +161,7 @@ export function buildErrorScreen(cveId, errorMessage, termRows, termCols) {
159
161
  lines.push(chalk.bold.cyan('║ ') + chalk.red.bold(centerText(titleText, innerWidth)) + chalk.bold.cyan(' ║'))
160
162
  lines.push(chalk.bold.cyan('║ ') + ' '.repeat(innerWidth) + chalk.bold.cyan(' ║'))
161
163
 
162
- const truncErr =
163
- errorMessage.length > innerWidth ? errorMessage.slice(0, innerWidth - 1) + '…' : errorMessage
164
+ const truncErr = errorMessage.length > innerWidth ? errorMessage.slice(0, innerWidth - 1) + '…' : errorMessage
164
165
  lines.push(chalk.bold.cyan('║ ') + chalk.red(truncErr.padEnd(innerWidth)) + chalk.bold.cyan(' ║'))
165
166
 
166
167
  const remaining = termRows - lines.length - 2
@@ -192,14 +193,14 @@ export function buildErrorScreen(cveId, errorMessage, termRows, termCols) {
192
193
  * }
193
194
  */
194
195
  export function handleModalKeypress(state, key) {
195
- const { modalContent, modalScrollOffset, termRows, firstRefUrl } = state
196
+ const {modalContent, modalScrollOffset, termRows, firstRefUrl} = state
196
197
 
197
- if (key.ctrl && key.name === 'c') return { exit: true }
198
- if (key.name === 'q') return { exit: true }
198
+ if (key.ctrl && key.name === 'c') return {exit: true}
199
+ if (key.name === 'q') return {exit: true}
199
200
 
200
- if (key.name === 'escape') return { backToTable: true }
201
+ if (key.name === 'escape') return {backToTable: true}
201
202
 
202
- if (key.name === 'o' && firstRefUrl) return { openUrl: firstRefUrl }
203
+ if (key.name === 'o' && firstRefUrl) return {openUrl: firstRefUrl}
203
204
 
204
205
  const contentLen = modalContent ? modalContent.length : 0
205
206
  const BORDER_LINES = 3
@@ -208,16 +209,16 @@ export function handleModalKeypress(state, key) {
208
209
  const maxOffset = Math.max(0, contentLen - contentViewport)
209
210
 
210
211
  if (key.name === 'up') {
211
- return { ...state, modalScrollOffset: clamp(modalScrollOffset - 1, 0, maxOffset) }
212
+ return {...state, modalScrollOffset: clamp(modalScrollOffset - 1, 0, maxOffset)}
212
213
  }
213
214
  if (key.name === 'down') {
214
- return { ...state, modalScrollOffset: clamp(modalScrollOffset + 1, 0, maxOffset) }
215
+ return {...state, modalScrollOffset: clamp(modalScrollOffset + 1, 0, maxOffset)}
215
216
  }
216
217
  if (key.name === 'pageup') {
217
- return { ...state, modalScrollOffset: clamp(modalScrollOffset - contentViewport, 0, maxOffset) }
218
+ return {...state, modalScrollOffset: clamp(modalScrollOffset - contentViewport, 0, maxOffset)}
218
219
  }
219
220
  if (key.name === 'pagedown') {
220
- return { ...state, modalScrollOffset: clamp(modalScrollOffset + contentViewport, 0, maxOffset) }
221
+ return {...state, modalScrollOffset: clamp(modalScrollOffset + contentViewport, 0, maxOffset)}
221
222
  }
222
223
 
223
224
  return state // unrecognized key — no state change
@@ -1,9 +1,9 @@
1
1
  import readline from 'node:readline'
2
2
  import chalk from 'chalk'
3
- import { NVD_ATTRIBUTION } from '../../services/nvd.js'
4
- import { buildModalScreen, buildLoadingScreen, buildErrorScreen, handleModalKeypress } from './modal.js'
5
- import { formatCveDetailPlain } from '../../formatters/vuln.js'
6
- import { openBrowser } from '../open-browser.js'
3
+ import {NVD_ATTRIBUTION} from '../../services/nvd.js'
4
+ import {buildModalScreen, buildLoadingScreen, buildErrorScreen, handleModalKeypress} from './modal.js'
5
+ import {formatCveDetailPlain} from '../../formatters/vuln.js'
6
+ import {openBrowser} from '../open-browser.js'
7
7
 
8
8
  // ──────────────────────────────────────────────────────────────────────────────
9
9
  // ANSI escape sequences
@@ -104,7 +104,7 @@ export function computeViewport(selectedIndex, totalRows, viewportHeight) {
104
104
  startIndex = Math.max(0, startIndex)
105
105
  startIndex = Math.min(Math.max(0, totalRows - viewportHeight), startIndex)
106
106
  const endIndex = Math.min(startIndex + viewportHeight, totalRows)
107
- return { startIndex, endIndex }
107
+ return {startIndex, endIndex}
108
108
  }
109
109
 
110
110
  // ──────────────────────────────────────────────────────────────────────────────
@@ -149,7 +149,7 @@ export function formatRow(row, columns, termCols, isSelected) {
149
149
  * @returns {string}
150
150
  */
151
151
  export function buildTableScreen(state) {
152
- const { rows, columns, heading, totalResults, selectedIndex, viewportHeight, termCols } = state
152
+ const {rows, columns, heading, totalResults, selectedIndex, viewportHeight, termCols} = state
153
153
  const lines = []
154
154
 
155
155
  // ── Header ────────────────────────────────────────────────────────────────
@@ -167,7 +167,7 @@ export function buildTableScreen(state) {
167
167
  lines.push(chalk.dim('─'.repeat(Math.min(termCols, dividerWidth))))
168
168
 
169
169
  // ── Data rows ─────────────────────────────────────────────────────────────
170
- const { startIndex, endIndex } = computeViewport(selectedIndex, rows.length, viewportHeight)
170
+ const {startIndex, endIndex} = computeViewport(selectedIndex, rows.length, viewportHeight)
171
171
  for (let i = startIndex; i < endIndex; i++) {
172
172
  lines.push(formatRow(rows[i], columns, termCols, i === selectedIndex))
173
173
  }
@@ -229,26 +229,26 @@ export function createInteractiveTableState(rows, columns, heading, totalResults
229
229
  * @returns {InteractiveTableState | { exit: true }}
230
230
  */
231
231
  export function handleTableKeypress(state, key) {
232
- const { selectedIndex, rows, viewportHeight } = state
232
+ const {selectedIndex, rows, viewportHeight} = state
233
233
 
234
- if (key.name === 'escape' || key.name === 'q') return { exit: true }
235
- if (key.ctrl && key.name === 'c') return { exit: true }
234
+ if (key.name === 'escape' || key.name === 'q') return {exit: true}
235
+ if (key.ctrl && key.name === 'c') return {exit: true}
236
236
 
237
237
  if (key.name === 'return') {
238
- return { ...state, currentView: 'modal' }
238
+ return {...state, currentView: 'modal'}
239
239
  }
240
240
 
241
241
  if (key.name === 'up') {
242
- return { ...state, selectedIndex: Math.max(0, selectedIndex - 1) }
242
+ return {...state, selectedIndex: Math.max(0, selectedIndex - 1)}
243
243
  }
244
244
  if (key.name === 'down') {
245
- return { ...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + 1) }
245
+ return {...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + 1)}
246
246
  }
247
247
  if (key.name === 'pageup') {
248
- return { ...state, selectedIndex: Math.max(0, selectedIndex - viewportHeight) }
248
+ return {...state, selectedIndex: Math.max(0, selectedIndex - viewportHeight)}
249
249
  }
250
250
  if (key.name === 'pagedown') {
251
- return { ...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + viewportHeight) }
251
+ return {...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + viewportHeight)}
252
252
  }
253
253
 
254
254
  return state // unrecognized key — no state change
@@ -370,7 +370,7 @@ export async function startInteractiveTable(rows, columns, heading, totalResults
370
370
  if (advisoryUrl) {
371
371
  await openBrowser(String(advisoryUrl))
372
372
  }
373
- state = { ...state, currentView: 'table' }
373
+ state = {...state, currentView: 'table'}
374
374
  process.stdout.write(buildTableScreen(state))
375
375
  return
376
376
  }