Repository navigation
[EXP] Host interactive Claude agents over stream-json behind KCAP_CLAUDE_TRANSPORT #1877
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 |
|---|---|---|
|
|
@@ -51,6 +51,9 @@ public sealed class ChatTabViewModel : ReactiveObject, IAttachmentSink { | |
| // token it can ask without an ObjectDisposedException. | ||
| readonly CancellationToken _lifetimeToken; | ||
| readonly AvaloniaList<ChatItemViewModel> _items = new(); | ||
| /// Stands in for the launch prompt until the transcript's own rows land. Never a queued send: | ||
| /// the transcript's first read is history, which cannot acknowledge one. | ||
| UserTurnItem? _launchTurn; | ||
| readonly AvaloniaList<QueuedChatMessage> _queuedMessages = new(); | ||
| // Keep retired sends eligible for late echoes without letting them consume a later send's receipt. | ||
| readonly List<(QueuedChatMessage Old, QueuedChatMessage Replacement)> _superseded = new(); | ||
|
|
@@ -1020,10 +1023,18 @@ async Task ChooseTerminalMenuAsync(byte[] keys) { | |
| SetTerminalMenuChoiceTaken(false); | ||
| } | ||
|
|
||
| public void ShowLaunchPrompt(string text) { | ||
| if (_launchTurn is not null || _items.Count > 0) return; | ||
| _launchTurn = new UserTurnItem(text); | ||
| _items.Add(_launchTurn); | ||
|
Comment on lines
+1028
to
+1029
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. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Keep transcript availability visible beside the provisional row. If the feed reports 🤖 Prompt for AI Agents
|
||
| this.RaisePropertyChanged(nameof(PhaseNote)); | ||
|
Comment on lines
+1026
to
+1030
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. 5. Launch placeholder hides transcript failures ShowLaunchPrompt adds a synthetic UserTurnItem that remains in _items, while Prepare checks _items.Count == 0 before entering ChatTabPhase.Failed and PhaseNote returns empty whenever _items is non-empty. When a launched agent’s transcript stays Missing or fails to read before any real row is projected, the placeholder satisfies both item-count guards, leaving only the user’s prompt visible instead of the missing or failed explanation. Agent Prompt
|
||
| } | ||
|
|
||
| void SwitchFeed(string key, Func<string, IChatTranscriptFeed> open) { | ||
| // A released tab's runs belong to the monitor that took its feed; this tab reads nothing more. | ||
| if (_feedReleased) return; | ||
| _items.Clear(); | ||
| if (_launchTurn is not null) _items.Add(_launchTurn); | ||
| _history.Clear(); | ||
| _literalInputHistory.Clear(); | ||
| _unechoed.Clear(); | ||
|
|
@@ -1339,6 +1350,7 @@ bool Prepare(int generation, FeedRead read) { | |
| // names where that history ends — anything past it arrived after and can acknowledge. | ||
| RebaseQueuedMessages(read.SnapshotOffset ?? CurrentOffset ?? 0); | ||
| _items.Clear(); | ||
| if (_launchTurn is not null) _items.Add(_launchTurn); | ||
| _history.ClearForReplay(); | ||
| _pendingTools.Clear(); | ||
| _settledTools.Clear(); | ||
|
|
@@ -1485,7 +1497,11 @@ void Finish(FeedRead read, LineCursor? cursor) { | |
| foreach (var projected in cursor.Restored) | ||
| foreach (var text in projected.SubmittedInputs) | ||
| _history.Observe(AttachmentTrailer.Strip(text)); | ||
| if (cursor.Fresh.Count > 0) _items.AddRange(cursor.Fresh); | ||
| if (cursor.Fresh.Count > 0) { | ||
| if (_launchTurn is not null) _items.Remove(_launchTurn); | ||
| _launchTurn = null; | ||
| _items.AddRange(cursor.Fresh); | ||
| } | ||
| } | ||
| Phase = ChatTabPhase.Reading; | ||
| ApplyFeedRuns(read); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -672,9 +672,10 @@ open is RemoteSessionViewModel remote | |
| /// arriving after any navigation (closing the workspace, another session, close-to-hide, the | ||
| /// shutdown latch) opens nothing, rather than attaching an invisible terminal or replacing what | ||
| /// the user opened while the launch was in flight. | ||
| public void OpenSessionIfCurrent(string agentId, int generation) { | ||
| public void OpenSessionIfCurrent(string agentId, int generation, string? launchPrompt = null) { | ||
| if (generation != _navigation.Generation) return; | ||
| OpenSession(agentId); | ||
| if (OpenSession(agentId) && launchPrompt is { Length: > 0 } && CurrentWorkspace is WorkspaceViewModel workspace) | ||
| workspace.ShowLaunchPrompt(launchPrompt); | ||
|
Comment on lines
+677
to
+678
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. 3. Unsent prompts appear as user messages OpenSessionIfCurrent displays launchPrompt after opening the workspace without checking whether PTY prompt delivery succeeded. For a long prompt delivered after spawn, an agent exit, stop, cancellation, or write failure can leave a “You” turn that was never submitted, because the delivery outcome is only logged. Agent Prompt
|
||
| } | ||
|
|
||
| /// The launcher words a launch failure, and an open workspace covers the launcher. Only a | ||
|
|
||
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.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Insert the launch prompt before pending cards.
If a permission card arrives before the first transcript row,
SyncPendingCardItemshas already added aPendingCardItemto_items. The count check then rejects the launch prompt. The user cannot see the submitted prompt while deciding that permission request. Check for transcript rows rather than any row, and insert the prompt before pending cards.🤖 Prompt for AI Agents