opencode-drive 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -80
- package/package.json +1 -1
- package/src/cli/commands.ts +104 -68
- package/src/cli/control.ts +143 -0
- package/src/cli/index.ts +149 -106
- package/src/cli/instance.ts +222 -168
- package/src/cli/list.ts +10 -0
- package/src/cli/logs.ts +9 -0
- package/src/cli/mock-backend.ts +37 -0
- package/src/cli/registry.ts +224 -71
- package/src/cli/response-generator.ts +334 -0
- package/src/cli/responses.ts +20 -0
- package/src/cli/restart.ts +2 -65
- package/src/cli/script.ts +77 -0
- package/src/cli/send.ts +22 -39
- package/src/cli/start.ts +202 -65
- package/src/cli/stop.ts +19 -26
- package/src/cli/types.ts +7 -30
- package/src/client/backend.ts +95 -33
- package/src/client/client.ts +86 -29
- package/src/client/protocol.ts +116 -29
- package/src/client/protocol.types.ts +17 -23
- package/src/experimental/driver.ts +29 -18
- package/src/experimental/flow-driver.ts +130 -43
- package/src/experimental/flows/properties.ts +19 -13
- package/src/experimental/hello-driver.ts +11 -4
- package/src/experimental/stale-running-driver.ts +45 -13
- package/src/index.ts +2 -0
- package/src/cli/describe.ts +0 -14
- package/src/cli/driver-runner.ts +0 -39
- package/src/cli/driver.ts +0 -28
- package/src/experimental/cli-campaign.ts +0 -179
package/src/client/backend.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Backend,
|
|
3
|
-
type JsonRpc,
|
|
4
|
-
} from "./protocol.js"
|
|
1
|
+
import { Backend, type JsonRpc } from "./protocol.js"
|
|
5
2
|
|
|
6
3
|
const defaultBackendPort = 40950
|
|
7
4
|
|
|
8
5
|
type BackendMethods = {
|
|
9
|
-
readonly "llm.attach": {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly "llm.
|
|
6
|
+
readonly "llm.attach": {
|
|
7
|
+
readonly params: undefined
|
|
8
|
+
readonly result: { readonly attached: true }
|
|
9
|
+
}
|
|
10
|
+
readonly "llm.chunk": {
|
|
11
|
+
readonly params: Backend.ChunkParams
|
|
12
|
+
readonly result: { readonly ok: true }
|
|
13
|
+
}
|
|
14
|
+
readonly "llm.finish": {
|
|
15
|
+
readonly params: Partial<Backend.FinishParams> &
|
|
16
|
+
Pick<Backend.FinishParams, "id">
|
|
17
|
+
readonly result: { readonly ok: true }
|
|
18
|
+
}
|
|
19
|
+
readonly "llm.disconnect": {
|
|
20
|
+
readonly params: Backend.DisconnectParams
|
|
21
|
+
readonly result: { readonly ok: true }
|
|
22
|
+
}
|
|
14
23
|
}
|
|
15
24
|
|
|
16
25
|
type BackendMethodName = keyof BackendMethods
|
|
@@ -45,21 +54,37 @@ export class BackendSimulationClient {
|
|
|
45
54
|
private readonly socket: WebSocket
|
|
46
55
|
private readonly timeout: number
|
|
47
56
|
private nextId = 1
|
|
57
|
+
private closing = false
|
|
48
58
|
private readonly pending = new Map<number, Waiter>()
|
|
49
|
-
private readonly llmRequests = new Set<
|
|
59
|
+
private readonly llmRequests = new Set<
|
|
60
|
+
(request: Backend.OpenedExchange) => void
|
|
61
|
+
>()
|
|
50
62
|
|
|
51
63
|
private constructor(socket: WebSocket, url: string, timeout: number) {
|
|
52
64
|
this.socket = socket
|
|
53
65
|
this.url = url
|
|
54
66
|
this.timeout = timeout
|
|
55
|
-
socket.addEventListener("message", (event) =>
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
socket.addEventListener("message", (event) =>
|
|
68
|
+
this.onMessage(String(event.data)),
|
|
69
|
+
)
|
|
70
|
+
socket.addEventListener("close", () =>
|
|
71
|
+
this.rejectAll(new BackendSimulationError("connection closed")),
|
|
72
|
+
)
|
|
73
|
+
socket.addEventListener("error", () =>
|
|
74
|
+
this.rejectAll(new BackendSimulationError("connection error")),
|
|
75
|
+
)
|
|
58
76
|
}
|
|
59
77
|
|
|
60
|
-
static async connect(
|
|
78
|
+
static async connect(
|
|
79
|
+
options?: BackendSimulationClientOptions,
|
|
80
|
+
): Promise<BackendSimulationClient> {
|
|
61
81
|
const timeout = options?.timeout ?? 30_000
|
|
62
|
-
if (options?.url !== undefined)
|
|
82
|
+
if (options?.url !== undefined)
|
|
83
|
+
return new BackendSimulationClient(
|
|
84
|
+
await open(options.url),
|
|
85
|
+
options.url,
|
|
86
|
+
timeout,
|
|
87
|
+
)
|
|
63
88
|
const first = options?.port ?? defaultBackendPort
|
|
64
89
|
const attempts = options?.portAttempts ?? 10
|
|
65
90
|
for (let offset = 0; offset < attempts; offset++) {
|
|
@@ -68,28 +93,52 @@ export class BackendSimulationClient {
|
|
|
68
93
|
return new BackendSimulationClient(await open(url), url, timeout)
|
|
69
94
|
} catch {}
|
|
70
95
|
}
|
|
71
|
-
throw new BackendSimulationError(
|
|
96
|
+
throw new BackendSimulationError(
|
|
97
|
+
`no backend simulation server found on ports ${first}-${first + attempts - 1}`,
|
|
98
|
+
)
|
|
72
99
|
}
|
|
73
100
|
|
|
74
101
|
async call<M extends BackendMethodName>(
|
|
75
102
|
method: M,
|
|
76
103
|
params?: BackendMethods[M]["params"],
|
|
77
104
|
): Promise<BackendMethods[M]["result"]> {
|
|
78
|
-
if (this.socket.readyState !== WebSocket.OPEN)
|
|
105
|
+
if (this.socket.readyState !== WebSocket.OPEN)
|
|
106
|
+
throw new BackendSimulationError("connection is not open", method)
|
|
79
107
|
const id = this.nextId++
|
|
80
108
|
const promise = new Promise<unknown>((resolve, reject) => {
|
|
81
109
|
const timer = setTimeout(() => {
|
|
82
110
|
this.pending.delete(id)
|
|
83
|
-
reject(
|
|
111
|
+
reject(
|
|
112
|
+
new BackendSimulationError(
|
|
113
|
+
`timed out after ${this.timeout}ms`,
|
|
114
|
+
method,
|
|
115
|
+
),
|
|
116
|
+
)
|
|
84
117
|
}, this.timeout)
|
|
85
118
|
this.pending.set(id, { method, resolve, reject, timer })
|
|
86
119
|
})
|
|
87
|
-
this.socket.send(
|
|
120
|
+
this.socket.send(
|
|
121
|
+
JSON.stringify({
|
|
122
|
+
jsonrpc: "2.0",
|
|
123
|
+
id,
|
|
124
|
+
method,
|
|
125
|
+
...(params === undefined ? {} : { params }),
|
|
126
|
+
}),
|
|
127
|
+
)
|
|
88
128
|
return (await promise) as BackendMethods[M]["result"]
|
|
89
129
|
}
|
|
90
130
|
|
|
91
|
-
async attach(
|
|
92
|
-
|
|
131
|
+
async attach(
|
|
132
|
+
onRequest: (request: Backend.OpenedExchange) => void | Promise<void>,
|
|
133
|
+
) {
|
|
134
|
+
this.llmRequests.add((request) => {
|
|
135
|
+
void Promise.resolve(onRequest(request)).catch((error) => {
|
|
136
|
+
if (!this.closing)
|
|
137
|
+
console.error(
|
|
138
|
+
`error: ${error instanceof Error ? error.message : String(error)}`,
|
|
139
|
+
)
|
|
140
|
+
})
|
|
141
|
+
})
|
|
93
142
|
return await this.call("llm.attach")
|
|
94
143
|
}
|
|
95
144
|
|
|
@@ -98,19 +147,19 @@ export class BackendSimulationClient {
|
|
|
98
147
|
}
|
|
99
148
|
|
|
100
149
|
finish(id: string, reason?: Backend.FinishReason) {
|
|
101
|
-
return this.call("llm.finish", {
|
|
150
|
+
return this.call("llm.finish", {
|
|
151
|
+
id,
|
|
152
|
+
...(reason === undefined ? {} : { reason }),
|
|
153
|
+
})
|
|
102
154
|
}
|
|
103
155
|
|
|
104
156
|
disconnect(id: string) {
|
|
105
157
|
return this.call("llm.disconnect", { id })
|
|
106
158
|
}
|
|
107
159
|
|
|
108
|
-
pendingExchanges() {
|
|
109
|
-
return this.call("llm.pending")
|
|
110
|
-
}
|
|
111
|
-
|
|
112
160
|
close() {
|
|
113
|
-
this.
|
|
161
|
+
this.closing = true
|
|
162
|
+
this.socket.terminate()
|
|
114
163
|
}
|
|
115
164
|
|
|
116
165
|
private onMessage(data: string) {
|
|
@@ -118,7 +167,8 @@ export class BackendSimulationClient {
|
|
|
118
167
|
if (message === undefined) return
|
|
119
168
|
if ("method" in message) {
|
|
120
169
|
if (message.method === "llm.request") {
|
|
121
|
-
for (const listener of this.llmRequests)
|
|
170
|
+
for (const listener of this.llmRequests)
|
|
171
|
+
listener(message.params as Backend.OpenedExchange)
|
|
122
172
|
}
|
|
123
173
|
return
|
|
124
174
|
}
|
|
@@ -127,7 +177,10 @@ export class BackendSimulationClient {
|
|
|
127
177
|
if (waiter === undefined) return
|
|
128
178
|
this.pending.delete(message.id)
|
|
129
179
|
clearTimeout(waiter.timer)
|
|
130
|
-
if (message.error)
|
|
180
|
+
if (message.error)
|
|
181
|
+
waiter.reject(
|
|
182
|
+
new BackendSimulationError(message.error.message, waiter.method),
|
|
183
|
+
)
|
|
131
184
|
else waiter.resolve(message.result)
|
|
132
185
|
}
|
|
133
186
|
|
|
@@ -140,13 +193,21 @@ export class BackendSimulationClient {
|
|
|
140
193
|
}
|
|
141
194
|
}
|
|
142
195
|
|
|
143
|
-
function parseResponse(
|
|
196
|
+
function parseResponse(
|
|
197
|
+
data: string,
|
|
198
|
+
):
|
|
199
|
+
| JsonRpc.Response
|
|
200
|
+
| { readonly method: string; readonly params: unknown }
|
|
201
|
+
| undefined {
|
|
144
202
|
try {
|
|
145
203
|
const value = JSON.parse(data) as unknown
|
|
146
204
|
if (typeof value !== "object" || value === null) return undefined
|
|
147
205
|
if (!("jsonrpc" in value) || value.jsonrpc !== "2.0") return undefined
|
|
148
206
|
if ("method" in value && typeof value.method === "string") {
|
|
149
|
-
return {
|
|
207
|
+
return {
|
|
208
|
+
method: value.method,
|
|
209
|
+
params: "params" in value ? value.params : undefined,
|
|
210
|
+
}
|
|
150
211
|
}
|
|
151
212
|
if (!("id" in value)) return undefined
|
|
152
213
|
return value as JsonRpc.Response
|
|
@@ -175,5 +236,6 @@ function open(url: string): Promise<WebSocket> {
|
|
|
175
236
|
})
|
|
176
237
|
}
|
|
177
238
|
|
|
178
|
-
export const connectBackendSimulation = (
|
|
179
|
-
|
|
239
|
+
export const connectBackendSimulation = (
|
|
240
|
+
options?: BackendSimulationClientOptions,
|
|
241
|
+
): Promise<BackendSimulationClient> => BackendSimulationClient.connect(options)
|
package/src/client/client.ts
CHANGED
|
@@ -1,21 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Frontend,
|
|
3
|
-
type JsonRpc,
|
|
4
|
-
} from "./protocol.js"
|
|
1
|
+
import { Frontend, type JsonRpc } from "./protocol.js"
|
|
5
2
|
|
|
6
3
|
const defaultPort = 40900
|
|
7
4
|
|
|
8
5
|
type Methods = {
|
|
9
|
-
readonly "ui.screenshot": {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
readonly "ui.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly "ui.
|
|
18
|
-
|
|
6
|
+
readonly "ui.screenshot": {
|
|
7
|
+
readonly params: undefined
|
|
8
|
+
readonly result: Frontend.Screenshot
|
|
9
|
+
}
|
|
10
|
+
readonly "ui.state": {
|
|
11
|
+
readonly params: undefined
|
|
12
|
+
readonly result: Frontend.State
|
|
13
|
+
}
|
|
14
|
+
readonly "ui.start-record": {
|
|
15
|
+
readonly params: undefined
|
|
16
|
+
readonly result: Frontend.StartRecord
|
|
17
|
+
}
|
|
18
|
+
readonly "ui.end-record": {
|
|
19
|
+
readonly params: undefined
|
|
20
|
+
readonly result: Frontend.EndRecord
|
|
21
|
+
}
|
|
22
|
+
readonly "ui.type": {
|
|
23
|
+
readonly params: Frontend.TypeParams
|
|
24
|
+
readonly result: Frontend.State
|
|
25
|
+
}
|
|
26
|
+
readonly "ui.press": {
|
|
27
|
+
readonly params: Frontend.PressParams
|
|
28
|
+
readonly result: Frontend.State
|
|
29
|
+
}
|
|
30
|
+
readonly "ui.enter": {
|
|
31
|
+
readonly params: undefined
|
|
32
|
+
readonly result: Frontend.State
|
|
33
|
+
}
|
|
34
|
+
readonly "ui.arrow": {
|
|
35
|
+
readonly params: Frontend.ArrowParams
|
|
36
|
+
readonly result: Frontend.State
|
|
37
|
+
}
|
|
38
|
+
readonly "ui.focus": {
|
|
39
|
+
readonly params: Frontend.FocusParams
|
|
40
|
+
readonly result: Frontend.State
|
|
41
|
+
}
|
|
42
|
+
readonly "ui.click": {
|
|
43
|
+
readonly params: Frontend.ClickParams
|
|
44
|
+
readonly result: Frontend.State
|
|
45
|
+
}
|
|
19
46
|
}
|
|
20
47
|
|
|
21
48
|
type MethodName = keyof Methods
|
|
@@ -73,12 +100,20 @@ export class SimulationClient {
|
|
|
73
100
|
this.socket = socket
|
|
74
101
|
this.url = url
|
|
75
102
|
this.timeout = timeout
|
|
76
|
-
socket.addEventListener("message", (event) =>
|
|
77
|
-
|
|
78
|
-
|
|
103
|
+
socket.addEventListener("message", (event) =>
|
|
104
|
+
this.onMessage(String(event.data)),
|
|
105
|
+
)
|
|
106
|
+
socket.addEventListener("close", () =>
|
|
107
|
+
this.rejectAll(new SimulationError("connection closed")),
|
|
108
|
+
)
|
|
109
|
+
socket.addEventListener("error", () =>
|
|
110
|
+
this.rejectAll(new SimulationError("connection error")),
|
|
111
|
+
)
|
|
79
112
|
}
|
|
80
113
|
|
|
81
|
-
static async connect(
|
|
114
|
+
static async connect(
|
|
115
|
+
options?: SimulationClientOptions,
|
|
116
|
+
): Promise<SimulationClient> {
|
|
82
117
|
const timeout = options?.timeout ?? 30_000
|
|
83
118
|
if (options?.url !== undefined) {
|
|
84
119
|
return new SimulationClient(await open(options.url), options.url, timeout)
|
|
@@ -100,7 +135,10 @@ export class SimulationClient {
|
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
/** Raw JSON-RPC call. Prefer the typed wrappers below. */
|
|
103
|
-
async call<M extends MethodName>(
|
|
138
|
+
async call<M extends MethodName>(
|
|
139
|
+
method: M,
|
|
140
|
+
params?: Methods[M]["params"],
|
|
141
|
+
): Promise<Methods[M]["result"]> {
|
|
104
142
|
if (this.socket.readyState !== WebSocket.OPEN) {
|
|
105
143
|
throw new SimulationError("connection is not open", method)
|
|
106
144
|
}
|
|
@@ -112,7 +150,14 @@ export class SimulationClient {
|
|
|
112
150
|
}, this.timeout)
|
|
113
151
|
this.pending.set(id, { method, resolve, reject, timer })
|
|
114
152
|
})
|
|
115
|
-
this.socket.send(
|
|
153
|
+
this.socket.send(
|
|
154
|
+
JSON.stringify({
|
|
155
|
+
jsonrpc: "2.0",
|
|
156
|
+
id,
|
|
157
|
+
method,
|
|
158
|
+
...(params === undefined ? {} : { params }),
|
|
159
|
+
}),
|
|
160
|
+
)
|
|
116
161
|
// The server contract types each method's result; the cast happens once
|
|
117
162
|
// here rather than at every call site.
|
|
118
163
|
return (await promise) as Methods[M]["result"]
|
|
@@ -142,15 +187,23 @@ export class SimulationClient {
|
|
|
142
187
|
return this.call("ui.type", { text })
|
|
143
188
|
}
|
|
144
189
|
|
|
145
|
-
pressKey(
|
|
146
|
-
|
|
190
|
+
pressKey(
|
|
191
|
+
key: string,
|
|
192
|
+
modifiers?: Frontend.KeyModifiers,
|
|
193
|
+
): Promise<Frontend.State> {
|
|
194
|
+
return this.call("ui.press", {
|
|
195
|
+
key: key === "escape" ? "\u001b" : key,
|
|
196
|
+
...(modifiers === undefined ? {} : { modifiers }),
|
|
197
|
+
})
|
|
147
198
|
}
|
|
148
199
|
|
|
149
200
|
pressEnter(): Promise<Frontend.State> {
|
|
150
201
|
return this.call("ui.enter")
|
|
151
202
|
}
|
|
152
203
|
|
|
153
|
-
pressArrow(
|
|
204
|
+
pressArrow(
|
|
205
|
+
direction: "up" | "down" | "left" | "right",
|
|
206
|
+
): Promise<Frontend.State> {
|
|
154
207
|
return this.call("ui.arrow", { direction })
|
|
155
208
|
}
|
|
156
209
|
|
|
@@ -165,7 +218,7 @@ export class SimulationClient {
|
|
|
165
218
|
// ── lifecycle ─────────────────────────────────────────────────────────
|
|
166
219
|
|
|
167
220
|
close(): void {
|
|
168
|
-
this.socket.
|
|
221
|
+
this.socket.terminate()
|
|
169
222
|
}
|
|
170
223
|
|
|
171
224
|
private onMessage(data: string) {
|
|
@@ -175,7 +228,8 @@ export class SimulationClient {
|
|
|
175
228
|
if (waiter === undefined) return
|
|
176
229
|
this.pending.delete(message.id)
|
|
177
230
|
clearTimeout(waiter.timer)
|
|
178
|
-
if (message.error)
|
|
231
|
+
if (message.error)
|
|
232
|
+
waiter.reject(new SimulationError(message.error.message, waiter.method))
|
|
179
233
|
else waiter.resolve(message.result)
|
|
180
234
|
}
|
|
181
235
|
|
|
@@ -199,14 +253,16 @@ function parseResponse(data: string): JsonRpc.Response | undefined {
|
|
|
199
253
|
if (!("jsonrpc" in value) || value.jsonrpc !== "2.0") return undefined
|
|
200
254
|
if (!("id" in value)) return undefined
|
|
201
255
|
const id = value.id
|
|
202
|
-
if (typeof id !== "number" && typeof id !== "string" && id !== null)
|
|
256
|
+
if (typeof id !== "number" && typeof id !== "string" && id !== null)
|
|
257
|
+
return undefined
|
|
203
258
|
const result = "result" in value ? value.result : undefined
|
|
204
259
|
const error = "error" in value ? value.error : undefined
|
|
205
260
|
if (error !== undefined) {
|
|
206
261
|
if (typeof error !== "object" || error === null) return undefined
|
|
207
262
|
const code = "code" in error ? error.code : undefined
|
|
208
263
|
const message = "message" in error ? error.message : undefined
|
|
209
|
-
if (typeof code !== "number" || typeof message !== "string")
|
|
264
|
+
if (typeof code !== "number" || typeof message !== "string")
|
|
265
|
+
return undefined
|
|
210
266
|
return { jsonrpc: "2.0", id, error: { code, message } }
|
|
211
267
|
}
|
|
212
268
|
return { jsonrpc: "2.0", id, result: result as JsonRpc.Response["result"] }
|
|
@@ -232,5 +288,6 @@ function open(url: string): Promise<WebSocket> {
|
|
|
232
288
|
})
|
|
233
289
|
}
|
|
234
290
|
|
|
235
|
-
export const connectSimulation = (
|
|
236
|
-
|
|
291
|
+
export const connectSimulation = (
|
|
292
|
+
options?: SimulationClientOptions,
|
|
293
|
+
): Promise<SimulationClient> => SimulationClient.connect(options)
|
package/src/client/protocol.ts
CHANGED
|
@@ -31,7 +31,10 @@ export namespace JsonRpc {
|
|
|
31
31
|
|
|
32
32
|
export const decodeRequest = Schema.decodeUnknownSync(Request)
|
|
33
33
|
|
|
34
|
-
export function success(
|
|
34
|
+
export function success(
|
|
35
|
+
id: Request["id"],
|
|
36
|
+
result: unknown,
|
|
37
|
+
): Response | undefined {
|
|
35
38
|
if (id === undefined) return undefined
|
|
36
39
|
return { jsonrpc: "2.0", id, result: result as Json }
|
|
37
40
|
}
|
|
@@ -56,15 +59,29 @@ export namespace Frontend {
|
|
|
56
59
|
super: Schema.optional(Schema.Boolean),
|
|
57
60
|
hyper: Schema.optional(Schema.Boolean),
|
|
58
61
|
})
|
|
59
|
-
export interface KeyModifiers extends Schema.Schema.Type<
|
|
62
|
+
export interface KeyModifiers extends Schema.Schema.Type<
|
|
63
|
+
typeof KeyModifiers
|
|
64
|
+
> {}
|
|
60
65
|
|
|
61
66
|
export const Action = Schema.Union([
|
|
62
67
|
Schema.Struct({ type: Schema.Literal("ui.type"), text: Schema.String }),
|
|
63
|
-
Schema.Struct({
|
|
68
|
+
Schema.Struct({
|
|
69
|
+
type: Schema.Literal("ui.press"),
|
|
70
|
+
key: Schema.String,
|
|
71
|
+
modifiers: Schema.optional(KeyModifiers),
|
|
72
|
+
}),
|
|
64
73
|
Schema.Struct({ type: Schema.Literal("ui.enter") }),
|
|
65
|
-
Schema.Struct({
|
|
74
|
+
Schema.Struct({
|
|
75
|
+
type: Schema.Literal("ui.arrow"),
|
|
76
|
+
direction: Schema.Literals(["up", "down", "left", "right"]),
|
|
77
|
+
}),
|
|
66
78
|
Schema.Struct({ type: Schema.Literal("ui.focus"), target: Schema.Number }),
|
|
67
|
-
Schema.Struct({
|
|
79
|
+
Schema.Struct({
|
|
80
|
+
type: Schema.Literal("ui.click"),
|
|
81
|
+
target: Schema.Number,
|
|
82
|
+
x: Schema.Number,
|
|
83
|
+
y: Schema.Number,
|
|
84
|
+
}),
|
|
68
85
|
])
|
|
69
86
|
export type Action = Schema.Schema.Type<typeof Action>
|
|
70
87
|
|
|
@@ -103,24 +120,53 @@ export namespace Frontend {
|
|
|
103
120
|
export const TypeParams = Schema.Struct({ text: Schema.String })
|
|
104
121
|
export interface TypeParams extends Schema.Schema.Type<typeof TypeParams> {}
|
|
105
122
|
|
|
106
|
-
export const PressParams = Schema.Struct({
|
|
123
|
+
export const PressParams = Schema.Struct({
|
|
124
|
+
key: Schema.String,
|
|
125
|
+
modifiers: Schema.optional(KeyModifiers),
|
|
126
|
+
})
|
|
107
127
|
export interface PressParams extends Schema.Schema.Type<typeof PressParams> {}
|
|
108
128
|
|
|
109
|
-
export const ArrowParams = Schema.Struct({
|
|
129
|
+
export const ArrowParams = Schema.Struct({
|
|
130
|
+
direction: Schema.Literals(["up", "down", "left", "right"]),
|
|
131
|
+
})
|
|
110
132
|
export interface ArrowParams extends Schema.Schema.Type<typeof ArrowParams> {}
|
|
111
133
|
|
|
112
134
|
export const FocusParams = Schema.Struct({ target: Schema.Number })
|
|
113
135
|
export interface FocusParams extends Schema.Schema.Type<typeof FocusParams> {}
|
|
114
136
|
|
|
115
|
-
export const ClickParams = Schema.Struct({
|
|
137
|
+
export const ClickParams = Schema.Struct({
|
|
138
|
+
target: Schema.Number,
|
|
139
|
+
x: Schema.Number,
|
|
140
|
+
y: Schema.Number,
|
|
141
|
+
})
|
|
116
142
|
export interface ClickParams extends Schema.Schema.Type<typeof ClickParams> {}
|
|
117
143
|
|
|
118
144
|
export const Request = Schema.Union([
|
|
119
|
-
Schema.Struct({
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
145
|
+
Schema.Struct({
|
|
146
|
+
...JsonRpc.RequestFields,
|
|
147
|
+
method: Schema.Literal("ui.type"),
|
|
148
|
+
params: TypeParams,
|
|
149
|
+
}),
|
|
150
|
+
Schema.Struct({
|
|
151
|
+
...JsonRpc.RequestFields,
|
|
152
|
+
method: Schema.Literal("ui.press"),
|
|
153
|
+
params: PressParams,
|
|
154
|
+
}),
|
|
155
|
+
Schema.Struct({
|
|
156
|
+
...JsonRpc.RequestFields,
|
|
157
|
+
method: Schema.Literal("ui.arrow"),
|
|
158
|
+
params: ArrowParams,
|
|
159
|
+
}),
|
|
160
|
+
Schema.Struct({
|
|
161
|
+
...JsonRpc.RequestFields,
|
|
162
|
+
method: Schema.Literal("ui.focus"),
|
|
163
|
+
params: FocusParams,
|
|
164
|
+
}),
|
|
165
|
+
Schema.Struct({
|
|
166
|
+
...JsonRpc.RequestFields,
|
|
167
|
+
method: Schema.Literal("ui.click"),
|
|
168
|
+
params: ClickParams,
|
|
169
|
+
}),
|
|
124
170
|
Schema.Struct({
|
|
125
171
|
...JsonRpc.RequestFields,
|
|
126
172
|
method: Schema.Literals([
|
|
@@ -134,47 +180,87 @@ export namespace Frontend {
|
|
|
134
180
|
])
|
|
135
181
|
export type Request = Schema.Schema.Type<typeof Request>
|
|
136
182
|
export const decodeRequest = Schema.decodeUnknownSync(Request)
|
|
137
|
-
|
|
138
183
|
}
|
|
139
184
|
|
|
140
185
|
export namespace Backend {
|
|
141
186
|
export const Item = Schema.Union([
|
|
142
187
|
Schema.Struct({ type: Schema.Literal("textDelta"), text: Schema.String }),
|
|
143
|
-
Schema.Struct({
|
|
144
|
-
|
|
188
|
+
Schema.Struct({
|
|
189
|
+
type: Schema.Literal("reasoningDelta"),
|
|
190
|
+
text: Schema.String,
|
|
191
|
+
}),
|
|
192
|
+
Schema.Struct({
|
|
193
|
+
type: Schema.Literal("toolCall"),
|
|
194
|
+
index: Schema.Number,
|
|
195
|
+
id: Schema.String,
|
|
196
|
+
name: Schema.String,
|
|
197
|
+
input: Schema.Json,
|
|
198
|
+
}),
|
|
145
199
|
Schema.Struct({ type: Schema.Literal("raw"), chunk: Schema.Json }),
|
|
146
200
|
])
|
|
147
201
|
export type Item = Schema.Schema.Type<typeof Item>
|
|
148
202
|
|
|
149
|
-
export const FinishReason = Schema.Literals([
|
|
203
|
+
export const FinishReason = Schema.Literals([
|
|
204
|
+
"stop",
|
|
205
|
+
"tool-calls",
|
|
206
|
+
"length",
|
|
207
|
+
"content-filter",
|
|
208
|
+
])
|
|
150
209
|
export type FinishReason = Schema.Schema.Type<typeof FinishReason>
|
|
151
210
|
|
|
152
|
-
export const ChunkParams = Schema.Struct({
|
|
211
|
+
export const ChunkParams = Schema.Struct({
|
|
212
|
+
id: Schema.String,
|
|
213
|
+
items: Schema.Array(Item),
|
|
214
|
+
})
|
|
153
215
|
export interface ChunkParams extends Schema.Schema.Type<typeof ChunkParams> {}
|
|
154
216
|
|
|
155
217
|
export const FinishParams = Schema.Struct({
|
|
156
218
|
id: Schema.String,
|
|
157
|
-
reason: FinishReason.pipe(
|
|
219
|
+
reason: FinishReason.pipe(
|
|
220
|
+
Schema.withDecodingDefault(Effect.succeed("stop" as const)),
|
|
221
|
+
),
|
|
158
222
|
})
|
|
159
|
-
export interface FinishParams extends Schema.Schema.Type<
|
|
223
|
+
export interface FinishParams extends Schema.Schema.Type<
|
|
224
|
+
typeof FinishParams
|
|
225
|
+
> {}
|
|
160
226
|
|
|
161
227
|
export const DisconnectParams = Schema.Struct({ id: Schema.String })
|
|
162
|
-
export interface DisconnectParams extends Schema.Schema.Type<
|
|
228
|
+
export interface DisconnectParams extends Schema.Schema.Type<
|
|
229
|
+
typeof DisconnectParams
|
|
230
|
+
> {}
|
|
163
231
|
|
|
164
232
|
export const Request = Schema.Union([
|
|
165
|
-
Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.chunk"), params: ChunkParams }),
|
|
166
|
-
Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.finish"), params: FinishParams }),
|
|
167
|
-
Schema.Struct({ ...JsonRpc.RequestFields, method: Schema.Literal("llm.disconnect"), params: DisconnectParams }),
|
|
168
233
|
Schema.Struct({
|
|
169
234
|
...JsonRpc.RequestFields,
|
|
170
|
-
method: Schema.
|
|
235
|
+
method: Schema.Literal("llm.chunk"),
|
|
236
|
+
params: ChunkParams,
|
|
237
|
+
}),
|
|
238
|
+
Schema.Struct({
|
|
239
|
+
...JsonRpc.RequestFields,
|
|
240
|
+
method: Schema.Literal("llm.finish"),
|
|
241
|
+
params: FinishParams,
|
|
242
|
+
}),
|
|
243
|
+
Schema.Struct({
|
|
244
|
+
...JsonRpc.RequestFields,
|
|
245
|
+
method: Schema.Literal("llm.disconnect"),
|
|
246
|
+
params: DisconnectParams,
|
|
247
|
+
}),
|
|
248
|
+
Schema.Struct({
|
|
249
|
+
...JsonRpc.RequestFields,
|
|
250
|
+
method: Schema.Literal("llm.attach"),
|
|
171
251
|
}),
|
|
172
252
|
])
|
|
173
253
|
export type Request = Schema.Schema.Type<typeof Request>
|
|
174
254
|
export const decodeRequest = Schema.decodeUnknownSync(Request)
|
|
175
255
|
|
|
176
|
-
export const OpenedExchange = Schema.Struct({
|
|
177
|
-
|
|
256
|
+
export const OpenedExchange = Schema.Struct({
|
|
257
|
+
id: Schema.String,
|
|
258
|
+
url: Schema.String,
|
|
259
|
+
body: Schema.Json,
|
|
260
|
+
})
|
|
261
|
+
export interface OpenedExchange extends Schema.Schema.Type<
|
|
262
|
+
typeof OpenedExchange
|
|
263
|
+
> {}
|
|
178
264
|
|
|
179
265
|
export const NetworkLogEntry = Schema.Struct({
|
|
180
266
|
time: Schema.Number,
|
|
@@ -182,8 +268,9 @@ export namespace Backend {
|
|
|
182
268
|
url: Schema.String,
|
|
183
269
|
matched: Schema.Boolean,
|
|
184
270
|
})
|
|
185
|
-
export interface NetworkLogEntry extends Schema.Schema.Type<
|
|
186
|
-
|
|
271
|
+
export interface NetworkLogEntry extends Schema.Schema.Type<
|
|
272
|
+
typeof NetworkLogEntry
|
|
273
|
+
> {}
|
|
187
274
|
}
|
|
188
275
|
|
|
189
276
|
export * as SimulationProtocol from "./index"
|