Gateway: keep whole T3 history pages, and show a command's first line as its activity
This commit is contained in:
1 parent
52210d0223
commit
abd2fd0e13
3 files changed
+13
-7
No files matched your search
+3
-2
@@ -94,7 +94,7 @@ when the gateway cannot find its parent, or the parent already shows a request.
|
||||
for a moment after a thread changes.
|
||||
|
||||
`activity` is the newest step the agent has in progress. `kind` is `command`, `edit`, `search`,
|
||||
`web`, `subagent`, `thinking` or `tool`, and `text` is the command line, the file name (without its
|
||||
`web`, `subagent`, `thinking` or `tool`, and `text` is the command's first line, the file name (without its
|
||||
directory), the search, the subagent's title or the tool's name, trimmed to about 80 characters.
|
||||
Monitors are left out, since they run for hours. It is null when no step is in progress. The gateway
|
||||
rereads a running thread at most every 5 seconds, so it can lag that much.
|
||||
@@ -136,7 +136,8 @@ GET /v1/threads/:hostId/:threadId/history?cursor=<earlierCursor>
|
||||
200 { "messages": [Message], "earlierCursor": "..." | null }
|
||||
```
|
||||
|
||||
The 20 messages before the ones the watch has, oldest first. Pass the returned `earlierCursor` for
|
||||
The messages before the ones the watch has, oldest first: 20 at a time at first, then one T3 history
|
||||
page at a time, which can hold more. Pass the returned `earlierCursor` for
|
||||
the page before that. It is null at the start of the thread. Cursors are opaque.
|
||||
|
||||
```
|
||||
|
||||
@@ -93,7 +93,10 @@ function windowCursor(start: number, bounded: BoundedThread): string | null {
|
||||
return bounded.hasMoreHistory && bounded.historyCursor ? `h${bounded.historyCursor}` : null;
|
||||
}
|
||||
|
||||
/** Up to 20 messages before `cursor`. T3 pages without messages are skipped, three at most. */
|
||||
/**
|
||||
* The messages before `cursor`: 20 from the bounded window, or one T3 page, which can hold more.
|
||||
* T3 pages without messages are skipped, three at most.
|
||||
*/
|
||||
export async function loadHistory(host: T3Host, thread: ThreadShell, cursor: string): Promise<HistoryResponse> {
|
||||
if (cursor.startsWith("w")) {
|
||||
const end = Number(cursor.slice(1));
|
||||
@@ -120,7 +123,7 @@ export async function loadHistory(host: T3Host, thread: ThreadShell, cursor: str
|
||||
createdAt: item.startedAt ?? item.updatedAt ?? "",
|
||||
}),
|
||||
);
|
||||
if (messages.length > 0) return { messages: messages.slice(-MESSAGES_PER_THREAD), earlierCursor: next && `h${next}` };
|
||||
if (messages.length > 0) return { messages, earlierCursor: next && `h${next}` };
|
||||
}
|
||||
return { messages: [], earlierCursor: next && `h${next}` };
|
||||
}
|
||||
@@ -139,7 +142,9 @@ export function currentActivity(turnItems: TurnItem[]): Activity | null {
|
||||
function describeStep(item: TurnItem): Omit<Activity, "startedAt"> | null {
|
||||
switch (item.type) {
|
||||
case "command_execution":
|
||||
return item.monitor || typeof item.input !== "string" ? null : { kind: "command", text: item.input };
|
||||
return item.monitor || typeof item.input !== "string"
|
||||
? null
|
||||
: { kind: "command", text: item.input.split("\n").find((line) => line.trim()) ?? item.input };
|
||||
case "file_change":
|
||||
return item.fileName ? { kind: "edit", text: item.fileName.split("/").pop()! } : null;
|
||||
case "file_search":
|
||||
|
||||
@@ -239,11 +239,11 @@ describe("currentActivity", () => {
|
||||
expect(
|
||||
currentActivity([
|
||||
item("file_change", "running", { fileName: "gateway/src/host.ts" }),
|
||||
item("command_execution", "running", { input: "bun test" }),
|
||||
item("command_execution", "running", { input: "\nbun test \\\n --bail" }),
|
||||
item("command_execution", "running", { input: "tail -f log", monitor: true }),
|
||||
item("assistant_message", "running"),
|
||||
]),
|
||||
).toEqual({ kind: "command", text: "bun test", startedAt: "2026-11-01T09:00:00.000Z" });
|
||||
).toEqual({ kind: "command", text: "bun test \\", startedAt: "2026-11-01T09:00:00.000Z" });
|
||||
expect(currentActivity([item("file_change", "running", { fileName: "gateway/src/host.ts" })])?.text).toBe("host.ts");
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user