@ijfw/install 1.1.0 → 1.1.2
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/CHANGELOG.md +66 -0
- package/dist/ijfw.js +1324 -8
- package/dist/install.js +9 -2
- package/dist/uninstall.js +99 -10
- package/docs/GUIDE.md +556 -0
- package/docs/guide/assets/README.md +11 -0
- package/docs/guide/assets/dashboard.png +0 -0
- package/docs/guide/assets/memory-recall.svg +31 -0
- package/docs/guide/assets/session-receipt.svg +30 -0
- package/docs/guide/assets/trident-demo.svg +36 -0
- package/package.json +6 -4
package/dist/install.js
CHANGED
|
@@ -216,7 +216,14 @@ function cloneOrPull(dir, branch) {
|
|
|
216
216
|
function runInstallScript(dir) {
|
|
217
217
|
const script = join2(dir, "scripts", "install.sh");
|
|
218
218
|
if (!existsSync2(script)) throw new Error(`IJFW install script not found at ${script} -- re-run the installer to restore it.`);
|
|
219
|
-
const
|
|
219
|
+
const canonicalDir = join2(homedir2(), ".ijfw");
|
|
220
|
+
const isCustomDir = resolve(dir) !== canonicalDir ? "1" : "0";
|
|
221
|
+
const env = {
|
|
222
|
+
...process.env,
|
|
223
|
+
IJFW_NONINTERACTIVE: process.env.CI ? "1" : process.env.IJFW_NONINTERACTIVE ?? "",
|
|
224
|
+
IJFW_HOME: dir,
|
|
225
|
+
IJFW_CUSTOM_DIR: isCustomDir
|
|
226
|
+
};
|
|
220
227
|
const r = spawnSync("bash", ["scripts/install.sh"], { cwd: dir, stdio: "inherit", env });
|
|
221
228
|
if (r.status !== 0) throw new Error(`IJFW platform config step did not complete (exit ${r.status}) -- run ijfw doctor to see what to fix.`);
|
|
222
229
|
}
|
|
@@ -253,7 +260,7 @@ async function main() {
|
|
|
253
260
|
console.log(` marketplace registered in ${settingsPath}`);
|
|
254
261
|
}
|
|
255
262
|
console.log("");
|
|
256
|
-
console.log("IJFW now active across
|
|
263
|
+
console.log("IJFW now active across 8 platforms -- one memory layer, all your AIs, zero config.");
|
|
257
264
|
console.log(" Run `ijfw demo` to see the Trident in action.");
|
|
258
265
|
console.log(" Run `ijfw doctor` to confirm which auditors are reachable.");
|
|
259
266
|
console.log(" Privacy: everything stays local. See NO_TELEMETRY.md.");
|
package/dist/uninstall.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { existsSync as existsSync2, rmSync, cpSync, mkdtempSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2, readdirSync } from "node:fs";
|
|
5
5
|
import { resolve, join as join2 } from "node:path";
|
|
6
6
|
import { homedir as homedir2, tmpdir } from "node:os";
|
|
7
|
+
import { spawnSync } from "node:child_process";
|
|
7
8
|
|
|
8
9
|
// src/marketplace.js
|
|
9
10
|
import { readFileSync, writeFileSync, renameSync, existsSync, mkdirSync } from "node:fs";
|
|
@@ -156,12 +157,74 @@ function removeCodexHooks(p) {
|
|
|
156
157
|
} catch {
|
|
157
158
|
return false;
|
|
158
159
|
}
|
|
159
|
-
if (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
if (Array.isArray(doc)) {
|
|
161
|
+
const before = doc.length;
|
|
162
|
+
const after = doc.filter((h) => !(h && h._ijfw));
|
|
163
|
+
if (after.length === before) return false;
|
|
164
|
+
backupFile(p);
|
|
165
|
+
writeFileSync2(p, JSON.stringify(after, null, 2) + "\n");
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
if (!doc || typeof doc !== "object" || !doc.hooks) return false;
|
|
169
|
+
if (doc.hooks && typeof doc.hooks === "object" && !Array.isArray(doc.hooks)) {
|
|
170
|
+
let changed = false;
|
|
171
|
+
for (const ev of Object.keys(doc.hooks)) {
|
|
172
|
+
const groups = doc.hooks[ev];
|
|
173
|
+
if (!Array.isArray(groups)) continue;
|
|
174
|
+
const before = groups.length;
|
|
175
|
+
doc.hooks[ev] = groups.filter((g) => {
|
|
176
|
+
if (!g || !Array.isArray(g.hooks)) return true;
|
|
177
|
+
return !g.hooks.some((h) => h && h._ijfw);
|
|
178
|
+
});
|
|
179
|
+
if (doc.hooks[ev].length !== before) changed = true;
|
|
180
|
+
}
|
|
181
|
+
if (!changed) return false;
|
|
182
|
+
backupFile(p);
|
|
183
|
+
writeFileSync2(p, JSON.stringify(doc, null, 2) + "\n");
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
if (Array.isArray(doc.hooks)) {
|
|
187
|
+
const before = doc.hooks.length;
|
|
188
|
+
doc.hooks = doc.hooks.filter((h) => !(h && h._ijfw));
|
|
189
|
+
if (doc.hooks.length === before) return false;
|
|
190
|
+
backupFile(p);
|
|
191
|
+
writeFileSync2(p, JSON.stringify(doc, null, 2) + "\n");
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
function removeYamlMcpEntry(p) {
|
|
197
|
+
if (!existsSync2(p)) return false;
|
|
198
|
+
const raw = readFileSync2(p, "utf8");
|
|
199
|
+
if (!/\bijfw-memory\b/.test(raw)) return false;
|
|
200
|
+
const py = spawnSync("python3", ["-c", `
|
|
201
|
+
import sys, yaml
|
|
202
|
+
p = sys.argv[1]
|
|
203
|
+
with open(p) as f: raw = f.read()
|
|
204
|
+
doc = yaml.safe_load(raw) if raw.strip() else {}
|
|
205
|
+
if not isinstance(doc, dict): sys.exit(2)
|
|
206
|
+
srv = doc.get("mcp_servers")
|
|
207
|
+
if not isinstance(srv, dict) or "ijfw-memory" not in srv: sys.exit(3)
|
|
208
|
+
del srv["ijfw-memory"]
|
|
209
|
+
if not srv: del doc["mcp_servers"]
|
|
210
|
+
with open(p + ".tmp", "w") as f:
|
|
211
|
+
yaml.safe_dump(doc, f, sort_keys=False, default_flow_style=False)
|
|
212
|
+
import os; os.replace(p + ".tmp", p)
|
|
213
|
+
`, p], { encoding: "utf8" });
|
|
214
|
+
if (py.status === 0) {
|
|
215
|
+
backupFile(p);
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
const stripped = raw.replace(
|
|
219
|
+
/^ ijfw-memory:\n(?: .*\n)*(?:# IJFW-MCP-END ijfw-memory\n)?/m,
|
|
220
|
+
""
|
|
221
|
+
).replace(
|
|
222
|
+
/# IJFW-MCP-BEGIN ijfw-memory\n(?:.*\n)*?# IJFW-MCP-END ijfw-memory\n/,
|
|
223
|
+
""
|
|
224
|
+
);
|
|
225
|
+
if (stripped === raw) return false;
|
|
163
226
|
backupFile(p);
|
|
164
|
-
writeFileSync2(p,
|
|
227
|
+
writeFileSync2(p, stripped);
|
|
165
228
|
return true;
|
|
166
229
|
}
|
|
167
230
|
function removeIjfwSkills(dir) {
|
|
@@ -205,6 +268,26 @@ function cleanPlatforms() {
|
|
|
205
268
|
}
|
|
206
269
|
const vscodeMcp = join2(".vscode", "mcp.json");
|
|
207
270
|
if (removeJsonMcpEntry(vscodeMcp)) removed.push(".vscode/mcp.json (removed ijfw-memory)");
|
|
271
|
+
if (removeYamlMcpEntry(join2(HOME, ".hermes", "config.yaml"))) {
|
|
272
|
+
removed.push("~/.hermes/config.yaml (removed ijfw-memory)");
|
|
273
|
+
}
|
|
274
|
+
const hermesSkills = removeIjfwSkills(join2(HOME, ".hermes", "skills"));
|
|
275
|
+
if (hermesSkills > 0) removed.push(`~/.hermes/skills/ijfw-* (removed ${hermesSkills} skill dirs)`);
|
|
276
|
+
const hermesMd = join2(HOME, ".hermes", "HERMES.md");
|
|
277
|
+
if (existsSync2(hermesMd)) {
|
|
278
|
+
rmSync(hermesMd, { force: true });
|
|
279
|
+
removed.push("~/.hermes/HERMES.md");
|
|
280
|
+
}
|
|
281
|
+
if (removeYamlMcpEntry(join2(HOME, ".wayland", "config.yaml"))) {
|
|
282
|
+
removed.push("~/.wayland/config.yaml (removed ijfw-memory)");
|
|
283
|
+
}
|
|
284
|
+
const waylandSkills = removeIjfwSkills(join2(HOME, ".wayland", "skills"));
|
|
285
|
+
if (waylandSkills > 0) removed.push(`~/.wayland/skills/ijfw-* (removed ${waylandSkills} skill dirs)`);
|
|
286
|
+
const waylandMd = join2(HOME, ".wayland", "WAYLAND.md");
|
|
287
|
+
if (existsSync2(waylandMd)) {
|
|
288
|
+
rmSync(waylandMd, { force: true });
|
|
289
|
+
removed.push("~/.wayland/WAYLAND.md");
|
|
290
|
+
}
|
|
208
291
|
return removed;
|
|
209
292
|
}
|
|
210
293
|
function resolveTarget(opt) {
|
|
@@ -238,17 +321,23 @@ async function main() {
|
|
|
238
321
|
console.log(" memory/ was not present; nothing to preserve");
|
|
239
322
|
}
|
|
240
323
|
}
|
|
241
|
-
|
|
324
|
+
const canonicalDir = join2(HOME, ".ijfw");
|
|
325
|
+
const isCanonical = target === canonicalDir;
|
|
326
|
+
if (isCanonical && !opts.noMarketplace) {
|
|
242
327
|
const settingsPath = claudeSettingsPath();
|
|
243
328
|
if (existsSync2(settingsPath)) {
|
|
244
329
|
unmergeMarketplace(settingsPath);
|
|
245
330
|
console.log(` marketplace removed from ${settingsPath}`);
|
|
246
331
|
}
|
|
247
332
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
333
|
+
if (isCanonical) {
|
|
334
|
+
const cleaned = cleanPlatforms();
|
|
335
|
+
if (cleaned.length > 0) {
|
|
336
|
+
console.log(" platform configs cleaned:");
|
|
337
|
+
for (const line of cleaned) console.log(` ${line}`);
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
console.log(` custom-dir uninstall (${target}) -- platform configs in your real home left untouched.`);
|
|
252
341
|
}
|
|
253
342
|
console.log("\nIJFW uninstalled. Thanks for trying it.");
|
|
254
343
|
process.exit(0);
|