@appclaw/agent 2.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.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # appclaw-agent
2
+
3
+ Agent-native command line interface for AppClaw. It exposes deterministic
4
+ terminal commands so Claude Code, Gemini CLI, Codex CLI, and other agents can
5
+ inspect and operate an Appium-backed mobile session.
6
+
7
+ ```bash
8
+ npm install -g appclaw-agent
9
+ appclaw-agent help workflow
10
+
11
+ appclaw-agent --session demo open com.example.app --platform android
12
+ appclaw-agent --session demo snapshot -i --json
13
+ appclaw-agent --session demo press @e1 --json
14
+ appclaw-agent --session demo close
15
+ ```
16
+
17
+ The first device command starts a user-local daemon. The daemon owns named
18
+ device sessions so separate agent terminal invocations can continue operating
19
+ on the same screen.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { run } from '../dist/cli.js';
3
+
4
+ process.exitCode = await run(process.argv.slice(2));
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function run(argv: string[]): Promise<number>;
package/dist/cli.js ADDED
@@ -0,0 +1,55 @@
1
+ import { sendCommand } from './client.js';
2
+ import { helpText, VERSION, workflowText } from './help.js';
3
+ import { parseInvocation } from './parser.js';
4
+ const c = {
5
+ reset: '\x1b[0m',
6
+ bold: '\x1b[1m',
7
+ dim: '\x1b[2m',
8
+ green: '\x1b[32m',
9
+ red: '\x1b[31m',
10
+ cyan: '\x1b[36m',
11
+ yellow: '\x1b[33m',
12
+ magenta: '\x1b[35m',
13
+ };
14
+ function colorOutput(session, ok, message, output) {
15
+ const icon = ok ? `${c.green}✔${c.reset}` : `${c.red}✘${c.reset}`;
16
+ const tag = session ? ` ${c.cyan}[${session}]${c.reset}` : '';
17
+ if (output)
18
+ process.stdout.write(`${c.dim}${output}${c.reset}\n`);
19
+ process.stdout.write(`${icon}${tag} ${message}\n`);
20
+ }
21
+ export async function run(argv) {
22
+ try {
23
+ const parsed = parseInvocation(argv);
24
+ if (parsed.local === 'version') {
25
+ console.log(VERSION);
26
+ return 0;
27
+ }
28
+ if (parsed.local === 'help') {
29
+ console.log(argv.includes('workflow') ? workflowText() : helpText());
30
+ return 0;
31
+ }
32
+ const response = await sendCommand(parsed.session, parsed.command);
33
+ if (parsed.json) {
34
+ process.stdout.write(`${JSON.stringify(response)}\n`);
35
+ }
36
+ else {
37
+ colorOutput(response.session, response.ok, response.message, response.output);
38
+ }
39
+ return response.ok ? 0 : 1;
40
+ }
41
+ catch (error) {
42
+ const message = error instanceof Error ? error.message : String(error);
43
+ if (argv.includes('--json')) {
44
+ process.stdout.write(`${JSON.stringify({ ok: false, message })}\n`);
45
+ }
46
+ else {
47
+ process.stderr.write(`${c.red}✘${c.reset} ${c.bold}Error:${c.reset} ${message}\n`);
48
+ }
49
+ return 1;
50
+ }
51
+ }
52
+ if (process.argv[1]?.endsWith('cli.js')) {
53
+ process.exitCode = await run(process.argv.slice(2));
54
+ }
55
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { Command, CommandResponse } from './types.js';
2
+ export declare function sendCommand(session: string, command: Command): Promise<CommandResponse>;
package/dist/client.js ADDED
@@ -0,0 +1,95 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
3
+ import { connect } from 'node:net';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { LOCK_PATH, METADATA_PATH, SOCKET_PATH, STATE_DIR } from './paths.js';
6
+ export async function sendCommand(session, command) {
7
+ const metadata = await ensureDaemon();
8
+ return request(metadata, { token: metadata.token, session, command });
9
+ }
10
+ async function ensureDaemon(retryStaleLock = true) {
11
+ const current = await readDaemonMetadata();
12
+ if (current && (await canConnect(current)))
13
+ return current;
14
+ await mkdir(STATE_DIR, { recursive: true, mode: 0o700 });
15
+ const ownsStartup = await acquireStartupLock();
16
+ if (ownsStartup) {
17
+ await Promise.allSettled([
18
+ rm(METADATA_PATH, { force: true }),
19
+ rm(SOCKET_PATH, { force: true }),
20
+ ]);
21
+ const entry = fileURLToPath(new URL('./daemon-entry.js', import.meta.url));
22
+ const child = spawn(process.execPath, [entry], {
23
+ detached: true,
24
+ stdio: 'ignore',
25
+ env: process.env,
26
+ });
27
+ child.unref();
28
+ }
29
+ const deadline = Date.now() + 5000;
30
+ while (Date.now() < deadline) {
31
+ const started = await readDaemonMetadata();
32
+ if (started && (await canConnect(started))) {
33
+ if (ownsStartup)
34
+ await rm(LOCK_PATH, { force: true });
35
+ return started;
36
+ }
37
+ await new Promise((resolve) => setTimeout(resolve, 50));
38
+ }
39
+ await rm(LOCK_PATH, { force: true });
40
+ if (!ownsStartup && retryStaleLock) {
41
+ return ensureDaemon(false);
42
+ }
43
+ throw new Error('Timed out starting the appclaw-agent daemon');
44
+ }
45
+ async function acquireStartupLock() {
46
+ try {
47
+ await writeFile(LOCK_PATH, `${process.pid}\n`, { flag: 'wx', mode: 0o600 });
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ async function readDaemonMetadata() {
55
+ try {
56
+ return JSON.parse(await readFile(METADATA_PATH, 'utf8'));
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
62
+ async function canConnect(metadata) {
63
+ try {
64
+ const response = await request(metadata, {
65
+ token: metadata.token,
66
+ session: 'default',
67
+ command: { kind: 'list' },
68
+ });
69
+ return response.ok;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ }
75
+ function request(metadata, message) {
76
+ return new Promise((resolve, reject) => {
77
+ const socket = connect(metadata.socketPath);
78
+ let body = '';
79
+ socket.setEncoding('utf8');
80
+ socket.once('error', reject);
81
+ socket.on('data', (chunk) => {
82
+ body += chunk;
83
+ });
84
+ socket.once('connect', () => socket.write(`${JSON.stringify(message)}\n`));
85
+ socket.once('end', () => {
86
+ try {
87
+ resolve(JSON.parse(body.trim()));
88
+ }
89
+ catch (error) {
90
+ reject(error);
91
+ }
92
+ });
93
+ });
94
+ }
95
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAuB,MAAM,YAAY,CAAC;AAGnG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,OAAgB;IACjE,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,OAAO,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,cAAc,GAAG,IAAI;IAC/C,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC3C,IAAI,OAAO,IAAI,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAE3D,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC/C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,OAAO,CAAC,UAAU,CAAC;YACvB,EAAE,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAClC,EAAE,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;SACjC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE;YAC7C,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,OAAO,CAAC,GAAG;SACjB,CAAC,CAAC;QACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACnC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAC3C,IAAI,OAAO,IAAI,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAC3C,IAAI,WAAW;gBAAE,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,WAAW,IAAI,cAAc,EAAE,CAAC;QACnC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACjE,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5E,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAmB,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAwB;IAChD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE;YACvC,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;SAC1B,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,QAAwB,EAAE,OAAsB;IAC/D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,IAAI,KAAK,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAoB,CAAC,CAAC;YACtD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { AgentDaemon } from './daemon.js';
2
+ const daemon = new AgentDaemon();
3
+ await daemon.start();
4
+ //# sourceMappingURL=daemon-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-entry.js","sourceRoot":"","sources":["../src/daemon-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;AACjC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare class AgentDaemon {
2
+ private readonly token;
3
+ private readonly state;
4
+ private server;
5
+ private idleTimer;
6
+ start(): Promise<void>;
7
+ stop(): Promise<void>;
8
+ private accept;
9
+ private respond;
10
+ private refreshIdleTimer;
11
+ }
package/dist/daemon.js ADDED
@@ -0,0 +1,85 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { chmod, mkdir, rm, writeFile } from 'node:fs/promises';
3
+ import { createServer } from 'node:net';
4
+ import { AgentDaemonState } from './server.js';
5
+ import { LOCK_PATH, METADATA_PATH, SOCKET_PATH, STATE_DIR } from './paths.js';
6
+ const IDLE_TIMEOUT_MS = Number(process.env.APPCLAW_AGENT_IDLE_TIMEOUT_MS ?? 30000);
7
+ export class AgentDaemon {
8
+ token = randomBytes(32).toString('hex');
9
+ state = new AgentDaemonState();
10
+ server = null;
11
+ idleTimer = null;
12
+ async start() {
13
+ await mkdir(STATE_DIR, { recursive: true, mode: 0o700 });
14
+ await rm(SOCKET_PATH, { force: true });
15
+ const server = createServer((socket) => this.accept(socket));
16
+ this.server = server;
17
+ await new Promise((resolve, reject) => {
18
+ server.once('error', reject);
19
+ server.listen(SOCKET_PATH, resolve);
20
+ });
21
+ await chmod(SOCKET_PATH, 0o600);
22
+ const metadata = {
23
+ pid: process.pid,
24
+ socketPath: SOCKET_PATH,
25
+ token: this.token,
26
+ };
27
+ await writeFile(METADATA_PATH, JSON.stringify(metadata), { mode: 0o600 });
28
+ process.once('SIGTERM', () => void this.stop());
29
+ process.once('SIGINT', () => void this.stop());
30
+ this.refreshIdleTimer();
31
+ }
32
+ async stop() {
33
+ if (this.idleTimer)
34
+ clearTimeout(this.idleTimer);
35
+ await this.state.closeAll();
36
+ if (this.server) {
37
+ await new Promise((resolve) => this.server.close(() => resolve()));
38
+ }
39
+ await Promise.allSettled([
40
+ rm(SOCKET_PATH, { force: true }),
41
+ rm(METADATA_PATH, { force: true }),
42
+ rm(LOCK_PATH, { force: true }),
43
+ ]);
44
+ process.exitCode = 0;
45
+ }
46
+ accept(socket) {
47
+ let input = '';
48
+ socket.setEncoding('utf8');
49
+ socket.on('data', (chunk) => {
50
+ input += chunk;
51
+ const newline = input.indexOf('\n');
52
+ if (newline < 0)
53
+ return;
54
+ const raw = input.slice(0, newline);
55
+ void this.respond(socket, raw);
56
+ });
57
+ }
58
+ async respond(socket, raw) {
59
+ try {
60
+ const request = JSON.parse(raw);
61
+ if (request.token !== this.token) {
62
+ socket.end(`${JSON.stringify({ ok: false, message: 'Unauthorized daemon request' })}\n`);
63
+ return;
64
+ }
65
+ const response = await this.state.execute(request.session, request.command);
66
+ socket.end(`${JSON.stringify(response)}\n`);
67
+ this.refreshIdleTimer();
68
+ }
69
+ catch (error) {
70
+ socket.end(`${JSON.stringify({
71
+ ok: false,
72
+ message: error instanceof Error ? error.message : String(error),
73
+ })}\n`);
74
+ }
75
+ }
76
+ refreshIdleTimer() {
77
+ if (this.idleTimer)
78
+ clearTimeout(this.idleTimer);
79
+ if (this.state.sessionCount > 0)
80
+ return;
81
+ this.idleTimer = setTimeout(() => void this.stop(), IDLE_TIMEOUT_MS);
82
+ this.idleTimer.unref();
83
+ }
84
+ }
85
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
package/dist/help.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare const VERSION = "0.1.0";
2
+ export declare function helpText(): string;
3
+ export declare function workflowText(): string;
package/dist/help.js ADDED
@@ -0,0 +1,62 @@
1
+ export const VERSION = '0.1.0';
2
+ export function helpText() {
3
+ return `appclaw-agent - terminal mobile automation for coding agents
4
+
5
+ Usage:
6
+ appclaw-agent --session <name> <command> [options]
7
+
8
+ Run \`appclaw-agent help workflow\` for the recommended agent workflow.`;
9
+ }
10
+ export function workflowText() {
11
+ return `Recommended AppClaw agent workflow:
12
+
13
+ 1. Open a named session:
14
+ appclaw-agent --session <name> open <app-id> --platform android|ios
15
+
16
+ 2. Inspect actionable UI:
17
+ appclaw-agent --session <name> snapshot -i --json
18
+
19
+ 3. Use returned refs or stable selectors:
20
+ appclaw-agent --session <name> press @e1 --json
21
+ appclaw-agent --session <name> fill @e2 "text" --json
22
+ appclaw-agent --session <name> press 'id="login_button"' --json
23
+
24
+ 4. Scroll the screen or a specific container:
25
+ appclaw-agent --session <name> scroll down --json (scroll down — see content below)
26
+ appclaw-agent --session <name> scroll up --json (scroll up — see content above)
27
+ appclaw-agent --session <name> scroll @e24 down --json (scroll within a specific element)
28
+
29
+ Always use "scroll", not "swipe" — they are aliases but "scroll down/up" is unambiguous.
30
+ Never use "swipe @eN direction" — element-scoped swipe is not implemented.
31
+
32
+ Re-run snapshot after every state-changing action; refs are invalidated.
33
+
34
+ NOTE: snapshot reports DOM elements — it does not confirm visual on-screen
35
+ presence. To verify what is actually rendered, take a screenshot instead:
36
+ appclaw-agent --session <name> screenshot /tmp/screen.png
37
+
38
+ 5. Press hardware keys:
39
+ appclaw-agent --session <name> enter --json
40
+ appclaw-agent --session <name> back --json
41
+ appclaw-agent --session <name> home --json
42
+
43
+ 6. Verify visual state:
44
+ IMPORTANT: Always verify assertions visually via screenshot. DOM checks only confirm
45
+ an element exists in the hierarchy — not that it is visible on screen. An element can
46
+ be in the DOM but scrolled off-screen or clipped. Screenshot is the only reliable check.
47
+
48
+ - Visual/rendered check (PREFERRED — actually on screen):
49
+ appclaw-agent --session <name> screenshot /tmp/screen.png
50
+ (then read the image file to analyze visually — base pass/fail on what you see)
51
+ - DOM check (element exists in hierarchy, NOT a visibility guarantee):
52
+ appclaw-agent --session <name> is visible 'text="Sign in"' --json
53
+ - Vision check (requires AppClaw vision API key configured):
54
+ appclaw-agent --session <name> is visible --vision "search icon" --json
55
+ appclaw-agent --session <name> get info --vision "displayed total" --json
56
+ When vision is NOT configured, these commands automatically capture a screenshot
57
+ and return its path in screenshotPath — read that file to answer visually.
58
+
59
+ 7. Close the session:
60
+ appclaw-agent --session <name> close`;
61
+ }
62
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../src/help.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,MAAM,UAAU,QAAQ;IACtB,OAAO;;;;;wEAK+D,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wCAiD+B,CAAC;AACzC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ParsedInvocation, TargetInput } from './types.js';
2
+ export declare function parseInvocation(argv: string[]): ParsedInvocation;
3
+ export declare function parseTarget(value: string): TargetInput;
package/dist/parser.js ADDED
@@ -0,0 +1,202 @@
1
+ import { resolve } from 'node:path';
2
+ export function parseInvocation(argv) {
3
+ const args = [...argv];
4
+ let session = 'default';
5
+ let json = false;
6
+ for (let i = 0; i < args.length;) {
7
+ if (args[i] === '--session') {
8
+ session = required(args[i + 1], '--session requires a name');
9
+ args.splice(i, 2);
10
+ }
11
+ else if (args[i] === '--json') {
12
+ json = true;
13
+ args.splice(i, 1);
14
+ }
15
+ else {
16
+ i++;
17
+ }
18
+ }
19
+ if (args.length === 0 || args[0] === '--help' || args[0] === 'help') {
20
+ return { session, json, local: 'help' };
21
+ }
22
+ if (args[0] === '--version' || args[0] === 'version') {
23
+ return { session, json, local: 'version' };
24
+ }
25
+ const name = args.shift();
26
+ if (name === 'session' && args[0] === 'list')
27
+ return { session, json, command: { kind: 'list' } };
28
+ if (name === 'open') {
29
+ const app = required(args.shift(), 'open requires an app id');
30
+ const platform = option(args, '--platform');
31
+ if (platform !== 'android' && platform !== 'ios') {
32
+ throw new Error('open requires --platform android|ios');
33
+ }
34
+ const rawDeviceType = option(args, '--device-type');
35
+ if (rawDeviceType && rawDeviceType !== 'simulator' && rawDeviceType !== 'real') {
36
+ throw new Error('--device-type must be simulator or real');
37
+ }
38
+ return {
39
+ session,
40
+ json,
41
+ command: {
42
+ kind: 'open',
43
+ options: {
44
+ app,
45
+ platform,
46
+ ...(rawDeviceType && { deviceType: rawDeviceType }),
47
+ ...(option(args, '--device') && { device: option(args, '--device') }),
48
+ ...(option(args, '--udid') && { udid: option(args, '--udid') }),
49
+ },
50
+ },
51
+ };
52
+ }
53
+ if (name === 'snapshot') {
54
+ if (args.includes('--vision')) {
55
+ throw new Error('--vision is not supported on snapshot. Use "is visible --vision" or "get info --vision" for visual checks, or "screenshot <path>" to capture and analyze the screen.');
56
+ }
57
+ return { session, json, command: { kind: 'snapshot', interactiveOnly: args.includes('-i') } };
58
+ }
59
+ if (name === 'press') {
60
+ const vision = option(args, '--vision');
61
+ return {
62
+ session,
63
+ json,
64
+ command: vision
65
+ ? { kind: 'press', target: { text: vision }, vision }
66
+ : { kind: 'press', target: parseTarget(required(args[0], 'press requires a target')) },
67
+ };
68
+ }
69
+ if (name === 'fill') {
70
+ return {
71
+ session,
72
+ json,
73
+ command: {
74
+ kind: 'fill',
75
+ target: parseTarget(required(args[0], 'fill requires a target')),
76
+ text: required(args[1], 'fill requires text'),
77
+ },
78
+ };
79
+ }
80
+ if (name === 'longpress') {
81
+ const duration = args[1] ? Number(args[1]) : undefined;
82
+ if (duration !== undefined && !Number.isFinite(duration))
83
+ throw new Error('duration must be numeric');
84
+ return {
85
+ session,
86
+ json,
87
+ command: {
88
+ kind: 'longpress',
89
+ target: parseTarget(required(args[0], 'longpress requires a target')),
90
+ ...(duration !== undefined && { duration }),
91
+ },
92
+ };
93
+ }
94
+ if (name === 'swipe' || name === 'scroll') {
95
+ const DIRECTIONS = ['up', 'down', 'left', 'right'];
96
+ // swipe <target> <direction> — element-scoped scroll
97
+ if (args.length >= 2 && DIRECTIONS.includes(args[1])) {
98
+ return {
99
+ session,
100
+ json,
101
+ command: {
102
+ kind: 'swipe',
103
+ target: parseTarget(args[0]),
104
+ direction: args[1],
105
+ },
106
+ };
107
+ }
108
+ // swipe <direction> — full-screen swipe
109
+ const direction = args[0];
110
+ if (!DIRECTIONS.includes(direction)) {
111
+ throw new Error(`${name} requires up|down|left|right, or <target> up|down|left|right`);
112
+ }
113
+ return { session, json, command: { kind: 'swipe', direction: direction } };
114
+ }
115
+ if (name === 'back' || name === 'home' || name === 'enter') {
116
+ return { session, json, command: { kind: 'key', key: name.toUpperCase() } };
117
+ }
118
+ if (name === 'get' && args[0] === 'info') {
119
+ const vision = option(args, '--vision');
120
+ if (!vision)
121
+ throw new Error('get info requires --vision "<description>"');
122
+ return { session, json, command: { kind: 'getInfo', vision } };
123
+ }
124
+ if (name === 'get' && (args[0] === 'text' || args[0] === 'attrs')) {
125
+ const target = parseTarget(required(args[1], `get ${args[0]} requires a target`));
126
+ return {
127
+ session,
128
+ json,
129
+ command: args[0] === 'text' ? { kind: 'getText', target } : { kind: 'getAttrs', target },
130
+ };
131
+ }
132
+ if (name === 'is' && args[0] === 'visible') {
133
+ const vision = option(args, '--vision');
134
+ if (vision)
135
+ return { session, json, command: { kind: 'isVisible', vision } };
136
+ const target = required(args[1], 'is visible requires a target or --vision');
137
+ return { session, json, command: visibleCommand(target) };
138
+ }
139
+ if (name === 'wait' && (args[0] === 'visible' || args[0] === 'gone')) {
140
+ const target = required(args[1], `wait ${args[0]} requires a target`);
141
+ const parsed = parseTargetOrText(target);
142
+ return {
143
+ session,
144
+ json,
145
+ command: { kind: 'wait', condition: args[0], ...parsed },
146
+ };
147
+ }
148
+ if (name === 'screenshot') {
149
+ return {
150
+ session,
151
+ json,
152
+ command: {
153
+ kind: 'screenshot',
154
+ path: resolve(required(args[0], 'screenshot requires a path')),
155
+ },
156
+ };
157
+ }
158
+ if (name === 'close')
159
+ return { session, json, command: { kind: 'close' } };
160
+ throw new Error(`Unknown command: ${name}. Run appclaw-agent help workflow.`);
161
+ }
162
+ export function parseTarget(value) {
163
+ if (/^@e\d+$/.test(value))
164
+ return { ref: value };
165
+ const selector = parseSelector(value);
166
+ if (selector)
167
+ return { selector };
168
+ const coords = /^(\d+),(\d+)$/.exec(value);
169
+ if (coords)
170
+ return { coordinates: [Number(coords[1]), Number(coords[2])] };
171
+ throw new Error(`Invalid target "${value}". Use @e1, id="...", accessibility="...", text="...", or x,y.`);
172
+ }
173
+ function parseTargetOrText(value) {
174
+ try {
175
+ return { target: parseTarget(value) };
176
+ }
177
+ catch {
178
+ return { text: value };
179
+ }
180
+ }
181
+ function visibleCommand(value) {
182
+ const parsed = parseTargetOrText(value);
183
+ return { kind: 'isVisible', ...parsed };
184
+ }
185
+ function parseSelector(value) {
186
+ const match = /^(id|accessibility|text)="([\s\S]*)"$/.exec(value);
187
+ if (!match)
188
+ return undefined;
189
+ return { kind: match[1], value: match[2] };
190
+ }
191
+ function option(args, name) {
192
+ const index = args.indexOf(name);
193
+ if (index < 0)
194
+ return undefined;
195
+ return required(args[index + 1], `${name} requires a value`);
196
+ }
197
+ function required(value, message) {
198
+ if (!value)
199
+ throw new Error(message);
200
+ return value;
201
+ }
202
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const STATE_DIR: string;
2
+ export declare const SOCKET_PATH: string;
3
+ export declare const METADATA_PATH: string;
4
+ export declare const LOCK_PATH: string;
5
+ export interface DaemonMetadata {
6
+ pid: number;
7
+ socketPath: string;
8
+ token: string;
9
+ }
package/dist/paths.js ADDED
@@ -0,0 +1,7 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ export const STATE_DIR = join(homedir(), '.appclaw', 'agent-cli');
4
+ export const SOCKET_PATH = join(STATE_DIR, 'daemon.sock');
5
+ export const METADATA_PATH = join(STATE_DIR, 'daemon.json');
6
+ export const LOCK_PATH = join(STATE_DIR, 'daemon.lock');
7
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Command, CommandResponse } from './types.js';
2
+ export declare class AgentDaemonState {
3
+ private readonly sessions;
4
+ get sessionCount(): number;
5
+ execute(sessionName: string, command: Command): Promise<CommandResponse>;
6
+ closeAll(): Promise<void>;
7
+ private requireSession;
8
+ }
package/dist/server.js ADDED
@@ -0,0 +1,168 @@
1
+ import { tmpdir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { AgentRuntimeSession } from '@appclaw/core/agent-runtime';
4
+ import { snapshotWithRefs } from './snapshot.js';
5
+ export class AgentDaemonState {
6
+ sessions = new Map();
7
+ get sessionCount() {
8
+ return this.sessions.size;
9
+ }
10
+ async execute(sessionName, command) {
11
+ try {
12
+ if (command.kind === 'list') {
13
+ const sessions = [...this.sessions.keys()];
14
+ return {
15
+ ok: true,
16
+ message: sessions.length ? sessions.join('\n') : 'No active sessions',
17
+ data: { sessions },
18
+ };
19
+ }
20
+ if (command.kind === 'open') {
21
+ const previous = this.sessions.get(sessionName);
22
+ if (previous) {
23
+ await previous.runtime.close();
24
+ this.sessions.delete(sessionName);
25
+ }
26
+ const runtime = await AgentRuntimeSession.open(command.options);
27
+ this.sessions.set(sessionName, { runtime, refs: null });
28
+ return {
29
+ ok: true,
30
+ session: sessionName,
31
+ message: `Opened ${command.options.app} on ${command.options.platform}`,
32
+ data: { sessionId: runtime.sessionId },
33
+ };
34
+ }
35
+ if (command.kind === 'close') {
36
+ const current = this.requireSession(sessionName);
37
+ await current.runtime.close();
38
+ this.sessions.delete(sessionName);
39
+ return { ok: true, session: sessionName, message: `Closed session ${sessionName}` };
40
+ }
41
+ const current = this.requireSession(sessionName);
42
+ if (command.kind === 'snapshot') {
43
+ const snapshot = await current.runtime.snapshot(command.interactiveOnly);
44
+ const formatted = snapshotWithRefs(snapshot);
45
+ current.refs = formatted.refs;
46
+ return {
47
+ ok: true,
48
+ session: sessionName,
49
+ message: `Snapshot contains ${snapshot.elements.length} element(s)`,
50
+ output: formatted.output,
51
+ data: {
52
+ platform: snapshot.platform,
53
+ elements: snapshot.elements,
54
+ refs: formatted.entries,
55
+ },
56
+ };
57
+ }
58
+ let response;
59
+ switch (command.kind) {
60
+ case 'press':
61
+ if (command.vision && !current.runtime.isVisionConfigured()) {
62
+ return screenshotFallback(sessionName, current.runtime, command.vision, true);
63
+ }
64
+ response = result(sessionName, command.vision
65
+ ? await current.runtime.visionPress(command.vision)
66
+ : await current.runtime.press(resolveTarget(current, command.target)));
67
+ break;
68
+ case 'fill':
69
+ response = result(sessionName, await current.runtime.fill(resolveTarget(current, command.target), command.text));
70
+ break;
71
+ case 'longpress':
72
+ response = result(sessionName, await current.runtime.longpress(resolveTarget(current, command.target), command.duration));
73
+ break;
74
+ case 'swipe':
75
+ response = result(sessionName, command.target
76
+ ? await current.runtime.swipeElement(resolveTarget(current, command.target), command.direction)
77
+ : await current.runtime.swipe(command.direction));
78
+ break;
79
+ case 'key':
80
+ response = result(sessionName, await current.runtime.pressKey(command.key));
81
+ break;
82
+ case 'getText':
83
+ return result(sessionName, await current.runtime.getText(resolveTarget(current, command.target)));
84
+ case 'getAttrs':
85
+ return result(sessionName, await current.runtime.getAttrs(resolveTarget(current, command.target)));
86
+ case 'getInfo':
87
+ if (!current.runtime.isVisionConfigured()) {
88
+ return screenshotFallback(sessionName, current.runtime, command.vision, false);
89
+ }
90
+ return result(sessionName, await current.runtime.visionInfo(command.vision));
91
+ case 'isVisible':
92
+ if (command.vision && !current.runtime.isVisionConfigured()) {
93
+ return screenshotFallback(sessionName, current.runtime, command.vision, false);
94
+ }
95
+ return result(sessionName, command.vision
96
+ ? await current.runtime.visionVisible(command.vision)
97
+ : await current.runtime.isVisible(command.target ? resolveTarget(current, command.target) : (command.text ?? '')));
98
+ case 'wait':
99
+ return result(sessionName, await current.runtime.waitFor(command.condition, command.target ? resolveTarget(current, command.target) : (command.text ?? '')));
100
+ case 'screenshot':
101
+ return result(sessionName, await current.runtime.saveScreenshot(command.path));
102
+ default:
103
+ return { ok: false, session: sessionName, message: 'Unsupported command' };
104
+ }
105
+ if (response.ok)
106
+ current.refs = null;
107
+ return response;
108
+ }
109
+ catch (error) {
110
+ return {
111
+ ok: false,
112
+ session: sessionName,
113
+ message: error instanceof Error ? error.message : String(error),
114
+ };
115
+ }
116
+ }
117
+ async closeAll() {
118
+ const current = [...this.sessions.values()];
119
+ this.sessions.clear();
120
+ await Promise.allSettled(current.map(({ runtime }) => runtime.close()));
121
+ }
122
+ requireSession(name) {
123
+ const session = this.sessions.get(name);
124
+ if (!session) {
125
+ throw new Error(`No active session "${name}". Run appclaw-agent --session ${name} open first.`);
126
+ }
127
+ return session;
128
+ }
129
+ }
130
+ function resolveTarget(state, target) {
131
+ if ('ref' in target) {
132
+ if (!state.refs) {
133
+ throw new Error(`Reference ${target.ref} is stale. Run snapshot -i again before interacting.`);
134
+ }
135
+ const value = state.refs.get(target.ref);
136
+ if (!value)
137
+ throw new Error(`Unknown reference ${target.ref}. Run snapshot -i again.`);
138
+ return value;
139
+ }
140
+ if ('selector' in target)
141
+ return { selector: target.selector };
142
+ if ('coordinates' in target)
143
+ return { coordinates: target.coordinates };
144
+ throw new Error('Text targets are supported only by visibility and wait commands');
145
+ }
146
+ async function screenshotFallback(session, runtime, visualQuery, pressIntent) {
147
+ const screenshotPath = join(tmpdir(), `appclaw-visual-${Date.now()}.png`);
148
+ await runtime.saveScreenshot(screenshotPath);
149
+ const action = pressIntent
150
+ ? `Determine the coordinates of "${visualQuery}" from the screenshot, then use press <x,y> to tap it.`
151
+ : `Read this image file and visually determine if "${visualQuery}" is present on screen.`;
152
+ return {
153
+ ok: true,
154
+ session,
155
+ message: `Vision not configured — screenshot captured for visual analysis. ${action}`,
156
+ screenshotPath,
157
+ visualQuery,
158
+ };
159
+ }
160
+ function result(session, operation) {
161
+ return {
162
+ ok: operation.success,
163
+ session,
164
+ message: operation.message,
165
+ ...(operation.value !== undefined && { data: operation.value }),
166
+ };
167
+ }
168
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AgentSnapshot, AgentTarget } from '@appclaw/core/agent-runtime';
2
+ import type { SnapshotRef } from './types.js';
3
+ export declare function snapshotWithRefs(snapshot: AgentSnapshot): {
4
+ refs: Map<string, AgentTarget>;
5
+ entries: SnapshotRef[];
6
+ output: string;
7
+ };
@@ -0,0 +1,26 @@
1
+ export function snapshotWithRefs(snapshot) {
2
+ const refs = new Map();
3
+ const entries = [];
4
+ const lines = snapshot.elements.map((element, index) => {
5
+ const ref = `@e${index + 1}`;
6
+ const target = element.selector
7
+ ? { selector: element.selector }
8
+ : { coordinates: element.center };
9
+ refs.set(ref, target);
10
+ entries.push({ ref, target });
11
+ const label = element.text ? ` "${element.text}"` : '';
12
+ const id = element.id
13
+ ? ` id="${element.id}"`
14
+ : element.accessibilityId
15
+ ? ` accessibility="${element.accessibilityId}"`
16
+ : '';
17
+ const state = element.enabled ? '' : ' disabled';
18
+ return `${ref} [${element.type || element.action}]${label}${id}${state}`;
19
+ });
20
+ return {
21
+ refs,
22
+ entries,
23
+ output: lines.length ? lines.join('\n') : '(no matching elements on screen)',
24
+ };
25
+ }
26
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IAKtD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC5C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAgB,OAAO,CAAC,QAAQ;YAC1C,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;YAChC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACtB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE;YACnB,CAAC,CAAC,QAAQ,OAAO,CAAC,EAAE,GAAG;YACvB,CAAC,CAAC,OAAO,CAAC,eAAe;gBACvB,CAAC,CAAC,mBAAmB,OAAO,CAAC,eAAe,GAAG;gBAC/C,CAAC,CAAC,EAAE,CAAC;QACT,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QACjD,OAAO,GAAG,GAAG,KAAK,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,OAAO;QACL,IAAI;QACJ,OAAO;QACP,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kCAAkC;KAC7E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,87 @@
1
+ import type { AgentOpenOptions, AgentSelector, AgentTarget } from '@appclaw/core/agent-runtime';
2
+ export type Command = {
3
+ kind: 'open';
4
+ options: AgentOpenOptions;
5
+ } | {
6
+ kind: 'snapshot';
7
+ interactiveOnly: boolean;
8
+ } | {
9
+ kind: 'press';
10
+ target: TargetInput;
11
+ vision?: string;
12
+ } | {
13
+ kind: 'fill';
14
+ target: TargetInput;
15
+ text: string;
16
+ } | {
17
+ kind: 'longpress';
18
+ target: TargetInput;
19
+ duration?: number;
20
+ } | {
21
+ kind: 'swipe';
22
+ direction: 'up' | 'down' | 'left' | 'right';
23
+ target?: TargetInput;
24
+ } | {
25
+ kind: 'key';
26
+ key: 'BACK' | 'HOME' | 'ENTER';
27
+ } | {
28
+ kind: 'getText';
29
+ target: TargetInput;
30
+ } | {
31
+ kind: 'getAttrs';
32
+ target: TargetInput;
33
+ } | {
34
+ kind: 'getInfo';
35
+ vision: string;
36
+ } | {
37
+ kind: 'isVisible';
38
+ target?: TargetInput;
39
+ text?: string;
40
+ vision?: string;
41
+ } | {
42
+ kind: 'wait';
43
+ condition: 'visible' | 'gone';
44
+ target?: TargetInput;
45
+ text?: string;
46
+ } | {
47
+ kind: 'screenshot';
48
+ path: string;
49
+ } | {
50
+ kind: 'list';
51
+ } | {
52
+ kind: 'close';
53
+ };
54
+ export type TargetInput = {
55
+ ref: string;
56
+ } | {
57
+ selector: AgentSelector;
58
+ } | {
59
+ text: string;
60
+ } | {
61
+ coordinates: [number, number];
62
+ };
63
+ export interface ParsedInvocation {
64
+ session: string;
65
+ json: boolean;
66
+ local?: 'help' | 'version';
67
+ command?: Command;
68
+ }
69
+ export interface DaemonRequest {
70
+ token: string;
71
+ session: string;
72
+ command: Command;
73
+ }
74
+ export interface CommandResponse {
75
+ ok: boolean;
76
+ session?: string;
77
+ message: string;
78
+ data?: unknown;
79
+ output?: string;
80
+ /** Set when vision was requested but not configured. Read this image file to answer the visualQuery visually. */
81
+ screenshotPath?: string;
82
+ visualQuery?: string;
83
+ }
84
+ export interface SnapshotRef {
85
+ ref: string;
86
+ target: AgentTarget;
87
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@appclaw/agent",
3
+ "version": "2.0.0",
4
+ "description": "Agent-native terminal CLI for AppClaw mobile automation",
5
+ "type": "module",
6
+ "bin": {
7
+ "appclaw-agent": "bin/appclaw-agent.js"
8
+ },
9
+ "main": "dist/cli.js",
10
+ "types": "dist/cli.d.ts",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "bin",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest run"
23
+ },
24
+ "dependencies": {
25
+ "@appclaw/core": "2.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@semantic-release/changelog": "^6.0.3",
29
+ "@semantic-release/commit-analyzer": "^13.0.1",
30
+ "@semantic-release/git": "^10.0.1",
31
+ "@semantic-release/github": "^11.0.6",
32
+ "@semantic-release/npm": "^12.0.2",
33
+ "@semantic-release/release-notes-generator": "^14.1.0",
34
+ "@types/node": "^22.0.0",
35
+ "conventional-changelog-conventionalcommits": "^9.3.1",
36
+ "semantic-release": "^24.2.9",
37
+ "typescript": "^5.6.0",
38
+ "vitest": "^4.1.2"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ }
43
+ }