@ivotoby/postgram-cli 1.30.0 → 1.30.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/dist/client.js +6 -0
- package/dist/pgm.js +82 -3
- package/package.json +2 -1
package/dist/client.js
CHANGED
|
@@ -49,6 +49,12 @@ export function createPgmClient(options) {
|
|
|
49
49
|
body: input
|
|
50
50
|
});
|
|
51
51
|
},
|
|
52
|
+
groomSessionContext(input) {
|
|
53
|
+
return request(options, '/api/memory/session-context/groom', {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
body: input
|
|
56
|
+
});
|
|
57
|
+
},
|
|
52
58
|
recallEntity(id, input = {}) {
|
|
53
59
|
const params = new URLSearchParams();
|
|
54
60
|
if (input.owner) {
|
package/dist/pgm.js
CHANGED
|
@@ -64,6 +64,43 @@ function validateToonOptions(options, json) {
|
|
|
64
64
|
throw new AppError(ErrorCode.VALIDATION, '--toon cannot be combined with --json or --full-response');
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
function parseDurationMs(value) {
|
|
68
|
+
const match = /^(\d+)([mhd])$/i.exec(value.trim());
|
|
69
|
+
if (!match) {
|
|
70
|
+
throw new AppError(ErrorCode.VALIDATION, `Invalid duration '${value}'. Use format like '15m', '2h', or '7d'.`);
|
|
71
|
+
}
|
|
72
|
+
const [, amountText, unitText] = match;
|
|
73
|
+
const amount = Number(amountText);
|
|
74
|
+
const unit = unitText.toLowerCase();
|
|
75
|
+
const milliseconds = unit === 'm'
|
|
76
|
+
? amount * 60 * 1000
|
|
77
|
+
: unit === 'h'
|
|
78
|
+
? amount * 60 * 60 * 1000
|
|
79
|
+
: amount * 24 * 60 * 60 * 1000;
|
|
80
|
+
if (milliseconds > 3650 * 24 * 60 * 60 * 1000) {
|
|
81
|
+
throw new AppError(ErrorCode.VALIDATION, `Duration '${value}' exceeds the maximum allowed (3650 days / ~10 years).`);
|
|
82
|
+
}
|
|
83
|
+
return milliseconds;
|
|
84
|
+
}
|
|
85
|
+
function formatGroomCandidates(candidates) {
|
|
86
|
+
if (candidates.length === 0) {
|
|
87
|
+
return ['No eligible session-context memories'];
|
|
88
|
+
}
|
|
89
|
+
const lines = [`Would archive ${candidates.length} session-context memories`];
|
|
90
|
+
for (const candidate of candidates) {
|
|
91
|
+
const metadata = candidate.metadata;
|
|
92
|
+
lines.push([
|
|
93
|
+
` ${shortId(candidate.id)} ${candidate.createdAt.slice(0, 10)}`,
|
|
94
|
+
candidate.tags.length ? `tags=${candidate.tags.join(',')}` : 'tags=-',
|
|
95
|
+
metadata.topic ? `topic=${metadata.topic}` : undefined,
|
|
96
|
+
metadata.session_id ? `session=${metadata.session_id}` : undefined,
|
|
97
|
+
candidate.content ? `content=${candidate.content}` : 'content=-'
|
|
98
|
+
]
|
|
99
|
+
.filter(Boolean)
|
|
100
|
+
.join(' | '));
|
|
101
|
+
}
|
|
102
|
+
return lines;
|
|
103
|
+
}
|
|
67
104
|
async function resolveStoreContent(content) {
|
|
68
105
|
if (content !== undefined) {
|
|
69
106
|
return content;
|
|
@@ -259,7 +296,6 @@ program
|
|
|
259
296
|
.option('--expand-graph', 'include graph-connected entities in results')
|
|
260
297
|
.option('--include-archived', 'include archived entities in results')
|
|
261
298
|
.option('--memory-role <role>', 'memory role filter: durable_memory or session_context')
|
|
262
|
-
.option('--include-other-clients-session-context', 'include session context from other clients')
|
|
263
299
|
.option('--full-response', 'emit the full API response instead of compact default output when used with --json')
|
|
264
300
|
.option('--toon', 'emit compact TOON output for lower agent token use; formatting is applied in the CLI, not the API')
|
|
265
301
|
.action(async (query, options, command) => {
|
|
@@ -282,8 +318,7 @@ program
|
|
|
282
318
|
recency_weight: Number(options.recencyWeight),
|
|
283
319
|
expand_graph: options.expandGraph === true ? true : undefined,
|
|
284
320
|
include_archived: options.includeArchived === true ? true : undefined,
|
|
285
|
-
memory_role: options.memoryRole
|
|
286
|
-
include_other_clients_session_context: options.includeOtherClientsSessionContext === true ? true : undefined
|
|
321
|
+
memory_role: options.memoryRole
|
|
287
322
|
});
|
|
288
323
|
if (options.toon === true) {
|
|
289
324
|
return searchResponseToToon(compactSearchResponse(body));
|
|
@@ -299,6 +334,50 @@ program
|
|
|
299
334
|
const memoryCommand = program
|
|
300
335
|
.command('memory')
|
|
301
336
|
.description('Memory-specific commands');
|
|
337
|
+
memoryCommand
|
|
338
|
+
.command('groom')
|
|
339
|
+
.description('Preview or archive stale session-context memories for the authenticated client')
|
|
340
|
+
.option('--dry-run', 'preview without mutating')
|
|
341
|
+
.option('--older-than <duration>', 'only include memories older than this (e.g. 15m, 2h, 7d)', '7d')
|
|
342
|
+
.option('--limit <limit>', 'maximum candidates', '50')
|
|
343
|
+
.option('--topic <topic>', 'filter by topic')
|
|
344
|
+
.option('--session-id <sessionId>', 'filter by session id')
|
|
345
|
+
.option('--tag <tag>', 'filter by tag (repeatable)', (value, previous = []) => {
|
|
346
|
+
previous.push(value);
|
|
347
|
+
return previous;
|
|
348
|
+
}, [])
|
|
349
|
+
.option('--yes', 'confirm archive mutation')
|
|
350
|
+
.action(async (options, command) => {
|
|
351
|
+
await runWithClient(command, async (client, json) => {
|
|
352
|
+
const limit = Number.parseInt(options.limit, 10);
|
|
353
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
354
|
+
throw new AppError(ErrorCode.VALIDATION, '--limit must be a positive integer');
|
|
355
|
+
}
|
|
356
|
+
if (options.dryRun !== true && options.yes !== true) {
|
|
357
|
+
throw new AppError(ErrorCode.VALIDATION, '--yes is required outside dry-run');
|
|
358
|
+
}
|
|
359
|
+
const body = await client.groomSessionContext({
|
|
360
|
+
dry_run: options.dryRun === true,
|
|
361
|
+
confirmed: options.dryRun === true ? undefined : true,
|
|
362
|
+
older_than_ms: parseDurationMs(options.olderThan),
|
|
363
|
+
limit,
|
|
364
|
+
topic: options.topic,
|
|
365
|
+
session_id: options.sessionId,
|
|
366
|
+
tags: options.tag
|
|
367
|
+
});
|
|
368
|
+
if (json) {
|
|
369
|
+
return body;
|
|
370
|
+
}
|
|
371
|
+
if (body.dryRun) {
|
|
372
|
+
return formatGroomCandidates(body.eligible ?? []);
|
|
373
|
+
}
|
|
374
|
+
return [
|
|
375
|
+
`Archived ${body.archived} session-context memories`,
|
|
376
|
+
` promoted: ${body.promoted}`,
|
|
377
|
+
` skipped: ${body.skipped}`
|
|
378
|
+
];
|
|
379
|
+
});
|
|
380
|
+
});
|
|
302
381
|
memoryCommand
|
|
303
382
|
.command('session-context')
|
|
304
383
|
.alias('session')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ivotoby/postgram-cli",
|
|
3
|
-
"version": "1.30.
|
|
3
|
+
"version": "1.30.1",
|
|
4
4
|
"description": "Postgram CLI — store, search, and manage entities from the command line",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "tsc -p tsconfig.build.json",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.build.json --noEmit",
|
|
36
37
|
"prepublishOnly": "npm run build",
|
|
37
38
|
"test": "vitest run",
|
|
38
39
|
"test:watch": "vitest",
|