Skip to content

feat: add session.stopping hook for plugins#16598

Open
yehudacohen wants to merge 9 commits intoanomalyco:devfrom
yehudacohen:feat/session-stopping-hook
Open

feat: add session.stopping hook for plugins#16598
yehudacohen wants to merge 9 commits intoanomalyco:devfrom
yehudacohen:feat/session-stopping-hook

Conversation

@yehudacohen
Copy link
Copy Markdown

@yehudacohen yehudacohen commented Mar 8, 2026

Issue for this PR

Closes #16626

Related to #12472 (the Stop hook re-activation use case is a subset of what that issue describes).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds a session.stopping hook to the plugin API. It fires before the agent loop breaks, giving plugins a chance to inject a follow-up user message and continue the loop instead of stopping. If no plugin is installed, behaviour is unchanged.

Known limitation: if a plugin unconditionally sets stop=false on every call, the loop will run indefinitely. There is no built-in re-entry cap. Plugins are responsible for their own termination condition. This is intentional: the correct guard depends entirely on the plugin's use case (a counter, a state flag, a file on disk) and cannot be generalised in core without constraining valid use cases. The same responsibility applies to any plugin that calls client.session.chat from session.idle.

How did you verify your code works?

Four tests in test/plugin/session-stopping.test.ts — no mocks, real plugin files written to a temp dir and loaded via Plugin.init(): plugin mutation propagates through Plugin.trigger; no plugin leaves stop as true; stop=false with no message does not satisfy the re-entry condition; hook message is persisted as a real user message via SessionPrompt.prompt.

End-to-end against the dev build: created a one-shot plugin that sets stop=false on first fire. Ran opencode run "say exactly the word HELLO and nothing else". Session export confirmed 4 messages in order: original user prompt, HELLO, hook-injected user message, second assistant reply. The loop stopped cleanly on the second hook fire because the plugin saw its own marker file and returned without modifying output.

bun typecheck clean.

Screenshots / recordings

N/A — no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions bot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 8, 2026
@yehudacohen yehudacohen marked this pull request as draft March 8, 2026 13:23
Fires before the agent loop exits, allowing plugins to inject a follow-up
message and re-enter the loop instead of going idle.

Changes:
- packages/plugin/src/index.ts: add session.stopping to Hooks interface
- packages/opencode/src/session/prompt.ts: fire hook before loop break,
  inject message and continue if plugin returns stop=false
- test/plugin/session-stopping.test.ts: tests for hook loading and trigger
@github-actions github-actions bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 8, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@yehudacohen yehudacohen force-pushed the feat/session-stopping-hook branch from 425a791 to daf9c96 Compare March 8, 2026 14:11
@github-actions github-actions bot added needs:compliance This means the issue will auto-close after 2 hours. and removed needs:compliance This means the issue will auto-close after 2 hours. labels Mar 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 8, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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.

[FEATURE]: add session.stopping plugin hook to allow re-entering the agent loop

1 participant