feat(spec): add llm() action-backend marker

This commit is contained in:
pj committed 2026-06-12 10:25:51 +05:30
1 parent 6b0d6cb971
commit e30ed6f7ed
3 files changed
+14 -1

No files matched your search

+4 -1
View File
@@ -57,10 +57,13 @@ export type ActionDescriptor =
// weighted: probabilistic choice over child nodes, scanned ascending. // weighted: probabilistic choice over child nodes, scanned ascending.
// actions: author callback returning a list to pick uniformly from. // actions: author callback returning a list to pick uniformly from.
// builtin: host-backed leaf identified by a verb. // builtin: host-backed leaf identified by a verb.
// llm: marker selecting the LLM action backend; inert on the JS picker
// (walk returns null), Go reads config.model off globalThis.actions.
export type GeneratorNode = export type GeneratorNode =
| { kind: "weighted"; branches: ReadonlyArray<readonly [number, GeneratorNode]> } | { kind: "weighted"; branches: ReadonlyArray<readonly [number, GeneratorNode]> }
| { kind: "actions"; generate: () => ActionDescriptor[] } | { kind: "actions"; generate: () => ActionDescriptor[] }
| { kind: "builtin"; verb: BuiltinVerb }; | { kind: "builtin"; verb: BuiltinVerb }
| { kind: "llm"; config: { model: string } };
// Candidate is one host-enumerated target for a builtin verb. The host // Candidate is one host-enumerated target for a builtin verb. The host
// resolves geometry (and a native selector) so no element handle crosses into // resolves geometry (and a native selector) so no element handle crosses into
+9
View File
@@ -34,6 +34,15 @@ export function actions(generator: () => Action[]): GeneratorNode {
return { kind: "actions", generate: generator as () => ActionDescriptor[] }; return { kind: "actions", generate: generator as () => ActionDescriptor[] };
} }
// llm selects the LLM action backend: instead of the seeded picker drawing a
// random candidate, Go drives an OpenRouter model that chooses which candidate
// to act on from the screenshot + the candidate list. The returned marker is
// inert on the JS picker (pick.ts walks it to null); Go reads its config.model
// off globalThis.actions. API key comes from OPENROUTER_API_KEY.
export function llm(config: { model: string }): GeneratorNode {
return { kind: "llm", config };
}
export function whenRoute( export function whenRoute(
routeExtractor: { readonly current: string | null }, routeExtractor: { readonly current: string | null },
routes: string | readonly string[], routes: string | readonly string[],
+1
View File
@@ -42,6 +42,7 @@ export {
actions, actions,
doubleTaps, doubleTaps,
from, from,
llm,
longPresses, longPresses,
pressKeys, pressKeys,
scrolls, scrolls,