Skip to content

feat(api): peek_stream#1909

Draft
paul-nechifor wants to merge 1 commit intodevfrom
paul/feat/topic-echo
Draft

feat(api): peek_stream#1909
paul-nechifor wants to merge 1 commit intodevfrom
paul/feat/topic-echo

Conversation

@paul-nechifor
Copy link
Copy Markdown
Contributor

Problem

Closes DIM-XXX

Solution

Breaking Changes

How to Test

Contributor License Agreement

  • I have read and approved the CLA.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 24, 2026

Greptile Summary

This PR adds a peek_stream(name, timeout) method to the Dimos class that fetches the next emission from a named stream across any running module, with a 25-second cap on the timeout to stay within RPyC limits.

  • P1 — silent error swallowing: except Exception: return None around stream.get_next() catches all exceptions (dropped connections, EOFError, AttributeError, etc.), not just timeouts. Callers cannot distinguish a genuine timeout from a connection fault.

Confidence Score: 4/5

Safe to merge after narrowing the exception catch around stream.get_next() to avoid silently swallowing non-timeout errors.

One P1 finding remains: the bare except Exception around stream.get_next() hides all runtime faults (connection drops, EOFError, etc.) behind a None return, making failures invisible to callers. Everything else — the lock pattern, the 25s timeout cap, docs, and error-path tests — looks correct.

dimos/porcelain/dimos.py — the exception handling block around stream.get_next() (lines 192-195)

Important Files Changed

Filename Overview
dimos/porcelain/dimos.py Adds peek_stream() to fetch the next message from a named stream; the bare except Exception: return None on stream.get_next() is too broad and silently hides non-timeout errors.
dimos/porcelain/test_dimos.py Adds two error-path tests for peek_stream (before run, unknown stream); no happy-path test verifying a value is actually returned.
docs/usage/python-api.md Documents the new peek_stream() API with a usage example; clear and accurate.

Sequence Diagram

sequenceDiagram
    participant Caller
    participant Dimos
    participant ModuleSource
    participant RpycModule
    participant Stream

    Caller->>Dimos: peek_stream(name, timeout)
    Dimos->>Dimos: acquire lock, grab source ref, release lock
    loop for each module_name
        Dimos->>ModuleSource: list_module_names()
        Dimos->>ModuleSource: get_rpyc_module(module_name)
        ModuleSource-->>Dimos: RpycModule
        Dimos->>RpycModule: check outputs[name] / inputs[name]
        RpycModule-->>Dimos: stream (or not found)
    end
    alt stream found
        Dimos->>Stream: get_next(effective_timeout)
        Stream-->>Dimos: value (or raises)
        Dimos-->>Caller: value (or None on any exception)
    else stream not found
        Dimos-->>Caller: raises LookupError
    end
Loading

Reviews (1): Last reviewed commit: "feat(api): peek_image" | Re-trigger Greptile

Comment thread dimos/porcelain/dimos.py
Comment on lines +192 to +195
try:
return stream.get_next(effective_timeout)
except Exception:
return None
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Overly broad exception swallowing

except Exception: return None catches every exception from stream.get_next(), not just timeouts. This means a dropped RPyC connection, AttributeError, EOFError, or any other runtime fault silently returns None, making it indistinguishable from a legitimate timeout. Callers have no way to tell the difference, which can hide real failures.

Consider only catching exceptions that signal a timeout (e.g. queue.Empty, or whatever get_next raises on expiry), and re-raising anything else:

try:
    return stream.get_next(effective_timeout)
except TimeoutError:
    return None

If get_next doesn't raise a specific timeout type, at minimum document what exception it raises on timeout so the catch can be made precise.

@paul-nechifor paul-nechifor changed the title feat(api): peek_image feat(api): peek_stream Apr 24, 2026
@paul-nechifor paul-nechifor marked this pull request as draft April 24, 2026 04:52
@leshy
Copy link
Copy Markdown
Contributor

leshy commented Apr 24, 2026

I think this is attractive but directionally problematic and should be careful with peek_stream type functionality.

(extension of my "I think we should be careful about py repl") - agents don't know about modules, process boundaries etc, having peek_stream makes it very attractive for agents to then write a while loop, do live data processing via this function, suddenly they'll write a module that's not a module at all.

A need for peek_stream shows me our module API should be better since we want to cheat.

We can make writing a temporary test module simpler, for example agent should be able to write a script that's a module that interacts with a blueprint, once script is killed, module is dead also. This already works (or worked) nothing used to stop you from running your module from a separate script

Not blocking this, just some thoughts, we will see experimentally, maybe it's ok

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.

2 participants