gm-oc 2.0.394 → 2.0.395

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-oc",
3
- "version": "2.0.394",
3
+ "version": "2.0.395",
4
4
  "description": "State machine agent with hooks, skills, and automated git enforcement",
5
5
  "author": "AnEntrypoint",
6
6
  "license": "MIT",
@@ -10,10 +10,20 @@ allowed-tools: Bash(browser:*), Bash(exec:browser*)
10
10
 
11
11
  **Session commands** (`browser:` prefix) — manage multi-step sessions via playwriter CLI. Each `browser:` block runs its commands sequentially.
12
12
 
13
- **JS execution** (`exec:browser`) — run JavaScript directly against `page`. State persists across calls.
13
+ **JS execution** (`exec:browser`) — run JavaScript directly against `page`. State persists across calls via `state` global.
14
14
 
15
15
  **CRITICAL**: Never mix these two pathways. Each `browser:` block is a separate Bash call. Each `exec:browser` block is a separate Bash call.
16
16
 
17
+ ## 15-Second Ceiling — How It Works
18
+
19
+ Every `exec:browser` call has a 15s live window. During that window, all stdout/stderr is streamed to you in real time. After 15s the task backgrounds and you receive:
20
+ - All output produced so far (live drain)
21
+ - A task ID with `plugkit sleep/status/close` instructions
22
+
23
+ **The task keeps running.** Every subsequent plugkit interaction automatically drains all running browser tasks — you will see new output without asking.
24
+
25
+ **Never use `await new Promise(r => setTimeout(r, N))` with N > 10000.** Use short poll loops instead (see patterns below).
26
+
17
27
  ## Session Pathway (`browser:`)
18
28
 
19
29
  Create a session first, use `--direct` for CDP mode (requires Chrome with remote debugging):
@@ -83,14 +93,55 @@ Never add shell quoting — write plain JavaScript directly.
83
93
 
84
94
  ## Core Workflow
85
95
 
86
- 1. **Create session**: `browser:\nplaywriter session new --direct`
87
- 2. **Navigate** (one call per command): `browser:\nplaywriter -s 1 -e 'await page.goto("url")'`
88
- 3. **Snapshot**: `browser:\nplaywriter -s 1 -e 'await snapshot({ page })'`
89
- 4. **Interact**: click, fill, type — each as a separate browser: call
90
- 5. **Extract data**: use `exec:browser` for JS queries
96
+ 1. **Navigate**: `exec:browser\nawait page.goto('url')` — session auto-created on first call
97
+ 2. **Snapshot**: `exec:browser\nawait snapshot({ page })`
98
+ 3. **Interact**: click, fill, type in subsequent `exec:browser` calls
99
+ 4. **Extract data**: `exec:browser\nconsole.log(await page.evaluate(() => document.title))`
100
+
101
+ ## Long-Running Operations — Poll Pattern
102
+
103
+ For operations that take >10s (model loading, network fetches, animations):
104
+
105
+ **Step 1** — set up listener and kick off the operation:
106
+ ```
107
+ exec:browser
108
+ state.done = false
109
+ state.result = null
110
+ page.on('console', msg => {
111
+ const t = msg.text()
112
+ if (t.includes('loaded') || t.includes('ready')) { state.done = true; state.result = t }
113
+ })
114
+ await page.click('#start-button')
115
+ console.log('started, waiting...')
116
+ ```
117
+
118
+ **Step 2** — poll in short bursts (this will background after 15s and keep draining):
119
+ ```
120
+ exec:browser
121
+ const start = Date.now()
122
+ while (!state.done && Date.now() - start < 12000) {
123
+ await new Promise(r => setTimeout(r, 500))
124
+ }
125
+ console.log('done:', state.done, 'result:', state.result)
126
+ ```
127
+
128
+ If step 2 backgrounds (takes >15s), every subsequent plugkit call will drain its output automatically. When you see the result in the drain log, close the task:
129
+ ```
130
+ exec:close
131
+ task_N
132
+ ```
91
133
 
92
134
  ## Common Patterns
93
135
 
136
+ ### Navigate and check current URL/status
137
+
138
+ ```
139
+ exec:browser
140
+ await page.goto('https://example.com')
141
+ console.log('URL:', page.url())
142
+ console.log('title:', await page.title())
143
+ ```
144
+
94
145
  ### Screenshot
95
146
 
96
147
  ```
@@ -98,7 +149,7 @@ browser:
98
149
  playwriter -s 1 -e 'await screenshotWithAccessibilityLabels({ page })'
99
150
  ```
100
151
 
101
- ### Data Extraction (use exec:browser)
152
+ ### Data Extraction
102
153
 
103
154
  ```
104
155
  exec:browser
@@ -106,35 +157,24 @@ const items = await page.$$eval('.product-title', els => els.map(e => e.textCont
106
157
  console.log(JSON.stringify(items))
107
158
  ```
108
159
 
109
- ### Console Monitoring (exec:browser)
160
+ ### Console Monitoring — set up listener first, then poll
110
161
 
111
162
  ```
112
163
  exec:browser
113
- state.consoleMsgs = []
114
- page.on('console', msg => state.consoleMsgs.push({ type: msg.type(), text: msg.text() }))
115
- page.on('pageerror', e => state.consoleMsgs.push({ type: 'error', text: e.message }))
164
+ state.logs = []
165
+ state.errors = []
166
+ page.on('console', msg => state.logs.push({ type: msg.type(), text: msg.text() }))
167
+ page.on('pageerror', e => state.errors.push(e.message))
168
+ console.log('listeners attached')
116
169
  ```
117
170
 
118
171
  ```
119
172
  exec:browser
120
- console.log(JSON.stringify(state.consoleMsgs))
173
+ console.log('logs so far:', JSON.stringify(state.logs.slice(-20)))
174
+ console.log('errors:', JSON.stringify(state.errors))
121
175
  ```
122
176
 
123
- ### Web Worker Console Monitoring
124
-
125
- ```
126
- exec:browser
127
- state.workerMsgs = []
128
- for (const w of page.workers()) {
129
- w.evaluate(() => {
130
- const o = console.log.bind(console)
131
- console.log = (...a) => { o(...a) }
132
- }).catch(() => {})
133
- }
134
- page.on('worker', w => {
135
- state.workerMsgs.push('[worker] ' + w.url())
136
- })
137
- ```
177
+ ### Web Worker Access
138
178
 
139
179
  ```
140
180
  exec:browser
@@ -150,7 +190,7 @@ if (page.workers().length > 0) {
150
190
  }
151
191
  ```
152
192
 
153
- ### Access window.debug globals
193
+ ### Access window globals
154
194
 
155
195
  ```
156
196
  exec:browser
@@ -161,10 +201,24 @@ const result = await page.evaluate(() => JSON.stringify({
161
201
  console.log(result)
162
202
  ```
163
203
 
204
+ ### Wait for element with short poll
205
+
206
+ ```
207
+ exec:browser
208
+ const start = Date.now()
209
+ while (Date.now() - start < 12000) {
210
+ const el = await page.$('#status')
211
+ if (el) { console.log('found:', await el.textContent()); break }
212
+ await new Promise(r => setTimeout(r, 300))
213
+ }
214
+ ```
215
+
164
216
  ## Key Rules
165
217
 
166
218
  - `browser:` prefix → playwriter session management (one command per block)
167
- - `exec:browser` → JS in page context (multi-line JS allowed)
219
+ - `exec:browser` → JS in page context (multi-line JS allowed, 15s live window)
168
220
  - Never mix pathways in the same Bash call
169
221
  - `-e` argument: single quotes on outside, double quotes inside for JS strings
170
222
  - One `playwriter` command per `browser:` block
223
+ - Never `await setTimeout(N)` with N > 10000 — use short poll loops instead
224
+ - All running browser tasks drain automatically on every plugkit interaction