@geravant/sinain 1.0.18 → 1.0.19

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.
@@ -0,0 +1,89 @@
1
+ /**
2
+ * sinain-knowledge — Shared type definitions
3
+ *
4
+ * All types used across the knowledge system layers.
5
+ * No runtime dependencies — pure type definitions + interfaces.
6
+ */
7
+
8
+ // ============================================================================
9
+ // Logger interface (decoupled from OpenClaw)
10
+ // ============================================================================
11
+
12
+ export interface Logger {
13
+ info(msg: string): void;
14
+ warn(msg: string): void;
15
+ }
16
+
17
+ // ============================================================================
18
+ // Plugin config
19
+ // ============================================================================
20
+
21
+ export type PluginConfig = {
22
+ heartbeatPath?: string;
23
+ skillPath?: string;
24
+ memoryPath?: string;
25
+ modulesPath?: string;
26
+ sessionKey?: string;
27
+ userTimezone?: string;
28
+ snapshotRepoPath?: string;
29
+ };
30
+
31
+ // ============================================================================
32
+ // Module system
33
+ // ============================================================================
34
+
35
+ export type ModuleRegistryEntry = {
36
+ status: "active" | "suspended" | "disabled";
37
+ priority: number;
38
+ activatedAt: string | null;
39
+ lastTriggered: string | null;
40
+ locked: boolean;
41
+ };
42
+
43
+ export type ModuleRegistry = {
44
+ version: number;
45
+ modules: Record<string, ModuleRegistryEntry>;
46
+ };
47
+
48
+ // ============================================================================
49
+ // Session tracking
50
+ // ============================================================================
51
+
52
+ export type ToolUsageEntry = {
53
+ toolName: string;
54
+ ts: number;
55
+ durationMs?: number;
56
+ error?: string;
57
+ };
58
+
59
+ export type SessionState = {
60
+ startedAt: number;
61
+ toolUsage: ToolUsageEntry[];
62
+ workspaceDir?: string;
63
+ heartbeatToolCalled?: boolean;
64
+ };
65
+
66
+ // ============================================================================
67
+ // Parent context injection (subagent support)
68
+ // ============================================================================
69
+
70
+ export type ParentContextCache = {
71
+ sessionKey: string;
72
+ capturedAt: number;
73
+ contextText: string;
74
+ };
75
+
76
+ // ============================================================================
77
+ // Script execution abstraction
78
+ // ============================================================================
79
+
80
+ export type ScriptResult = {
81
+ code: number;
82
+ stdout: string;
83
+ stderr: string;
84
+ };
85
+
86
+ export type ScriptRunner = (
87
+ args: string[],
88
+ opts: { timeoutMs: number; cwd: string },
89
+ ) => Promise<ScriptResult>;
@@ -0,0 +1,226 @@
1
+ /**
2
+ * sinain-knowledge — Snapshot export/import
3
+ *
4
+ * Serializes the entire knowledge state (playbook, modules, triplestore, logs, config)
5
+ * to a portable JSON format for backup and cross-instance transfer.
6
+ */
7
+
8
+ import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from "node:fs";
9
+ import { join, dirname } from "node:path";
10
+ import { createHash } from "node:crypto";
11
+
12
+ import type { ModuleRegistry } from "./schema.js";
13
+ import type { KnowledgeStore } from "./store.js";
14
+
15
+ // ============================================================================
16
+ // Types
17
+ // ============================================================================
18
+
19
+ export interface KnowledgeSnapshot {
20
+ version: 2;
21
+ integrity: string;
22
+ exportedAt: string;
23
+ exportedFrom: string;
24
+ playbook: {
25
+ base: string;
26
+ effective: string;
27
+ archive: Array<{ ts: string; content: string }>;
28
+ };
29
+ modules: {
30
+ registry: ModuleRegistry | null;
31
+ items: Array<{
32
+ id: string;
33
+ manifest: Record<string, unknown> | null;
34
+ patterns: string;
35
+ guidance: string;
36
+ }>;
37
+ };
38
+ triplestore: {
39
+ dbBase64: string;
40
+ };
41
+ logs: {
42
+ sessionSummaries: string;
43
+ recentPlaybookLogs: string[];
44
+ recentEvalLogs: string[];
45
+ };
46
+ config: {
47
+ memoryConfig: Record<string, unknown> | null;
48
+ evalConfig: Record<string, unknown> | null;
49
+ };
50
+ }
51
+
52
+ // ============================================================================
53
+ // Helpers
54
+ // ============================================================================
55
+
56
+ function readFileSafe(path: string): string {
57
+ try {
58
+ return readFileSync(path, "utf-8");
59
+ } catch {
60
+ return "";
61
+ }
62
+ }
63
+
64
+ function readJsonSafe(path: string): Record<string, unknown> | null {
65
+ try {
66
+ return JSON.parse(readFileSync(path, "utf-8"));
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+
72
+ function computeIntegrity(snapshot: Omit<KnowledgeSnapshot, "integrity">): string {
73
+ const content = JSON.stringify({ ...snapshot, integrity: "" });
74
+ return createHash("sha256").update(content).digest("hex");
75
+ }
76
+
77
+ /** Resolve triplestore path, checking both naming conventions (TS vs Python). */
78
+ export function resolveTriplestorePath(workspaceDir: string): string | null {
79
+ const p1 = join(workspaceDir, "memory", "triples.db");
80
+ if (existsSync(p1)) return p1;
81
+ const p2 = join(workspaceDir, "memory", "triplestore.db");
82
+ if (existsSync(p2)) return p2;
83
+ return null;
84
+ }
85
+
86
+ // ============================================================================
87
+ // Export
88
+ // ============================================================================
89
+
90
+ export function exportSnapshot(
91
+ store: KnowledgeStore,
92
+ opts?: { skipTriplestore?: boolean },
93
+ ): KnowledgeSnapshot {
94
+ const workspaceDir = store.getWorkspaceDir();
95
+
96
+ // Playbook
97
+ const base = store.readPlaybook() ?? "";
98
+ const effective = store.readEffectivePlaybook() ?? "";
99
+ const archiveDir = join(workspaceDir, "memory", "playbook-archive");
100
+ const archive: Array<{ ts: string; content: string }> = [];
101
+ if (existsSync(archiveDir)) {
102
+ const files = readdirSync(archiveDir).filter((f) => f.endsWith(".md")).sort().reverse().slice(0, 10);
103
+ for (const f of files) {
104
+ archive.push({ ts: f.replace(".md", ""), content: readFileSafe(join(archiveDir, f)) });
105
+ }
106
+ }
107
+
108
+ // Modules
109
+ const registry = store.readModuleRegistry();
110
+ const items: KnowledgeSnapshot["modules"]["items"] = [];
111
+ if (registry) {
112
+ for (const id of Object.keys(registry.modules)) {
113
+ const modDir = join(workspaceDir, "modules", id);
114
+ items.push({
115
+ id,
116
+ manifest: readJsonSafe(join(modDir, "manifest.json")),
117
+ patterns: readFileSafe(join(modDir, "patterns.md")),
118
+ guidance: readFileSafe(join(modDir, "guidance.md")),
119
+ });
120
+ }
121
+ }
122
+
123
+ // Triplestore — skip if caller handles it directly (e.g., git store binary copy)
124
+ let dbBase64 = "";
125
+ if (!opts?.skipTriplestore) {
126
+ const dbPath = resolveTriplestorePath(workspaceDir);
127
+ if (dbPath) {
128
+ try { dbBase64 = readFileSync(dbPath).toString("base64"); } catch {}
129
+ }
130
+ }
131
+
132
+ // Logs
133
+ const sessionSummaries = readFileSafe(join(workspaceDir, "memory", "session-summaries.jsonl"));
134
+ const recentPlaybookLogs: string[] = [];
135
+ const pbLogDir = join(workspaceDir, "memory", "playbook-logs");
136
+ if (existsSync(pbLogDir)) {
137
+ const files = readdirSync(pbLogDir).filter((f) => f.endsWith(".jsonl")).sort().reverse().slice(0, 7);
138
+ for (const f of files) {
139
+ recentPlaybookLogs.push(readFileSafe(join(pbLogDir, f)));
140
+ }
141
+ }
142
+ const recentEvalLogs = store.readRecentEvalLogs(20);
143
+
144
+ // Config
145
+ const evalConfig = store.readEvalConfig();
146
+ const memoryConfig = readJsonSafe(join(workspaceDir, "memory", "memory-config.json"));
147
+
148
+ const partial = {
149
+ version: 2 as const,
150
+ exportedAt: new Date().toISOString(),
151
+ exportedFrom: workspaceDir,
152
+ playbook: { base, effective, archive },
153
+ modules: { registry, items },
154
+ triplestore: { dbBase64 },
155
+ logs: { sessionSummaries, recentPlaybookLogs, recentEvalLogs },
156
+ config: { memoryConfig, evalConfig },
157
+ };
158
+
159
+ return {
160
+ ...partial,
161
+ integrity: computeIntegrity(partial),
162
+ };
163
+ }
164
+
165
+ // ============================================================================
166
+ // Import
167
+ // ============================================================================
168
+
169
+ export function importSnapshot(store: KnowledgeStore, snapshot: KnowledgeSnapshot): void {
170
+ const workspaceDir = store.getWorkspaceDir();
171
+
172
+ // Verify integrity
173
+ const expected = computeIntegrity({ ...snapshot, integrity: "" });
174
+ if (expected !== snapshot.integrity) {
175
+ throw new Error(`Snapshot integrity mismatch: expected ${expected}, got ${snapshot.integrity}`);
176
+ }
177
+
178
+ store.ensureMemoryDirs();
179
+
180
+ // Playbook
181
+ if (snapshot.playbook.base) {
182
+ store.writePlaybook(snapshot.playbook.base);
183
+ }
184
+ if (snapshot.playbook.effective) {
185
+ const effectivePath = join(workspaceDir, "memory", "sinain-playbook-effective.md");
186
+ writeFileSync(effectivePath, snapshot.playbook.effective, "utf-8");
187
+ }
188
+ for (const entry of snapshot.playbook.archive) {
189
+ const archiveDir = join(workspaceDir, "memory", "playbook-archive");
190
+ if (!existsSync(archiveDir)) mkdirSync(archiveDir, { recursive: true });
191
+ writeFileSync(join(archiveDir, `${entry.ts}.md`), entry.content, "utf-8");
192
+ }
193
+
194
+ // Modules
195
+ if (snapshot.modules.registry) {
196
+ const modulesDir = join(workspaceDir, "modules");
197
+ if (!existsSync(modulesDir)) mkdirSync(modulesDir, { recursive: true });
198
+ writeFileSync(join(modulesDir, "module-registry.json"), JSON.stringify(snapshot.modules.registry, null, 2), "utf-8");
199
+ }
200
+ for (const mod of snapshot.modules.items) {
201
+ const modDir = join(workspaceDir, "modules", mod.id);
202
+ if (!existsSync(modDir)) mkdirSync(modDir, { recursive: true });
203
+ if (mod.manifest) writeFileSync(join(modDir, "manifest.json"), JSON.stringify(mod.manifest, null, 2), "utf-8");
204
+ if (mod.patterns) writeFileSync(join(modDir, "patterns.md"), mod.patterns, "utf-8");
205
+ if (mod.guidance) writeFileSync(join(modDir, "guidance.md"), mod.guidance, "utf-8");
206
+ }
207
+
208
+ // Triplestore
209
+ if (snapshot.triplestore.dbBase64) {
210
+ const dbPath = join(workspaceDir, "memory", "triples.db");
211
+ writeFileSync(dbPath, Buffer.from(snapshot.triplestore.dbBase64, "base64"));
212
+ }
213
+
214
+ // Logs
215
+ if (snapshot.logs.sessionSummaries) {
216
+ writeFileSync(join(workspaceDir, "memory", "session-summaries.jsonl"), snapshot.logs.sessionSummaries, "utf-8");
217
+ }
218
+
219
+ // Config
220
+ if (snapshot.config.evalConfig) {
221
+ writeFileSync(join(workspaceDir, "memory", "eval-config.json"), JSON.stringify(snapshot.config.evalConfig, null, 2), "utf-8");
222
+ }
223
+ if (snapshot.config.memoryConfig) {
224
+ writeFileSync(join(workspaceDir, "memory", "memory-config.json"), JSON.stringify(snapshot.config.memoryConfig, null, 2), "utf-8");
225
+ }
226
+ }