@hasna/computer 0.1.8 → 0.1.9
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/LICENSE +4 -2
- package/README.md +73 -7
- package/dist/apps/ghostty/applescript.d.ts +36 -0
- package/dist/apps/ghostty/applescript.d.ts.map +1 -0
- package/dist/apps/ghostty/applescript.test.d.ts +2 -0
- package/dist/apps/ghostty/applescript.test.d.ts.map +1 -0
- package/dist/apps/ghostty/driver.d.ts +10 -0
- package/dist/apps/ghostty/driver.d.ts.map +1 -0
- package/dist/apps/registry.d.ts +5 -0
- package/dist/apps/registry.d.ts.map +1 -0
- package/dist/apps/registry.test.d.ts +2 -0
- package/dist/apps/registry.test.d.ts.map +1 -0
- package/dist/apps/types.d.ts +47 -0
- package/dist/apps/types.d.ts.map +1 -0
- package/dist/cli/index.js +1055 -91
- package/dist/cli/storage.d.ts +3 -0
- package/dist/cli/storage.d.ts.map +1 -0
- package/dist/cli/storage.test.d.ts +2 -0
- package/dist/cli/storage.test.d.ts.map +1 -0
- package/dist/db/storage-sync.d.ts +57 -0
- package/dist/db/storage-sync.d.ts.map +1 -0
- package/dist/db/storage-sync.test.d.ts +2 -0
- package/dist/db/storage-sync.test.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -26
- package/dist/mcp/http.d.ts +16 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.test.d.ts +2 -0
- package/dist/mcp/http.test.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +609 -262
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/server/index.js +34565 -8747
- package/dist/storage.d.ts +5 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +5519 -0
- package/package.json +7 -2
- package/dist/cli/cloud.d.ts +0 -3
- package/dist/cli/cloud.d.ts.map +0 -1
- package/dist/db/cloud-sync.d.ts +0 -33
- package/dist/db/cloud-sync.d.ts.map +0 -1
package/LICENSE
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
Apache License
|
|
2
3
|
Version 2.0, January 2004
|
|
3
4
|
http://www.apache.org/licenses/
|
|
@@ -34,7 +35,8 @@
|
|
|
34
35
|
|
|
35
36
|
"Work" shall mean the work of authorship, whether in Source or
|
|
36
37
|
Object form, made available under the License, as indicated by a
|
|
37
|
-
copyright notice that is included in or attached to the work
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
38
40
|
|
|
39
41
|
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
42
|
form, that is based on (or derived from) the Work and for which the
|
|
@@ -174,7 +176,7 @@
|
|
|
174
176
|
|
|
175
177
|
END OF TERMS AND CONDITIONS
|
|
176
178
|
|
|
177
|
-
Copyright 2026
|
|
179
|
+
Copyright 2026 Hasna, Inc.
|
|
178
180
|
|
|
179
181
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
180
182
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -47,12 +47,63 @@ bun install -g @hasna/computer
|
|
|
47
47
|
computer run <task> # Run a computer use task
|
|
48
48
|
computer run <task> -p openai # Use OpenAI instead of Anthropic
|
|
49
49
|
computer run <task> -s 30 # Limit to 30 steps
|
|
50
|
+
computer open <app> [options] # Open an app deterministically via its driver
|
|
51
|
+
computer apps # List app drivers + availability
|
|
50
52
|
computer screenshot # Capture current screen
|
|
51
53
|
computer sessions # List past sessions
|
|
52
54
|
computer session <id> # Show session details + action log
|
|
53
55
|
computer stats # Usage statistics
|
|
54
56
|
```
|
|
55
57
|
|
|
58
|
+
## Apps
|
|
59
|
+
|
|
60
|
+
Beyond AI-driven tasks (`computer run`), `computer` ships deterministic **app
|
|
61
|
+
drivers** that open and arrange desktop apps with zero AI in the loop — windows,
|
|
62
|
+
tabs, pane grids, and a command per pane.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
computer apps # List registered drivers and availability
|
|
66
|
+
computer open <app> [options] # Open/orchestrate an app via its driver
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Options for `computer open`:
|
|
70
|
+
|
|
71
|
+
| Option | Description |
|
|
72
|
+
|--------|-------------|
|
|
73
|
+
| `--grid RxC` | Split the window into R rows x C cols (panes fill row-major: left-to-right, top-to-bottom) |
|
|
74
|
+
| `--tabs "spec1,spec2,..."` | Multiple tabs in one window, each with its own grid (e.g. `"2x2,1x2,1x2"`) |
|
|
75
|
+
| `--run <cmd>` | Command for the next pane in order (repeatable); with `--tabs`, commands flow across tabs |
|
|
76
|
+
| `--all` | Run the single `--run` command in every pane |
|
|
77
|
+
| `--dir <path>` | Working directory — every pane `cd`s there first |
|
|
78
|
+
| `--max` | Maximize the new window (not native fullscreen) |
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# 2x2 grid, run codewith in all four panes, maximized
|
|
84
|
+
computer open ghostty --grid 2x2 --run "codewith" --all --max
|
|
85
|
+
|
|
86
|
+
# 2x2 grid with a different command per pane
|
|
87
|
+
computer open ghostty --grid 2x2 --run "htop" --run "btop" --run "vim" --run "bun dev"
|
|
88
|
+
|
|
89
|
+
# Three tabs (2x2, then two 1x2), every pane cd'd into the project
|
|
90
|
+
computer open ghostty --tabs "2x2,1x2,1x2" --dir ~/Workspace/myproject
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Drivers:**
|
|
94
|
+
|
|
95
|
+
- **ghostty** — Ghostty terminal (macOS, Ghostty 1.3+). Uses Ghostty's native
|
|
96
|
+
AppleScript dictionary for windows, tabs, and splits. Requires
|
|
97
|
+
`/Applications/Ghostty.app` (or `ghostty` on PATH).
|
|
98
|
+
|
|
99
|
+
Drivers are app-generic: each implements `available()` (with a reason when
|
|
100
|
+
unavailable, e.g. on Linux) and `open(spec)`. New drivers register in
|
|
101
|
+
`src/apps/registry.ts`.
|
|
102
|
+
|
|
103
|
+
The same surface is exposed over MCP via `computer_open_app`
|
|
104
|
+
(params: `app`, `grid`, `tabs`, `run[]`, `all`, `dir`, `max` — falls back to a
|
|
105
|
+
plain macOS app launch for apps without a driver) and `computer_list_apps`.
|
|
106
|
+
|
|
56
107
|
## MCP Server
|
|
57
108
|
|
|
58
109
|
Add to your Claude Code config:
|
|
@@ -67,6 +118,19 @@ Add to your Claude Code config:
|
|
|
67
118
|
}
|
|
68
119
|
```
|
|
69
120
|
|
|
121
|
+
## HTTP mode
|
|
122
|
+
|
|
123
|
+
Shared Streamable HTTP transport for multi-agent sessions (stdio remains the default):
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
computer-mcp --http # http://127.0.0.1:8806/mcp
|
|
127
|
+
MCP_HTTP=1 computer-mcp # same via env
|
|
128
|
+
computer-mcp --http --port 9000 # override port
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- Health: `GET http://127.0.0.1:8806/health` → `{"status":"ok","name":"computer"}`
|
|
132
|
+
- MCP endpoint is also mounted on `computer-serve` at `/mcp`.
|
|
133
|
+
|
|
70
134
|
**Available tools:**
|
|
71
135
|
- `computer_run_task` — Run a full computer use task
|
|
72
136
|
- `computer_screenshot` — Capture the screen
|
|
@@ -146,19 +210,21 @@ const result = await driver.execute({
|
|
|
146
210
|
|
|
147
211
|
Sessions and action logs are stored in `~/.hasna/computer/computer.db` (SQLite).
|
|
148
212
|
|
|
149
|
-
##
|
|
213
|
+
## Storage Sync
|
|
150
214
|
|
|
151
215
|
Optional Postgres sync is available through package-local commands:
|
|
152
216
|
|
|
153
217
|
```bash
|
|
154
|
-
export
|
|
155
|
-
computer
|
|
156
|
-
computer
|
|
157
|
-
computer
|
|
158
|
-
computer
|
|
218
|
+
export HASNA_COMPUTER_DATABASE_URL=postgres://...
|
|
219
|
+
computer storage status
|
|
220
|
+
computer storage push
|
|
221
|
+
computer storage pull
|
|
222
|
+
computer storage sync
|
|
159
223
|
```
|
|
160
224
|
|
|
161
|
-
The MCP server also exposes `
|
|
225
|
+
The MCP server also exposes `storage_status`, `storage_push`, `storage_pull`, and `storage_sync`.
|
|
226
|
+
|
|
227
|
+
`COMPUTER_DATABASE_URL` is accepted as the non-Hasna fallback database URL.
|
|
162
228
|
|
|
163
229
|
## License
|
|
164
230
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PaneGrid } from "../types.js";
|
|
2
|
+
/** Parse "RxC" (e.g. "2x2", "3x1") into a PaneGrid. Throws on invalid input. */
|
|
3
|
+
export declare function parseGrid(spec: string): PaneGrid;
|
|
4
|
+
/** Parse a comma-separated tabs spec like "2x2,1x2,1x2" into one grid per tab. */
|
|
5
|
+
export declare function parseTabsSpec(spec: string): PaneGrid[];
|
|
6
|
+
/** Escape a string for embedding inside an AppleScript double-quoted literal. */
|
|
7
|
+
export declare function escapeAppleScript(s: string): string;
|
|
8
|
+
/** Single-quote a string for POSIX shells (used for `cd <dir>`). */
|
|
9
|
+
export declare function shellQuote(s: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Map run commands onto panes (row-major across tabs in order).
|
|
12
|
+
* - `all` fills every pane with the single command (requires exactly one).
|
|
13
|
+
* - Otherwise commands are assigned in order; extra panes get undefined.
|
|
14
|
+
* Throws when there are more commands than panes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assignPaneCommands(totalPanes: number, run: string[], all: boolean): (string | undefined)[];
|
|
17
|
+
export interface GhosttyScriptOptions {
|
|
18
|
+
/** One grid per tab; the first tab reuses the new window's selected tab. */
|
|
19
|
+
tabs: PaneGrid[];
|
|
20
|
+
/** Command per pane, row-major across tabs in order. undefined = empty shell. */
|
|
21
|
+
commands?: (string | undefined)[];
|
|
22
|
+
/** Working directory — every pane cds here before its command. */
|
|
23
|
+
dir?: string;
|
|
24
|
+
/** Maximize the new window (toggle_maximize, not native fullscreen). */
|
|
25
|
+
max?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build the full AppleScript for opening one Ghostty window with the given
|
|
29
|
+
* tabs/grids/commands. Pure — returns the script string.
|
|
30
|
+
*
|
|
31
|
+
* Grid algorithm (per tab): build column 0 downward (split direction down
|
|
32
|
+
* from the previous row), then split each row rightward C-1 times, then
|
|
33
|
+
* equalize once. Commands inject row-major with `input text` + enter key.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildGhosttyScript(opts: GhosttyScriptOptions): string;
|
|
36
|
+
//# sourceMappingURL=applescript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applescript.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/applescript.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAShD;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAMtD;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EAAE,EACb,GAAG,EAAE,OAAO,GACX,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAWxB;AAED,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IAClC,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAiErE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applescript.test.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/applescript.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AppAvailability, AppDriver } from "../types.js";
|
|
2
|
+
export interface GhosttyEnvironment {
|
|
3
|
+
platform?: NodeJS.Platform | string;
|
|
4
|
+
hasAppBundle?: boolean;
|
|
5
|
+
hasBinary?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** Availability check, injectable for tests. */
|
|
8
|
+
export declare function ghosttyAvailability(env?: GhosttyEnvironment): AppAvailability;
|
|
9
|
+
export declare const ghosttyDriver: AppDriver;
|
|
10
|
+
//# sourceMappingURL=driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../../src/apps/ghostty/driver.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAwC,MAAM,aAAa,CAAC;AAKpG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,gDAAgD;AAChD,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,kBAAuB,GAAG,eAAe,CAWjF;AAmBD,eAAO,MAAM,aAAa,EAAE,SAiD3B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AppDriver } from "./types.js";
|
|
2
|
+
export declare function registerAppDriver(driver: AppDriver): void;
|
|
3
|
+
export declare function getAppDriver(name: string): AppDriver | undefined;
|
|
4
|
+
export declare function listAppDrivers(): AppDriver[];
|
|
5
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/apps/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAEzD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEhE;AAED,wBAAgB,cAAc,IAAI,SAAS,EAAE,CAE5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../src/apps/registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** A pane grid: R rows x C cols. Panes are addressed row-major. */
|
|
2
|
+
export interface PaneGrid {
|
|
3
|
+
rows: number;
|
|
4
|
+
cols: number;
|
|
5
|
+
}
|
|
6
|
+
/** Declarative description of how to open/arrange an app. */
|
|
7
|
+
export interface AppOpenSpec {
|
|
8
|
+
/** Split the window into rows x cols panes (single tab). */
|
|
9
|
+
grid?: PaneGrid;
|
|
10
|
+
/** Multiple tabs in one window, each with its own grid. Overrides `grid`. */
|
|
11
|
+
tabs?: PaneGrid[];
|
|
12
|
+
/** Commands per pane, row-major across tabs in order. */
|
|
13
|
+
run?: string[];
|
|
14
|
+
/** Fill every pane with the single `run` command. */
|
|
15
|
+
all?: boolean;
|
|
16
|
+
/** Working directory — every pane cds here before running its command. */
|
|
17
|
+
dir?: string;
|
|
18
|
+
/** Maximize the new window (not native fullscreen). */
|
|
19
|
+
max?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Whether a driver can run on this machine, and why not if it can't. */
|
|
22
|
+
export interface AppAvailability {
|
|
23
|
+
available: boolean;
|
|
24
|
+
/** Human-readable reason when unavailable. */
|
|
25
|
+
reason?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Result of an open() call. */
|
|
28
|
+
export interface AppOpenResult {
|
|
29
|
+
ok: boolean;
|
|
30
|
+
message: string;
|
|
31
|
+
/** Total panes created (when applicable). */
|
|
32
|
+
panes?: number;
|
|
33
|
+
/** Tabs created (when applicable). */
|
|
34
|
+
tabs?: number;
|
|
35
|
+
}
|
|
36
|
+
/** A deterministic driver for one desktop application. */
|
|
37
|
+
export interface AppDriver {
|
|
38
|
+
/** Registry key, e.g. "ghostty". Lowercase. */
|
|
39
|
+
name: string;
|
|
40
|
+
/** One-line human description. */
|
|
41
|
+
description: string;
|
|
42
|
+
/** Check availability on this machine. */
|
|
43
|
+
available(): AppAvailability;
|
|
44
|
+
/** Open/orchestrate the app according to spec. */
|
|
45
|
+
open(spec: AppOpenSpec): Promise<AppOpenResult>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/apps/types.ts"],"names":[],"mappings":"AAOA,mEAAmE;AACnE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC;IAClB,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,qDAAqD;IACrD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,gCAAgC;AAChC,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,0DAA0D;AAC1D,MAAM,WAAW,SAAS;IACxB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,SAAS,IAAI,eAAe,CAAC;IAC7B,kDAAkD;IAClD,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACjD"}
|