Skip to content

fix: forward thinking param in stream mode and harden stream timeout#44

Open
veithly wants to merge 3 commits intomasterfrom
fix/streaming-thinking-timeout
Open

fix: forward thinking param in stream mode and harden stream timeout#44
veithly wants to merge 3 commits intomasterfrom
fix/streaming-thinking-timeout

Conversation

@veithly
Copy link
Contributor

@veithly veithly commented Mar 23, 2026

Summary

  • Thinking not displaying: stream()._run_and_signal() was calling agent.run() without forwarding thinking=True, so the LLM never produced thinking chunks in streaming mode. Now correctly passes the param when the agent supports it.
  • Conversations randomly interrupted: Two root causes — (1) hardcoded 120s stream deadline silently broke the loop; increased to 300s/600s with a STREAM_TIMEOUT error event emitted to the client. (2) ConnectionManager.send_message disconnected on the first failure; now retries 2x with backoff before disconnecting.

Changes

File What
spoon_bot/agent/loop.py Forward thinking to _run_and_signal(), increase stream timeout, emit error on deadline
spoon_bot/gateway/websocket/manager.py Add retry logic to send_message (2 retries + backoff)
tests/test_stream_thinking_fix.py 9 new tests covering all three fixes

Test plan

  • 9/9 new tests pass (test_stream_thinking_fix.py)
  • 78/78 existing gateway WS tests pass (test_gateway_ws_bugs.py)
  • 53/53 existing streaming model/protocol tests pass (test_streaming_thinking.py)
  • Manual verification: send a message with thinking: true, stream: true and confirm thinking chunks appear
  • Manual verification: send a long-running agent task and confirm no premature disconnection

Made with Cursor

Codex added 3 commits March 23, 2026 11:35
When yolo_mode is enabled (via config.yaml `agent.yolo_mode: true` or
env var `SPOON_BOT_YOLO_MODE=true`), the agent works directly in the
configured workspace path instead of a sandboxed directory.  All shell
commands, file reads/writes, and workspace FS operations target the
user's real filesystem.

Changes:
- config.py: add yolo_mode field to AgentLoopConfig & SpoonBotSettings;
  skip mkdir + write-test in YOLO mode (require existing directory)
- loop.py: pass yolo_mode through AgentLoop and create_agent; extend
  filesystem read paths in YOLO mode
- context.py: add YOLO mode banner to system prompt
- workspace_fs.py: add yolo-aware path resolution to WorkspaceFSService
- handler.py: propagate yolo_mode from agent to WorkspaceFSService
- server.py: read SPOON_BOT_YOLO_MODE from env/config and pass to agent
- channels/config.py: support yolo_mode in load_agent_config env map
- Dockerfile: add SPOON_BOT_YOLO_MODE env var with usage docs
- config.example.yaml, .env.example: document yolo_mode option

Made-with: Cursor
13 test cases covering:
- AgentLoopConfig yolo_mode defaults and validation
- validate_agent_loop_params with yolo_mode (CWD default, explicit workspace)
- WorkspaceFSService YOLO path resolution (relative, absolute, boundary)
- WorkspaceFSService YOLO read/write operations
- ContextBuilder YOLO mode banner presence/absence

Made-with: Cursor
- stream()._run_and_signal() now passes thinking=True to agent.run()
  so the LLM actually produces thinking chunks (was silently dropped)
- Increase stream deadline from hardcoded 120s to 300s/600s (thinking)
  and emit a STREAM_TIMEOUT error event instead of silently breaking
- ConnectionManager.send_message retries 2x with backoff before
  disconnecting, preventing transient failures from killing sessions

Made-with: Cursor
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa0c9127a6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 694 to +698
if not resolved.get(field):
for var in env_vars:
val = os.environ.get(var)
if val:
if field in {"max_iterations", "shell_timeout", "max_output", "context_window"}:
if field in _int_fields:

Choose a reason for hiding this comment

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

P1 Badge Honor explicit false yolo_mode settings

load_agent_config() documents YAML > env, but if not resolved.get(field) treats a configured boolean false as if the field were unset. If an operator puts agent.yolo_mode: false in YAML on a host that still has SPOON_BOT_YOLO_MODE=true, this block flips it back to true (and _lifespan() re-applies the same or at spoon_bot/gateway/server.py:95-98), so the agent can come up unsandboxed even though the config explicitly disabled YOLO mode.

Useful? React with 👍 / 👎.

"workspace": ["SPOON_BOT_WORKSPACE_PATH"],
"max_iterations": ["SPOON_BOT_MAX_ITERATIONS", "SPOON_MAX_STEPS"],
"enable_skills": ["SPOON_BOT_ENABLE_SKILLS"],
"yolo_mode": ["SPOON_BOT_YOLO_MODE"],

Choose a reason for hiding this comment

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

P2 Badge Thread yolo_mode into the CLI launch paths

This makes SPOON_BOT_YOLO_MODE look like a supported top-level agent setting, but both CLI entrypoints still drop it: _run_agent() builds create_kwargs without yolo_mode at spoon_bot/cli.py:534-558, and _run_gateway() does the same at spoon_bot/cli.py:998-1030. Anyone enabling YOLO via .env or config.yaml in the normal spoon-bot commands will silently stay in sandbox mode.

Useful? React with 👍 / 👎.

Comment on lines +726 to 728
if self.yolo_mode:
_extra_read.extend(p for p in self.workspace.parents if p != Path.home())
self.tools.register(ReadFileTool(workspace=self.workspace, additional_read_paths=_extra_read, max_output=15000))

Choose a reason for hiding this comment

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

P2 Badge Don't rely on additional_read_paths for YOLO reads yet

In YOLO mode this tries to grant read access to the workspace parents, but ReadFileTool.execute() still calls validate_read_path(path, workspace=self._workspace) in spoon_bot/agent/tools/filesystem.py:99, which creates a fresh PathValidator without additional_read_paths. The result is that reads outside the workspace root still fail with "outside workspace boundary", so the new parent-directory navigation path is unreachable.

Useful? React with 👍 / 👎.

Comment on lines +486 to +490
if self.yolo_mode:
if not self.workspace.is_dir():
raise ValueError(
f"YOLO mode workspace path does not exist: {self.workspace}"
)

Choose a reason for hiding this comment

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

P2 Badge Keep the writability check for YOLO workspaces

Returning early here lets a read-only YOLO workspace pass validation, but agent startup still writes under that directory unconditionally: MemoryStore creates memory/ and MEMORY.md (spoon_bot/memory/store.py:28-37) and file-session fallback creates sessions/ (spoon_bot/session/manager.py:143-145). On a read-only bind mount the failure moves from a clear config error to a later initialization crash.

Useful? React with 👍 / 👎.

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