Conversation
Greptile SummaryThis PR adds content-hash-based file change detection (
Confidence Score: 4/5Not safe to merge as-is: the cache-poisoning bug in One clear P1 defect in the primary feature path (
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[NativeModule.start] --> B[_maybe_build]
B --> C{rebuild_on_change\nset AND exe exists?}
C -- No --> D{exe exists?}
C -- Yes --> E["did_change(update=True ⚠️)\nWrites new hash to cache\nBEFORE build runs"]
E -- False\nno change --> D
E -- True\nchanged --> F[needs_rebuild = True]
F --> G[Run build_command]
D -- Yes, no rebuild --> H[return early / no build]
D -- No, or needs rebuild --> G
G -- returncode != 0 --> I["raise RuntimeError\n(cache already updated ⚠️)"]
G -- success --> J[exe verified exists]
J --> K["did_change again\n(redundant – cache already current)"]
K --> L[return]
I --> M["Next _maybe_build call:\ndid_change → False\n→ skips rebuild forever ⚠️"]
style E fill:#ffcccc,stroke:#cc0000
style I fill:#ffcccc,stroke:#cc0000
style M fill:#ffcccc,stroke:#cc0000
Reviews (1): Last reviewed commit: "native rebuild changes" | Re-trigger Greptile |
dimos/utils/change_detect.py
Outdated
| try: | ||
| # Include the path so additions/deletions/renames are detected | ||
| h.update(str(fpath).encode()) | ||
| h.update(fpath.read_bytes()) |
There was a problem hiding this comment.
this will load a full file into memory, ok for source files, but will for sure cause a weird issue for someone down the line. maybe easy hack for this is to check the file size and simply not hash if larger then 500k-1Mb or something
|
so not sure, haven't looked into details, but is there a reason we aren't relying nix build before each module start, since nix essentially does the above by itself? |
dimos/core/native_module.py
Outdated
|
|
||
| # Override in subclasses to exclude fields from CLI arg generation | ||
| cli_exclude: frozenset[str] = frozenset() | ||
| cli_exclude: frozenset[str] = frozenset({"rebuild_on_change"}) |
There was a problem hiding this comment.
this breaks subclass overriding right? since now all nativemodules need to explicitly include this value
| _tail_size = 50 | ||
|
|
||
| @property | ||
| def _mod_label(self) -> str: |
| _stopping: bool = False | ||
| _last_stderr_lines: collections.deque[str] | ||
| _stderr_tail: collections.deque[str] | ||
| _stdout_tail: collections.deque[str] |
There was a problem hiding this comment.
every line is already being passed to the logger.
So the tail buffers are keeping a duplicate copy of data that's already been logged just to re-log it again - why? I see also _last_stderr_lines was added previously.
IMO if we want more ergonomics with logging should fix the actual logger to allow you to filter, have per module log files you can tail in another term etc
| # from terminal signals (SIGINT from the tty). preexec_fn is unsafe | ||
| # in the presence of threads (subprocess docs), so we only use it on | ||
| # Linux where prctl(PR_SET_PDEATHSIG) has no alternative. | ||
| def _child_preexec_linux() -> None: |
| extra_env: dict[str, str] = Field(default_factory=dict) | ||
| shutdown_timeout: float = 10.0 | ||
| log_format: LogFormat = LogFormat.TEXT | ||
| rebuild_on_change: list[PathEntry] | None = None |
There was a problem hiding this comment.
btw this is the first actual setting that's different between prod and dev, we def don't want this on deployments, so probably if toggled True should be done not in code but the local config file level or via local env vars.
There was a problem hiding this comment.
Whats the difference between prod and dev? I don't follow
Unfortunately yeah. I don't care much about speed, but rebuild_on_change is 1980x faster than nix's check on reboot, and merely 280x faster once nix has a "warm" cache. And that's for the mid360, which is absolutely tiny. For a native module like PathFollower being checked onboard the G1, nix takes 1037.89ms just to confirm nothing changed ( I'm not thrilled about Now that I think about it though, we should probably have it always rebuild unless there is a |
Problem
Editing source code doesnt cause native modules to rebuild. Very easy to forget and not friendly for ai edits.
Solution
Some generic utils:
dimos/utils/change_detect.py: Content-hash-based file change detection usingxxhash.NativeModuleConfig.rebuild_on_change: Optionallist[str|Path|Glob]Breaking Changes
None
How to Test
Contributor License Agreement