jorgex-stack 1.9.59 → 1.9.61
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 +7 -7
- package/dist/chunk-2CBCBOP7.js +245 -0
- package/dist/{chunk-NNPFC6QV.js → chunk-4USZMJ3I.js} +6 -15
- package/dist/chunk-66WVKOU4.js +693 -0
- package/dist/chunk-B76ZJXXD.js +989 -0
- package/dist/{chunk-M6QX2F3A.js → chunk-BSHTDTJL.js} +5 -6
- package/dist/{chunk-GOLJ5PA3.js → chunk-KKN4OYHD.js} +5 -12
- package/dist/{claude-code-WY4JJAXP.js → claude-code-BBHLN5TD.js} +3 -2
- package/dist/cli.js +232 -217
- package/dist/{codex-WSWHXYJ3.js → codex-ALGP2YBC.js} +3 -2
- package/dist/official-engram-setup-4WIXM4EF.js +34 -0
- package/dist/{opencode-NUDGK6J7.js → opencode-VG2IZRRF.js} +3 -2
- package/dist/pi-CKFSPGJU.js +13 -0
- package/package.json +1 -1
- package/dist/chunk-KB5IQEKL.js +0 -1400
- package/stack/system-prompt/engram-protocol.md +0 -55
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ Programmatic mode does **not** provide:
|
|
|
116
116
|
|
|
117
117
|
El canon de Stack y el paquete Pi adoptado mantienen una snapshot de 17 árboles de skills con 89 archivos de skill. La identidad, procedencia e integridad del paquete adoptado son autoritativas en `src/lib/pi-runtime-pin.json`.
|
|
118
118
|
|
|
119
|
-
Pi combines the frozen **snapshot v2** package with a Stack-owned shared projection. The
|
|
119
|
+
Pi combines the frozen **snapshot v2** package with a Stack-owned shared projection. The current pin is the published `jorgex-pi@0.8.28` artifact. Package identity, integrity and lifecycle are maintained in [docs/references/pi-runtime.md](docs/references/pi-runtime.md) and `src/lib/pi-runtime-pin.json`; this README does not duplicate mutable pin metadata.
|
|
120
120
|
|
|
121
121
|
The following command block is retained as historical reference for that transition:
|
|
122
122
|
|
|
@@ -128,13 +128,13 @@ pnpm dlx jorgex-stack@1.9.7 sync --agents pi
|
|
|
128
128
|
pnpm dlx jorgex-stack@1.9.7 uninstall --agents pi
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
For the current Pi `0.8.
|
|
131
|
+
For the current Pi `0.8.28` pin, package identity and runner validation precede projection; the exact pending initialization diagnostic remains provisional until projection and final `sync` complete.
|
|
132
132
|
|
|
133
|
-
Stack
|
|
133
|
+
Stack runs provider-owned `engram setup pi` before Pi package activation on a real managed install. It backs up and verifies Pi's `settings.json`, `mcp.json` and provider-owned `npm` tree, and restores the backup on setup failure; Pi is not activated unless setup and subsequent package lifecycle succeed. The exact 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. A managed install then runs provider setup, `package install → projection install → package sync`. Stack projects shared resources such as the system prompt, canonical skills and `lean-audit`; it does not inject `jorgex:engram-protocol`, project Engram tools, or filter provider tools. The behavioral `engram` role remains part of the Pi contract, while the official provider owns its setup and tools. Pi registers Context7 through an isolated in-memory HTTP bridge during bootstrap; `available` means configuration permits registration and does not imply an HTTP handshake. A conflict preserves the existing MCP file and blocks managed activation. No MCP credentials are written. For the file runtimes, Context7, Playwright and DevTools use independent managed sections. The global Playwright package and Chromium cache are shared by the machine; `--playwright-runtimes` controls which runtime receives the guide. The adopted Pi package implements and tests `playwright-handoff-v1` through `PI_CODING_AGENT_DIR/jorgex-pi/playwright.v1.json`. 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.
|
|
134
134
|
|
|
135
135
|
The static `AGENTS.md` projected by Stack does not include Context7; Pi's native bootstrap adds that section after registering the isolated bridge. Pi never writes, owns or removes MCP files. In Claude Code, Codex and OpenCode, a compatible existing Context7 entry is preserved and removed only with explicit canonical Stack ownership. During package installation only, `initialization-diagnostics-v1` permits the exact pending `doctor` envelope described in [the Pi runtime reference](docs/references/pi-runtime.md); it is provisional and does not make Pi healthy. Projection and final `sync` must still complete, and every other unhealthy or malformed result remains blocked.
|
|
136
136
|
|
|
137
|
-
Pi 0.8.
|
|
137
|
+
Pi 0.8.28 also seeds `theme=JorgeX`, `quietStartup=true`, and `hideThinkingBlock=true` only for missing fields during first initialization. User changes and deletions are preserved without reseeding. `hideThinkingBlock` changes presentation only; `defaultThinkingLevel` and reasoning remain unchanged. Pi owns only the fields it creates and records in its lifecycle receipt; pre-existing user settings remain unowned. The JorgeX header preserves builtin and custom commands. `Ctrl+O` remains Pi's native tool presentation, with `NO_COLOR` and `JORGEX_PI_MOTION` behavior unchanged; Stack adds no renderer.
|
|
138
138
|
|
|
139
139
|
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.
|
|
140
140
|
|
|
@@ -152,11 +152,11 @@ Claude's official plugin still requires stable Engram 2.0.0 or newer: an existin
|
|
|
152
152
|
|
|
153
153
|
### Integración oficial de Engram
|
|
154
154
|
|
|
155
|
-
En una instalación real, `install` delega Claude Code, Codex y OpenCode 1.x a `engram setup <runtime>` una vez por runtime durante esa instalación. No ejecuta ese setup durante `sync`, `dry-run`, `--target-dir`, `doctor` ni `uninstall`. Stack respalda los archivos afectados, verifica los artefactos oficiales y revierte el cambio si falla;
|
|
155
|
+
En una instalación real, `install` delega Claude Code, Codex y OpenCode 1.x a `engram setup <runtime>` una vez por runtime durante esa instalación, y Pi ejecuta `engram setup pi` antes de activar el paquete. El comportamiento del provider oficial permanece sin cambios: Stack no proyecta el protocolo Engram ni filtra sus herramientas. No ejecuta ese setup durante `sync`, `dry-run`, `--target-dir`, `doctor` ni `uninstall`. Stack respalda los archivos afectados, verifica los artefactos oficiales y revierte el cambio si falla; para Pi incluye `settings.json`, `mcp.json` y el árbol `npm`. No modifica `~/.engram`, sus memorias ni reemplaza un binario existente. Los artefactos oficiales se conservan al desinstalar. El `stack/plugins/opencode/engram.ts` legado ya no se despliega y queda retirado por esta integración.
|
|
156
156
|
|
|
157
157
|
Para Codex, Engram 2.0 ignora `CODEX_HOME` y escribe siempre en `$HOME/.codex`; por eso el setup oficial real requiere ese destino predeterminado. Si `CODEX_HOME` apunta a otro directorio, `install` falla cerrado en el preflight, antes de escribir la configuración de Codex, y recomienda usar `$HOME/.codex`. `sync`, `dry-run` y `--target-dir` no invocan el setup oficial.
|
|
158
158
|
|
|
159
|
-
La política de complementos distingue estrategias `exact` y `provider-managed`. DevTools MCP y Playwright CLI mantienen pins exactos; las integraciones oficiales de Engram son `provider-managed`/rolling, incluido Codex `main
|
|
159
|
+
La política de complementos distingue estrategias `exact` y `provider-managed`. DevTools MCP y Playwright CLI mantienen pins exactos; las integraciones oficiales de Engram son `provider-managed`/rolling, incluido Codex `main`, `pi-mcp-adapter` y el setup oficial de Pi sin pin en Stack. OpenCode 2 queda fuera de alcance y no bloquea esta integración.
|
|
160
160
|
|
|
161
161
|
Históricamente, Stack `1.9.7` reconocía el receipt exacto de Pi `npm:jorgex-pi@0.8.4`. Usa versiones exactas, nunca `latest`, y no edites receipts o hashes ni borres `HOME`, Engram o la proyección de otro runtime para forzar confianza. El pin y los comandos actuales de transición y rollback están en [docs/references/pi-runtime.md](docs/references/pi-runtime.md).
|
|
162
162
|
|
|
@@ -206,7 +206,7 @@ Daily operation:
|
|
|
206
206
|
- `doctor` reports the Playwright CLI state (`disabled`, `healthy`, `missing:package`, `missing:browser`, `unreadable`, `broken`, `outdated`) and, when the opt-in package and browser cache are present, verifies one local headless Chromium launch against `about:blank`; it does not open external sites or repair state. An `unreadable` browser cache includes its exact path and filesystem error code so permissions or another local cause can be investigated. If either preference file is corrupt, doctor prints the exact path and the remedy (`Corrige o borra ese archivo antes de reintentar`) before any other browser check; in that case `install`/`uninstall`/`update`/`update --check` will abort with exit 1 until the file is fixed, so the corruption cannot be reconciled destructively.
|
|
207
207
|
- `update --check` only inspects Playwright CLI when its preference is `enabled` (a binary appearing in `PATH` is not consent). It compares the installed version against the approved pin `0.1.18` — it does not consult npm latest, and a Playwright CLI binary-only update does not require `sync` afterwards.
|
|
208
208
|
- `uninstall` preserves the global `@playwright/cli` package and all browser data by default; `--remove-playwright` removes the package only (never the browser cache, profiles, cookies, storage state, traces, screenshots or videos). If `pnpm remove --global @playwright/cli` exits non-zero, `uninstall` reports the failure instead of a success outro. For DevTools MCP, ownership is released only after the corresponding unmerge is applied; if no unmerge action is written, the ownership marker is preserved for a later retry.
|
|
209
|
-
- `install`/`sync` also inject (and `disable`/`uninstall` remove) managed capability sections in `AGENTS.md` (OpenCode, Codex) or `CLAUDE.md` (Claude Code). File runtimes keep `jorgex:playwright`, `jorgex:chrome-devtools` and `jorgex:context7` independent; Pi 0.8.
|
|
209
|
+
- `install`/`sync` also inject (and `disable`/`uninstall` remove) managed capability sections in `AGENTS.md` (OpenCode, Codex) or `CLAUDE.md` (Claude Code). File runtimes keep `jorgex:playwright`, `jorgex:chrome-devtools` and `jorgex:context7` independent; Pi 0.8.28 projects Context7 after registering its isolated HTTP bridge. Stack does not add an Engram protocol section or filter provider tools. User content outside managed markers is preserved. `--target-dir` never reads the real preferences, so by default no section is emitted in target-dir runs — but explicit flags like `--devtools` simulate the MCP entry (and its DevTools block) inside the temp target without touching the real global state, and `install --dry-run --playwright` projects the Playwright section into the plan preview without installing anything. If reconciliation detects a partial or ambiguous system-prompt state, the CLI exits non-zero and recommends repairing it with `sync` or a repeated install; no write is attempted before marker validation. See [docs/references/browser-automation.md](docs/references/browser-automation.md) §2.7 for the full lifecycle.
|
|
210
210
|
|
|
211
211
|
### Update: Interactive Flow
|
|
212
212
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
registerOfficialSetupVerifier
|
|
4
|
+
} from "./chunk-B76ZJXXD.js";
|
|
5
|
+
import {
|
|
6
|
+
HOME,
|
|
7
|
+
samePath
|
|
8
|
+
} from "./chunk-NQZVJFV2.js";
|
|
9
|
+
|
|
10
|
+
// src/adapters/pi.ts
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
function piSystemPromptFile(targetDir) {
|
|
14
|
+
const configDir = targetDir === void 0 ? process.env.PI_CODING_AGENT_DIR ?? path.join(HOME, ".pi", "agent") : path.join(path.resolve(targetDir), "pi-agent");
|
|
15
|
+
return path.join(configDir, "AGENTS.md");
|
|
16
|
+
}
|
|
17
|
+
var piAdapter = {
|
|
18
|
+
id: "pi",
|
|
19
|
+
paths(configDir) {
|
|
20
|
+
const piConfigDir = path.dirname(piSystemPromptFile());
|
|
21
|
+
const agentsHome = samePath(configDir, piConfigDir) ? HOME : path.join(path.dirname(configDir), "home");
|
|
22
|
+
return {
|
|
23
|
+
systemPromptFile: path.join(configDir, "AGENTS.md"),
|
|
24
|
+
agentsDir: path.join(configDir, "agents"),
|
|
25
|
+
skillsDir: path.join(agentsHome, ".agents", "skills"),
|
|
26
|
+
commandsDir: path.join(configDir, "prompts"),
|
|
27
|
+
pluginsDir: null,
|
|
28
|
+
scriptsDir: path.join(configDir, "scripts"),
|
|
29
|
+
outputStylesDir: null,
|
|
30
|
+
profilesDir: null
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
renderCommand(file, content) {
|
|
34
|
+
return { file, content: content.replace(/\{\{input\}\}/g, "$ARGUMENTS") };
|
|
35
|
+
},
|
|
36
|
+
// La guía Context7 se habilita al adoptar su registro HTTP en Pi.
|
|
37
|
+
adaptSystemPromptSections(sections) {
|
|
38
|
+
const modular = { ...sections };
|
|
39
|
+
delete modular.context7;
|
|
40
|
+
return modular;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
function isRecord(value) {
|
|
44
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
45
|
+
}
|
|
46
|
+
function piPackageSource(entry) {
|
|
47
|
+
if (typeof entry === "string") return entry;
|
|
48
|
+
if (!isRecord(entry)) return null;
|
|
49
|
+
const source = entry["source"];
|
|
50
|
+
return typeof source === "string" ? source : null;
|
|
51
|
+
}
|
|
52
|
+
function isSafePiVersionSpec(spec) {
|
|
53
|
+
if (spec === "" || /[\r\n]/.test(spec)) return false;
|
|
54
|
+
if (spec.includes("/") || spec.includes("\\") || spec.includes(":") || spec.includes("#") || spec.includes("?")) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
if (spec.startsWith(".")) return false;
|
|
58
|
+
const lower = spec.toLowerCase();
|
|
59
|
+
if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz") || lower.endsWith(".tar")) return false;
|
|
60
|
+
return /^[A-Za-z0-9._\-^~><=| +*xXv]+$/.test(spec);
|
|
61
|
+
}
|
|
62
|
+
function claimsProtectedName(source, name) {
|
|
63
|
+
return source === `npm:${name}` || source.startsWith(`npm:${name}@`);
|
|
64
|
+
}
|
|
65
|
+
function isNamedPiSource(source, name) {
|
|
66
|
+
if (source === `npm:${name}`) return true;
|
|
67
|
+
const prefix = `npm:${name}@`;
|
|
68
|
+
if (!source.startsWith(prefix)) return false;
|
|
69
|
+
return isSafePiVersionSpec(source.slice(prefix.length));
|
|
70
|
+
}
|
|
71
|
+
function isGentleSource(source) {
|
|
72
|
+
return isNamedPiSource(source, "gentle-engram");
|
|
73
|
+
}
|
|
74
|
+
function isAdapterSource(source) {
|
|
75
|
+
return isNamedPiSource(source, "pi-mcp-adapter");
|
|
76
|
+
}
|
|
77
|
+
function isExactPiEngramMcp(value, engramBin) {
|
|
78
|
+
if (!isRecord(value)) return false;
|
|
79
|
+
if (typeof engramBin !== "string" || engramBin === "" || !path.isAbsolute(engramBin)) return false;
|
|
80
|
+
const keys = Object.keys(value).sort();
|
|
81
|
+
if (keys.length !== 4 || keys[0] !== "args" || keys[1] !== "command" || keys[2] !== "directTools" || keys[3] !== "lifecycle") {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
if (value["command"] !== engramBin) return false;
|
|
85
|
+
if (value["lifecycle"] !== "lazy") return false;
|
|
86
|
+
if (value["directTools"] !== false) return false;
|
|
87
|
+
const args = value["args"];
|
|
88
|
+
if (!Array.isArray(args) || args.length !== 2 || args[0] !== "mcp" || args[1] !== "--tools=agent") {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
function errnoCode(error) {
|
|
94
|
+
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : "UNKNOWN";
|
|
95
|
+
}
|
|
96
|
+
async function verifyOfficialSetup(args) {
|
|
97
|
+
void args.homeDir;
|
|
98
|
+
const passed = [];
|
|
99
|
+
const missing = [];
|
|
100
|
+
let duplicates = false;
|
|
101
|
+
let packagesDetail = null;
|
|
102
|
+
try {
|
|
103
|
+
const raw = fs.readFileSync(path.join(args.configDir, "settings.json"), "utf8");
|
|
104
|
+
let parsed;
|
|
105
|
+
try {
|
|
106
|
+
parsed = JSON.parse(raw);
|
|
107
|
+
} catch {
|
|
108
|
+
packagesDetail = "packages:invalid";
|
|
109
|
+
missing.push(packagesDetail);
|
|
110
|
+
packagesDetail = "singleton inv\xE1lido en settings.json (JSON no parseable)";
|
|
111
|
+
throw new Error("__invalid__");
|
|
112
|
+
}
|
|
113
|
+
if (!isRecord(parsed) || !Array.isArray(parsed["packages"])) {
|
|
114
|
+
missing.push("packages:missing");
|
|
115
|
+
packagesDetail = "singleton incompleto en settings.json (falta packages[])";
|
|
116
|
+
} else {
|
|
117
|
+
const sources = parsed["packages"].map(piPackageSource);
|
|
118
|
+
const unsafeClaimed = sources.filter(
|
|
119
|
+
(source) => source !== null && (claimsProtectedName(source, "gentle-engram") && !isGentleSource(source) || claimsProtectedName(source, "pi-mcp-adapter") && !isAdapterSource(source))
|
|
120
|
+
);
|
|
121
|
+
if (unsafeClaimed.length > 0) {
|
|
122
|
+
missing.push("packages:invalid");
|
|
123
|
+
packagesDetail = `singleton inv\xE1lido en settings.json (selector inseguro que reclama nombre protegido: ${unsafeClaimed[0]})`;
|
|
124
|
+
} else {
|
|
125
|
+
const gentle = sources.filter((source) => source !== null && isGentleSource(source));
|
|
126
|
+
const adapter = sources.filter((source) => source !== null && isAdapterSource(source));
|
|
127
|
+
if (gentle.length === 1 && adapter.length === 1) {
|
|
128
|
+
passed.push("packages");
|
|
129
|
+
packagesDetail = null;
|
|
130
|
+
} else {
|
|
131
|
+
duplicates = gentle.length > 1 || adapter.length > 1;
|
|
132
|
+
if (duplicates) missing.push("packages:duplicate");
|
|
133
|
+
else if (gentle.length === 0 || adapter.length === 0) {
|
|
134
|
+
const absent = [
|
|
135
|
+
...gentle.length === 0 ? ["gentle-engram"] : [],
|
|
136
|
+
...adapter.length === 0 ? ["pi-mcp-adapter"] : []
|
|
137
|
+
].join(" + ");
|
|
138
|
+
missing.push("packages:missing");
|
|
139
|
+
void absent;
|
|
140
|
+
} else {
|
|
141
|
+
missing.push("packages:missing");
|
|
142
|
+
}
|
|
143
|
+
const detail2 = duplicates ? `singleton duplicado en settings.json (gentle-engram x${gentle.length}, pi-mcp-adapter x${adapter.length})` : `singleton incompleto en settings.json (falta ${gentle.length === 0 ? "gentle-engram" : "pi-mcp-adapter"})`;
|
|
144
|
+
packagesDetail = detail2;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (error) {
|
|
149
|
+
if (error instanceof Error && error.message === "__invalid__") {
|
|
150
|
+
} else {
|
|
151
|
+
const code = errnoCode(error);
|
|
152
|
+
if (code === "ENOENT") {
|
|
153
|
+
missing.push("packages:missing");
|
|
154
|
+
packagesDetail = "singleton incompleto en settings.json (ausente)";
|
|
155
|
+
} else {
|
|
156
|
+
missing.push("packages:unreadable");
|
|
157
|
+
packagesDetail = `singleton ilegible en settings.json (unreadable ${code})`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
let mcpDetail = null;
|
|
162
|
+
if (typeof args.engramBin !== "string" || args.engramBin === "") {
|
|
163
|
+
missing.push("mcp:missing");
|
|
164
|
+
mcpDetail = "mcp inv\xE1lido en mcp.json (sin engramBin absoluto)";
|
|
165
|
+
} else {
|
|
166
|
+
try {
|
|
167
|
+
const raw = fs.readFileSync(path.join(args.configDir, "mcp.json"), "utf8");
|
|
168
|
+
let parsed;
|
|
169
|
+
try {
|
|
170
|
+
parsed = JSON.parse(raw);
|
|
171
|
+
} catch {
|
|
172
|
+
missing.push("mcp:invalid");
|
|
173
|
+
mcpDetail = "mcp inv\xE1lido en mcp.json (JSON no parseable)";
|
|
174
|
+
parsed = null;
|
|
175
|
+
throw new Error("__invalid_mcp__");
|
|
176
|
+
}
|
|
177
|
+
if (!isRecord(parsed)) {
|
|
178
|
+
missing.push("mcp:invalid");
|
|
179
|
+
mcpDetail = "mcp inv\xE1lido en mcp.json (ra\xEDz no objeto)";
|
|
180
|
+
} else {
|
|
181
|
+
const servers = parsed["mcpServers"];
|
|
182
|
+
if (!isRecord(servers) || servers["engram"] === void 0) {
|
|
183
|
+
const alt = isRecord(parsed["servers"]) ? parsed["servers"]["engram"] : void 0;
|
|
184
|
+
if (alt === void 0) {
|
|
185
|
+
missing.push("mcp:missing");
|
|
186
|
+
mcpDetail = "mcp ausente en mcp.json (falta mcpServers.engram)";
|
|
187
|
+
} else if (isExactPiEngramMcp(alt, args.engramBin)) {
|
|
188
|
+
passed.push("mcp");
|
|
189
|
+
mcpDetail = null;
|
|
190
|
+
} else {
|
|
191
|
+
missing.push("mcp:invalid");
|
|
192
|
+
mcpDetail = `mcp inv\xE1lido en mcp.json (se exige forma directa can\xF3nica: command === engramBin absoluto, args === ["mcp","--tools=agent"], lifecycle === "lazy", directTools === false)`;
|
|
193
|
+
}
|
|
194
|
+
} else if (isExactPiEngramMcp(servers["engram"], args.engramBin)) {
|
|
195
|
+
const legacy = isRecord(parsed["servers"]) ? parsed["servers"]["engram"] : void 0;
|
|
196
|
+
if (legacy !== void 0) {
|
|
197
|
+
missing.push("mcp:conflict");
|
|
198
|
+
mcpDetail = "mcp en conflicto en mcp.json (servers.engram legacy coexiste con mcpServers.engram can\xF3nico; conflicto fail-closed sin activar Pi)";
|
|
199
|
+
} else {
|
|
200
|
+
passed.push("mcp");
|
|
201
|
+
mcpDetail = null;
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
const foreign = isRecord(servers["engram"]) && typeof servers["engram"]["command"] === "string" && servers["engram"]["command"] !== args.engramBin && !String(servers["engram"]["command"]).includes("node") && !JSON.stringify(servers["engram"]).includes(args.engramBin);
|
|
205
|
+
missing.push(foreign ? "mcp:conflict" : "mcp:invalid");
|
|
206
|
+
mcpDetail = foreign ? `mcp en conflicto en mcp.json (no apunta al binario oficial ${args.engramBin}); se preserva sin reescribir` : `mcp inv\xE1lido en mcp.json (se exige forma directa can\xF3nica: command === engramBin absoluto, args === ["mcp","--tools=agent"], lifecycle === "lazy", directTools === false)`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error instanceof Error && error.message === "__invalid_mcp__") {
|
|
211
|
+
} else {
|
|
212
|
+
const code = errnoCode(error);
|
|
213
|
+
if (code === "ENOENT") {
|
|
214
|
+
if (mcpDetail === null && !missing.some((entry) => entry.startsWith("mcp:"))) {
|
|
215
|
+
missing.push("mcp:missing");
|
|
216
|
+
mcpDetail = "mcp ausente en mcp.json (falta mcpServers.engram)";
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
missing.push("mcp:unreadable");
|
|
220
|
+
mcpDetail = `mcp ilegible en mcp.json (unreadable ${code}, parcial sin activar Pi)`;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (missing.length === 0) {
|
|
226
|
+
return { ok: true, layers: passed, duplicates: false };
|
|
227
|
+
}
|
|
228
|
+
const detail = `Pi: setup oficial Engram incompleto (${[
|
|
229
|
+
...packagesDetail !== null ? [packagesDetail] : [],
|
|
230
|
+
...mcpDetail !== null ? [mcpDetail] : []
|
|
231
|
+
].join("; ")}; falta: ${missing.join(", ")}).`;
|
|
232
|
+
return {
|
|
233
|
+
ok: false,
|
|
234
|
+
layers: [...passed, ...missing],
|
|
235
|
+
duplicates,
|
|
236
|
+
reason: detail
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
registerOfficialSetupVerifier("pi", verifyOfficialSetup);
|
|
240
|
+
|
|
241
|
+
export {
|
|
242
|
+
piSystemPromptFile,
|
|
243
|
+
piAdapter,
|
|
244
|
+
verifyOfficialSetup
|
|
245
|
+
};
|
|
@@ -5,14 +5,16 @@ import {
|
|
|
5
5
|
hasManagedMarkdownSection,
|
|
6
6
|
isCanonicalMcpServerEnabled,
|
|
7
7
|
loadCanonicalDefaults,
|
|
8
|
-
readTextIfExists,
|
|
9
|
-
registerOfficialSetupVerifier,
|
|
10
8
|
removeNativeHooks,
|
|
11
9
|
removeSystemPromptSections,
|
|
12
10
|
resolveAgentModel,
|
|
13
11
|
upsertJson,
|
|
14
12
|
upsertNativeHooks
|
|
15
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-66WVKOU4.js";
|
|
14
|
+
import {
|
|
15
|
+
readTextIfExists,
|
|
16
|
+
registerOfficialSetupVerifier
|
|
17
|
+
} from "./chunk-B76ZJXXD.js";
|
|
16
18
|
import {
|
|
17
19
|
stackRoot
|
|
18
20
|
} from "./chunk-NQZVJFV2.js";
|
|
@@ -24,13 +26,6 @@ import { isDeepStrictEqual } from "util";
|
|
|
24
26
|
function yamlString(value) {
|
|
25
27
|
return JSON.stringify(value);
|
|
26
28
|
}
|
|
27
|
-
var memoryTools = (names) => names.flatMap((n) => [`mcp__engram__${n}`, `mcp__plugin_engram_engram__${n}`]);
|
|
28
|
-
var MEMORY_TOOLS = memoryTools(["mem_save", "mem_search", "mem_context"]);
|
|
29
|
-
var ENGRAM_AGENT_TOOLS = [
|
|
30
|
-
"Read",
|
|
31
|
-
"Skill",
|
|
32
|
-
...memoryTools(["mem_context", "mem_search", "mem_get_observation", "mem_timeline", "mem_current_project"])
|
|
33
|
-
];
|
|
34
29
|
function isRecord(value) {
|
|
35
30
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
36
31
|
}
|
|
@@ -88,11 +83,10 @@ function hasClaudeManualApproval(configDir) {
|
|
|
88
83
|
}
|
|
89
84
|
}
|
|
90
85
|
function toolsFor(agent) {
|
|
91
|
-
if (agent.name === "engram") return
|
|
86
|
+
if (agent.name === "engram") return null;
|
|
92
87
|
if (!agent.readonly) return null;
|
|
93
88
|
const tools = ["Read", "Grep", "Glob", "Skill"];
|
|
94
89
|
if (agent.bash !== "none") tools.push("Bash");
|
|
95
|
-
tools.push(...MEMORY_TOOLS);
|
|
96
90
|
return tools.join(", ");
|
|
97
91
|
}
|
|
98
92
|
function hasEngramPlugin(configDir) {
|
|
@@ -136,9 +130,6 @@ var claudeCodeAdapter = {
|
|
|
136
130
|
}] : []
|
|
137
131
|
]);
|
|
138
132
|
},
|
|
139
|
-
injectEngramProtocol(ctx) {
|
|
140
|
-
return !hasEngramPlugin(ctx.configDir);
|
|
141
|
-
},
|
|
142
133
|
paths(configDir) {
|
|
143
134
|
return {
|
|
144
135
|
systemPromptFile: path.join(configDir, "CLAUDE.md"),
|