opencode-mastra-om 0.1.4 → 0.1.6

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 +189 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -179825,38 +179825,75 @@ var MastraPlugin = async (ctx) => {
179825
179825
  }
179826
179826
  const om = new ObservationalMemory(omOptions);
179827
179827
  omLog(`[init] ObservationalMemory created, model=${config2.model ?? "default"}`);
179828
- const backupObservations = async (threadId, label) => {
179828
+ const backupObservations = async (threadId, trigger) => {
179829
179829
  try {
179830
179830
  const record3 = await om.getRecord(threadId);
179831
179831
  const observations = record3?.activeObservations;
179832
179832
  if (!observations)
179833
179833
  return;
179834
- const generationCount = record3?.generationCount ?? 0;
179835
- const lookupKey = threadId;
179836
- const savedAt = new Date().toISOString();
179837
179834
  const db = store.turso;
179838
179835
  if (!db)
179839
179836
  return;
179837
+ const snap = {
179838
+ lookupKey: threadId,
179839
+ generationCount: record3.generationCount ?? 0,
179840
+ observations,
179841
+ observationTokenCount: record3.observationTokenCount ?? 0,
179842
+ lastObservedAt: record3.lastObservedAt ?? null,
179843
+ lastReflectionAt: record3.lastReflectionAt ?? null,
179844
+ pendingMessageTokens: record3.pendingMessageTokens ?? 0,
179845
+ observedMessageIds: record3.observedMessageIds ?? "[]",
179846
+ trigger,
179847
+ savedAt: new Date().toISOString()
179848
+ };
179840
179849
  await db.execute({
179841
- sql: `INSERT INTO mastra_om_backups (id, lookupKey, slot, generationCount, observations, savedAt)
179842
- SELECT hex(randomblob(16)), lookupKey, 2, generationCount, observations, savedAt
179850
+ sql: `INSERT INTO mastra_om_backups
179851
+ (id, lookupKey, slot, generationCount, observations, observationTokenCount,
179852
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt)
179853
+ SELECT hex(randomblob(16)), lookupKey, 2, generationCount, observations, observationTokenCount,
179854
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt
179843
179855
  FROM mastra_om_backups WHERE lookupKey = ? AND slot = 1
179844
179856
  ON CONFLICT(lookupKey, slot) DO UPDATE SET
179845
179857
  generationCount = excluded.generationCount,
179846
179858
  observations = excluded.observations,
179859
+ observationTokenCount = excluded.observationTokenCount,
179860
+ lastObservedAt = excluded.lastObservedAt,
179861
+ lastReflectionAt = excluded.lastReflectionAt,
179862
+ pendingMessageTokens = excluded.pendingMessageTokens,
179863
+ observedMessageIds = excluded.observedMessageIds,
179864
+ trigger = excluded.trigger,
179847
179865
  savedAt = excluded.savedAt`,
179848
- args: [lookupKey]
179866
+ args: [threadId]
179849
179867
  });
179850
179868
  await db.execute({
179851
- sql: `INSERT INTO mastra_om_backups (id, lookupKey, slot, generationCount, observations, savedAt)
179852
- VALUES (hex(randomblob(16)), ?, 1, ?, ?, ?)
179869
+ sql: `INSERT INTO mastra_om_backups
179870
+ (id, lookupKey, slot, generationCount, observations, observationTokenCount,
179871
+ lastObservedAt, lastReflectionAt, pendingMessageTokens, observedMessageIds, trigger, savedAt)
179872
+ VALUES (hex(randomblob(16)), ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?)
179853
179873
  ON CONFLICT(lookupKey, slot) DO UPDATE SET
179854
179874
  generationCount = excluded.generationCount,
179855
179875
  observations = excluded.observations,
179876
+ observationTokenCount = excluded.observationTokenCount,
179877
+ lastObservedAt = excluded.lastObservedAt,
179878
+ lastReflectionAt = excluded.lastReflectionAt,
179879
+ pendingMessageTokens = excluded.pendingMessageTokens,
179880
+ observedMessageIds = excluded.observedMessageIds,
179881
+ trigger = excluded.trigger,
179856
179882
  savedAt = excluded.savedAt`,
179857
- args: [lookupKey, generationCount, observations, savedAt]
179883
+ args: [
179884
+ threadId,
179885
+ snap.generationCount,
179886
+ snap.observations,
179887
+ snap.observationTokenCount,
179888
+ snap.lastObservedAt,
179889
+ snap.lastReflectionAt,
179890
+ snap.pendingMessageTokens,
179891
+ snap.observedMessageIds,
179892
+ snap.trigger,
179893
+ snap.savedAt
179894
+ ]
179858
179895
  });
179859
- omLog(`[backup] ${label} — saved gen ${generationCount} to slot 1, rotated old slot 1 → slot 2`);
179896
+ omLog(`[backup] ${trigger} — saved gen ${snap.generationCount} to slot 1, rotated old slot 1 → slot 2`);
179860
179897
  } catch (err) {
179861
179898
  omLog(`[backup] failed: ${err instanceof Error ? err.message : String(err)}`);
179862
179899
  }
@@ -180008,7 +180045,7 @@ ${OBSERVATION_CONTINUATION_HINT}`);
180008
180045
  }
180009
180046
  }),
180010
180047
  om_observe: tool5({
180011
- description: "Manually trigger an observation cycle right now, without waiting for the token threshold.",
180048
+ description: "Manually trigger an observation cycle right now, without waiting for the token threshold. Automatically chunks large message sets if chunkTokens is configured.",
180012
180049
  args: {},
180013
180050
  async execute(_args, context2) {
180014
180051
  const threadId = context2.sessionID;
@@ -180019,8 +180056,54 @@ ${OBSERVATION_CONTINUATION_HINT}`);
180019
180056
  return "No messages to observe.";
180020
180057
  const mastraMessages = convertMessages2(resp.data, threadId);
180021
180058
  await backupObservations(threadId, "pre-observe");
180022
- await runObserve(threadId, mastraMessages);
180023
- return "Observation cycle triggered. Check memory_status for results.";
180059
+ const chunkTokens = config2.chunkTokens;
180060
+ if (!chunkTokens) {
180061
+ await runObserve(threadId, mastraMessages);
180062
+ return "Observation cycle triggered. Check om_status for results.";
180063
+ }
180064
+ const tokenCounter = new TokenCounter;
180065
+ const chunks = [];
180066
+ let currentChunk = [];
180067
+ let currentTokens = 0;
180068
+ for (const msg of mastraMessages) {
180069
+ const msgTokens = tokenCounter.countMessages([msg]);
180070
+ if (currentTokens + msgTokens > chunkTokens && currentChunk.length > 0) {
180071
+ chunks.push(currentChunk);
180072
+ currentChunk = [msg];
180073
+ currentTokens = msgTokens;
180074
+ } else {
180075
+ currentChunk.push(msg);
180076
+ currentTokens += msgTokens;
180077
+ }
180078
+ }
180079
+ if (currentChunk.length > 0)
180080
+ chunks.push(currentChunk);
180081
+ if (chunks.length === 1) {
180082
+ await runObserve(threadId, mastraMessages);
180083
+ return "Observation cycle triggered (single chunk). Check om_status for results.";
180084
+ }
180085
+ omLog(`[observe] chunked into ${chunks.length} chunks of ~${chunkTokens} tokens each`);
180086
+ ctx.client.tui.showToast({
180087
+ body: { title: "Mastra OM", message: `Observing in ${chunks.length} chunks...`, variant: "info", duration: 5000 }
180088
+ });
180089
+ const refThreshold = resolveThreshold(omOptions.reflection?.observationTokens ?? 60000);
180090
+ const reflectAt = Math.floor(refThreshold * 0.8);
180091
+ for (let i = 0;i < chunks.length; i++) {
180092
+ omLog(`[observe] processing chunk ${i + 1}/${chunks.length} (${chunks[i].length} messages)`);
180093
+ await runObserve(threadId, chunks[i]);
180094
+ if (i < chunks.length - 1) {
180095
+ const record3 = await om.getRecord(threadId);
180096
+ const obsTokens = record3?.observationTokenCount ?? 0;
180097
+ if (obsTokens >= reflectAt) {
180098
+ omLog(`[observe] observations at ${obsTokens} tokens (>= ${reflectAt}), reflecting before next chunk`);
180099
+ ctx.client.tui.showToast({
180100
+ body: { title: "Mastra OM", message: `Reflecting between chunks (${i + 1}/${chunks.length})...`, variant: "info", duration: 5000 }
180101
+ });
180102
+ await om.reflect(threadId);
180103
+ }
180104
+ }
180105
+ }
180106
+ return `Observation complete — processed ${chunks.length} chunks, ${mastraMessages.length} messages total. Check om_status for results.`;
180024
180107
  } catch (err) {
180025
180108
  const msg = err instanceof Error ? err.message : String(err);
180026
180109
  lastError = msg;
@@ -180063,6 +180146,98 @@ ${OBSERVATION_CONTINUATION_HINT}`);
180063
180146
  }
180064
180147
  }
180065
180148
  }),
180149
+ om_restore: tool5({
180150
+ description: "Restore observational memory from backup slot 1 (most recent) or slot 2 (one generation older).",
180151
+ args: { slot: { type: "number", description: "1 = most recent backup, 2 = one generation older" } },
180152
+ async execute(args, context2) {
180153
+ const threadId = context2.sessionID;
180154
+ const slot = args.slot === 2 ? 2 : 1;
180155
+ try {
180156
+ const db = store.turso;
180157
+ if (!db)
180158
+ return "Raw DB access unavailable.";
180159
+ const result = await db.execute({
180160
+ sql: `SELECT * FROM mastra_om_backups WHERE lookupKey = ? AND slot = ?`,
180161
+ args: [threadId, slot]
180162
+ });
180163
+ const row = result.rows?.[0];
180164
+ if (!row)
180165
+ return `No backup found in slot ${slot}.`;
180166
+ await db.execute({
180167
+ sql: `UPDATE mastra_observational_memory SET
180168
+ activeObservations = ?,
180169
+ generationCount = ?,
180170
+ observationTokenCount = ?,
180171
+ lastObservedAt = ?,
180172
+ lastReflectionAt = ?,
180173
+ pendingMessageTokens = ?,
180174
+ observedMessageIds = ?
180175
+ WHERE lookupKey = ?`,
180176
+ args: [
180177
+ row.observations,
180178
+ row.generationCount,
180179
+ row.observationTokenCount,
180180
+ row.lastObservedAt,
180181
+ row.lastReflectionAt,
180182
+ row.pendingMessageTokens,
180183
+ row.observedMessageIds,
180184
+ threadId
180185
+ ]
180186
+ });
180187
+ omLog(`[restore] restored slot ${slot} — gen ${row.generationCount}, saved at ${row.savedAt}, trigger=${row.trigger}`);
180188
+ return [
180189
+ `✅ Restored from slot ${slot}`,
180190
+ ` Generation: ${row.generationCount}`,
180191
+ ` Saved at: ${row.savedAt}`,
180192
+ ` Trigger: ${row.trigger}`,
180193
+ ` Observation tokens: ${row.observationTokenCount}`,
180194
+ ` Last observed: ${row.lastObservedAt ?? "never"}`,
180195
+ ` Last reflection: ${row.lastReflectionAt ?? "never"}`
180196
+ ].join(`
180197
+ `);
180198
+ } catch (err) {
180199
+ const msg = err instanceof Error ? err.message : String(err);
180200
+ return `Restore failed: ${msg}`;
180201
+ }
180202
+ }
180203
+ }),
180204
+ om_reset: tool5({
180205
+ description: "Reset observational memory for this session to a clean slate. Backs up current state first so it can be restored via om_restore.",
180206
+ args: {},
180207
+ async execute(_args, context2) {
180208
+ const threadId = context2.sessionID;
180209
+ try {
180210
+ const db = store.turso;
180211
+ if (!db)
180212
+ return "Raw DB access unavailable.";
180213
+ await backupObservations(threadId, "pre-reset");
180214
+ await db.execute({
180215
+ sql: `UPDATE mastra_observational_memory SET
180216
+ activeObservations = '',
180217
+ generationCount = 0,
180218
+ observationTokenCount = 0,
180219
+ lastObservedAt = NULL,
180220
+ lastReflectionAt = NULL,
180221
+ pendingMessageTokens = 0,
180222
+ observedMessageIds = '[]',
180223
+ bufferedObservations = NULL,
180224
+ bufferedObservationTokens = 0,
180225
+ bufferedMessageIds = NULL,
180226
+ bufferedReflection = NULL,
180227
+ bufferedReflectionTokens = 0,
180228
+ bufferedReflectionInputTokens = 0,
180229
+ reflectedObservationLineCount = 0
180230
+ WHERE lookupKey = ?`,
180231
+ args: [threadId]
180232
+ });
180233
+ omLog(`[reset] observations cleared for ${threadId}`);
180234
+ return "✅ Observational memory reset. Previous state saved to backup slot 1 — use om_restore to recover if needed.";
180235
+ } catch (err) {
180236
+ const msg = err instanceof Error ? err.message : String(err);
180237
+ return `Reset failed: ${msg}`;
180238
+ }
180239
+ }
180240
+ }),
180066
180241
  om_config: tool5({
180067
180242
  description: "Show the current Mastra Observational Memory configuration.",
180068
180243
  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.4",
4
+ "version": "0.1.6",
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",