@remnic/plugin-pi 9.3.523 → 9.3.525

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/publisher.js CHANGED
@@ -103,12 +103,16 @@ var PiMemoryExtensionPublisher = class {
103
103
  try {
104
104
  restorePublishSnapshot(extensionRoot, rootExisted, snapshots);
105
105
  } catch (restoreErr) {
106
- ctx.log.warn(`Pi extension rollback failed: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`);
106
+ ctx.log.warn(
107
+ `Pi extension rollback failed: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`
108
+ );
107
109
  }
108
110
  try {
109
111
  restorePiTokenEntry(priorTokenEntry);
110
112
  } catch (tokenErr) {
111
- ctx.log.warn(`Pi connector token rollback failed: ${tokenErr instanceof Error ? tokenErr.message : String(tokenErr)}`);
113
+ ctx.log.warn(
114
+ `Pi connector token rollback failed: ${tokenErr instanceof Error ? tokenErr.message : String(tokenErr)}`
115
+ );
112
116
  }
113
117
  throw err;
114
118
  }
@@ -190,11 +194,7 @@ function snapshotFiles(paths) {
190
194
  });
191
195
  }
192
196
  function restorePublishSnapshot(extensionRoot, rootExisted, snapshots) {
193
- if (!rootExisted) {
194
- assertSafeExistingPath(extensionRoot);
195
- fs.rmSync(extensionRoot, { recursive: true, force: true });
196
- return;
197
- }
197
+ if (!rootExisted && !canCleanNewExtensionRoot(extensionRoot)) return;
198
198
  for (const snapshot of snapshots) {
199
199
  if (!snapshot.existed) {
200
200
  assertSafeExistingPath(snapshot.path);
@@ -210,6 +210,37 @@ function restorePublishSnapshot(extensionRoot, rootExisted, snapshots) {
210
210
  }
211
211
  }
212
212
  }
213
+ if (!rootExisted) {
214
+ removeEmptyDirectory(extensionRoot);
215
+ }
216
+ }
217
+ function canCleanNewExtensionRoot(extensionRoot) {
218
+ let stat;
219
+ try {
220
+ stat = fs.lstatSync(extensionRoot);
221
+ } catch (err) {
222
+ if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") return false;
223
+ throw err;
224
+ }
225
+ if (stat.isSymbolicLink()) {
226
+ throw new Error(`Pi extension path must not be a symlink: ${extensionRoot}`);
227
+ }
228
+ return stat.isDirectory();
229
+ }
230
+ function removeEmptyDirectory(dirPath) {
231
+ let stat;
232
+ try {
233
+ stat = fs.lstatSync(dirPath);
234
+ } catch (err) {
235
+ if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") return;
236
+ throw err;
237
+ }
238
+ if (stat.isSymbolicLink()) {
239
+ throw new Error(`Pi extension path must not be a symlink: ${dirPath}`);
240
+ }
241
+ if (!stat.isDirectory()) return;
242
+ if (fs.readdirSync(dirPath).length > 0) return;
243
+ fs.rmdirSync(dirPath);
213
244
  }
214
245
  function mkdirPiExtensionRoot(extensionRoot, env) {
215
246
  const extensionsDir = path.join(resolvePiAgentHome(env), "extensions");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/publisher.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\nimport {\n getConnectorToken,\n loadTokenStore,\n saveTokenStore,\n type MemoryExtensionPublisher,\n type PublishContext,\n type PublishResult,\n type PublisherCapabilities,\n type TokenEntry,\n} from \"@remnic/core\";\n\nimport { resolvePiAgentHome, resolvePiExtensionRoot } from \"./paths.js\";\n\nconst DEFAULT_DAEMON_PORT = 4318;\n\ntype FileSnapshot = {\n path: string;\n existed: boolean;\n content?: Buffer;\n mode?: number;\n};\n\nexport class PiMemoryExtensionPublisher implements MemoryExtensionPublisher {\n readonly hostId = \"pi\";\n\n static readonly capabilities: PublisherCapabilities = {\n instructionsMd: false,\n skillsFolder: false,\n citationFormat: false,\n readPathTemplate: false,\n };\n\n async resolveExtensionRoot(env?: NodeJS.ProcessEnv): Promise<string> {\n return resolvePiExtensionRoot(env ?? process.env);\n }\n\n async isHostAvailable(): Promise<boolean> {\n // Pi auto-discovers extensions from ~/.pi/agent/extensions. The directory can\n // be created before Pi has been launched, so availability should not block\n // first-time installation.\n return true;\n }\n\n async renderInstructions(ctx: PublishContext): Promise<string> {\n const namespace = ctx.config.namespace ?? \"default\";\n const daemonUrl = resolveDaemonUrl(ctx);\n return [\n \"# Remnic for Pi\",\n \"\",\n \"Remnic provides memory, retrieval, observation, MCP tools, and long-context compaction coordination for Pi Coding Agent.\",\n \"\",\n \"## Installed Capabilities\",\n \"\",\n \"- Recall relevant Remnic context in Pi's `context` hook before agent turns.\",\n \"- Observe Pi user, assistant, and tool messages with `sourceFormat: \\\"pi\\\"`.\",\n \"- Coordinate Pi `session_before_compact` with Remnic LCM flush and checkpoint recording.\",\n \"- Register Remnic MCP tools as Pi tools when daemon authentication is configured.\",\n \"- Persist lightweight dedupe state in Pi custom entries via `appendEntry`.\",\n \"\",\n \"## Runtime\",\n \"\",\n `- Remnic daemon: \\`${daemonUrl}\\``,\n `- Namespace: \\`${namespace}\\``,\n `- Memory directory: \\`${ctx.config.memoryDir}\\``,\n \"\",\n \"The private `remnic.config.json` file stores the daemon URL, namespace, and connector auth token with owner-only permissions.\",\n ].join(\"\\n\");\n }\n\n async publish(ctx: PublishContext): Promise<PublishResult> {\n const extensionRoot = await this.resolveExtensionRoot();\n assertSafePiExtensionRoot(extensionRoot, process.env);\n const filesWritten: string[] = [];\n const skipped: string[] = [];\n\n ctx.log.info(`Publishing Pi memory extension to ${extensionRoot}`);\n\n const configPath = path.join(extensionRoot, \"remnic.config.json\");\n const wrapperPath = path.join(extensionRoot, \"index.ts\");\n const readmePath = path.join(extensionRoot, \"README.md\");\n const rootExisted = fs.existsSync(extensionRoot);\n const snapshots = snapshotFiles([configPath, wrapperPath, readmePath]);\n const priorTokenEntry =\n ctx.rollbackTokenEntry === undefined ? snapshotPiTokenEntry() : cloneTokenEntry(ctx.rollbackTokenEntry);\n\n const token = getConnectorToken(\"pi\");\n if (!token) {\n skipped.push(\"auth token unavailable; run `remnic token generate pi` and reinstall the connector\");\n }\n\n try {\n const priorConfig = readPriorConfig(configPath);\n const config: Record<string, unknown> = {\n recallMode: \"auto\",\n recallTopK: 8,\n recallBudgetChars: 12000,\n recallEnabled: true,\n observeEnabled: true,\n observeSkipExtraction: false,\n compactionEnabled: true,\n mcpToolsEnabled: true,\n statusEnabled: true,\n requestTimeoutMs: 60000,\n ...priorConfig,\n remnicDaemonUrl: resolveDaemonUrl(ctx),\n };\n if (token) {\n config.authToken = token;\n }\n if (ctx.config.namespace) {\n config.namespace = ctx.config.namespace;\n }\n\n mkdirPiExtensionRoot(extensionRoot, process.env);\n\n atomicWriteFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, 0o600);\n filesWritten.push(configPath);\n\n atomicWriteFile(wrapperPath, renderWrapper(resolveExtensionModulePath(), configPath), 0o644);\n filesWritten.push(wrapperPath);\n\n atomicWriteFile(readmePath, `${await this.renderInstructions(ctx)}\\n`, 0o644);\n filesWritten.push(readmePath);\n } catch (err) {\n try {\n restorePublishSnapshot(extensionRoot, rootExisted, snapshots);\n } catch (restoreErr) {\n ctx.log.warn(`Pi extension rollback failed: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`);\n }\n try {\n restorePiTokenEntry(priorTokenEntry);\n } catch (tokenErr) {\n ctx.log.warn(`Pi connector token rollback failed: ${tokenErr instanceof Error ? tokenErr.message : String(tokenErr)}`);\n }\n throw err;\n }\n\n return {\n hostId: this.hostId,\n extensionRoot,\n filesWritten,\n skipped,\n };\n }\n\n async unpublish(): Promise<void> {\n const extensionRoot = await this.resolveExtensionRoot();\n assertSafePiExtensionRoot(extensionRoot, process.env);\n if (fs.existsSync(extensionRoot)) {\n fs.rmSync(extensionRoot, { recursive: true, force: true });\n }\n }\n}\n\nfunction resolveDaemonUrl(ctx: PublishContext): string {\n if (ctx.config.daemonUrl && ctx.config.daemonUrl.trim().length > 0) {\n return trimTrailingSlashes(ctx.config.daemonUrl.trim());\n }\n return `http://127.0.0.1:${ctx.config.daemonPort ?? DEFAULT_DAEMON_PORT}`;\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;\n return value.slice(0, end);\n}\n\nfunction resolveExtensionModulePath(): string {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const built = path.join(moduleDir, \"index.js\");\n if (fs.existsSync(built)) return built;\n\n const source = path.join(moduleDir, \"index.ts\");\n if (fs.existsSync(source)) return source;\n\n return built;\n}\n\nfunction renderWrapper(extensionModulePath: string, configPath: string): string {\n const moduleUrl = pathToFileURL(extensionModulePath).href;\n return [\n `import { createRemnicPiExtension } from ${JSON.stringify(moduleUrl)};`,\n \"\",\n `export default createRemnicPiExtension({ configPath: ${JSON.stringify(configPath)} });`,\n \"\",\n ].join(\"\\n\");\n}\n\nfunction atomicWriteFile(filePath: string, content: string, mode: number): void {\n rejectSymlinkPath(filePath);\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;\n try {\n fs.writeFileSync(tmpPath, content, { encoding: \"utf-8\", mode });\n fs.renameSync(tmpPath, filePath);\n try {\n fs.chmodSync(filePath, mode);\n } catch {\n // Best effort for platforms that do not support chmod.\n }\n } catch (err) {\n try {\n if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);\n } catch {\n // Best-effort cleanup only.\n }\n throw err;\n }\n}\n\nfunction snapshotFiles(paths: string[]): FileSnapshot[] {\n return paths.map((filePath) => {\n if (!fs.existsSync(filePath)) return { path: filePath, existed: false };\n const stat = fs.lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${filePath}`);\n }\n if (!stat.isFile()) return { path: filePath, existed: false };\n return {\n path: filePath,\n existed: true,\n content: fs.readFileSync(filePath),\n mode: stat.mode & 0o777,\n };\n });\n}\n\nfunction restorePublishSnapshot(extensionRoot: string, rootExisted: boolean, snapshots: FileSnapshot[]): void {\n if (!rootExisted) {\n assertSafeExistingPath(extensionRoot);\n fs.rmSync(extensionRoot, { recursive: true, force: true });\n return;\n }\n\n for (const snapshot of snapshots) {\n if (!snapshot.existed) {\n assertSafeExistingPath(snapshot.path);\n fs.rmSync(snapshot.path, { force: true });\n continue;\n }\n fs.mkdirSync(path.dirname(snapshot.path), { recursive: true });\n fs.writeFileSync(snapshot.path, snapshot.content ?? Buffer.alloc(0), { mode: snapshot.mode });\n if (snapshot.mode !== undefined) {\n try {\n fs.chmodSync(snapshot.path, snapshot.mode);\n } catch {\n // Best effort for platforms that do not support chmod.\n }\n }\n }\n}\n\nfunction mkdirPiExtensionRoot(extensionRoot: string, env: NodeJS.ProcessEnv): void {\n const extensionsDir = path.join(resolvePiAgentHome(env), \"extensions\");\n assertSafePiExtensionRoot(extensionRoot, env);\n fs.mkdirSync(extensionsDir, { recursive: true });\n rejectSymlinkPath(extensionsDir);\n fs.mkdirSync(extensionRoot, { recursive: true });\n rejectSymlinkPath(extensionRoot);\n}\n\nfunction assertSafePiExtensionRoot(extensionRoot: string, env: NodeJS.ProcessEnv): void {\n const expected = path.join(resolvePiAgentHome(env), \"extensions\", \"remnic\");\n if (path.resolve(extensionRoot) !== path.resolve(expected)) {\n throw new Error(`Pi extension root is outside the configured Pi extensions directory: ${extensionRoot}`);\n }\n const agentHome = path.resolve(resolvePiAgentHome(env));\n const extensionsDir = path.join(agentHome, \"extensions\");\n assertPathContained(agentHome, extensionsDir);\n assertPathContained(extensionsDir, extensionRoot);\n rejectSymlinkPath(agentHome);\n if (fs.existsSync(extensionsDir)) rejectSymlinkPath(extensionsDir);\n if (fs.existsSync(extensionRoot)) rejectSymlinkPath(extensionRoot);\n}\n\nfunction assertSafeExistingPath(filePath: string): void {\n if (fs.existsSync(filePath)) rejectSymlinkPath(filePath);\n}\n\nfunction rejectSymlinkPath(filePath: string): void {\n if (!fs.existsSync(filePath)) return;\n const stat = fs.lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${filePath}`);\n }\n}\n\nfunction assertPathContained(root: string, candidate: string): void {\n const rootResolved = path.resolve(root);\n const candidateResolved = path.resolve(candidate);\n const relative = path.relative(rootResolved, candidateResolved);\n if (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) return;\n throw new Error(`Pi extension path escapes allowed root: ${candidate}`);\n}\n\nfunction readPriorConfig(configPath: string): Record<string, unknown> {\n if (!fs.existsSync(configPath)) return {};\n try {\n const parsed = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n throw new Error(\"expected a JSON object\");\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to load existing Remnic Pi config at ${configPath}: ${reason}`);\n }\n}\n\nfunction snapshotPiTokenEntry(): TokenEntry | null {\n const entry = loadTokenStore().tokens.find((candidate) => candidate.connector === \"pi\");\n return cloneTokenEntry(entry ?? null);\n}\n\nfunction cloneTokenEntry(entry: TokenEntry | null): TokenEntry | null {\n return entry ? { ...entry } : null;\n}\n\nfunction restorePiTokenEntry(priorEntry: TokenEntry | null): void {\n const store = loadTokenStore();\n store.tokens = store.tokens.filter((entry) => entry.connector !== \"pi\");\n if (priorEntry) store.tokens.push(priorEntry);\n saveTokenStore(store);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/publisher.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\n\nimport {\n type MemoryExtensionPublisher,\n type PublishContext,\n type PublishResult,\n type PublisherCapabilities,\n type TokenEntry,\n getConnectorToken,\n loadTokenStore,\n saveTokenStore,\n} from \"@remnic/core\";\n\nimport { resolvePiAgentHome, resolvePiExtensionRoot } from \"./paths.js\";\n\nconst DEFAULT_DAEMON_PORT = 4318;\n\ntype FileSnapshot = {\n path: string;\n existed: boolean;\n content?: Buffer;\n mode?: number;\n};\n\nexport class PiMemoryExtensionPublisher implements MemoryExtensionPublisher {\n readonly hostId = \"pi\";\n\n static readonly capabilities: PublisherCapabilities = {\n instructionsMd: false,\n skillsFolder: false,\n citationFormat: false,\n readPathTemplate: false,\n };\n\n async resolveExtensionRoot(env?: NodeJS.ProcessEnv): Promise<string> {\n return resolvePiExtensionRoot(env ?? process.env);\n }\n\n async isHostAvailable(): Promise<boolean> {\n // Pi auto-discovers extensions from ~/.pi/agent/extensions. The directory can\n // be created before Pi has been launched, so availability should not block\n // first-time installation.\n return true;\n }\n\n async renderInstructions(ctx: PublishContext): Promise<string> {\n const namespace = ctx.config.namespace ?? \"default\";\n const daemonUrl = resolveDaemonUrl(ctx);\n return [\n \"# Remnic for Pi\",\n \"\",\n \"Remnic provides memory, retrieval, observation, MCP tools, and long-context compaction coordination for Pi Coding Agent.\",\n \"\",\n \"## Installed Capabilities\",\n \"\",\n \"- Recall relevant Remnic context in Pi's `context` hook before agent turns.\",\n '- Observe Pi user, assistant, and tool messages with `sourceFormat: \"pi\"`.',\n \"- Coordinate Pi `session_before_compact` with Remnic LCM flush and checkpoint recording.\",\n \"- Register Remnic MCP tools as Pi tools when daemon authentication is configured.\",\n \"- Persist lightweight dedupe state in Pi custom entries via `appendEntry`.\",\n \"\",\n \"## Runtime\",\n \"\",\n `- Remnic daemon: \\`${daemonUrl}\\``,\n `- Namespace: \\`${namespace}\\``,\n `- Memory directory: \\`${ctx.config.memoryDir}\\``,\n \"\",\n \"The private `remnic.config.json` file stores the daemon URL, namespace, and connector auth token with owner-only permissions.\",\n ].join(\"\\n\");\n }\n\n async publish(ctx: PublishContext): Promise<PublishResult> {\n const extensionRoot = await this.resolveExtensionRoot();\n assertSafePiExtensionRoot(extensionRoot, process.env);\n const filesWritten: string[] = [];\n const skipped: string[] = [];\n\n ctx.log.info(`Publishing Pi memory extension to ${extensionRoot}`);\n\n const configPath = path.join(extensionRoot, \"remnic.config.json\");\n const wrapperPath = path.join(extensionRoot, \"index.ts\");\n const readmePath = path.join(extensionRoot, \"README.md\");\n const rootExisted = fs.existsSync(extensionRoot);\n const snapshots = snapshotFiles([configPath, wrapperPath, readmePath]);\n const priorTokenEntry =\n ctx.rollbackTokenEntry === undefined ? snapshotPiTokenEntry() : cloneTokenEntry(ctx.rollbackTokenEntry);\n\n const token = getConnectorToken(\"pi\");\n if (!token) {\n skipped.push(\"auth token unavailable; run `remnic token generate pi` and reinstall the connector\");\n }\n\n try {\n const priorConfig = readPriorConfig(configPath);\n const config: Record<string, unknown> = {\n recallMode: \"auto\",\n recallTopK: 8,\n recallBudgetChars: 12000,\n recallEnabled: true,\n observeEnabled: true,\n observeSkipExtraction: false,\n compactionEnabled: true,\n mcpToolsEnabled: true,\n statusEnabled: true,\n requestTimeoutMs: 60000,\n ...priorConfig,\n remnicDaemonUrl: resolveDaemonUrl(ctx),\n };\n if (token) {\n config.authToken = token;\n }\n if (ctx.config.namespace) {\n config.namespace = ctx.config.namespace;\n }\n\n mkdirPiExtensionRoot(extensionRoot, process.env);\n\n atomicWriteFile(configPath, `${JSON.stringify(config, null, 2)}\\n`, 0o600);\n filesWritten.push(configPath);\n\n atomicWriteFile(wrapperPath, renderWrapper(resolveExtensionModulePath(), configPath), 0o644);\n filesWritten.push(wrapperPath);\n\n atomicWriteFile(readmePath, `${await this.renderInstructions(ctx)}\\n`, 0o644);\n filesWritten.push(readmePath);\n } catch (err) {\n try {\n restorePublishSnapshot(extensionRoot, rootExisted, snapshots);\n } catch (restoreErr) {\n ctx.log.warn(\n `Pi extension rollback failed: ${restoreErr instanceof Error ? restoreErr.message : String(restoreErr)}`\n );\n }\n try {\n restorePiTokenEntry(priorTokenEntry);\n } catch (tokenErr) {\n ctx.log.warn(\n `Pi connector token rollback failed: ${tokenErr instanceof Error ? tokenErr.message : String(tokenErr)}`\n );\n }\n throw err;\n }\n\n return {\n hostId: this.hostId,\n extensionRoot,\n filesWritten,\n skipped,\n };\n }\n\n async unpublish(): Promise<void> {\n const extensionRoot = await this.resolveExtensionRoot();\n assertSafePiExtensionRoot(extensionRoot, process.env);\n if (fs.existsSync(extensionRoot)) {\n fs.rmSync(extensionRoot, { recursive: true, force: true });\n }\n }\n}\n\nfunction resolveDaemonUrl(ctx: PublishContext): string {\n if (ctx.config.daemonUrl && ctx.config.daemonUrl.trim().length > 0) {\n return trimTrailingSlashes(ctx.config.daemonUrl.trim());\n }\n return `http://127.0.0.1:${ctx.config.daemonPort ?? DEFAULT_DAEMON_PORT}`;\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;\n return value.slice(0, end);\n}\n\nfunction resolveExtensionModulePath(): string {\n const moduleDir = path.dirname(fileURLToPath(import.meta.url));\n const built = path.join(moduleDir, \"index.js\");\n if (fs.existsSync(built)) return built;\n\n const source = path.join(moduleDir, \"index.ts\");\n if (fs.existsSync(source)) return source;\n\n return built;\n}\n\nfunction renderWrapper(extensionModulePath: string, configPath: string): string {\n const moduleUrl = pathToFileURL(extensionModulePath).href;\n return [\n `import { createRemnicPiExtension } from ${JSON.stringify(moduleUrl)};`,\n \"\",\n `export default createRemnicPiExtension({ configPath: ${JSON.stringify(configPath)} });`,\n \"\",\n ].join(\"\\n\");\n}\n\nfunction atomicWriteFile(filePath: string, content: string, mode: number): void {\n rejectSymlinkPath(filePath);\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;\n try {\n fs.writeFileSync(tmpPath, content, { encoding: \"utf-8\", mode });\n fs.renameSync(tmpPath, filePath);\n try {\n fs.chmodSync(filePath, mode);\n } catch {\n // Best effort for platforms that do not support chmod.\n }\n } catch (err) {\n try {\n if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);\n } catch {\n // Best-effort cleanup only.\n }\n throw err;\n }\n}\n\nfunction snapshotFiles(paths: string[]): FileSnapshot[] {\n return paths.map((filePath) => {\n if (!fs.existsSync(filePath)) return { path: filePath, existed: false };\n const stat = fs.lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${filePath}`);\n }\n if (!stat.isFile()) return { path: filePath, existed: false };\n return {\n path: filePath,\n existed: true,\n content: fs.readFileSync(filePath),\n mode: stat.mode & 0o777,\n };\n });\n}\n\nfunction restorePublishSnapshot(extensionRoot: string, rootExisted: boolean, snapshots: FileSnapshot[]): void {\n if (!rootExisted && !canCleanNewExtensionRoot(extensionRoot)) return;\n\n for (const snapshot of snapshots) {\n if (!snapshot.existed) {\n assertSafeExistingPath(snapshot.path);\n fs.rmSync(snapshot.path, { force: true });\n continue;\n }\n fs.mkdirSync(path.dirname(snapshot.path), { recursive: true });\n fs.writeFileSync(snapshot.path, snapshot.content ?? Buffer.alloc(0), { mode: snapshot.mode });\n if (snapshot.mode !== undefined) {\n try {\n fs.chmodSync(snapshot.path, snapshot.mode);\n } catch {\n // Best effort for platforms that do not support chmod.\n }\n }\n }\n\n if (!rootExisted) {\n removeEmptyDirectory(extensionRoot);\n }\n}\n\nfunction canCleanNewExtensionRoot(extensionRoot: string): boolean {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(extensionRoot);\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && err.code === \"ENOENT\") return false;\n throw err;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${extensionRoot}`);\n }\n return stat.isDirectory();\n}\n\nfunction removeEmptyDirectory(dirPath: string): void {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(dirPath);\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && err.code === \"ENOENT\") return;\n throw err;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${dirPath}`);\n }\n if (!stat.isDirectory()) return;\n if (fs.readdirSync(dirPath).length > 0) return;\n fs.rmdirSync(dirPath);\n}\n\nfunction mkdirPiExtensionRoot(extensionRoot: string, env: NodeJS.ProcessEnv): void {\n const extensionsDir = path.join(resolvePiAgentHome(env), \"extensions\");\n assertSafePiExtensionRoot(extensionRoot, env);\n fs.mkdirSync(extensionsDir, { recursive: true });\n rejectSymlinkPath(extensionsDir);\n fs.mkdirSync(extensionRoot, { recursive: true });\n rejectSymlinkPath(extensionRoot);\n}\n\nfunction assertSafePiExtensionRoot(extensionRoot: string, env: NodeJS.ProcessEnv): void {\n const expected = path.join(resolvePiAgentHome(env), \"extensions\", \"remnic\");\n if (path.resolve(extensionRoot) !== path.resolve(expected)) {\n throw new Error(`Pi extension root is outside the configured Pi extensions directory: ${extensionRoot}`);\n }\n const agentHome = path.resolve(resolvePiAgentHome(env));\n const extensionsDir = path.join(agentHome, \"extensions\");\n assertPathContained(agentHome, extensionsDir);\n assertPathContained(extensionsDir, extensionRoot);\n rejectSymlinkPath(agentHome);\n if (fs.existsSync(extensionsDir)) rejectSymlinkPath(extensionsDir);\n if (fs.existsSync(extensionRoot)) rejectSymlinkPath(extensionRoot);\n}\n\nfunction assertSafeExistingPath(filePath: string): void {\n if (fs.existsSync(filePath)) rejectSymlinkPath(filePath);\n}\n\nfunction rejectSymlinkPath(filePath: string): void {\n if (!fs.existsSync(filePath)) return;\n const stat = fs.lstatSync(filePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`Pi extension path must not be a symlink: ${filePath}`);\n }\n}\n\nfunction assertPathContained(root: string, candidate: string): void {\n const rootResolved = path.resolve(root);\n const candidateResolved = path.resolve(candidate);\n const relative = path.relative(rootResolved, candidateResolved);\n if (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) return;\n throw new Error(`Pi extension path escapes allowed root: ${candidate}`);\n}\n\nfunction readPriorConfig(configPath: string): Record<string, unknown> {\n if (!fs.existsSync(configPath)) return {};\n try {\n const parsed = JSON.parse(fs.readFileSync(configPath, \"utf8\"));\n if (parsed && typeof parsed === \"object\" && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n throw new Error(\"expected a JSON object\");\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to load existing Remnic Pi config at ${configPath}: ${reason}`);\n }\n}\n\nfunction snapshotPiTokenEntry(): TokenEntry | null {\n const entry = loadTokenStore().tokens.find((candidate) => candidate.connector === \"pi\");\n return cloneTokenEntry(entry ?? null);\n}\n\nfunction cloneTokenEntry(entry: TokenEntry | null): TokenEntry | null {\n return entry ? { ...entry } : null;\n}\n\nfunction restorePiTokenEntry(priorEntry: TokenEntry | null): void {\n const store = loadTokenStore();\n store.tokens = store.tokens.filter((entry) => entry.connector !== \"pi\");\n if (priorEntry) store.tokens.push(priorEntry);\n saveTokenStore(store);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/plugin-pi",
3
- "version": "9.3.523",
3
+ "version": "9.3.525",
4
4
  "description": "Remnic memory extension for Pi Coding Agent",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@sinclair/typebox": "^0.34.0",
41
- "@remnic/core": "^9.3.523"
41
+ "@remnic/core": "^9.3.525"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@earendil-works/pi-coding-agent": "*"