jorgex-stack 1.9.31 → 1.9.32
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 +6 -3
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +165 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,7 +120,7 @@ pnpm dlx jorgex-stack@1.9.7 sync --agents pi
|
|
|
120
120
|
pnpm dlx jorgex-stack@1.9.7 uninstall --agents pi
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
Stack downloads the frozen registry tarball, verifies its exact size plus SHA-256/SHA-512, backs up Pi's `settings.json`, and only then asks Pi to install that local file. The historical `0.8.0` tarball was `89128340` bytes; the exact adopted artifact and integrity values are authoritative in `src/lib/pi-runtime-pin.json`, while the lifecycle remains authoritative in `src/lib/pi-runtime.ts`. Pi's own package-manager invocation is the narrow runtime exception to the repository's pnpm-only rule; the Stack lifecycle never launches npm directly. After the package is healthy, Stack projects the shared resources into Pi: marked `jorgex:system-prompt` and `jorgex:engram-protocol` sections in `~/.pi/agent/AGENTS.md`, canonical skills under `~/.agents/skills`, and `~/.pi/agent/prompts/lean-audit.md`. When the managed Playwright preference is active, the projection also adds or removes the marked `jorgex:browser` section dynamically. The Pi
|
|
123
|
+
Stack downloads the frozen registry tarball, verifies its exact size plus SHA-256/SHA-512, backs up Pi's `settings.json`, and only then asks Pi to install that local file. The historical `0.8.0` tarball was `89128340` bytes; the exact adopted artifact and integrity values are authoritative in `src/lib/pi-runtime-pin.json`, while the lifecycle remains authoritative in `src/lib/pi-runtime.ts`. Pi's own package-manager invocation is the narrow runtime exception to the repository's pnpm-only rule; the Stack lifecycle never launches npm directly. After the package is healthy, Stack projects the shared resources into Pi: marked `jorgex:system-prompt` and `jorgex:engram-protocol` sections in `~/.pi/agent/AGENTS.md`, canonical skills under `~/.agents/skills`, and `~/.pi/agent/prompts/lean-audit.md`. When the managed Playwright preference is active, the projection also adds or removes the marked `jorgex:browser` section dynamically. The global Playwright package and Chromium cache are shared by the machine; `--playwright-runtimes` controls which runtime receives the guide. Pi is selectable only when the adopted package declares `playwright-handoff-v1`; otherwise Stack reports that it can install the global capability but cannot project it into Pi yet. The adopted Pi `0.8.13` candidate also supports the optional Chrome DevTools handoff; Stack persists the selected handoff as part of the Pi projection and records its SHA-256 in the optional `devtools.sha256` field of `~/.jorgex-stack/pi-projection-receipt.json` after a successful operation. Context7 remains outside the Pi scope. The published `1.9.7` entry `{ "source": "npm:jorgex-pi@0.8.4", "skills": [], "prompts": [] }` and the `0.8.5` snapshot reference are historical; they do not describe the adopted pin. Filters are applied only after this projection exists, so the package does not duplicate shared resources. Package ownership is recorded separately in `~/.jorgex-stack/pi-receipt.json`; projection ownership is recorded in `~/.jorgex-stack/pi-projection-receipt.json`. Package receipts reject manual, duplicate, divergent, partial, corrupt, copied-to-another-scope, or unknown-history state. Projection cleanup requires an exact scope-bound ownership receipt; DevTools conflicts preserve the handoff for review.
|
|
124
124
|
|
|
125
125
|
Historically, the published Pi 0.8.0 direct-package snapshot added `work-audit`: the snapshot grew from **17 to 18 skill trees** (96 to 97 files), and the active runtime allowlist grew from **16 to 17 skills**. The historical Pi 0.8.5 snapshot reference records 18 skill trees and 98 files; it does not describe the adopted pin. Reference F2-A is included while the private F1 skills remain preserved. `playwright-cli` remains in the snapshot but inactive because browser automation is a separate opt-in integration.
|
|
126
126
|
|
|
@@ -156,6 +156,9 @@ pnpm dlx jorgex-stack install
|
|
|
156
156
|
# Non-interactive / agent: --playwright authorizes the global install.
|
|
157
157
|
pnpm dlx jorgex-stack install --yes --playwright
|
|
158
158
|
|
|
159
|
+
# Instala el paquete compartido y activa la guía solo en estos runtimes.
|
|
160
|
+
pnpm dlx jorgex-stack install --playwright --playwright-runtimes=opencode,claude-code
|
|
161
|
+
|
|
159
162
|
# Enable Chrome DevTools MCP explicitly per runtime.
|
|
160
163
|
pnpm dlx jorgex-stack install --devtools
|
|
161
164
|
pnpm dlx jorgex-stack install --no-devtools
|
|
@@ -163,7 +166,7 @@ pnpm dlx jorgex-stack install --agents pi --devtools
|
|
|
163
166
|
pnpm dlx jorgex-stack sync --agents pi --no-devtools
|
|
164
167
|
```
|
|
165
168
|
|
|
166
|
-
Under the hood, `--playwright` runs two `pnpm` argv-only plans back to back: `pnpm add --global @playwright/cli@0.1.18` (the package) and then `pnpm dlx @playwright/cli@0.1.18 install-browser` (the
|
|
169
|
+
Under the hood, `--playwright` runs two `pnpm` argv-only plans back to back: `pnpm add --global @playwright/cli@0.1.18` (the package) and then `pnpm dlx @playwright/cli@0.1.18 install-browser chromium` (the Chromium cache). It then verifies that the pinned package launches Chromium headless against `about:blank`. Removal is `pnpm remove --global @playwright/cli` (no version suffix). If installation fails, the error identifies the failed phase — global package, browser download, browser launch, or preference persistence — and recommends `jorgex-stack install --playwright`; the preference is not marked enabled unless the complete plan succeeds.
|
|
167
170
|
|
|
168
171
|
Daily operation:
|
|
169
172
|
|
|
@@ -179,7 +182,7 @@ Daily operation:
|
|
|
179
182
|
|
|
180
183
|
1. **Stack** (jorgex-stack): detects whether it is a git clone or a global install, then offers an update with confirmation.
|
|
181
184
|
2. **Engram** (binary): detects the installed version and offers an update through the **native channel** (brew -> `go install` -> release URL). Nothing needs to be stopped: as in upstream macOS/Linux, live processes keep using the old version until clients restart; on Windows, the in-use `.exe` is rotated by rename before installation. **Automatic DB backup before updating**. The database and memories are never touched.
|
|
182
|
-
3. **Playwright CLI** (only when explicitly enabled): compares the detected binary with the approved bundle pin and offers to realign it with explicit confirmation. The realignment re-applies **both** plans — `pnpm add --global @playwright/cli@0.1.18` (package) and `pnpm dlx @playwright/cli@0.1.18 install-browser` (
|
|
185
|
+
3. **Playwright CLI** (only when explicitly enabled): compares the detected binary with the approved bundle pin and offers to realign it with explicit confirmation. The realignment re-applies **both** plans — `pnpm add --global @playwright/cli@0.1.18` (package) and `pnpm dlx @playwright/cli@0.1.18 install-browser chromium` (Chromium cache) — and fails closed if either step returns non-zero. The error identifies whether the package-update or browser-download phase failed and recommends `jorgex-stack install --playwright` to retry both; a Playwright update does not require `sync`.
|
|
183
186
|
4. **Vendored skills** (maintainer only): third-party skills ship **pinned** with the stack version, so the installed package never reaches out to their upstreams. Only when running from a git clone (`pnpm cli update`) does `update` scan the upstreams in `upstreams.json`, download to a temp directory, **show a mandatory diff**, and ask for confirmation. A moved upstream is only a candidate until that review is accepted and a deliberate re-pin is made for a future release; it is never treated as an accepted official update automatically. Skills with local changes (`modified: true`) warn and require double confirmation.
|
|
184
187
|
|
|
185
188
|
Usage:
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -2165,6 +2165,8 @@ function resolvePnpmFailureRemedy(reason) {
|
|
|
2165
2165
|
return PNPM_GLOBAL_BIN_REMEDY;
|
|
2166
2166
|
case "action-failed":
|
|
2167
2167
|
return null;
|
|
2168
|
+
case "browser-launch":
|
|
2169
|
+
return "Chromium se descarg\xF3, pero no ha podido arrancar. Revisa el error de lanzamiento y las dependencias de tu sistema antes de reintentar.";
|
|
2168
2170
|
}
|
|
2169
2171
|
}
|
|
2170
2172
|
function hasNonzeroProcessStatus(error) {
|
|
@@ -2186,6 +2188,18 @@ function resolvePlaywrightCliState({ binPath, versionOutput }) {
|
|
|
2186
2188
|
}
|
|
2187
2189
|
function detectPlaywrightCli() {
|
|
2188
2190
|
const binPath = lookPath(PLAYWRIGHT_CLI.bin);
|
|
2191
|
+
if (binPath === null) {
|
|
2192
|
+
const pnpmHome = resolvePnpmHome();
|
|
2193
|
+
const name = process.platform === "win32" ? `${PLAYWRIGHT_CLI.bin}.cmd` : PLAYWRIGHT_CLI.bin;
|
|
2194
|
+
const known = [path18.join(pnpmHome, name), path18.join(pnpmHome, "bin", name)].find((file) => {
|
|
2195
|
+
try {
|
|
2196
|
+
return fs13.statSync(file).isFile();
|
|
2197
|
+
} catch {
|
|
2198
|
+
return false;
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
if (known) return { status: "not-in-path", binPath: known, detectedVersion: null };
|
|
2202
|
+
}
|
|
2189
2203
|
return resolvePlaywrightCliState({
|
|
2190
2204
|
binPath,
|
|
2191
2205
|
versionOutput: binPath ? runDetectedBin(binPath, ["--version"], 5e3, { NO_UPDATE_NOTIFIER: "1" }) : null
|
|
@@ -2248,7 +2262,44 @@ function planPlaywrightCliCommand(action, pnpmBin) {
|
|
|
2248
2262
|
case "remove":
|
|
2249
2263
|
return { command: pnpmBin, args: ["remove", "--global", PLAYWRIGHT_CLI.packageName] };
|
|
2250
2264
|
case "install-browser":
|
|
2251
|
-
return { command: pnpmBin, args: ["dlx", pinnedPackage, PLAYWRIGHT_CLI.browserInstallAction] };
|
|
2265
|
+
return { command: pnpmBin, args: ["dlx", pinnedPackage, PLAYWRIGHT_CLI.browserInstallAction, "chromium"] };
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
function verifyPlaywrightBrowser(pnpmBin, env = process.env, cwd) {
|
|
2269
|
+
const rootCommand = planDetectedBinCommand(pnpmBin, ["root", "--global"]);
|
|
2270
|
+
if (rootCommand === null) return false;
|
|
2271
|
+
try {
|
|
2272
|
+
const root = execFileSync2(rootCommand.command, rootCommand.args, {
|
|
2273
|
+
encoding: "utf8",
|
|
2274
|
+
timeout: 5e3,
|
|
2275
|
+
env,
|
|
2276
|
+
cwd,
|
|
2277
|
+
stdio: ["ignore", "pipe", "inherit"]
|
|
2278
|
+
}).trim();
|
|
2279
|
+
if (!path18.isAbsolute(root)) return false;
|
|
2280
|
+
const packageFile = fs13.realpathSync(path18.join(root, "@playwright", "cli", "package.json"));
|
|
2281
|
+
const installed = JSON.parse(fs13.readFileSync(packageFile, "utf8"));
|
|
2282
|
+
if (installed.name !== PLAYWRIGHT_CLI.packageName || installed.version !== PLAYWRIGHT_CLI.version) return false;
|
|
2283
|
+
const probe = `
|
|
2284
|
+
const { createRequire } = require('node:module');
|
|
2285
|
+
const { chromium } = createRequire(process.argv[1])('playwright');
|
|
2286
|
+
(async () => {
|
|
2287
|
+
const browser = await chromium.launch({ headless: true, timeout: 15000 });
|
|
2288
|
+
try {
|
|
2289
|
+
const page = await browser.newPage();
|
|
2290
|
+
await page.goto('about:blank', { timeout: 5000 });
|
|
2291
|
+
} finally { await browser.close(); }
|
|
2292
|
+
})().catch(error => { console.error(error.message); process.exitCode = 1; });
|
|
2293
|
+
`;
|
|
2294
|
+
execFileSync2(process.execPath, ["-e", probe, packageFile], {
|
|
2295
|
+
timeout: 25e3,
|
|
2296
|
+
stdio: "inherit",
|
|
2297
|
+
cwd,
|
|
2298
|
+
env: { ...env, NO_UPDATE_NOTIFIER: "1" }
|
|
2299
|
+
});
|
|
2300
|
+
return true;
|
|
2301
|
+
} catch {
|
|
2302
|
+
return false;
|
|
2252
2303
|
}
|
|
2253
2304
|
}
|
|
2254
2305
|
function executePlaywrightToolAction(action, pnpmBin = resolvePnpmBin(), env) {
|
|
@@ -2270,14 +2321,22 @@ function executePlaywrightToolAction(action, pnpmBin = resolvePnpmBin(), env) {
|
|
|
2270
2321
|
const command = planPlaywrightCliCommand(action, pnpmBin);
|
|
2271
2322
|
const invocation = planDetectedBinCommand(command.command, command.args);
|
|
2272
2323
|
if (invocation === null) return { ok: false, reason: "pnpm-command" };
|
|
2324
|
+
const cwd = action === "install-browser" ? fs13.mkdtempSync(path18.join(os.tmpdir(), "jorgex-playwright-")) : void 0;
|
|
2325
|
+
const childEnv = action === "install-browser" ? { ...env ?? process.env, NO_UPDATE_NOTIFIER: "1" } : env ?? process.env;
|
|
2273
2326
|
try {
|
|
2274
2327
|
execFileSync2(invocation.command, invocation.args, {
|
|
2275
2328
|
stdio: "inherit",
|
|
2276
|
-
|
|
2329
|
+
env: childEnv,
|
|
2330
|
+
...cwd === void 0 ? {} : { cwd }
|
|
2277
2331
|
});
|
|
2332
|
+
if (action === "install-browser" && !verifyPlaywrightBrowser(pnpmBin, childEnv, cwd)) {
|
|
2333
|
+
return { ok: false, reason: "browser-launch" };
|
|
2334
|
+
}
|
|
2278
2335
|
return { ok: true };
|
|
2279
2336
|
} catch {
|
|
2280
2337
|
return { ok: false, reason: "action-failed" };
|
|
2338
|
+
} finally {
|
|
2339
|
+
if (cwd !== void 0) fs13.rmSync(cwd, { recursive: true, force: true });
|
|
2281
2340
|
}
|
|
2282
2341
|
}
|
|
2283
2342
|
|
|
@@ -2287,6 +2346,7 @@ import path19 from "path";
|
|
|
2287
2346
|
var PLAYWRIGHT_CLI_PREFERENCE_VERSION = 1;
|
|
2288
2347
|
var DEVTOOLS_MCP_PREFERENCE_VERSION = 1;
|
|
2289
2348
|
var PRIMARY_MODEL_OWNERSHIP_VERSION = 1;
|
|
2349
|
+
var PLAYWRIGHT_RUNTIMES = ["opencode", "claude-code", "codex", "pi"];
|
|
2290
2350
|
function readPreference(file) {
|
|
2291
2351
|
try {
|
|
2292
2352
|
return { raw: fs14.readFileSync(file, "utf8"), errorCode: null };
|
|
@@ -2301,8 +2361,11 @@ function playwrightCliPreferenceFile(stateDir = dataDir()) {
|
|
|
2301
2361
|
function parsePlaywrightCliPreference(raw) {
|
|
2302
2362
|
try {
|
|
2303
2363
|
const value = JSON.parse(raw);
|
|
2304
|
-
if (value
|
|
2305
|
-
return value.enabled;
|
|
2364
|
+
if (!isRecord2(value)) return void 0;
|
|
2365
|
+
if (value.version === 1 && typeof value.enabled === "boolean") return { version: 1, enabled: value.enabled };
|
|
2366
|
+
if (value.version !== 2 || !isRecord2(value.enabled)) return void 0;
|
|
2367
|
+
if (Object.entries(value.enabled).some(([runtime, enabled]) => !PLAYWRIGHT_RUNTIMES.includes(runtime) || typeof enabled !== "boolean")) return void 0;
|
|
2368
|
+
return { version: 2, enabled: value.enabled };
|
|
2306
2369
|
} catch {
|
|
2307
2370
|
return void 0;
|
|
2308
2371
|
}
|
|
@@ -2315,15 +2378,28 @@ function playwrightCliPreferenceError(file = playwrightCliPreferenceFile()) {
|
|
|
2315
2378
|
if (raw === null || parsePlaywrightCliPreference(raw) !== void 0) return null;
|
|
2316
2379
|
return `Playwright CLI: preferencia inv\xE1lida en ${file}. Corrige o borra ese archivo antes de reintentar.`;
|
|
2317
2380
|
}
|
|
2318
|
-
function loadPlaywrightCliPreference(file = playwrightCliPreferenceFile()) {
|
|
2381
|
+
function loadPlaywrightCliPreference(file = playwrightCliPreferenceFile(), runtime) {
|
|
2319
2382
|
const { raw } = readPreference(file);
|
|
2320
|
-
|
|
2321
|
-
|
|
2383
|
+
const state = raw === null ? void 0 : parsePlaywrightCliPreference(raw);
|
|
2384
|
+
if (state === void 0) return void 0;
|
|
2385
|
+
if (state.version === 1) return state.enabled;
|
|
2386
|
+
return runtime === void 0 ? Object.values(state.enabled).some(Boolean) : state.enabled[runtime] === true;
|
|
2322
2387
|
}
|
|
2323
|
-
function savePlaywrightCliPreference(file, enabled) {
|
|
2388
|
+
function savePlaywrightCliPreference(file, enabled, selection) {
|
|
2324
2389
|
const error = playwrightCliPreferenceError(file);
|
|
2325
2390
|
if (error !== null) throw new Error(error);
|
|
2326
|
-
|
|
2391
|
+
const { raw } = readPreference(file);
|
|
2392
|
+
const previous = raw === null ? void 0 : parsePlaywrightCliPreference(raw);
|
|
2393
|
+
if (selection === void 0 && previous?.version !== 2) {
|
|
2394
|
+
writeText(file, JSON.stringify({ version: PLAYWRIGHT_CLI_PREFERENCE_VERSION, enabled }) + "\n");
|
|
2395
|
+
return;
|
|
2396
|
+
}
|
|
2397
|
+
const inherited = previous?.version === 2 ? previous.enabled : Object.fromEntries(PLAYWRIGHT_RUNTIMES.map((runtime) => [runtime, previous?.enabled === true]));
|
|
2398
|
+
const choices = { ...inherited, ...selection };
|
|
2399
|
+
const state = { version: 2, enabled: enabled ? choices : Object.fromEntries(Object.keys(choices).map((runtime) => [runtime, false])) };
|
|
2400
|
+
const content = JSON.stringify(state) + "\n";
|
|
2401
|
+
if (parsePlaywrightCliPreference(content) === void 0) throw new Error("Playwright CLI: selecci\xF3n de runtimes inv\xE1lida.");
|
|
2402
|
+
writeText(file, content);
|
|
2327
2403
|
}
|
|
2328
2404
|
function devtoolsMcpPreferenceFile(stateDir = dataDir()) {
|
|
2329
2405
|
return path19.join(stateDir, "devtools-mcp.json");
|
|
@@ -2536,7 +2612,7 @@ function makeContext(adapter, configDir, mode = DEFAULT_INSTALL_MODE_PREFERENCE,
|
|
|
2536
2612
|
models,
|
|
2537
2613
|
warnings: [],
|
|
2538
2614
|
enabledMcpServers: enabledMcpServers(adapter.id, void 0, useBrowserPreferences),
|
|
2539
|
-
playwrightCliEnabled: useBrowserPreferences && loadPlaywrightCliPreference() === true,
|
|
2615
|
+
playwrightCliEnabled: useBrowserPreferences && loadPlaywrightCliPreference(playwrightCliPreferenceFile(), adapter.id) === true,
|
|
2540
2616
|
ownedMcpServers: ownedMcpServers(adapter.id, useBrowserPreferences),
|
|
2541
2617
|
ownedPrimaryModelFields: useBrowserPreferences ? loadPrimaryModelOwnership(primaryModelOwnershipFile(), adapter.id, configDir) : /* @__PURE__ */ new Set()
|
|
2542
2618
|
};
|
|
@@ -2655,7 +2731,7 @@ async function runInstall(opts) {
|
|
|
2655
2731
|
models,
|
|
2656
2732
|
warnings: [],
|
|
2657
2733
|
enabledMcpServers: enabledMcpServers(id, opts.devtoolsMcpSelection?.[id], useManifest),
|
|
2658
|
-
playwrightCliEnabled: projectPlaywrightPrompt
|
|
2734
|
+
playwrightCliEnabled: projectPlaywrightPrompt ? opts.playwrightToolConsent?.runtimeSelection?.[id] ?? true : useManifest && loadPlaywrightCliPreference(playwrightCliPreferenceFile(), id) === true,
|
|
2659
2735
|
ownedMcpServers: ownedMcpServers(id, useManifest),
|
|
2660
2736
|
ownedPrimaryModelFields: useManifest ? loadPrimaryModelOwnership(primaryModelOwnershipFile(), id, configDir) : /* @__PURE__ */ new Set()
|
|
2661
2737
|
};
|
|
@@ -2750,7 +2826,7 @@ async function runInstall(opts) {
|
|
|
2750
2826
|
const pnpmBin = resolvePnpmBin();
|
|
2751
2827
|
return executePlaywrightToolAction2(action, pnpmBin, env);
|
|
2752
2828
|
},
|
|
2753
|
-
persistEnabled: (enabled) => savePlaywrightCliPreference(playwrightCliPreferenceFile(), enabled),
|
|
2829
|
+
persistEnabled: (enabled) => savePlaywrightCliPreference(playwrightCliPreferenceFile(), enabled, opts.playwrightToolConsent?.runtimeSelection),
|
|
2754
2830
|
setupPnpm: (pnpmBin) => setupPnpmGlobal(pnpmBin)
|
|
2755
2831
|
};
|
|
2756
2832
|
let setupAttempted = false;
|
|
@@ -2778,6 +2854,7 @@ async function runInstall(opts) {
|
|
|
2778
2854
|
return first;
|
|
2779
2855
|
}
|
|
2780
2856
|
preparedEnv = setup.env;
|
|
2857
|
+
p.log.info("pnpm preparado para esta instalaci\xF3n. Abre una terminal nueva al terminar para que otras herramientas y doctor reciban el PATH actualizado.");
|
|
2781
2858
|
return baseDeps.run(action, preparedEnv);
|
|
2782
2859
|
}
|
|
2783
2860
|
});
|
|
@@ -2789,7 +2866,11 @@ async function runInstall(opts) {
|
|
|
2789
2866
|
} else {
|
|
2790
2867
|
let promptReconciliationFailed = false;
|
|
2791
2868
|
for (const { adapter, ctx } of successfulContexts) {
|
|
2792
|
-
const browserCtx = {
|
|
2869
|
+
const browserCtx = {
|
|
2870
|
+
...ctx,
|
|
2871
|
+
playwrightCliEnabled: opts.playwrightToolConsent?.runtimeSelection?.[adapter.id] ?? true,
|
|
2872
|
+
warnings: []
|
|
2873
|
+
};
|
|
2793
2874
|
try {
|
|
2794
2875
|
const browserChanges = diffPlan(planSystemPrompt(adapter, browserCtx)).filter((change) => change.status !== "unchanged");
|
|
2795
2876
|
if (browserChanges.length === 0) continue;
|
|
@@ -2812,7 +2893,7 @@ async function runInstall(opts) {
|
|
|
2812
2893
|
exitCode = 1;
|
|
2813
2894
|
p.log.error("Playwright CLI y navegador se han instalado y la preferencia est\xE1 activada, pero la gu\xEDa de navegador qued\xF3 en estado parcial. Ejecuta 'jorgex-stack sync' para repararla.");
|
|
2814
2895
|
} else {
|
|
2815
|
-
p.log.success("Playwright CLI y
|
|
2896
|
+
p.log.success("Playwright CLI instalado y arranque de Chromium verificado.");
|
|
2816
2897
|
}
|
|
2817
2898
|
}
|
|
2818
2899
|
}
|
|
@@ -3954,6 +4035,7 @@ function engramVersion(bin) {
|
|
|
3954
4035
|
}
|
|
3955
4036
|
function resolvePlaywrightDoctorState(input) {
|
|
3956
4037
|
if (input.enabled !== true) return { status: "disabled" };
|
|
4038
|
+
if (input.cli.status === "not-in-path") return { status: "not-in-path" };
|
|
3957
4039
|
if (input.cli.status === "absent") return { status: "missing", missing: "package" };
|
|
3958
4040
|
if (input.cli.status === "broken") return { status: "broken" };
|
|
3959
4041
|
if (input.cli.status === "outdated") return { status: "outdated" };
|
|
@@ -4014,7 +4096,10 @@ async function runDoctor() {
|
|
|
4014
4096
|
if (playwright.status === "disabled") {
|
|
4015
4097
|
p3.log.info("Playwright CLI: deshabilitado (opcional). Usa 'install --playwright' para instalarlo de forma expl\xEDcita.");
|
|
4016
4098
|
} else if (playwright.status === "healthy") {
|
|
4017
|
-
p3.log.success("Playwright CLI: paquete y
|
|
4099
|
+
p3.log.success("Playwright CLI: paquete y cach\xE9 de Chromium detectados (doctor no prueba el arranque).");
|
|
4100
|
+
} else if (playwright.status === "not-in-path") {
|
|
4101
|
+
p3.log.warn("Playwright CLI: instalado en el directorio de pnpm, pero fuera del PATH de esta terminal. Abre una terminal nueva tras pnpm setup; no hace falta reinstalarlo.");
|
|
4102
|
+
problems++;
|
|
4018
4103
|
} else if (playwright.status === "missing") {
|
|
4019
4104
|
const target = playwright.missing === "package" ? "el paquete global" : "el navegador de Playwright";
|
|
4020
4105
|
p3.log.warn(`Playwright CLI: habilitado, pero falta ${target} \u2192 ejecuta 'jorgex-stack install --playwright'.`);
|
|
@@ -5480,9 +5565,12 @@ function normalizeInstalledSource(settingsJson, alias, canonical) {
|
|
|
5480
5565
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
5481
5566
|
const packages = Reflect.get(parsed, "packages");
|
|
5482
5567
|
if (!Array.isArray(packages)) return null;
|
|
5483
|
-
const
|
|
5484
|
-
if (packages.filter((entry) => entry === alias).length !== 1 ||
|
|
5485
|
-
Reflect.set(parsed, "packages", packages.map((entry) =>
|
|
5568
|
+
const sourceOf = (entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry) ? Reflect.get(entry, "source") : entry;
|
|
5569
|
+
if (packages.filter((entry) => sourceOf(entry) === alias).length !== 1 || packages.some((entry) => sourceOf(entry) === canonical)) return null;
|
|
5570
|
+
Reflect.set(parsed, "packages", packages.map((entry) => {
|
|
5571
|
+
if (sourceOf(entry) !== alias) return entry;
|
|
5572
|
+
return typeof entry === "string" ? canonical : { ...entry, source: canonical };
|
|
5573
|
+
}));
|
|
5486
5574
|
return JSON.stringify(parsed);
|
|
5487
5575
|
} catch {
|
|
5488
5576
|
return null;
|
|
@@ -5945,7 +6033,7 @@ function managedPackageResult(result) {
|
|
|
5945
6033
|
async function runManagedPiSystem(input) {
|
|
5946
6034
|
const { devtoolsMcpEnabled: explicitDevtools, ...runtimeInput } = input;
|
|
5947
6035
|
const devtoolsMcpEnabled = explicitDevtools ?? (input.targetDir === void 0 && loadDevtoolsMcpPreference(devtoolsMcpPreferenceFile(), "pi"));
|
|
5948
|
-
const playwrightCliEnabled = input.targetDir === void 0 && loadPlaywrightCliPreference() === true;
|
|
6036
|
+
const playwrightCliEnabled = input.targetDir === void 0 && loadPlaywrightCliPreference(void 0, "pi") === true;
|
|
5949
6037
|
const projectionInput = {
|
|
5950
6038
|
targetDir: input.targetDir,
|
|
5951
6039
|
packageSource: PI_RUNTIME_CANDIDATE.package.source,
|
|
@@ -6472,6 +6560,7 @@ var VERSION = readPackageVersion();
|
|
|
6472
6560
|
var COMMANDS = ["install", "sync", "models", "update", "doctor", "restore", "uninstall", "quality"];
|
|
6473
6561
|
var QUALITY_REJECTED_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
6474
6562
|
"--agents",
|
|
6563
|
+
"--playwright-runtimes",
|
|
6475
6564
|
"-a",
|
|
6476
6565
|
"--target-dir",
|
|
6477
6566
|
"--mode",
|
|
@@ -6557,7 +6646,13 @@ function parseFlags(args, allowReceipt = false) {
|
|
|
6557
6646
|
flags.subagentConcurrency = value ?? "";
|
|
6558
6647
|
i = nextIndex;
|
|
6559
6648
|
} else if (arg.startsWith("--subagent-concurrency=")) flags.subagentConcurrency = arg.slice(23);
|
|
6560
|
-
else if (arg === "--
|
|
6649
|
+
else if (arg === "--playwright-runtimes") {
|
|
6650
|
+
const [value, nextIndex] = readValue(i);
|
|
6651
|
+
flags.playwrightRuntimes = (value ?? "").split(",").filter(Boolean);
|
|
6652
|
+
i = nextIndex;
|
|
6653
|
+
} else if (arg.startsWith("--playwright-runtimes=")) {
|
|
6654
|
+
flags.playwrightRuntimes = arg.slice("--playwright-runtimes=".length).split(",").filter(Boolean);
|
|
6655
|
+
} else if (arg === "--dry-run") flags.dryRun = true;
|
|
6561
6656
|
else if (arg === "--yes" || arg === "-y") flags.yes = true;
|
|
6562
6657
|
else if (arg === "--help" || arg === "-h") flags.help = true;
|
|
6563
6658
|
else if (arg === "--version" || arg === "-v") flags.version = true;
|
|
@@ -6635,8 +6730,25 @@ Corrige o borra ${preferenceFile}, o vuelve a ejecutar con --mode human|programm
|
|
|
6635
6730
|
subagentConcurrency: concurrency
|
|
6636
6731
|
};
|
|
6637
6732
|
}
|
|
6638
|
-
async function resolvePlaywrightToolConsent(command, flags) {
|
|
6733
|
+
async function resolvePlaywrightToolConsent(command, flags, runtimes) {
|
|
6639
6734
|
const interactive = Boolean(process.stdout.isTTY);
|
|
6735
|
+
const supported = runtimes.filter((runtime) => runtime !== "pi" || PI_RUNTIME_CANDIDATE.contract.capabilities.includes("playwright-handoff-v1"));
|
|
6736
|
+
if (flags.playwrightRuntimes !== void 0) {
|
|
6737
|
+
const requested = flags.playwrightRuntimes;
|
|
6738
|
+
let error;
|
|
6739
|
+
if (requested.length === 0) error = "--playwright-runtimes requiere al menos un runtime.";
|
|
6740
|
+
for (const runtime of requested) {
|
|
6741
|
+
if (!["opencode", "claude-code", "codex", "pi"].includes(runtime)) error = `Runtime Playwright desconocido: ${runtime}.`;
|
|
6742
|
+
else if (!runtimes.includes(runtime)) error = `El runtime ${runtime} no est\xE1 en --agents/destinos de esta instalaci\xF3n.`;
|
|
6743
|
+
else if (!supported.includes(runtime)) error = "Pi requiere un candidato con playwright-handoff-v1 para activar Playwright.";
|
|
6744
|
+
if (error) break;
|
|
6745
|
+
}
|
|
6746
|
+
if (error) {
|
|
6747
|
+
console.error(error);
|
|
6748
|
+
process.exitCode = 1;
|
|
6749
|
+
return null;
|
|
6750
|
+
}
|
|
6751
|
+
}
|
|
6640
6752
|
let confirmed = false;
|
|
6641
6753
|
if (command === "install" && interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0) {
|
|
6642
6754
|
const answer = await p6.confirm({
|
|
@@ -6646,13 +6758,33 @@ async function resolvePlaywrightToolConsent(command, flags) {
|
|
|
6646
6758
|
if (p6.isCancel(answer)) return null;
|
|
6647
6759
|
confirmed = answer === true;
|
|
6648
6760
|
}
|
|
6761
|
+
let runtimeSelection;
|
|
6762
|
+
const approved = interactive && !flags.yes ? confirmed : flags.yes && flags.playwright;
|
|
6763
|
+
if (command === "install" && approved && supported.length > 0) {
|
|
6764
|
+
let selected = flags.playwrightRuntimes ?? supported;
|
|
6765
|
+
if (interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0 && flags.playwrightRuntimes === void 0) {
|
|
6766
|
+
const answer = await p6.multiselect({
|
|
6767
|
+
message: "\xBFEn qu\xE9 runtimes activar la gu\xEDa de Playwright? (instalaci\xF3n global compartida)",
|
|
6768
|
+
required: false,
|
|
6769
|
+
options: supported.map((runtime) => ({ value: runtime, label: runtime === "pi" ? "Pi" : ADAPTERS[runtime]?.name ?? runtime })),
|
|
6770
|
+
initialValues: supported.filter((runtime) => loadPlaywrightCliPreference(void 0, runtime) === true)
|
|
6771
|
+
});
|
|
6772
|
+
if (p6.isCancel(answer)) return null;
|
|
6773
|
+
selected = answer;
|
|
6774
|
+
}
|
|
6775
|
+
runtimeSelection = Object.fromEntries(supported.map((runtime) => [runtime, selected.includes(runtime)]));
|
|
6776
|
+
}
|
|
6777
|
+
if (command === "install" && approved && runtimes.includes("pi") && !supported.includes("pi")) {
|
|
6778
|
+
p6.log.info("La activaci\xF3n de Playwright en Pi requiere la pr\xF3xima adopci\xF3n del paquete Pi; el binario global s\xED puede instalarse.");
|
|
6779
|
+
}
|
|
6649
6780
|
return {
|
|
6650
6781
|
command,
|
|
6651
6782
|
interactive,
|
|
6652
6783
|
yes: flags.yes,
|
|
6653
6784
|
targetDir: flags.targetDir !== void 0,
|
|
6654
6785
|
explicitToolSelection: flags.playwright,
|
|
6655
|
-
confirmed
|
|
6786
|
+
confirmed,
|
|
6787
|
+
...runtimeSelection === void 0 ? {} : { runtimeSelection }
|
|
6656
6788
|
};
|
|
6657
6789
|
}
|
|
6658
6790
|
async function resolveDevtoolsMcpSelection(command, flags, runtimes) {
|
|
@@ -6827,6 +6959,7 @@ Opciones:
|
|
|
6827
6959
|
--no-devtools (install/sync) desactiva Chrome DevTools MCP (incompatible con --devtools)
|
|
6828
6960
|
--remove-engram (uninstall) desregistra Engram de los runtimes;
|
|
6829
6961
|
memorias y binario quedan intactos igualmente
|
|
6962
|
+
--playwright-runtimes <csv> Activa su gu\xEDa s\xF3lo en estos runtimes de --agents (con --playwright)
|
|
6830
6963
|
--remove-playwright (uninstall) retira solo el paquete global de Playwright;
|
|
6831
6964
|
nunca perfiles, cach\xE9 ni navegadores
|
|
6832
6965
|
--receipt <path> (quality) escribe el receipt en ese path de forma at\xF3mica
|
|
@@ -6861,6 +6994,11 @@ Flags disponibles: jorgex-stack --help`
|
|
|
6861
6994
|
process.exitCode = 1;
|
|
6862
6995
|
return;
|
|
6863
6996
|
}
|
|
6997
|
+
if (flags.playwrightRuntimes !== void 0 && (command !== "install" || !flags.playwright)) {
|
|
6998
|
+
console.error("--playwright-runtimes requiere install --playwright.");
|
|
6999
|
+
process.exitCode = 1;
|
|
7000
|
+
return;
|
|
7001
|
+
}
|
|
6864
7002
|
if (command !== "quality" && flags.targetDir !== void 0 && flags.agents.length !== 1) {
|
|
6865
7003
|
console.error("--target-dir requiere exactamente un runtime en --agents.");
|
|
6866
7004
|
process.exitCode = 1;
|
|
@@ -6927,8 +7065,11 @@ Flags disponibles: jorgex-stack --help`
|
|
|
6927
7065
|
exitCode = process.exitCode === 1 ? 1 : 0;
|
|
6928
7066
|
return;
|
|
6929
7067
|
}
|
|
6930
|
-
const playwrightToolConsent = await resolvePlaywrightToolConsent(command, flags);
|
|
6931
|
-
if (playwrightToolConsent === null)
|
|
7068
|
+
const playwrightToolConsent = await resolvePlaywrightToolConsent(command, flags, runtimes);
|
|
7069
|
+
if (playwrightToolConsent === null) {
|
|
7070
|
+
exitCode = process.exitCode === 1 ? 1 : 0;
|
|
7071
|
+
return;
|
|
7072
|
+
}
|
|
6932
7073
|
if (!await ensureOpenCodeModelsForInstall(command, flags, fileRuntimes)) {
|
|
6933
7074
|
exitCode = 1;
|
|
6934
7075
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jorgex-stack",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.32",
|
|
4
4
|
"description": "Harness multi-agente portable: instala la config JorgeX (agentes, skills, hooks, Engram, MCPs) en Claude Code, Codex CLI, OpenCode y Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|