@@ -0,0 +1,143 @@
1+const omitEmpty = object =>
2+ Object.fromEntries(Object.entries(object).filter(([, value]) => value !== ""));
4+export const capabilitiesName = capabilities => capabilities.pluginName;
5+export const capabilitiesRoot = capabilities => capabilities.pluginRoot;
7+export const next = continuation => event => () => continuation(event);
9+export const registerCommand = capabilities => command => () =>
10+ capabilities.commandRegister({
12+ description: command.description,
13+ argumentHint: command.argumentHint || undefined,
16+export const registerTool = capabilities => tool => () =>
17+ capabilities.toolRegister({
19+ description: tool.description,
20+ inputSchema: tool.inputSchema,
22+ }).then(result => result.tool);
24+export const spawn = capabilities => request => onChunk => onResult => () => {
25+ const stream = capabilities.processSpawn({ argv: request.argv, cwd: request.cwd });
26+ const state = { stream, cancelled: false };
27+ state.done = (async () => {
29+ let next = await stream.next();
31+ if (!state.cancelled) onChunk({ stream: next.value.stream, text: next.value.text })();
32+ next = await stream.next();
34+ const value = next.value ?? { code: null, signal: null };
35+ if (!state.cancelled) onResult({ code: value.code, signal: value.signal })();
36+ return { code: value.code, signal: value.signal };
40+ signal: error instanceof Error ? error.message : String(error),
42+ if (!state.cancelled) onResult(value)();
49+export const awaitSpawn = spawn => () => spawn.done;
51+export const cancelSpawn = spawn => () => {
52+ if (spawn.cancelled) return;
53+ spawn.cancelled = true;
54+ void spawn.stream.return?.();
57+export const after = capabilities => milliseconds => callback => () =>
58+ capabilities.clockAfter(milliseconds, callback);
60+export const cancelTimer = timer => () => timer.cancel();
62+export const fetch = capabilities => request => () =>
63+ capabilities.httpFetch(request.url, {
64+ method: request.method,
65+ headers: { Authorization: request.authorization },
66+ body: request.body == null ? undefined : request.body,
67+ }).then(response => ({ ok: response.ok, status: response.status, text: response.text }));
69+export const blit = capabilities => request => () =>
70+ capabilities.uiBlit({
71+ requestId: request.requestId,
73+ source: request.source,
74+ columns: request.columns,
76+ }).then(result => result.deny ?? null);
78+export const invalidateRender = capabilities => () => capabilities.uiInvalidate();
80+export const configTheme = capabilities => () =>
81+ capabilities.configList().then(rows => {
82+ const theme = rows.find(row => row.key === "theme");
83+ return { theme: typeof theme?.value === "string" ? theme.value : null };
86+export const commandInput = event => {
87+ if (event == null || typeof event.command !== "string" || typeof event.args !== "string") return null;
88+ return { command: event.command, args: event.args };
91+export const toolCall = event => {
92+ if (event == null || typeof event.tool !== "string") return null;
93+ return { tool: event.tool, input: event };
96+export const sessionStart = event =>
97+ event != null && typeof event.cwd === "string" ? { cwd: event.cwd } : null;
99+export const configSet = event => {
100+ if (event == null || typeof event.key !== "string") return null;
101+ return { key: event.key, value: typeof event.value === "string" ? event.value : null };
104+export const renderContext = capabilities => event => () => {
107+ typeof event.requestId !== "string" ||
108+ typeof event.surface !== "string" ||
109+ typeof event.component !== "string"
111+ const props = event.props ?? {};
113+ elements: capabilities.uiResolve(event),
115+ requestId: event.requestId,
116+ surface: event.surface,
117+ component: event.component,
118+ bodyColumns: Number.isInteger(props.bodyColumns) ? props.bodyColumns : 0,
119+ maxRows: Number.isInteger(props.maxRows) ? props.maxRows : 0,
120+ hasSurvey: props.hasSurvey === true,
125+export const renderInput = context => context.input;
127+export const box = context => props => children =>
128+ context.elements.Box({ ...omitEmpty(props), children });
130+export const text = context => props => value =>
131+ context.elements.Text({ ...props, children: value });
133+export const button = context => props => onPress =>
134+ context.elements.Button({
135+ ...omitEmpty(props),
136+ plain: props.plain ? true : undefined,
137+ autoFocus: props.autoFocus ? true : undefined,
138+ onPress: () => onPress(),
141+export const image = context => props => context.elements.Image(props);
143+export const renderElement = element => element;