@dzhi/ocpg 0.6.2 → 0.8.0

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 (3) hide show
  1. package/README.md +17 -25
  2. package/ocpg.ts +13 -34
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -12,41 +12,33 @@ In `opencode.json`:
12
12
  ```json
13
13
  {
14
14
  "plugin": [
15
- ["@dzhi/ocpg", {}]
15
+ "@dzhi/ocpg"
16
16
  ]
17
17
  }
18
18
  ```
19
19
 
20
20
  ## Connecting to the database
21
21
 
22
- Pass connection params as the plugin options tuple (all optional):
22
+ Need a Postgres instance? The [`deploy/`](./deploy) directory ships a hardened Docker Compose setup (localhost-only, `memories` schema auto-created on first boot) — see [`deploy/README.md`](./deploy/README.md).
23
23
 
24
- ```json
25
- {
26
- "plugin": [
27
- [
28
- "@dzhi/ocpg",
29
- {
30
- "host": "localhost",
31
- "port": 5432,
32
- "user": "pguser",
33
- "database": "agent-memory"
34
- }
35
- ]
36
- ]
37
- }
38
- ```
24
+ Configure the connection via environment variables, e.g. in `~/.zshenv`. Any Postgres user and database name will do — use whatever names fit your setup and mirror them here:
39
25
 
40
- Precedence: plugin options > env vars > defaults.
26
+ ```bash
27
+ export OCPG_HOST="localhost"
28
+ export OCPG_PORT="5432"
29
+ export OCPG_USER="ocpguser"
30
+ export OCPG_PASSWORD="your-postgres-password"
31
+ export OCPG_DB="ocpg"
32
+ ```
41
33
 
42
- | Param | Env var (fallback) | Default |
43
- | ---------- | ------------------ | -------------- |
44
- | `host` | `OCPG_HOST` | `localhost` |
45
- | `port` | `OCPG_PORT` | `5432` |
46
- | `user` | `OCPG_USER` | `pguser` |
47
- | `database` | `OCPG_DB` | `agent-memory` |
34
+ | Env var | Default |
35
+ | --------------- | ------------ |
36
+ | `OCPG_HOST` | `localhost` |
37
+ | `OCPG_PORT` | `5432` |
38
+ | `OCPG_USER` | `ocpguser` |
39
+ | `OCPG_DB` | `ocpg` |
48
40
 
49
- **Password is never set via params** it resolves from `OCPG_PASSWORD`.
41
+ **Password is env-only.** The plugin never reads config files, options, or external secret managers — set `OCPG_PASSWORD` in your shell environment (e.g. via direnv/.envrc, however you source your secrets).
50
42
 
51
43
  ## Tools
52
44
 
package/ocpg.ts CHANGED
@@ -2,29 +2,24 @@
2
2
  import { SQL } from "bun";
3
3
  import { Plugin } from "@opencode/plugin";
4
4
 
5
- // --- DB config: plugin options > env > defaults. Password is deliberately env-only (never in config).
6
- type DbOptions = {
7
- host?: string;
8
- port?: number;
9
- user?: string;
10
- database?: string;
5
+ // --- DB config: env > defaults. Plugin options are not read; password is deliberately env-only (never in config).
6
+ type DbConfig = {
7
+ host: string;
8
+ port: number;
9
+ user: string;
10
+ database: string;
11
11
  };
12
- type DbConfig = Required<DbOptions>;
13
12
  type RecallArgs = { query?: string; global?: boolean; limit?: number };
14
13
  type RememberArgs = { content: string; tags?: string[] };
15
14
 
16
- // Defaults resolved ONCE at module init — the pass lookup here is the only permitted spawn in this file.
15
+ // Defaults resolved ONCE at module init — env-only, no process spawning.
17
16
  const defaultConfig: DbConfig = {
18
17
  host: process.env.OCPG_HOST || "localhost",
19
18
  port: Number(process.env.OCPG_PORT) || 5432,
20
- user: process.env.OCPG_USER || "pguser",
21
- database: process.env.OCPG_DB || "agent-memory",
19
+ user: process.env.OCPG_USER || "ocpguser",
20
+ database: process.env.OCPG_DB || "ocpg",
22
21
  };
23
- const password =
24
- process.env.OCPG_PASSWORD ||
25
- Bun.spawnSync(["pass", "show", "postgres-workstation-password"])
26
- .stdout.toString()
27
- .trim();
22
+ const password = process.env.OCPG_PASSWORD || "";
28
23
 
29
24
  // Options-object constructor, not a URL string: Bun's SQL parses string URLs via
30
25
  // url.parse(), which emits the DEP0169 DeprecationWarning at plugin load under opencode.
@@ -41,14 +36,6 @@ function makeSql(cfg: DbConfig): SQL {
41
36
 
42
37
  let sql = makeSql(defaultConfig);
43
38
 
44
- // Swap the pool when the plugin loads with config options ({ "package": "@dzhi/ocpg", "options": {...} } in opencode.jsonc).
45
- // No-op without options so the module-level env/default config stands. Pools are lazy — a never-connected pool closes cleanly.
46
- function reconfigure(options?: DbOptions): void {
47
- if (!options) return;
48
- void sql.close().catch(() => {});
49
- sql = makeSql({ ...defaultConfig, ...options });
50
- }
51
-
52
39
  export interface MemoryRow {
53
40
  id: number;
54
41
  content: string;
@@ -150,12 +137,6 @@ async function dispose(): Promise<void> {
150
137
 
151
138
  // --- Agent tools: recall + remember with dedup-on-write ---
152
139
 
153
- function normalizeTags(tags: string[] | undefined, projectDir: string): string[] {
154
- const input = tags ?? [];
155
- const base = projectDir.split('/').pop() ?? projectDir;
156
- return [...input, `project:${base}`];
157
- }
158
-
159
140
  async function recall(
160
141
  args: RecallArgs,
161
142
  ctx: { directory: string },
@@ -207,7 +188,8 @@ async function remember(
207
188
  return 'ERROR: content must be at least 10 characters.';
208
189
  }
209
190
 
210
- const normalizedTags = normalizeTags(args.tags, ctx.directory);
191
+ // Tags are stored verbatim — project scoping lives in the project column, not tags.
192
+ const tags = args.tags ?? [];
211
193
  const basename = ctx.directory.split('/').pop() ?? ctx.directory;
212
194
 
213
195
  // Dedup: project-scoped, common-opening-words AND-match via FTS
@@ -233,7 +215,7 @@ async function remember(
233
215
  // the element type hint is required for clean array storage.
234
216
  const inserted = await sql`
235
217
  INSERT INTO memories (content, tags, session_id, project)
236
- VALUES (${args.content}, ${sql.array(normalizedTags, "text")}, ${ctx.sessionID}, ${ctx.directory})
218
+ VALUES (${args.content}, ${sql.array(tags, "text")}, ${ctx.sessionID}, ${ctx.directory})
237
219
  RETURNING id
238
220
  ` as { id: number }[];
239
221
 
@@ -256,7 +238,6 @@ function invalidateInjection(sessionID: string): void {
256
238
  const ocpg = Plugin.define({
257
239
  id: "ocpg",
258
240
  async setup(ctx) {
259
- reconfigure(ctx.options as DbOptions | undefined);
260
241
  const directory = ctx.location.directory;
261
242
 
262
243
  // Inject project memories into every model request's system context.
@@ -320,11 +301,9 @@ const __internals = {
320
301
  get sql() {
321
302
  return sql;
322
303
  },
323
- reconfigure,
324
304
  truncateMemory,
325
305
  formatBlock,
326
306
  handleTransform,
327
- normalizeTags,
328
307
  recall,
329
308
  remember,
330
309
  invalidateInjection,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhi/ocpg",
3
- "version": "0.6.2",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "Postgres-backed persistent memory plugin for OpenCode",
6
6
  "main": "ocpg.ts",