opencode-mastra-om 0.1.16 → 0.1.17

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/dist/index.js +60 -214
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -178099,104 +178099,65 @@ var MastraPlugin = async (ctx) => {
178099
178099
  omLog(`[credentials] set ${envVars.join(", ")} from config.apiKey`);
178100
178100
  }
178101
178101
  }
178102
- if (!config2.apiKey) {
178103
- try {
178104
- const providersResponse = await Promise.race([
178105
- ctx.client.config.providers(),
178106
- new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), 3000))
178107
- ]);
178108
- if (providersResponse.data) {
178109
- for (const provider of providersResponse.data.providers) {
178110
- const key = provider.key ?? provider.apiKey ?? provider.token;
178111
- if (key && provider.env) {
178112
- for (const envVar of provider.env) {
178113
- if (!process.env[envVar]) {
178114
- process.env[envVar] = key;
178115
- omLog(`[credentials] set ${envVar} from provider store`);
178116
- }
178102
+ try {
178103
+ const providersResponse = await ctx.client.config.providers();
178104
+ if (providersResponse.data) {
178105
+ for (const provider of providersResponse.data.providers) {
178106
+ const key = provider.key ?? provider.apiKey ?? provider.token;
178107
+ if (key && provider.env) {
178108
+ for (const envVar of provider.env) {
178109
+ if (!process.env[envVar]) {
178110
+ process.env[envVar] = key;
178111
+ omLog(`[credentials] set ${envVar} from provider store`);
178117
178112
  }
178118
178113
  }
178119
178114
  }
178120
178115
  }
178121
- } catch (e2) {
178122
- omLog(`[credentials] provider store unavailable: ${e2}`);
178123
178116
  }
178117
+ } catch (e2) {
178118
+ omLog(`[credentials] provider store unavailable: ${e2}`);
178124
178119
  }
178125
178120
  credentialsReady = true;
178126
178121
  omLog(`[credentials] resolved. GOOGLE_GENERATIVE_AI_API_KEY=${process.env.GOOGLE_GENERATIVE_AI_API_KEY ? "set" : "missing"}`);
178127
178122
  };
178128
178123
  let store;
178129
- let om;
178130
- let initFailed = false;
178131
- try {
178132
- if (config2.storageUrl && (config2.storageUrl.startsWith("postgresql://") || config2.storageUrl.startsWith("postgres://"))) {
178133
- omLog(`[init] using PostgreSQL storage: ${config2.storageUrl.replace(/:\/\/[^@]+@/, "://<redacted>@")}`);
178134
- const pgMod = await new Function('return import("@mastra/pg")')();
178135
- const PostgresStore = pgMod.PostgresStore;
178136
- store = new PostgresStore({ connectionString: config2.storageUrl });
178137
- await store.init();
178138
- } else {
178139
- const url2 = config2.storageUrl ?? `file:${join5(ctx.directory, config2.storagePath ?? DEFAULT_STORAGE_PATH)}`;
178140
- if (!config2.storageUrl) {
178141
- const dbAbsolutePath = join5(ctx.directory, config2.storagePath ?? DEFAULT_STORAGE_PATH);
178142
- await mkdir2(dirname4(dbAbsolutePath), { recursive: true });
178143
- }
178144
- omLog(`[init] using SQLite/LibSQL storage: ${url2}`);
178145
- store = new LibSQLStore({ id: "mastra-om", url: url2 });
178146
- await store.init();
178147
- }
178148
- const storage = await store.getStore("memory");
178149
- if (!storage) {
178150
- omLog(`[init] ERROR: failed to get storage — OM disabled`);
178151
- initFailed = true;
178152
- } else {
178153
- const omOptions2 = {
178154
- storage,
178155
- scope: config2.scope,
178156
- shareTokenBudget: config2.shareTokenBudget,
178157
- observation: {
178158
- ...config2.observation,
178159
- ...config2.observationModel ? { model: config2.observationModel } : {}
178160
- },
178161
- reflection: {
178162
- ...config2.reflection,
178163
- ...config2.reflectionModel ? { model: config2.reflectionModel } : {}
178164
- }
178165
- };
178166
- if (config2.model && !config2.observationModel && !config2.reflectionModel) {
178167
- omOptions2.model = config2.model;
178168
- }
178169
- om = new ObservationalMemory(omOptions2);
178170
- omLog(`[init] ObservationalMemory created, model=${config2.model ?? "default"}`);
178171
- try {
178172
- const db = store.turso;
178173
- if (db) {
178174
- await db.execute(`CREATE TABLE IF NOT EXISTS mastra_om_backups (
178175
- id TEXT PRIMARY KEY,
178176
- lookupKey TEXT NOT NULL,
178177
- slot INTEGER NOT NULL,
178178
- generationCount INTEGER NOT NULL DEFAULT 0,
178179
- observations TEXT,
178180
- observationTokenCount INTEGER NOT NULL DEFAULT 0,
178181
- lastObservedAt TEXT,
178182
- lastReflectionAt TEXT,
178183
- pendingMessageTokens INTEGER NOT NULL DEFAULT 0,
178184
- observedMessageIds TEXT NOT NULL DEFAULT '[]',
178185
- triggerEvent TEXT,
178186
- savedAt TEXT NOT NULL,
178187
- UNIQUE(lookupKey, slot)
178188
- )`);
178189
- omLog(`[init] mastra_om_backups table ready`);
178190
- }
178191
- } catch (tableErr) {
178192
- omLog(`[init] WARNING: could not create mastra_om_backups: ${tableErr instanceof Error ? tableErr.message : String(tableErr)}`);
178193
- }
178124
+ if (config2.storageUrl && (config2.storageUrl.startsWith("postgresql://") || config2.storageUrl.startsWith("postgres://"))) {
178125
+ omLog(`[init] using PostgreSQL storage: ${config2.storageUrl.replace(/:\/\/[^@]+@/, "://<redacted>@")}`);
178126
+ const pgMod = await new Function('return import("@mastra/pg")')();
178127
+ const PostgresStore = pgMod.PostgresStore;
178128
+ store = new PostgresStore({ connectionString: config2.storageUrl });
178129
+ await store.init();
178130
+ } else {
178131
+ const url2 = config2.storageUrl ?? `file:${join5(ctx.directory, config2.storagePath ?? DEFAULT_STORAGE_PATH)}`;
178132
+ if (!config2.storageUrl) {
178133
+ const dbAbsolutePath = join5(ctx.directory, config2.storagePath ?? DEFAULT_STORAGE_PATH);
178134
+ await mkdir2(dirname4(dbAbsolutePath), { recursive: true });
178135
+ }
178136
+ omLog(`[init] using SQLite/LibSQL storage: ${url2}`);
178137
+ store = new LibSQLStore({ id: "mastra-om", url: url2 });
178138
+ await store.init();
178139
+ }
178140
+ const storage = await store.getStore("memory");
178141
+ if (!storage)
178142
+ throw new Error(`mastra-om: failed to initialize storage`);
178143
+ const omOptions = {
178144
+ storage,
178145
+ scope: config2.scope,
178146
+ shareTokenBudget: config2.shareTokenBudget,
178147
+ observation: {
178148
+ ...config2.observation,
178149
+ ...config2.observationModel ? { model: config2.observationModel } : {}
178150
+ },
178151
+ reflection: {
178152
+ ...config2.reflection,
178153
+ ...config2.reflectionModel ? { model: config2.reflectionModel } : {}
178194
178154
  }
178195
- } catch (err) {
178196
- const msg = err instanceof Error ? err.message : String(err);
178197
- omLog(`[init] ERROR during storage init: ${msg} — OM disabled`);
178198
- initFailed = true;
178155
+ };
178156
+ if (config2.model && !config2.observationModel && !config2.reflectionModel) {
178157
+ omOptions.model = config2.model;
178199
178158
  }
178159
+ const om = new ObservationalMemory(omOptions);
178160
+ omLog(`[init] ObservationalMemory created, model=${config2.model ?? "default"}`);
178200
178161
  const backupObservations = async (threadId, trigger) => {
178201
178162
  try {
178202
178163
  const record3 = await om.getRecord(threadId);
@@ -178215,15 +178176,15 @@ var MastraPlugin = async (ctx) => {
178215
178176
  lastReflectionAt: record3.lastReflectionAt ?? null,
178216
178177
  pendingMessageTokens: record3.pendingMessageTokens ?? 0,
178217
178178
  observedMessageIds: record3.observedMessageIds ?? "[]",
178218
- triggerEvent: trigger,
178179
+ trigger,
178219
178180
  savedAt: new Date().toISOString()
178220
178181
  };
178221
178182
  await db.execute({
178222
178183
  sql: `INSERT INTO mastra_om_backups
178223
178184
  (id, lookupKey, slot, generationCount, observations, observationTokenCount,
178224
- lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, triggerEvent, savedAt)
178185
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt)
178225
178186
  SELECT hex(randomblob(16)), lookupKey, 2, generationCount, observations, observationTokenCount,
178226
- lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, triggerEvent, savedAt
178187
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt
178227
178188
  FROM mastra_om_backups WHERE lookupKey = ? AND slot = 1
178228
178189
  ON CONFLICT(lookupKey, slot) DO UPDATE SET
178229
178190
  generationCount = excluded.generationCount,
@@ -178233,14 +178194,14 @@ var MastraPlugin = async (ctx) => {
178233
178194
  lastReflectionAt = excluded.lastReflectionAt,
178234
178195
  pendingMessageTokens = excluded.pendingMessageTokens,
178235
178196
  observedMessageIds = excluded.observedMessageIds,
178236
- triggerEvent = excluded.triggerEvent,
178197
+ trigger = excluded.trigger,
178237
178198
  savedAt = excluded.savedAt`,
178238
178199
  args: [threadId]
178239
178200
  });
178240
178201
  await db.execute({
178241
178202
  sql: `INSERT INTO mastra_om_backups
178242
178203
  (id, lookupKey, slot, generationCount, observations, observationTokenCount,
178243
- lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, triggerEvent, savedAt)
178204
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt)
178244
178205
  VALUES (hex(randomblob(16)), ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?)
178245
178206
  ON CONFLICT(lookupKey, slot) DO UPDATE SET
178246
178207
  generationCount = excluded.generationCount,
@@ -178250,7 +178211,7 @@ var MastraPlugin = async (ctx) => {
178250
178211
  lastReflectionAt = excluded.lastReflectionAt,
178251
178212
  pendingMessageTokens = excluded.pendingMessageTokens,
178252
178213
  observedMessageIds = excluded.observedMessageIds,
178253
- triggerEvent = excluded.triggerEvent,
178214
+ trigger = excluded.trigger,
178254
178215
  savedAt = excluded.savedAt`,
178255
178216
  args: [
178256
178217
  threadId,
@@ -178301,12 +178262,8 @@ var MastraPlugin = async (ctx) => {
178301
178262
  };
178302
178263
  return {
178303
178264
  event: async ({ event }) => {
178304
- omLog(`[event] received event type=${event.type}`);
178305
- if (initFailed || !om)
178306
- return;
178307
178265
  if (event.type === "session.created") {
178308
178266
  const sessionId = event.properties.info.id;
178309
- omLog(`[session] creating record for ${sessionId}`);
178310
178267
  try {
178311
178268
  await om.getOrCreateRecord(sessionId);
178312
178269
  omLog(`[session] initialized record for ${sessionId}`);
@@ -178317,32 +178274,16 @@ var MastraPlugin = async (ctx) => {
178317
178274
  }
178318
178275
  },
178319
178276
  "experimental.chat.messages.transform": async (_input, output) => {
178320
- omLog(`[transform] messages.transform called, messages=${output.messages.length}`);
178321
- if (initFailed || !om) {
178322
- omLog(`[transform] OM not initialized, skipping`);
178323
- return;
178324
- }
178325
178277
  const sessionId = output.messages[0]?.info.sessionID;
178326
- if (!sessionId) {
178327
- omLog(`[transform] no sessionId, skipping`);
178278
+ if (!sessionId)
178328
178279
  return;
178329
- }
178330
- omLog(`[transform] sessionId=${sessionId}`);
178331
- omLog(`[transform] calling resolveCredentials`);
178332
178280
  await resolveCredentials();
178333
- omLog(`[transform] resolveCredentials done`);
178334
178281
  try {
178335
- omLog(`[transform] converting messages`);
178336
178282
  const mastraMessages = convertMessages2(output.messages, sessionId);
178337
- omLog(`[transform] converted ${mastraMessages.length} messages`);
178338
178283
  if (mastraMessages.length > 0) {
178339
- omLog(`[transform] calling runObserve`);
178340
178284
  await runObserve(sessionId, mastraMessages);
178341
- omLog(`[transform] runObserve done`);
178342
178285
  }
178343
- omLog(`[transform] getting record`);
178344
178286
  const record3 = await om.getRecord(sessionId);
178345
- omLog(`[transform] got record, lastObservedAt=${record3?.lastObservedAt}`);
178346
178287
  if (record3?.lastObservedAt) {
178347
178288
  const lastObservedAt = new Date(record3.lastObservedAt);
178348
178289
  output.messages = output.messages.filter(({ info }) => {
@@ -178350,7 +178291,6 @@ var MastraPlugin = async (ctx) => {
178350
178291
  });
178351
178292
  }
178352
178293
  lastError = null;
178353
- omLog(`[transform] done`);
178354
178294
  } catch (err) {
178355
178295
  lastError = err instanceof Error ? err.message : String(err);
178356
178296
  omLog(`[error] transform failed: ${lastError}`);
@@ -178360,20 +178300,11 @@ var MastraPlugin = async (ctx) => {
178360
178300
  }
178361
178301
  },
178362
178302
  "experimental.chat.system.transform": async (input, output) => {
178363
- omLog(`[system.transform] called, sessionID=${input.sessionID}`);
178364
- if (initFailed || !om) {
178365
- omLog(`[system.transform] OM not initialized, skipping`);
178366
- return;
178367
- }
178368
178303
  const sessionId = input.sessionID;
178369
- if (!sessionId) {
178370
- omLog(`[system.transform] no sessionId, skipping`);
178304
+ if (!sessionId)
178371
178305
  return;
178372
- }
178373
178306
  try {
178374
- omLog(`[system.transform] getting observations`);
178375
178307
  const observations = await om.getObservations(sessionId);
178376
- omLog(`[system.transform] got observations, length=${observations?.length ?? 0}`);
178377
178308
  if (!observations)
178378
178309
  return;
178379
178310
  const optimized = optimizeObservationsForContext(observations);
@@ -178386,10 +178317,7 @@ ${optimized}
178386
178317
  ${OBSERVATION_CONTEXT_INSTRUCTIONS}
178387
178318
 
178388
178319
  ${OBSERVATION_CONTINUATION_HINT}`);
178389
- omLog(`[system.transform] done`);
178390
- } catch (err) {
178391
- omLog(`[system.transform] error: ${err instanceof Error ? err.message : String(err)}`);
178392
- }
178320
+ } catch {}
178393
178321
  },
178394
178322
  tool: {
178395
178323
  om_status: tool5({
@@ -178449,7 +178377,7 @@ ${OBSERVATION_CONTINUATION_HINT}`);
178449
178377
  }
178450
178378
  }),
178451
178379
  om_observe: tool5({
178452
- description: "Manually trigger an observation cycle right now, without waiting for the token threshold. Automatically chunks large message sets if chunkTokens is configured.",
178380
+ description: "Manually trigger an observation cycle right now, without waiting for the token threshold.",
178453
178381
  args: {},
178454
178382
  async execute(_args, context2) {
178455
178383
  const threadId = context2.sessionID;
@@ -178460,53 +178388,8 @@ ${OBSERVATION_CONTINUATION_HINT}`);
178460
178388
  return "No messages to observe.";
178461
178389
  const mastraMessages = convertMessages2(resp.data, threadId);
178462
178390
  await backupObservations(threadId, "pre-observe");
178463
- const chunkBytes = config2.chunkBytes;
178464
- if (!chunkBytes) {
178465
- await runObserve(threadId, mastraMessages);
178466
- return "Observation cycle triggered. Check om_status for results.";
178467
- }
178468
- const chunks = [];
178469
- let currentChunk = [];
178470
- let currentBytes = 0;
178471
- for (const msg of mastraMessages) {
178472
- const msgBytes = Buffer.byteLength(JSON.stringify(msg), "utf8");
178473
- if (currentBytes + msgBytes > chunkBytes && currentChunk.length > 0) {
178474
- chunks.push(currentChunk);
178475
- currentChunk = [msg];
178476
- currentBytes = msgBytes;
178477
- } else {
178478
- currentChunk.push(msg);
178479
- currentBytes += msgBytes;
178480
- }
178481
- }
178482
- if (currentChunk.length > 0)
178483
- chunks.push(currentChunk);
178484
- if (chunks.length === 1) {
178485
- await runObserve(threadId, mastraMessages);
178486
- return "Observation cycle triggered (single chunk). Check om_status for results.";
178487
- }
178488
- omLog(`[observe] chunked into ${chunks.length} chunks of ~${Math.round(chunkBytes / 1024)}KB each`);
178489
- ctx.client.tui.showToast({
178490
- body: { title: "Mastra OM", message: `Observing in ${chunks.length} chunks (~${Math.round(chunkBytes / 1024)}KB each)...`, variant: "info", duration: 5000 }
178491
- });
178492
- const refThreshold = resolveThreshold(omOptions.reflection?.observationTokens ?? 60000);
178493
- const reflectAt = Math.floor(refThreshold * 0.8);
178494
- for (let i = 0;i < chunks.length; i++) {
178495
- omLog(`[observe] processing chunk ${i + 1}/${chunks.length} (${chunks[i].length} messages)`);
178496
- await runObserve(threadId, chunks[i]);
178497
- if (i < chunks.length - 1) {
178498
- const record3 = await om.getRecord(threadId);
178499
- const obsTokens = record3?.observationTokenCount ?? 0;
178500
- if (obsTokens >= reflectAt) {
178501
- omLog(`[observe] observations at ${obsTokens} tokens (>= ${reflectAt}), reflecting before next chunk`);
178502
- ctx.client.tui.showToast({
178503
- body: { title: "Mastra OM", message: `Reflecting between chunks (${i + 1}/${chunks.length})...`, variant: "info", duration: 5000 }
178504
- });
178505
- await om.reflect(threadId);
178506
- }
178507
- }
178508
- }
178509
- return `Observation complete — processed ${chunks.length} chunks, ${mastraMessages.length} messages total. Check om_status for results.`;
178391
+ await runObserve(threadId, mastraMessages);
178392
+ return "Observation cycle triggered. Check memory_status for results.";
178510
178393
  } catch (err) {
178511
178394
  const msg = err instanceof Error ? err.message : String(err);
178512
178395
  lastError = msg;
@@ -178592,7 +178475,7 @@ ${OBSERVATION_CONTINUATION_HINT}`);
178592
178475
  `✅ Restored from slot ${slot}`,
178593
178476
  ` Generation: ${row.generationCount}`,
178594
178477
  ` Saved at: ${row.savedAt}`,
178595
- ` Trigger: ${row.triggerEvent}`,
178478
+ ` Trigger: ${row.trigger}`,
178596
178479
  ` Observation tokens: ${row.observationTokenCount}`,
178597
178480
  ` Last observed: ${row.lastObservedAt ?? "never"}`,
178598
178481
  ` Last reflection: ${row.lastReflectionAt ?? "never"}`
@@ -178604,43 +178487,6 @@ ${OBSERVATION_CONTINUATION_HINT}`);
178604
178487
  }
178605
178488
  }
178606
178489
  }),
178607
- om_reset: tool5({
178608
- description: "Reset observational memory for this session to a clean slate. Backs up current state first so it can be restored via om_restore.",
178609
- args: {},
178610
- async execute(_args, context2) {
178611
- const threadId = context2.sessionID;
178612
- try {
178613
- const db = store.turso;
178614
- if (!db)
178615
- return "Raw DB access unavailable.";
178616
- await backupObservations(threadId, "pre-reset");
178617
- await db.execute({
178618
- sql: `UPDATE mastra_observational_memory SET
178619
- activeObservations = '',
178620
- generationCount = 0,
178621
- observationTokenCount = 0,
178622
- lastObservedAt = NULL,
178623
- lastReflectionAt = NULL,
178624
- pendingMessageTokens = 0,
178625
- observedMessageIds = '[]',
178626
- bufferedObservations = NULL,
178627
- bufferedObservationTokens = 0,
178628
- bufferedMessageIds = NULL,
178629
- bufferedReflection = NULL,
178630
- bufferedReflectionTokens = 0,
178631
- bufferedReflectionInputTokens = 0,
178632
- reflectedObservationLineCount = 0
178633
- WHERE lookupKey = ?`,
178634
- args: [threadId]
178635
- });
178636
- omLog(`[reset] observations cleared for ${threadId}`);
178637
- return "✅ Observational memory reset. Previous state saved to backup slot 1 — use om_restore to recover if needed.";
178638
- } catch (err) {
178639
- const msg = err instanceof Error ? err.message : String(err);
178640
- return `Reset failed: ${msg}`;
178641
- }
178642
- }
178643
- }),
178644
178490
  om_config: tool5({
178645
178491
  description: "Show the current Mastra Observational Memory configuration.",
178646
178492
  args: {},
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "opencode-mastra-om",
4
- "version": "0.1.16",
4
+ "version": "0.1.17",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "description": "Enhanced Mastra Observational Memory plugin for OpenCode — persistent cross-session memory with observation, reflection, and manual trigger tools",