@ivotoby/postgram-cli 1.25.0 → 1.28.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 CHANGED
@@ -63,6 +63,41 @@ pgm queue
63
63
  pgm store "hello" --json
64
64
  ```
65
65
 
66
+ ## Memory Roles
67
+
68
+ Store durable memory:
69
+
70
+ ```bash
71
+ pgm store "Ivo prefers client-scoped session context in Postgram." \
72
+ --type memory \
73
+ --visibility personal \
74
+ --metadata '{"memory_role":"durable_memory"}'
75
+ ```
76
+
77
+ Store session context:
78
+
79
+ ```bash
80
+ pgm memory session-context "We are discussing Postgram memory lifecycle roles." \
81
+ --visibility personal \
82
+ --topic postgram-memory \
83
+ --agent-id codex \
84
+ --tags session-context
85
+ ```
86
+
87
+ Search session context:
88
+
89
+ ```bash
90
+ pgm search "Postgram memory lifecycle roles" \
91
+ --type memory \
92
+ --memory-role session_context \
93
+ --visibility personal
94
+ ```
95
+
96
+ Use durable memory for stable facts, decisions, constraints, and preferences.
97
+ Use session context for recent-thread continuity. Session context is embedded
98
+ for semantic recall, scoped to the calling client when the server knows its
99
+ `client_id`, and skipped by graph extraction.
100
+
66
101
  ## Claude Code skill
67
102
 
68
103
  A portable Claude Code skill for using `pgm` from your agent lives in
package/dist/client.js CHANGED
@@ -43,6 +43,12 @@ export function createPgmClient(options) {
43
43
  body: input
44
44
  });
45
45
  },
46
+ storeSessionContext(input) {
47
+ return request(options, '/api/memory/session-context', {
48
+ method: 'POST',
49
+ body: input
50
+ });
51
+ },
46
52
  recallEntity(id, input = {}) {
47
53
  const params = new URLSearchParams();
48
54
  if (input.owner) {
package/dist/pgm.js CHANGED
@@ -208,6 +208,7 @@ program
208
208
  .option('--tags <tags>', 'comma-separated tags')
209
209
  .option('--source <source>', 'entity source')
210
210
  .option('--metadata <json>', 'JSON metadata object')
211
+ .option('--skip-extraction', 'store without ever queueing graph extraction')
211
212
  .action(async (content, options, command) => {
212
213
  await runWithClient(command, async (client, json) => {
213
214
  const body = await client.storeEntity({
@@ -218,7 +219,8 @@ program
218
219
  status: options.status,
219
220
  tags: parseCommaList(options.tags),
220
221
  source: options.source,
221
- metadata: parseJsonObject(options.metadata)
222
+ metadata: parseJsonObject(options.metadata),
223
+ skip_extraction: options.skipExtraction === true ? true : undefined
222
224
  });
223
225
  return json
224
226
  ? body
@@ -246,8 +248,14 @@ program
246
248
  .option('--recency-weight <recencyWeight>', 'recency weight', '0.1')
247
249
  .option('--expand-graph', 'include graph-connected entities in results')
248
250
  .option('--include-archived', 'include archived entities in results')
251
+ .option('--memory-role <role>', 'memory role filter: durable_memory or session_context')
252
+ .option('--include-other-clients-session-context', 'include session context from other clients')
249
253
  .action(async (query, options, command) => {
250
254
  await runWithClient(command, async (client, json) => {
255
+ if (options.memoryRole !== undefined &&
256
+ !['durable_memory', 'session_context'].includes(options.memoryRole)) {
257
+ throw new AppError(ErrorCode.VALIDATION, '--memory-role must be durable_memory or session_context');
258
+ }
251
259
  const body = await client.searchEntities({
252
260
  query,
253
261
  type: options.type,
@@ -258,11 +266,57 @@ program
258
266
  threshold: Number(options.threshold),
259
267
  recency_weight: Number(options.recencyWeight),
260
268
  expand_graph: options.expandGraph === true ? true : undefined,
261
- include_archived: options.includeArchived === true ? true : undefined
269
+ include_archived: options.includeArchived === true ? true : undefined,
270
+ memory_role: options.memoryRole,
271
+ include_other_clients_session_context: options.includeOtherClientsSessionContext === true ? true : undefined
262
272
  });
263
273
  return json ? body : formatSearchResults(body.results);
264
274
  });
265
275
  });
276
+ const memoryCommand = program
277
+ .command('memory')
278
+ .description('Memory-specific commands');
279
+ memoryCommand
280
+ .command('session-context')
281
+ .alias('session')
282
+ .description('Store client-scoped session-context memory')
283
+ .argument('[content]', 'session context content')
284
+ .option('--visibility <visibility>', 'entity visibility', 'shared')
285
+ .option('--owner <owner>', 'entity owner or namespace')
286
+ .option('--session-id <sessionId>', 'external session or thread id')
287
+ .option('--agent-id <agentId>', 'agent or persona id')
288
+ .option('--topic <topic>', 'topic label')
289
+ .option('--tags <tags>', 'comma-separated tags')
290
+ .option('--promotable', 'mark this session context as promotable')
291
+ .option('--groom-after <groomAfter>', 'ISO timestamp after which grooming may archive/promote it')
292
+ .option('--expires-at <expiresAt>', 'ISO timestamp after which the context is stale')
293
+ .action(async (content, options, command) => {
294
+ await runWithClient(command, async (client, json) => {
295
+ const body = await client.storeSessionContext({
296
+ content: await resolveStoreContent(content),
297
+ visibility: options.visibility,
298
+ owner: options.owner,
299
+ session_id: options.sessionId,
300
+ agent_id: options.agentId,
301
+ topic: options.topic,
302
+ tags: parseCommaList(options.tags),
303
+ promotable: options.promotable === true ? true : undefined,
304
+ groom_after: options.groomAfter,
305
+ expires_at: options.expiresAt
306
+ });
307
+ return json
308
+ ? body
309
+ : formatStoredEntity({
310
+ id: body.entity.id,
311
+ type: body.entity.type,
312
+ content: body.entity.content,
313
+ status: body.entity.status,
314
+ visibility: body.entity.visibility,
315
+ owner: body.entity.owner,
316
+ tags: body.entity.tags
317
+ });
318
+ });
319
+ });
266
320
  program
267
321
  .command('recall')
268
322
  .description('Recall an entity by ID')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivotoby/postgram-cli",
3
- "version": "1.25.0",
3
+ "version": "1.28.1",
4
4
  "description": "Postgram CLI — store, search, and manage entities from the command line",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,7 +28,8 @@
28
28
  "embeddings"
29
29
  ],
30
30
  "publishConfig": {
31
- "access": "public"
31
+ "access": "public",
32
+ "provenance": true
32
33
  },
33
34
  "scripts": {
34
35
  "build": "tsc -p tsconfig.build.json",
@@ -46,10 +47,9 @@
46
47
  "@eslint/js": "^9.38.0",
47
48
  "@semantic-release/changelog": "^6.0.3",
48
49
  "@semantic-release/commit-analyzer": "^13.0.1",
49
- "@semantic-release/exec": "^7.1.0",
50
50
  "@semantic-release/git": "^10.0.1",
51
51
  "@semantic-release/github": "^11.0.6",
52
- "@semantic-release/npm": "^12.0.2",
52
+ "@semantic-release/npm": "^13.1.5",
53
53
  "@semantic-release/release-notes-generator": "^14.1.0",
54
54
  "conventional-changelog-conventionalcommits": "^9.3.1",
55
55
  "eslint": "^9.38.0",