@eleboucher/opencode-memini 0.7.9 → 0.7.11

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 (2) hide show
  1. package/memini.js +45 -23
  2. package/package.json +1 -1
package/memini.js CHANGED
@@ -120,14 +120,9 @@ export function resolveInstallContextFrom(startPath) {
120
120
  }
121
121
 
122
122
  /**
123
- * resolveInstallContext finds the opencode plugin cache wrapper directory that
124
- * holds this running plugin instance. opencode installs each npm plugin spec
125
- * into its own isolated dir under ~/.cache/opencode/packages/<spec>/ (e.g.
126
- * .../opencode-memini@latest/), containing a package.json listing the plugin as
127
- * a dependency and a node_modules/ tree. The plugin's own file lives at
128
- * <wrapper>/node_modules/@eleboucher/opencode-memini/memini.js, so the wrapper
129
- * is the first ancestor whose child is a `node_modules` directory. Returns
130
- * { installDir, packageJsonPath } or null. Exported for testing.
123
+ * resolveInstallContext finds the opencode plugin cache wrapper directory
124
+ * holding this running plugin instance, by walking up from import.meta.url.
125
+ * Exported for testing.
131
126
  */
132
127
  export function resolveInstallContext() {
133
128
  try {
@@ -175,7 +170,7 @@ export function prepareCacheUpdate(newVersion, log, ctx) {
175
170
  ctx = resolveInstallContext();
176
171
  }
177
172
  if (!ctx) {
178
- log.warn("auto-update: could not resolve install context");
173
+ log.error("auto-update: could not resolve install context");
179
174
  return null;
180
175
  }
181
176
  // Rewrite package.json with the new version pin
@@ -187,7 +182,7 @@ export function prepareCacheUpdate(newVersion, log, ctx) {
187
182
  pkg.dependencies = { ...pkg.dependencies, [PACKAGE_NAME]: newVersion };
188
183
  writeFileSync(ctx.packageJsonPath, JSON.stringify(pkg, null, 2));
189
184
  } catch (err) {
190
- log.warn(`auto-update: failed to rewrite cache package.json: ${String(err)}`);
185
+ log.error(`auto-update: failed to rewrite cache package.json: ${String(err)}`);
191
186
  return null;
192
187
  }
193
188
  // Remove installed node_modules so the install re-fetches
@@ -195,7 +190,7 @@ export function prepareCacheUpdate(newVersion, log, ctx) {
195
190
  const pkgDir = join(ctx.installDir, "node_modules", "@eleboucher", "opencode-memini");
196
191
  if (existsSync(pkgDir)) rmSync(pkgDir, { recursive: true, force: true });
197
192
  } catch (err) {
198
- log.warn(`auto-update: failed to remove cached node_modules: ${String(err)}`);
193
+ log.error(`auto-update: failed to remove cached node_modules: ${String(err)}`);
199
194
  return null;
200
195
  }
201
196
  // Clean lockfiles: opencode's installer may write either package-lock.json
@@ -1131,15 +1126,42 @@ export function lastAssistantFailed(messages) {
1131
1126
  }
1132
1127
 
1133
1128
  export const MeminiPlugin = async ({ client, worktree, directory }, options) => {
1129
+ // Structured logger is primary; console.error is the fallback when it
1130
+ // throws (absent client.app.log). Direct call so a missing app.log reaches
1131
+ // the catch. Symbols match oh-my-opencode-slim: [ok]/[x]/[!]/[i].
1132
+ const GREEN = "\x1b[32m";
1133
+ const RED = "\x1b[31m";
1134
+ const YELLOW = "\x1b[33m";
1135
+ const BLUE = "\x1b[34m";
1136
+ const RESET = "\x1b[0m";
1134
1137
  const log = {
1138
+ error: (message) => {
1139
+ try {
1140
+ client.app.log({ body: { service: "memini", level: "error", message } });
1141
+ } catch {
1142
+ console.error(`${RED}[x]${RESET} [memini] ${message}`);
1143
+ }
1144
+ },
1135
1145
  warn: (message) => {
1136
- // client.app.log is opencode's structured logger; fall back to stderr.
1137
1146
  try {
1138
- client?.app?.log?.({ body: { service: "memini", level: "warn", message } });
1147
+ client.app.log({ body: { service: "memini", level: "warn", message } });
1148
+ } catch {
1149
+ console.error(`${YELLOW}[!]${RESET} [memini] ${message}`);
1150
+ }
1151
+ },
1152
+ info: (message) => {
1153
+ try {
1154
+ client.app.log({ body: { service: "memini", level: "info", message } });
1155
+ } catch {
1156
+ console.error(`${BLUE}[i]${RESET} [memini] ${message}`);
1157
+ }
1158
+ },
1159
+ success: (message) => {
1160
+ try {
1161
+ client.app.log({ body: { service: "memini", level: "info", message } });
1139
1162
  } catch {
1140
- /* ignore logging failures */
1163
+ console.error(`${GREEN}[ok]${RESET} [memini] ${message}`);
1141
1164
  }
1142
- console.error(`[memini] ${message}`);
1143
1165
  },
1144
1166
  };
1145
1167
 
@@ -1245,7 +1267,7 @@ export const MeminiPlugin = async ({ client, worktree, directory }, options) =>
1245
1267
  excludeIds: serverExcludeIds ? excludeIds : [],
1246
1268
  onExcludeIdsUnsupported: () => {
1247
1269
  serverExcludeIds = false;
1248
- log.warn("memini: server does not accept exclude_ids; using client-side dedupe only");
1270
+ log.info("memini: server does not accept exclude_ids; using client-side dedupe only");
1249
1271
  },
1250
1272
  });
1251
1273
 
@@ -1256,7 +1278,7 @@ export const MeminiPlugin = async ({ client, worktree, directory }, options) =>
1256
1278
  try {
1257
1279
  return await fn(...args);
1258
1280
  } catch (error) {
1259
- log.warn(`${name} hook failed: ${String(error)}`);
1281
+ log.error(`${name} hook failed: ${String(error)}`);
1260
1282
  }
1261
1283
  };
1262
1284
 
@@ -1375,7 +1397,7 @@ export const MeminiPlugin = async ({ client, worktree, directory }, options) =>
1375
1397
  result = await Promise.race([settled, budget]);
1376
1398
  clearTimeout(timer);
1377
1399
  if (result === BUDGET_EXPIRED) {
1378
- log.warn(
1400
+ log.info(
1379
1401
  `recall exceeded its ${live.recall_budget_ms}ms budget; late results will inject next turn`,
1380
1402
  );
1381
1403
  if (sessionID) {
@@ -1480,20 +1502,20 @@ export const MeminiPlugin = async ({ client, worktree, directory }, options) =>
1480
1502
  const cur = parseVersion(CLIENT_VERSION);
1481
1503
  const nxt = parseVersion(latest);
1482
1504
  if (!cur || !nxt || cur.major !== nxt.major) {
1483
- log.warn(`auto-update: v${latest} available (major bump — update manually: pin @eleboucher/opencode-memini@${latest} in opencode.json)`);
1505
+ log.info(`auto-update: v${latest} available (major bump — update manually: pin @eleboucher/opencode-memini@${latest} in opencode.json)`);
1484
1506
  return;
1485
1507
  }
1486
- log.warn(`auto-update: updating ${CLIENT_VERSION} → ${latest}`);
1508
+ log.info(`auto-update: updating ${CLIENT_VERSION} → ${latest}`);
1487
1509
  const installDir = prepareCacheUpdate(latest, log);
1488
1510
  if (!installDir) return;
1489
1511
  const ok = runNpmInstall(installDir);
1490
1512
  if (ok) {
1491
- log.warn(`auto-update: installed v${latest} — restart opencode to apply`);
1513
+ log.success(`auto-update: installed v${latest} — restart opencode to apply`);
1492
1514
  } else {
1493
- log.warn(`auto-update: npm install failed; will retry next session`);
1515
+ log.error(`auto-update: npm install failed; will retry next session`);
1494
1516
  }
1495
1517
  } catch (err) {
1496
- log.warn(`auto-update: check failed: ${String(err)}`);
1518
+ log.error(`auto-update: check failed: ${String(err)}`);
1497
1519
  }
1498
1520
  })();
1499
1521
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eleboucher/opencode-memini",
3
- "version": "0.7.9",
3
+ "version": "0.7.11",
4
4
  "description": "Automatic cross-session memory for opencode via memini — recall before each turn, capture after.",
5
5
  "keywords": [
6
6
  "memini",