@bunkercache/opencode-memoir 0.2.3 → 0.3.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 (2) hide show
  1. package/dist/index.js +112 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -161,12 +161,16 @@ function resolveStoragePaths(worktree, projectId, config) {
161
161
  const relativePath = getGitignoreRelativePath(memoryDb.path, worktree);
162
162
  if (relativePath) {
163
163
  gitignorePaths.push(relativePath);
164
+ gitignorePaths.push(`${relativePath}-shm`);
165
+ gitignorePaths.push(`${relativePath}-wal`);
164
166
  }
165
167
  }
166
168
  if (historyDb?.isLocal && historyDb.manageGitignore && !sharedDatabase) {
167
169
  const relativePath = getGitignoreRelativePath(historyDb.path, worktree);
168
170
  if (relativePath && !gitignorePaths.includes(relativePath)) {
169
171
  gitignorePaths.push(relativePath);
172
+ gitignorePaths.push(`${relativePath}-shm`);
173
+ gitignorePaths.push(`${relativePath}-wal`);
170
174
  }
171
175
  }
172
176
  return {
@@ -1616,6 +1620,37 @@ class ChunkService {
1616
1620
  getRecentSummaryChunks(limit = 5) {
1617
1621
  return this.repository.getRecentSummaryChunks(limit);
1618
1622
  }
1623
+ getRecentChunks(options) {
1624
+ const limit = options?.limit ?? 10;
1625
+ let sql = `
1626
+ SELECT id, session_id, parent_id, depth, child_refs, content, summary,
1627
+ status, created_at, finalized_at, compacted_at, embedding
1628
+ FROM chunks
1629
+ `;
1630
+ const params = [];
1631
+ if (options?.sessionId) {
1632
+ sql += " WHERE session_id = ?";
1633
+ params.push(options.sessionId);
1634
+ }
1635
+ sql += " ORDER BY created_at DESC LIMIT ?";
1636
+ params.push(limit);
1637
+ const stmt = this.db.prepare(sql);
1638
+ const rows = stmt.all(...params);
1639
+ return rows.map((row) => ({
1640
+ id: row.id,
1641
+ sessionId: row.session_id,
1642
+ parentId: row.parent_id,
1643
+ depth: row.depth,
1644
+ childRefs: row.child_refs ? JSON.parse(row.child_refs) : null,
1645
+ content: JSON.parse(row.content),
1646
+ summary: row.summary,
1647
+ status: row.status,
1648
+ createdAt: row.created_at,
1649
+ finalizedAt: row.finalized_at,
1650
+ compactedAt: row.compacted_at,
1651
+ embedding: row.embedding
1652
+ }));
1653
+ }
1619
1654
  }
1620
1655
  var chunkService = null;
1621
1656
  function initializeChunkService(db, config) {
@@ -14556,28 +14591,89 @@ function estimateTokens2(text) {
14556
14591
  return Math.ceil(text.length / CHARS_PER_TOKEN2);
14557
14592
  }
14558
14593
  var historyTool = tool({
14559
- description: `Search session history for past work. Returns compact chunk summaries with IDs that can be expanded.
14594
+ description: `Browse or search session history. Returns chunk summaries with IDs for memoir_expand.
14595
+
14596
+ DEFAULTS: Searches current session only. Returns recent chunks if no query provided.
14597
+
14598
+ OPTIONS:
14599
+ - query: Search text (omit to list recent chunks)
14600
+ - all_sessions: true to include past sessions
14601
+ - limit: Max results (default 10)
14560
14602
 
14561
- CONTEXT BUDGET: Results are summaries (~50-200 tokens each). To view full chunk content, use memoir_expand. For deep exploration of multiple chunks, consider delegating to a subagent.`,
14603
+ Use memoir_expand({ chunk_id }) to see full content of any chunk.`,
14562
14604
  args: {
14563
- query: tool.schema.string().describe("Search query for finding relevant history"),
14564
- session_id: tool.schema.string().optional().describe("Limit search to a specific session"),
14565
- depth: tool.schema.number().optional().describe("Minimum depth to search (0 = original chunks, higher = summaries)"),
14566
- limit: tool.schema.number().optional().describe("Maximum number of results to return (default: 10, max recommended: 20)")
14605
+ query: tool.schema.string().optional().describe("Search query (omit to list recent chunks without searching)"),
14606
+ all_sessions: tool.schema.boolean().optional().describe("Include past sessions (default: current session only)"),
14607
+ session_ids: tool.schema.array(tool.schema.string()).optional().describe("Search specific session IDs"),
14608
+ depth: tool.schema.number().optional().describe("Minimum chunk depth (0=original, 1+=summaries)"),
14609
+ limit: tool.schema.number().optional().describe("Max results (default: 10)")
14567
14610
  },
14568
- async execute(args) {
14611
+ async execute(args, context) {
14569
14612
  const chunkService2 = getChunkService();
14570
- const results = chunkService2.search(args.query, {
14571
- sessionId: args.session_id,
14613
+ let sessionId;
14614
+ let searchScope;
14615
+ if (args.session_ids && args.session_ids.length > 0) {
14616
+ sessionId = args.session_ids[0];
14617
+ searchScope = `sessions: ${args.session_ids.join(", ")}`;
14618
+ } else if (args.all_sessions) {
14619
+ sessionId = undefined;
14620
+ searchScope = "all sessions";
14621
+ } else {
14622
+ sessionId = context.sessionID;
14623
+ searchScope = "current session";
14624
+ }
14625
+ const limit = args.limit ?? 10;
14626
+ const query = args.query?.trim();
14627
+ if (!query) {
14628
+ const recentChunks = chunkService2.getRecentChunks({
14629
+ sessionId,
14630
+ limit
14631
+ });
14632
+ if (recentChunks.length === 0) {
14633
+ return JSON.stringify({
14634
+ success: true,
14635
+ count: 0,
14636
+ scope: searchScope,
14637
+ mode: "recent",
14638
+ message: `No chunks found in ${searchScope}`,
14639
+ hint: args.all_sessions ? undefined : "Try with all_sessions: true to see past sessions"
14640
+ });
14641
+ }
14642
+ const formatted2 = recentChunks.map((c) => ({
14643
+ id: c.id,
14644
+ sessionId: c.sessionId,
14645
+ depth: c.depth,
14646
+ status: c.status,
14647
+ summary: c.summary || `${c.content.messages.length} messages`,
14648
+ created: new Date(c.createdAt * 1000).toISOString(),
14649
+ stats: {
14650
+ messages: c.content.messages.length,
14651
+ files_modified: c.content.metadata.files_modified?.length || 0
14652
+ }
14653
+ }));
14654
+ return JSON.stringify({
14655
+ success: true,
14656
+ count: formatted2.length,
14657
+ scope: searchScope,
14658
+ mode: "recent",
14659
+ chunks: formatted2,
14660
+ hint: 'Use memoir_expand({ chunk_id: "ch_xxx" }) to see full content.'
14661
+ });
14662
+ }
14663
+ const results = chunkService2.search(query, {
14664
+ sessionId,
14572
14665
  depth: args.depth,
14573
- limit: args.limit
14666
+ limit
14574
14667
  });
14575
14668
  if (results.length === 0) {
14576
14669
  return JSON.stringify({
14577
14670
  success: true,
14578
14671
  count: 0,
14579
- estimated_tokens: 50,
14580
- message: "No matching chunks found"
14672
+ scope: searchScope,
14673
+ mode: "search",
14674
+ query,
14675
+ message: `No matches for "${query}" in ${searchScope}`,
14676
+ hint: args.all_sessions ? undefined : "Try with all_sessions: true to search past sessions"
14581
14677
  });
14582
14678
  }
14583
14679
  const formatted = results.map((r) => {
@@ -14608,10 +14704,13 @@ CONTEXT BUDGET: Results are summaries (~50-200 tokens each). To view full chunk
14608
14704
  const response = {
14609
14705
  success: true,
14610
14706
  count: results.length,
14707
+ scope: searchScope,
14708
+ mode: "search",
14709
+ query,
14611
14710
  estimated_tokens: estimatedTokens,
14612
14711
  estimated_expanded_tokens: estimatedExpandedTokens,
14613
14712
  chunks: formatted,
14614
- hint: 'Use memoir_expand({ chunk_id: "ch_xxx", preview_only: true }) to check size before full expansion.'
14713
+ hint: 'Use memoir_expand({ chunk_id: "ch_xxx" }) to see full content.'
14615
14714
  };
14616
14715
  if (estimatedExpandedTokens > LARGE_RESULT_TOKEN_THRESHOLD && results.length > 3) {
14617
14716
  response.warning = `Expanding all ${results.length} results would use ~${estimatedExpandedTokens} tokens. Consider using memoir_expand with preview_only=true first, or delegate detailed analysis to a subagent.`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunkercache/opencode-memoir",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "A smart memory management plugin for OpenCode that supports nested aggregation of memory, summaries, and file changes that compact in layers with upstream references for lookups.",
5
5
  "author": {
6
6
  "name": "Chris Tunbridge",