opencode-mempalace 0.1.5 → 0.1.7
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/dist/auto-update.d.ts +11 -0
- package/dist/index.js +211 -17
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface UpdateResult {
|
|
2
|
+
currentVersion: string | null;
|
|
3
|
+
latestVersion: string | null;
|
|
4
|
+
updated: boolean;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Check npm registry for a newer version and install it if available.
|
|
9
|
+
* @param runInstall - Callback to run `bun install` in a given directory. Returns true on success.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkAndUpdate(runInstall: (cwd: string) => Promise<boolean>): Promise<UpdateResult>;
|
package/dist/index.js
CHANGED
|
@@ -12334,12 +12334,182 @@ function tool(input) {
|
|
|
12334
12334
|
return input;
|
|
12335
12335
|
}
|
|
12336
12336
|
tool.schema = exports_external;
|
|
12337
|
+
// src/auto-update.ts
|
|
12338
|
+
import * as fs from "fs";
|
|
12339
|
+
import * as path from "path";
|
|
12340
|
+
import * as os from "os";
|
|
12341
|
+
import * as crypto from "crypto";
|
|
12342
|
+
var PACKAGE_NAME = "opencode-mempalace";
|
|
12343
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags`;
|
|
12344
|
+
var NPM_FETCH_TIMEOUT = 5000;
|
|
12345
|
+
function getOpenCodeCacheDir() {
|
|
12346
|
+
if (process.platform === "win32") {
|
|
12347
|
+
const appdata = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
|
12348
|
+
return path.join(appdata, "opencode");
|
|
12349
|
+
}
|
|
12350
|
+
return path.join(process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), ".cache"), "opencode");
|
|
12351
|
+
}
|
|
12352
|
+
function getOpenCodeConfigDir() {
|
|
12353
|
+
if (process.platform === "win32") {
|
|
12354
|
+
const appdata = process.env.APPDATA ?? path.join(os.homedir(), "AppData", "Roaming");
|
|
12355
|
+
return path.join(appdata, "opencode");
|
|
12356
|
+
}
|
|
12357
|
+
return path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "opencode");
|
|
12358
|
+
}
|
|
12359
|
+
var CACHE_DIR = path.join(getOpenCodeCacheDir(), "packages");
|
|
12360
|
+
var CONFIG_DIR = getOpenCodeConfigDir();
|
|
12361
|
+
function getCachedVersion() {
|
|
12362
|
+
const locations = [
|
|
12363
|
+
path.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json"),
|
|
12364
|
+
path.join(CACHE_DIR, `${PACKAGE_NAME}@latest`, "node_modules", PACKAGE_NAME, "package.json"),
|
|
12365
|
+
path.join(CONFIG_DIR, "node_modules", PACKAGE_NAME, "package.json")
|
|
12366
|
+
];
|
|
12367
|
+
for (const pkgPath of locations) {
|
|
12368
|
+
try {
|
|
12369
|
+
if (fs.existsSync(pkgPath)) {
|
|
12370
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
12371
|
+
if (pkg.version)
|
|
12372
|
+
return pkg.version;
|
|
12373
|
+
}
|
|
12374
|
+
} catch {}
|
|
12375
|
+
}
|
|
12376
|
+
return null;
|
|
12377
|
+
}
|
|
12378
|
+
async function getLatestVersion() {
|
|
12379
|
+
const controller = new AbortController;
|
|
12380
|
+
const timeoutId = setTimeout(() => controller.abort(), NPM_FETCH_TIMEOUT);
|
|
12381
|
+
try {
|
|
12382
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
12383
|
+
signal: controller.signal,
|
|
12384
|
+
headers: { Accept: "application/json" }
|
|
12385
|
+
});
|
|
12386
|
+
if (!response.ok)
|
|
12387
|
+
return null;
|
|
12388
|
+
const data = await response.json();
|
|
12389
|
+
return data.latest ?? null;
|
|
12390
|
+
} catch {
|
|
12391
|
+
return null;
|
|
12392
|
+
} finally {
|
|
12393
|
+
clearTimeout(timeoutId);
|
|
12394
|
+
}
|
|
12395
|
+
}
|
|
12396
|
+
function stripTrailingCommas(json2) {
|
|
12397
|
+
return json2.replace(/,(\s*[}\]])/g, "$1");
|
|
12398
|
+
}
|
|
12399
|
+
function invalidatePackage() {
|
|
12400
|
+
const pkgDirs = [
|
|
12401
|
+
path.join(CONFIG_DIR, "node_modules", PACKAGE_NAME),
|
|
12402
|
+
path.join(CACHE_DIR, "node_modules", PACKAGE_NAME),
|
|
12403
|
+
path.join(CACHE_DIR, `${PACKAGE_NAME}@latest`, "node_modules", PACKAGE_NAME)
|
|
12404
|
+
];
|
|
12405
|
+
let removed = false;
|
|
12406
|
+
for (const dir of pkgDirs) {
|
|
12407
|
+
try {
|
|
12408
|
+
if (fs.existsSync(dir)) {
|
|
12409
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
12410
|
+
removed = true;
|
|
12411
|
+
}
|
|
12412
|
+
} catch {}
|
|
12413
|
+
}
|
|
12414
|
+
for (const baseDir of [CACHE_DIR, path.join(CACHE_DIR, `${PACKAGE_NAME}@latest`)]) {
|
|
12415
|
+
const textLock = path.join(baseDir, "bun.lock");
|
|
12416
|
+
const binaryLock = path.join(baseDir, "bun.lockb");
|
|
12417
|
+
if (fs.existsSync(textLock)) {
|
|
12418
|
+
try {
|
|
12419
|
+
const content = fs.readFileSync(textLock, "utf-8");
|
|
12420
|
+
const lock = JSON.parse(stripTrailingCommas(content));
|
|
12421
|
+
if (lock.packages?.[PACKAGE_NAME]) {
|
|
12422
|
+
delete lock.packages[PACKAGE_NAME];
|
|
12423
|
+
fs.writeFileSync(textLock, JSON.stringify(lock, null, 2));
|
|
12424
|
+
removed = true;
|
|
12425
|
+
}
|
|
12426
|
+
} catch {}
|
|
12427
|
+
} else if (fs.existsSync(binaryLock)) {
|
|
12428
|
+
try {
|
|
12429
|
+
fs.unlinkSync(binaryLock);
|
|
12430
|
+
removed = true;
|
|
12431
|
+
} catch {}
|
|
12432
|
+
}
|
|
12433
|
+
}
|
|
12434
|
+
return removed;
|
|
12435
|
+
}
|
|
12436
|
+
function syncCachePackageJson(pkgJsonPath) {
|
|
12437
|
+
try {
|
|
12438
|
+
if (!fs.existsSync(pkgJsonPath)) {
|
|
12439
|
+
fs.mkdirSync(path.dirname(pkgJsonPath), { recursive: true });
|
|
12440
|
+
fs.writeFileSync(pkgJsonPath, JSON.stringify({ dependencies: { [PACKAGE_NAME]: "latest" } }, null, 2));
|
|
12441
|
+
return true;
|
|
12442
|
+
}
|
|
12443
|
+
const content = fs.readFileSync(pkgJsonPath, "utf-8");
|
|
12444
|
+
const pkg = JSON.parse(content);
|
|
12445
|
+
if (!pkg.dependencies)
|
|
12446
|
+
pkg.dependencies = {};
|
|
12447
|
+
if (pkg.dependencies[PACKAGE_NAME] === "latest")
|
|
12448
|
+
return true;
|
|
12449
|
+
pkg.dependencies[PACKAGE_NAME] = "latest";
|
|
12450
|
+
const tmpPath = `${pkgJsonPath}.${crypto.randomUUID()}`;
|
|
12451
|
+
fs.writeFileSync(tmpPath, JSON.stringify(pkg, null, 2));
|
|
12452
|
+
fs.renameSync(tmpPath, pkgJsonPath);
|
|
12453
|
+
return true;
|
|
12454
|
+
} catch {
|
|
12455
|
+
return false;
|
|
12456
|
+
}
|
|
12457
|
+
}
|
|
12458
|
+
function resolveActiveWorkspace() {
|
|
12459
|
+
const configInstall = path.join(CONFIG_DIR, "node_modules", PACKAGE_NAME, "package.json");
|
|
12460
|
+
const cacheInstall = path.join(CACHE_DIR, "node_modules", PACKAGE_NAME, "package.json");
|
|
12461
|
+
if (fs.existsSync(configInstall))
|
|
12462
|
+
return CONFIG_DIR;
|
|
12463
|
+
if (fs.existsSync(cacheInstall))
|
|
12464
|
+
return CACHE_DIR;
|
|
12465
|
+
if (fs.existsSync(path.join(CACHE_DIR, "package.json")))
|
|
12466
|
+
return CACHE_DIR;
|
|
12467
|
+
return CONFIG_DIR;
|
|
12468
|
+
}
|
|
12469
|
+
async function checkAndUpdate(runInstall) {
|
|
12470
|
+
const currentVersion = getCachedVersion();
|
|
12471
|
+
const latestVersion = await getLatestVersion();
|
|
12472
|
+
if (!currentVersion || !latestVersion) {
|
|
12473
|
+
return { currentVersion, latestVersion, updated: false };
|
|
12474
|
+
}
|
|
12475
|
+
if (currentVersion === latestVersion) {
|
|
12476
|
+
return { currentVersion, latestVersion, updated: false };
|
|
12477
|
+
}
|
|
12478
|
+
try {
|
|
12479
|
+
syncCachePackageJson(path.join(CACHE_DIR, "package.json"));
|
|
12480
|
+
const atLatestDir = path.join(CACHE_DIR, `${PACKAGE_NAME}@latest`);
|
|
12481
|
+
if (fs.existsSync(atLatestDir)) {
|
|
12482
|
+
syncCachePackageJson(path.join(atLatestDir, "package.json"));
|
|
12483
|
+
}
|
|
12484
|
+
invalidatePackage();
|
|
12485
|
+
const activeWorkspace = resolveActiveWorkspace();
|
|
12486
|
+
const success2 = await runInstall(activeWorkspace);
|
|
12487
|
+
if (success2) {
|
|
12488
|
+
if (activeWorkspace !== CACHE_DIR) {
|
|
12489
|
+
await runInstall(CACHE_DIR).catch(() => {});
|
|
12490
|
+
}
|
|
12491
|
+
if (activeWorkspace !== atLatestDir && fs.existsSync(path.join(atLatestDir, "package.json"))) {
|
|
12492
|
+
await runInstall(atLatestDir).catch(() => {});
|
|
12493
|
+
}
|
|
12494
|
+
}
|
|
12495
|
+
return {
|
|
12496
|
+
currentVersion,
|
|
12497
|
+
latestVersion,
|
|
12498
|
+
updated: success2,
|
|
12499
|
+
error: success2 ? undefined : "bun install failed"
|
|
12500
|
+
};
|
|
12501
|
+
} catch (err) {
|
|
12502
|
+
return {
|
|
12503
|
+
currentVersion,
|
|
12504
|
+
latestVersion,
|
|
12505
|
+
updated: false,
|
|
12506
|
+
error: err instanceof Error ? err.message : String(err)
|
|
12507
|
+
};
|
|
12508
|
+
}
|
|
12509
|
+
}
|
|
12510
|
+
|
|
12337
12511
|
// src/index.ts
|
|
12338
|
-
var DEFAULT_MCP_COMMAND = [
|
|
12339
|
-
"bun",
|
|
12340
|
-
"run",
|
|
12341
|
-
"/home/dat/mempalace-js/src/mcp-server.ts"
|
|
12342
|
-
];
|
|
12512
|
+
var DEFAULT_MCP_COMMAND = ["npx", "-y", "-p", "@nguyentamdat/mempalace", "mempalace-mcp"];
|
|
12343
12513
|
var PALACE_PROTOCOL = `IMPORTANT \u2014 MemPalace Memory Protocol:
|
|
12344
12514
|
1. ON WAKE-UP: Call mempalace_status to load palace overview + AAAK spec.
|
|
12345
12515
|
2. BEFORE RESPONDING about any person, project, or past event: call mempalace_kg_query or mempalace_search FIRST. Never guess \u2014 verify.
|
|
@@ -12356,12 +12526,31 @@ On session start, load mempalace context by calling these tools directly (do NOT
|
|
|
12356
12526
|
|
|
12357
12527
|
Call both in parallel. If either fails (ChromaDB not running), skip silently and continue.
|
|
12358
12528
|
Use the results to inform your responses \u2014 do not announce or summarize them unless the user asks.
|
|
12359
|
-
Proceed with the user's request immediately
|
|
12360
|
-
|
|
12529
|
+
Proceed with the user's request immediately.
|
|
12530
|
+
<!-- MEMPALACE -->`;
|
|
12531
|
+
var mempalacePlugin = async (input, options) => {
|
|
12361
12532
|
const opts = options ?? {};
|
|
12362
12533
|
const mcpCommand = opts.mcpCommand ?? DEFAULT_MCP_COMMAND;
|
|
12363
12534
|
const sessionsSeen = new Set;
|
|
12364
12535
|
const diaryWritten = new Set;
|
|
12536
|
+
let updateResult = null;
|
|
12537
|
+
if (!opts.disableAutoUpdate) {
|
|
12538
|
+
checkAndUpdate(async (cwd) => {
|
|
12539
|
+
try {
|
|
12540
|
+
const result = await input.$`bun install`.cwd(cwd).quiet().nothrow();
|
|
12541
|
+
return result.exitCode === 0;
|
|
12542
|
+
} catch {
|
|
12543
|
+
return false;
|
|
12544
|
+
}
|
|
12545
|
+
}).then((result) => {
|
|
12546
|
+
updateResult = result;
|
|
12547
|
+
if (result.updated) {
|
|
12548
|
+
console.log(`[opencode-mempalace] Auto-updated: ${result.currentVersion} \u2192 ${result.latestVersion}. Restart to apply.`);
|
|
12549
|
+
} else if (result.error) {
|
|
12550
|
+
console.log(`[opencode-mempalace] Update available: ${result.currentVersion} \u2192 ${result.latestVersion} (install failed: ${result.error})`);
|
|
12551
|
+
}
|
|
12552
|
+
}).catch(() => {});
|
|
12553
|
+
}
|
|
12365
12554
|
return {
|
|
12366
12555
|
config: opts.disableMcp ? undefined : async (config2) => {
|
|
12367
12556
|
if (!config2.mcp)
|
|
@@ -12374,23 +12563,28 @@ var mempalacePlugin = async (_input, options) => {
|
|
|
12374
12563
|
};
|
|
12375
12564
|
}
|
|
12376
12565
|
},
|
|
12377
|
-
"experimental.chat.system.transform":
|
|
12378
|
-
|
|
12566
|
+
"experimental.chat.system.transform": async (_input, output) => {
|
|
12567
|
+
if (!opts.disableProtocol) {
|
|
12568
|
+
output.system.push(PALACE_PROTOCOL);
|
|
12569
|
+
}
|
|
12570
|
+
if (updateResult?.updated) {
|
|
12571
|
+
output.system.push(`[opencode-mempalace] Updated ${updateResult.currentVersion} \u2192 ${updateResult.latestVersion}. Restart OpenCode to apply.`);
|
|
12572
|
+
}
|
|
12379
12573
|
},
|
|
12380
|
-
"tool.execute.after": async (
|
|
12381
|
-
if (
|
|
12382
|
-
diaryWritten.add(
|
|
12574
|
+
"tool.execute.after": async (input2, _output) => {
|
|
12575
|
+
if (input2.tool === "mcp_mempalace_mempalace_diary_write") {
|
|
12576
|
+
diaryWritten.add(input2.sessionID);
|
|
12383
12577
|
}
|
|
12384
12578
|
},
|
|
12385
|
-
"experimental.session.compacting": async (
|
|
12386
|
-
if (!diaryWritten.has(
|
|
12579
|
+
"experimental.session.compacting": async (input2, output) => {
|
|
12580
|
+
if (!diaryWritten.has(input2.sessionID)) {
|
|
12387
12581
|
output.context.push("\u26A0\uFE0F MEMPALACE: No diary entry written yet for this session. Call mcp_mempalace_mempalace_diary_write with a session summary BEFORE important context is lost to compaction.");
|
|
12388
12582
|
}
|
|
12389
12583
|
},
|
|
12390
|
-
"chat.message": opts.disableAutoLoad ? undefined : async (
|
|
12391
|
-
if (sessionsSeen.has(
|
|
12584
|
+
"chat.message": opts.disableAutoLoad ? undefined : async (input2, output) => {
|
|
12585
|
+
if (sessionsSeen.has(input2.sessionID))
|
|
12392
12586
|
return;
|
|
12393
|
-
sessionsSeen.add(
|
|
12587
|
+
sessionsSeen.add(input2.sessionID);
|
|
12394
12588
|
const firstTextPart = output.parts.find((p) => p.type === "text");
|
|
12395
12589
|
if (firstTextPart && "text" in firstTextPart) {
|
|
12396
12590
|
firstTextPart.text = `${SESSION_START_INSTRUCTION}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-mempalace",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "OpenCode plugin for MemPalace memory system — auto-registers MCP server, injects memory protocol into system prompt, and loads context on session start",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|