@mojoaar/opencode-mimir 0.16.0 → 0.18.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Plugin } from '@opencode/plugin';
2
2
  export declare const DIGEST_HEADER = "## What this project already knows (Mimir)\n\n";
3
+ export declare const NUDGE_HEADER = "## Memory check (Mimir)\n\n";
3
4
  /**
4
5
  * One injection point and two tools. The hook is what puts the project's
5
6
  * digest in front of the model before the first turn, so a session starts
package/dist/index.js CHANGED
@@ -3,6 +3,16 @@ import { callTool, detectRepo } from './client.js';
3
3
  import { resolveConfig } from './config.js';
4
4
  import { registerTools } from './tools.js';
5
5
  export const DIGEST_HEADER = '## What this project already knows (Mimir)\n\n';
6
+ export const NUDGE_HEADER = '## Memory check (Mimir)\n\n';
7
+ /**
8
+ * A fact written before a compaction is cheap; one that has already been
9
+ * summarised away is gone. So the reminder comes every twenty turns, and again
10
+ * the moment the transcript shrinks, which is what a compaction looks like from
11
+ * the message list this hook is handed.
12
+ */
13
+ const NUDGE_EVERY = 20;
14
+ const NUDGE = 'If this session settled a decision, a convention or a gotcha that is not in Mimir yet, ' +
15
+ 'call memory_write now at one clear path, before the detail is compacted away.';
6
16
  /**
7
17
  * One injection point and two tools. The hook is what puts the project's
8
18
  * digest in front of the model before the first turn, so a session starts
@@ -35,10 +45,20 @@ export default Plugin.define({
35
45
  return;
36
46
  event.system.push({ type: 'text', text: `${DIGEST_HEADER}${text}` });
37
47
  });
48
+ const counts = new Map();
49
+ const nudge = await ctx.session.hook('context', async (event) => {
50
+ const state = counts.get(event.sessionID) ?? { turns: 0, nudgedAt: 0 };
51
+ const turns = event.messages?.length ?? 0;
52
+ const due = turns < state.turns || turns - state.nudgedAt >= NUDGE_EVERY;
53
+ counts.set(event.sessionID, { turns, nudgedAt: due ? turns : state.nudgedAt });
54
+ if (due)
55
+ event.system.push({ type: 'text', text: `${NUDGE_HEADER}${NUDGE}` });
56
+ });
38
57
  const tools = await registerTools(ctx, config, repo);
39
58
  return async () => {
40
59
  await tools.dispose();
41
60
  await session.dispose();
61
+ await nudge.dispose();
42
62
  };
43
63
  },
44
64
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mojoaar/opencode-mimir",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Mimir long-term memory for OpenCode sessions",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/index.ts CHANGED
@@ -4,6 +4,18 @@ import { resolveConfig } from './config.js'
4
4
  import { registerTools } from './tools.js'
5
5
 
6
6
  export const DIGEST_HEADER = '## What this project already knows (Mimir)\n\n'
7
+ export const NUDGE_HEADER = '## Memory check (Mimir)\n\n'
8
+
9
+ /**
10
+ * A fact written before a compaction is cheap; one that has already been
11
+ * summarised away is gone. So the reminder comes every twenty turns, and again
12
+ * the moment the transcript shrinks, which is what a compaction looks like from
13
+ * the message list this hook is handed.
14
+ */
15
+ const NUDGE_EVERY = 20
16
+ const NUDGE =
17
+ 'If this session settled a decision, a convention or a gotcha that is not in Mimir yet, ' +
18
+ 'call memory_write now at one clear path, before the detail is compacted away.'
7
19
 
8
20
  /**
9
21
  * One injection point and two tools. The hook is what puts the project's
@@ -43,11 +55,21 @@ export default Plugin.define({
43
55
  event.system.push({ type: 'text', text: `${DIGEST_HEADER}${text}` })
44
56
  })
45
57
 
58
+ const counts = new Map<string, { turns: number; nudgedAt: number }>()
59
+ const nudge = await ctx.session.hook('context', async (event) => {
60
+ const state = counts.get(event.sessionID) ?? { turns: 0, nudgedAt: 0 }
61
+ const turns = event.messages?.length ?? 0
62
+ const due = turns < state.turns || turns - state.nudgedAt >= NUDGE_EVERY
63
+ counts.set(event.sessionID, { turns, nudgedAt: due ? turns : state.nudgedAt })
64
+ if (due) event.system.push({ type: 'text', text: `${NUDGE_HEADER}${NUDGE}` })
65
+ })
66
+
46
67
  const tools = await registerTools(ctx, config, repo)
47
68
 
48
69
  return async () => {
49
70
  await tools.dispose()
50
71
  await session.dispose()
72
+ await nudge.dispose()
51
73
  }
52
74
  },
53
75
  })