gm-skill 2.0.1618 → 2.0.1620
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.
|
@@ -26,7 +26,7 @@ capture\n<expression>
|
|
|
26
26
|
profile\n<expression>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
**Open on the page you want to test, not a blank one.** A bare `https://...` URL body navigates the session straight to that page and returns `{url, title}` -- the simplest "show me this page." `url=<url>\n<expression>` navigates first, then runs your expression on the loaded page, so the global/DOM you assert is already there in one dispatch instead of a blank surface you must `page.goto` yourself. `url=` composes with `timeout=` and `capture` -- stack the prefix lines in order `timeout=`, then `url=`, then `capture`, the expression last; the prepended `page.goto` rides inside the capture so its navigation console/network is captured too. A bare expression with no URL prefix
|
|
29
|
+
**Open on the page you want to test, not a blank one.** A bare `https://...` URL body navigates the session straight to that page and returns `{url, title}` -- the simplest "show me this page." `url=<url>\n<expression>` navigates first, then runs your expression on the loaded page, so the global/DOM you assert is already there in one dispatch instead of a blank surface you must `page.goto` yourself. `url=` composes with `timeout=` and `capture` -- stack the prefix lines in order `timeout=`, then `url=`, then `capture`, the expression last; the prepended `page.goto` rides inside the capture so its navigation console/network is captured too. A bare expression with no `url=`/bare-URL prefix runs against whatever the session is already on -- a never-navigated session is on `about:blank`, so the expression evaluates an empty page and the envelope comes back with `landed_on_blank: true` and a `hint` telling you to add `url=`; navigate first and the surprise never happens. `session new` returns the id you carry. (`session close` and `session kill` are aliases.) Default per-eval timeout 120000ms; operations that legitimately exceed it prefix `timeout=<ms>\n` (wrapper clamps to 120000ms). The response carries `timeout_ms_used`; `browser.runner-timeout` fires at the cap -- read `stderr`, narrow or raise, never retry blind at the same budget.
|
|
30
30
|
|
|
31
31
|
**`capture\n<expression>` is the zero-boilerplate debug path -- prefer it.** Prefix your script with `capture` (or `profile`) on its own line and the wrapper auto-attaches `page.on('console'|'pageerror'|'requestfinished')` before your code runs, runs your script in an async wrapper (your top-level `await`/`return` work unchanged), and returns `{result: <your return>, debug: {console, pageErrors, network, performance}}` -- page console logs, uncaught errors, per-request network timing, and navigation performance, captured for free. Combine with timeout via `timeout=<ms>\ncapture\n<expr>`. Use the bare expression only when you do not want the capture overhead.
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ profile\n<expression>
|
|
|
34
34
|
|
|
35
35
|
## Envelope
|
|
36
36
|
|
|
37
|
-
`{ok, stdout, stderr, exit_code, session_id?}`. `stdout` = stringified eval result; `stderr` = page errors + launch diagnostics; `exit_code` non-zero = the dispatch did not land -- read `stderr` and re-dispatch, never blind.
|
|
37
|
+
`{ok, stdout, stderr, exit_code, session_id?, navigation_requested, landed_on_blank?, hint?}`. `stdout` = stringified eval result; `stderr` = page errors + launch diagnostics; `exit_code` non-zero = the dispatch did not land -- read `stderr` and re-dispatch, never blind. `navigation_requested` reflects whether the dispatch carried a `url=`/bare-URL navigation; `landed_on_blank: true` with a `hint` means the expression ran against `about:blank` -- prefix `url=<target>` and re-dispatch.
|
|
38
38
|
|
|
39
39
|
## Headed by default
|
|
40
40
|
|
package/gm-plugkit/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-plugkit",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1620",
|
|
4
4
|
"description": "Bootstrap and daemon-spawn tool for gm plugkit binary. Downloads the correct platform binary, verifies SHA256, and starts the spool watcher daemon. Includes plugkit-wasm-wrapper for WASM-based spool watching.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -1062,6 +1062,13 @@ function startManagedBrowser(pw, profileDir) {
|
|
|
1062
1062
|
'--disable-default-apps',
|
|
1063
1063
|
'--disable-gpu-process-crash-limit',
|
|
1064
1064
|
];
|
|
1065
|
+
// In containers where unprivileged user namespaces are disabled, Chromium's
|
|
1066
|
+
// sandbox cannot initialize and the remote-debugging port never binds (the CDP
|
|
1067
|
+
// "did not become ready" failure). Opt in to running without the sandbox (plus
|
|
1068
|
+
// the small-/dev/shm workaround common in containers) via GM_BROWSER_NO_SANDBOX=1.
|
|
1069
|
+
if (process.env.GM_BROWSER_NO_SANDBOX === '1') {
|
|
1070
|
+
args.push('--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage');
|
|
1071
|
+
}
|
|
1065
1072
|
if (headless) {
|
|
1066
1073
|
args.push('--headless=new');
|
|
1067
1074
|
} else {
|
|
@@ -2120,6 +2127,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
2120
2127
|
+ `page.on('pageerror',e=>{try{__errs.push(String(e&&e.message||e));}catch(_){}});`
|
|
2121
2128
|
+ `page.on('requestfinished',r=>{try{const t=r.timing();__net.push({url:String(r.url()).slice(0,120),dur_ms:Math.round(t.responseEnd),ttfb_ms:Math.round(t.responseStart)});}catch(_){}});}catch(_){}\n`;
|
|
2122
2129
|
const perfRead = `let __perf=null;try{__perf=await page.evaluate(()=>{const n=performance.getEntriesByType('navigation')[0];return n?{load_ms:Math.round(n.loadEventEnd||0),dcl_ms:Math.round(n.domContentLoadedEventEnd||0),resources:performance.getEntriesByType('resource').length,now:Math.round(performance.now())}:null;});}catch(_){}\n`;
|
|
2130
|
+
const blankProbe = startUrl ? '' : `try{const __u=page.url();if(__u==='about:blank'||__u===''){console.error('__GM_BLANK__');}}catch(_){}\n`;
|
|
2123
2131
|
if (modeMatch && modeMatch[1] === 'profile') {
|
|
2124
2132
|
const userScript = modeMatch[2];
|
|
2125
2133
|
const intervalUs = 100;
|
|
@@ -2127,7 +2135,7 @@ function makeHostFunctions(instanceRef) {
|
|
|
2127
2135
|
+ `let __profile=null,__profileError=null;\n`
|
|
2128
2136
|
+ `let __cdp=null;\n`
|
|
2129
2137
|
+ `try{__cdp=await page.context().newCDPSession(page);await __cdp.send('Profiler.enable');await __cdp.send('Profiler.setSamplingInterval',{interval:${intervalUs}});await __cdp.send('Profiler.start');}catch(e){__profileError=String(e&&e.message||e);__cdp=null;}\n`
|
|
2130
|
-
+ `const __result = await (async () => {\n${gotoPrefix}${userScript}\n})();\n`
|
|
2138
|
+
+ `const __result = await (async () => {\n${blankProbe}${gotoPrefix}${userScript}\n})();\n`
|
|
2131
2139
|
+ `if(__cdp){try{const __r=await __cdp.send('Profiler.stop');__profile=__r&&__r.profile||null;}catch(e){__profileError=String(e&&e.message||e);}}\n`
|
|
2132
2140
|
+ perfRead
|
|
2133
2141
|
+ AGGREGATE_CPU_PROFILE_SRC + `\n`
|
|
@@ -2136,11 +2144,13 @@ function makeHostFunctions(instanceRef) {
|
|
|
2136
2144
|
} else if (modeMatch && modeMatch[1] === 'capture') {
|
|
2137
2145
|
const userScript = modeMatch[2];
|
|
2138
2146
|
evalBody = debugSetup
|
|
2139
|
-
+ `const __result = await (async () => {\n${gotoPrefix}${userScript}\n})();\n`
|
|
2147
|
+
+ `const __result = await (async () => {\n${blankProbe}${gotoPrefix}${userScript}\n})();\n`
|
|
2140
2148
|
+ perfRead
|
|
2141
2149
|
+ `return {result:__result,debug:{console:__logs,pageErrors:__errs,network:__net.slice(0,30),performance:__perf}};`;
|
|
2142
2150
|
} else if (startUrl) {
|
|
2143
2151
|
evalBody = `${gotoPrefix}${evalBody}`;
|
|
2152
|
+
} else if (blankProbe) {
|
|
2153
|
+
evalBody = `${blankProbe}${evalBody}`;
|
|
2144
2154
|
}
|
|
2145
2155
|
const outerTimeoutMs = Math.min(timeoutMs + 6000, 126000);
|
|
2146
2156
|
const r = runBrowserRunner(pw, ['-s', pwSessionId, '--timeout', String(timeoutMs), '-e', evalBody], outerTimeoutMs, cwd, sessionId);
|
|
@@ -2148,14 +2158,22 @@ function makeHostFunctions(instanceRef) {
|
|
|
2148
2158
|
if (!ok && r.status === null) {
|
|
2149
2159
|
logEvent('plugkit', 'browser.runner-timeout', { session_id: pwSessionId, timeout_ms: timeoutMs, body_bytes: evalBody.length });
|
|
2150
2160
|
}
|
|
2151
|
-
|
|
2161
|
+
const rawStderr = r.stderr || '';
|
|
2162
|
+
const landedOnBlank = !startUrl && rawStderr.includes('__GM_BLANK__');
|
|
2163
|
+
const envelope = {
|
|
2152
2164
|
ok,
|
|
2153
2165
|
stdout: scrubBrowserRunnerText(r.stdout || ''),
|
|
2154
|
-
stderr: scrubBrowserRunnerText(r
|
|
2166
|
+
stderr: scrubBrowserRunnerText(rawStderr.replace(/^__GM_BLANK__\r?\n?/gm, '')),
|
|
2155
2167
|
exit_code: r.status === null ? -1 : r.status,
|
|
2156
2168
|
session_id: pwSessionId,
|
|
2157
2169
|
timeout_ms_used: timeoutMs,
|
|
2158
|
-
}
|
|
2170
|
+
};
|
|
2171
|
+
envelope.navigation_requested = !!startUrl;
|
|
2172
|
+
if (landedOnBlank) {
|
|
2173
|
+
envelope.landed_on_blank = true;
|
|
2174
|
+
envelope.hint = "page is about:blank: this dispatch did not navigate, so the expression evaluated against an empty page. Prefix the body with 'url=<target>' (or send a bare 'https://...' URL) to open the page you want before evaluating.";
|
|
2175
|
+
}
|
|
2176
|
+
return writeWasmJson(instanceRef.value, envelope);
|
|
2159
2177
|
} catch (e) {
|
|
2160
2178
|
return writeWasmJson(instanceRef.value, { ok: false, error: scrubBrowserRunnerText(e.message) });
|
|
2161
2179
|
}
|
package/gm.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gm-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1620",
|
|
4
4
|
"description": "Canonical universal harness — AI-native software engineering via skill-driven orchestration; bootstraps plugkit for task execution and session isolation. Install in any AI coding agent host.",
|
|
5
5
|
"author": "AnEntrypoint",
|
|
6
6
|
"license": "MIT",
|