@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.
Files changed (78) hide show
  1. package/README.md +175 -4
  2. package/dist/actions/db-ask.d.ts +12 -0
  3. package/dist/actions/db-ask.js +130 -0
  4. package/dist/actions/db-ask.js.map +1 -0
  5. package/dist/actions/db-explain.d.ts +12 -0
  6. package/dist/actions/db-explain.js +123 -0
  7. package/dist/actions/db-explain.js.map +1 -0
  8. package/dist/actions/db-migrate.d.ts +13 -0
  9. package/dist/actions/db-migrate.js +124 -0
  10. package/dist/actions/db-migrate.js.map +1 -0
  11. package/dist/actions/db-schema.d.ts +11 -0
  12. package/dist/actions/db-schema.js +38 -0
  13. package/dist/actions/db-schema.js.map +1 -0
  14. package/dist/actions/upgrade-deps.d.ts +14 -0
  15. package/dist/actions/upgrade-deps.js +227 -0
  16. package/dist/actions/upgrade-deps.js.map +1 -0
  17. package/dist/actions/upgrade-prisma.d.ts +12 -0
  18. package/dist/actions/upgrade-prisma.js +177 -0
  19. package/dist/actions/upgrade-prisma.js.map +1 -0
  20. package/dist/actions.js +48 -13
  21. package/dist/actions.js.map +1 -1
  22. package/dist/agent.js +28 -9
  23. package/dist/agent.js.map +1 -1
  24. package/dist/cli.js +82 -0
  25. package/dist/cli.js.map +1 -1
  26. package/dist/db/client-usage.d.ts +19 -0
  27. package/dist/db/client-usage.js +107 -0
  28. package/dist/db/client-usage.js.map +1 -0
  29. package/dist/db/migrate.d.ts +26 -0
  30. package/dist/db/migrate.js +59 -0
  31. package/dist/db/migrate.js.map +1 -0
  32. package/dist/db/schema.d.ts +106 -0
  33. package/dist/db/schema.js +275 -0
  34. package/dist/db/schema.js.map +1 -0
  35. package/dist/db/summary.d.ts +12 -0
  36. package/dist/db/summary.js +133 -0
  37. package/dist/db/summary.js.map +1 -0
  38. package/dist/fs-helpers.d.ts +19 -0
  39. package/dist/fs-helpers.js +92 -0
  40. package/dist/fs-helpers.js.map +1 -0
  41. package/dist/parser.d.ts +9 -0
  42. package/dist/parser.js +86 -0
  43. package/dist/parser.js.map +1 -1
  44. package/dist/prompt-loader.d.ts +9 -0
  45. package/dist/prompt-loader.js +26 -0
  46. package/dist/prompt-loader.js.map +1 -0
  47. package/dist/prompts/db_ask.md +39 -0
  48. package/dist/prompts/db_explain.md +43 -0
  49. package/dist/prompts/db_migrate.md +48 -0
  50. package/dist/prompts/upgrade_deps.md +23 -0
  51. package/dist/prompts/upgrade_prisma.md +28 -0
  52. package/dist/provider.d.ts +2 -0
  53. package/dist/provider.js +6 -35
  54. package/dist/provider.js.map +1 -1
  55. package/dist/storage.d.ts +11 -0
  56. package/dist/storage.js +36 -4
  57. package/dist/storage.js.map +1 -1
  58. package/dist/tools.d.ts +26 -0
  59. package/dist/tools.js +256 -8
  60. package/dist/tools.js.map +1 -1
  61. package/dist/upgrade/changelog.d.ts +21 -0
  62. package/dist/upgrade/changelog.js +62 -0
  63. package/dist/upgrade/changelog.js.map +1 -0
  64. package/dist/upgrade/classifier.d.ts +25 -0
  65. package/dist/upgrade/classifier.js +78 -0
  66. package/dist/upgrade/classifier.js.map +1 -0
  67. package/dist/upgrade/outdated.d.ts +17 -0
  68. package/dist/upgrade/outdated.js +138 -0
  69. package/dist/upgrade/outdated.js.map +1 -0
  70. package/dist/upgrade/prisma-upgrade.d.ts +20 -0
  71. package/dist/upgrade/prisma-upgrade.js +63 -0
  72. package/dist/upgrade/prisma-upgrade.js.map +1 -0
  73. package/package.json +7 -4
  74. package/dist/prompts/prompts/ask.md +0 -20
  75. package/dist/prompts/prompts/explore.md +0 -38
  76. package/dist/prompts/prompts/patch.md +0 -27
  77. package/dist/prompts/prompts/plan.md +0 -41
  78. package/dist/prompts/prompts/review.md +0 -33
@@ -0,0 +1,11 @@
1
+ /**
2
+ * aria db schema — parse and render schema.prisma content.
3
+ * No LLM call: pure parsing + rendering. Instant and free.
4
+ */
5
+ export interface DbSchemaOptions {
6
+ json?: boolean;
7
+ model?: string;
8
+ quiet?: boolean;
9
+ projectRoot?: string;
10
+ }
11
+ export declare function runDbSchema(options: DbSchemaOptions): Promise<void>;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * aria db schema — parse and render schema.prisma content.
3
+ * No LLM call: pure parsing + rendering. Instant and free.
4
+ */
5
+ import { parsePrismaSchema } from '../db/schema.js';
6
+ import { renderSchemaSummary, renderModelSummary } from '../db/summary.js';
7
+ import { initUI, info, error as uiError } from '../ui.js';
8
+ import { getConfig } from '../config.js';
9
+ import * as path from 'node:path';
10
+ export async function runDbSchema(options) {
11
+ const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
12
+ const config = getConfig(projectRoot, { quiet: options.quiet });
13
+ initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
14
+ const schemaInfo = parsePrismaSchema(projectRoot);
15
+ if (!schemaInfo) {
16
+ uiError('No schema.prisma found in project. Run `prisma init` to create one.');
17
+ process.exit(5);
18
+ }
19
+ // --json: output raw JSON
20
+ if (options.json) {
21
+ process.stdout.write(JSON.stringify(schemaInfo, null, 2) + '\n');
22
+ return;
23
+ }
24
+ // --model <name>: filter to single model
25
+ if (options.model) {
26
+ const model = schemaInfo.models.find((m) => m.name.toLowerCase() === options.model.toLowerCase());
27
+ if (!model) {
28
+ uiError(`Model "${options.model}" not found in schema. Available: ${schemaInfo.models.map((m) => m.name).join(', ')}`);
29
+ process.exit(2);
30
+ }
31
+ const colorEnabled = config.ui.color !== 'never';
32
+ info(renderModelSummary(model, colorEnabled));
33
+ return;
34
+ }
35
+ const colorEnabled = config.ui.color !== 'never';
36
+ info(renderSchemaSummary(schemaInfo, colorEnabled));
37
+ }
38
+ //# sourceMappingURL=db-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-schema.js","sourceRoot":"","sources":["../../src/actions/db-schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AASlC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAwB;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IAEnE,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,CAAC,qEAAqE,CAAC,CAAC;QAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0BAA0B;IAC1B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,KAAM,CAAC,WAAW,EAAE,CAC7D,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,UAAU,OAAO,CAAC,KAAK,qCAAqC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,OAAO,CAAC;QACjD,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,OAAO,CAAC;IACjD,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * aria upgrade deps — analyze outdated dependencies, propose upgrades grouped by risk.
3
+ * Modifies package.json only. Never runs install commands.
4
+ */
5
+ export interface UpgradeDepsOptions {
6
+ dryRun?: boolean;
7
+ yes?: boolean;
8
+ risk?: 'patch' | 'minor' | 'major' | 'all';
9
+ dev?: boolean;
10
+ session?: string;
11
+ quiet?: boolean;
12
+ projectRoot?: string;
13
+ }
14
+ export declare function runUpgradeDeps(options: UpgradeDepsOptions): Promise<void>;
@@ -0,0 +1,227 @@
1
+ /**
2
+ * aria upgrade deps — analyze outdated dependencies, propose upgrades grouped by risk.
3
+ * Modifies package.json only. Never runs install commands.
4
+ */
5
+ import * as path from 'node:path';
6
+ import { getConfig } from '../config.js';
7
+ import { detectProjectType } from '../repo.js';
8
+ import { createProvider } from '../provider.js';
9
+ import { initializeDatabase, resolveOrCreateSession, updateSessionStatus, logMessage, logMutation, } from '../storage.js';
10
+ import { initUI, info, success, warn, error as uiError, bold, dim, green, yellow, red, cyan, printTable, confirm, ConfirmCancelledError, createSpinner, } from '../ui.js';
11
+ import { getOutdatedPackages } from '../upgrade/outdated.js';
12
+ import { classifyAll, } from '../upgrade/classifier.js';
13
+ import { fetchChangelogInfo } from '../upgrade/changelog.js';
14
+ import { readJsonFile, writeFileAtomic } from '../fs-helpers.js';
15
+ import { loadPromptTemplate } from '../prompt-loader.js';
16
+ export async function runUpgradeDeps(options) {
17
+ const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
18
+ const config = getConfig(projectRoot, { quiet: options.quiet });
19
+ initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
20
+ const project = detectProjectType(projectRoot);
21
+ const pm = project.packageManager ?? 'npm';
22
+ // 1. Fetch outdated packages
23
+ const spinner = createSpinner('Checking for outdated packages...');
24
+ spinner.start();
25
+ let outdated;
26
+ try {
27
+ outdated = await getOutdatedPackages(projectRoot, pm);
28
+ }
29
+ catch (err) {
30
+ spinner.fail('Failed to check outdated packages');
31
+ uiError(err instanceof Error ? err.message : String(err));
32
+ process.exit(1);
33
+ }
34
+ if (outdated.length === 0) {
35
+ spinner.succeed('All dependencies up to date');
36
+ return;
37
+ }
38
+ spinner.succeed(`Found ${outdated.length} outdated package(s)`);
39
+ // 2. Classify by risk
40
+ const classified = classifyAll(outdated);
41
+ // 3. Filter by --risk flag (default: patch + minor)
42
+ const riskFilter = options.risk ?? 'minor';
43
+ const filtered = filterByRisk(classified, riskFilter);
44
+ if (filtered.length === 0) {
45
+ info(`No upgrades matching risk level "${riskFilter}". Use --risk all to see everything.`);
46
+ return;
47
+ }
48
+ // 4. Render upgrade preview table
49
+ renderUpgradeTable(filtered);
50
+ // 5. For major upgrades, use LLM to summarize breaking changes
51
+ const majors = filtered.filter((u) => u.risk === 'major');
52
+ if (majors.length > 0) {
53
+ await summarizeMajorUpgrades(majors, project.type, projectRoot, config);
54
+ }
55
+ // 6. Build MutationSummary
56
+ const highestRisk = getHighestRisk(filtered);
57
+ const summary = {
58
+ action: 'upgrade_deps',
59
+ affectedFiles: ['package.json'],
60
+ commandsToRun: [`${pm} install`],
61
+ migrations: [],
62
+ riskLevel: riskToLevel(highestRisk),
63
+ reversible: true,
64
+ rollbackHints: ['git checkout -- package.json', `${pm} install`],
65
+ };
66
+ info('');
67
+ info(dim(`Risk: ${summary.riskLevel} | Files: package.json | Reversible: yes`));
68
+ // 7. Handle dry-run / confirmation
69
+ if (options.dryRun) {
70
+ warn('Dry-run mode — package.json will not be modified.');
71
+ return;
72
+ }
73
+ if (!options.yes) {
74
+ const ok = await confirm(`Apply ${filtered.length} upgrade(s) to package.json?`);
75
+ if (!ok)
76
+ throw new ConfirmCancelledError();
77
+ }
78
+ // 8. Apply changes to package.json (atomic write)
79
+ applyUpgrades(projectRoot, filtered);
80
+ // 9. Log mutation (with session existence check)
81
+ const db = initializeDatabase();
82
+ const sessionId = resolveOrCreateSession(db, {
83
+ sessionId: options.session,
84
+ command: 'upgrade deps',
85
+ projectRoot,
86
+ provider: config.provider.default,
87
+ model: config.provider.model,
88
+ });
89
+ logMutation(db, sessionId, {
90
+ action: 'upgrade_deps',
91
+ affectedFiles: ['package.json'],
92
+ riskLevel: riskToLevel(highestRisk),
93
+ reversible: true,
94
+ rollbackHints: ['git checkout -- package.json', `${pm} install`],
95
+ });
96
+ updateSessionStatus(db, sessionId, 'completed');
97
+ // 10. Print next steps
98
+ info('');
99
+ success(`Updated package.json with ${filtered.length} dependency upgrade(s)`);
100
+ info('');
101
+ info('To install the new versions, run:');
102
+ info(` ${pm} install`);
103
+ info('');
104
+ info('Then verify:');
105
+ info(` ${pm} test`);
106
+ info(` ${pm} run build`);
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Helpers
110
+ // ---------------------------------------------------------------------------
111
+ function filterByRisk(upgrades, risk) {
112
+ switch (risk) {
113
+ case 'patch':
114
+ return upgrades.filter((u) => u.risk === 'patch');
115
+ case 'minor':
116
+ return upgrades.filter((u) => u.risk === 'patch' || u.risk === 'minor');
117
+ case 'major':
118
+ case 'all':
119
+ return upgrades;
120
+ default:
121
+ return upgrades.filter((u) => u.risk === 'patch' || u.risk === 'minor');
122
+ }
123
+ }
124
+ function renderUpgradeTable(upgrades) {
125
+ const riskColor = (risk) => {
126
+ switch (risk) {
127
+ case 'patch':
128
+ return green(risk);
129
+ case 'minor':
130
+ return yellow(risk);
131
+ case 'major':
132
+ return red(risk);
133
+ case 'prerelease':
134
+ return cyan(risk);
135
+ }
136
+ };
137
+ info('');
138
+ info(bold('Dependency Upgrades:'));
139
+ printTable({
140
+ head: ['Package', 'Current', 'Target', 'Risk', 'Type'],
141
+ colWidths: [30, 12, 12, 14, 18],
142
+ }, upgrades.map((u) => [u.name, u.current, u.target, riskColor(u.risk), u.type]));
143
+ }
144
+ function getHighestRisk(upgrades) {
145
+ if (upgrades.some((u) => u.risk === 'major'))
146
+ return 'major';
147
+ if (upgrades.some((u) => u.risk === 'minor'))
148
+ return 'minor';
149
+ if (upgrades.some((u) => u.risk === 'prerelease'))
150
+ return 'prerelease';
151
+ return 'patch';
152
+ }
153
+ function riskToLevel(risk) {
154
+ switch (risk) {
155
+ case 'major':
156
+ return 'high';
157
+ case 'minor':
158
+ case 'prerelease':
159
+ return 'medium';
160
+ case 'patch':
161
+ return 'low';
162
+ }
163
+ }
164
+ /**
165
+ * Modify package.json in-place (atomic write), updating version ranges for each upgrade.
166
+ */
167
+ function applyUpgrades(projectRoot, upgrades) {
168
+ const pkgPath = path.join(projectRoot, 'package.json');
169
+ const pkg = readJsonFile(pkgPath);
170
+ for (const u of upgrades) {
171
+ const section = pkg[u.type];
172
+ if (section && section[u.name] !== undefined) {
173
+ const existing = section[u.name];
174
+ const prefix = existing.match(/^[\^~>=<]+/)?.[0] ?? '^';
175
+ section[u.name] = `${prefix}${u.target}`;
176
+ }
177
+ }
178
+ writeFileAtomic(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
179
+ }
180
+ /**
181
+ * Use LLM to summarize breaking changes for major upgrades.
182
+ */
183
+ async function summarizeMajorUpgrades(majors, projectType, projectRoot, config) {
184
+ const changelogInfos = await fetchChangelogInfo(majors.map((m) => ({ name: m.name, current: m.current, target: m.target })));
185
+ const majorSummary = majors
186
+ .map((m) => {
187
+ const cl = changelogInfos.find((c) => c.name === m.name);
188
+ const repoLine = cl?.releaseNotesUrl ? ` Release notes: ${cl.releaseNotesUrl}` : '';
189
+ return `- ${m.name}: ${m.current} → ${m.target}${repoLine}`;
190
+ })
191
+ .join('\n');
192
+ const template = loadPromptTemplate('upgrade_deps', 'Summarize breaking changes for:\n{{ major_upgrades }}');
193
+ const systemPrompt = template
194
+ .replace(/\{\{ major_upgrades \}\}/g, majorSummary)
195
+ .replace(/\{\{ project_type \}\}/g, projectType);
196
+ info('');
197
+ info(bold('Major upgrade analysis:'));
198
+ try {
199
+ const provider = createProvider(config.provider.default);
200
+ const db = initializeDatabase();
201
+ const sessionId = resolveOrCreateSession(db, {
202
+ command: 'upgrade deps analysis',
203
+ projectRoot,
204
+ provider: config.provider.default,
205
+ model: config.provider.model,
206
+ });
207
+ logMessage(db, sessionId, 'system', systemPrompt);
208
+ // Use provider.chat directly instead of agentLoop with empty tools —
209
+ // no tools needed for changelog summarization, avoids wasted tokens.
210
+ const response = await provider.chat([
211
+ { role: 'system', content: systemPrompt },
212
+ {
213
+ role: 'user',
214
+ content: `Analyze these major dependency upgrades and summarize breaking changes:\n${majorSummary}`,
215
+ },
216
+ ], [], { model: config.provider.model, maxTokens: config.provider.maxTokens });
217
+ if (response.content) {
218
+ info(response.content);
219
+ }
220
+ logMessage(db, sessionId, 'assistant', response.content);
221
+ updateSessionStatus(db, sessionId, 'completed');
222
+ }
223
+ catch {
224
+ warn('Could not generate AI analysis for major upgrades. Proceeding without it.');
225
+ }
226
+ }
227
+ //# sourceMappingURL=upgrade-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-deps.js","sourceRoot":"","sources":["../../src/actions/upgrade-deps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * aria upgrade prisma — Prisma-specific upgrade with migration guidance.
3
+ * Updates package.json only. Never runs install or migrate commands.
4
+ */
5
+ export interface UpgradePrismaOptions {
6
+ dryRun?: boolean;
7
+ yes?: boolean;
8
+ session?: string;
9
+ quiet?: boolean;
10
+ projectRoot?: string;
11
+ }
12
+ export declare function runUpgradePrisma(options: UpgradePrismaOptions): Promise<void>;
@@ -0,0 +1,177 @@
1
+ /**
2
+ * aria upgrade prisma — Prisma-specific upgrade with migration guidance.
3
+ * Updates package.json only. Never runs install or migrate commands.
4
+ */
5
+ import * as path from 'node:path';
6
+ import { getConfig } from '../config.js';
7
+ import { detectProjectType } from '../repo.js';
8
+ import { parsePrismaSchema } from '../db/schema.js';
9
+ import { createProvider } from '../provider.js';
10
+ import { initializeDatabase, resolveOrCreateSession, updateSessionStatus, logMessage, logMutation, } from '../storage.js';
11
+ import { initUI, info, success, warn, error as uiError, bold, dim, confirm, ConfirmCancelledError, createSpinner, } from '../ui.js';
12
+ import { getPrismaVersionInfo } from '../upgrade/prisma-upgrade.js';
13
+ import { readJsonFile, writeFileAtomic } from '../fs-helpers.js';
14
+ import { loadPromptTemplate } from '../prompt-loader.js';
15
+ export async function runUpgradePrisma(options) {
16
+ const projectRoot = path.resolve(options.projectRoot ?? process.cwd());
17
+ const config = getConfig(projectRoot, { quiet: options.quiet });
18
+ initUI(config.ui.color, config.ui.quiet || Boolean(options.quiet));
19
+ const project = detectProjectType(projectRoot);
20
+ const pm = project.packageManager ?? 'npm';
21
+ // 1. Check if project has Prisma
22
+ const versionInfo = await getPrismaVersionInfo(projectRoot);
23
+ if (!versionInfo.hasPrisma) {
24
+ uiError('Prisma not detected in this project');
25
+ process.exit(5);
26
+ }
27
+ const current = versionInfo.currentPrisma || versionInfo.currentClient;
28
+ if (!current) {
29
+ uiError('Could not determine current Prisma version from package.json');
30
+ process.exit(5);
31
+ }
32
+ // 2. Fetch latest version
33
+ const spinner = createSpinner('Checking latest Prisma version...');
34
+ spinner.start();
35
+ if (!versionInfo.latestVersion) {
36
+ spinner.fail('Could not fetch latest Prisma version');
37
+ process.exit(1);
38
+ }
39
+ if (current === versionInfo.latestVersion) {
40
+ spinner.succeed(`Prisma is up to date (${current})`);
41
+ return;
42
+ }
43
+ spinner.succeed(`Prisma upgrade available: ${current} → ${versionInfo.latestVersion} (${versionInfo.risk})`);
44
+ // 3. For major upgrades, use LLM for migration guidance
45
+ const affectedFiles = ['package.json'];
46
+ if (versionInfo.risk === 'major' && project.prismaSchemaPath) {
47
+ affectedFiles.push(project.prismaSchemaPath);
48
+ await generateMigrationGuidance(current, versionInfo.latestVersion, projectRoot, config);
49
+ }
50
+ // 4. Show risk info
51
+ info('');
52
+ info(dim(`Risk: high | Files: ${affectedFiles.join(', ')} | Reversible: yes`));
53
+ // 5. Handle dry-run / confirmation
54
+ if (options.dryRun) {
55
+ warn('Dry-run mode — package.json will not be modified.');
56
+ return;
57
+ }
58
+ if (!options.yes) {
59
+ const ok = await confirm('Apply Prisma upgrade to package.json?');
60
+ if (!ok)
61
+ throw new ConfirmCancelledError();
62
+ }
63
+ // 6. Update package.json (atomic write)
64
+ applyPrismaUpgrade(projectRoot, versionInfo.latestVersion);
65
+ // 7. Log mutation (with session existence check)
66
+ const db = initializeDatabase();
67
+ const sessionId = resolveOrCreateSession(db, {
68
+ sessionId: options.session,
69
+ command: 'upgrade prisma',
70
+ projectRoot,
71
+ provider: config.provider.default,
72
+ model: config.provider.model,
73
+ });
74
+ logMutation(db, sessionId, {
75
+ action: 'upgrade_prisma',
76
+ affectedFiles,
77
+ riskLevel: 'high',
78
+ reversible: true,
79
+ rollbackHints: ['git checkout -- package.json', `${pm} install`],
80
+ });
81
+ updateSessionStatus(db, sessionId, 'completed');
82
+ // 8. Print next steps
83
+ const prismaCmd = pm === 'npm' ? 'npx' : pm;
84
+ const releaseUrl = `https://github.com/prisma/prisma/releases/tag/${versionInfo.latestVersion}`;
85
+ info('');
86
+ success('Updated Prisma versions in package.json:');
87
+ if (versionInfo.currentPrisma) {
88
+ info(` prisma: ${versionInfo.currentPrisma} → ${versionInfo.latestVersion}`);
89
+ }
90
+ if (versionInfo.currentClient) {
91
+ info(` @prisma/client: ${versionInfo.currentClient} → ${versionInfo.latestVersion}`);
92
+ }
93
+ info('');
94
+ info('Next steps (run in order):');
95
+ info('');
96
+ info('1. Install updated dependencies:');
97
+ info(` ${pm} install`);
98
+ info('');
99
+ info('2. Regenerate Prisma Client:');
100
+ info(` ${prismaCmd} prisma generate`);
101
+ info('');
102
+ info('3. Review breaking changes:');
103
+ info(` ${releaseUrl}`);
104
+ info('');
105
+ info('4. Run your test suite:');
106
+ info(` ${pm} test`);
107
+ info('');
108
+ info('Aria has updated package.json only.');
109
+ info('Migration commands must be run manually.');
110
+ }
111
+ // ---------------------------------------------------------------------------
112
+ // Helpers
113
+ // ---------------------------------------------------------------------------
114
+ /**
115
+ * Update prisma and @prisma/client versions in package.json (atomic write).
116
+ */
117
+ function applyPrismaUpgrade(projectRoot, targetVersion) {
118
+ const pkgPath = path.join(projectRoot, 'package.json');
119
+ const pkg = readJsonFile(pkgPath);
120
+ const updateSection = (section, name) => {
121
+ if (!section || section[name] === undefined)
122
+ return;
123
+ const existing = section[name];
124
+ const prefix = existing.match(/^[\^~>=<]+/)?.[0] ?? '^';
125
+ section[name] = `${prefix}${targetVersion}`;
126
+ };
127
+ updateSection(pkg.dependencies, 'prisma');
128
+ updateSection(pkg.dependencies, '@prisma/client');
129
+ updateSection(pkg.devDependencies, 'prisma');
130
+ updateSection(pkg.devDependencies, '@prisma/client');
131
+ writeFileAtomic(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
132
+ }
133
+ /**
134
+ * Use LLM to generate Prisma-specific migration guidance for major upgrades.
135
+ * Uses provider.chat directly — no tools needed for analysis.
136
+ */
137
+ async function generateMigrationGuidance(currentVersion, targetVersion, projectRoot, config) {
138
+ const schemaInfo = parsePrismaSchema(projectRoot);
139
+ const schemaSummary = schemaInfo
140
+ ? `Models: ${schemaInfo.models.map((m) => m.name).join(', ')}\nProvider: ${schemaInfo.datasourceProvider ?? 'unknown'}`
141
+ : 'No schema.prisma found';
142
+ const template = loadPromptTemplate('upgrade_prisma', 'Analyze Prisma upgrade from {{ current_version }} to {{ target_version }}.\nSchema: {{ schema_summary }}');
143
+ const systemPrompt = template
144
+ .replace(/\{\{ current_version \}\}/g, currentVersion)
145
+ .replace(/\{\{ target_version \}\}/g, targetVersion)
146
+ .replace(/\{\{ schema_summary \}\}/g, schemaSummary);
147
+ info('');
148
+ info(bold('Prisma upgrade analysis:'));
149
+ try {
150
+ const provider = createProvider(config.provider.default);
151
+ const db = initializeDatabase();
152
+ const sessionId = resolveOrCreateSession(db, {
153
+ command: 'upgrade prisma analysis',
154
+ projectRoot,
155
+ provider: config.provider.default,
156
+ model: config.provider.model,
157
+ });
158
+ logMessage(db, sessionId, 'system', systemPrompt);
159
+ // Use provider.chat directly instead of agentLoop with empty tools
160
+ const response = await provider.chat([
161
+ { role: 'system', content: systemPrompt },
162
+ {
163
+ role: 'user',
164
+ content: `Analyze the Prisma upgrade from ${currentVersion} to ${targetVersion} and provide migration guidance.`,
165
+ },
166
+ ], [], { model: config.provider.model, maxTokens: config.provider.maxTokens });
167
+ if (response.content) {
168
+ info(response.content);
169
+ }
170
+ logMessage(db, sessionId, 'assistant', response.content);
171
+ updateSessionStatus(db, sessionId, 'completed');
172
+ }
173
+ catch {
174
+ warn('Could not generate AI analysis for Prisma upgrade. Proceeding without it.');
175
+ }
176
+ }
177
+ //# sourceMappingURL=upgrade-prisma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-prisma.js","sourceRoot":"","sources":["../../src/actions/upgrade-prisma.ts"],"names":[],"mappings":"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"}
package/dist/actions.js CHANGED
@@ -24,6 +24,7 @@ import { agentLoop, UserCancelledError } from "./agent.js";
24
24
  import prompts from "prompts";
25
25
  import { initUI, info, print, error as uiError, bold, yellow, green, dim, cyan, red, renderTable, generateAndRenderDiff, confirm, ConfirmCancelledError, } from "./ui.js";
26
26
  import { loadConfig, validateConfig } from "./config.js";
27
+ import { getShellRcPath } from "./fs-helpers.js";
27
28
  const __dirname = dirname(fileURLToPath(import.meta.url));
28
29
  // ---------------------------------------------------------------------------
29
30
  // Provider resolution with interactive setup
@@ -145,27 +146,30 @@ async function resolveProvider(config) {
145
146
  const { saveKey } = await prompts({
146
147
  type: "confirm",
147
148
  name: "saveKey",
148
- message: `Save ${envKey} to ~/.zshrc for future sessions?`,
149
+ message: `Save ${envKey} to shell profile for future sessions?`,
149
150
  initial: true,
150
151
  }, {
151
152
  onCancel: () => { },
152
153
  });
153
154
  if (saveKey) {
154
- const shellRc = path.join(os.homedir(), ".zshrc");
155
- const exportLine = `\nexport ${envKey}="${apiKey}"\n`;
155
+ const shellRc = getShellRcPath();
156
+ const shellRcName = path.basename(shellRc);
157
+ // Escape double quotes, dollar signs, and backticks in the API key to prevent shell injection
158
+ const escapedKey = apiKey.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\$/g, '\\$').replace(/`/g, '\\`');
159
+ const exportLine = `\nexport ${envKey}="${escapedKey}"\n`;
156
160
  try {
157
161
  const existing = existsSync(shellRc) ? readFileSync(shellRc, "utf-8") : "";
158
162
  if (!existing.includes(envKey)) {
159
163
  writeFileSync(shellRc, existing + exportLine, "utf-8");
160
- info(green(`✓ Added ${envKey} to ~/.zshrc`));
161
- info(dim(" Run `source ~/.zshrc` or open a new terminal to apply."));
164
+ info(green(`✓ Added ${envKey} to ~/${shellRcName}`));
165
+ info(dim(` Run \`source ~/${shellRcName}\` or open a new terminal to apply.`));
162
166
  }
163
167
  else {
164
- info(dim(`${envKey} already exists in ~/.zshrc, skipping.`));
168
+ info(dim(`${envKey} already exists in ~/${shellRcName}, skipping.`));
165
169
  }
166
170
  }
167
171
  catch {
168
- info(yellow(`Could not write to ~/.zshrc. Set ${envKey} manually.`));
172
+ info(yellow(`Could not write to ~/${shellRcName}. Set ${envKey} manually.`));
169
173
  }
170
174
  }
171
175
  return createProvider(selectedProvider);
@@ -1085,7 +1089,10 @@ export async function runExplore(options) {
1085
1089
  * Requirements: 14.7
1086
1090
  */
1087
1091
  function formatTimestamp(timestamp) {
1088
- const date = new Date(timestamp.endsWith("Z") ? timestamp : timestamp + "Z");
1092
+ // SQLite CURRENT_TIMESTAMP returns "YYYY-MM-DD HH:MM:SS" (space, no T, no Z).
1093
+ // Normalize to ISO 8601 so Date() parses it as UTC.
1094
+ const normalized = timestamp.includes('T') ? timestamp : timestamp.replace(' ', 'T');
1095
+ const date = new Date(normalized.endsWith("Z") ? normalized : normalized + "Z");
1089
1096
  const now = Date.now();
1090
1097
  const diffMs = now - date.getTime();
1091
1098
  const diffSec = Math.floor(diffMs / 1000);
@@ -1362,7 +1369,15 @@ function setNestedValue(obj, key, value) {
1362
1369
  let current = result;
1363
1370
  for (let i = 0; i < parts.length - 1; i++) {
1364
1371
  const part = parts[i];
1365
- current[part] = { ...(current[part] ?? {}) };
1372
+ const existing = current[part];
1373
+ // If the intermediate value is not an object, replace it with an empty object.
1374
+ // This prevents spreading a primitive (string/number/boolean) into an object.
1375
+ if (existing === null || typeof existing !== 'object' || Array.isArray(existing)) {
1376
+ current[part] = {};
1377
+ }
1378
+ else {
1379
+ current[part] = { ...existing };
1380
+ }
1366
1381
  current = current[part];
1367
1382
  }
1368
1383
  current[parts[parts.length - 1]] = value;
@@ -1729,20 +1744,40 @@ export async function runDoctor(options = {}) {
1729
1744
  }
1730
1745
  }
1731
1746
  // -------------------------------------------------------------------------
1732
- // 8. Prisma schema existence if Prisma detected (Req 16.9)
1747
+ // 8. Prisma schema existence and model count (Req 16.9 + v0.2.0)
1733
1748
  // -------------------------------------------------------------------------
1734
1749
  {
1735
1750
  try {
1736
1751
  const project = detectProjectType(projectRoot);
1737
1752
  if (project.hasPrisma) {
1738
1753
  if (project.prismaSchemaPath && existsSync(project.prismaSchemaPath)) {
1739
- checks.push({ name: "prisma", status: "pass", message: `detected at ${project.prismaSchemaPath}` });
1754
+ // v0.2.0: parse schema and report model count + provider
1755
+ try {
1756
+ const { parsePrismaSchema } = await import('./db/schema.js');
1757
+ const schemaInfo = parsePrismaSchema(projectRoot);
1758
+ if (schemaInfo) {
1759
+ const providerLabel = schemaInfo.datasourceProvider ?? 'unknown';
1760
+ checks.push({
1761
+ name: 'prisma',
1762
+ status: 'pass',
1763
+ message: `${schemaInfo.path} (${providerLabel}, ${schemaInfo.models.length} models)`,
1764
+ });
1765
+ }
1766
+ else {
1767
+ checks.push({ name: 'prisma', status: 'pass', message: `detected at ${project.prismaSchemaPath}` });
1768
+ }
1769
+ }
1770
+ catch {
1771
+ checks.push({ name: 'prisma', status: 'pass', message: `detected at ${project.prismaSchemaPath}` });
1772
+ }
1740
1773
  }
1741
1774
  else {
1742
- checks.push({ name: "prisma", status: "warn", message: "dependency detected but prisma/schema.prisma not found" });
1775
+ checks.push({ name: 'prisma', status: 'warn', message: 'dependency detected but prisma/schema.prisma not found' });
1743
1776
  }
1744
1777
  }
1745
- // If no Prisma, skip this check entirely
1778
+ else {
1779
+ checks.push({ name: 'prisma', status: 'warn', message: 'no schema.prisma found (db commands unavailable)' });
1780
+ }
1746
1781
  }
1747
1782
  catch {
1748
1783
  // project detection already reported above