File size: 2,248 Bytes
6f91ce5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import { z } from 'zod'

// The `_canvas/*` ACP extension messages the harness sends to one researcher's browser (group README,
// Shared contracts). They change only that browser's view, never the shared room. Optional fields
// also accept null, since the Python side may send None for "not given".

export const CANVAS_METHODS = {
	focus: '_canvas/focus',
	highlight: '_canvas/highlight',
	openPaper: '_canvas/open_paper',
	tour: '_canvas/tour',
	snapshot: '_canvas/snapshot',
} as const

const sessionId = z.string().min(1)
const ids = z.array(z.string().min(1)).nullish()

export const focusParams = z.object({
	sessionId,
	shapeIds: ids,
	paperIds: ids,
	inset: z.number().nonnegative().nullish(),
	animate: z.boolean().nullish(),
})

export const highlightParams = z.object({
	sessionId,
	shapeIds: ids,
	paperIds: ids,
	durationMs: z.number().nonnegative().nullish(),
})

export const openPaperParams = z.object({ sessionId, paperId: z.string().min(1) })

export const DEFAULT_TOUR_TITLE = 'Catch-up'

export const tourParams = z.object({
	sessionId,
	title: z.string().default(DEFAULT_TOUR_TITLE),
	steps: z.array(z.object({ paperId: z.string().min(1), line: z.string() })),
})

/**
 * A request, not a notification: the agent waits for the picture (T07). `shapes` takes `shapeIds`
 * and/or `paperIds`; there are no PDF pages to draw (decision D25).
 */
export const snapshotParams = z.object({
	sessionId,
	target: z.enum(['viewport', 'board', 'shapes']),
	shapeIds: ids,
	paperIds: ids,
	maxSide: z.number().int().positive().nullish(),
})

/** The browser's answer to `_canvas/snapshot`; it fails with a JSON-RPC error instead when it can't draw. */
export const snapshotResult = z.object({
	mimeType: z.literal('image/png'),
	/** Base64, no data: prefix. */
	data: z.string().min(1),
	width: z.number().int().positive(),
	height: z.number().int().positive(),
	caption: z.string(),
})

export type FocusParams = z.infer<typeof focusParams>
export type HighlightParams = z.infer<typeof highlightParams>
export type OpenPaperParams = z.infer<typeof openPaperParams>
export type TourParams = z.infer<typeof tourParams>
export type SnapshotParams = z.infer<typeof snapshotParams>
export type SnapshotResult = z.infer<typeof snapshotResult>