jorgex-stack 1.9.30 → 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 +169 -26
- 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) {
|
|
@@ -2257,10 +2308,12 @@ function executePlaywrightToolAction(action, pnpmBin = resolvePnpmBin(), env) {
|
|
|
2257
2308
|
const preflight = planDetectedBinCommand(pnpmBin, ["bin", "--global"]);
|
|
2258
2309
|
if (preflight === null) return { ok: false, reason: "pnpm-command" };
|
|
2259
2310
|
try {
|
|
2260
|
-
execFileSync2(preflight.command, preflight.args, {
|
|
2261
|
-
|
|
2311
|
+
const globalBin = execFileSync2(preflight.command, preflight.args, {
|
|
2312
|
+
encoding: "utf8",
|
|
2313
|
+
stdio: ["ignore", "pipe", "inherit"],
|
|
2262
2314
|
...env === void 0 ? {} : { env }
|
|
2263
2315
|
});
|
|
2316
|
+
if (globalBin.trim() === "") return { ok: false, reason: "pnpm-global-bin" };
|
|
2264
2317
|
} catch (error) {
|
|
2265
2318
|
return { ok: false, reason: hasNonzeroProcessStatus(error) ? "pnpm-global-bin" : "pnpm-command" };
|
|
2266
2319
|
}
|
|
@@ -2268,14 +2321,22 @@ function executePlaywrightToolAction(action, pnpmBin = resolvePnpmBin(), env) {
|
|
|
2268
2321
|
const command = planPlaywrightCliCommand(action, pnpmBin);
|
|
2269
2322
|
const invocation = planDetectedBinCommand(command.command, command.args);
|
|
2270
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;
|
|
2271
2326
|
try {
|
|
2272
2327
|
execFileSync2(invocation.command, invocation.args, {
|
|
2273
2328
|
stdio: "inherit",
|
|
2274
|
-
|
|
2329
|
+
env: childEnv,
|
|
2330
|
+
...cwd === void 0 ? {} : { cwd }
|
|
2275
2331
|
});
|
|
2332
|
+
if (action === "install-browser" && !verifyPlaywrightBrowser(pnpmBin, childEnv, cwd)) {
|
|
2333
|
+
return { ok: false, reason: "browser-launch" };
|
|
2334
|
+
}
|
|
2276
2335
|
return { ok: true };
|
|
2277
2336
|
} catch {
|
|
2278
2337
|
return { ok: false, reason: "action-failed" };
|
|
2338
|
+
} finally {
|
|
2339
|
+
if (cwd !== void 0) fs13.rmSync(cwd, { recursive: true, force: true });
|
|
2279
2340
|
}
|
|
2280
2341
|
}
|
|
2281
2342
|
|
|
@@ -2285,6 +2346,7 @@ import path19 from "path";
|
|
|
2285
2346
|
var PLAYWRIGHT_CLI_PREFERENCE_VERSION = 1;
|
|
2286
2347
|
var DEVTOOLS_MCP_PREFERENCE_VERSION = 1;
|
|
2287
2348
|
var PRIMARY_MODEL_OWNERSHIP_VERSION = 1;
|
|
2349
|
+
var PLAYWRIGHT_RUNTIMES = ["opencode", "claude-code", "codex", "pi"];
|
|
2288
2350
|
function readPreference(file) {
|
|
2289
2351
|
try {
|
|
2290
2352
|
return { raw: fs14.readFileSync(file, "utf8"), errorCode: null };
|
|
@@ -2299,8 +2361,11 @@ function playwrightCliPreferenceFile(stateDir = dataDir()) {
|
|
|
2299
2361
|
function parsePlaywrightCliPreference(raw) {
|
|
2300
2362
|
try {
|
|
2301
2363
|
const value = JSON.parse(raw);
|
|
2302
|
-
if (value
|
|
2303
|
-
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 };
|
|
2304
2369
|
} catch {
|
|
2305
2370
|
return void 0;
|
|
2306
2371
|
}
|
|
@@ -2313,15 +2378,28 @@ function playwrightCliPreferenceError(file = playwrightCliPreferenceFile()) {
|
|
|
2313
2378
|
if (raw === null || parsePlaywrightCliPreference(raw) !== void 0) return null;
|
|
2314
2379
|
return `Playwright CLI: preferencia inv\xE1lida en ${file}. Corrige o borra ese archivo antes de reintentar.`;
|
|
2315
2380
|
}
|
|
2316
|
-
function loadPlaywrightCliPreference(file = playwrightCliPreferenceFile()) {
|
|
2381
|
+
function loadPlaywrightCliPreference(file = playwrightCliPreferenceFile(), runtime) {
|
|
2317
2382
|
const { raw } = readPreference(file);
|
|
2318
|
-
|
|
2319
|
-
|
|
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;
|
|
2320
2387
|
}
|
|
2321
|
-
function savePlaywrightCliPreference(file, enabled) {
|
|
2388
|
+
function savePlaywrightCliPreference(file, enabled, selection) {
|
|
2322
2389
|
const error = playwrightCliPreferenceError(file);
|
|
2323
2390
|
if (error !== null) throw new Error(error);
|
|
2324
|
-
|
|
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);
|
|
2325
2403
|
}
|
|
2326
2404
|
function devtoolsMcpPreferenceFile(stateDir = dataDir()) {
|
|
2327
2405
|
return path19.join(stateDir, "devtools-mcp.json");
|
|
@@ -2534,7 +2612,7 @@ function makeContext(adapter, configDir, mode = DEFAULT_INSTALL_MODE_PREFERENCE,
|
|
|
2534
2612
|
models,
|
|
2535
2613
|
warnings: [],
|
|
2536
2614
|
enabledMcpServers: enabledMcpServers(adapter.id, void 0, useBrowserPreferences),
|
|
2537
|
-
playwrightCliEnabled: useBrowserPreferences && loadPlaywrightCliPreference() === true,
|
|
2615
|
+
playwrightCliEnabled: useBrowserPreferences && loadPlaywrightCliPreference(playwrightCliPreferenceFile(), adapter.id) === true,
|
|
2538
2616
|
ownedMcpServers: ownedMcpServers(adapter.id, useBrowserPreferences),
|
|
2539
2617
|
ownedPrimaryModelFields: useBrowserPreferences ? loadPrimaryModelOwnership(primaryModelOwnershipFile(), adapter.id, configDir) : /* @__PURE__ */ new Set()
|
|
2540
2618
|
};
|
|
@@ -2653,7 +2731,7 @@ async function runInstall(opts) {
|
|
|
2653
2731
|
models,
|
|
2654
2732
|
warnings: [],
|
|
2655
2733
|
enabledMcpServers: enabledMcpServers(id, opts.devtoolsMcpSelection?.[id], useManifest),
|
|
2656
|
-
playwrightCliEnabled: projectPlaywrightPrompt
|
|
2734
|
+
playwrightCliEnabled: projectPlaywrightPrompt ? opts.playwrightToolConsent?.runtimeSelection?.[id] ?? true : useManifest && loadPlaywrightCliPreference(playwrightCliPreferenceFile(), id) === true,
|
|
2657
2735
|
ownedMcpServers: ownedMcpServers(id, useManifest),
|
|
2658
2736
|
ownedPrimaryModelFields: useManifest ? loadPrimaryModelOwnership(primaryModelOwnershipFile(), id, configDir) : /* @__PURE__ */ new Set()
|
|
2659
2737
|
};
|
|
@@ -2748,7 +2826,7 @@ async function runInstall(opts) {
|
|
|
2748
2826
|
const pnpmBin = resolvePnpmBin();
|
|
2749
2827
|
return executePlaywrightToolAction2(action, pnpmBin, env);
|
|
2750
2828
|
},
|
|
2751
|
-
persistEnabled: (enabled) => savePlaywrightCliPreference(playwrightCliPreferenceFile(), enabled),
|
|
2829
|
+
persistEnabled: (enabled) => savePlaywrightCliPreference(playwrightCliPreferenceFile(), enabled, opts.playwrightToolConsent?.runtimeSelection),
|
|
2752
2830
|
setupPnpm: (pnpmBin) => setupPnpmGlobal(pnpmBin)
|
|
2753
2831
|
};
|
|
2754
2832
|
let setupAttempted = false;
|
|
@@ -2776,6 +2854,7 @@ async function runInstall(opts) {
|
|
|
2776
2854
|
return first;
|
|
2777
2855
|
}
|
|
2778
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.");
|
|
2779
2858
|
return baseDeps.run(action, preparedEnv);
|
|
2780
2859
|
}
|
|
2781
2860
|
});
|
|
@@ -2787,7 +2866,11 @@ async function runInstall(opts) {
|
|
|
2787
2866
|
} else {
|
|
2788
2867
|
let promptReconciliationFailed = false;
|
|
2789
2868
|
for (const { adapter, ctx } of successfulContexts) {
|
|
2790
|
-
const browserCtx = {
|
|
2869
|
+
const browserCtx = {
|
|
2870
|
+
...ctx,
|
|
2871
|
+
playwrightCliEnabled: opts.playwrightToolConsent?.runtimeSelection?.[adapter.id] ?? true,
|
|
2872
|
+
warnings: []
|
|
2873
|
+
};
|
|
2791
2874
|
try {
|
|
2792
2875
|
const browserChanges = diffPlan(planSystemPrompt(adapter, browserCtx)).filter((change) => change.status !== "unchanged");
|
|
2793
2876
|
if (browserChanges.length === 0) continue;
|
|
@@ -2810,7 +2893,7 @@ async function runInstall(opts) {
|
|
|
2810
2893
|
exitCode = 1;
|
|
2811
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.");
|
|
2812
2895
|
} else {
|
|
2813
|
-
p.log.success("Playwright CLI y
|
|
2896
|
+
p.log.success("Playwright CLI instalado y arranque de Chromium verificado.");
|
|
2814
2897
|
}
|
|
2815
2898
|
}
|
|
2816
2899
|
}
|
|
@@ -3952,6 +4035,7 @@ function engramVersion(bin) {
|
|
|
3952
4035
|
}
|
|
3953
4036
|
function resolvePlaywrightDoctorState(input) {
|
|
3954
4037
|
if (input.enabled !== true) return { status: "disabled" };
|
|
4038
|
+
if (input.cli.status === "not-in-path") return { status: "not-in-path" };
|
|
3955
4039
|
if (input.cli.status === "absent") return { status: "missing", missing: "package" };
|
|
3956
4040
|
if (input.cli.status === "broken") return { status: "broken" };
|
|
3957
4041
|
if (input.cli.status === "outdated") return { status: "outdated" };
|
|
@@ -4012,7 +4096,10 @@ async function runDoctor() {
|
|
|
4012
4096
|
if (playwright.status === "disabled") {
|
|
4013
4097
|
p3.log.info("Playwright CLI: deshabilitado (opcional). Usa 'install --playwright' para instalarlo de forma expl\xEDcita.");
|
|
4014
4098
|
} else if (playwright.status === "healthy") {
|
|
4015
|
-
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++;
|
|
4016
4103
|
} else if (playwright.status === "missing") {
|
|
4017
4104
|
const target = playwright.missing === "package" ? "el paquete global" : "el navegador de Playwright";
|
|
4018
4105
|
p3.log.warn(`Playwright CLI: habilitado, pero falta ${target} \u2192 ejecuta 'jorgex-stack install --playwright'.`);
|
|
@@ -5478,9 +5565,12 @@ function normalizeInstalledSource(settingsJson, alias, canonical) {
|
|
|
5478
5565
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
5479
5566
|
const packages = Reflect.get(parsed, "packages");
|
|
5480
5567
|
if (!Array.isArray(packages)) return null;
|
|
5481
|
-
const
|
|
5482
|
-
if (packages.filter((entry) => entry === alias).length !== 1 ||
|
|
5483
|
-
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
|
+
}));
|
|
5484
5574
|
return JSON.stringify(parsed);
|
|
5485
5575
|
} catch {
|
|
5486
5576
|
return null;
|
|
@@ -5943,7 +6033,7 @@ function managedPackageResult(result) {
|
|
|
5943
6033
|
async function runManagedPiSystem(input) {
|
|
5944
6034
|
const { devtoolsMcpEnabled: explicitDevtools, ...runtimeInput } = input;
|
|
5945
6035
|
const devtoolsMcpEnabled = explicitDevtools ?? (input.targetDir === void 0 && loadDevtoolsMcpPreference(devtoolsMcpPreferenceFile(), "pi"));
|
|
5946
|
-
const playwrightCliEnabled = input.targetDir === void 0 && loadPlaywrightCliPreference() === true;
|
|
6036
|
+
const playwrightCliEnabled = input.targetDir === void 0 && loadPlaywrightCliPreference(void 0, "pi") === true;
|
|
5947
6037
|
const projectionInput = {
|
|
5948
6038
|
targetDir: input.targetDir,
|
|
5949
6039
|
packageSource: PI_RUNTIME_CANDIDATE.package.source,
|
|
@@ -6470,6 +6560,7 @@ var VERSION = readPackageVersion();
|
|
|
6470
6560
|
var COMMANDS = ["install", "sync", "models", "update", "doctor", "restore", "uninstall", "quality"];
|
|
6471
6561
|
var QUALITY_REJECTED_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
6472
6562
|
"--agents",
|
|
6563
|
+
"--playwright-runtimes",
|
|
6473
6564
|
"-a",
|
|
6474
6565
|
"--target-dir",
|
|
6475
6566
|
"--mode",
|
|
@@ -6555,7 +6646,13 @@ function parseFlags(args, allowReceipt = false) {
|
|
|
6555
6646
|
flags.subagentConcurrency = value ?? "";
|
|
6556
6647
|
i = nextIndex;
|
|
6557
6648
|
} else if (arg.startsWith("--subagent-concurrency=")) flags.subagentConcurrency = arg.slice(23);
|
|
6558
|
-
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;
|
|
6559
6656
|
else if (arg === "--yes" || arg === "-y") flags.yes = true;
|
|
6560
6657
|
else if (arg === "--help" || arg === "-h") flags.help = true;
|
|
6561
6658
|
else if (arg === "--version" || arg === "-v") flags.version = true;
|
|
@@ -6633,8 +6730,25 @@ Corrige o borra ${preferenceFile}, o vuelve a ejecutar con --mode human|programm
|
|
|
6633
6730
|
subagentConcurrency: concurrency
|
|
6634
6731
|
};
|
|
6635
6732
|
}
|
|
6636
|
-
async function resolvePlaywrightToolConsent(command, flags) {
|
|
6733
|
+
async function resolvePlaywrightToolConsent(command, flags, runtimes) {
|
|
6637
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
|
+
}
|
|
6638
6752
|
let confirmed = false;
|
|
6639
6753
|
if (command === "install" && interactive && !flags.yes && !flags.dryRun && flags.targetDir === void 0) {
|
|
6640
6754
|
const answer = await p6.confirm({
|
|
@@ -6644,13 +6758,33 @@ async function resolvePlaywrightToolConsent(command, flags) {
|
|
|
6644
6758
|
if (p6.isCancel(answer)) return null;
|
|
6645
6759
|
confirmed = answer === true;
|
|
6646
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
|
+
}
|
|
6647
6780
|
return {
|
|
6648
6781
|
command,
|
|
6649
6782
|
interactive,
|
|
6650
6783
|
yes: flags.yes,
|
|
6651
6784
|
targetDir: flags.targetDir !== void 0,
|
|
6652
6785
|
explicitToolSelection: flags.playwright,
|
|
6653
|
-
confirmed
|
|
6786
|
+
confirmed,
|
|
6787
|
+
...runtimeSelection === void 0 ? {} : { runtimeSelection }
|
|
6654
6788
|
};
|
|
6655
6789
|
}
|
|
6656
6790
|
async function resolveDevtoolsMcpSelection(command, flags, runtimes) {
|
|
@@ -6825,6 +6959,7 @@ Opciones:
|
|
|
6825
6959
|
--no-devtools (install/sync) desactiva Chrome DevTools MCP (incompatible con --devtools)
|
|
6826
6960
|
--remove-engram (uninstall) desregistra Engram de los runtimes;
|
|
6827
6961
|
memorias y binario quedan intactos igualmente
|
|
6962
|
+
--playwright-runtimes <csv> Activa su gu\xEDa s\xF3lo en estos runtimes de --agents (con --playwright)
|
|
6828
6963
|
--remove-playwright (uninstall) retira solo el paquete global de Playwright;
|
|
6829
6964
|
nunca perfiles, cach\xE9 ni navegadores
|
|
6830
6965
|
--receipt <path> (quality) escribe el receipt en ese path de forma at\xF3mica
|
|
@@ -6859,6 +6994,11 @@ Flags disponibles: jorgex-stack --help`
|
|
|
6859
6994
|
process.exitCode = 1;
|
|
6860
6995
|
return;
|
|
6861
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
|
+
}
|
|
6862
7002
|
if (command !== "quality" && flags.targetDir !== void 0 && flags.agents.length !== 1) {
|
|
6863
7003
|
console.error("--target-dir requiere exactamente un runtime en --agents.");
|
|
6864
7004
|
process.exitCode = 1;
|
|
@@ -6925,8 +7065,11 @@ Flags disponibles: jorgex-stack --help`
|
|
|
6925
7065
|
exitCode = process.exitCode === 1 ? 1 : 0;
|
|
6926
7066
|
return;
|
|
6927
7067
|
}
|
|
6928
|
-
const playwrightToolConsent = await resolvePlaywrightToolConsent(command, flags);
|
|
6929
|
-
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
|
+
}
|
|
6930
7073
|
if (!await ensureOpenCodeModelsForInstall(command, flags, fileRuntimes)) {
|
|
6931
7074
|
exitCode = 1;
|
|
6932
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",
|