devvami 1.4.1 → 1.5.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.
- package/README.md +7 -0
- package/oclif.manifest.json +41 -1
- package/package.json +2 -1
- package/src/commands/auth/login.js +20 -16
- package/src/commands/changelog.js +12 -12
- package/src/commands/costs/get.js +14 -24
- package/src/commands/costs/trend.js +13 -24
- package/src/commands/create/repo.js +72 -54
- package/src/commands/docs/list.js +29 -25
- package/src/commands/docs/projects.js +58 -24
- package/src/commands/docs/read.js +56 -39
- package/src/commands/docs/search.js +37 -25
- package/src/commands/doctor.js +37 -35
- package/src/commands/dotfiles/add.js +51 -39
- package/src/commands/dotfiles/setup.js +62 -33
- package/src/commands/dotfiles/status.js +18 -18
- package/src/commands/dotfiles/sync.js +62 -46
- package/src/commands/init.js +143 -132
- package/src/commands/logs/index.js +10 -16
- package/src/commands/open.js +12 -12
- package/src/commands/pipeline/logs.js +8 -11
- package/src/commands/pipeline/rerun.js +21 -16
- package/src/commands/pipeline/status.js +28 -24
- package/src/commands/pr/create.js +40 -27
- package/src/commands/pr/detail.js +9 -7
- package/src/commands/pr/review.js +18 -19
- package/src/commands/pr/status.js +27 -21
- package/src/commands/prompts/browse.js +15 -15
- package/src/commands/prompts/download.js +15 -16
- package/src/commands/prompts/install-speckit.js +11 -12
- package/src/commands/prompts/list.js +12 -12
- package/src/commands/prompts/run.js +16 -19
- package/src/commands/repo/list.js +57 -41
- package/src/commands/search.js +20 -18
- package/src/commands/security/setup.js +38 -34
- package/src/commands/sync-config-ai/index.js +143 -0
- package/src/commands/tasks/assigned.js +43 -33
- package/src/commands/tasks/list.js +43 -33
- package/src/commands/tasks/today.js +32 -30
- package/src/commands/upgrade.js +18 -17
- package/src/commands/vuln/detail.js +8 -8
- package/src/commands/vuln/scan.js +95 -21
- package/src/commands/vuln/search.js +23 -18
- package/src/commands/welcome.js +2 -2
- package/src/commands/whoami.js +19 -23
- package/src/formatters/ai-config.js +127 -0
- package/src/formatters/charts.js +6 -23
- package/src/formatters/cost.js +1 -7
- package/src/formatters/dotfiles.js +48 -19
- package/src/formatters/markdown.js +11 -6
- package/src/formatters/openapi.js +7 -9
- package/src/formatters/prompts.js +69 -78
- package/src/formatters/security.js +2 -2
- package/src/formatters/status.js +1 -1
- package/src/formatters/table.js +1 -3
- package/src/formatters/vuln.js +33 -20
- package/src/help.js +162 -164
- package/src/hooks/init.js +1 -3
- package/src/hooks/postrun.js +5 -7
- package/src/index.js +1 -1
- package/src/services/ai-config-store.js +318 -0
- package/src/services/ai-env-deployer.js +444 -0
- package/src/services/ai-env-scanner.js +242 -0
- package/src/services/audit-detector.js +2 -2
- package/src/services/audit-runner.js +40 -31
- package/src/services/auth.js +9 -9
- package/src/services/awesome-copilot.js +7 -4
- package/src/services/aws-costs.js +22 -22
- package/src/services/clickup.js +26 -26
- package/src/services/cloudwatch-logs.js +5 -9
- package/src/services/config.js +13 -13
- package/src/services/docs.js +19 -20
- package/src/services/dotfiles.js +149 -51
- package/src/services/github.js +22 -24
- package/src/services/nvd.js +21 -31
- package/src/services/platform.js +2 -2
- package/src/services/prompts.js +23 -35
- package/src/services/security.js +135 -61
- package/src/services/shell.js +4 -4
- package/src/services/skills-sh.js +3 -9
- package/src/services/speckit.js +4 -7
- package/src/services/version-check.js +10 -10
- package/src/types.js +85 -0
- package/src/utils/aws-vault.js +18 -41
- package/src/utils/banner.js +5 -7
- package/src/utils/errors.js +42 -46
- package/src/utils/frontmatter.js +4 -4
- package/src/utils/gradient.js +18 -16
- package/src/utils/open-browser.js +3 -3
- package/src/utils/tui/form.js +1006 -0
- package/src/utils/tui/modal.js +15 -14
- package/src/utils/tui/navigable-table.js +25 -17
- package/src/utils/tui/tab-tui.js +800 -0
- package/src/utils/typewriter.js +3 -3
- package/src/utils/welcome.js +18 -21
- package/src/validators/repo-name.js +2 -2
package/src/utils/tui/modal.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
-
import {
|
|
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 {
|
|
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(
|
|
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 {
|
|
196
|
+
const {modalContent, modalScrollOffset, termRows, firstRefUrl} = state
|
|
196
197
|
|
|
197
|
-
if (key.ctrl && key.name === 'c') return {
|
|
198
|
-
if (key.name === 'q') return {
|
|
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 {
|
|
201
|
+
if (key.name === 'escape') return {backToTable: true}
|
|
201
202
|
|
|
202
|
-
if (key.name === 'o' && firstRefUrl) return {
|
|
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 {
|
|
212
|
+
return {...state, modalScrollOffset: clamp(modalScrollOffset - 1, 0, maxOffset)}
|
|
212
213
|
}
|
|
213
214
|
if (key.name === 'down') {
|
|
214
|
-
return {
|
|
215
|
+
return {...state, modalScrollOffset: clamp(modalScrollOffset + 1, 0, maxOffset)}
|
|
215
216
|
}
|
|
216
217
|
if (key.name === 'pageup') {
|
|
217
|
-
return {
|
|
218
|
+
return {...state, modalScrollOffset: clamp(modalScrollOffset - contentViewport, 0, maxOffset)}
|
|
218
219
|
}
|
|
219
220
|
if (key.name === 'pagedown') {
|
|
220
|
-
return {
|
|
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 {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
232
|
+
const {selectedIndex, rows, viewportHeight} = state
|
|
233
233
|
|
|
234
|
-
if (key.name === 'escape' || key.name === 'q') return {
|
|
235
|
-
if (key.ctrl && key.name === 'c') return {
|
|
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 {
|
|
238
|
+
return {...state, currentView: 'modal'}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
if (key.name === 'up') {
|
|
242
|
-
return {
|
|
242
|
+
return {...state, selectedIndex: Math.max(0, selectedIndex - 1)}
|
|
243
243
|
}
|
|
244
244
|
if (key.name === 'down') {
|
|
245
|
-
return {
|
|
245
|
+
return {...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + 1)}
|
|
246
246
|
}
|
|
247
247
|
if (key.name === 'pageup') {
|
|
248
|
-
return {
|
|
248
|
+
return {...state, selectedIndex: Math.max(0, selectedIndex - viewportHeight)}
|
|
249
249
|
}
|
|
250
250
|
if (key.name === 'pagedown') {
|
|
251
|
-
return {
|
|
251
|
+
return {...state, selectedIndex: Math.min(rows.length - 1, selectedIndex + viewportHeight)}
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
return state // unrecognized key — no state change
|
|
@@ -360,9 +360,17 @@ export async function startInteractiveTable(rows, columns, heading, totalResults
|
|
|
360
360
|
* @returns {Promise<void>}
|
|
361
361
|
*/
|
|
362
362
|
async function openDetail() {
|
|
363
|
-
const
|
|
363
|
+
const row = state.rows[state.selectedIndex]
|
|
364
|
+
const cveId = row?.id
|
|
365
|
+
|
|
364
366
|
if (!cveId) {
|
|
365
|
-
|
|
367
|
+
// No CVE ID — check for an advisory URL (e.g. npm/pnpm advisory findings).
|
|
368
|
+
// Open it in the browser and stay in table view rather than showing a modal.
|
|
369
|
+
const advisoryUrl = row?.advisoryUrl
|
|
370
|
+
if (advisoryUrl) {
|
|
371
|
+
await openBrowser(String(advisoryUrl))
|
|
372
|
+
}
|
|
373
|
+
state = {...state, currentView: 'table'}
|
|
366
374
|
process.stdout.write(buildTableScreen(state))
|
|
367
375
|
return
|
|
368
376
|
}
|