fix(e2e): decode packed history records
This commit is contained in:
parent
04c0758fe9
commit
4f02717ebc
5 changed files with 25 additions and 19 deletions
|
|
@ -11,6 +11,7 @@ import { tmpdir } from 'node:os'
|
|||
import { join } from 'node:path'
|
||||
import { setTimeout as delay } from 'node:timers/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { decodeStorageRecord } from '@deepseek-ai/dsh-session/chunk-rows'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import WebSocket from 'ws'
|
||||
|
||||
|
|
@ -59,15 +60,15 @@ interface WorkspaceBaseline {
|
|||
}
|
||||
|
||||
interface HistoryPage {
|
||||
events: Array<{
|
||||
event: {
|
||||
type: string
|
||||
data: unknown
|
||||
}
|
||||
}>
|
||||
records: Array<{ event: HistoryEvent } | { chunks: unknown }>
|
||||
hasMore: boolean
|
||||
}
|
||||
|
||||
interface HistoryEvent {
|
||||
type: string
|
||||
data: unknown
|
||||
}
|
||||
|
||||
interface ProcessObservation {
|
||||
readonly ready: Promise<string>
|
||||
readonly text: () => string
|
||||
|
|
@ -255,10 +256,10 @@ async function history(baseUrl: string, sessionId: string): Promise<HistoryPage>
|
|||
{ request: { address: { kind: 'session', sessionId }, maxMessages: 100 } },
|
||||
value => isRecord(value)
|
||||
&& value.type === 'snapshot'
|
||||
&& Array.isArray(value.events)
|
||||
&& Array.isArray(value.records)
|
||||
&& typeof value.hasMore === 'boolean',
|
||||
)
|
||||
return { events: frame.events as HistoryPage['events'], hasMore: frame.hasMore as boolean }
|
||||
return { records: frame.records as HistoryPage['records'], hasMore: frame.hasMore as boolean }
|
||||
}
|
||||
|
||||
/** Poll a public observation until it satisfies the test's behavior predicate. */
|
||||
|
|
@ -294,7 +295,7 @@ async function eventually<T>(
|
|||
/** Return every text block from durable assistant messages. */
|
||||
function assistantText(page: HistoryPage): string {
|
||||
const text: string[] = []
|
||||
for (const { event } of page.events) {
|
||||
for (const event of historyEvents(page)) {
|
||||
if (event.type !== 'assistant/message' || !isRecord(event.data) || !isRecord(event.data.message)) continue
|
||||
const content = event.data.message.content
|
||||
if (!Array.isArray(content)) continue
|
||||
|
|
@ -305,6 +306,11 @@ function assistantText(page: HistoryPage): string {
|
|||
return text.join('\n')
|
||||
}
|
||||
|
||||
/** Expand lossless history records for assertions over the public event stream. */
|
||||
function historyEvents(page: HistoryPage): HistoryEvent[] {
|
||||
return page.records.flatMap(record => 'event' in record ? [record.event] : decodeStorageRecord(record.chunks))
|
||||
}
|
||||
|
||||
/** Stop the spawned CLI through its normal signal path, escalating only on a stuck teardown. */
|
||||
async function stop(child: ChildProcess): Promise<void> {
|
||||
if (child.exitCode !== null) return
|
||||
|
|
@ -410,7 +416,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('GitHub webhook through the real
|
|||
'webhook provenance, title, and permission events',
|
||||
async () => await history(baseUrl, sessionId),
|
||||
(page) => {
|
||||
const events = page.events.map(item => item.event)
|
||||
const events = historyEvents(page)
|
||||
const title = events.find(event => event.type === 'session/title')
|
||||
const permission = events.find(event =>
|
||||
event.type === 'permission/preset'
|
||||
|
|
@ -429,7 +435,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('GitHub webhook through the real
|
|||
},
|
||||
30_000,
|
||||
)
|
||||
const webhookMessage = admitted.events.map(item => item.event)
|
||||
const webhookMessage = historyEvents(admitted)
|
||||
.find(event => event.type === 'user/message'
|
||||
&& isRecord(event.data)
|
||||
&& isRecord(event.data.source)
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/event-producer-consumer.md
|
||||
event-producer-consumer.md: 6f971f5470c34093dd3774650ad191f9a3516df7
|
||||
event-producer-consumer.md: ce914f90821adc09c59dca15f202831a51655565
|
||||
event-producer-consumer.zh.md: ca375c98b6c0552f255e5d2604c9ad0c1d968aad
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
|||
| `agent/session-start` | `emit` | [`packages/core/agent/src/runtime-types.ts:224`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emitAgentEvent`) | `agent-team`, [`goal`](../packages/goal/goal), [`goal-round-driver`](../packages/goal/goal-round-driver), [`hooks-claude-code`](../packages/hooks/hooks-claude-code), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `agent/status` | `emit` | [`packages/core/agent/src/runtime-types.ts:185`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`emit`) | [`agent`](../packages/core/agent), `agent-team`, [`compaction-basic`](../packages/compaction/compaction-basic), [`goal-round-driver`](../packages/goal/goal-round-driver), [`schedule`](../packages/schedule/schedule), `server`, `session-controller` |
|
||||
| `agent/turn-stopping` | `serial` | [`packages/core/agent/src/runtime-types.ts:285`](../packages/core/agent/src/runtime-types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`hooks-claude-code`](../packages/hooks/hooks-claude-code), [`hooks-codex`](../packages/hooks/hooks-codex) |
|
||||
| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:482`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:462`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:489`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:468`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:475`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/activity` | `emit` | [`packages/api/session-controller/src/types.ts:491`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/added` | `emit` | [`packages/api/session-controller/src/types.ts:471`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/error` | `emit` | [`packages/api/session-controller/src/types.ts:498`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/removed` | `emit` | [`packages/api/session-controller/src/types.ts:477`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `api-session/status` | `emit` | [`packages/api/session-controller/src/types.ts:484`](../packages/api/session-controller/src/types.ts) | `session-controller` (`emit`) | `remotes` |
|
||||
| `approval/request` | `waterfall` | [`packages/interaction/user-approval/src/types.ts:85`](../packages/interaction/user-approval/src/types.ts) | [`user-approval`](../packages/interaction/user-approval) (`waterfall`) | [`acp`](../packages/acp/acp), `remotes` |
|
||||
| `authorization/settled` | `emit` | [`packages/credentials/authorization/src/index.ts:57`](../packages/credentials/authorization/src/index.ts) | [`authorization`](../packages/credentials/authorization) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization) |
|
||||
| `commands/change` | `emit` | [`packages/interaction/commands/src/types.ts:80`](../packages/interaction/commands/src/types.ts) | [`commands`](../packages/interaction/commands) (`events.dispatch`) | `remotes` |
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/persistence-catalog.md
|
||||
persistence-catalog.md: 12558eeadc009b498c9a178cfcc79116bf1b7c2b
|
||||
persistence-catalog.md: 7c63cd8dfdb181fac09cf3ce2e4bcec96d2bd59c
|
||||
persistence-catalog.zh.md: f855d6969aa2dcade159ac8d6549e5f0350a7f0f
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ Source: [`packages/llm/llm-retry/src/types.ts:11`](../packages/llm/llm-retry/src
|
|||
'model/selection': ModelSelection
|
||||
```
|
||||
|
||||
Source: [`packages/api/session-controller/src/types.ts:39`](../packages/api/session-controller/src/types.ts)
|
||||
Source: [`packages/api/session-controller/src/types.ts:40`](../packages/api/session-controller/src/types.ts)
|
||||
|
||||
### `permission/*`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue