gemiterm 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/.env +2 -0
- package/.github/workflows/manual-release.yml +34 -0
- package/.github/workflows/release.yml +198 -0
- package/.github/workflows/test.yml +29 -0
- package/.opencode/commands/opsx-apply.md +152 -0
- package/.opencode/commands/opsx-archive.md +157 -0
- package/.opencode/commands/opsx-explore.md +169 -0
- package/.opencode/commands/opsx-propose.md +104 -0
- package/.opencode/commands/opsx-sync.md +140 -0
- package/.opencode/commands/search-intelligently.md +9 -0
- package/.opencode/opencode.json +20 -0
- package/.opencode/skills/intellisearch/.version +1 -0
- package/.opencode/skills/intellisearch/SKILL.md +84 -0
- package/.opencode/skills/intellisearch/references/brave-search.md +67 -0
- package/.opencode/skills/intellisearch/references/ddg-search.md +79 -0
- package/.opencode/skills/intellisearch/references/deepwiki-tools.md +246 -0
- package/.opencode/skills/intellisearch/references/examples.md +97 -0
- package/.opencode/skills/intellisearch/references/gh-cli.md +143 -0
- package/.opencode/skills/intellisearch/references/google-search.md +40 -0
- package/.opencode/skills/intellisearch/references/search-workflow.md +143 -0
- package/.opencode/skills/intellisearch/references/workflow.md +115 -0
- package/.opencode/skills/openspec-apply-change/SKILL.md +159 -0
- package/.opencode/skills/openspec-archive-change/SKILL.md +117 -0
- package/.opencode/skills/openspec-explore/SKILL.md +287 -0
- package/.opencode/skills/openspec-propose/SKILL.md +111 -0
- package/.opencode/skills/openspec-sync-specs/SKILL.md +147 -0
- package/.serena/project.yml +133 -0
- package/AGENTS.md +136 -0
- package/CHANGELOG.md +3 -0
- package/README.md +245 -0
- package/bun.lock +105 -0
- package/docs/INSTALL.md +185 -0
- package/docs/PLAYWRIGHT_CLI_API.md +306 -0
- package/docs/python-release-for-reference.md +175 -0
- package/examples/sample_json_export.json +32 -0
- package/examples/sample_markdown_export.md +221 -0
- package/examples/usage_examples.sh +222 -0
- package/install.ps1 +264 -0
- package/install.sh +275 -0
- package/openspec/MAESTRO_MIGRATION.md +180 -0
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/design.md +194 -0
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/proposal.md +52 -0
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/specs/multi-profile-conversations/spec.md +133 -0
- package/openspec/changes/archive/2026-06-08-command-spec-conformance/tasks.md +95 -0
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/design.md +28 -0
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/proposal.md +22 -0
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/specs/interactive-prompt-loop/spec.md +35 -0
- package/openspec/changes/archive/2026-06-09-refactor-interactive-prompt-loop/tasks.md +28 -0
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/design.md +323 -0
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/proposal.md +122 -0
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/specs/no-capability-changes/spec.md +29 -0
- package/openspec/changes/archive/2026-06-09-replace-gemini-api-placeholder-with-gemini-reverse/tasks.md +172 -0
- package/openspec/changes/archive/2026-06-09-v2-install-migration/.openspec.yaml +2 -0
- package/openspec/changes/archive/2026-06-09-v2-install-migration/design.md +241 -0
- package/openspec/changes/archive/2026-06-09-v2-install-migration/proposal.md +41 -0
- package/openspec/changes/archive/2026-06-09-v2-install-migration/specs/v2-installer/spec.md +205 -0
- package/openspec/changes/archive/2026-06-09-v2-install-migration/tasks.md +97 -0
- package/openspec/changes/commander-cli-parser/.openspec.yaml +2 -0
- package/openspec/changes/commander-cli-parser/design.md +107 -0
- package/openspec/changes/commander-cli-parser/proposal.md +31 -0
- package/openspec/changes/commander-cli-parser/specs/cli/spec.md +48 -0
- package/openspec/changes/commander-cli-parser/tasks.md +33 -0
- package/openspec/changes/cross-platform-build-and-ci/.openspec.yaml +2 -0
- package/openspec/changes/cross-platform-build-and-ci/design.md +213 -0
- package/openspec/changes/cross-platform-build-and-ci/proposal.md +50 -0
- package/openspec/changes/cross-platform-build-and-ci/specs/path-and-file-mediation/spec.md +335 -0
- package/openspec/changes/cross-platform-build-and-ci/specs/release-pipeline/spec.md +95 -0
- package/openspec/changes/cross-platform-build-and-ci/tasks.md +164 -0
- package/openspec/config.yaml +20 -0
- package/openspec/specs/auth/spec.md +394 -0
- package/openspec/specs/cli/spec.md +108 -0
- package/openspec/specs/commands/spec.md +409 -0
- package/openspec/specs/configuration/spec.md +130 -0
- package/openspec/specs/conversations/spec.md +139 -0
- package/openspec/specs/domain-model/spec.md +128 -0
- package/openspec/specs/formatters/spec.md +158 -0
- package/openspec/specs/install-browser/spec.md +146 -0
- package/openspec/specs/interactive-prompt-loop/spec.md +41 -0
- package/openspec/specs/logger/spec.md +71 -0
- package/openspec/specs/mediator/spec.md +72 -0
- package/openspec/specs/multi-profile-conversations/spec.md +145 -0
- package/openspec/specs/path-utils/spec.md +101 -0
- package/openspec/specs/profiles/spec.md +94 -0
- package/openspec/specs/storage/spec.md +198 -0
- package/openspec/specs/testing/spec.md +237 -0
- package/openspec/specs/v2-installer/spec.md +205 -0
- package/openspec/specs/validators/spec.md +65 -0
- package/package.json +45 -0
- package/scripts/build.ts +88 -0
- package/scripts/clean-build.ps1 +4 -0
- package/scripts/clean-build.sh +5 -0
- package/scripts/install-browser.ps1 +5 -0
- package/scripts/install-browser.sh +6 -0
- package/scripts/lint-path-mediation.ps1 +65 -0
- package/scripts/lint-path-mediation.sh +40 -0
- package/src/cli/.gitkeep +0 -0
- package/src/cli/command-registry.ts +62 -0
- package/src/cli/commands/auth-command.ts +179 -0
- package/src/cli/commands/continue-command.ts +158 -0
- package/src/cli/commands/delete-command.ts +163 -0
- package/src/cli/commands/export-all-command.ts +243 -0
- package/src/cli/commands/export-command.ts +156 -0
- package/src/cli/commands/fetch-command.ts +176 -0
- package/src/cli/commands/help.ts +45 -0
- package/src/cli/commands/install-browser-command.ts +33 -0
- package/src/cli/commands/list-command.ts +226 -0
- package/src/cli/commands/new-command.ts +147 -0
- package/src/cli/commands/profile-command.ts +226 -0
- package/src/cli/commands/status-command.ts +59 -0
- package/src/cli/index.ts +213 -0
- package/src/cli/utils/interactive-prompt.ts +64 -0
- package/src/core/.gitkeep +0 -0
- package/src/core/command-handlers.ts +240 -0
- package/src/core/errors.ts +41 -0
- package/src/core/mediator.ts +58 -0
- package/src/core/query-handlers.ts +163 -0
- package/src/core/types.ts +43 -0
- package/src/infrastructure/.gitkeep +0 -0
- package/src/infrastructure/cli-table.ts +45 -0
- package/src/infrastructure/config.ts +52 -0
- package/src/infrastructure/formatters.ts +130 -0
- package/src/infrastructure/io.ts +161 -0
- package/src/infrastructure/logger.ts +41 -0
- package/src/infrastructure/path-utils.ts +157 -0
- package/src/infrastructure/storage.ts +209 -0
- package/src/infrastructure/validators.ts +28 -0
- package/src/services/.gitkeep +0 -0
- package/src/services/auth-service.ts +135 -0
- package/src/services/cookie-monitor.ts +159 -0
- package/src/services/cookie-storage-service.ts +74 -0
- package/src/services/gemini-client-wrapper.ts +239 -0
- package/src/services/install-browser-service.ts +205 -0
- package/src/services/playwright-cli-driver.ts +269 -0
- package/src/services/profile-auth-manager.ts +65 -0
- package/src/services/profile-service.ts +121 -0
- package/tests/cli/auth-command.test.ts +220 -0
- package/tests/cli/command-registry.test.ts +67 -0
- package/tests/cli/continue-command.test.ts +100 -0
- package/tests/cli/delete-command.test.ts +128 -0
- package/tests/cli/export-all-command.test.ts +375 -0
- package/tests/cli/install-browser-command.test.ts +48 -0
- package/tests/cli/list-command.test.ts +179 -0
- package/tests/cli/new-command.test.ts +139 -0
- package/tests/cli/status-command.test.ts +106 -0
- package/tests/core/query-handlers.test.ts +187 -0
- package/tests/fixtures/auth-fixtures.ts +98 -0
- package/tests/fixtures/chat-fixtures.ts +87 -0
- package/tests/infrastructure/cli-table.test.ts +107 -0
- package/tests/infrastructure/formatters.test.ts +202 -0
- package/tests/infrastructure/io.test.ts +197 -0
- package/tests/infrastructure/logger.test.ts +74 -0
- package/tests/infrastructure/storage.test.ts +335 -0
- package/tests/infrastructure/validators.test.ts +67 -0
- package/tests/integration/commands/auth.test.ts +186 -0
- package/tests/integration/commands/continue.test.ts +130 -0
- package/tests/integration/commands/delete.test.ts +140 -0
- package/tests/integration/commands/export.test.ts +266 -0
- package/tests/integration/commands/fetch.test.ts +238 -0
- package/tests/integration/commands/list.test.ts +281 -0
- package/tests/integration/commands/profile.test.ts +258 -0
- package/tests/integration/commands/status.test.ts +223 -0
- package/tests/integration/installer-script-shape.test.ts +67 -0
- package/tests/parity/compare-outputs.ts +359 -0
- package/tests/parity/test-commands-parity.ps1 +82 -0
- package/tests/parity/test-commands-parity.sh +61 -0
- package/tests/services/auth-service.test.ts +315 -0
- package/tests/services/cookie-monitor.test.ts +229 -0
- package/tests/services/cookie-storage-service.test.ts +230 -0
- package/tests/services/gemini-client-wrapper.test.ts +688 -0
- package/tests/services/install-browser-service.test.ts +83 -0
- package/tests/services/playwright-cli-driver.test.ts +468 -0
- package/tests/services/profile-auth-manager.test.ts +334 -0
- package/tests/services/profile-service.test.ts +224 -0
- package/tests/setup.ts +95 -0
- package/tests/smoke/smoke.test.ts +52 -0
- package/tests/unit/config.test.ts +159 -0
- package/tests/unit/errors.test.ts +119 -0
- package/tests/unit/formatters.test.ts +316 -0
- package/tests/unit/mediator.test.ts +152 -0
- package/tests/unit/path-utils.test.ts +289 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# playwright-cli API Reference
|
|
2
|
+
|
|
3
|
+
> Source: [microsoft/playwright-cli](https://github.com/microsoft/playwright-cli)
|
|
4
|
+
> Verified against: `@playwright/cli` (installed via `bunx --bun @playwright/cli --help`)
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
- **Daemon-based**: `open` returns immediately; the browser runs as a background process.
|
|
9
|
+
- **Session-based**: Every command targets a browser session via `-s=<name>`. Without `-s`, commands hit the unnamed **default session**.
|
|
10
|
+
- **Session resolution priority**: `-s=<name>` flag → `PLAYWRIGHT_CLI_SESSION` env var → default session.
|
|
11
|
+
|
|
12
|
+
## Session Management
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
playwright-cli list # list all active sessions
|
|
16
|
+
playwright-cli -s=myprofile list # list details for one session
|
|
17
|
+
playwright-cli close # close the default session
|
|
18
|
+
playwright-cli close-all # close all sessions gracefully
|
|
19
|
+
playwright-cli kill-all # force-kill all sessions
|
|
20
|
+
playwright-cli delete-data # wipe persistent profile data for a session
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Core Commands
|
|
24
|
+
|
|
25
|
+
### `open [url]`
|
|
26
|
+
|
|
27
|
+
Opens a headed browser and navigates to the URL. **Returns immediately** (daemon-style).
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
playwright-cli open https://example.com
|
|
31
|
+
playwright-cli -s=myprofile open --browser=chromium --headed --persistent --profile=/path/to/dir https://example.com
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| Flag | Description | Values |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `--browser` | Browser engine | `chromium`, `firefox`, `webkit`, `msedge` |
|
|
37
|
+
| `--headed` | Show the browser UI (default: headless) | flag |
|
|
38
|
+
| `--persistent` | Persist profile to disk on close | flag |
|
|
39
|
+
| `--profile=<path>` | Custom user-data directory path | absolute path |
|
|
40
|
+
| `--config=<file>` | Path to config file | default: `.playwright/cli.config.json` |
|
|
41
|
+
| `--extension` | Connect via browser extension | flag |
|
|
42
|
+
|
|
43
|
+
### `goto <url>`
|
|
44
|
+
|
|
45
|
+
Navigate the current session to a URL (must target an open session):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
playwright-cli -s=myprofile goto https://other.example.com
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `close` / `detach` / `attach`
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
playwright-cli -s=myprofile close # graceful close
|
|
55
|
+
playwright-cli -s=myprofile detach # detach CLI but keep browser running
|
|
56
|
+
playwright-cli attach myprofile # re-attach to a running session
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Input Commands
|
|
60
|
+
|
|
61
|
+
All input commands target an active session and operate on element references obtained from `snapshot`.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
playwright-cli -s=myprofile click <ref> [button]
|
|
65
|
+
playwright-cli -s=myprofile type <text>
|
|
66
|
+
playwright-cli -s=myprofile fill <ref> <text>
|
|
67
|
+
playwright-cli -s=myprofile press <key> # e.g. Enter, Tab, Escape
|
|
68
|
+
playwright-cli -s=myprofile hover <ref>
|
|
69
|
+
playwright-cli -s=myprofile select <ref> <val>
|
|
70
|
+
playwright-cli -s=myprofile upload <file>
|
|
71
|
+
playwright-cli -s=myprofile check <ref> / uncheck <ref>
|
|
72
|
+
playwright-cli -s=myprofile drag <startRef> <endRef>
|
|
73
|
+
playwright-cli -s=myprofile drop <ref>
|
|
74
|
+
playwright-cli -s=myprofile dialog-accept [prompt]
|
|
75
|
+
playwright-cli -s=myprofile dialog-dismiss
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Storage & State Commands
|
|
79
|
+
|
|
80
|
+
### `state-save [filename]`
|
|
81
|
+
|
|
82
|
+
Exports the current session's cookies + localStorage to a JSON file. **Writes directly to disk.**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
playwright-cli -s=myprofile state-save auth.json
|
|
86
|
+
playwright-cli -s=myprofile state-save # auto-name: storage-state-{timestamp}.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The output JSON matches Playwright's `StorageState` format:
|
|
90
|
+
|
|
91
|
+
```jsonc
|
|
92
|
+
{
|
|
93
|
+
"cookies": [{ "name": "...", "value": "...", "domain": "...", "path": "/", "expires": -1, "httpOnly": true, "secure": true, "sameSite": "Lax" }],
|
|
94
|
+
"origins": [{ "origin": "https://example.com", "localStorage": [{ "name": "...", "value": "..." }] }]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `state-load <filename>`
|
|
99
|
+
|
|
100
|
+
Imports cookies and localStorage from a JSON file into the current session. **Must be called after the browser is open.**
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
playwright-cli -s=myprofile state-load auth.json
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `cookie-list` / `cookie-get` / `cookie-set` / `cookie-delete` / `cookie-clear`
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
playwright-cli -s=myprofile cookie-list # text table output
|
|
110
|
+
playwright-cli -s=myprofile cookie-list --json # JSON output
|
|
111
|
+
playwright-cli -s=myprofile cookie-list --domain=google.com # filter by domain
|
|
112
|
+
playwright-cli -s=myprofile cookie-get "__Secure-1PSID"
|
|
113
|
+
playwright-cli -s=myprofile cookie-set "name" "value" --domain=.example.com --secure --httpOnly
|
|
114
|
+
playwright-cli -s=myprofile cookie-delete "name"
|
|
115
|
+
playwright-cli -s=myprofile cookie-clear
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Important**: `cookie-list` outputs a human-readable text table by default. The `--json` flag (undocumented in `--help`, silently supported) wraps that text in a JSON object: `{"result": "<text>"}` — it does **not** emit a JSON array of cookie objects. See [Cookie-list output format](#cookie-list-output-format) below for the real shapes.
|
|
119
|
+
|
|
120
|
+
### Cookie-list output format
|
|
121
|
+
|
|
122
|
+
`cookie-list` is one of the most-misused commands because `--json` does not return what its name suggests.
|
|
123
|
+
|
|
124
|
+
**Default output (no flag)** — one cookie per line, no header:
|
|
125
|
+
```
|
|
126
|
+
__Secure-1PSID=abc123 (domain: .google.com, path: /)
|
|
127
|
+
__Secure-1PSIDTS=xyz789 (domain: .google.com, path: /)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**With `--json`** — single-line wrapper whose `result` field is the same text as above:
|
|
131
|
+
```json
|
|
132
|
+
{"result": "__Secure-1PSID=abc123 (domain: .google.com, path: /)\n__Secure-1PSIDTS=xyz789 (domain: .google.com, path: /)\n"}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Empty state** — the literal line `No cookies found` (and with `--json`, `{"result": "No cookies found\n"}`).
|
|
136
|
+
|
|
137
|
+
**What's missing from the text format:** `expires`, `httpOnly`, `secure`, `sameSite`. If you need those, use `run-code` with `page.context().cookies()` or call `state-save` and parse the resulting file.
|
|
138
|
+
|
|
139
|
+
**Note:** `--json` is not listed in `cookie-list --help` but is silently supported. Verified in `@playwright/cli` v0.1.13.
|
|
140
|
+
|
|
141
|
+
## Evaluation & Snapshots
|
|
142
|
+
|
|
143
|
+
### `eval <func> [ref]`
|
|
144
|
+
|
|
145
|
+
Run JavaScript on the page and print the result.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
playwright-cli -s=myprofile eval "document.title"
|
|
149
|
+
playwright-cli -s=myprofile eval "document.querySelector('textarea') !== null"
|
|
150
|
+
playwright-cli -s=myprofile eval "window.location.href"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `snapshot [target]`
|
|
154
|
+
|
|
155
|
+
Captures a page snapshot for obtaining element references. **Returns YAML/HTML, NOT JSON.**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
playwright-cli -s=myprofile snapshot # full page → stdout/YAML
|
|
159
|
+
playwright-cli -s=myprofile snapshot --filename=snap.yaml # save to file
|
|
160
|
+
playwright-cli -s=myprofile snapshot "div.main" # target a specific element
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
> ⚠️ `snapshot` does **not** return an accessibility (AX) tree. Use `eval` with DOM queries for conditional logic like login detection.
|
|
164
|
+
|
|
165
|
+
### `run-code [code]`
|
|
166
|
+
|
|
167
|
+
Run a Playwright code snippet with access to the `page` object.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
playwright-cli -s=myprofile run-code "async page => {
|
|
171
|
+
const title = await page.title();
|
|
172
|
+
return title;
|
|
173
|
+
}"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Navigation Commands
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
playwright-cli -s=myprofile go-back
|
|
180
|
+
playwright-cli -s=myprofile go-forward
|
|
181
|
+
playwright-cli -s=myprofile reload
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Tab Management
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
playwright-cli -s=myprofile tab-list
|
|
188
|
+
playwright-cli -s=myprofile tab-new [url]
|
|
189
|
+
playwright-cli -s=myprofile tab-close [index]
|
|
190
|
+
playwright-cli -s=myprofile tab-select <index>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Global Flags
|
|
194
|
+
|
|
195
|
+
| Flag | Description |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `-s=<name>` | Target a named session |
|
|
198
|
+
| `--json` | Output as JSON (applies to most read commands) |
|
|
199
|
+
| `--raw` | Output only the value, no status wrapper |
|
|
200
|
+
| `--config=<file>` | Use a specific config file |
|
|
201
|
+
| `--help [command]` | Show help |
|
|
202
|
+
| `--version` | Print version |
|
|
203
|
+
|
|
204
|
+
## Configuration File
|
|
205
|
+
|
|
206
|
+
Located at `.playwright/cli.config.json` by default:
|
|
207
|
+
|
|
208
|
+
```jsonc
|
|
209
|
+
{
|
|
210
|
+
"browser": {
|
|
211
|
+
"browserName": "chromium", // chromium | firefox | webkit
|
|
212
|
+
"isolated": false, // true = in-memory only (no persistence)
|
|
213
|
+
"userDataDir": "/path/to/dir", // persistent profile directory
|
|
214
|
+
"launchOptions": {
|
|
215
|
+
"headless": false,
|
|
216
|
+
"channel": "chrome", // use system Chrome instead of bundled Chromium
|
|
217
|
+
"executablePath": "/path/to/browser"
|
|
218
|
+
},
|
|
219
|
+
"contextOptions": {
|
|
220
|
+
"viewport": { "width": 1280, "height": 720 }
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"outputDir": "./output",
|
|
224
|
+
"outputMode": "stdout", // stdout | file
|
|
225
|
+
"console": { "level": "info" },
|
|
226
|
+
"testIdAttribute": "data-testid"
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Output Format Reference
|
|
231
|
+
|
|
232
|
+
| Command | Default Output | With `--json` |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| `cookie-list` | Text table (name, value, domain, flags) | JSON wrapper `{"result": "<text>"}` (not an array) |
|
|
235
|
+
| `snapshot` | YAML/HTML (not AX tree) | JSON status wrapper |
|
|
236
|
+
| `state-save` | Writes file to disk, confirmation on stdout | N/A |
|
|
237
|
+
| `eval` | Raw JS return value | JSON status wrapper |
|
|
238
|
+
| `list` | Text session info | JSON session objects |
|
|
239
|
+
|
|
240
|
+
## Persistence Behavior
|
|
241
|
+
|
|
242
|
+
- `--persistent` / `--profile=<dir>`: Profile data is **automatically saved** when the browser closes. Reopening with the same profile preserves cookies, localStorage, etc.
|
|
243
|
+
- `state-save`: **Explicit export** to a portable JSON file. Needed when you want to share state across different profile directories or import into non-CLI Playwright contexts.
|
|
244
|
+
- For cookie scraping: use `state-save` to export to `.auth/<profile>.json`. The persistent profile is only for the browser's own session continuity.
|
|
245
|
+
|
|
246
|
+
## Common Patterns
|
|
247
|
+
|
|
248
|
+
### Login Detection (eval)
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# Check for Gemini prompt textarea
|
|
252
|
+
playwright-cli -s=gemini eval "document.querySelector('textarea[aria-label*=\"prompt\" i]') !== null"
|
|
253
|
+
|
|
254
|
+
# Check URL
|
|
255
|
+
playwright-cli -s=gemini eval "window.location.href"
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
> Tip: cookie-based detection (poll `cookie-list` for `__Secure-1PSID`) is more reliable than DOM probes because cookies are observable even when the page is still mid-render. See [Cookie-list output format](#cookie-list-output-format) for how to parse the response.
|
|
259
|
+
|
|
260
|
+
### Cookie Scraping Pipeline
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# 1. Open headed browser with persistent profile
|
|
264
|
+
playwright-cli -s=mysess open --headed --persistent --profile=./.auth/profiles/gemini https://gemini.google.com/app
|
|
265
|
+
|
|
266
|
+
# 2. User logs in manually...
|
|
267
|
+
|
|
268
|
+
# 3. Export state to portable JSON
|
|
269
|
+
playwright-cli -s=mysess state-save .auth/gemini.json
|
|
270
|
+
|
|
271
|
+
# 4. Close the session
|
|
272
|
+
playwright-cli -s=mysess close
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Re-verify a Saved Login
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
# 1. Open browser (can use same persistent profile or fresh)
|
|
279
|
+
playwright-cli -s=mysess open --headed https://gemini.google.com/app
|
|
280
|
+
|
|
281
|
+
# 2. Inject saved state
|
|
282
|
+
playwright-cli -s=mysess state-load .auth/gemini.json
|
|
283
|
+
|
|
284
|
+
# 3. Reload page to apply cookies
|
|
285
|
+
playwright-cli -s=mysess reload
|
|
286
|
+
|
|
287
|
+
## Common Pitfalls
|
|
288
|
+
|
|
289
|
+
Things that look right but will silently break your code. Verified against `@playwright/cli` v0.1.13.
|
|
290
|
+
|
|
291
|
+
### `cookie-list --json` is not a JSON array
|
|
292
|
+
|
|
293
|
+
It's a wrapper `{"result": "<text>"}` around the same human-readable text. Calling `JSON.parse` and treating the result as an array will always yield zero cookies, and your login detection will time out without any visible error. See [Cookie-list output format](#cookie-list-output-format).
|
|
294
|
+
|
|
295
|
+
### `eval` results are wrapped unless you pass `--raw`
|
|
296
|
+
|
|
297
|
+
`playwright-cli -s=X eval "..."` returns a JSON status envelope, e.g. `{"status":"success","result":"..."}`. To get the raw return value, append `--raw`. Required whenever you compare an eval result to a literal string (e.g. `=== "true"`).
|
|
298
|
+
|
|
299
|
+
### `open` is fire-and-forget (daemon-style)
|
|
300
|
+
|
|
301
|
+
`playwright-cli open <url>` returns as soon as the browser process has been launched, not when the page is loaded. If you start polling the session immediately after, your first `eval` / `cookie-list` may race the still-spawning daemon and throw. Either delay the first poll or use the `state-save` round-trip to wait for the page to be ready.
|
|
302
|
+
|
|
303
|
+
### `--profile` requires an absolute path
|
|
304
|
+
|
|
305
|
+
Relative paths are accepted by the CLI but the resulting profile directory is not portable across working directories and may not be picked up by subsequent runs.
|
|
306
|
+
```
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
skip_publish:
|
|
10
|
+
description: 'Skip PyPI publish (for testing)'
|
|
11
|
+
type: boolean
|
|
12
|
+
default: false
|
|
13
|
+
skip_release:
|
|
14
|
+
description: 'Skip GitHub release (for testing)'
|
|
15
|
+
type: boolean
|
|
16
|
+
default: true
|
|
17
|
+
tag:
|
|
18
|
+
description: 'Tag for release (e.g. v1.0.8) - only needed for workflow_dispatch'
|
|
19
|
+
type: string
|
|
20
|
+
default: ''
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
test:
|
|
24
|
+
name: Test
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: '3.12'
|
|
31
|
+
- name: Install deps
|
|
32
|
+
run: |
|
|
33
|
+
pip install -e ".[dev]"
|
|
34
|
+
- name: Run tests
|
|
35
|
+
run: pytest -v
|
|
36
|
+
|
|
37
|
+
build-linux:
|
|
38
|
+
name: Build (Linux)
|
|
39
|
+
needs: test
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: '3.12'
|
|
47
|
+
|
|
48
|
+
- name: Build package
|
|
49
|
+
run: pip install build && python -m build
|
|
50
|
+
|
|
51
|
+
- name: Install dependencies
|
|
52
|
+
run: pip install rich click playwright gemini-webapi pyinstaller
|
|
53
|
+
|
|
54
|
+
- name: Build executable
|
|
55
|
+
run: |
|
|
56
|
+
pythonPath=$(python -c "import site; print(site.getsitepackages()[0])")
|
|
57
|
+
pyinstaller --onefile --name GemiTerm --add-data "src/gemiterm:gemiterm" --paths "$pythonPath" --hidden-import=rich --hidden-import=rich.console --hidden-import=rich.progress --hidden-import=rich.table --hidden-import=rich.panel --hidden-import=rich.markdown --hidden-import=rich.syntax --hidden-import=click --hidden-import=playwright --hidden-import=gemini_webapi --hidden-import=gemini_webapi_async src/gemiterm/__main__.py
|
|
58
|
+
|
|
59
|
+
- name: Verify build
|
|
60
|
+
run: |
|
|
61
|
+
exeSize=$(stat -c%s dist/GemiTerm)
|
|
62
|
+
exeSizeMB=$((exeSize / 1024 / 1024))
|
|
63
|
+
echo "GemiTerm size: $exeSizeMB MB"
|
|
64
|
+
if [ "$exeSizeMB" -lt 20 ]; then
|
|
65
|
+
echo "ERROR: Exe is too small ($exeSizeMB MB). Dependencies may not be bundled."
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
echo "Build verification passed"
|
|
69
|
+
|
|
70
|
+
- name: Upload artifact
|
|
71
|
+
uses: actions/upload-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: GemiTerm
|
|
74
|
+
path: dist/GemiTerm
|
|
75
|
+
|
|
76
|
+
build-windows:
|
|
77
|
+
name: Build (Windows)
|
|
78
|
+
needs: test
|
|
79
|
+
runs-on: windows-latest
|
|
80
|
+
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
- uses: actions/setup-python@v5
|
|
84
|
+
with:
|
|
85
|
+
python-version: '3.12'
|
|
86
|
+
|
|
87
|
+
- name: Build package
|
|
88
|
+
run: pip install build && python -m build
|
|
89
|
+
|
|
90
|
+
- name: Install dependencies
|
|
91
|
+
run: pip install rich click playwright gemini-webapi pyinstaller
|
|
92
|
+
|
|
93
|
+
- name: Build executable
|
|
94
|
+
run: |
|
|
95
|
+
$pythonPath = python -c "import site; print(site.getsitepackages()[0])"
|
|
96
|
+
pyinstaller --onefile --name GemiTerm --add-data "src/gemiterm;gemiterm" --paths "$pythonPath" --hidden-import=rich --hidden-import=rich.console --hidden-import=rich.progress --hidden-import=rich.table --hidden-import=rich.panel --hidden-import=rich.markdown --hidden-import=rich.syntax --hidden-import=click --hidden-import=playwright --hidden-import=gemini_webapi --hidden-import=gemini_webapi_async src/gemiterm/__main__.py
|
|
97
|
+
|
|
98
|
+
- name: Verify build
|
|
99
|
+
run: |
|
|
100
|
+
$exeSize = (Get-Item dist/GemiTerm.exe).Length / 1MB
|
|
101
|
+
Write-Host "GemiTerm.exe size: $exeSize MB"
|
|
102
|
+
if ($exeSize -lt 20) {
|
|
103
|
+
Write-Host "ERROR: Exe is too small ($exeSize MB). Dependencies may not be bundled."
|
|
104
|
+
exit 1
|
|
105
|
+
}
|
|
106
|
+
Write-Host "Build verification passed"
|
|
107
|
+
|
|
108
|
+
- name: Upload artifact
|
|
109
|
+
uses: actions/upload-artifact@v4
|
|
110
|
+
with:
|
|
111
|
+
name: GemiTerm.exe
|
|
112
|
+
path: dist/GemiTerm.exe
|
|
113
|
+
|
|
114
|
+
publish:
|
|
115
|
+
name: Publish to PyPI
|
|
116
|
+
needs: [build-linux, build-windows]
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.skip_publish) }}
|
|
119
|
+
permissions:
|
|
120
|
+
id-token: write
|
|
121
|
+
contents: read
|
|
122
|
+
|
|
123
|
+
steps:
|
|
124
|
+
- uses: actions/checkout@v4
|
|
125
|
+
|
|
126
|
+
- uses: actions/setup-python@v5
|
|
127
|
+
with:
|
|
128
|
+
python-version: '3.12'
|
|
129
|
+
|
|
130
|
+
- name: Build package
|
|
131
|
+
run: pip install build && python -m build
|
|
132
|
+
|
|
133
|
+
- name: Publish to PyPI
|
|
134
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
135
|
+
with:
|
|
136
|
+
password: ${{ secrets.OIDC_PYPI_TOKEN }}
|
|
137
|
+
|
|
138
|
+
release:
|
|
139
|
+
name: Create Release
|
|
140
|
+
needs: [build-linux, build-windows]
|
|
141
|
+
runs-on: ubuntu-latest
|
|
142
|
+
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.skip_release) }}
|
|
143
|
+
permissions:
|
|
144
|
+
contents: write
|
|
145
|
+
|
|
146
|
+
steps:
|
|
147
|
+
- uses: actions/checkout@v4
|
|
148
|
+
|
|
149
|
+
- name: Download Linux binary
|
|
150
|
+
uses: actions/download-artifact@v4
|
|
151
|
+
with:
|
|
152
|
+
name: GemiTerm
|
|
153
|
+
path: dist
|
|
154
|
+
|
|
155
|
+
- name: Download Windows binary
|
|
156
|
+
uses: actions/download-artifact@v4
|
|
157
|
+
with:
|
|
158
|
+
name: GemiTerm.exe
|
|
159
|
+
path: dist
|
|
160
|
+
|
|
161
|
+
- name: Determine tag
|
|
162
|
+
id: tag
|
|
163
|
+
run: |
|
|
164
|
+
if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.tag }}" != "" ]; then
|
|
165
|
+
echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT
|
|
166
|
+
else
|
|
167
|
+
echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
- name: Create Release
|
|
171
|
+
uses: softprops/action-gh-release@v2
|
|
172
|
+
with:
|
|
173
|
+
tag_name: ${{ steps.tag.outputs.tag }}
|
|
174
|
+
files: dist/*
|
|
175
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"conversation_id": "sample_conversation_456",
|
|
3
|
+
"title": "API Design Discussion",
|
|
4
|
+
"export_date": "2026-03-21T15:00:00",
|
|
5
|
+
"metadata": {
|
|
6
|
+
"message_count": 4,
|
|
7
|
+
"first_message": "2026-03-21T14:45:00",
|
|
8
|
+
"last_message": "2026-03-21T15:00:00"
|
|
9
|
+
},
|
|
10
|
+
"messages": [
|
|
11
|
+
{
|
|
12
|
+
"role": "user",
|
|
13
|
+
"content": "What are the best practices for designing a REST API?",
|
|
14
|
+
"timestamp": "2026-03-21T14:45:00"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"role": "model",
|
|
18
|
+
"content": "Here are the key REST API best practices:\n\n## 1. Use Proper HTTP Methods\n\n| Method | Usage |\n|--------|-------|\n| GET | Retrieve resources |\n| POST | Create new resources |\n| PUT | Update entire resources |\n| PATCH | Partial updates |\n| DELETE | Remove resources |\n\n## 2. Use Nouns for Endpoints\n\n```\n# Good\nGET /users\nGET /users/123\n\n# Avoid\nGET /getUsers\nGET /user/123\n```\n\n## 3. Use Proper Status Codes\n\n- 200 OK - Success\n- 201 Created - Resource created\n- 400 Bad Request - Invalid input\n- 401 Unauthorized - Not authenticated\n- 404 Not Found - Resource doesn't exist\n- 500 Internal Server Error - Server issue",
|
|
19
|
+
"timestamp": "2026-03-21T14:46:30"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"role": "user",
|
|
23
|
+
"content": "How should we handle pagination?",
|
|
24
|
+
"timestamp": "2026-03-21T14:50:00"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"role": "model",
|
|
28
|
+
"content": "For pagination, I recommend cursor-based pagination for large datasets:\n\n```json\n{\n \"data\": [...],\n \"pagination\": {\n \"next_cursor\": \"eyJpZCI6MTIzfQ==\",\n \"has_more\": true,\n \"total_count\": 1042\n }\n}\n```\n\n## Comparison\n\n| Type | Pros | Cons |\n|------|------|------|\n| Offset | Simple, random access | Performance issues at scale |\n| Cursor | Efficient, consistent | No random access |\n| Page | Familiar to users | Inflexible |\n\nUse cursor-based pagination when:\n- Dealing with large datasets (millions of rows)\n- Real-time data where offset skips items\n- Infinite scroll interfaces\n\nUse offset pagination when:\n- Small datasets\n- User needs to jump to specific pages\n- Analytics or reporting use cases",
|
|
29
|
+
"timestamp": "2026-03-21T15:00:00"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|