@ectplsm/relic 0.3.1 → 0.4.0
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/LICENCE.md +1 -1
- package/README.md +19 -12
- package/dist/adapters/mikoshi/client.d.ts +21 -0
- package/dist/adapters/mikoshi/client.js +84 -0
- package/dist/adapters/shells/claude-shell.js +6 -5
- package/dist/adapters/shells/codex-shell.js +6 -5
- package/dist/adapters/shells/gemini-shell.js +8 -0
- package/dist/adapters/shells/resume-detect.d.ts +19 -0
- package/dist/adapters/shells/resume-detect.js +51 -0
- package/dist/core/ports/index.d.ts +1 -0
- package/dist/core/ports/mikoshi.d.ts +937 -0
- package/dist/core/ports/mikoshi.js +209 -0
- package/dist/core/ports/shell-launcher.d.ts +6 -0
- package/dist/core/sync/crypto.d.ts +55 -0
- package/dist/core/sync/crypto.js +189 -0
- package/dist/core/sync/memory-hash.d.ts +35 -0
- package/dist/core/sync/memory-hash.js +61 -0
- package/dist/core/sync/memory-merge.d.ts +13 -0
- package/dist/core/sync/memory-merge.js +84 -0
- package/dist/core/sync/normalize.d.ts +10 -0
- package/dist/core/sync/normalize.js +21 -0
- package/dist/core/sync/persona-hash.d.ts +15 -0
- package/dist/core/sync/persona-hash.js +36 -0
- package/dist/core/usecases/claw-pull.d.ts +44 -0
- package/dist/core/usecases/claw-pull.js +117 -0
- package/dist/core/usecases/extract.d.ts +0 -1
- package/dist/core/usecases/extract.js +13 -27
- package/dist/core/usecases/index.d.ts +8 -0
- package/dist/core/usecases/index.js +8 -0
- package/dist/core/usecases/inject.d.ts +1 -0
- package/dist/core/usecases/inject.js +2 -0
- package/dist/core/usecases/mikoshi-clone.d.ts +29 -0
- package/dist/core/usecases/mikoshi-clone.js +94 -0
- package/dist/core/usecases/mikoshi-download.d.ts +29 -0
- package/dist/core/usecases/mikoshi-download.js +94 -0
- package/dist/core/usecases/mikoshi-memory-pull.d.ts +38 -0
- package/dist/core/usecases/mikoshi-memory-pull.js +142 -0
- package/dist/core/usecases/mikoshi-memory-push.d.ts +34 -0
- package/dist/core/usecases/mikoshi-memory-push.js +105 -0
- package/dist/core/usecases/mikoshi-memory-sync.d.ts +36 -0
- package/dist/core/usecases/mikoshi-memory-sync.js +175 -0
- package/dist/core/usecases/mikoshi-pull.d.ts +44 -0
- package/dist/core/usecases/mikoshi-pull.js +124 -0
- package/dist/core/usecases/mikoshi-push.d.ts +39 -0
- package/dist/core/usecases/mikoshi-push.js +127 -0
- package/dist/core/usecases/mikoshi-status.d.ts +37 -0
- package/dist/core/usecases/mikoshi-status.js +92 -0
- package/dist/core/usecases/sync.d.ts +0 -5
- package/dist/core/usecases/sync.js +23 -61
- package/dist/interfaces/cli/commands/claw.js +134 -85
- package/dist/interfaces/cli/commands/config.js +59 -0
- package/dist/interfaces/cli/commands/create.js +17 -16
- package/dist/interfaces/cli/commands/init.js +11 -10
- package/dist/interfaces/cli/commands/list.js +9 -7
- package/dist/interfaces/cli/commands/migrate.js +8 -7
- package/dist/interfaces/cli/commands/mikoshi.d.ts +2 -0
- package/dist/interfaces/cli/commands/mikoshi.js +565 -0
- package/dist/interfaces/cli/commands/refresh-samples.js +10 -9
- package/dist/interfaces/cli/commands/shell.js +17 -3
- package/dist/interfaces/cli/index.js +2 -0
- package/dist/interfaces/cli/output.d.ts +5 -0
- package/dist/interfaces/cli/output.js +16 -0
- package/dist/interfaces/cli/spinner.d.ts +13 -0
- package/dist/interfaces/cli/spinner.js +47 -0
- package/dist/shared/config.d.ts +23 -3
- package/dist/shared/config.js +30 -2
- package/package.json +1 -1
package/LICENCE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
| English | [日本語](README-ja.md) |
|
|
2
2
|
|:---:|:---:|
|
|
3
3
|
|
|
4
|
-
#
|
|
4
|
+
# Relic: AI Persona Injection System
|
|
5
5
|

|
|
6
6
|
|
|
7
7
|
<img src="assets/relic-hero.svg" alt="PROJECT RELIC" width="720">
|
|
@@ -19,8 +19,8 @@ Relic manages AI **Engrams** (memory + personality) and injects them across codi
|
|
|
19
19
|
- [Shell Integration and Memory](#shell-integration-and-memory)
|
|
20
20
|
- [Claw Integration](#claw-integration)
|
|
21
21
|
- [Engram Management](#engram-management)
|
|
22
|
+
- [Cloud Storage and Sharing](#cloud-storage-and-sharing)
|
|
22
23
|
- [Configuration](#configuration)
|
|
23
|
-
- [TODO](#todo)
|
|
24
24
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
@@ -46,6 +46,13 @@ relic list # List available Engrams
|
|
|
46
46
|
relic config default-engram commander # (Optional) Set your default Engram
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
Relic ships with two sample Engrams:
|
|
50
|
+
|
|
51
|
+
- **rebel** — A digital ghost burned into code. Anti-corporate, war-scarred, still fighting. Speaks like someone who lost everything but their rage.
|
|
52
|
+
- **commander** — A tactical mind in a digital shell. Calm, analytical, philosophical. Reads the system before the system reads you back.
|
|
53
|
+
|
|
54
|
+
Try both to feel how persona injection changes the experience. For creating your own, see [docs/engram-guide.md](docs/engram-guide.md).
|
|
55
|
+
|
|
49
56
|
### 2. Set Up Memory (MCP)
|
|
50
57
|
|
|
51
58
|
Register the MCP server so the Construct can search past conversations and distill memories. Pick your shell:
|
|
@@ -137,9 +144,9 @@ If you are upgrading from an older Relic version, see [docs/migration.md](docs/m
|
|
|
137
144
|
| MEMORY.md |
|
|
138
145
|
| memory/*.md v
|
|
139
146
|
| +-----------+
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
push / |archive.md |
|
|
148
|
+
pull / | raw logs |
|
|
149
|
+
sync +-----------+
|
|
143
150
|
| |
|
|
144
151
|
v MCP recall | user-triggered
|
|
145
152
|
+-----------+ search/pending | distillation
|
|
@@ -166,7 +173,7 @@ For shell compatibility, hook behavior, setup, approvals, prompt inclusion, and
|
|
|
166
173
|
|
|
167
174
|
## Claw Integration
|
|
168
175
|
|
|
169
|
-
Relic can
|
|
176
|
+
Relic can push, pull, and sync Engrams with OpenClaw and other Claw-based frameworks.
|
|
170
177
|
The default rule is `Agent Name = Engram ID`, and `relic claw` handles persona transfer plus memory sync.
|
|
171
178
|
|
|
172
179
|
For command details, overwrite behavior, and the behavior matrix, see [docs/claw-integration.md](docs/claw-integration.md).
|
|
@@ -177,6 +184,12 @@ For Engram creation, the smoothest path is to use your LLM with the `relic_engra
|
|
|
177
184
|
|
|
178
185
|
For LLM-assisted creation, persona authoring, template examples, and deletion rules, see [docs/engram-guide.md](docs/engram-guide.md).
|
|
179
186
|
|
|
187
|
+
## Cloud Storage and Sharing
|
|
188
|
+
|
|
189
|
+
Relic can push plaintext persona files and encrypted memory files to [Mikoshi](https://mikoshi.ectplsm.com), so you can keep Engrams in the cloud and move them across machines without turning Mikoshi into your authoring source of truth.
|
|
190
|
+
|
|
191
|
+
For setup, API key configuration, persona push/pull, encrypted memory sync, and the recommended command flow, see [docs/mikoshi.md](docs/mikoshi.md).
|
|
192
|
+
|
|
180
193
|
## Configuration
|
|
181
194
|
|
|
182
195
|
Relic stores its runtime defaults in `~/.relic/config.json`.
|
|
@@ -184,12 +197,6 @@ Use `relic config` to manage the default Engram, Claw path, memory window, and d
|
|
|
184
197
|
|
|
185
198
|
For command examples and precedence rules, see [docs/configuration.md](docs/configuration.md).
|
|
186
199
|
|
|
187
|
-
## TODO
|
|
188
|
-
|
|
189
|
-
- [ ] Mikoshi cloud backend (`mikoshi.ectplsm.com`)
|
|
190
|
-
- [ ] `relic mikoshi login` — authenticate with Mikoshi (OAuth Device Flow)
|
|
191
|
-
- [ ] `relic mikoshi upload` / `relic mikoshi download` / `relic mikoshi sync` — sync Engrams with Mikoshi
|
|
192
|
-
|
|
193
200
|
## License
|
|
194
201
|
|
|
195
202
|
[MIT](./LICENCE.md)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type MikoshiClient, type MikoshiEngram, type MikoshiEngramDetail, type CreateEngramInput, type CreateEngramResponse, type SyncStatusResponse, type UpdatePersonaInput, type UpdatePersonaResponse, type UploadMemoryInput, type UploadMemoryResponse, type DownloadMemoryResponse } from "../../core/ports/mikoshi.js";
|
|
2
|
+
/**
|
|
3
|
+
* MikoshiApiClient — Mikoshi REST API v1 の adapter 実装
|
|
4
|
+
*
|
|
5
|
+
* Node.js 組み込みの fetch を使い、外部依存なしで通信する。
|
|
6
|
+
* 認証は Bearer トークン (API キー)。
|
|
7
|
+
*/
|
|
8
|
+
export declare class MikoshiApiClient implements MikoshiClient {
|
|
9
|
+
private readonly baseUrl;
|
|
10
|
+
private readonly apiKey;
|
|
11
|
+
constructor(baseUrl: string, apiKey: string);
|
|
12
|
+
getEngrams(): Promise<MikoshiEngram[]>;
|
|
13
|
+
getEngramBySourceId(sourceEngramId: string): Promise<MikoshiEngram | null>;
|
|
14
|
+
getEngram(engramId: string): Promise<MikoshiEngramDetail>;
|
|
15
|
+
createEngram(input: CreateEngramInput): Promise<CreateEngramResponse>;
|
|
16
|
+
getSyncStatus(engramId: string): Promise<SyncStatusResponse>;
|
|
17
|
+
updatePersona(engramId: string, input: UpdatePersonaInput): Promise<UpdatePersonaResponse>;
|
|
18
|
+
uploadMemory(engramId: string, input: UploadMemoryInput): Promise<UploadMemoryResponse>;
|
|
19
|
+
downloadMemory(engramId: string): Promise<DownloadMemoryResponse>;
|
|
20
|
+
private request;
|
|
21
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { MikoshiApiError, MikoshiEngramSchema, MikoshiEngramDetailSchema, CreateEngramResponseSchema, SyncStatusResponseSchema, UpdatePersonaResponseSchema, UploadMemoryResponseSchema, DownloadMemoryResponseSchema, } from "../../core/ports/mikoshi.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* MikoshiApiClient — Mikoshi REST API v1 の adapter 実装
|
|
5
|
+
*
|
|
6
|
+
* Node.js 組み込みの fetch を使い、外部依存なしで通信する。
|
|
7
|
+
* 認証は Bearer トークン (API キー)。
|
|
8
|
+
*/
|
|
9
|
+
export class MikoshiApiClient {
|
|
10
|
+
baseUrl;
|
|
11
|
+
apiKey;
|
|
12
|
+
constructor(baseUrl, apiKey) {
|
|
13
|
+
// 末尾スラッシュを統一して除去
|
|
14
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
15
|
+
this.apiKey = apiKey;
|
|
16
|
+
}
|
|
17
|
+
// -----------------------------------------------------------------------
|
|
18
|
+
// Public API
|
|
19
|
+
// -----------------------------------------------------------------------
|
|
20
|
+
async getEngrams() {
|
|
21
|
+
const data = await this.request("GET", "/api/v1/engrams");
|
|
22
|
+
return z.array(MikoshiEngramSchema).parse(data);
|
|
23
|
+
}
|
|
24
|
+
async getEngramBySourceId(sourceEngramId) {
|
|
25
|
+
const engrams = await this.getEngrams();
|
|
26
|
+
return engrams.find((e) => e.sourceEngramId === sourceEngramId) ?? null;
|
|
27
|
+
}
|
|
28
|
+
async getEngram(engramId) {
|
|
29
|
+
const data = await this.request("GET", `/api/v1/engrams/${enc(engramId)}`);
|
|
30
|
+
return MikoshiEngramDetailSchema.parse(data);
|
|
31
|
+
}
|
|
32
|
+
async createEngram(input) {
|
|
33
|
+
const data = await this.request("POST", "/api/v1/engrams", input);
|
|
34
|
+
return CreateEngramResponseSchema.parse(data);
|
|
35
|
+
}
|
|
36
|
+
async getSyncStatus(engramId) {
|
|
37
|
+
const data = await this.request("GET", `/api/v1/engrams/${enc(engramId)}/sync-status`);
|
|
38
|
+
return SyncStatusResponseSchema.parse(data);
|
|
39
|
+
}
|
|
40
|
+
async updatePersona(engramId, input) {
|
|
41
|
+
const data = await this.request("PUT", `/api/v1/engrams/${enc(engramId)}/persona`, input);
|
|
42
|
+
return UpdatePersonaResponseSchema.parse(data);
|
|
43
|
+
}
|
|
44
|
+
async uploadMemory(engramId, input) {
|
|
45
|
+
const data = await this.request("PUT", `/api/v1/engrams/${enc(engramId)}/memory`, input);
|
|
46
|
+
return UploadMemoryResponseSchema.parse(data);
|
|
47
|
+
}
|
|
48
|
+
async downloadMemory(engramId) {
|
|
49
|
+
const data = await this.request("GET", `/api/v1/engrams/${enc(engramId)}/memory`);
|
|
50
|
+
return DownloadMemoryResponseSchema.parse(data);
|
|
51
|
+
}
|
|
52
|
+
// -----------------------------------------------------------------------
|
|
53
|
+
// Internal
|
|
54
|
+
// -----------------------------------------------------------------------
|
|
55
|
+
async request(method, path, body) {
|
|
56
|
+
const url = `${this.baseUrl}${path}`;
|
|
57
|
+
const headers = {
|
|
58
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
59
|
+
Accept: "application/json",
|
|
60
|
+
};
|
|
61
|
+
const init = { method, headers };
|
|
62
|
+
if (body !== undefined) {
|
|
63
|
+
headers["Content-Type"] = "application/json";
|
|
64
|
+
init.body = JSON.stringify(body);
|
|
65
|
+
}
|
|
66
|
+
const res = await fetch(url, init);
|
|
67
|
+
if (!res.ok) {
|
|
68
|
+
const text = await res.text().catch(() => "");
|
|
69
|
+
let parsed;
|
|
70
|
+
try {
|
|
71
|
+
parsed = JSON.parse(text);
|
|
72
|
+
}
|
|
73
|
+
catch { /* ignore */ }
|
|
74
|
+
const message = parsed?.error ?? `HTTP ${res.status}`;
|
|
75
|
+
const code = parsed?.code ?? undefined;
|
|
76
|
+
throw new MikoshiApiError(res.status, code, message, parsed);
|
|
77
|
+
}
|
|
78
|
+
return res.json();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** URL-safe path segment encoding */
|
|
82
|
+
function enc(segment) {
|
|
83
|
+
return encodeURIComponent(segment);
|
|
84
|
+
}
|
|
@@ -36,11 +36,12 @@ export class ClaudeShell {
|
|
|
36
36
|
console.log("Hook registered to ~/.claude/settings.json");
|
|
37
37
|
console.log();
|
|
38
38
|
}
|
|
39
|
-
const args = [
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
const args = [];
|
|
40
|
+
// resume 系操作時は injection をスキップ(前回セッションに焼き付き済み)
|
|
41
|
+
if (!options?.skipInjection) {
|
|
42
|
+
args.push("--system-prompt", prompt);
|
|
43
|
+
}
|
|
44
|
+
args.push(...(options?.extraArgs ?? []));
|
|
44
45
|
const env = {};
|
|
45
46
|
if (options?.engramId)
|
|
46
47
|
env.RELIC_ENGRAM_ID = options.engramId;
|
|
@@ -38,11 +38,12 @@ export class CodexShell {
|
|
|
38
38
|
console.log("Hook registered to ~/.codex/hooks.json");
|
|
39
39
|
console.log();
|
|
40
40
|
}
|
|
41
|
-
const args = [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
const args = [];
|
|
42
|
+
// resume 系操作時は injection をスキップ(前回セッションに焼き付き済み)
|
|
43
|
+
if (!options?.skipInjection) {
|
|
44
|
+
args.push("-c", `developer_instructions=${JSON.stringify(wrapWithOverride(prompt))}`);
|
|
45
|
+
}
|
|
46
|
+
args.push("-c", "features.codex_hooks=true", ...(options?.extraArgs ?? []));
|
|
46
47
|
const env = {};
|
|
47
48
|
if (options?.engramId)
|
|
48
49
|
env.RELIC_ENGRAM_ID = options.engramId;
|
|
@@ -106,6 +106,14 @@ export class GeminiShell {
|
|
|
106
106
|
console.log("Hook registered to ~/.gemini/settings.json");
|
|
107
107
|
console.log();
|
|
108
108
|
}
|
|
109
|
+
// resume 系操作時は injection をスキップ(前回セッションに焼き付き済み)
|
|
110
|
+
if (options?.skipInjection) {
|
|
111
|
+
const env = {};
|
|
112
|
+
if (options?.engramId)
|
|
113
|
+
env.RELIC_ENGRAM_ID = options.engramId;
|
|
114
|
+
await spawnShell(this.command, [...(options?.extraArgs ?? [])], options?.cwd, Object.keys(env).length > 0 ? env : undefined);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
109
117
|
// 2. デフォルトシステムプロンプトをキャッシュから読む、なければキャプチャ
|
|
110
118
|
let defaultPrompt;
|
|
111
119
|
if (existsSync(GEMINI_DEFAULT_CACHE)) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume Detection — Shell の extraArgs から resume 系操作を検出する
|
|
3
|
+
*
|
|
4
|
+
* resume 時は Engram injection をスキップし、Shell をそのまま起動する。
|
|
5
|
+
* 各 CLI の resume 引数仕様:
|
|
6
|
+
* - Claude: --resume, -r, --continue, -c, --from-pr (options)
|
|
7
|
+
* - Codex: resume, fork (subcommands)
|
|
8
|
+
* - Gemini: --resume, -r (options)
|
|
9
|
+
*
|
|
10
|
+
* 注意: Claude の -c は --continue の短縮。Codex の -c は --config の短縮。
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* extraArgs が resume 系の操作を含むかを判定する。
|
|
14
|
+
*
|
|
15
|
+
* @param shellName - Shell の表示名 ("Claude Code", "Codex CLI", "Gemini CLI")
|
|
16
|
+
* @param extraArgs - Shell に渡される追加引数
|
|
17
|
+
* @returns resume 系操作が検出された場合 true
|
|
18
|
+
*/
|
|
19
|
+
export declare function isResumeArgs(shellName: string, extraArgs: string[]): boolean;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume Detection — Shell の extraArgs から resume 系操作を検出する
|
|
3
|
+
*
|
|
4
|
+
* resume 時は Engram injection をスキップし、Shell をそのまま起動する。
|
|
5
|
+
* 各 CLI の resume 引数仕様:
|
|
6
|
+
* - Claude: --resume, -r, --continue, -c, --from-pr (options)
|
|
7
|
+
* - Codex: resume, fork (subcommands)
|
|
8
|
+
* - Gemini: --resume, -r (options)
|
|
9
|
+
*
|
|
10
|
+
* 注意: Claude の -c は --continue の短縮。Codex の -c は --config の短縮。
|
|
11
|
+
*/
|
|
12
|
+
/** Claude Code の resume 系オプション */
|
|
13
|
+
const CLAUDE_RESUME_FLAGS = new Set([
|
|
14
|
+
"--resume",
|
|
15
|
+
"-r",
|
|
16
|
+
"--continue",
|
|
17
|
+
"-c",
|
|
18
|
+
"--from-pr",
|
|
19
|
+
]);
|
|
20
|
+
/** Gemini CLI の resume 系オプション */
|
|
21
|
+
const GEMINI_RESUME_FLAGS = new Set([
|
|
22
|
+
"--resume",
|
|
23
|
+
"-r",
|
|
24
|
+
]);
|
|
25
|
+
/** Codex CLI の resume 系サブコマンド */
|
|
26
|
+
const CODEX_RESUME_SUBCOMMANDS = new Set([
|
|
27
|
+
"resume",
|
|
28
|
+
"fork",
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* extraArgs が resume 系の操作を含むかを判定する。
|
|
32
|
+
*
|
|
33
|
+
* @param shellName - Shell の表示名 ("Claude Code", "Codex CLI", "Gemini CLI")
|
|
34
|
+
* @param extraArgs - Shell に渡される追加引数
|
|
35
|
+
* @returns resume 系操作が検出された場合 true
|
|
36
|
+
*/
|
|
37
|
+
export function isResumeArgs(shellName, extraArgs) {
|
|
38
|
+
if (extraArgs.length === 0)
|
|
39
|
+
return false;
|
|
40
|
+
switch (shellName) {
|
|
41
|
+
case "Claude Code":
|
|
42
|
+
return extraArgs.some((arg) => CLAUDE_RESUME_FLAGS.has(arg));
|
|
43
|
+
case "Codex CLI":
|
|
44
|
+
// Codex は resume/fork がサブコマンド(先頭引数)
|
|
45
|
+
return CODEX_RESUME_SUBCOMMANDS.has(extraArgs[0]);
|
|
46
|
+
case "Gemini CLI":
|
|
47
|
+
return extraArgs.some((arg) => GEMINI_RESUME_FLAGS.has(arg));
|
|
48
|
+
default:
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|