diff options
| author | Adam Malczewski <[email protected]> | 2026-06-21 16:56:42 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-21 16:56:42 +0900 |
| commit | ea0e938eca3072649dc8707c999ec00cf87b986a (patch) | |
| tree | 41f96ed517fe779ed612fc4cb3e8359a841ad088 /packages/transport-http/src/logic.ts | |
| parent | 36e950ba2cd2591e86f0dcc898f740481c59d912 (diff) | |
| download | dispatch-ea0e938eca3072649dc8707c999ec00cf87b986a.tar.gz dispatch-ea0e938eca3072649dc8707c999ec00cf87b986a.zip | |
feat(transport): CLI endpoints + conversation.open broadcast (Wave 2)
transport-http: GET /conversations (list with ?q= prefix filter),
GET /conversations/:id/last (blocks until turn settles, returns last AI
text), POST /conversations/:id/open (emits conversationOpened hook),
PUT /conversations/:id/title (set title). emit threaded from host.emit.
extractLastAssistantText pure helper. 21 new tests (166 total).
transport-ws: subscribes to conversationOpened hook, broadcasts
ConversationOpenMessage to all connected WS clients. 2 new tests.
session-orchestrator: conversationOpened hook descriptor (exported).
Diffstat (limited to 'packages/transport-http/src/logic.ts')
| -rw-r--r-- | packages/transport-http/src/logic.ts | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/packages/transport-http/src/logic.ts b/packages/transport-http/src/logic.ts index aa5394c..d20713c 100644 --- a/packages/transport-http/src/logic.ts +++ b/packages/transport-http/src/logic.ts @@ -1,4 +1,4 @@ -import type { AgentEvent, ReasoningEffort } from "@dispatch/kernel"; +import type { AgentEvent, ChatMessage, ReasoningEffort } from "@dispatch/kernel"; const VALID_REASONING_EFFORTS: readonly ReasoningEffort[] = [ "low", @@ -221,3 +221,33 @@ export function isReasoningEffortParseError( ): result is ParseError { return typeof result === "object" && result !== null && "error" in result; } + +/** + * Extract the text of the last assistant message's last `text` chunk — the + * "show me the last reply" affordance for `GET /conversations/:id/last`. + * + * Scan from the END for the last message with `role: "assistant"`, then within + * THAT message for the last `type: "text"` chunk. Returns its `text`. Returns + * `""` when there is no assistant message, or when the last assistant message + * has no text chunk (e.g. only tool-call chunks). + * + * Pure (input → output); zero I/O, so it tests directly without mocks. + */ +export function extractLastAssistantText(messages: readonly ChatMessage[]): string { + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + if (msg === undefined || msg.role !== "assistant") continue; + // Found the last assistant message — scan its chunks from the end for + // the last `text` chunk. Stop here (do not keep scanning earlier + // assistant messages): the contract is "the last assistant message's + // last text chunk", not "the most recent text chunk anywhere". + for (let j = msg.chunks.length - 1; j >= 0; j--) { + const chunk = msg.chunks[j]; + if (chunk !== undefined && chunk.type === "text") { + return chunk.text; + } + } + return ""; + } + return ""; +} |
