-
Notifications
You must be signed in to change notification settings - Fork 11
feat: document and mitigate debug-agent async message visibility #197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # Future: Async Message Visibility in Debug-Agent | ||
|
|
||
| ## Current Limitation | ||
|
|
||
| The debug-agent (and any pi session) operates in a **synchronous turn-based model**: | ||
| - When processing a user prompt, the LLM generates a response | ||
| - During this generation, incoming `send_to_session` messages are queued | ||
| - These queued messages are **invisible** until the current turn completes | ||
| - Only then does pi process the queue and present them as new user prompts | ||
|
|
||
| This creates confusion in debug/observability scenarios where admins expect real-time interaction. | ||
|
|
||
| ## Short-term Mitigation (this PR) | ||
|
|
||
| - Document the limitation clearly | ||
| - Add `/ready` command to signal completion | ||
| - Advise keeping responses short | ||
| - Provide socket checking workarounds | ||
|
|
||
| ## Long-term Solutions | ||
|
|
||
| ### Option 1: Pi Core Enhancement - Message Queue API | ||
|
|
||
| Extend pi's `ExtensionAPI` to expose pending message count: | ||
|
|
||
| ```typescript | ||
| interface ExtensionAPI { | ||
| // ... existing methods | ||
|
|
||
| /** | ||
| * Get count of pending send_to_session messages in queue | ||
| * Returns 0 if no messages pending, N if messages queued | ||
| */ | ||
| getPendingMessageCount(): number; | ||
|
|
||
| /** | ||
| * Get preview of pending messages (if available) | ||
| * Useful for dashboard indicators | ||
| */ | ||
| getPendingMessagePreviews(): Array<{ | ||
| from: string; // sender session ID or name | ||
| preview: string; // first 50 chars | ||
| timestamp: Date; | ||
| }>; | ||
| } | ||
| ``` | ||
|
|
||
| Then the dashboard could show: | ||
| ``` | ||
| ┌─────────────────────────────────────────────────────┐ | ||
| │ 📬 3 messages queued (complete turn to process) │ | ||
| │ • control-agent: "can you check..." │ | ||
| │ • user: "status update?" │ | ||
| └─────────────────────────────────────────────────────┘ | ||
| ``` | ||
|
|
||
| **Implementation**: Requires changes to pi's session control layer (WebSocket/message routing) | ||
|
|
||
| ### Option 2: Streaming Response with Message Interruption | ||
|
|
||
| More ambitious - allow interrupting mid-generation: | ||
|
|
||
| ```typescript | ||
| pi.on("message_received_during_turn", async (event, ctx) => { | ||
| // Opportunity to abort current generation | ||
| // Present queued message immediately | ||
| // Or queue for "after this sentence" | ||
| }); | ||
| ``` | ||
|
|
||
| **Challenges**: | ||
| - Requires streaming/incremental generation support | ||
| - Complex state management (partial responses) | ||
| - May confuse conversation context | ||
|
|
||
| ### Option 3: Parallel Session Mode | ||
|
|
||
| Create a "monitor" mode for debug-agent that spawns a parallel session: | ||
|
|
||
| ```typescript | ||
| // Main session: normal turn-based interaction | ||
| // Monitor session: async-only, polls for messages every 2s | ||
|
|
||
| pi.registerExtension("async-monitor", { | ||
| async init(ctx) { | ||
| if (ctx.sessionRole === "debug-observer") { | ||
| setInterval(() => { | ||
| // Poll session control for pending messages | ||
| // Display in dashboard without blocking main turn | ||
| }, 2000); | ||
| } | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| **Pros**: No pi core changes needed | ||
| **Cons**: Complex dual-session architecture, more resources | ||
|
|
||
| ### Option 4: Event-Driven Dashboard Widget | ||
|
|
||
| The dashboard widget already runs outside the LLM turn. Enhance it to: | ||
| 1. Listen on the session socket directly (bypassing pi's queue) | ||
| 2. Display pending messages in the widget itself (not as user prompts) | ||
| 3. Use `/accept-message <id>` command to pull from queue into conversation | ||
|
|
||
| **Pros**: Clean separation of monitoring vs. conversation | ||
| **Cons**: Two different interaction modes (in-chat vs. dashboard commands) | ||
|
|
||
| ## Recommendation | ||
|
|
||
| **Phase 1** (this PR): Documentation + workarounds | ||
| **Phase 2**: Implement Option 1 (message queue API in pi core) | ||
| **Phase 3**: Consider Option 4 if Option 1 proves insufficient | ||
|
|
||
| Option 1 is the cleanest long-term solution as it: | ||
| - Preserves pi's turn-based model | ||
| - Adds visibility without changing core behavior | ||
| - Minimal API surface area | ||
| - Useful for all session types, not just debug-agent | ||
|
|
||
| ## Related Pi Issues | ||
|
|
||
| - (TODO: check if @mariozechner/pi-coding-agent has issue tracker) | ||
| - Consider proposing this enhancement upstream |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -807,6 +807,14 @@ export default function dashboardExtension(pi: ExtensionAPI): void { | |
| }, | ||
| }); | ||
|
|
||
| // /ready command — signal completion for queued messages | ||
| pi.registerCommand("ready", { | ||
| description: "Signal completion to allow queued send_to_session messages to be processed", | ||
| handler: async (_args, ctx) => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: The Suggested FixAdd a guard clause at the beginning of the Prompt for AI AgentDid we get this right? 👍 / 👎 to inform future reviews. |
||
| ctx.ui.notify("Ready for next message. Complete your response to process queue.", "info"); | ||
| }, | ||
| }); | ||
|
Comment on lines
+810
to
+816
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The handler only fires a UI notification — it doesn't terminate the agent's current response turn or trigger queue processing in any way. Both the command An admin who types If there is a way to end the current turn early (e.g. a Prompt To Fix With AIThis is a comment left during a code review.
Path: pi/skills/debug-agent/debug-dashboard.ts
Line: 810-816
Comment:
**`/ready` doesn't actually signal turn completion**
The handler only fires a UI notification — it doesn't terminate the agent's current response turn or trigger queue processing in any way. Both the command `description` and the `SKILL.md` documentation claim it will *"signal completion to allow queued send_to_session messages to be processed,"* but a `ctx.ui.notify` call has no effect on turn state.
An admin who types `/ready` expecting queued messages to surface will see the notification and believe the workaround worked, when in fact nothing has changed: the agent turn is still in flight and the queue is still blocked. This makes the command actively misleading rather than helpful.
If there is a way to end the current turn early (e.g. a `ctx.session.complete()`, returning a value from the handler that pi interprets as a final response, or emitting a turn-end event), that mechanism should be used here. If no such API exists, the command and its documentation should be rephrased to clarify that it only sends a reminder notification — it does **not** release the queue — and the admin still has to wait for the agent's natural turn completion.
How can I resolve this? If you propose a fix, please make it concise. |
||
|
|
||
| pi.on("session_start", async (_event, ctx) => { | ||
| savedCtx = ctx; | ||
| await refresh(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent socket path (missing
~/.pi/prefix)Step 4 of the workaround refers to
/session-control/as an absolute path, but the Quick Reference table below shows the actual path as~/.pi/session-control/control-agent.alias. An admin following this hint literally would look in the wrong directory.Prompt To Fix With AI