@ariacode/cli 0.1.0 → 0.2.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.
- package/README.md +175 -4
- package/dist/actions/db-ask.d.ts +12 -0
- package/dist/actions/db-ask.js +130 -0
- package/dist/actions/db-ask.js.map +1 -0
- package/dist/actions/db-explain.d.ts +12 -0
- package/dist/actions/db-explain.js +123 -0
- package/dist/actions/db-explain.js.map +1 -0
- package/dist/actions/db-migrate.d.ts +13 -0
- package/dist/actions/db-migrate.js +124 -0
- package/dist/actions/db-migrate.js.map +1 -0
- package/dist/actions/db-schema.d.ts +11 -0
- package/dist/actions/db-schema.js +38 -0
- package/dist/actions/db-schema.js.map +1 -0
- package/dist/actions/upgrade-deps.d.ts +14 -0
- package/dist/actions/upgrade-deps.js +227 -0
- package/dist/actions/upgrade-deps.js.map +1 -0
- package/dist/actions/upgrade-prisma.d.ts +12 -0
- package/dist/actions/upgrade-prisma.js +177 -0
- package/dist/actions/upgrade-prisma.js.map +1 -0
- package/dist/actions.js +48 -13
- package/dist/actions.js.map +1 -1
- package/dist/agent.js +28 -9
- package/dist/agent.js.map +1 -1
- package/dist/cli.js +82 -0
- package/dist/cli.js.map +1 -1
- package/dist/db/client-usage.d.ts +19 -0
- package/dist/db/client-usage.js +107 -0
- package/dist/db/client-usage.js.map +1 -0
- package/dist/db/migrate.d.ts +26 -0
- package/dist/db/migrate.js +59 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/schema.d.ts +106 -0
- package/dist/db/schema.js +275 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/summary.d.ts +12 -0
- package/dist/db/summary.js +133 -0
- package/dist/db/summary.js.map +1 -0
- package/dist/fs-helpers.d.ts +19 -0
- package/dist/fs-helpers.js +92 -0
- package/dist/fs-helpers.js.map +1 -0
- package/dist/parser.d.ts +9 -0
- package/dist/parser.js +86 -0
- package/dist/parser.js.map +1 -1
- package/dist/prompt-loader.d.ts +9 -0
- package/dist/prompt-loader.js +26 -0
- package/dist/prompt-loader.js.map +1 -0
- package/dist/prompts/db_ask.md +39 -0
- package/dist/prompts/db_explain.md +43 -0
- package/dist/prompts/db_migrate.md +48 -0
- package/dist/prompts/upgrade_deps.md +23 -0
- package/dist/prompts/upgrade_prisma.md +28 -0
- package/dist/provider.d.ts +2 -0
- package/dist/provider.js +6 -35
- package/dist/provider.js.map +1 -1
- package/dist/storage.d.ts +11 -0
- package/dist/storage.js +36 -4
- package/dist/storage.js.map +1 -1
- package/dist/tools.d.ts +26 -0
- package/dist/tools.js +256 -8
- package/dist/tools.js.map +1 -1
- package/dist/upgrade/changelog.d.ts +21 -0
- package/dist/upgrade/changelog.js +62 -0
- package/dist/upgrade/changelog.js.map +1 -0
- package/dist/upgrade/classifier.d.ts +25 -0
- package/dist/upgrade/classifier.js +78 -0
- package/dist/upgrade/classifier.js.map +1 -0
- package/dist/upgrade/outdated.d.ts +17 -0
- package/dist/upgrade/outdated.js +138 -0
- package/dist/upgrade/outdated.js.map +1 -0
- package/dist/upgrade/prisma-upgrade.d.ts +20 -0
- package/dist/upgrade/prisma-upgrade.js +63 -0
- package/dist/upgrade/prisma-upgrade.js.map +1 -0
- package/package.json +7 -4
- package/dist/prompts/prompts/ask.md +0 -20
- package/dist/prompts/prompts/explore.md +0 -38
- package/dist/prompts/prompts/patch.md +0 -27
- package/dist/prompts/prompts/plan.md +0 -41
- package/dist/prompts/prompts/review.md +0 -33
package/README.md
CHANGED
|
@@ -6,12 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
[](./LICENSE)
|
|
9
|
-
[](https://github.com/ariacodeai/ariacode/actions)
|
|
10
9
|
[](https://www.npmjs.com/package/@ariacode/cli)
|
|
11
10
|
|
|
12
11
|
A predictable, terminal-native coding agent for Next.js, Nest.js, Prisma and Node.js projects.
|
|
13
12
|
|
|
14
|
-
Aria reads your repository, generates safe diffs with preview and tracks every mutation in a local SQLite history — no surprises.
|
|
13
|
+
Aria reads your repository, generates safe diffs with preview, understands your Prisma schema, upgrades dependencies with risk analysis, and tracks every mutation in a local SQLite history — no surprises.
|
|
15
14
|
|
|
16
15
|
## Requirements
|
|
17
16
|
|
|
@@ -48,6 +47,18 @@ aria review
|
|
|
48
47
|
# Explore an unfamiliar codebase
|
|
49
48
|
aria explore
|
|
50
49
|
|
|
50
|
+
# Prisma schema inspection (instant, no LLM)
|
|
51
|
+
aria db schema
|
|
52
|
+
|
|
53
|
+
# Ask about your database schema
|
|
54
|
+
aria db ask "users with more than 5 orders in the last 30 days"
|
|
55
|
+
|
|
56
|
+
# Upgrade outdated dependencies
|
|
57
|
+
aria upgrade deps
|
|
58
|
+
|
|
59
|
+
# Upgrade Prisma with migration guidance
|
|
60
|
+
aria upgrade prisma
|
|
61
|
+
|
|
51
62
|
# Check your environment
|
|
52
63
|
aria doctor
|
|
53
64
|
```
|
|
@@ -152,12 +163,169 @@ aria config init # Create ./.aria.toml with defaults
|
|
|
152
163
|
|
|
153
164
|
### `aria doctor`
|
|
154
165
|
|
|
155
|
-
Run environment diagnostics: Node.js version, git, ripgrep, config validity, history DB, provider API keys, and
|
|
166
|
+
Run environment diagnostics: Node.js version, git, ripgrep, config validity, history DB, provider API keys, project detection, and Prisma schema presence.
|
|
156
167
|
|
|
157
168
|
```
|
|
158
169
|
aria doctor [--format text|json]
|
|
159
170
|
```
|
|
160
171
|
|
|
172
|
+
### `aria db schema`
|
|
173
|
+
|
|
174
|
+
Parse and render `schema.prisma` content — models, fields, relations, enums, indexes. No LLM call, instant and free.
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
aria db schema [--json] [--model <name>]
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
| Flag | Description |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `--json` | Output raw `PrismaSchemaInfo` as JSON |
|
|
183
|
+
| `--model <name>` | Filter to a single model |
|
|
184
|
+
|
|
185
|
+
Example output:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
Prisma Schema: prisma/schema.prisma
|
|
189
|
+
Provider: postgresql
|
|
190
|
+
|
|
191
|
+
Models (3)
|
|
192
|
+
|
|
193
|
+
User
|
|
194
|
+
┌──────────────┬──────────┬──────────────────┐
|
|
195
|
+
│ Field │ Type │ Modifiers │
|
|
196
|
+
├──────────────┼──────────┼──────────────────┤
|
|
197
|
+
│ id │ String │ @id @default │
|
|
198
|
+
│ email │ String │ @unique │
|
|
199
|
+
│ createdAt │ DateTime │ @default(now()) │
|
|
200
|
+
│ orders │ Order[] │ relation │
|
|
201
|
+
└──────────────┴──────────┴──────────────────┘
|
|
202
|
+
|
|
203
|
+
Enums (1)
|
|
204
|
+
Role: ADMIN, USER, GUEST
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### `aria db ask <question>`
|
|
208
|
+
|
|
209
|
+
Q&A over your Prisma schema. Generates runnable Prisma Client code. Warns when queries touch sensitive fields (password, token, secret, apiKey).
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
aria db ask "<question>" [--session <id>] [--model <prisma-model>]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### `aria db explain <description>`
|
|
216
|
+
|
|
217
|
+
Analyze Prisma Client usage in your code. Identifies N+1 queries, missing indexes, over-fetching, and cartesian products. Suggests `@@index` additions and query improvements.
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
aria db explain "<description>" [--file <path>] [--session <id>]
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### `aria db migrate <description>`
|
|
224
|
+
|
|
225
|
+
Propose changes to `schema.prisma` with diff preview and confirmation. Prints manual `prisma migrate` commands — Aria never runs migrations.
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
aria db migrate "<description>" [--dry-run] [--yes] [--session <id>]
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| Flag | Description |
|
|
232
|
+
|------|-------------|
|
|
233
|
+
| `--dry-run` | Preview schema diff without writing |
|
|
234
|
+
| `--yes` | Skip confirmation prompt |
|
|
235
|
+
|
|
236
|
+
After a successful write:
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
✓ Schema updated: prisma/schema.prisma
|
|
240
|
+
|
|
241
|
+
To apply this migration, run:
|
|
242
|
+
|
|
243
|
+
Development:
|
|
244
|
+
pnpm prisma migrate dev --name <migration_name>
|
|
245
|
+
|
|
246
|
+
Production:
|
|
247
|
+
pnpm prisma migrate deploy
|
|
248
|
+
|
|
249
|
+
Aria does not run migrations automatically.
|
|
250
|
+
Review the generated SQL before applying to production.
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### `aria upgrade deps`
|
|
254
|
+
|
|
255
|
+
Analyze outdated dependencies, classify by semver risk, and propose upgrades to `package.json`. Supports npm, pnpm, yarn, and bun.
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
aria upgrade deps [--dry-run] [--yes] [--risk patch|minor|major|all] [--dev]
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
| Flag | Description |
|
|
262
|
+
|------|-------------|
|
|
263
|
+
| `--dry-run` | Preview upgrades without modifying `package.json` |
|
|
264
|
+
| `--yes` | Skip confirmation prompt |
|
|
265
|
+
| `--risk <level>` | Filter by risk: `patch`, `minor` (default — includes patch), `major`, `all` |
|
|
266
|
+
| `--dev` | Include devDependencies |
|
|
267
|
+
|
|
268
|
+
Behavior:
|
|
269
|
+
1. Detects your package manager from lockfile
|
|
270
|
+
2. Runs `{pm} outdated --json` (read-only)
|
|
271
|
+
3. Classifies each upgrade as patch / minor / major / prerelease
|
|
272
|
+
4. For major upgrades, uses LLM to summarize breaking changes
|
|
273
|
+
5. Shows a grouped table preview
|
|
274
|
+
6. On confirmation, updates `package.json` and prints install command
|
|
275
|
+
|
|
276
|
+
Aria never runs `npm install` / `pnpm install` / `yarn install` / `bun install`. You run it.
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
✓ Updated package.json with 12 dependency upgrades
|
|
280
|
+
|
|
281
|
+
To install the new versions, run:
|
|
282
|
+
pnpm install
|
|
283
|
+
|
|
284
|
+
Then verify:
|
|
285
|
+
pnpm test
|
|
286
|
+
pnpm run build
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### `aria upgrade prisma`
|
|
290
|
+
|
|
291
|
+
Prisma-specific upgrade with version detection and migration guidance for major upgrades.
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
aria upgrade prisma [--dry-run] [--yes]
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
| Flag | Description |
|
|
298
|
+
|------|-------------|
|
|
299
|
+
| `--dry-run` | Preview without modifying `package.json` |
|
|
300
|
+
| `--yes` | Skip confirmation prompt |
|
|
301
|
+
|
|
302
|
+
For major Prisma upgrades, the LLM analyzes your `schema.prisma` for patterns affected by breaking changes and provides project-specific migration steps.
|
|
303
|
+
|
|
304
|
+
After a successful upgrade:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
✓ Updated Prisma versions in package.json:
|
|
308
|
+
prisma: 5.22.0 → 6.1.0
|
|
309
|
+
@prisma/client: 5.22.0 → 6.1.0
|
|
310
|
+
|
|
311
|
+
Next steps (run in order):
|
|
312
|
+
|
|
313
|
+
1. Install updated dependencies:
|
|
314
|
+
pnpm install
|
|
315
|
+
|
|
316
|
+
2. Regenerate Prisma Client:
|
|
317
|
+
pnpm prisma generate
|
|
318
|
+
|
|
319
|
+
3. Review breaking changes:
|
|
320
|
+
https://github.com/prisma/prisma/releases/tag/6.1.0
|
|
321
|
+
|
|
322
|
+
4. Run your test suite:
|
|
323
|
+
pnpm test
|
|
324
|
+
|
|
325
|
+
Aria has updated package.json only.
|
|
326
|
+
Migration commands must be run manually.
|
|
327
|
+
```
|
|
328
|
+
|
|
161
329
|
## Configuration
|
|
162
330
|
|
|
163
331
|
Aria loads configuration from multiple sources in this precedence order (highest wins):
|
|
@@ -368,7 +536,7 @@ See the full model catalogue at [openrouter.ai/models](https://openrouter.ai/mod
|
|
|
368
536
|
| `2` | Invalid arguments |
|
|
369
537
|
| `3` | Configuration error |
|
|
370
538
|
| `4` | Provider error (e.g. missing API key) |
|
|
371
|
-
| `5` | Project detection error |
|
|
539
|
+
| `5` | Project detection error / Prisma not found |
|
|
372
540
|
| `130` | User cancelled (Ctrl+C or declined confirmation) |
|
|
373
541
|
|
|
374
542
|
## Session History
|
|
@@ -394,6 +562,9 @@ Sessions older than `retain_days` (default: 90) are cleaned up automatically.
|
|
|
394
562
|
- `.env` files and `node_modules` are excluded from directory listings by default
|
|
395
563
|
- API keys are never logged to the history database or terminal output
|
|
396
564
|
- All mutations require confirmation unless `--yes` is passed
|
|
565
|
+
- `aria db migrate` never executes `prisma migrate` — prints commands for user to run
|
|
566
|
+
- `aria upgrade deps` never runs `npm/pnpm/yarn/bun install` — modifies `package.json` only
|
|
567
|
+
- `aria upgrade prisma` never runs `prisma migrate` or install commands
|
|
397
568
|
|
|
398
569
|
## Contributing
|
|
399
570
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db ask — Q&A over Prisma schema, generates Prisma Client code.
|
|
3
|
+
* Forced read-only (plan mode). Never mutates.
|
|
4
|
+
*/
|
|
5
|
+
export interface DbAskOptions {
|
|
6
|
+
question: string;
|
|
7
|
+
session?: string;
|
|
8
|
+
model?: string;
|
|
9
|
+
quiet?: boolean;
|
|
10
|
+
projectRoot?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function runDbAsk(options: DbAskOptions): Promise<void>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db ask — Q&A over Prisma schema, generates Prisma Client code.
|
|
3
|
+
* Forced read-only (plan mode). Never mutates.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { dirname } from 'node:path';
|
|
10
|
+
import { getConfig } from '../config.js';
|
|
11
|
+
import { parsePrismaSchema } from '../db/schema.js';
|
|
12
|
+
import { renderSchemaSummary } from '../db/summary.js';
|
|
13
|
+
import { detectProjectType } from '../repo.js';
|
|
14
|
+
import { createProvider } from '../provider.js';
|
|
15
|
+
import { initializeDatabase, createSession, updateSessionStatus, logMessage } from '../storage.js';
|
|
16
|
+
import { readFileTool, searchCodeTool, readPrismaSchemaParserTool, findPrismaUsageTool, findModelReferencesTool, } from '../tools.js';
|
|
17
|
+
import { agentLoop, UserCancelledError } from '../agent.js';
|
|
18
|
+
import { initUI, info, error as uiError, yellow } from '../ui.js';
|
|
19
|
+
import { ConfirmCancelledError } from '../ui.js';
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const DB_ASK_TOOLS = [
|
|
22
|
+
readPrismaSchemaParserTool,
|
|
23
|
+
findPrismaUsageTool,
|
|
24
|
+
findModelReferencesTool,
|
|
25
|
+
readFileTool,
|
|
26
|
+
searchCodeTool,
|
|
27
|
+
];
|
|
28
|
+
const SENSITIVE_PATTERN = /password|token|secret|hash|apiKey|stripeCustomerId|ssn/i;
|
|
29
|
+
export async function runDbAsk(options) {
|
|
30
|
+
const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
|
|
31
|
+
const config = getConfig(projectRoot, { quiet: options.quiet });
|
|
32
|
+
initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
|
|
33
|
+
// Validate schema exists
|
|
34
|
+
const schemaInfo = parsePrismaSchema(projectRoot);
|
|
35
|
+
if (!schemaInfo) {
|
|
36
|
+
uiError('No schema.prisma found. aria db ask requires a Prisma project.');
|
|
37
|
+
process.exit(5);
|
|
38
|
+
}
|
|
39
|
+
const project = detectProjectType(projectRoot);
|
|
40
|
+
const db = initializeDatabase();
|
|
41
|
+
let sessionId;
|
|
42
|
+
if (options.session) {
|
|
43
|
+
// Validate session exists before resuming
|
|
44
|
+
const { getSession } = await import('../storage.js');
|
|
45
|
+
const existing = getSession(db, options.session);
|
|
46
|
+
if (!existing) {
|
|
47
|
+
uiError(`Session not found: ${options.session}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
sessionId = existing.id;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
sessionId = randomUUID();
|
|
54
|
+
createSession(db, {
|
|
55
|
+
id: sessionId,
|
|
56
|
+
command: 'db ask',
|
|
57
|
+
projectRoot,
|
|
58
|
+
provider: config.provider.default,
|
|
59
|
+
model: config.provider.model,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
let provider;
|
|
63
|
+
try {
|
|
64
|
+
provider = createProvider(config.provider.default);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
uiError(err instanceof Error ? err.message : String(err));
|
|
68
|
+
updateSessionStatus(db, sessionId, 'failed', String(err));
|
|
69
|
+
process.exit(4);
|
|
70
|
+
}
|
|
71
|
+
const ctx = {
|
|
72
|
+
projectRoot,
|
|
73
|
+
sessionId,
|
|
74
|
+
provider: config.provider.default,
|
|
75
|
+
model: config.provider.model,
|
|
76
|
+
mode: 'plan', // always read-only
|
|
77
|
+
dryRun: false,
|
|
78
|
+
assumeYes: false,
|
|
79
|
+
maxIterations: config.agent.maxIterations,
|
|
80
|
+
timeoutSeconds: config.agent.timeoutSeconds,
|
|
81
|
+
};
|
|
82
|
+
const schemaSummary = renderSchemaSummary(schemaInfo, false);
|
|
83
|
+
const systemPrompt = buildDbAskPrompt({
|
|
84
|
+
projectType: project.type,
|
|
85
|
+
schemaPath: schemaInfo.path,
|
|
86
|
+
datasourceProvider: schemaInfo.datasourceProvider ?? 'unknown',
|
|
87
|
+
schemaSummary,
|
|
88
|
+
templateDir: path.join(__dirname, '..', 'prompts'),
|
|
89
|
+
});
|
|
90
|
+
logMessage(db, sessionId, 'system', systemPrompt);
|
|
91
|
+
// Prepend sensitivity warning hint to question if relevant
|
|
92
|
+
let userRequest = options.question;
|
|
93
|
+
if (options.model) {
|
|
94
|
+
userRequest = `[Focus on model: ${options.model}]\n\n${userRequest}`;
|
|
95
|
+
}
|
|
96
|
+
if (SENSITIVE_PATTERN.test(options.question)) {
|
|
97
|
+
userRequest = `[NOTE: This question may involve sensitive fields. Add a WARNING above the code.]\n\n${userRequest}`;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await agentLoop(ctx, userRequest, DB_ASK_TOOLS, provider, config, 'db ask', db, systemPrompt);
|
|
101
|
+
updateSessionStatus(db, sessionId, 'completed');
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err instanceof UserCancelledError || err instanceof ConfirmCancelledError) {
|
|
105
|
+
info(yellow('Operation cancelled.'));
|
|
106
|
+
updateSessionStatus(db, sessionId, 'cancelled');
|
|
107
|
+
process.exit(130);
|
|
108
|
+
}
|
|
109
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
+
uiError(message);
|
|
111
|
+
updateSessionStatus(db, sessionId, 'failed', message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function buildDbAskPrompt(opts) {
|
|
116
|
+
const templatePath = path.join(opts.templateDir, 'db_ask.md');
|
|
117
|
+
let template;
|
|
118
|
+
try {
|
|
119
|
+
template = fs.readFileSync(templatePath, 'utf-8');
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
template = 'You are Aria Code\'s Prisma DB Assistant. Schema: {{schemaSummary}}';
|
|
123
|
+
}
|
|
124
|
+
return template
|
|
125
|
+
.replace(/\{\{projectType\}\}/g, opts.projectType)
|
|
126
|
+
.replace(/\{\{schemaPath\}\}/g, opts.schemaPath)
|
|
127
|
+
.replace(/\{\{datasourceProvider\}\}/g, opts.datasourceProvider)
|
|
128
|
+
.replace(/\{\{schemaSummary\}\}/g, () => opts.schemaSummary);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=db-ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-ask.js","sourceRoot":"","sources":["../../src/actions/db-ask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db explain — analyze Prisma Client usage, explain performance characteristics.
|
|
3
|
+
* Forced read-only (plan mode). Never mutates.
|
|
4
|
+
*/
|
|
5
|
+
export interface DbExplainOptions {
|
|
6
|
+
description: string;
|
|
7
|
+
file?: string;
|
|
8
|
+
session?: string;
|
|
9
|
+
quiet?: boolean;
|
|
10
|
+
projectRoot?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function runDbExplain(options: DbExplainOptions): Promise<void>;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db explain — analyze Prisma Client usage, explain performance characteristics.
|
|
3
|
+
* Forced read-only (plan mode). Never mutates.
|
|
4
|
+
*/
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import { fileURLToPath } from 'node:url';
|
|
9
|
+
import { dirname } from 'node:path';
|
|
10
|
+
import { getConfig } from '../config.js';
|
|
11
|
+
import { parsePrismaSchema } from '../db/schema.js';
|
|
12
|
+
import { renderSchemaSummary } from '../db/summary.js';
|
|
13
|
+
import { detectProjectType } from '../repo.js';
|
|
14
|
+
import { createProvider } from '../provider.js';
|
|
15
|
+
import { initializeDatabase, createSession, updateSessionStatus, logMessage } from '../storage.js';
|
|
16
|
+
import { readFileTool, searchCodeTool, readPrismaSchemaParserTool, findPrismaUsageTool, findModelReferencesTool, } from '../tools.js';
|
|
17
|
+
import { agentLoop, UserCancelledError } from '../agent.js';
|
|
18
|
+
import { initUI, info, error as uiError, yellow } from '../ui.js';
|
|
19
|
+
import { ConfirmCancelledError } from '../ui.js';
|
|
20
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const DB_EXPLAIN_TOOLS = [
|
|
22
|
+
readPrismaSchemaParserTool,
|
|
23
|
+
findPrismaUsageTool,
|
|
24
|
+
findModelReferencesTool,
|
|
25
|
+
readFileTool,
|
|
26
|
+
searchCodeTool,
|
|
27
|
+
];
|
|
28
|
+
export async function runDbExplain(options) {
|
|
29
|
+
const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
|
|
30
|
+
const config = getConfig(projectRoot, { quiet: options.quiet });
|
|
31
|
+
initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
|
|
32
|
+
const schemaInfo = parsePrismaSchema(projectRoot);
|
|
33
|
+
if (!schemaInfo) {
|
|
34
|
+
uiError('No schema.prisma found. aria db explain requires a Prisma project.');
|
|
35
|
+
process.exit(5);
|
|
36
|
+
}
|
|
37
|
+
const project = detectProjectType(projectRoot);
|
|
38
|
+
const db = initializeDatabase();
|
|
39
|
+
let sessionId;
|
|
40
|
+
if (options.session) {
|
|
41
|
+
const { getSession } = await import('../storage.js');
|
|
42
|
+
const existing = getSession(db, options.session);
|
|
43
|
+
if (!existing) {
|
|
44
|
+
uiError(`Session not found: ${options.session}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
sessionId = existing.id;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
sessionId = randomUUID();
|
|
51
|
+
createSession(db, {
|
|
52
|
+
id: sessionId,
|
|
53
|
+
command: 'db explain',
|
|
54
|
+
projectRoot,
|
|
55
|
+
provider: config.provider.default,
|
|
56
|
+
model: config.provider.model,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
let provider;
|
|
60
|
+
try {
|
|
61
|
+
provider = createProvider(config.provider.default);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
uiError(err instanceof Error ? err.message : String(err));
|
|
65
|
+
updateSessionStatus(db, sessionId, 'failed', String(err));
|
|
66
|
+
process.exit(4);
|
|
67
|
+
}
|
|
68
|
+
const ctx = {
|
|
69
|
+
projectRoot,
|
|
70
|
+
sessionId,
|
|
71
|
+
provider: config.provider.default,
|
|
72
|
+
model: config.provider.model,
|
|
73
|
+
mode: 'plan',
|
|
74
|
+
dryRun: false,
|
|
75
|
+
assumeYes: false,
|
|
76
|
+
maxIterations: config.agent.maxIterations,
|
|
77
|
+
timeoutSeconds: config.agent.timeoutSeconds,
|
|
78
|
+
};
|
|
79
|
+
const schemaSummary = renderSchemaSummary(schemaInfo, false);
|
|
80
|
+
const systemPrompt = buildDbExplainPrompt({
|
|
81
|
+
projectType: project.type,
|
|
82
|
+
schemaPath: schemaInfo.path,
|
|
83
|
+
datasourceProvider: schemaInfo.datasourceProvider ?? 'unknown',
|
|
84
|
+
schemaSummary,
|
|
85
|
+
templateDir: path.join(__dirname, '..', 'prompts'),
|
|
86
|
+
});
|
|
87
|
+
logMessage(db, sessionId, 'system', systemPrompt);
|
|
88
|
+
let userRequest = options.description;
|
|
89
|
+
if (options.file) {
|
|
90
|
+
userRequest = `[Focus on file: ${options.file}]\n\n${userRequest}`;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
await agentLoop(ctx, userRequest, DB_EXPLAIN_TOOLS, provider, config, 'db explain', db, systemPrompt);
|
|
94
|
+
updateSessionStatus(db, sessionId, 'completed');
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (err instanceof UserCancelledError || err instanceof ConfirmCancelledError) {
|
|
98
|
+
info(yellow('Operation cancelled.'));
|
|
99
|
+
updateSessionStatus(db, sessionId, 'cancelled');
|
|
100
|
+
process.exit(130);
|
|
101
|
+
}
|
|
102
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
103
|
+
uiError(message);
|
|
104
|
+
updateSessionStatus(db, sessionId, 'failed', message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function buildDbExplainPrompt(opts) {
|
|
109
|
+
const templatePath = path.join(opts.templateDir, 'db_explain.md');
|
|
110
|
+
let template;
|
|
111
|
+
try {
|
|
112
|
+
template = fs.readFileSync(templatePath, 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
template = 'You are Aria Code\'s Prisma query analyzer. Schema: {{schemaSummary}}';
|
|
116
|
+
}
|
|
117
|
+
return template
|
|
118
|
+
.replace(/\{\{projectType\}\}/g, opts.projectType)
|
|
119
|
+
.replace(/\{\{schemaPath\}\}/g, opts.schemaPath)
|
|
120
|
+
.replace(/\{\{datasourceProvider\}\}/g, opts.datasourceProvider)
|
|
121
|
+
.replace(/\{\{schemaSummary\}\}/g, () => opts.schemaSummary);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=db-explain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-explain.js","sourceRoot":"","sources":["../../src/actions/db-explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db migrate — propose changes to schema.prisma only.
|
|
3
|
+
* NEVER executes prisma migrate commands. User runs those manually.
|
|
4
|
+
*/
|
|
5
|
+
export interface DbMigrateOptions {
|
|
6
|
+
description: string;
|
|
7
|
+
dryRun?: boolean;
|
|
8
|
+
yes?: boolean;
|
|
9
|
+
session?: string;
|
|
10
|
+
quiet?: boolean;
|
|
11
|
+
projectRoot?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function runDbMigrate(options: DbMigrateOptions): Promise<void>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aria db migrate — propose changes to schema.prisma only.
|
|
3
|
+
* NEVER executes prisma migrate commands. User runs those manually.
|
|
4
|
+
*/
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import * as fs from 'node:fs';
|
|
7
|
+
import { getConfig } from '../config.js';
|
|
8
|
+
import { parsePrismaSchema, findSchemaPath } from '../db/schema.js';
|
|
9
|
+
import { manualMigrationInstructions } from '../db/migrate.js';
|
|
10
|
+
import { detectProjectType } from '../repo.js';
|
|
11
|
+
import { createProvider } from '../provider.js';
|
|
12
|
+
import { initializeDatabase, resolveOrCreateSession, updateSessionStatus, logMessage, logMutation } from '../storage.js';
|
|
13
|
+
import { validateFileSize } from '../safety.js';
|
|
14
|
+
import { readFileTool, searchCodeTool, readPrismaSchemaParserTool, findPrismaUsageTool, proposeSchemaChangeTool, applySchemaChangeTool, } from '../tools.js';
|
|
15
|
+
import { agentLoop, UserCancelledError } from '../agent.js';
|
|
16
|
+
import { initUI, info, error as uiError, yellow, green, bold, ConfirmCancelledError, } from '../ui.js';
|
|
17
|
+
import { loadPromptTemplate } from '../prompt-loader.js';
|
|
18
|
+
const DB_MIGRATE_TOOLS = [
|
|
19
|
+
readPrismaSchemaParserTool,
|
|
20
|
+
findPrismaUsageTool,
|
|
21
|
+
readFileTool,
|
|
22
|
+
searchCodeTool,
|
|
23
|
+
proposeSchemaChangeTool,
|
|
24
|
+
applySchemaChangeTool,
|
|
25
|
+
];
|
|
26
|
+
export async function runDbMigrate(options) {
|
|
27
|
+
const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
|
|
28
|
+
const config = getConfig(projectRoot, { quiet: options.quiet });
|
|
29
|
+
initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
|
|
30
|
+
const schemaInfo = parsePrismaSchema(projectRoot);
|
|
31
|
+
if (!schemaInfo) {
|
|
32
|
+
uiError('No schema.prisma found. aria db migrate requires a Prisma project.');
|
|
33
|
+
process.exit(5);
|
|
34
|
+
}
|
|
35
|
+
const schemaAbsPath = findSchemaPath(projectRoot);
|
|
36
|
+
if (!schemaAbsPath) {
|
|
37
|
+
uiError('Schema file disappeared between checks. Please try again.');
|
|
38
|
+
process.exit(5);
|
|
39
|
+
}
|
|
40
|
+
// Validate schema file size before reading
|
|
41
|
+
validateFileSize(schemaAbsPath, config.safety.maxFileSizeKb);
|
|
42
|
+
const schemaContent = fs.readFileSync(schemaAbsPath, 'utf-8');
|
|
43
|
+
const project = detectProjectType(projectRoot);
|
|
44
|
+
const db = initializeDatabase();
|
|
45
|
+
const sessionId = resolveOrCreateSession(db, {
|
|
46
|
+
sessionId: options.session,
|
|
47
|
+
command: 'db migrate',
|
|
48
|
+
projectRoot,
|
|
49
|
+
provider: config.provider.default,
|
|
50
|
+
model: config.provider.model,
|
|
51
|
+
});
|
|
52
|
+
let provider;
|
|
53
|
+
try {
|
|
54
|
+
provider = createProvider(config.provider.default);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
uiError(err instanceof Error ? err.message : String(err));
|
|
58
|
+
updateSessionStatus(db, sessionId, 'failed', String(err));
|
|
59
|
+
process.exit(4);
|
|
60
|
+
}
|
|
61
|
+
const ctx = {
|
|
62
|
+
projectRoot,
|
|
63
|
+
sessionId,
|
|
64
|
+
provider: config.provider.default,
|
|
65
|
+
model: config.provider.model,
|
|
66
|
+
mode: 'build',
|
|
67
|
+
dryRun: Boolean(options.dryRun),
|
|
68
|
+
assumeYes: Boolean(options.yes),
|
|
69
|
+
maxIterations: config.agent.maxIterations,
|
|
70
|
+
timeoutSeconds: config.agent.timeoutSeconds,
|
|
71
|
+
};
|
|
72
|
+
const systemPrompt = buildDbMigratePrompt({
|
|
73
|
+
projectType: project.type,
|
|
74
|
+
schemaPath: schemaInfo.path,
|
|
75
|
+
datasourceProvider: schemaInfo.datasourceProvider ?? 'unknown',
|
|
76
|
+
schemaContent,
|
|
77
|
+
});
|
|
78
|
+
logMessage(db, sessionId, 'system', systemPrompt);
|
|
79
|
+
if (options.dryRun) {
|
|
80
|
+
info(bold('Dry-run mode — schema.prisma will not be modified.'));
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
await agentLoop(ctx, options.description, DB_MIGRATE_TOOLS, provider, config, 'db migrate', db, systemPrompt);
|
|
84
|
+
if (!options.dryRun) {
|
|
85
|
+
// Log the mutation
|
|
86
|
+
logMutation(db, sessionId, {
|
|
87
|
+
action: 'db_migrate_schema',
|
|
88
|
+
affectedFiles: [schemaInfo.path],
|
|
89
|
+
riskLevel: 'high',
|
|
90
|
+
reversible: true,
|
|
91
|
+
rollbackHints: [`git checkout -- ${schemaInfo.path}`],
|
|
92
|
+
});
|
|
93
|
+
info('');
|
|
94
|
+
info(green(`✓ Schema updated: ${schemaInfo.path}`));
|
|
95
|
+
info(manualMigrationInstructions(project.packageManager ?? 'npx'));
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
info('');
|
|
99
|
+
info(yellow('Dry-run complete — schema.prisma was not modified.'));
|
|
100
|
+
}
|
|
101
|
+
updateSessionStatus(db, sessionId, 'completed');
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err instanceof UserCancelledError || err instanceof ConfirmCancelledError) {
|
|
105
|
+
info(yellow('Operation cancelled.'));
|
|
106
|
+
updateSessionStatus(db, sessionId, 'cancelled');
|
|
107
|
+
process.exit(130);
|
|
108
|
+
}
|
|
109
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
+
uiError(message);
|
|
111
|
+
updateSessionStatus(db, sessionId, 'failed', message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function buildDbMigratePrompt(opts) {
|
|
116
|
+
const template = loadPromptTemplate('db_migrate', 'You are Aria Code\'s schema migration assistant. Current schema:\n\n{{schemaContent}}');
|
|
117
|
+
// Use function replacer for schemaContent to avoid $& / $1 injection from schema text
|
|
118
|
+
return template
|
|
119
|
+
.replace(/\{\{projectType\}\}/g, opts.projectType)
|
|
120
|
+
.replace(/\{\{schemaPath\}\}/g, opts.schemaPath)
|
|
121
|
+
.replace(/\{\{datasourceProvider\}\}/g, opts.datasourceProvider)
|
|
122
|
+
.replace(/\{\{schemaContent\}\}/g, () => opts.schemaContent);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=db-migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db-migrate.js","sourceRoot":"","sources":["../../src/actions/db-migrate.ts"],"names":[],"mappings":"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"}
|