@ectplsm/relic 0.1.1 → 0.1.3

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.
Files changed (53) hide show
  1. package/README.md +172 -49
  2. package/dist/adapters/shells/claude-hook.d.ts +12 -0
  3. package/dist/adapters/shells/claude-hook.js +160 -0
  4. package/dist/adapters/shells/claude-shell.d.ts +5 -2
  5. package/dist/adapters/shells/claude-shell.js +17 -3
  6. package/dist/adapters/shells/codex-hook.d.ts +12 -0
  7. package/dist/adapters/shells/codex-hook.js +141 -0
  8. package/dist/adapters/shells/codex-shell.d.ts +7 -4
  9. package/dist/adapters/shells/codex-shell.js +22 -7
  10. package/dist/adapters/shells/copilot-shell.d.ts +2 -2
  11. package/dist/adapters/shells/copilot-shell.js +3 -3
  12. package/dist/adapters/shells/gemini-hook.d.ts +12 -0
  13. package/dist/adapters/shells/gemini-hook.js +108 -0
  14. package/dist/adapters/shells/gemini-shell.d.ts +6 -4
  15. package/dist/adapters/shells/gemini-shell.js +103 -14
  16. package/dist/adapters/shells/index.d.ts +0 -1
  17. package/dist/adapters/shells/index.js +0 -1
  18. package/dist/adapters/shells/spawn-shell.d.ts +1 -1
  19. package/dist/adapters/shells/spawn-shell.js +10 -3
  20. package/dist/adapters/shells/trust-registrar.d.ts +19 -0
  21. package/dist/adapters/shells/trust-registrar.js +141 -0
  22. package/dist/core/ports/shell-launcher.d.ts +17 -2
  23. package/dist/core/usecases/archive-cursor-update.d.ts +21 -0
  24. package/dist/core/usecases/archive-cursor-update.js +44 -0
  25. package/dist/core/usecases/archive-pending.d.ts +25 -0
  26. package/dist/core/usecases/archive-pending.js +61 -0
  27. package/dist/core/usecases/archive-search.d.ts +20 -0
  28. package/dist/core/usecases/archive-search.js +46 -0
  29. package/dist/core/usecases/inbox-search.d.ts +20 -0
  30. package/dist/core/usecases/inbox-search.js +46 -0
  31. package/dist/core/usecases/inbox-write.d.ts +27 -0
  32. package/dist/core/usecases/inbox-write.js +72 -0
  33. package/dist/core/usecases/index.d.ts +2 -1
  34. package/dist/core/usecases/index.js +2 -1
  35. package/dist/core/usecases/summon.d.ts +6 -1
  36. package/dist/core/usecases/summon.js +8 -2
  37. package/dist/interfaces/cli/commands/config.d.ts +2 -0
  38. package/dist/interfaces/cli/commands/config.js +83 -0
  39. package/dist/interfaces/cli/commands/extract.js +3 -2
  40. package/dist/interfaces/cli/commands/init.js +47 -0
  41. package/dist/interfaces/cli/commands/inject.js +3 -2
  42. package/dist/interfaces/cli/commands/shell.js +13 -11
  43. package/dist/interfaces/cli/index.js +8 -1
  44. package/dist/interfaces/mcp/index.js +68 -305
  45. package/dist/shared/config.d.ts +31 -0
  46. package/dist/shared/config.js +86 -16
  47. package/dist/shared/engram-composer.d.ts +16 -3
  48. package/dist/shared/engram-composer.js +50 -5
  49. package/dist/shared/memory-inbox.d.ts +78 -0
  50. package/dist/shared/memory-inbox.js +168 -0
  51. package/dist/shared/session-recorder.d.ts +47 -0
  52. package/dist/shared/session-recorder.js +112 -0
  53. package/package.json +5 -5
@@ -0,0 +1,83 @@
1
+ import { loadConfig, saveConfig, ensureInitialized, } from "../../../shared/config.js";
2
+ import { LocalEngramRepository } from "../../../adapters/local/index.js";
3
+ export function registerConfigCommand(program) {
4
+ const config = program
5
+ .command("config")
6
+ .description("Manage RELIC configuration");
7
+ // relic config show
8
+ config
9
+ .command("show")
10
+ .description("Show current configuration")
11
+ .action(async () => {
12
+ await ensureInitialized();
13
+ const cfg = await loadConfig();
14
+ console.log(JSON.stringify(cfg, null, 2));
15
+ });
16
+ // relic config default-engram [id]
17
+ config
18
+ .command("default-engram [id]")
19
+ .description("Get or set the default Engram ID (used when --engram is omitted)")
20
+ .option("-p, --path <dir>", "Override engrams directory path")
21
+ .action(async (id, opts) => {
22
+ await ensureInitialized();
23
+ const cfg = await loadConfig();
24
+ if (!id) {
25
+ // getter
26
+ if (cfg.defaultEngram) {
27
+ console.log(cfg.defaultEngram);
28
+ }
29
+ else {
30
+ console.log("(not set)");
31
+ }
32
+ return;
33
+ }
34
+ // setter — Engram 存在確認
35
+ const engramsPath = opts.path ?? cfg.engramsPath;
36
+ const repo = new LocalEngramRepository(engramsPath);
37
+ const engram = await repo.get(id);
38
+ if (!engram) {
39
+ console.error(`Error: Engram "${id}" not found in ${engramsPath}`);
40
+ process.exit(1);
41
+ }
42
+ cfg.defaultEngram = id;
43
+ await saveConfig(cfg);
44
+ console.log(`Default Engram set to: ${engram.meta.name} (${id})`);
45
+ });
46
+ // relic config openclaw-path [path]
47
+ config
48
+ .command("openclaw-path [path]")
49
+ .description("Get or set the OpenClaw directory path (default: ~/.openclaw)")
50
+ .action(async (path) => {
51
+ await ensureInitialized();
52
+ const cfg = await loadConfig();
53
+ if (!path) {
54
+ // getter
55
+ console.log(cfg.openclawPath ?? "(not set — using ~/.openclaw)");
56
+ return;
57
+ }
58
+ cfg.openclawPath = path;
59
+ await saveConfig(cfg);
60
+ console.log(`OpenClaw path set to: ${path}`);
61
+ });
62
+ // relic config memory-window [n]
63
+ config
64
+ .command("memory-window [n]")
65
+ .description("Get or set the number of recent memory entries to include in prompts (default: 2)")
66
+ .action(async (n) => {
67
+ await ensureInitialized();
68
+ const cfg = await loadConfig();
69
+ if (n === undefined) {
70
+ // getter
71
+ console.log(String(cfg.memoryWindowSize));
72
+ return;
73
+ }
74
+ const parsed = parseInt(n, 10);
75
+ if (isNaN(parsed) || parsed < 1) {
76
+ console.error("Error: memory-window must be a positive integer");
77
+ process.exit(1);
78
+ }
79
+ cfg.memoryWindowSize = parsed;
80
+ await saveConfig(cfg);
81
+ console.log(`Memory window set to: ${parsed}`);
82
+ });
83
+ }
@@ -1,6 +1,6 @@
1
1
  import { LocalEngramRepository } from "../../../adapters/local/index.js";
2
2
  import { Extract, WorkspaceNotFoundError, WorkspaceEmptyError, EngramAlreadyExistsError, ExtractNameRequiredError, } from "../../../core/usecases/index.js";
3
- import { resolveEngramsPath } from "../../../shared/config.js";
3
+ import { resolveEngramsPath, resolveOpenclawPath } from "../../../shared/config.js";
4
4
  export function registerExtractCommand(program) {
5
5
  program
6
6
  .command("extract")
@@ -12,12 +12,13 @@ export function registerExtractCommand(program) {
12
12
  .option("-f, --force", "Overwrite existing Engram persona files")
13
13
  .action(async (opts) => {
14
14
  const engramsPath = await resolveEngramsPath(opts.path);
15
+ const openclawDir = await resolveOpenclawPath(opts.openclaw);
15
16
  const repo = new LocalEngramRepository(engramsPath);
16
17
  const extract = new Extract(repo);
17
18
  try {
18
19
  const result = await extract.execute(opts.engram, {
19
20
  name: opts.name,
20
- openclawDir: opts.openclaw,
21
+ openclawDir,
21
22
  force: opts.force,
22
23
  });
23
24
  console.log(`Extracted "${result.engramName}" from ${result.sourcePath}`);
@@ -1,4 +1,16 @@
1
+ import { createInterface } from "node:readline";
1
2
  import { Init } from "../../../core/usecases/init.js";
3
+ import { setDefaultEngram, loadConfig } from "../../../shared/config.js";
4
+ import { LocalEngramRepository } from "../../../adapters/local/index.js";
5
+ function ask(question) {
6
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
7
+ return new Promise((resolve) => {
8
+ rl.question(question, (answer) => {
9
+ rl.close();
10
+ resolve(answer.trim());
11
+ });
12
+ });
13
+ }
2
14
  export function registerInitCommand(program) {
3
15
  program
4
16
  .command("init")
@@ -10,6 +22,41 @@ export function registerInitCommand(program) {
10
22
  console.log("Initialized RELIC:");
11
23
  console.log(` Config: ${result.configPath}`);
12
24
  console.log(` Engrams: ${result.engramsPath}`);
25
+ console.log();
26
+ // 利用可能なEngramを表示してデフォルト選択を促す
27
+ const cfg = await loadConfig();
28
+ const repo = new LocalEngramRepository(cfg.engramsPath);
29
+ const engrams = await repo.list();
30
+ if (engrams.length > 0) {
31
+ console.log("Available Engrams:");
32
+ console.log(` ${"ID".padEnd(12)} Name`);
33
+ for (const e of engrams) {
34
+ console.log(` ${e.id.padEnd(12)} ${e.name}`);
35
+ }
36
+ console.log();
37
+ const johnny = engrams.find((e) => e.id === "johnny");
38
+ const prompt = johnny
39
+ ? `Set a default Engram? (press Enter for "${johnny.id}", or enter ID, or "n" to skip): `
40
+ : "Set a default Engram? (Enter ID, or press Enter to skip): ";
41
+ const answer = await ask(prompt);
42
+ if (answer === "" && johnny) {
43
+ await setDefaultEngram(johnny.id);
44
+ console.log(`Default Engram set to: ${johnny.name} (${johnny.id})`);
45
+ }
46
+ else if (answer === "" || answer.toLowerCase() === "n") {
47
+ console.log(`Skipped. Run: relic config default-engram <id> to configure later.`);
48
+ }
49
+ else {
50
+ const match = engrams.find((e) => e.id === answer);
51
+ if (match) {
52
+ await setDefaultEngram(match.id);
53
+ console.log(`Default Engram set to: ${match.name} (${match.id})`);
54
+ }
55
+ else {
56
+ console.log(`Unknown Engram "${answer}". Skipped. Run: relic config default-engram <id>`);
57
+ }
58
+ }
59
+ }
13
60
  }
14
61
  else {
15
62
  console.log("Already initialized.");
@@ -1,6 +1,6 @@
1
1
  import { LocalEngramRepository } from "../../../adapters/local/index.js";
2
2
  import { Inject, InjectEngramNotFoundError, InjectAgentNotFoundError, } from "../../../core/usecases/index.js";
3
- import { resolveEngramsPath } from "../../../shared/config.js";
3
+ import { resolveEngramsPath, resolveOpenclawPath } from "../../../shared/config.js";
4
4
  export function registerInjectCommand(program) {
5
5
  program
6
6
  .command("inject")
@@ -11,12 +11,13 @@ export function registerInjectCommand(program) {
11
11
  .option("-p, --path <dir>", "Override engrams directory path")
12
12
  .action(async (opts) => {
13
13
  const engramsPath = await resolveEngramsPath(opts.path);
14
+ const openclawDir = await resolveOpenclawPath(opts.openclaw);
14
15
  const repo = new LocalEngramRepository(engramsPath);
15
16
  const inject = new Inject(repo);
16
17
  try {
17
18
  const result = await inject.execute(opts.engram, {
18
19
  to: opts.to,
19
- openclawDir: opts.openclaw,
20
+ openclawDir,
20
21
  });
21
22
  console.log(`Injected "${result.engramName}" into ${result.targetPath}`);
22
23
  console.log(` Files written: ${result.filesWritten.join(", ")}`);
@@ -1,11 +1,10 @@
1
1
  import { resolve } from "node:path";
2
2
  import { LocalEngramRepository } from "../../../adapters/local/index.js";
3
3
  import { Summon, EngramNotFoundError } from "../../../core/usecases/index.js";
4
- import { resolveEngramsPath } from "../../../shared/config.js";
4
+ import { resolveEngramsPath, resolveDefaultEngram, resolveMemoryWindowSize } from "../../../shared/config.js";
5
5
  import { ClaudeShell } from "../../../adapters/shells/claude-shell.js";
6
6
  import { GeminiShell } from "../../../adapters/shells/gemini-shell.js";
7
7
  import { CodexShell } from "../../../adapters/shells/codex-shell.js";
8
- import { CopilotShell } from "../../../adapters/shells/copilot-shell.js";
9
8
  const SHELLS = [
10
9
  {
11
10
  name: "claude",
@@ -22,18 +21,13 @@ const SHELLS = [
22
21
  description: "Summon an Engram into Codex CLI",
23
22
  create: () => new CodexShell(),
24
23
  },
25
- {
26
- name: "copilot",
27
- description: "Summon an Engram into GitHub Copilot CLI",
28
- create: () => new CopilotShell(),
29
- },
30
24
  ];
31
25
  export function registerShellCommands(program) {
32
26
  for (const shell of SHELLS) {
33
27
  program
34
28
  .command(shell.name)
35
29
  .description(shell.description)
36
- .requiredOption("-e, --engram <id>", "Engram ID to summon")
30
+ .option("-e, --engram <id>", "Engram ID to summon (default: config.defaultEngram)")
37
31
  .option("-p, --path <dir>", "Override engrams directory path")
38
32
  .option("--cwd <dir>", "Working directory for the Shell (default: current directory)")
39
33
  .allowUnknownOption(true)
@@ -45,17 +39,25 @@ export function registerShellCommands(program) {
45
39
  console.error(`Error: ${launcher.name} is not installed or not in PATH.`);
46
40
  process.exit(1);
47
41
  }
42
+ // Engram ID解決: --engram > config.defaultEngram > エラー
43
+ const engramId = await resolveDefaultEngram(opts.engram);
44
+ if (!engramId) {
45
+ console.error("Error: No Engram specified. Use --engram <id> or set a default with: relic config default-engram <id>");
46
+ process.exit(1);
47
+ }
48
48
  // Engram取得 & プロンプト生成
49
49
  const engramsPath = await resolveEngramsPath(opts.path);
50
50
  const repo = new LocalEngramRepository(engramsPath);
51
51
  const summon = new Summon(repo);
52
+ const memoryWindowSize = await resolveMemoryWindowSize();
52
53
  try {
53
- const result = await summon.execute(opts.engram);
54
- console.log(`Summoning "${result.engramName}" into ${launcher.name}...\n`);
54
+ const result = await summon.execute(engramId, { memoryWindowSize });
55
+ console.log(`Summoning "${result.engramName}" into ${launcher.name}...`);
56
+ console.log();
55
57
  // --engram, --path, --cwd 以外の引数をShellにパススルー
56
58
  const extraArgs = cmd.args;
57
59
  const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();
58
- await launcher.launch(result.prompt, extraArgs, cwd);
60
+ await launcher.launch(result.prompt, { extraArgs, cwd, engramId });
59
61
  }
60
62
  catch (err) {
61
63
  if (err instanceof EngramNotFoundError) {
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { resolve, dirname } from "node:path";
2
5
  import { Command } from "commander";
3
6
  import { registerInitCommand } from "./commands/init.js";
4
7
  import { registerListCommand } from "./commands/list.js";
@@ -7,11 +10,14 @@ import { registerShellCommands } from "./commands/shell.js";
7
10
  import { registerInjectCommand } from "./commands/inject.js";
8
11
  import { registerExtractCommand } from "./commands/extract.js";
9
12
  import { registerSyncCommand } from "./commands/sync.js";
13
+ import { registerConfigCommand } from "./commands/config.js";
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, "../../../package.json"), "utf-8"));
10
16
  const program = new Command();
11
17
  program
12
18
  .name("relic")
13
19
  .description("PROJECT RELIC — Engram injection system for AI constructs")
14
- .version("0.1.0");
20
+ .version(pkg.version);
15
21
  registerInitCommand(program);
16
22
  registerListCommand(program);
17
23
  registerShowCommand(program);
@@ -19,4 +25,5 @@ registerShellCommands(program);
19
25
  registerInjectCommand(program);
20
26
  registerExtractCommand(program);
21
27
  registerSyncCommand(program);
28
+ registerConfigCommand(program);
22
29
  program.parse();