Skip to content

feat: add Bub plugin — cross-tool knowledge for Bub agents#114

Merged
wey-gu merged 2 commits intomainfrom
dev_0610
Mar 12, 2026
Merged

feat: add Bub plugin — cross-tool knowledge for Bub agents#114
wey-gu merged 2 commits intomainfrom
dev_0610

Conversation

@wey-gu
Copy link
Copy Markdown
Member

@wey-gu wey-gu commented Mar 12, 2026

Native Bub integration via nowledge-mem-bub package:

  • 9 tools (mem.search, mem.save, mem.context, mem.connections, etc.)
  • 3 hooks (system_prompt, load_state, save_state)
  • Bundled nowledge-mem skill for agent self-guidance
  • Two modes: default (agent-driven) + session context (auto-inject)
  • Conversations captured to Nowledge Mem threads for cross-tool discovery
  • Access Anywhere support via config file or env vars

chore: remove .pyc files and add .gitignore for Bub plugin


Note

Medium Risk
Introduces a new Bub plugin that shells out to the nmem CLI and can automatically ingest session turns into external storage, so failures or misconfiguration could affect runtime behavior and data capture/privacy expectations.

Overview
Adds an initial nowledge-mem-bub Bub plugin package that connects Bub sessions to Nowledge Mem via the nmem CLI, including packaging (pyproject.toml), docs (README.md, CHANGELOG.md), and a bundled nowledge-mem skill.

Implements Bub hooks (system_prompt, load_state, save_state) to provide agent guidance, optionally auto-inject Working Memory + recalled memories per turn (NMEM_SESSION_CONTEXT), and incrementally capture each user/assistant turn into a Nowledge Mem thread (NMEM_SESSION_DIGEST).

Registers 9 new mem.* tools (mem.search, mem.save with best-effort dedupe, mem.context, mem.connections, mem.timeline, mem.forget, mem.threads, mem.thread, mem.status) backed by an async NmemClient wrapper supporting config/env-based remote access.

Written by Cursor Bugbot for commit 23a371e. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • Comprehensive memory tools: search, save, context, connections, timeline, forget, and thread management
    • Session context mode for automatic working-memory injection, recall, and per-session conversation capture
    • Asynchronous CLI-backed memory integration and status checking
  • Documentation

    • Full README, skill usage guide, and SKILL reference added
    • CHANGELOG documenting releases and fixes
  • Chores

    • Project packaging/configuration and .gitignore added for Python packaging and build setup

Native Bub integration via nowledge-mem-bub package:
- 9 tools (mem.search, mem.save, mem.context, mem.connections, etc.)
- 3 hooks (system_prompt, load_state, save_state)
- Bundled nowledge-mem skill for agent self-guidance
- Two modes: default (agent-driven) + session context (auto-inject)
- Conversations captured to Nowledge Mem threads for cross-tool discovery
- Access Anywhere support via config file or env vars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

chore: remove .pyc files and add .gitignore for Bub plugin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Adds a new nowledge-mem-bub-plugin: packaging and docs, an async nmem CLI client (NmemClient/NmemError), a Bub plugin (NowledgeMemPlugin) with session state hooks, and registered Bub tools for memory operations (mem.search, mem.save, mem.context, mem.connections, mem.timeline, mem.forget, mem.threads, mem.thread, mem.status).

Changes

Cohort / File(s) Summary
Project config & docs
nowledge-mem-bub-plugin/.gitignore, nowledge-mem-bub-plugin/pyproject.toml, nowledge-mem-bub-plugin/CHANGELOG.md, nowledge-mem-bub-plugin/README.md
Added packaging metadata, Bub entry-point, .gitignore, changelog and a comprehensive README with installation, usage, config, and tool listings.
Skill documentation
nowledge-mem-bub-plugin/src/bub_skills/nowledge-mem/SKILL.md
New SKILL.md describing memory policy, when to search/save/context, thread usage, and guidance for creating actionable memories.
Package markers
nowledge-mem-bub-plugin/src/bub_skills/__init__.py, nowledge-mem-bub-plugin/src/nowledge_mem_bub/__init__.py
Added package marker and package initializer exposing plugin.
Nmem CLI client
nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py
New async subprocess-based wrapper NmemClient and NmemError: config/env handling, command resolution, JSON exec helpers, and methods for search, add/get/delete memory, threads, graph, timeline, feed_events, status, and working-memory fallback.
Plugin core
nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py
New NowledgeMemPlugin implementing system_prompt, async load_state, async save_state, session-context handling, deterministic thread append/create flow, and a module-level plugin instance.
Bub tools
nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py
Register mem.* tools with input models and implementations: mem.search, mem.save (with pre-save dedup), mem.context, mem.connections, mem.timeline, mem.forget, mem.threads, mem.thread, mem.status; includes formatting, error handling, and context caching.

Sequence Diagram(s)

sequenceDiagram
    participant Agent as Bub Agent
    participant Plugin as NowledgeMemPlugin
    participant Client as NmemClient
    participant CLI as nmem CLI
    participant Mem as Memory System

    rect rgba(100, 150, 255, 0.5)
    Note over Agent,Mem: Session Load & Recall
    Agent->>Plugin: load_state(session_id)
    Plugin->>Client: read_working_memory()
    Client->>CLI: nmem get-working-memory --json
    CLI->>Mem: request working memory
    Mem-->>CLI: working memory JSON
    CLI-->>Client: JSON payload
    Client-->>Plugin: working memory dict
    Plugin->>Client: search(recall_query)
    Client->>CLI: nmem search --json ...
    CLI->>Mem: perform search
    Mem-->>CLI: search results
    CLI-->>Client: results JSON
    Client-->>Plugin: recalled list
    Plugin-->>Agent: state with _nmem_working_memory/_nmem_recalled
    end
Loading
sequenceDiagram
    participant Agent as Bub Agent
    participant Tool as mem.save Tool
    participant Client as NmemClient
    participant CLI as nmem CLI
    participant Mem as Memory System

    rect rgba(100, 200, 100, 0.5)
    Note over Agent,Mem: mem.save with pre-dedup
    Agent->>Tool: mem.save(content, title, labels...)
    Tool->>Client: search(content, labels=..., limit=1)
    Client->>CLI: nmem search --json ...
    CLI->>Mem: search request
    Mem-->>CLI: existing memory or empty
    CLI-->>Client: response
    alt duplicate found
        Client-->>Tool: existing memory info
        Tool-->>Agent: Skipped — duplicate detected
    else no duplicate
        Tool->>Client: add_memory(...)
        Client->>CLI: nmem add-memory --json ...
        CLI->>Mem: store memory
        Mem-->>CLI: new memory JSON
        CLI-->>Client: response
        Client-->>Tool: new memory dict
        Tool-->>Agent: Saved — memory id & summary
    end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • batch v0.6.3 changes #79: Implements overlapping Nowledge Mem features (thread provenance, pre-save deduplication, session-context hooks, thread search/fetch) with strong code-level similarity.

Poem

🐰 I hopped in with a tiny plugin cheer,
Tying Bub to mems both far and near,
Search and save, threads stitched tight,
Session whispers kept in sight,
Hooray — memories now hop into gear! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a Bub plugin that enables cross-tool knowledge integration for Bub agents. It is concise, clear, and directly reflects the primary objectives of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev_0610

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Free Tier Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py Outdated
Comment thread nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py (3)

125-128: Use exception chaining for JSON decode errors.

♻️ Proposed fix
         except json.JSONDecodeError as e:
-            raise NmemError(f"invalid JSON from nmem: {e}")
+            raise NmemError(f"invalid JSON from nmem: {e}") from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py` around lines 125 -
128, The JSON decode exception handler in the block that parses `raw` currently
raises NmemError without chaining the original exception; update the except in
that parsing code to re-raise NmemError using exception chaining (e.g., "raise
NmemError(f\"invalid JSON from nmem: {e}\") from e") so the original
json.JSONDecodeError is preserved for traceback and debugging while keeping the
existing message.

109-113: Use exception chaining for better tracebacks.

When re-raising exceptions, use raise ... from err (or from None to suppress chaining) to preserve the exception context for debugging.

♻️ Proposed fix
-        except asyncio.TimeoutError:
+        except asyncio.TimeoutError as err:
             proc.kill()  # type: ignore[union-attr]
-            raise NmemError(f"nmem timed out after {timeout}s")
+            raise NmemError(f"nmem timed out after {timeout}s") from err
-        except FileNotFoundError:
-            raise NmemError("nmem not found in PATH")
+        except FileNotFoundError as err:
+            raise NmemError("nmem not found in PATH") from err
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py` around lines 109 -
113, The except blocks in client.py are re-raising NmemError without exception
chaining; change them to capture the original exceptions (e.g., except
asyncio.TimeoutError as err and except FileNotFoundError as err), keep the
proc.kill() in the timeout branch, and re-raise using "raise NmemError(f'nmem
timed out after {timeout}s') from err" and "raise NmemError('nmem not found in
PATH') from err" so the original traceback is preserved for debugging (refer to
the exception handling in the function where proc.kill() is called and the two
except blocks).

64-73: Consider adding uvx fallback for nmem command resolution.

The current implementation only checks for nmem in PATH. Based on learnings from other Nowledge Mem plugins, the recommended pattern includes a fallback to uvx --from nmem-cli nmem when nmem is not directly available.

♻️ Proposed fix to add uvx fallback
     def _resolve_cmd(self) -> str:
         if self._cmd is not None:
             return self._cmd
         cmd = shutil.which("nmem")
         if cmd:
             self._cmd = cmd
             return cmd
+        # Fallback: try uvx
+        uvx = shutil.which("uvx")
+        if uvx:
+            self._cmd = uvx
+            return uvx
         raise NmemError(
-            "nmem not found in PATH. Install with: pip install nmem-cli"
+            "nmem not found in PATH. Install with: pip install nmem-cli or uvx --from nmem-cli nmem"
         )
+
+    def _base_args(self, *, json_output: bool = True) -> list[str]:
+        cmd = self._resolve_cmd()
+        # If using uvx, prepend the package specifier
+        if cmd.endswith("uvx"):
+            args = [cmd, "--from", "nmem-cli", "nmem"]
+        else:
+            args = [cmd]
+        if json_output:
+            args.append("--json")
+        if self._api_url:
+            args.extend(["--api-url", self._api_url])
+        return args

Based on learnings: "Memory backend uses nmem CLI, with fallback to uvx --from nmem-cli nmem"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py` around lines 64 - 73,
The _resolve_cmd method currently only looks for "nmem" in PATH and raises
NmemError if missing; update it to add a fallback that checks for "uvx" (using
shutil.which) and, if found, sets self._cmd to the composed command "uvx --from
nmem-cli nmem" and returns that string; otherwise keep raising NmemError.
Reference _resolve_cmd, self._cmd, NmemError and shutil.which when making the
change.
nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py (3)

294-299: Consider confirming deletion with the user.

The mem.forget tool deletes a memory without confirmation. Consider adding a confirmation step or returning more context about what was deleted to prevent accidental data loss.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py` around lines 294 -
299, The mem_forget tool (function mem_forget) currently calls
_get_client(context) and immediately awaits client.delete_memory(memory_id),
which can cause accidental deletions; modify mem_forget to either require an
explicit confirmation flag or return a structured prompt/result before deleting,
e.g., accept a confirm boolean or first fetch the memory via
client.get_memory(memory_id) and return its summary for user confirmation, then
only call client.delete_memory(memory_id) when confirmation is present; ensure
returned responses include what was deleted (memory_id and a brief summary) and
keep the same tool signature/context handling with _get_client and
client.delete_memory.

140-141: Consider logging dedup check failures.

The silent pass in the exception handler hides potential issues. While dedup is best-effort, a debug log would help with troubleshooting.

♻️ Proposed fix
     except Exception:
-        pass  # dedup is best-effort
+        logger.debug("dedup check failed (best-effort, continuing)")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py` around lines 140 -
141, Replace the silent except in the dedup check in tools.py (the "except
Exception: pass" block) with a debug-level log that records the exception and a
short contextual message; use the module's logger (e.g., logger or
logging.getLogger(__name__)) and include exc_info=True (or logger.exception at
debug level) so failures during the best-effort deduplication are captured
without changing behavior.

63-74: Replace EN DASH with HYPHEN-MINUS in Field descriptions.

The Field descriptions contain EN DASH characters () instead of standard HYPHEN-MINUS (-). While they render similarly, using ASCII hyphens is more consistent and avoids potential encoding issues.

♻️ Proposed fix
-    limit: int = Field(5, description="Max results (1–20).")
+    limit: int = Field(5, description="Max results (1-20).")

Apply similar changes to lines 103, 106, and 255.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py` around lines 63 - 74,
The Field descriptions in MemSearchInput (and other Field usages) use an EN DASH
(–) instead of an ASCII hyphen-minus (-); update the descriptions to replace EN
DASH with hyphen-minus (e.g., change "Max results (1–20)" to "Max results
(1-20)") and apply the same replacement to the other Field descriptions
mentioned in this file (the other occurrences noted in the review). Locate
usages by the class/name identifiers like MemSearchInput and the Field(...)
calls and update their description strings to use "-" everywhere.
nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py (1)

136-144: Improve recall search trigger condition.

The current condition len(query.strip()) > 3 is a minimal safeguard. Consider also checking that the query contains meaningful content (not just whitespace or punctuation) to avoid unnecessary API calls.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py` around lines 136 -
144, The recall trigger uses only len(query.strip()) > 3 which still fires for
punctuation-only inputs; before calling self.client.search in the block around
content_of(message) update the guard to ensure the query contains meaningful
text (e.g., strip whitespace and punctuation and check remaining length or
require at least one alphanumeric/word character) so you only call
self.client.search(query[:500], limit=5) for queries with substantive content;
keep the same error handling and assignment to state["_nmem_recalled"] and
retain logger.debug on exception.
nowledge-mem-bub-plugin/README.md (1)

29-42: Enhance tool documentation with detailed examples and response contracts.

The tool table provides helpful one-line descriptions, but lacks the detailed user-facing behavior and response contract examples that would help users understand how to call each tool and what to expect in return. Consider adding a dedicated section with:

  • Parameter schemas for each tool
  • Example requests and responses
  • Common use cases
  • Error conditions and handling

For example:

### mem.search

**Parameters:**
- `query` (string, required): Search terms
- `labels` (array, optional): Filter by labels
- `since` (string, optional): Date filter (ISO 8601)

**Example:**

,mem.search query="API design decisions" labels=["backend"]


**Response:**
Returns a list of matching memories with id, content, labels, and relevance score.

Based on learnings, README.md must document user-facing behavior and response contract examples for all tools.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/README.md` around lines 29 - 42, Update the Tools
section to include a dedicated detailed documentation subsection for each tool
(mem.search, mem.save, mem.context, mem.connections, mem.timeline, mem.forget,
mem.threads, mem.thread, mem.status) that specifies parameter schemas (types and
required/optional), example requests (call syntax) and example responses
(response contract with field names and types), common use cases, and documented
error conditions and handling guidance; ensure each tool entry contains at
least: a Parameters list, a short Example request, an Example response showing
returned fields (id, content, labels, relevance, pagination tokens, etc. where
applicable), and common errors (validation, auth, not-found) so users can
reliably call and parse each tool’s output.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nowledge-mem-bub-plugin/pyproject.toml`:
- Around line 29-30: The pyproject.toml packages list currently includes
"src/bub_skills" which is not a Python package (contains only SKILL.md and no
__init__.py) and will break the wheel build; either remove "src/bub_skills" from
the packages entry in pyproject.toml, or make bub_skills a real package by
adding an __init__.py and any needed modules so it can be imported;
alternatively, keep the directory out of packages and include SKILL.md via
package-data/include-package-data configuration so the file is bundled without
declaring bub_skills as a package.
- Line 15: The dependency line currently pins a pre-release ("bub>=0.3.0a1");
change this to use the stable release (e.g., "bub>=0.2.3") unless you
specifically need the alpha features from 0.3.0a1—if the alpha is intentional,
add a short note in the project metadata or repo docs explaining why the stable
"0.2.3" cannot be used and which 0.3.0a1 features are required; look for the
dependency string "bub>=0.3.0a1" in pyproject.toml and update or document
accordingly.

---

Nitpick comments:
In `@nowledge-mem-bub-plugin/README.md`:
- Around line 29-42: Update the Tools section to include a dedicated detailed
documentation subsection for each tool (mem.search, mem.save, mem.context,
mem.connections, mem.timeline, mem.forget, mem.threads, mem.thread, mem.status)
that specifies parameter schemas (types and required/optional), example requests
(call syntax) and example responses (response contract with field names and
types), common use cases, and documented error conditions and handling guidance;
ensure each tool entry contains at least: a Parameters list, a short Example
request, an Example response showing returned fields (id, content, labels,
relevance, pagination tokens, etc. where applicable), and common errors
(validation, auth, not-found) so users can reliably call and parse each tool’s
output.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py`:
- Around line 125-128: The JSON decode exception handler in the block that
parses `raw` currently raises NmemError without chaining the original exception;
update the except in that parsing code to re-raise NmemError using exception
chaining (e.g., "raise NmemError(f\"invalid JSON from nmem: {e}\") from e") so
the original json.JSONDecodeError is preserved for traceback and debugging while
keeping the existing message.
- Around line 109-113: The except blocks in client.py are re-raising NmemError
without exception chaining; change them to capture the original exceptions
(e.g., except asyncio.TimeoutError as err and except FileNotFoundError as err),
keep the proc.kill() in the timeout branch, and re-raise using "raise
NmemError(f'nmem timed out after {timeout}s') from err" and "raise
NmemError('nmem not found in PATH') from err" so the original traceback is
preserved for debugging (refer to the exception handling in the function where
proc.kill() is called and the two except blocks).
- Around line 64-73: The _resolve_cmd method currently only looks for "nmem" in
PATH and raises NmemError if missing; update it to add a fallback that checks
for "uvx" (using shutil.which) and, if found, sets self._cmd to the composed
command "uvx --from nmem-cli nmem" and returns that string; otherwise keep
raising NmemError. Reference _resolve_cmd, self._cmd, NmemError and shutil.which
when making the change.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py`:
- Around line 136-144: The recall trigger uses only len(query.strip()) > 3 which
still fires for punctuation-only inputs; before calling self.client.search in
the block around content_of(message) update the guard to ensure the query
contains meaningful text (e.g., strip whitespace and punctuation and check
remaining length or require at least one alphanumeric/word character) so you
only call self.client.search(query[:500], limit=5) for queries with substantive
content; keep the same error handling and assignment to state["_nmem_recalled"]
and retain logger.debug on exception.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py`:
- Around line 294-299: The mem_forget tool (function mem_forget) currently calls
_get_client(context) and immediately awaits client.delete_memory(memory_id),
which can cause accidental deletions; modify mem_forget to either require an
explicit confirmation flag or return a structured prompt/result before deleting,
e.g., accept a confirm boolean or first fetch the memory via
client.get_memory(memory_id) and return its summary for user confirmation, then
only call client.delete_memory(memory_id) when confirmation is present; ensure
returned responses include what was deleted (memory_id and a brief summary) and
keep the same tool signature/context handling with _get_client and
client.delete_memory.
- Around line 140-141: Replace the silent except in the dedup check in tools.py
(the "except Exception: pass" block) with a debug-level log that records the
exception and a short contextual message; use the module's logger (e.g., logger
or logging.getLogger(__name__)) and include exc_info=True (or logger.exception
at debug level) so failures during the best-effort deduplication are captured
without changing behavior.
- Around line 63-74: The Field descriptions in MemSearchInput (and other Field
usages) use an EN DASH (–) instead of an ASCII hyphen-minus (-); update the
descriptions to replace EN DASH with hyphen-minus (e.g., change "Max results
(1–20)" to "Max results (1-20)") and apply the same replacement to the other
Field descriptions mentioned in this file (the other occurrences noted in the
review). Locate usages by the class/name identifiers like MemSearchInput and the
Field(...) calls and update their description strings to use "-" everywhere.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 48f593ae-6a80-4033-9c66-b5bc4550c0e2

📥 Commits

Reviewing files that changed from the base of the PR and between 41e1168 and 23a371e.

📒 Files selected for processing (9)
  • nowledge-mem-bub-plugin/.gitignore
  • nowledge-mem-bub-plugin/CHANGELOG.md
  • nowledge-mem-bub-plugin/README.md
  • nowledge-mem-bub-plugin/pyproject.toml
  • nowledge-mem-bub-plugin/src/bub_skills/nowledge-mem/SKILL.md
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/__init__.py
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/tools.py

Comment thread nowledge-mem-bub-plugin/pyproject.toml
Comment thread nowledge-mem-bub-plugin/pyproject.toml
…ckaging, dead code

- save_state: only retry create_thread on "not found" errors, not timeouts/auth;
  cache thread existence to skip retry on subsequent turns
- bub_skills: add __init__.py so importlib can discover the skill directory
- client: remove unused get_memory method
- bump to v0.1.1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nowledge-co nowledge-co deleted a comment from cursor Bot Mar 12, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py (1)

166-167: SHA1 for ID generation is acceptable, but consider SHA256.

Static analysis flags sha1 as insecure (S324), but this is a false positive here—SHA1 is used for deterministic ID generation from session_id, not for cryptographic security. The 10-char hex substring provides sufficient uniqueness for thread IDs.

That said, switching to sha256 silences the linter at no performance cost and is considered modern best practice.

🔇 Optional: use SHA256 to silence linter
-            digest = hashlib.sha1(session_id.encode()).hexdigest()[:10]
+            digest = hashlib.sha256(session_id.encode()).hexdigest()[:10]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py` around lines 166 -
167, Replace the use of hashlib.sha1 with hashlib.sha256 when deriving digest
from session_id: update the digest calculation (the variable digest that
currently does hashlib.sha1(session_id.encode()).hexdigest()[:10]) to use
hashlib.sha256(session_id.encode()).hexdigest()[:10], leaving the thread_id
construction (thread_id = f"bub-{digest}") and session_id handling unchanged so
the deterministic ID behavior remains the same and the linter warning is
silenced.
nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py (1)

109-128: Add exception chaining for better debugging.

Re-raised exceptions should chain the original cause using raise ... from err (to preserve the traceback) or raise ... from None (to explicitly suppress it). This aids debugging when nmem failures occur.

♻️ Proposed fix for exception chaining
         except asyncio.TimeoutError:
             proc.kill()  # type: ignore[union-attr]
-            raise NmemError(f"nmem timed out after {timeout}s")
+            raise NmemError(f"nmem timed out after {timeout}s") from None
         except FileNotFoundError:
-            raise NmemError("nmem not found in PATH")
+            raise NmemError("nmem not found in PATH") from None
         except json.JSONDecodeError as e:
-            raise NmemError(f"invalid JSON from nmem: {e}")
+            raise NmemError(f"invalid JSON from nmem: {e}") from e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py` around lines 109 -
128, The NmemError raises lose the original exception context; update the
exception handling in _exec and _exec_json to chain causes: in the
asyncio.TimeoutError except block re-raise NmemError using "raise
NmemError(f'nmem timed out after {timeout}s') from err" (or similar naming) so
the timeout traceback is preserved; in the FileNotFoundError except block
re-raise NmemError using "raise NmemError('nmem not found in PATH') from err";
and in _exec_json catch of json.JSONDecodeError change "raise
NmemError(f'invalid JSON from nmem: {e}')" to "raise NmemError(f'invalid JSON
from nmem: {e}') from e" so the original JSONDecodeError is chained. Ensure you
reference the _exec and _exec_json functions and the NmemError type when making
these changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py`:
- Around line 109-128: The NmemError raises lose the original exception context;
update the exception handling in _exec and _exec_json to chain causes: in the
asyncio.TimeoutError except block re-raise NmemError using "raise
NmemError(f'nmem timed out after {timeout}s') from err" (or similar naming) so
the timeout traceback is preserved; in the FileNotFoundError except block
re-raise NmemError using "raise NmemError('nmem not found in PATH') from err";
and in _exec_json catch of json.JSONDecodeError change "raise
NmemError(f'invalid JSON from nmem: {e}')" to "raise NmemError(f'invalid JSON
from nmem: {e}') from e" so the original JSONDecodeError is chained. Ensure you
reference the _exec and _exec_json functions and the NmemError type when making
these changes.

In `@nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py`:
- Around line 166-167: Replace the use of hashlib.sha1 with hashlib.sha256 when
deriving digest from session_id: update the digest calculation (the variable
digest that currently does hashlib.sha1(session_id.encode()).hexdigest()[:10])
to use hashlib.sha256(session_id.encode()).hexdigest()[:10], leaving the
thread_id construction (thread_id = f"bub-{digest}") and session_id handling
unchanged so the deterministic ID behavior remains the same and the linter
warning is silenced.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 588ffa05-34ba-42ca-a2ad-45df5369f8be

📥 Commits

Reviewing files that changed from the base of the PR and between 23a371e and e06f989.

📒 Files selected for processing (5)
  • nowledge-mem-bub-plugin/CHANGELOG.md
  • nowledge-mem-bub-plugin/pyproject.toml
  • nowledge-mem-bub-plugin/src/bub_skills/__init__.py
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/client.py
  • nowledge-mem-bub-plugin/src/nowledge_mem_bub/plugin.py
✅ Files skipped from review due to trivial changes (1)
  • nowledge-mem-bub-plugin/src/bub_skills/init.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • nowledge-mem-bub-plugin/pyproject.toml
  • nowledge-mem-bub-plugin/CHANGELOG.md

@wey-gu
Copy link
Copy Markdown
Member Author

wey-gu commented Mar 12, 2026

Let's merge it and working on new PR for iterations!

@wey-gu wey-gu merged commit d486fc4 into main Mar 12, 2026
1 check passed
@wey-gu wey-gu deleted the dev_0610 branch March 12, 2026 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant