pmpt-cli 1.14.0 → 1.14.2
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/dist/mcp.js +61 -3
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -12,7 +12,7 @@ import { resolve, join } from 'path';
|
|
|
12
12
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
13
13
|
import glob from 'fast-glob';
|
|
14
14
|
import { createRequire } from 'module';
|
|
15
|
-
import { isInitialized, loadConfig, getDocsDir } from './lib/config.js';
|
|
15
|
+
import { isInitialized, loadConfig, getDocsDir, getHistoryDir } from './lib/config.js';
|
|
16
16
|
import { createFullSnapshot, getAllSnapshots, getTrackedFiles, resolveFullSnapshot } from './lib/history.js';
|
|
17
17
|
import { computeQuality } from './lib/quality.js';
|
|
18
18
|
import { getPlanProgress, savePlanProgress, savePlanDocuments, PLAN_QUESTIONS } from './lib/plan.js';
|
|
@@ -245,6 +245,64 @@ server.tool('pmpt_diff', 'Compare two versions, or a version against the current
|
|
|
245
245
|
return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
|
|
246
246
|
}
|
|
247
247
|
});
|
|
248
|
+
server.tool('pmpt_squash', 'Remove empty snapshots (no file changes) and renumber remaining versions sequentially. Use this to clean up history when there are snapshots with no actual content changes.', {
|
|
249
|
+
projectPath: z.string().optional().describe('Project root path. Defaults to cwd.'),
|
|
250
|
+
}, async ({ projectPath }) => {
|
|
251
|
+
try {
|
|
252
|
+
const pp = resolveProjectPath(projectPath);
|
|
253
|
+
assertInitialized(pp);
|
|
254
|
+
const snapshots = getAllSnapshots(pp);
|
|
255
|
+
if (snapshots.length === 0) {
|
|
256
|
+
return { content: [{ type: 'text', text: 'No snapshots found.' }] };
|
|
257
|
+
}
|
|
258
|
+
const emptySnapshots = snapshots.filter(s => s.changedFiles && s.changedFiles.length === 0);
|
|
259
|
+
if (emptySnapshots.length === 0) {
|
|
260
|
+
return { content: [{ type: 'text', text: 'No empty snapshots found. History is clean.' }] };
|
|
261
|
+
}
|
|
262
|
+
// Delete empty snapshots
|
|
263
|
+
const { rmSync, renameSync } = await import('fs');
|
|
264
|
+
const { basename } = await import('path');
|
|
265
|
+
for (const snap of emptySnapshots) {
|
|
266
|
+
if (existsSync(snap.snapshotDir)) {
|
|
267
|
+
rmSync(snap.snapshotDir, { recursive: true });
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Renumber remaining snapshots
|
|
271
|
+
const historyDir = getHistoryDir(pp);
|
|
272
|
+
const remaining = getAllSnapshots(pp);
|
|
273
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
274
|
+
const snap = remaining[i];
|
|
275
|
+
const newVersion = i + 1;
|
|
276
|
+
if (snap.version === newVersion)
|
|
277
|
+
continue;
|
|
278
|
+
const dirName = basename(snap.snapshotDir);
|
|
279
|
+
const newDirName = dirName.replace(/^v\d+/, `v${newVersion}`);
|
|
280
|
+
const newDir = join(historyDir, newDirName);
|
|
281
|
+
renameSync(snap.snapshotDir, newDir);
|
|
282
|
+
const metaPath = join(newDir, '.meta.json');
|
|
283
|
+
if (existsSync(metaPath)) {
|
|
284
|
+
const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
|
|
285
|
+
meta.version = newVersion;
|
|
286
|
+
writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const finalCount = getAllSnapshots(pp).length;
|
|
290
|
+
return {
|
|
291
|
+
content: [{
|
|
292
|
+
type: 'text',
|
|
293
|
+
text: [
|
|
294
|
+
`Squashed: removed ${emptySnapshots.length} empty snapshot(s).`,
|
|
295
|
+
`Remaining: ${finalCount} snapshot(s), renumbered v1-v${finalCount}.`,
|
|
296
|
+
'',
|
|
297
|
+
`Removed versions: ${emptySnapshots.map(s => `v${s.version}`).join(', ')}`,
|
|
298
|
+
].join('\n'),
|
|
299
|
+
}],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
|
|
304
|
+
}
|
|
305
|
+
});
|
|
248
306
|
server.tool('pmpt_quality', 'Check project quality score and publish readiness.', { projectPath: z.string().optional().describe('Project root path. Defaults to cwd.') }, async ({ projectPath }) => {
|
|
249
307
|
try {
|
|
250
308
|
const pp = resolveProjectPath(projectPath);
|
|
@@ -524,7 +582,7 @@ server.tool('pmpt_log_decision', 'Record an architectural or technical decision
|
|
|
524
582
|
return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
|
|
525
583
|
}
|
|
526
584
|
});
|
|
527
|
-
server.tool('pmpt_publish', 'Publish the project to pmptwiki.com.
|
|
585
|
+
server.tool('pmpt_publish', 'Publish the project to pmptwiki.com. This tool handles everything non-interactively — just provide the slug and optional metadata. Note: the user must have run `pmpt login` once before (check if auth exists). If not logged in, ask the user to run `pmpt login` in their terminal, then retry this tool.', {
|
|
528
586
|
projectPath: z.string().optional().describe('Project root path. Defaults to cwd.'),
|
|
529
587
|
slug: z.string().describe('Project slug (3-50 chars, lowercase alphanumeric and hyphens).'),
|
|
530
588
|
description: z.string().optional().describe('Project description (max 500 chars).'),
|
|
@@ -616,7 +674,7 @@ server.tool('pmpt_publish', 'Publish the project to pmptwiki.com. Requires prior
|
|
|
616
674
|
return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true };
|
|
617
675
|
}
|
|
618
676
|
});
|
|
619
|
-
server.tool('pmpt_graduate', 'Graduate a project on pmptwiki — archives it with a Hall of Fame badge. The project can no longer be updated.
|
|
677
|
+
server.tool('pmpt_graduate', 'Graduate a project on pmptwiki — archives it with a Hall of Fame badge. The project can no longer be updated. Non-interactive. User must have run `pmpt login` once before.', {
|
|
620
678
|
slug: z.string().describe('Project slug to graduate.'),
|
|
621
679
|
note: z.string().optional().describe('Graduation note (e.g., "Reached 1000 users!").'),
|
|
622
680
|
}, async ({ slug, note }) => {
|