tapline-host 0.0.0-stage → 1.0.0

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.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -2
  3. package/dist/annotate.d.ts +20 -0
  4. package/dist/annotate.js +139 -0
  5. package/dist/annotate.js.map +1 -0
  6. package/dist/captions.d.ts +14 -0
  7. package/dist/captions.js +101 -0
  8. package/dist/captions.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +284 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/config.d.ts +75 -0
  13. package/dist/config.js +209 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/control.d.ts +44 -0
  16. package/dist/control.js +119 -0
  17. package/dist/control.js.map +1 -0
  18. package/dist/dev.d.ts +29 -0
  19. package/dist/dev.js +103 -0
  20. package/dist/dev.js.map +1 -0
  21. package/dist/doctor.d.ts +26 -0
  22. package/dist/doctor.js +336 -0
  23. package/dist/doctor.js.map +1 -0
  24. package/dist/format.d.ts +47 -0
  25. package/dist/format.js +350 -0
  26. package/dist/format.js.map +1 -0
  27. package/dist/images.d.ts +39 -0
  28. package/dist/images.js +279 -0
  29. package/dist/images.js.map +1 -0
  30. package/dist/index.d.ts +8 -0
  31. package/dist/index.js +8 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mcp.d.ts +10 -0
  34. package/dist/mcp.js +256 -0
  35. package/dist/mcp.js.map +1 -0
  36. package/dist/pairing.d.ts +24 -0
  37. package/dist/pairing.js +71 -0
  38. package/dist/pairing.js.map +1 -0
  39. package/dist/protocol.d.ts +312 -0
  40. package/dist/protocol.js +169 -0
  41. package/dist/protocol.js.map +1 -0
  42. package/dist/server.d.ts +196 -0
  43. package/dist/server.js +636 -0
  44. package/dist/server.js.map +1 -0
  45. package/dist/skill.d.ts +36 -0
  46. package/dist/skill.js +77 -0
  47. package/dist/skill.js.map +1 -0
  48. package/dist/tool-text-data.d.ts +71 -0
  49. package/dist/tool-text-data.js +74 -0
  50. package/dist/tool-text-data.js.map +1 -0
  51. package/dist/tool-text.d.ts +11 -0
  52. package/dist/tool-text.js +16 -0
  53. package/dist/tool-text.js.map +1 -0
  54. package/dist/tools.d.ts +346 -0
  55. package/dist/tools.js +1552 -0
  56. package/dist/tools.js.map +1 -0
  57. package/dist/viewer-page.d.ts +9 -0
  58. package/dist/viewer-page.js +10 -0
  59. package/dist/viewer-page.js.map +1 -0
  60. package/dist/viewer.d.ts +204 -0
  61. package/dist/viewer.js +513 -0
  62. package/dist/viewer.js.map +1 -0
  63. package/package.json +57 -4
  64. package/skills/tapline/SKILL.md +217 -0
  65. package/skills/tapline/agents/openai.yaml +4 -0
  66. package/skills/tapline/references/setup.md +143 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tapline contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,90 @@
1
- # Temporary Holding Version
1
+ # tapline-host
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The computer side of [Tapline](https://github.com/bo5amis/tapline#readme): the server your app's
4
+ `react-native-tapline` connects to over the same Wi-Fi, an MCP server for agents, and a CLI.
5
+ Node.js 20 or later. Full setup: [docs/setup.md](https://github.com/bo5amis/tapline/blob/main/docs/setup.md).
6
+
7
+ ## CLI
8
+
9
+ | Command | |
10
+ |---|---|
11
+ | `tapline mcp` | the host plus an MCP server on stdio (what agents run) |
12
+ | `tapline host` | the host alone, logging connections and app logs (`--scheme` also prints a pairing QR code) |
13
+ | `tapline pair --scheme <s>` | a pairing link and QR code in the terminal |
14
+ | `tapline info` | this computer's name and address, and the code the app needs |
15
+ | `tapline doctor` | check Node, this computer's Wi-Fi or LAN address, the token, ports and the Windows firewall (Tailscale and Metro over https are optional: warnings only) |
16
+ | `tapline dev [-- <metro command>]` | optional, for a phone away from this Wi-Fi: serve Metro over https in your tailnet and run Metro with `EXPO_PACKAGER_PROXY_URL` set |
17
+ | `tapline replay <name>` | replay a recorded script without an agent (exit code 1 when a step fails) |
18
+ | `tapline token` | print the token (only to connect without pairing, e.g. a simulator) |
19
+ | `tapline skill install` / `skill path` | install the agent skill for Claude Code, Codex and other agents / print where it is |
20
+
21
+ Options: `--port <n>` for a fixed port (or `TAPLINE_PORT`; otherwise 7210, moving up to
22
+ 7219 when taken, so each agent's host gets its own); `--host <addr>[,<addr>…]` to listen
23
+ on other addresses; `--screenshots file` (or `TAPLINE_SCREENSHOTS=file`) makes `look` save
24
+ screenshots in `~/.tapline/shots` (newest 50 kept) and return the path instead of the image,
25
+ for agents that hand images to smaller models; `--viewer <local|remote|off>` (or
26
+ `TAPLINE_VIEWER`) sets where the live viewer opens: this computer only (default), also your
27
+ own devices on Tailscale, or nowhere. `TAPLINE_HOME` moves the data directory (default
28
+ `~/.tapline`).
29
+
30
+ Claude Code: `claude mcp add tapline -- tapline mcp`. Other MCP clients: run `tapline mcp`
31
+ as a stdio server; it logs to stderr only.
32
+
33
+ ## MCP tools
34
+
35
+ `pair`, `apps`, `open_app`, `look`, `check_layout`, `tap`, `long_press`, `type_text`,
36
+ `scroll`, `swipe`, `toggle`, `open_url`, `back`, `app_command`, `wait_for`, `record`, `replay`,
37
+ `compare_screen`, `filmstrip`, `viewer`, `logs`, `reload`, `wait`. Targets: `{ref}`, `{id}`
38
+ (the `testID` prop), `{label}`, `{text}` or `{x, y}`; `index` goes with `id`, `label` and
39
+ `text`. Every action answers with the verb and the element, then `Same screen. Changes:`
40
+ (or the full list when the screen changed), then `Settled in N s.`, then any `Note:` lines;
41
+ `look: false` returns only the first line. No image is sent by default: `screenshot: true`
42
+ on any action or on `look` adds one (`width` in pixels, default 600). Errors read
43
+ `Error <code>: <message>`; a `not_actionable` message starts with its reason (`disabled`,
44
+ `off_screen`, `covered`, `under_tab_bar`, `behind_alert`, `no_action`). After a person acts
45
+ in the live viewer, `{ref}` targets fail with `stale` until the next `look`. `scroll.amount`
46
+ is a share of the scroll area (0.1 to 1, default 0.8); `long_press` takes `seconds`, which
47
+ Tapline ignores.
48
+
49
+ - `pair {scheme}` returns a pairing link for this host (with the port it actually got),
50
+ its QR code as an image, and the forget link; the QR code is also saved as
51
+ `~/.tapline/pair-<port>.png`. A code works once, for 10 minutes.
52
+ - With several apps connected, the latest one is used until `open_app {app}` picks another (`app` is a session id, app
53
+ id or name; several matches give `ambiguous`).
54
+ Phones that send no name (iPhones) show their install id.
55
+ - If an app can't take screenshots, the host remembers it for that session and stops asking.
56
+ - `reload` waits for the app to reconnect, then returns the element list.
57
+ - `logs` returns what the host has buffered since the app connected (500 lines); with
58
+ nothing buffered it asks the app for its own.
59
+ - `viewer` returns the live viewer's link, plus the app's capture and stutter numbers while
60
+ someone watches. The viewer rides on the host's port (`/viewer`, `/stream`, `/ws`) and
61
+ speaks [docs/VIEWER-PROTOCOL.md](https://github.com/bo5amis/tapline/blob/main/docs/VIEWER-PROTOCOL.md). The app captures frames
62
+ only while someone watches. A person's input goes ahead of the agent's actions, which
63
+ wait until the person has been idle for 3 s (`busy` after 30 s; `paused` while paused).
64
+
65
+ ## Security
66
+
67
+ - The token (32 random hex characters) is created on the first run in `~/.tapline/token`
68
+ (`%USERPROFILE%\.tapline\token` on Windows). Treat it like a password. Pairing hands it
69
+ to the app, which keeps it in the keychain; the MCP server never shows it to the agent.
70
+ Delete the file to make a new one: every phone then has to pair again.
71
+ - Pairing codes are signed with the token, expire after 10 minutes, and each host accepts
72
+ a code once.
73
+ - The host listens on this computer's Wi-Fi or LAN address (private addresses on real
74
+ adapters only), on its Tailscale address when there is one, and on 127.0.0.1. Phones pair
75
+ with the Wi-Fi or LAN address. `--host <addr>` chooses other addresses.
76
+ - Connections without the right token are closed (4001), and bad pairing codes too
77
+ (4004). Traffic is plain WebSocket: use a Wi-Fi you trust (Tailscale, when used, encrypts it).
78
+ - The live viewer has its own random key, new on each start, in the link the `viewer` tool
79
+ gives. Only that first page load takes the key in the address: it sets an HttpOnly,
80
+ SameSite=Strict cookie and the page removes the key from the address bar. The stream and
81
+ the WebSocket take the cookie or an `Authorization: Bearer` header, never the key in the
82
+ URL. A cookie sent from another site (even another port on this computer:
83
+ `Sec-Fetch-Site`) is refused, so are requests from another Host or (for the WebSocket)
84
+ another Origin, and by default only this computer can open it.
85
+
86
+ ## Develop
87
+
88
+ ```sh
89
+ npm run typecheck && npm run build && npm test
90
+ ```
@@ -0,0 +1,20 @@
1
+ import type { TreeElement } from "./protocol.js";
2
+ /**
3
+ * Labeled screenshots: draws each actionable element's box and its ref (for example "e12")
4
+ * onto a JPEG screenshot, so a vision model can name elements by ref.
5
+ */
6
+ export interface ShotImage {
7
+ mime: string;
8
+ data: string;
9
+ width?: number;
10
+ height?: number;
11
+ }
12
+ export interface ScreenSize {
13
+ width: number;
14
+ height: number;
15
+ }
16
+ type Rgb = readonly [number, number, number];
17
+ /** Saturated, high-contrast colours (white text stays readable on all of them). */
18
+ export declare const ANNOTATION_PALETTE: readonly Rgb[];
19
+ export declare function annotateScreenshot(shot: ShotImage, elements: TreeElement[], screen: ScreenSize): ShotImage;
20
+ export {};
@@ -0,0 +1,139 @@
1
+ import jpeg from "jpeg-js";
2
+ /** Saturated, high-contrast colours (white text stays readable on all of them). */
3
+ export const ANNOTATION_PALETTE = [
4
+ [220, 20, 60], // crimson
5
+ [0, 90, 255], // blue
6
+ [0, 140, 60], // green
7
+ [150, 40, 200], // purple
8
+ [230, 100, 0], // orange
9
+ [0, 130, 140], // teal
10
+ ];
11
+ const JPEG_QUALITY = 80;
12
+ const OUTLINE = 2;
13
+ const WIDE_IMAGE = 500;
14
+ const MID_IMAGE = 280;
15
+ const GLYPH_W = 5;
16
+ const GLYPH_H = 7;
17
+ // 5x7 glyphs, one string per row, '#' = ink.
18
+ const GLYPHS = {
19
+ e: [".....", ".....", ".###.", "#...#", "#####", "#....", ".###."],
20
+ "0": [".###.", "#...#", "#..##", "#.#.#", "##..#", "#...#", ".###."],
21
+ "1": ["..#..", ".##..", "..#..", "..#..", "..#..", "..#..", ".###."],
22
+ "2": [".###.", "#...#", "....#", "...#.", "..#..", ".#...", "#####"],
23
+ "3": ["#####", "...#.", "..#..", "...#.", "....#", "#...#", ".###."],
24
+ "4": ["...#.", "..##.", ".#.#.", "#..#.", "#####", "...#.", "...#."],
25
+ "5": ["#####", "#....", "####.", "....#", "....#", "#...#", ".###."],
26
+ "6": ["..##.", ".#...", "#....", "####.", "#...#", "#...#", ".###."],
27
+ "7": ["#####", "....#", "...#.", "..#..", ".#...", ".#...", ".#..."],
28
+ "8": [".###.", "#...#", "#...#", ".###.", "#...#", "#...#", ".###."],
29
+ "9": [".###.", "#...#", "#...#", ".####", "....#", "...#.", ".##.."],
30
+ };
31
+ function setPixel(canvas, x, y, colour) {
32
+ if (x < 0 || y < 0 || x >= canvas.width || y >= canvas.height)
33
+ return;
34
+ const i = (y * canvas.width + x) * 4;
35
+ canvas.data[i] = colour[0];
36
+ canvas.data[i + 1] = colour[1];
37
+ canvas.data[i + 2] = colour[2];
38
+ canvas.data[i + 3] = 255;
39
+ }
40
+ function fillRect(canvas, x, y, w, h, colour) {
41
+ const x0 = Math.max(0, x);
42
+ const y0 = Math.max(0, y);
43
+ const x1 = Math.min(canvas.width, x + w);
44
+ const y1 = Math.min(canvas.height, y + h);
45
+ for (let yy = y0; yy < y1; yy++) {
46
+ for (let xx = x0; xx < x1; xx++)
47
+ setPixel(canvas, xx, yy, colour);
48
+ }
49
+ }
50
+ /** Outline drawn inside the rectangle's edges. */
51
+ function strokeRect(canvas, x, y, w, h, thickness, colour) {
52
+ const t = Math.min(thickness, Math.floor(w / 2), Math.floor(h / 2));
53
+ if (t <= 0) {
54
+ fillRect(canvas, x, y, w, h, colour);
55
+ return;
56
+ }
57
+ fillRect(canvas, x, y, w, t, colour); // top
58
+ fillRect(canvas, x, y + h - t, w, t, colour); // bottom
59
+ fillRect(canvas, x, y + t, t, h - 2 * t, colour); // left
60
+ fillRect(canvas, x + w - t, y + t, t, h - 2 * t, colour); // right
61
+ }
62
+ const WHITE = [255, 255, 255];
63
+ function drawLabel(canvas, text, frameX, frameY, colour) {
64
+ const glyphs = [...text].map((ch) => GLYPHS[ch]);
65
+ if (glyphs.some((g) => g === undefined))
66
+ return;
67
+ // Big enough to read on a phone screenshot (a vision model found 2x on 600 px too small).
68
+ const scale = canvas.width >= WIDE_IMAGE ? 3 : canvas.width >= MID_IMAGE ? 2 : 1;
69
+ const pad = scale;
70
+ const spacing = scale; // 1 px of the 1x grid between glyphs
71
+ const textW = glyphs.length * GLYPH_W * scale + Math.max(0, glyphs.length - 1) * spacing;
72
+ const boxW = textW + 2 * pad;
73
+ const boxH = GLYPH_H * scale + 2 * pad;
74
+ // Keep the whole label inside the image: shift left/down when the frame touches an edge.
75
+ const boxX = Math.max(0, Math.min(frameX, canvas.width - boxW));
76
+ const boxY = Math.max(0, Math.min(frameY, canvas.height - boxH));
77
+ fillRect(canvas, boxX, boxY, boxW, boxH, colour);
78
+ let cursor = boxX + pad;
79
+ for (const glyph of glyphs) {
80
+ if (glyph === undefined)
81
+ continue;
82
+ for (let row = 0; row < GLYPH_H; row++) {
83
+ const line = glyph[row] ?? "";
84
+ for (let col = 0; col < GLYPH_W; col++) {
85
+ if (line[col] === "#")
86
+ fillRect(canvas, cursor + col * scale, boxY + pad + row * scale, scale, scale, WHITE);
87
+ }
88
+ }
89
+ cursor += GLYPH_W * scale + spacing;
90
+ }
91
+ }
92
+ function isLabelled(element) {
93
+ if (!element.frame)
94
+ return false;
95
+ return (element.actions ?? []).some((action) => action !== "scroll");
96
+ }
97
+ export function annotateScreenshot(shot, elements, screen) {
98
+ if (shot.mime !== "image/jpeg")
99
+ return shot;
100
+ if (!(screen.width > 0) || !(screen.height > 0))
101
+ return shot;
102
+ let decoded;
103
+ try {
104
+ decoded = jpeg.decode(Buffer.from(shot.data, "base64"), { useTArray: true });
105
+ }
106
+ catch {
107
+ return shot;
108
+ }
109
+ if (decoded.width <= 0 || decoded.height <= 0)
110
+ return shot;
111
+ const canvas = { width: decoded.width, height: decoded.height, data: decoded.data };
112
+ const scale = canvas.width / screen.width;
113
+ let index = 0;
114
+ for (const element of elements) {
115
+ const frame = element.frame;
116
+ if (!frame || !isLabelled(element))
117
+ continue;
118
+ const x = Math.round(frame.x * scale);
119
+ const y = Math.round(frame.y * scale);
120
+ const w = Math.max(1, Math.round(frame.width * scale));
121
+ const h = Math.max(1, Math.round(frame.height * scale));
122
+ if (x >= canvas.width || y >= canvas.height || x + w <= 0 || y + h <= 0)
123
+ continue;
124
+ const colour = ANNOTATION_PALETTE[index % ANNOTATION_PALETTE.length];
125
+ index++;
126
+ if (!colour)
127
+ continue;
128
+ strokeRect(canvas, x, y, w, h, OUTLINE, colour);
129
+ drawLabel(canvas, element.ref, x, y, colour);
130
+ }
131
+ const encoded = jpeg.encode({ data: canvas.data, width: canvas.width, height: canvas.height }, JPEG_QUALITY);
132
+ return {
133
+ mime: "image/jpeg",
134
+ data: encoded.data.toString("base64"),
135
+ width: canvas.width,
136
+ height: canvas.height,
137
+ };
138
+ }
139
+ //# sourceMappingURL=annotate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotate.js","sourceRoot":"","sources":["../src/annotate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * VIEWER-PROTOCOL 1.4: the `kind` of an action the viewer is shown, and the plain-language `caption`
3
+ * for the agent's steps. A caption never carries refs, coordinates, typed text or a link's address,
4
+ * and never the failure reason (the page adds that). A person's steps get no caption from here:
5
+ * the page words them itself ("You tapped …").
6
+ */
7
+ import type { PersonInput } from "./viewer.js";
8
+ export declare function agentKind(method: string): string;
9
+ /** A person's input → the viewer's input name (tap, longPress, drag, scroll, text, enter, backspace). */
10
+ export declare function personKind(input: PersonInput, method: string): string;
11
+ /** The reason word of a refusal, for the viewer (1.4 `reason`); undefined for any other error. */
12
+ export declare function reasonOf(code: string | undefined, message: string | undefined): string | undefined;
13
+ /** The agent's step in plain words, or undefined for steps a viewer needn't see (wait_for). */
14
+ export declare function captionFor(kind: string, label?: string, params?: unknown): string | undefined;
@@ -0,0 +1,101 @@
1
+ /** The app's method → the AGENT-TOOLS tool the agent called. */
2
+ const AGENT_KINDS = {
3
+ press: "tap",
4
+ longPress: "long_press",
5
+ type: "type_text",
6
+ scroll: "scroll",
7
+ swipe: "swipe",
8
+ toggle: "toggle",
9
+ back: "back",
10
+ openURL: "open_url",
11
+ waitFor: "wait_for",
12
+ command: "app_command",
13
+ reload: "reload",
14
+ };
15
+ export function agentKind(method) {
16
+ return AGENT_KINDS[method] ?? method;
17
+ }
18
+ /** A person's input → the viewer's input name (tap, longPress, drag, scroll, text, enter, backspace). */
19
+ export function personKind(input, method) {
20
+ switch (input.type) {
21
+ case "text":
22
+ return "text";
23
+ case "key":
24
+ return input.key;
25
+ case "scroll":
26
+ return "scroll";
27
+ case "gesture":
28
+ if (method === "press")
29
+ return "tap";
30
+ if (method === "longPress")
31
+ return "longPress";
32
+ if (method === "swipe")
33
+ return "drag";
34
+ return "scroll";
35
+ }
36
+ }
37
+ /** AGENT-TOOLS §4's reason words: the first word of a not_actionable message. */
38
+ const REASONS = new Set(["disabled", "off_screen", "covered", "under_tab_bar", "behind_alert", "no_action"]);
39
+ /** The reason word of a refusal, for the viewer (1.4 `reason`); undefined for any other error. */
40
+ export function reasonOf(code, message) {
41
+ if (code !== "not_actionable" || message === undefined)
42
+ return undefined;
43
+ const word = /^([a-z_]+):/.exec(message.trim())?.[1];
44
+ return word !== undefined && REASONS.has(word) ? word : undefined;
45
+ }
46
+ const NAME_MAX = 32;
47
+ /** An element's name for a caption: 32 characters at most, then an ellipsis. */
48
+ function shortName(label) {
49
+ const clean = label.replace(/\s+/g, " ").trim();
50
+ return clean.length <= NAME_MAX ? clean : `${clean.slice(0, NAME_MAX).trimEnd()}…`;
51
+ }
52
+ function field(params, key) {
53
+ return typeof params === "object" && params !== null ? params[key] : undefined;
54
+ }
55
+ const DIRECTIONS = new Set(["up", "down", "left", "right"]);
56
+ /** The agent's step in plain words, or undefined for steps a viewer needn't see (wait_for). */
57
+ export function captionFor(kind, label, params) {
58
+ const name = label !== undefined && label.trim() !== "" ? shortName(label) : undefined;
59
+ const quoted = name !== undefined ? ` "${name}"` : "";
60
+ switch (kind) {
61
+ case "tap":
62
+ return `Tap${quoted}`;
63
+ case "long_press":
64
+ return `Press and hold${quoted}`;
65
+ case "type_text":
66
+ return name !== undefined ? `Type into${quoted}` : "Type";
67
+ case "scroll": {
68
+ const direction = field(params, "direction");
69
+ return typeof direction === "string" && DIRECTIONS.has(direction) ? `Scroll ${direction}` : "Scroll";
70
+ }
71
+ case "swipe":
72
+ return "Swipe";
73
+ case "toggle": {
74
+ const value = field(params, "value");
75
+ if (value === true)
76
+ return `Turn on${quoted}`;
77
+ if (value === false)
78
+ return `Turn off${quoted}`;
79
+ return `Switch${quoted}`;
80
+ }
81
+ case "back":
82
+ return "Go back";
83
+ case "open_url":
84
+ return "Open link";
85
+ case "reload":
86
+ return "Reload the app";
87
+ case "app_command": {
88
+ const command = field(params, "name");
89
+ const scheme = field(field(params, "args"), "scheme");
90
+ if (command === "appearance" && (scheme === "dark" || scheme === "light"))
91
+ return `Switch to ${scheme} mode`;
92
+ const named = typeof command === "string" && command !== "" ? shortName(command) : name;
93
+ return named !== undefined ? `Run "${named}"` : "Run a test command";
94
+ }
95
+ case "wait_for":
96
+ return undefined;
97
+ default:
98
+ return kind.replace(/_/g, " ");
99
+ }
100
+ }
101
+ //# sourceMappingURL=captions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captions.js","sourceRoot":"","sources":["../src/captions.ts"],"names":[],"mappings":"AAQA,gEAAgE;AAChE,MAAM,WAAW,GAA2B;IAC1C,KAAK,EAAE,KAAK;IACZ,SAAS,EAAE,YAAY;IACvB,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,UAAU;IACnB,OAAO,EAAE,UAAU;IACnB,OAAO,EAAE,aAAa;IACtB,MAAM,EAAE,QAAQ;CACjB,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;AACvC,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,UAAU,CAAC,KAAkB,EAAE,MAAc;IAC3D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC,GAAG,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,KAAK,SAAS;YACZ,IAAI,MAAM,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC;YACrC,IAAI,MAAM,KAAK,WAAW;gBAAE,OAAO,WAAW,CAAC;YAC/C,IAAI,MAAM,KAAK,OAAO;gBAAE,OAAO,MAAM,CAAC;YACtC,OAAO,QAAQ,CAAC;IACpB,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;AAE7G,kGAAkG;AAClG,MAAM,UAAU,QAAQ,CAAC,IAAwB,EAAE,OAA2B;IAC5E,IAAI,IAAI,KAAK,gBAAgB,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrD,OAAO,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,MAAM,QAAQ,GAAG,EAAE,CAAC;AAEpB,gFAAgF;AAChF,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,OAAO,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC;AACrF,CAAC;AAED,SAAS,KAAK,CAAC,MAAe,EAAE,GAAW;IACzC,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAE,MAAkC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9G,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5D,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAc,EAAE,MAAgB;IACvE,MAAM,IAAI,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvF,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,MAAM,MAAM,EAAE,CAAC;QACxB,KAAK,YAAY;YACf,OAAO,iBAAiB,MAAM,EAAE,CAAC;QACnC,KAAK,WAAW;YACd,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAC7C,OAAO,OAAO,SAAS,KAAK,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;QACvG,CAAC;QACD,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACrC,IAAI,KAAK,KAAK,IAAI;gBAAE,OAAO,UAAU,MAAM,EAAE,CAAC;YAC9C,IAAI,KAAK,KAAK,KAAK;gBAAE,OAAO,WAAW,MAAM,EAAE,CAAC;YAChD,OAAO,SAAS,MAAM,EAAE,CAAC;QAC3B,CAAC;QACD,KAAK,MAAM;YACT,OAAO,SAAS,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,WAAW,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,gBAAgB,CAAC;QAC1B,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACtC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;YACtD,IAAI,OAAO,KAAK,YAAY,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,OAAO,CAAC;gBAAE,OAAO,aAAa,MAAM,OAAO,CAAC;YAC7G,MAAM,KAAK,GAAG,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACxF,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,oBAAoB,CAAC;QACvE,CAAC;QACD,KAAK,UAAU;YACb,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;AACH,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};