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,6 +1,6 @@
1
1
  import chalk from 'chalk'
2
- import { marked } from 'marked'
3
- import { renderTable } from './table.js'
2
+ import {marked} from 'marked'
3
+ import {renderTable} from './table.js'
4
4
 
5
5
  /** @import { Prompt, Skill, AwesomeEntry } from '../types.js' */
6
6
 
@@ -16,31 +16,28 @@ export function formatPromptTable(prompts) {
16
16
  return chalk.dim('No prompts found.')
17
17
  }
18
18
 
19
- return renderTable(
20
- /** @type {Record<string, unknown>[]} */ (prompts),
21
- [
22
- {
23
- header: 'Title',
24
- key: 'title',
25
- width: 36,
26
- colorize: (v) => chalk.hex('#FF9A5C')(v),
27
- },
28
- {
29
- header: 'Category',
30
- key: 'category',
31
- width: 16,
32
- format: (v) => v ?? '—',
33
- colorize: (v) => chalk.hex('#4A9EFF')(v),
34
- },
35
- {
36
- header: 'Description',
37
- key: 'description',
38
- width: 60,
39
- format: (v) => v ?? '—',
40
- colorize: (v) => chalk.white(v),
41
- },
42
- ],
43
- )
19
+ return renderTable(/** @type {Record<string, unknown>[]} */ (prompts), [
20
+ {
21
+ header: 'Title',
22
+ key: 'title',
23
+ width: 36,
24
+ colorize: (v) => chalk.hex('#FF9A5C')(v),
25
+ },
26
+ {
27
+ header: 'Category',
28
+ key: 'category',
29
+ width: 16,
30
+ format: (v) => v ?? '',
31
+ colorize: (v) => chalk.hex('#4A9EFF')(v),
32
+ },
33
+ {
34
+ header: 'Description',
35
+ key: 'description',
36
+ width: 60,
37
+ format: (v) => v ?? '',
38
+ colorize: (v) => chalk.white(v),
39
+ },
40
+ ])
44
41
  }
45
42
 
46
43
  /**
@@ -63,7 +60,7 @@ export function formatPromptBody(prompt) {
63
60
  .join('\n')
64
61
 
65
62
  // Render markdown to plain terminal text by stripping HTML tags from marked output
66
- const rendered = marked(prompt.body, { async: false })
63
+ const rendered = marked(prompt.body, {async: false})
67
64
  const plain = String(rendered)
68
65
  .replace(/<[^>]+>/g, '')
69
66
  .replace(/&amp;/g, '&')
@@ -91,31 +88,28 @@ export function formatSkillTable(skills) {
91
88
  return chalk.dim('No skills found.')
92
89
  }
93
90
 
94
- return renderTable(
95
- /** @type {Record<string, unknown>[]} */ (skills),
96
- [
97
- {
98
- header: 'Name',
99
- key: 'name',
100
- width: 36,
101
- colorize: (v) => chalk.hex('#FF9A5C')(v),
102
- },
103
- {
104
- header: 'Installs',
105
- key: 'installs',
106
- width: 10,
107
- format: (v) => (v != null ? String(v) : '—'),
108
- colorize: (v) => chalk.hex('#4A9EFF')(v),
109
- },
110
- {
111
- header: 'Description',
112
- key: 'description',
113
- width: 60,
114
- format: (v) => v ?? '—',
115
- colorize: (v) => chalk.white(v),
116
- },
117
- ],
118
- )
91
+ return renderTable(/** @type {Record<string, unknown>[]} */ (skills), [
92
+ {
93
+ header: 'Name',
94
+ key: 'name',
95
+ width: 36,
96
+ colorize: (v) => chalk.hex('#FF9A5C')(v),
97
+ },
98
+ {
99
+ header: 'Installs',
100
+ key: 'installs',
101
+ width: 10,
102
+ format: (v) => (v != null ? String(v) : ''),
103
+ colorize: (v) => chalk.hex('#4A9EFF')(v),
104
+ },
105
+ {
106
+ header: 'Description',
107
+ key: 'description',
108
+ width: 60,
109
+ format: (v) => v ?? '',
110
+ colorize: (v) => chalk.white(v),
111
+ },
112
+ ])
119
113
  }
120
114
 
121
115
  /**
@@ -131,29 +125,26 @@ export function formatAwesomeTable(entries, category) {
131
125
  return chalk.dim(category ? `No entries found for category "${category}".` : 'No entries found.')
132
126
  }
133
127
 
134
- return renderTable(
135
- /** @type {Record<string, unknown>[]} */ (entries),
136
- [
137
- {
138
- header: 'Name',
139
- key: 'name',
140
- width: 36,
141
- colorize: (v) => chalk.hex('#FF9A5C')(v),
142
- },
143
- {
144
- header: 'Category',
145
- key: 'category',
146
- width: 14,
147
- format: (v) => v ?? '—',
148
- colorize: (v) => chalk.hex('#4A9EFF')(v),
149
- },
150
- {
151
- header: 'Description',
152
- key: 'description',
153
- width: 58,
154
- format: (v) => v ?? '—',
155
- colorize: (v) => chalk.white(v),
156
- },
157
- ],
158
- )
128
+ return renderTable(/** @type {Record<string, unknown>[]} */ (entries), [
129
+ {
130
+ header: 'Name',
131
+ key: 'name',
132
+ width: 36,
133
+ colorize: (v) => chalk.hex('#FF9A5C')(v),
134
+ },
135
+ {
136
+ header: 'Category',
137
+ key: 'category',
138
+ width: 14,
139
+ format: (v) => v ?? '',
140
+ colorize: (v) => chalk.hex('#4A9EFF')(v),
141
+ },
142
+ {
143
+ header: 'Description',
144
+ key: 'description',
145
+ width: 58,
146
+ format: (v) => v ?? '',
147
+ colorize: (v) => chalk.white(v),
148
+ },
149
+ ])
159
150
  }
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk'
2
- import { deriveOverallStatus } from '../services/security.js'
2
+ import {deriveOverallStatus} from '../services/security.js'
3
3
 
4
4
  /** @import { SetupSession, SecurityToolStatus, PlatformInfo } from '../types.js' */
5
5
 
@@ -116,4 +116,4 @@ export function formatSecuritySummary(session, platformInfo) {
116
116
  * @param {SecurityToolStatus[]} tools
117
117
  * @returns {'success'|'partial'|'not-configured'}
118
118
  */
119
- export { deriveOverallStatus }
119
+ export {deriveOverallStatus}
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk'
2
- import { colorStatus } from './table.js'
2
+ import {colorStatus} from './table.js'
3
3
 
4
4
  /** @import { DoctorCheck } from '../types.js' */
5
5
 
@@ -51,9 +51,7 @@ export function renderTable(rows, columns) {
51
51
  })
52
52
 
53
53
  // Header row
54
- const header = columns
55
- .map((col, i) => chalk.bold.white(col.header.padEnd(widths[i])))
56
- .join(' ')
54
+ const header = columns.map((col, i) => chalk.bold.white(col.header.padEnd(widths[i]))).join(' ')
57
55
 
58
56
  // Divider
59
57
  const divider = chalk.dim(widths.map((w) => '─'.repeat(w)).join(' '))
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk'
2
- import { renderTable } from './table.js'
3
- import { NVD_ATTRIBUTION } from '../services/nvd.js'
2
+ import {renderTable} from './table.js'
3
+ import {NVD_ATTRIBUTION} from '../services/nvd.js'
4
4
 
5
5
  /** @import { CveSearchResult, CveDetail, VulnerabilityFinding, ScanResult } from '../types.js' */
6
6
 
@@ -11,11 +11,16 @@ import { NVD_ATTRIBUTION } from '../services/nvd.js'
11
11
  */
12
12
  export function colorSeverity(severity) {
13
13
  switch (severity) {
14
- case 'Critical': return chalk.red.bold(severity)
15
- case 'High': return chalk.red(severity)
16
- case 'Medium': return chalk.yellow(severity)
17
- case 'Low': return chalk.blue(severity)
18
- default: return chalk.gray(severity)
14
+ case 'Critical':
15
+ return chalk.red.bold(severity)
16
+ case 'High':
17
+ return chalk.red(severity)
18
+ case 'Medium':
19
+ return chalk.yellow(severity)
20
+ case 'Low':
21
+ return chalk.blue(severity)
22
+ default:
23
+ return chalk.gray(severity)
19
24
  }
20
25
  }
21
26
 
@@ -83,16 +88,21 @@ export function formatCveSearchTable(results, keyword, days, totalResults) {
83
88
  }))
84
89
 
85
90
  const table = renderTable(rows, [
86
- { header: 'CVE ID', key: 'id', colorize: (v) => chalk.cyan(v) },
87
- { header: 'Severity', key: 'severity', colorize: (v) => colorSeverity(v) },
88
- { header: 'Score', key: 'score', width: 5 },
89
- { header: 'Published', key: 'published', width: 10 },
90
- { header: 'Description', key: 'description', width: 90 },
91
- { header: 'Reference', key: 'reference', width: 45 },
91
+ {header: 'CVE ID', key: 'id', colorize: (v) => chalk.cyan(v)},
92
+ {header: 'Severity', key: 'severity', colorize: (v) => colorSeverity(v)},
93
+ {header: 'Score', key: 'score', width: 5},
94
+ {header: 'Published', key: 'published', width: 10},
95
+ {header: 'Description', key: 'description', width: 90},
96
+ {header: 'Reference', key: 'reference', width: 45},
92
97
  ])
93
98
 
94
99
  // Indent table by 2 spaces
95
- lines.push(table.split('\n').map((l) => ` ${l}`).join('\n'))
100
+ lines.push(
101
+ table
102
+ .split('\n')
103
+ .map((l) => ` ${l}`)
104
+ .join('\n'),
105
+ )
96
106
  lines.push('')
97
107
  lines.push(`Showing ${results.length} of ${totalResults} results.`)
98
108
  lines.push(chalk.dim(NVD_ATTRIBUTION))
@@ -250,14 +260,17 @@ export function formatFindingsTable(findings) {
250
260
  }))
251
261
 
252
262
  const table = renderTable(rows, [
253
- { header: 'Package', key: 'pkg', width: 20 },
254
- { header: 'Version', key: 'version', width: 12 },
255
- { header: 'Severity', key: 'severity', colorize: (v) => colorSeverity(v) },
256
- { header: 'CVE', key: 'cve', colorize: (v) => (v !== '—' ? chalk.cyan(v) : chalk.gray(v)) },
257
- { header: 'Title', key: 'title', width: 40 },
263
+ {header: 'Package', key: 'pkg', width: 20},
264
+ {header: 'Version', key: 'version', width: 12},
265
+ {header: 'Severity', key: 'severity', colorize: (v) => colorSeverity(v)},
266
+ {header: 'CVE', key: 'cve', colorize: (v) => (v !== '—' ? chalk.cyan(v) : chalk.gray(v))},
267
+ {header: 'Title', key: 'title', width: 40},
258
268
  ])
259
269
 
260
- return table.split('\n').map((l) => ` ${l}`).join('\n')
270
+ return table
271
+ .split('\n')
272
+ .map((l) => ` ${l}`)
273
+ .join('\n')
261
274
  }
262
275
 
263
276
  /**