@poprobertdaniel/openclaw-memory 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.
- package/README.md +22 -10
- package/dist/{chunk-RFLG2CCR.js → chunk-7DNVIKQ3.js} +100 -10
- package/dist/chunk-7DNVIKQ3.js.map +1 -0
- package/dist/{chunk-JSQBXYDM.js → chunk-BTR4T5L3.js} +157 -26
- package/dist/chunk-BTR4T5L3.js.map +1 -0
- package/dist/{chunk-VXULEX3A.cjs → chunk-CSGZH2SG.cjs} +9 -9
- package/dist/chunk-CSGZH2SG.cjs.map +1 -0
- package/dist/{chunk-JNWCMHOB.js → chunk-ITGUJZUL.js} +2 -2
- package/dist/{chunk-JNWCMHOB.js.map → chunk-ITGUJZUL.js.map} +1 -1
- package/dist/{chunk-NHFPLDZK.js → chunk-J2C5USXH.js} +3 -3
- package/dist/{chunk-CRPEAZ44.cjs → chunk-JYQB2DOK.cjs} +161 -30
- package/dist/chunk-JYQB2DOK.cjs.map +1 -0
- package/dist/{chunk-ZY2C2CJQ.cjs → chunk-LA5OP5VI.cjs} +2 -2
- package/dist/chunk-LA5OP5VI.cjs.map +1 -0
- package/dist/{chunk-NMUPGLJW.cjs → chunk-NYZMAY73.cjs} +110 -20
- package/dist/chunk-NYZMAY73.cjs.map +1 -0
- package/dist/cli/index.cjs +25 -25
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +7 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -2
- package/dist/index.d.ts +64 -2
- package/dist/index.js +4 -4
- package/dist/memory-service-B2BAEKR2.cjs +9 -0
- package/dist/memory-service-B2BAEKR2.cjs.map +1 -0
- package/dist/memory-service-ZTLGPIUH.js +9 -0
- package/dist/{server-BTbRv-yX.d.ts → server-CtNlCow7.d.cts} +62 -0
- package/dist/{server-BTbRv-yX.d.cts → server-CtNlCow7.d.ts} +62 -0
- package/dist/server.cjs +4 -4
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +3 -3
- package/package.json +2 -2
- package/templates/.env.example +1 -1
- package/templates/openclaw-memory.config.ts +2 -2
- package/dist/chunk-CRPEAZ44.cjs.map +0 -1
- package/dist/chunk-JSQBXYDM.js.map +0 -1
- package/dist/chunk-NMUPGLJW.cjs.map +0 -1
- package/dist/chunk-RFLG2CCR.js.map +0 -1
- package/dist/chunk-VXULEX3A.cjs.map +0 -1
- package/dist/chunk-ZY2C2CJQ.cjs.map +0 -1
- package/dist/memory-service-6WDMF6KX.cjs +0 -9
- package/dist/memory-service-6WDMF6KX.cjs.map +0 -1
- package/dist/memory-service-GKEG6J2D.js +0 -9
- /package/dist/{chunk-NHFPLDZK.js.map → chunk-J2C5USXH.js.map} +0 -0
- /package/dist/{memory-service-GKEG6J2D.js.map → memory-service-ZTLGPIUH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/private/tmp/openclaw-memory-publish/dist/chunk-LA5OP5VI.cjs","../src/config/index.ts","../src/core/errors.ts","../src/config/defaults.ts"],"names":[],"mappings":"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;AACT,EAAA;AACI,EAAA;AACK,IAAA;AACT,EAAA;AAGM,EAAA;AAGA,EAAA;AAGF,EAAA;AACA,EAAA;AACF,IAAA;AACO,MAAA;AACL,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAEI,EAAA;AACA,EAAA;AACG,IAAA;AACH,MAAA;AACF,IAAA;AACM,IAAA;AACJ,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAEI,EAAA;AACA,EAAA;AACF,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAEI,EAAA;AACA,EAAA;AACF,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACF,IAAA;AACF,EAAA;AAEO,EAAA;AACL,IAAA;AACM,IAAA;AACA,IAAA;AACA,IAAA;AACJ,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AACF;AAIgB;AACP,EAAA;AACT;AAIgB;AACR,EAAA;AACJ,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,EAAA;AAEI,EAAA;AACI,IAAA;AACR,EAAA;AACI,EAAA;AACI,IAAA;AACR,EAAA;AACI,EAAA;AACI,IAAA;AACR,EAAA;AACI,EAAA;AACI,IAAA;AACR,EAAA;AAEO,EAAA;AACT;ADZW;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/private/tmp/openclaw-memory-publish/dist/chunk-LA5OP5VI.cjs","sourcesContent":[null,"import path from \"node:path\";\nimport os from \"node:os\";\nimport fs from \"node:fs\";\nimport type { Tier } from \"../core/types.js\";\nimport { ConfigError } from \"../core/errors.js\";\nimport { DEFAULTS } from \"./defaults.js\";\nimport type { Config, ResolvedConfig, QdrantConfig, AgeConfig, EmbeddingConfig, ExtractionConfig } from \"./schema.js\";\n\nexport type { Config, ResolvedConfig } from \"./schema.js\";\n\n// ── Helper: expand ~ to home dir ────────────────────────────────────────\n\nfunction expandHome(p: string): string {\n if (p.startsWith(\"~/\") || p === \"~\") {\n return path.join(os.homedir(), p.slice(1));\n }\n return p;\n}\n\n// ── Data Directory ──────────────────────────────────────────────────────\n\nexport function getDataDir(): string {\n return process.env.OPENCLAW_MEMORY_DATA_DIR || path.join(os.homedir(), \".openclaw-memory\");\n}\n\nexport function getDefaultSqlitePath(): string {\n return path.join(getDataDir(), \"memory.sqlite\");\n}\n\nexport function getPidFilePath(): string {\n return path.join(getDataDir(), \"server.pid\");\n}\n\n// ── Config File Discovery ───────────────────────────────────────────────\n\nfunction getConfigSearchPaths(cwd: string): string[] {\n return [\n path.join(cwd, \"openclaw-memory.config.ts\"),\n path.join(cwd, \"openclaw-memory.config.js\"),\n path.join(cwd, \"openclaw-memory.config.json\"),\n path.join(getDataDir(), \"config.ts\"),\n path.join(getDataDir(), \"config.json\"),\n ];\n}\n\nasync function loadConfigFile(configPath?: string): Promise<Config | null> {\n const searchPaths = configPath ? [configPath] : getConfigSearchPaths(process.cwd());\n\n for (const p of searchPaths) {\n if (fs.existsSync(p)) {\n if (p.endsWith(\".json\")) {\n const content = fs.readFileSync(p, \"utf-8\");\n return JSON.parse(content) as Config;\n }\n // For .ts and .js files, try dynamic import\n try {\n const mod = await import(p);\n return (mod.default || mod) as Config;\n } catch {\n // Can't import .ts outside of Bun — skip\n }\n }\n }\n\n return null;\n}\n\n// ── Environment Variable Loading ────────────────────────────────────────\n\nfunction loadFromEnv(): Partial<Config> {\n const config: Partial<Config> = {};\n\n // Load .env file if dotenv is available\n try {\n const dotenvPath = path.join(process.cwd(), \".env\");\n if (fs.existsSync(dotenvPath)) {\n const envContent = fs.readFileSync(dotenvPath, \"utf-8\");\n for (const line of envContent.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx === -1) continue;\n const key = trimmed.slice(0, eqIdx).trim();\n const value = trimmed.slice(eqIdx + 1).trim().replace(/^[\"']|[\"']$/g, \"\");\n if (!process.env[key]) {\n process.env[key] = value;\n }\n }\n }\n } catch {\n // No .env file — that's fine\n }\n\n const env = process.env;\n\n // Tier\n const tier = env.OPENCLAW_MEMORY_TIER || env.MEMORY_TIER;\n if (tier && [\"lite\", \"standard\", \"full\"].includes(tier)) {\n config.tier = tier as Tier;\n }\n\n // Port/Host\n const port = env.OPENCLAW_MEMORY_PORT || env.PORT;\n if (port) config.port = parseInt(port, 10);\n\n const host = env.OPENCLAW_MEMORY_HOST;\n if (host) config.host = host;\n\n // Auth\n const authToken = env.OPENCLAW_MEMORY_AUTH__TOKEN || env.AUTH_TOKEN || env.MEMORY_TOKEN;\n if (authToken) {\n config.auth = { token: authToken, enabled: true };\n }\n\n // SQLite\n const sqlitePath = env.OPENCLAW_MEMORY_SQLITE__PATH || env.SQLITE_PATH;\n if (sqlitePath) {\n config.sqlite = { path: sqlitePath };\n }\n\n // Qdrant\n const qdrantUrl = env.OPENCLAW_MEMORY_QDRANT__URL || env.QDRANT_URL;\n if (qdrantUrl) {\n config.qdrant = {\n url: qdrantUrl,\n collection: env.OPENCLAW_MEMORY_QDRANT__COLLECTION || env.QDRANT_COLLECTION || DEFAULTS.qdrant.collection,\n apiKey: env.OPENCLAW_MEMORY_QDRANT__API_KEY,\n };\n }\n\n // AGE\n const ageHost = env.OPENCLAW_MEMORY_AGE__HOST || env.PGHOST;\n if (ageHost) {\n config.age = {\n host: ageHost,\n port: parseInt(env.OPENCLAW_MEMORY_AGE__PORT || env.PGPORT || String(DEFAULTS.age.port), 10),\n user: env.OPENCLAW_MEMORY_AGE__USER || env.PGUSER || \"\",\n password: env.OPENCLAW_MEMORY_AGE__PASSWORD || env.PGPASSWORD || \"\",\n database: env.OPENCLAW_MEMORY_AGE__DATABASE || env.PGDATABASE || \"\",\n graph: env.OPENCLAW_MEMORY_AGE__GRAPH || env.AGE_GRAPH || DEFAULTS.age.graph,\n };\n }\n\n // Embedding\n const embeddingApiKey = env.OPENCLAW_MEMORY_EMBEDDING__API_KEY || env.OPENROUTER_API_KEY || env.OPENAI_API_KEY;\n if (embeddingApiKey) {\n config.embedding = {\n apiKey: embeddingApiKey,\n baseUrl: env.OPENCLAW_MEMORY_EMBEDDING__BASE_URL || env.EMBEDDING_BASE_URL,\n model: env.OPENCLAW_MEMORY_EMBEDDING__MODEL || env.EMBEDDING_MODEL || DEFAULTS.embedding.model,\n dimensions: parseInt(env.OPENCLAW_MEMORY_EMBEDDING__DIMENSIONS || String(DEFAULTS.embedding.dimensions), 10),\n };\n }\n\n // Extraction\n const extractionApiKey = env.OPENCLAW_MEMORY_EXTRACTION__API_KEY || env.OPENROUTER_API_KEY || env.OPENAI_API_KEY;\n if (extractionApiKey) {\n config.extraction = {\n apiKey: extractionApiKey,\n baseUrl: env.OPENCLAW_MEMORY_EXTRACTION__BASE_URL || env.EXTRACTION_BASE_URL,\n model: env.OPENCLAW_MEMORY_EXTRACTION__MODEL || env.EXTRACTION_MODEL || DEFAULTS.extraction.model,\n enabled: env.OPENCLAW_MEMORY_EXTRACTION__ENABLED !== \"false\",\n };\n }\n\n return config;\n}\n\n// ── Tier Inference ──────────────────────────────────────────────────────\n\nfunction inferTier(config: Partial<Config>): Tier {\n if (config.tier) return config.tier;\n if (config.qdrant && config.age) return \"full\";\n if (config.qdrant) return \"standard\";\n return \"lite\";\n}\n\n// ── Config Resolution ───────────────────────────────────────────────────\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n // 1. Load from file\n const fileConfig = await loadConfigFile(configPath);\n\n // 2. Load from env\n const envConfig = loadFromEnv();\n\n // 3. Merge: file < env (env wins)\n const merged: Partial<Config> = {\n ...fileConfig,\n ...envConfig,\n // Deep merge nested objects\n auth: { ...fileConfig?.auth, ...envConfig.auth },\n sqlite: { ...fileConfig?.sqlite, ...envConfig.sqlite },\n };\n\n if (envConfig.qdrant || fileConfig?.qdrant) {\n merged.qdrant = { ...fileConfig?.qdrant, ...envConfig.qdrant } as Config[\"qdrant\"];\n }\n if (envConfig.age || fileConfig?.age) {\n merged.age = { ...fileConfig?.age, ...envConfig.age } as Config[\"age\"];\n }\n if (envConfig.embedding || fileConfig?.embedding) {\n merged.embedding = { ...fileConfig?.embedding, ...envConfig.embedding } as Config[\"embedding\"];\n }\n if (envConfig.extraction || fileConfig?.extraction) {\n merged.extraction = { ...fileConfig?.extraction, ...envConfig.extraction } as Config[\"extraction\"];\n }\n\n // 4. Infer tier\n const tier = inferTier(merged);\n\n // 5. Resolve defaults\n const sqlitePath = expandHome(merged.sqlite?.path || DEFAULTS.sqlite.path);\n\n // 6. Resolve optional layers based on tier\n let qdrant: QdrantConfig | null = null;\n if (tier !== \"lite\" && merged.qdrant?.url) {\n qdrant = {\n url: merged.qdrant.url,\n collection: merged.qdrant.collection || DEFAULTS.qdrant.collection,\n apiKey: merged.qdrant.apiKey,\n };\n }\n\n let age: AgeConfig | null = null;\n if (tier === \"full\" && merged.age?.host) {\n if (!merged.age.user || !merged.age.password || !merged.age.database) {\n throw new ConfigError(\"Full tier requires age.user, age.password, and age.database\");\n }\n age = {\n host: merged.age.host,\n port: merged.age.port || DEFAULTS.age.port,\n user: merged.age.user,\n password: merged.age.password,\n database: merged.age.database,\n graph: merged.age.graph || DEFAULTS.age.graph,\n };\n }\n\n let embedding: EmbeddingConfig | null = null;\n if (tier !== \"lite\" && merged.embedding?.apiKey) {\n embedding = {\n apiKey: merged.embedding.apiKey,\n baseUrl: merged.embedding.baseUrl,\n model: merged.embedding.model || DEFAULTS.embedding.model,\n dimensions: merged.embedding.dimensions || DEFAULTS.embedding.dimensions,\n };\n }\n\n let extraction: ExtractionConfig | null = null;\n if (tier !== \"lite\" && merged.extraction?.apiKey) {\n extraction = {\n apiKey: merged.extraction.apiKey,\n baseUrl: merged.extraction.baseUrl,\n model: merged.extraction.model || DEFAULTS.extraction.model,\n enabled: merged.extraction.enabled ?? DEFAULTS.extraction.enabled,\n };\n }\n\n return {\n tier,\n port: merged.port || DEFAULTS.port,\n host: merged.host || DEFAULTS.host,\n auth: {\n token: merged.auth?.token,\n enabled: merged.auth?.enabled ?? DEFAULTS.auth.enabled,\n },\n sqlite: { path: sqlitePath },\n qdrant,\n age,\n embedding,\n extraction,\n agents: merged.agents || fileConfig?.agents || [],\n };\n}\n\n// ── defineConfig helper for config files ────────────────────────────────\n\nexport function defineConfig(config: Config): Config {\n return config;\n}\n\n// ── Config summary (redacted) for logging ───────────────────────────────\n\nexport function configSummary(config: ResolvedConfig): string {\n const lines: string[] = [\n `Tier: ${config.tier}`,\n `Port: ${config.port}`,\n `Host: ${config.host}`,\n `SQLite: ${config.sqlite.path}`,\n `Auth: ${config.auth.enabled ? \"enabled\" : \"disabled\"}`,\n ];\n\n if (config.qdrant) {\n lines.push(`Qdrant: ${config.qdrant.url} (collection: ${config.qdrant.collection})`);\n }\n if (config.age) {\n lines.push(`AGE: ${config.age.host}:${config.age.port}/${config.age.database}`);\n }\n if (config.embedding) {\n lines.push(`Embedding: ${config.embedding.model}${config.embedding.baseUrl ? ` via ${config.embedding.baseUrl}` : \"\"}`);\n }\n if (config.extraction) {\n lines.push(`Extraction: ${config.extraction.model}${config.extraction.enabled ? \"\" : \" (disabled)\"}`);\n }\n\n return lines.join(\"\\n\");\n}\n","// ── Custom Error Classes ────────────────────────────────────────────────\n\nexport class MemoryError extends Error {\n constructor(message: string, public readonly code: string) {\n super(message);\n this.name = \"MemoryError\";\n }\n}\n\nexport class ConfigError extends MemoryError {\n constructor(message: string) {\n super(message, \"CONFIG_ERROR\");\n this.name = \"ConfigError\";\n }\n}\n\nexport class StorageError extends MemoryError {\n constructor(message: string, public readonly layer: \"sqlite\" | \"qdrant\" | \"age\") {\n super(message, \"STORAGE_ERROR\");\n this.name = \"StorageError\";\n }\n}\n\nexport class ValidationError extends MemoryError {\n constructor(message: string, public readonly details?: unknown) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\nexport class NotFoundError extends MemoryError {\n constructor(resource: string, id: string) {\n super(`${resource} not found: ${id}`, \"NOT_FOUND\");\n this.name = \"NotFoundError\";\n }\n}\n\nexport class AuthError extends MemoryError {\n constructor(message: string = \"Unauthorized\") {\n super(message, \"AUTH_ERROR\");\n this.name = \"AuthError\";\n }\n}\n","// ── Default Configuration Values ────────────────────────────────────────\n\nexport const DEFAULTS = {\n port: 7777,\n host: \"0.0.0.0\",\n sqlite: {\n path: \"~/.openclaw-memory/memory.sqlite\",\n },\n qdrant: {\n collection: \"openclaw_memories\",\n },\n age: {\n port: 5432,\n graph: \"agent_memory\",\n },\n embedding: {\n model: \"text-embedding-3-small\",\n dimensions: 1536,\n },\n extraction: {\n model: \"gpt-5-nano\",\n enabled: true,\n },\n auth: {\n enabled: true,\n },\n} as const;\n"]}
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var _chunkCRPEAZ44cjs = require('./chunk-CRPEAZ44.cjs');
|
|
6
5
|
|
|
6
|
+
var _chunkJYQB2DOKcjs = require('./chunk-JYQB2DOK.cjs');
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
var _chunkLA5OP5VIcjs = require('./chunk-LA5OP5VI.cjs');
|
|
14
15
|
|
|
15
16
|
// src/server.ts
|
|
16
17
|
var _url = require('url');
|
|
@@ -146,7 +147,7 @@ function memoriesRoutes(orchestrator) {
|
|
|
146
147
|
// src/api/search.ts
|
|
147
148
|
|
|
148
149
|
function searchRoutes(orchestrator) {
|
|
149
|
-
const searchEngine = new (0,
|
|
150
|
+
const searchEngine = new (0, _chunkJYQB2DOKcjs.SearchEngine)(orchestrator);
|
|
150
151
|
return new (0, _elysia.Elysia)({ prefix: "/api/search" }).post(
|
|
151
152
|
"/",
|
|
152
153
|
async ({ body, set }) => {
|
|
@@ -296,7 +297,7 @@ function searchRoutes(orchestrator) {
|
|
|
296
297
|
// src/api/conversations.ts
|
|
297
298
|
|
|
298
299
|
function conversationRoutes(orchestrator, config) {
|
|
299
|
-
const summarizer = config.extraction ? new (0,
|
|
300
|
+
const summarizer = config.extraction ? new (0, _chunkJYQB2DOKcjs.ConversationSummarizer)({
|
|
300
301
|
apiKey: config.extraction.apiKey,
|
|
301
302
|
baseUrl: config.extraction.baseUrl,
|
|
302
303
|
model: config.extraction.model
|
|
@@ -489,9 +490,10 @@ function entityRoutes(orchestrator) {
|
|
|
489
490
|
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
490
491
|
|
|
491
492
|
function adminRoutes(orchestrator) {
|
|
492
|
-
|
|
493
|
+
const healthHandler = async () => {
|
|
493
494
|
return await orchestrator.healthCheck();
|
|
494
|
-
}
|
|
495
|
+
};
|
|
496
|
+
return new (0, _elysia.Elysia)().get("/api/health", healthHandler).get("/health", healthHandler).post("/api/sync/retry", async ({ set }) => {
|
|
495
497
|
try {
|
|
496
498
|
const result = await orchestrator.retrySyncQueue();
|
|
497
499
|
return result;
|
|
@@ -502,7 +504,63 @@ function adminRoutes(orchestrator) {
|
|
|
502
504
|
details: error instanceof Error ? error.message : String(error)
|
|
503
505
|
};
|
|
504
506
|
}
|
|
505
|
-
}).
|
|
507
|
+
}).post(
|
|
508
|
+
"/api/admin/resync",
|
|
509
|
+
async ({ query, set }) => {
|
|
510
|
+
const layerParam = parseLayerParam(query.layer);
|
|
511
|
+
if (!layerParam) {
|
|
512
|
+
set.status = 400;
|
|
513
|
+
return {
|
|
514
|
+
error: "Invalid layer parameter",
|
|
515
|
+
details: "Use ?layer=qdrant|age|both"
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
const batch = parseBatchParam(query.batch);
|
|
519
|
+
if (batch === null) {
|
|
520
|
+
set.status = 400;
|
|
521
|
+
return {
|
|
522
|
+
error: "Invalid batch parameter",
|
|
523
|
+
details: "Use a positive integer for ?batch=50"
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
const layers = layerParam === "both" ? ["qdrant", "age"] : [layerParam];
|
|
527
|
+
try {
|
|
528
|
+
const memories = listAllMemories(orchestrator);
|
|
529
|
+
let queuedItems = 0;
|
|
530
|
+
for (const memory of memories) {
|
|
531
|
+
for (const layer of layers) {
|
|
532
|
+
orchestrator.sqlite.addToSyncQueue(memory.id, layer, "upsert");
|
|
533
|
+
queuedItems++;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
const syncResults = await _chunkJYQB2DOKcjs.SyncQueueProcessor.withBatchSize(batch, async () => {
|
|
537
|
+
return await orchestrator.retrySyncQueue();
|
|
538
|
+
});
|
|
539
|
+
return {
|
|
540
|
+
layer: layerParam,
|
|
541
|
+
layers,
|
|
542
|
+
batch,
|
|
543
|
+
memory_count: memories.length,
|
|
544
|
+
queued_items: queuedItems,
|
|
545
|
+
sync_results: syncResults
|
|
546
|
+
};
|
|
547
|
+
} catch (error) {
|
|
548
|
+
set.status = 500;
|
|
549
|
+
return {
|
|
550
|
+
error: "Resync failed",
|
|
551
|
+
details: error instanceof Error ? error.message : String(error)
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
query: _elysia.t.Object({
|
|
557
|
+
layer: _elysia.t.Optional(
|
|
558
|
+
_elysia.t.Union([_elysia.t.Literal("qdrant"), _elysia.t.Literal("age"), _elysia.t.Literal("both")])
|
|
559
|
+
),
|
|
560
|
+
batch: _elysia.t.Optional(_elysia.t.String())
|
|
561
|
+
})
|
|
562
|
+
}
|
|
563
|
+
).get("/api/sync/queue", () => {
|
|
506
564
|
const items = orchestrator.sqlite.getSyncQueue(100);
|
|
507
565
|
return { items, count: items.length };
|
|
508
566
|
}).post(
|
|
@@ -531,6 +589,33 @@ function adminRoutes(orchestrator) {
|
|
|
531
589
|
return { error: "Not yet implemented" };
|
|
532
590
|
});
|
|
533
591
|
}
|
|
592
|
+
function parseLayerParam(layer) {
|
|
593
|
+
if (!layer) return "both";
|
|
594
|
+
if (layer === "qdrant" || layer === "age" || layer === "both") return layer;
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
function parseBatchParam(batch) {
|
|
598
|
+
if (!batch) return 50;
|
|
599
|
+
const parsed = Number.parseInt(batch, 10);
|
|
600
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return null;
|
|
601
|
+
return parsed;
|
|
602
|
+
}
|
|
603
|
+
function listAllMemories(orchestrator) {
|
|
604
|
+
const pageSize = 5e3;
|
|
605
|
+
const memories = [];
|
|
606
|
+
let offset = 0;
|
|
607
|
+
while (true) {
|
|
608
|
+
const page = orchestrator.sqlite.listMemories({
|
|
609
|
+
limit: pageSize,
|
|
610
|
+
offset,
|
|
611
|
+
order: "asc"
|
|
612
|
+
});
|
|
613
|
+
memories.push(...page);
|
|
614
|
+
if (page.length < pageSize) break;
|
|
615
|
+
offset += pageSize;
|
|
616
|
+
}
|
|
617
|
+
return memories;
|
|
618
|
+
}
|
|
534
619
|
async function migrateMarkdownFiles(orchestrator, request) {
|
|
535
620
|
const { markdown_paths, agent_id, dry_run } = request;
|
|
536
621
|
let migrated = 0;
|
|
@@ -653,34 +738,34 @@ function inferTags(heading, fileName) {
|
|
|
653
738
|
// src/api/router.ts
|
|
654
739
|
function createApp(orchestrator, config) {
|
|
655
740
|
const app = new (0, _elysia.Elysia)().use(_cors.cors.call(void 0, )).derive(({ headers, set, path: path2 }) => {
|
|
656
|
-
if (path2 === "/api/health") return {};
|
|
741
|
+
if (path2 === "/api/health" || path2 === "/health") return {};
|
|
657
742
|
if (!config.auth.enabled || !config.auth.token) return {};
|
|
658
743
|
const authHeader = headers.authorization;
|
|
659
744
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
660
745
|
set.status = 401;
|
|
661
|
-
throw new (0,
|
|
746
|
+
throw new (0, _chunkLA5OP5VIcjs.AuthError)("Missing or invalid Authorization header");
|
|
662
747
|
}
|
|
663
748
|
const token = authHeader.slice(7);
|
|
664
749
|
if (token !== config.auth.token) {
|
|
665
750
|
set.status = 403;
|
|
666
|
-
throw new (0,
|
|
751
|
+
throw new (0, _chunkLA5OP5VIcjs.AuthError)("Invalid token");
|
|
667
752
|
}
|
|
668
753
|
return {};
|
|
669
754
|
}).onError(({ code, error, set }) => {
|
|
670
|
-
if (error instanceof
|
|
755
|
+
if (error instanceof _chunkLA5OP5VIcjs.AuthError) {
|
|
671
756
|
const status = error.message.includes("Invalid token") ? 403 : 401;
|
|
672
757
|
set.status = status;
|
|
673
758
|
return { error: error.message, code: error.code };
|
|
674
759
|
}
|
|
675
|
-
if (error instanceof
|
|
760
|
+
if (error instanceof _chunkLA5OP5VIcjs.NotFoundError) {
|
|
676
761
|
set.status = 404;
|
|
677
762
|
return { error: error.message, code: error.code };
|
|
678
763
|
}
|
|
679
|
-
if (error instanceof
|
|
764
|
+
if (error instanceof _chunkLA5OP5VIcjs.ValidationError) {
|
|
680
765
|
set.status = 400;
|
|
681
766
|
return { error: error.message, code: error.code, details: error.details };
|
|
682
767
|
}
|
|
683
|
-
if (error instanceof
|
|
768
|
+
if (error instanceof _chunkLA5OP5VIcjs.MemoryError) {
|
|
684
769
|
set.status = 500;
|
|
685
770
|
return { error: error.message, code: error.code };
|
|
686
771
|
}
|
|
@@ -689,6 +774,11 @@ function createApp(orchestrator, config) {
|
|
|
689
774
|
set.status = 400;
|
|
690
775
|
return { error: "Validation error", details: msg2 };
|
|
691
776
|
}
|
|
777
|
+
if (code === "NOT_FOUND") {
|
|
778
|
+
const msg2 = error && "message" in error ? error.message : "Route not found";
|
|
779
|
+
set.status = 404;
|
|
780
|
+
return { error: msg2, code };
|
|
781
|
+
}
|
|
692
782
|
const msg = error instanceof Error ? error.stack || error.message : String(error);
|
|
693
783
|
console.error(`[api] Unhandled error: ${msg}`);
|
|
694
784
|
set.status = 500;
|
|
@@ -699,8 +789,8 @@ function createApp(orchestrator, config) {
|
|
|
699
789
|
|
|
700
790
|
// src/server.ts
|
|
701
791
|
async function createServer(configPath) {
|
|
702
|
-
const config = await
|
|
703
|
-
const orchestrator = new (0,
|
|
792
|
+
const config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, configPath);
|
|
793
|
+
const orchestrator = new (0, _chunkJYQB2DOKcjs.StorageOrchestrator)(config);
|
|
704
794
|
await orchestrator.init();
|
|
705
795
|
const app = createApp(orchestrator, config);
|
|
706
796
|
return { app, orchestrator, config };
|
|
@@ -712,7 +802,7 @@ async function main() {
|
|
|
712
802
|
console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
713
803
|
const { app, orchestrator, config } = await createServer();
|
|
714
804
|
console.log("[config]");
|
|
715
|
-
console.log(
|
|
805
|
+
console.log(_chunkLA5OP5VIcjs.configSummary.call(void 0, config).split("\n").map((l) => ` ${l}`).join("\n"));
|
|
716
806
|
app.listen(config.port);
|
|
717
807
|
console.log(`[server] Listening on http://${config.host}:${config.port}`);
|
|
718
808
|
console.log(`[server] Health check: http://localhost:${config.port}/api/health`);
|
|
@@ -726,8 +816,8 @@ async function main() {
|
|
|
726
816
|
}
|
|
727
817
|
function isMainModule() {
|
|
728
818
|
try {
|
|
729
|
-
|
|
730
|
-
|
|
819
|
+
const bun = globalThis.Bun;
|
|
820
|
+
if (typeof bun !== "undefined") {
|
|
731
821
|
return bun.main === _url.fileURLToPath.call(void 0, import.meta.url);
|
|
732
822
|
}
|
|
733
823
|
if (process.argv[1]) {
|
|
@@ -749,4 +839,4 @@ if (isMainModule()) {
|
|
|
749
839
|
|
|
750
840
|
|
|
751
841
|
exports.createApp = createApp; exports.createServer = createServer;
|
|
752
|
-
//# sourceMappingURL=chunk-
|
|
842
|
+
//# sourceMappingURL=chunk-NYZMAY73.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/private/tmp/openclaw-memory-publish/dist/chunk-NYZMAY73.cjs","../src/server.ts","../src/api/router.ts","../src/api/memories.ts","../src/api/search.ts","../src/api/conversations.ts","../src/api/entities.ts","../src/api/admin.ts"],"names":["Elysia","t","path"],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACF,wDAA6B;AAC7B;AACA;ACfA,0BAA8B;AAC9B,wEAAwB;ADiBxB;AACA;AEnBA,gCAAuB;AACvB,sCAAqB;AFqBrB;AACA;AGvBA;AAMO,SAAS,cAAA,CAAe,YAAA,EAAmC;AAChE,EAAA,OAAO,IAAI,mBAAA,CAAO,EAAE,MAAA,EAAQ,gBAAgB,CAAC,CAAA,CAE1C,IAAA;AAAA,IACC,GAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,EAAS,MAAM,YAAA,CAAa,YAAA,CAAa,IAA2B,CAAA;AAC1E,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO,MAAA;AAAA,MACT,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,yBAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,SAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAU,SAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QACnB,KAAA,EAAO,SAAA,CAAE,KAAA,CAAM;AAAA,UACb,SAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,UAChB,SAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,UACjB,SAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,UAClB,SAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,UACnB,SAAA,CAAE,OAAA,CAAQ,SAAS;AAAA,QACrB,CAAC,CAAA;AAAA,QACD,UAAA,EAAY,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,OAAA,EAAS,SAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAClB,IAAA,EAAM,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,KAAA,CAAM,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QACpC,MAAA,EAAQ,SAAA,CAAE,QAAA;AAAA,UACR,SAAA,CAAE,KAAA,CAAM;AAAA,YACN,SAAA,CAAE,OAAA,CAAQ,UAAU,CAAA;AAAA,YACpB,SAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,YACnB,SAAA,CAAE,OAAA,CAAQ,aAAa,CAAA;AAAA,YACvB,SAAA,CAAE,OAAA,CAAQ,sBAAsB,CAAA;AAAA,YAChC,SAAA,CAAE,OAAA,CAAQ,mBAAmB,CAAA;AAAA,YAC7B,SAAA,CAAE,OAAA,CAAQ,cAAc,CAAA;AAAA,YACxB,SAAA,CAAE,OAAA,CAAQ,WAAW;AAAA,UACvB,CAAC;AAAA,QACH,CAAA;AAAA,QACA,UAAA,EAAY,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,gBAAA,EAAkB,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,QACxC,UAAA,EAAY,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC;AAAA,MAC/C,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,GAAA,CAAI,MAAA,EAAQ,CAAC,EAAE,MAAA,EAAQ,IAAI,CAAA,EAAA,GAAM;AAChC,IAAA,MAAM,OAAA,EAAS,YAAA,CAAa,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,EAAE,CAAA;AACtD,IAAA,GAAA,CAAI,CAAC,MAAA,EAAQ;AACX,MAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,MAAA,OAAO,EAAE,KAAA,EAAO,mBAAmB,CAAA;AAAA,IACrC;AACA,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA,CAGA,GAAA;AAAA,IACC,MAAA;AAAA,IACA,MAAA,CAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AAC/B,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,EAAS,MAAM,YAAA,CAAa,YAAA;AAAA,UAChC,MAAA,CAAO,EAAA;AAAA,UACP;AAAA,QACF,CAAA;AACA,QAAA,GAAA,CAAI,CAAC,MAAA,EAAQ;AACX,UAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,UAAA,OAAO,EAAE,KAAA,EAAO,mBAAmB,CAAA;AAAA,QACrC;AACA,QAAA,OAAO,MAAA;AAAA,MACT,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,yBAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,SAAA,CAAE,MAAA,CAAO;AAAA,QACb,OAAA,EAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC9B,IAAA,EAAM,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,KAAA,CAAM,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QACpC,KAAA,EAAO,SAAA,CAAE,QAAA;AAAA,UACP,SAAA,CAAE,KAAA,CAAM;AAAA,YACN,SAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,YAChB,SAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,YACjB,SAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,YAClB,SAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,YACnB,SAAA,CAAE,OAAA,CAAQ,SAAS;AAAA,UACrB,CAAC;AAAA,QACH,CAAA;AAAA,QACA,UAAA,EAAY,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,UAAA,EAAY,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,gBAAA,EAAkB,SAAA,CAAE,QAAA,CAAS,SAAA,CAAE,OAAA,CAAQ,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,MAAA,CAAO,MAAA,EAAQ,MAAA,CAAO,EAAE,MAAA,EAAQ,IAAI,CAAA,EAAA,GAAM;AACzC,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,EAAU,MAAM,YAAA,CAAa,YAAA,CAAa,MAAA,CAAO,EAAE,CAAA;AACzD,MAAA,GAAA,CAAI,CAAC,OAAA,EAAS;AACZ,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO,EAAE,KAAA,EAAO,mBAAmB,CAAA;AAAA,MACrC;AACA,MAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,EAAA,EAAI,MAAA,CAAO,GAAG,CAAA;AAAA,IACxC,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,yBAAA;AAAA,QACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,MAChE,CAAA;AAAA,IACF;AAAA,EACF,CAAC,CAAA,CAGA,GAAA,CAAI,GAAA,EAAK,CAAC,EAAE,MAAM,CAAA,EAAA,GAAM;AACvB,IAAA,MAAM,SAAA,EAAW,YAAA,CAAa,MAAA,CAAO,YAAA,CAAa;AAAA,MAChD,QAAA,EAAU,KAAA,CAAM,QAAA;AAAA,MAChB,KAAA,EAAO,KAAA,CAAM,KAAA;AAAA,MACb,UAAA,EAAY,KAAA,CAAM,UAAA;AAAA,MAClB,MAAA,EAAQ,KAAA,CAAM,MAAA;AAAA,MACd,IAAA,EAAM,KAAA,CAAM,IAAA;AAAA,MACZ,KAAA,EAAO,KAAA,CAAM,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,EAAG,EAAE,EAAA,EAAI,KAAA,CAAA;AAAA,MACzD,MAAA,EAAQ,KAAA,CAAM,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,EAAG,EAAE,EAAA,EAAI,KAAA,CAAA;AAAA,MAC5D,KAAA,EAAQ,KAAA,CAAM,MAAA,GAA4B;AAAA,IAC5C,CAAC,CAAA;AACD,IAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,QAAA,CAAS,OAAO,CAAA;AAAA,EAC5C,CAAC,CAAA;AACL;AHMA;AACA;AIlJA;AAOO,SAAS,YAAA,CAAa,YAAA,EAAmC;AAC9D,EAAA,MAAM,aAAA,EAAe,IAAI,mCAAA,CAAa,YAAY,CAAA;AAElD,EAAA,OAAO,IAAIA,mBAAAA,CAAO,EAAE,MAAA,EAAQ,cAAc,CAAC,CAAA,CAExC,IAAA;AAAA,IACC,GAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,EAAM,IAAA;AACZ,QAAA,GAAA,CAAI,CAAC,GAAA,CAAI,QAAA,EAAU,GAAA,CAAI,YAAA,EAAc,IAAA;AACrC,QAAA,OAAO,MAAM,YAAA,CAAa,MAAA,CAAO,GAAG,CAAA;AAAA,MACtC,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,eAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMC,SAAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAUA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC/B,KAAA,EAAOA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAChB,MAAA,EAAQA,SAAAA,CAAE,QAAA;AAAA,UACRA,SAAAA,CAAE,KAAA;AAAA,YACAA,SAAAA,CAAE,KAAA,CAAM;AAAA,cACNA,SAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,cAChBA,SAAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,cACjBA,SAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,cAClBA,SAAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,cACnBA,SAAAA,CAAE,OAAA,CAAQ,SAAS;AAAA,YACrB,CAAC;AAAA,UACH;AAAA,QACF,CAAA;AAAA,QACA,UAAA,EAAYA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,KAAA,EAAOA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC5B,aAAA,EAAeA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,QACrC,WAAA,EAAaA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,QACnC,QAAA,EAAUA,SAAAA,CAAE,QAAA;AAAA,UACVA,SAAAA,CAAE,KAAA,CAAM;AAAA,YACNA,SAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,YAChBA,SAAAA,CAAE,OAAA,CAAQ,UAAU,CAAA;AAAA,YACpBA,SAAAA,CAAE,OAAA,CAAQ,UAAU,CAAA;AAAA,YACpBA,SAAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,YACjBA,SAAAA,CAAE,OAAA,CAAQ,KAAK;AAAA,UACjB,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,IAAA;AAAA,IACC,WAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,YAAA,CAAa,MAAA,CAAO;AAAA,UAC/B,GAAI,IAAA;AAAA,UACJ,QAAA,EAAU;AAAA,QACZ,CAAC,CAAA;AAAA,MACH,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,wBAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMA,SAAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAUA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC/B,KAAA,EAAOA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAChB,MAAA,EAAQA,SAAAA,CAAE,QAAA;AAAA,UACRA,SAAAA,CAAE,KAAA;AAAA,YACAA,SAAAA,CAAE,KAAA,CAAM;AAAA,cACNA,SAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,cAChBA,SAAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,cACjBA,SAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,cAClBA,SAAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,cACnBA,SAAAA,CAAE,OAAA,CAAQ,SAAS;AAAA,YACrB,CAAC;AAAA,UACH;AAAA,QACF,CAAA;AAAA,QACA,UAAA,EAAYA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,KAAA,EAAOA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC5B,WAAA,EAAaA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,OAAA,CAAQ,CAAC;AAAA,MACrC,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,IAAA;AAAA,IACC,QAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,YAAA,CAAa,MAAA,CAAO;AAAA,UAC/B,GAAI,IAAA;AAAA,UACJ,QAAA,EAAU,OAAA;AAAA,UACV,aAAA,EAAe;AAAA,QACjB,CAAC,CAAA;AAAA,MACH,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,qBAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMA,SAAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAUA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC/B,KAAA,EAAOA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAChB,MAAA,EAAQA,SAAAA,CAAE,QAAA;AAAA,UACRA,SAAAA,CAAE,KAAA;AAAA,YACAA,SAAAA,CAAE,KAAA,CAAM;AAAA,cACNA,SAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,cAChBA,SAAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA,cACjBA,SAAAA,CAAE,OAAA,CAAQ,QAAQ,CAAA;AAAA,cAClBA,SAAAA,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,cACnBA,SAAAA,CAAE,OAAA,CAAQ,SAAS;AAAA,YACrB,CAAC;AAAA,UACH;AAAA,QACF,CAAA;AAAA,QACA,UAAA,EAAYA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,KAAA,EAAOA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,IAAA;AAAA,IACC,WAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,YAAA,CAAa,MAAA,CAAO;AAAA,UAC/B,GAAI,IAAA;AAAA,UACJ,QAAA,EAAU,UAAA;AAAA,UACV,aAAA,EAAe;AAAA,QACjB,CAAC,CAAA;AAAA,MACH,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,wBAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMA,SAAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAUA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAA;AAAA,QAC/B,KAAA,EAAOA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAChB,MAAA,EAAQA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,KAAA,CAAMA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QACtC,UAAA,EAAYA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,QAC7C,KAAA,EAAOA,SAAAA,CAAE,QAAA,CAASA,SAAAA,CAAE,MAAA,CAAO,CAAC;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF,CAAA;AACJ;AJkIA;AACA;AKxSA;AAQO,SAAS,kBAAA,CACd,YAAA,EACA,MAAA,EACA;AAEA,EAAA,MAAM,WAAA,EAAa,MAAA,CAAO,WAAA,EACtB,IAAI,6CAAA,CAAuB;AAAA,IACzB,MAAA,EAAQ,MAAA,CAAO,UAAA,CAAW,MAAA;AAAA,IAC1B,OAAA,EAAS,MAAA,CAAO,UAAA,CAAW,OAAA;AAAA,IAC3B,KAAA,EAAO,MAAA,CAAO,UAAA,CAAW;AAAA,EAC3B,CAAC,EAAA,EACD,IAAA;AAEJ,EAAA,OAAO,IAAID,mBAAAA,CAAO,EAAE,MAAA,EAAQ,qBAAqB,CAAC,CAAA,CAE/C,IAAA;AAAA,IACC,MAAA;AAAA,IACA,CAAC,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACjB,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,MAAA,CAAO,qBAAA,CAAsB,IAA4B,CAAA;AACtE,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO,EAAE,EAAA,EAAI,KAAK,CAAA;AAAA,MACpB,EAAA,MAAA,CAAS,KAAA,EAAO;AACd,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,mCAAA;AAAA,UACP,OAAA,EAAS,MAAA,WAAiB,MAAA,EAAQ,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,KAAK;AAAA,QAChE,CAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAMC,SAAAA,CAAE,MAAA,CAAO;AAAA,QACb,QAAA,EAAUA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QACnB,UAAA,EAAYA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QACrB,OAAA,EAASA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAClB,OAAA,EAASA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAClB,IAAA,EAAMA,SAAAA,CAAE,KAAA,CAAM;AAAA,UACZA,SAAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA,UAChBA,SAAAA,CAAE,OAAA,CAAQ,WAAW,CAAA;AAAA,UACrBA,SAAAA,CAAE,OAAA,CAAQ,QAAQ;AAAA,QACpB,CAAC,CAAA;AAAA,QACD,OAAA,EAASA,SAAAA,CAAE,MAAA,CAAO,CAAA;AAAA,QAClB,SAAA,EAAWA,SAAAA,CAAE,MAAA,CAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF,CAAA,CAGC,IAAA;AAAA,IACC,YAAA;AAAA,IACA,MAAA,CAAO,EAAE,IAAA,EAAM,IAAI,CAAA,EAAA,GAAM;AACvB,MAAA,GAAA,CAAI,CAAC,UAAA,EAAY;AACf,QAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,QAAA,OAAO,EAAE,KAAA,EAAO,gEAA2D,CAAA;AAAA,MAC7E;AAEA,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,OAAA,EAAS,OAAA,EAAS,SAAS,EAAA,EAAI,IAAA;AAE7D,QAAA,MAAM,QAAA,EAAU,MAAM,UAAA,CAAW,SAAA,CAAU,QAAQ,CAAA;AACnD,QAAA,GAAA,CAAI,CAAC,OAAA,EAAS;AACZ,UAAA,GAAA,CAAI,OAAA,EAAS,GAAA;AACb,UAAA,OAAO,EAAE,KAAA,EAAO,6BAA6B,CAAA;AAAA,QAC/C;AAEA,QAAA,MAAM,UAAA,EAAiC;AAAA,UACrC,QAAA;AAAA,UACA,KAAA,EAAO,SAAA;AAAA,UACP,UAAA,EAAY,OAAA;AAAA,UACZ,OAAA,EAAS,OAAA;AAAA,UACT,IAAA,EAAM,CAAC,sBAAA,EAAwB,OAAA,EAAS,CAAA,QAAA,EAAW,UAAU,CAAA,CAAA;AACrD,UAAA;AACI,UAAA;AACM,UAAA;AACpB,QAAA;AAEwD,QAAA;AAEpB,QAAA;AAChB,UAAA;AAClB,UAAA;AAC2B,UAAA;AACJ,UAAA;AACzB,QAAA;AAEa,QAAA;AACN,QAAA;AACO,MAAA;AACD,QAAA;AACN,QAAA;AACE,UAAA;AACuD,UAAA;AAChE,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACiB,MAAA;AACM,QAAA;AACE,QAAA;AACH,QAAA;AACA,QAAA;AACN,QAAA;AACD,UAAA;AACO,YAAA;AACI,cAAA;AACK,cAAA;AACH,cAAA;AACnB,YAAA;AACiB,YAAA;AACE,YAAA;AACrB,UAAA;AACH,QAAA;AAC6B,QAAA;AAC9B,MAAA;AACH,IAAA;AACF,EAAA;AACJ;ALiRwE;AACA;AM9Y9C;AAKsC;AAGtC,EAAA;AACG,IAAA;AACR,MAAA;AACG,MAAA;AAClB,IAAA;AAEI,IAAA;AACsC,MAAA;AAC/B,QAAA;AACD,QAAA;AAC4C,QAAA;AACpD,MAAA;AAC0C,MAAA;AAC5B,IAAA;AACD,MAAA;AACN,MAAA;AACE,QAAA;AACuD,QAAA;AAChE,MAAA;AACF,IAAA;AAI4C,EAAA;AACrB,IAAA;AACR,MAAA;AACG,MAAA;AAClB,IAAA;AAEI,IAAA;AACoC,MAAA;AAC7B,QAAA;AACA,QAAA;AACT,MAAA;AACoB,MAAA;AACL,QAAA;AACsB,QAAA;AACrC,MAAA;AACO,MAAA;AACO,IAAA;AACD,MAAA;AACN,MAAA;AACE,QAAA;AACuD,QAAA;AAChE,MAAA;AACF,IAAA;AAI2D,EAAA;AACpC,IAAA;AACR,MAAA;AACG,MAAA;AAClB,IAAA;AAEI,IAAA;AAC8D,MAAA;AACzB,MAAA;AAC9B,QAAA;AACP,QAAA;AACF,MAAA;AACwC,MAAA;AAC1B,IAAA;AACD,MAAA;AACN,MAAA;AACE,QAAA;AACuD,QAAA;AAChE,MAAA;AACF,IAAA;AAID,EAAA;AACC,IAAA;AACyB,IAAA;AACY,MAAA;AACpB,QAAA;AACG,QAAA;AAClB,MAAA;AAEI,MAAA;AAC6D,QAAA;AACxD,QAAA;AACO,MAAA;AACD,QAAA;AACN,QAAA;AACE,UAAA;AACuD,UAAA;AAChE,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACiB,MAAA;AACE,QAAA;AAChB,MAAA;AACH,IAAA;AACF,EAAA;AACJ;AN6XwE;AACA;AOve9C;AACX;AACE;AAO8C;AAC3B,EAAA;AACM,IAAA;AACxC,EAAA;AAKkB,EAAA;AAIV,IAAA;AAC+C,MAAA;AAC1C,MAAA;AACO,IAAA;AACD,MAAA;AACN,MAAA;AACE,QAAA;AACuD,QAAA;AAChE,MAAA;AACF,IAAA;AAID,EAAA;AACC,IAAA;AAC0B,IAAA;AAC4C,MAAA;AACnD,MAAA;AACF,QAAA;AACN,QAAA;AACE,UAAA;AACE,UAAA;AACX,QAAA;AACF,MAAA;AAE+D,MAAA;AAC3C,MAAA;AACL,QAAA;AACN,QAAA;AACE,UAAA;AACE,UAAA;AACX,QAAA;AACF,MAAA;AAG+C,MAAA;AAE3C,MAAA;AAC2C,QAAA;AAC3B,QAAA;AAEa,QAAA;AACD,UAAA;AAC2B,YAAA;AACrD,YAAA;AACF,UAAA;AACF,QAAA;AAE2D,QAAA;AAChB,UAAA;AAC1C,QAAA;AAEM,QAAA;AACE,UAAA;AACP,UAAA;AACA,UAAA;AACuB,UAAA;AACT,UAAA;AACA,UAAA;AAChB,QAAA;AACc,MAAA;AACD,QAAA;AACN,QAAA;AACE,UAAA;AACuD,UAAA;AAChE,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACkB,MAAA;AACL,QAAA;AACmD,UAAA;AAC5D,QAAA;AAC4B,QAAA;AAC7B,MAAA;AACH,IAAA;AAI4B,EAAA;AACsB,IAAA;AACd,IAAA;AAIrC,EAAA;AACC,IAAA;AACyB,IAAA;AACnB,MAAA;AAC2D,QAAA;AACtD,QAAA;AACO,MAAA;AACD,QAAA;AACN,QAAA;AACE,UAAA;AACuD,UAAA;AAChE,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACiB,MAAA;AACqB,QAAA;AACf,QAAA;AACY,QAAA;AAChC,MAAA;AACH,IAAA;AAIkD,EAAA;AACrC,IAAA;AACyB,IAAA;AACvC,EAAA;AACL;AAIwE;AACnD,EAAA;AACmD,EAAA;AAC/D,EAAA;AACT;AAEmE;AAC9C,EAAA;AACqB,EAAA;AACY,EAAA;AAC7C,EAAA;AACT;AAE4D;AACzC,EAAA;AACsD,EAAA;AAC1D,EAAA;AAEA,EAAA;AACmC,IAAA;AACrC,MAAA;AACP,MAAA;AACO,MAAA;AACR,IAAA;AAEoB,IAAA;AACO,IAAA;AAClB,IAAA;AACZ,EAAA;AAEO,EAAA;AACT;AAYG;AAC6C,EAAA;AAC/B,EAAA;AACD,EAAA;AACY,EAAA;AACwC,EAAA;AAE3B,EAAA;AACjC,IAAA;AAC4B,MAAA;AACa,QAAA;AACzC,QAAA;AACA,QAAA;AACF,MAAA;AAEiD,MAAA;AACH,MAAA;AACA,MAAA;AAEd,MAAA;AACU,QAAA;AACtC,UAAA;AACA,UAAA;AACF,QAAA;AAEa,QAAA;AACG,UAAA;AACR,YAAA;AACyC,YAAA;AAC9C,UAAA;AACD,UAAA;AACA,UAAA;AACF,QAAA;AAEkD,QAAA;AACf,QAAA;AACa,QAAA;AAEf,QAAA;AAC/B,UAAA;AACA,UAAA;AACY,UAAA;AACkB,UAAA;AAC9B,UAAA;AACkB,UAAA;AACN,UAAA;AACM,UAAA;AACpB,QAAA;AAEI,QAAA;AACgD,UAAA;AACpC,UAAA;AACD,YAAA;AACkC,YAAA;AAC9C,UAAA;AACD,UAAA;AACc,QAAA;AACP,UAAA;AAC8C,YAAA;AACrD,UAAA;AACF,QAAA;AACF,MAAA;AACc,IAAA;AACP,MAAA;AACsD,QAAA;AAC7D,MAAA;AACF,IAAA;AACF,EAAA;AAE6C,EAAA;AAC/C;AAUoE;AACjC,EAAA;AACI,EAAA;AAChB,EAAA;AACF,EAAA;AACa,EAAA;AAEN,EAAA;AAC0B,IAAA;AAChC,IAAA;AACe,MAAA;AACf,QAAA;AACH,UAAA;AAC+B,UAAA;AACjC,UAAA;AACR,QAAA;AACH,MAAA;AACsC,MAAA;AACP,MAAA;AACb,MAAA;AACb,IAAA;AACmB,MAAA;AAC1B,IAAA;AACF,EAAA;AAE+B,EAAA;AACf,IAAA;AACH,MAAA;AAC+B,MAAA;AACjC,MAAA;AACR,IAAA;AACH,EAAA;AAEO,EAAA;AACT;AAEqF;AACrD,EAAA;AACC,EAAA;AAE2B,EAAA;AACxB,EAAA;AACF,EAAA;AACmC,EAAA;AAC5D,EAAA;AACT;AAE6E;AAC1B,EAAA;AAC1C,EAAA;AACT;AAEgE;AAC3B,EAAA;AACO,EAAA;AACb,IAAA;AAC7B,EAAA;AACwB,EAAA;AACqC,IAAA;AAC7D,EAAA;AACO,EAAA;AACT;AP8ZwE;AACA;AEptBa;AAKxDC,EAAAA;AAEmC,IAAA;AAGF,IAAA;AAE7B,IAAA;AAC2B,IAAA;AACvC,MAAA;AACgD,MAAA;AAC/D,IAAA;AAEgC,IAAA;AACC,IAAA;AAClB,MAAA;AACsB,MAAA;AACrC,IAAA;AAEQ,IAAA;AAIyB,EAAA;AAED,IAAA;AACiC,MAAA;AAClD,MAAA;AACmC,MAAA;AAClD,IAAA;AAGoC,IAAA;AACrB,MAAA;AACmC,MAAA;AAClD,IAAA;AAEsC,IAAA;AACvB,MAAA;AACmD,MAAA;AAClE,IAAA;AAEkC,IAAA;AACnB,MAAA;AACmC,MAAA;AAClD,IAAA;AAG2B,IAAA;AACmD,MAAA;AAC/D,MAAA;AACoC,MAAA;AACnD,IAAA;AAG0B,IAAA;AAEmC,MAAA;AAC9C,MAAA;AACa,MAAA;AAC5B,IAAA;AAGoE,IAAA;AACvB,IAAA;AAChC,IAAA;AAC2B,IAAA;AAMzC,EAAA;AAII,EAAA;AACT;AFqrBwE;AACA;AC7wBhB;AACZ,EAAA;AACS,EAAA;AAC3B,EAAA;AAEkB,EAAA;AAEP,EAAA;AACrC;AAIsB;AACR,EAAA;AAC+C,EAAA;AACA,EAAA;AAC/C,EAAA;AAE6C,EAAA;AAEnC,EAAA;AAC6C,EAAA;AAE7C,EAAA;AACgD,EAAA;AACJ,EAAA;AAErC,EAAA;AACc,IAAA;AAChB,IAAA;AACX,IAAA;AAChB,EAAA;AAE6B,EAAA;AACC,EAAA;AAChC;AAGiC;AAC3B,EAAA;AAE0E,IAAA;AAC5C,IAAA;AACmB,MAAA;AACnD,IAAA;AAEqB,IAAA;AACuC,MAAA;AAC5D,IAAA;AACO,IAAA;AACD,EAAA;AACC,IAAA;AACT,EAAA;AACF;AAEoB;AACM,EAAA;AACQ,IAAA;AAChB,IAAA;AACf,EAAA;AACH;ADgwBwE;AACA;AACA;AACA;AACA","file":"/private/tmp/openclaw-memory-publish/dist/chunk-NYZMAY73.cjs","sourcesContent":[null,"import { fileURLToPath } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { loadConfig, configSummary } from \"./config/index.js\";\nimport { StorageOrchestrator } from \"./storage/orchestrator.js\";\nimport { createApp } from \"./api/router.js\";\n\n// ── Server Entry Point ──────────────────────────────────────────────────\n\nexport async function createServer(configPath?: string) {\n const config = await loadConfig(configPath);\n const orchestrator = new StorageOrchestrator(config);\n await orchestrator.init();\n\n const app = createApp(orchestrator, config);\n\n return { app, orchestrator, config };\n}\n\n// ── Main ────────────────────────────────────────────────────────────────\n\nasync function main() {\n console.log(\"┌──────────────────────────────────────────┐\");\n console.log(\"│ openclaw-memory service v0.1.0 │\");\n console.log(\"│ Triple-Layer Memory System │\");\n console.log(\"└──────────────────────────────────────────┘\");\n\n const { app, orchestrator, config } = await createServer();\n\n console.log(\"[config]\");\n console.log(configSummary(config).split(\"\\n\").map((l) => ` ${l}`).join(\"\\n\"));\n\n app.listen(config.port);\n console.log(`[server] Listening on http://${config.host}:${config.port}`);\n console.log(`[server] Health check: http://localhost:${config.port}/api/health`);\n\n const shutdown = async () => {\n console.log(\"\\n[server] Shutting down...\");\n await orchestrator.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\n// Run if executed directly (works in both Bun and Node ESM)\nfunction isMainModule(): boolean {\n try {\n // Bun runtime\n const bun = (globalThis as typeof globalThis & { Bun?: { main?: string } }).Bun;\n if (typeof bun !== \"undefined\") {\n return bun.main === fileURLToPath(import.meta.url);\n }\n // Node.js\n if (process.argv[1]) {\n return resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));\n }\n return false;\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n main().catch((error) => {\n console.error(\"[fatal]\", error);\n process.exit(1);\n });\n}\n","import { Elysia } from \"elysia\";\nimport { cors } from \"@elysiajs/cors\";\nimport type { ResolvedConfig } from \"../config/index.js\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\nimport { AuthError, MemoryError, NotFoundError, ValidationError } from \"../core/errors.js\";\nimport { memoriesRoutes } from \"./memories.js\";\nimport { searchRoutes } from \"./search.js\";\nimport { conversationRoutes } from \"./conversations.js\";\nimport { entityRoutes } from \"./entities.js\";\nimport { adminRoutes } from \"./admin.js\";\n\n// ── App Router ──────────────────────────────────────────────────────────\n\nexport function createApp(orchestrator: StorageOrchestrator, config: ResolvedConfig) {\n const app = new Elysia()\n .use(cors())\n\n // ── Auth Middleware ────────────────────────────────────────────────\n .derive(({ headers, set, path }) => {\n // Skip auth for health check\n if (path === \"/api/health\" || path === \"/health\") return {};\n\n // Skip auth if disabled\n if (!config.auth.enabled || !config.auth.token) return {};\n\n const authHeader = headers.authorization;\n if (!authHeader || !authHeader.startsWith(\"Bearer \")) {\n set.status = 401;\n throw new AuthError(\"Missing or invalid Authorization header\");\n }\n\n const token = authHeader.slice(7);\n if (token !== config.auth.token) {\n set.status = 403;\n throw new AuthError(\"Invalid token\");\n }\n\n return {};\n })\n\n // ── Error Handler ─────────────────────────────────────────────────\n .onError(({ code, error, set }) => {\n // Handle AuthError\n if (error instanceof AuthError) {\n const status = error.message.includes(\"Invalid token\") ? 403 : 401;\n set.status = status;\n return { error: error.message, code: error.code };\n }\n\n // Handle other custom errors\n if (error instanceof NotFoundError) {\n set.status = 404;\n return { error: error.message, code: error.code };\n }\n\n if (error instanceof ValidationError) {\n set.status = 400;\n return { error: error.message, code: error.code, details: error.details };\n }\n\n if (error instanceof MemoryError) {\n set.status = 500;\n return { error: error.message, code: error.code };\n }\n\n // Elysia validation errors\n if (code === \"VALIDATION\") {\n const msg = error && \"message\" in error ? (error as Error).message : String(error);\n set.status = 400;\n return { error: \"Validation error\", details: msg };\n }\n\n // Elysia built-in not found errors\n if (code === \"NOT_FOUND\") {\n const msg =\n error && \"message\" in error ? (error as Error).message : \"Route not found\";\n set.status = 404;\n return { error: msg, code };\n }\n\n // Unknown errors\n const msg = error instanceof Error ? error.stack || error.message : String(error);\n console.error(`[api] Unhandled error: ${msg}`);\n set.status = 500;\n return { error: \"Internal server error\" };\n })\n\n // ── Mount Routes ──────────────────────────────────────────────────\n .use(memoriesRoutes(orchestrator))\n .use(searchRoutes(orchestrator))\n .use(conversationRoutes(orchestrator, config))\n .use(entityRoutes(orchestrator))\n .use(adminRoutes(orchestrator));\n\n return app;\n}\n","import { Elysia, t } from \"elysia\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\nimport type { CreateMemoryRequest, UpdateMemoryRequest, MemoryScope, MemorySource } from \"../core/types.js\";\n\n// ── Memory CRUD Routes ──────────────────────────────────────────────────\n\nexport function memoriesRoutes(orchestrator: StorageOrchestrator) {\n return new Elysia({ prefix: \"/api/memories\" })\n // POST /api/memories — Create a new memory\n .post(\n \"/\",\n async ({ body, set }) => {\n try {\n const result = await orchestrator.createMemory(body as CreateMemoryRequest);\n set.status = 201;\n return result;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to create memory\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.String(),\n scope: t.Union([\n t.Literal(\"user\"),\n t.Literal(\"agent\"),\n t.Literal(\"global\"),\n t.Literal(\"project\"),\n t.Literal(\"session\"),\n ]),\n subject_id: t.Optional(t.Nullable(t.String())),\n content: t.String(),\n tags: t.Optional(t.Array(t.String())),\n source: t.Optional(\n t.Union([\n t.Literal(\"explicit\"),\n t.Literal(\"derived\"),\n t.Literal(\"observation\"),\n t.Literal(\"conversation_summary\"),\n t.Literal(\"entity_extraction\"),\n t.Literal(\"daily_digest\"),\n t.Literal(\"migration\"),\n ])\n ),\n created_by: t.Optional(t.Nullable(t.String())),\n extract_entities: t.Optional(t.Boolean()),\n expires_at: t.Optional(t.Nullable(t.String())),\n }),\n }\n )\n\n // GET /api/memories/:id — Get a memory by ID\n .get(\"/:id\", ({ params, set }) => {\n const memory = orchestrator.sqlite.getMemory(params.id);\n if (!memory) {\n set.status = 404;\n return { error: \"Memory not found\" };\n }\n return memory;\n })\n\n // PUT /api/memories/:id — Update a memory\n .put(\n \"/:id\",\n async ({ params, body, set }) => {\n try {\n const result = await orchestrator.updateMemory(\n params.id,\n body as UpdateMemoryRequest\n );\n if (!result) {\n set.status = 404;\n return { error: \"Memory not found\" };\n }\n return result;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to update memory\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n content: t.Optional(t.String()),\n tags: t.Optional(t.Array(t.String())),\n scope: t.Optional(\n t.Union([\n t.Literal(\"user\"),\n t.Literal(\"agent\"),\n t.Literal(\"global\"),\n t.Literal(\"project\"),\n t.Literal(\"session\"),\n ])\n ),\n subject_id: t.Optional(t.Nullable(t.String())),\n expires_at: t.Optional(t.Nullable(t.String())),\n extract_entities: t.Optional(t.Boolean()),\n }),\n }\n )\n\n // DELETE /api/memories/:id — Delete a memory\n .delete(\"/:id\", async ({ params, set }) => {\n try {\n const deleted = await orchestrator.deleteMemory(params.id);\n if (!deleted) {\n set.status = 404;\n return { error: \"Memory not found\" };\n }\n return { deleted: true, id: params.id };\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to delete memory\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n })\n\n // GET /api/memories — List memories with filters\n .get(\"/\", ({ query }) => {\n const memories = orchestrator.sqlite.listMemories({\n agent_id: query.agent_id as string | undefined,\n scope: query.scope as MemoryScope | undefined,\n subject_id: query.subject_id as string | undefined,\n source: query.source as MemorySource | undefined,\n tags: query.tags as string | undefined,\n limit: query.limit ? parseInt(String(query.limit), 10) : undefined,\n offset: query.offset ? parseInt(String(query.offset), 10) : undefined,\n order: (query.order as \"asc\" | \"desc\") || \"desc\",\n });\n return { memories, count: memories.length };\n });\n}\n","import { Elysia, t } from \"elysia\";\nimport { SearchEngine } from \"../search/engine.js\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\nimport type { SearchRequest } from \"../core/types.js\";\n\n// ── Search Routes ───────────────────────────────────────────────────────\n\nexport function searchRoutes(orchestrator: StorageOrchestrator) {\n const searchEngine = new SearchEngine(orchestrator);\n\n return new Elysia({ prefix: \"/api/search\" })\n // POST /api/search — Smart search (auto-selects layers)\n .post(\n \"/\",\n async ({ body, set }) => {\n try {\n const req = body as SearchRequest;\n if (!req.agent_id) req.cross_agent = true;\n return await searchEngine.search(req);\n } catch (error) {\n set.status = 500;\n return {\n error: \"Search failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.Optional(t.String()),\n query: t.String(),\n scopes: t.Optional(\n t.Array(\n t.Union([\n t.Literal(\"user\"),\n t.Literal(\"agent\"),\n t.Literal(\"global\"),\n t.Literal(\"project\"),\n t.Literal(\"session\"),\n ])\n )\n ),\n subject_id: t.Optional(t.Nullable(t.String())),\n limit: t.Optional(t.Number()),\n include_graph: t.Optional(t.Boolean()),\n cross_agent: t.Optional(t.Boolean()),\n strategy: t.Optional(\n t.Union([\n t.Literal(\"auto\"),\n t.Literal(\"semantic\"),\n t.Literal(\"fulltext\"),\n t.Literal(\"graph\"),\n t.Literal(\"all\"),\n ])\n ),\n }),\n }\n )\n\n // POST /api/search/semantic — Force Qdrant semantic search\n .post(\n \"/semantic\",\n async ({ body, set }) => {\n try {\n return await searchEngine.search({\n ...(body as SearchRequest),\n strategy: \"semantic\",\n });\n } catch (error) {\n set.status = 500;\n return {\n error: \"Semantic search failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.Optional(t.String()),\n query: t.String(),\n scopes: t.Optional(\n t.Array(\n t.Union([\n t.Literal(\"user\"),\n t.Literal(\"agent\"),\n t.Literal(\"global\"),\n t.Literal(\"project\"),\n t.Literal(\"session\"),\n ])\n )\n ),\n subject_id: t.Optional(t.Nullable(t.String())),\n limit: t.Optional(t.Number()),\n cross_agent: t.Optional(t.Boolean()),\n }),\n }\n )\n\n // POST /api/search/graph — Force AGE graph traversal\n .post(\n \"/graph\",\n async ({ body, set }) => {\n try {\n return await searchEngine.search({\n ...(body as SearchRequest),\n strategy: \"graph\",\n include_graph: true,\n });\n } catch (error) {\n set.status = 500;\n return {\n error: \"Graph search failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.Optional(t.String()),\n query: t.String(),\n scopes: t.Optional(\n t.Array(\n t.Union([\n t.Literal(\"user\"),\n t.Literal(\"agent\"),\n t.Literal(\"global\"),\n t.Literal(\"project\"),\n t.Literal(\"session\"),\n ])\n )\n ),\n subject_id: t.Optional(t.Nullable(t.String())),\n limit: t.Optional(t.Number()),\n }),\n }\n )\n\n // POST /api/search/fulltext — Force SQLite FTS search\n .post(\n \"/fulltext\",\n async ({ body, set }) => {\n try {\n return await searchEngine.search({\n ...(body as SearchRequest),\n strategy: \"fulltext\",\n include_graph: false,\n });\n } catch (error) {\n set.status = 500;\n return {\n error: \"Fulltext search failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.Optional(t.String()),\n query: t.String(),\n scopes: t.Optional(t.Array(t.String())),\n subject_id: t.Optional(t.Nullable(t.String())),\n limit: t.Optional(t.Number()),\n }),\n }\n );\n}\n","import { Elysia, t } from \"elysia\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\nimport type { ResolvedConfig } from \"../config/index.js\";\nimport { ConversationSummarizer } from \"../extraction/summarizer.js\";\nimport type { ConversationLogEntry, CreateMemoryRequest, SummarizeResponse } from \"../core/types.js\";\n\n// ── Conversation Routes ─────────────────────────────────────────────────\n\nexport function conversationRoutes(\n orchestrator: StorageOrchestrator,\n config: ResolvedConfig\n) {\n // Summarizer is only available if extraction config is present\n const summarizer = config.extraction\n ? new ConversationSummarizer({\n apiKey: config.extraction.apiKey,\n baseUrl: config.extraction.baseUrl,\n model: config.extraction.model,\n })\n : null;\n\n return new Elysia({ prefix: \"/api/conversations\" })\n // POST /api/conversations/log — Append conversation entry\n .post(\n \"/log\",\n ({ body, set }) => {\n try {\n orchestrator.sqlite.appendConversationLog(body as ConversationLogEntry);\n set.status = 201;\n return { ok: true };\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to append conversation log\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.String(),\n session_id: t.String(),\n user_id: t.String(),\n channel: t.String(),\n role: t.Union([\n t.Literal(\"user\"),\n t.Literal(\"assistant\"),\n t.Literal(\"system\"),\n ]),\n content: t.String(),\n timestamp: t.String(),\n }),\n }\n )\n\n // POST /api/conversations/summarize — Summarize a session\n .post(\n \"/summarize\",\n async ({ body, set }) => {\n if (!summarizer) {\n set.status = 501;\n return { error: \"Summarization not available — extraction config required\" };\n }\n\n try {\n const { agent_id, session_id, user_id, channel, messages } = body;\n\n const summary = await summarizer.summarize(messages);\n if (!summary) {\n set.status = 422;\n return { error: \"Failed to generate summary\" };\n }\n\n const memoryReq: CreateMemoryRequest = {\n agent_id,\n scope: \"session\",\n subject_id: user_id,\n content: summary,\n tags: [\"conversation_summary\", channel, `session:${session_id}`],\n source: \"conversation_summary\",\n created_by: agent_id,\n extract_entities: true,\n };\n\n const result = await orchestrator.createMemory(memoryReq);\n\n const response: SummarizeResponse = {\n memory_id: result.id,\n summary,\n entities_extracted: result.entities,\n relationships_created: 0,\n };\n\n set.status = 201;\n return response;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Summarization failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n agent_id: t.String(),\n session_id: t.String(),\n user_id: t.String(),\n channel: t.String(),\n messages: t.Array(\n t.Object({\n role: t.Union([\n t.Literal(\"user\"),\n t.Literal(\"assistant\"),\n t.Literal(\"system\"),\n ]),\n content: t.String(),\n timestamp: t.String(),\n })\n ),\n reason: t.Optional(t.String()),\n }),\n }\n );\n}\n","import { Elysia, t } from \"elysia\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\n\n// ── Entity Routes ───────────────────────────────────────────────────────\n\nexport function entityRoutes(orchestrator: StorageOrchestrator) {\n return new Elysia({ prefix: \"/api/entities\" })\n // GET /api/entities/:type — List entities by type\n .get(\"/:type\", async ({ params, query, set }) => {\n if (!orchestrator.age) {\n set.status = 501;\n return { error: \"Graph layer not available — requires Full tier\" };\n }\n\n try {\n const entities = await orchestrator.age.listEntities(\n params.type,\n query.agent_id as string | undefined,\n query.limit ? parseInt(String(query.limit), 10) : 50\n );\n return { entities, count: entities.length };\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to list entities\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n })\n\n // GET /api/entities/:type/:id — Get entity with relationships\n .get(\"/:type/:id\", async ({ params, set }) => {\n if (!orchestrator.age) {\n set.status = 501;\n return { error: \"Graph layer not available — requires Full tier\" };\n }\n\n try {\n const result = await orchestrator.age.getEntityWithRelationships(\n params.type,\n params.id\n );\n if (!result.entity) {\n set.status = 404;\n return { error: \"Entity not found\" };\n }\n return result;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to get entity\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n })\n\n // GET /api/entities/:type/:id/related — Get related entities\n .get(\"/:type/:id/related\", async ({ params, query, set }) => {\n if (!orchestrator.age) {\n set.status = 501;\n return { error: \"Graph layer not available — requires Full tier\" };\n }\n\n try {\n const depth = query.depth ? parseInt(String(query.depth), 10) : 2;\n const related = await orchestrator.age.getRelatedEntities(\n params.id,\n depth\n );\n return { related, count: related.length };\n } catch (error) {\n set.status = 500;\n return {\n error: \"Failed to get related entities\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n })\n\n // POST /api/entities/extract — Manually trigger entity extraction\n .post(\n \"/extract\",\n async ({ body, set }) => {\n if (!orchestrator.entityExtractor) {\n set.status = 501;\n return { error: \"Entity extraction not available — requires extraction config\" };\n }\n\n try {\n const result = await orchestrator.entityExtractor.extract(body.text);\n return result;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Entity extraction failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n text: t.String(),\n }),\n }\n );\n}\n","import { Elysia, t } from \"elysia\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport type { StorageOrchestrator } from \"../storage/orchestrator.js\";\nimport type { CreateMemoryRequest, MigrateMarkdownRequest } from \"../core/types.js\";\nimport { SyncQueueProcessor } from \"../storage/sync-queue.js\";\n\n// ── Admin Routes ────────────────────────────────────────────────────────\n\nexport function adminRoutes(orchestrator: StorageOrchestrator) {\n const healthHandler = async () => {\n return await orchestrator.healthCheck();\n };\n\n return new Elysia()\n // GET /api/health and /health — Health checks\n .get(\"/api/health\", healthHandler)\n .get(\"/health\", healthHandler)\n\n // POST /api/sync/retry — Retry failed L2/L3 syncs\n .post(\"/api/sync/retry\", async ({ set }) => {\n try {\n const result = await orchestrator.retrySyncQueue();\n return result;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Sync retry failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n })\n\n // POST /api/admin/resync — Requeue all memories for L2/L3 sync\n .post(\n \"/api/admin/resync\",\n async ({ query, set }) => {\n const layerParam = parseLayerParam(query.layer as string | undefined);\n if (!layerParam) {\n set.status = 400;\n return {\n error: \"Invalid layer parameter\",\n details: \"Use ?layer=qdrant|age|both\",\n };\n }\n\n const batch = parseBatchParam(query.batch as string | undefined);\n if (batch === null) {\n set.status = 400;\n return {\n error: \"Invalid batch parameter\",\n details: \"Use a positive integer for ?batch=50\",\n };\n }\n\n const layers: Array<\"qdrant\" | \"age\"> =\n layerParam === \"both\" ? [\"qdrant\", \"age\"] : [layerParam];\n\n try {\n const memories = listAllMemories(orchestrator);\n let queuedItems = 0;\n\n for (const memory of memories) {\n for (const layer of layers) {\n orchestrator.sqlite.addToSyncQueue(memory.id, layer, \"upsert\");\n queuedItems++;\n }\n }\n\n const syncResults = await SyncQueueProcessor.withBatchSize(batch, async () => {\n return await orchestrator.retrySyncQueue();\n });\n\n return {\n layer: layerParam,\n layers,\n batch,\n memory_count: memories.length,\n queued_items: queuedItems,\n sync_results: syncResults,\n };\n } catch (error) {\n set.status = 500;\n return {\n error: \"Resync failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n query: t.Object({\n layer: t.Optional(\n t.Union([t.Literal(\"qdrant\"), t.Literal(\"age\"), t.Literal(\"both\")])\n ),\n batch: t.Optional(t.String()),\n }),\n }\n )\n\n // GET /api/sync/queue — View pending sync queue\n .get(\"/api/sync/queue\", () => {\n const items = orchestrator.sqlite.getSyncQueue(100);\n return { items, count: items.length };\n })\n\n // POST /api/admin/migrate-markdown — Migrate markdown files\n .post(\n \"/api/admin/migrate-markdown\",\n async ({ body, set }) => {\n try {\n const results = await migrateMarkdownFiles(orchestrator, body);\n return results;\n } catch (error) {\n set.status = 500;\n return {\n error: \"Migration failed\",\n details: error instanceof Error ? error.message : String(error),\n };\n }\n },\n {\n body: t.Object({\n markdown_paths: t.Array(t.String()),\n agent_id: t.String(),\n dry_run: t.Optional(t.Boolean()),\n }),\n }\n )\n\n // POST /api/admin/daily-digest — Trigger daily digest\n .post(\"/api/admin/daily-digest\", async ({ set }) => {\n set.status = 501;\n return { error: \"Not yet implemented\" };\n });\n}\n\ntype ResyncLayer = \"qdrant\" | \"age\" | \"both\";\n\nfunction parseLayerParam(layer: string | undefined): ResyncLayer | null {\n if (!layer) return \"both\";\n if (layer === \"qdrant\" || layer === \"age\" || layer === \"both\") return layer;\n return null;\n}\n\nfunction parseBatchParam(batch: string | undefined): number | null {\n if (!batch) return 50;\n const parsed = Number.parseInt(batch, 10);\n if (!Number.isFinite(parsed) || parsed <= 0) return null;\n return parsed;\n}\n\nfunction listAllMemories(orchestrator: StorageOrchestrator) {\n const pageSize = 5_000;\n const memories: ReturnType<typeof orchestrator.sqlite.listMemories> = [];\n let offset = 0;\n\n while (true) {\n const page = orchestrator.sqlite.listMemories({\n limit: pageSize,\n offset,\n order: \"asc\",\n });\n\n memories.push(...page);\n if (page.length < pageSize) break;\n offset += pageSize;\n }\n\n return memories;\n}\n\n// ── Markdown Migration ──────────────────────────────────────────────────\n\nasync function migrateMarkdownFiles(\n orchestrator: StorageOrchestrator,\n request: MigrateMarkdownRequest\n): Promise<{\n migrated: number;\n skipped: number;\n errors: string[];\n memories: Array<{ id: string; content_preview: string }>;\n}> {\n const { markdown_paths, agent_id, dry_run } = request;\n let migrated = 0;\n let skipped = 0;\n const errors: string[] = [];\n const memories: Array<{ id: string; content_preview: string }> = [];\n\n for (const filePath of markdown_paths) {\n try {\n if (!fs.existsSync(filePath)) {\n errors.push(`File not found: ${filePath}`);\n skipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const fileName = path.basename(filePath, \".md\");\n const sections = parseMarkdownSections(content);\n\n for (const section of sections) {\n if (section.content.trim().length < 10) {\n skipped++;\n continue;\n }\n\n if (dry_run) {\n memories.push({\n id: \"(dry-run)\",\n content_preview: section.content.slice(0, 100),\n });\n migrated++;\n continue;\n }\n\n const scope = inferScope(section.heading, fileName);\n const source = inferSource(fileName);\n const tags = inferTags(section.heading, fileName);\n\n const req: CreateMemoryRequest = {\n agent_id,\n scope,\n subject_id: null,\n content: section.content.trim(),\n tags,\n source: source || \"migration\",\n created_by: \"migration\",\n extract_entities: true,\n };\n\n try {\n const result = await orchestrator.createMemory(req);\n memories.push({\n id: result.id,\n content_preview: section.content.slice(0, 100),\n });\n migrated++;\n } catch (error) {\n errors.push(\n `Failed to migrate section \"${section.heading}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n } catch (error) {\n errors.push(\n `Failed to process ${filePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n return { migrated, skipped, errors, memories };\n}\n\n// ── Markdown Parsing Helpers ────────────────────────────────────────────\n\ninterface MarkdownSection {\n heading: string;\n content: string;\n level: number;\n}\n\nfunction parseMarkdownSections(markdown: string): MarkdownSection[] {\n const lines = markdown.split(\"\\n\");\n const sections: MarkdownSection[] = [];\n let currentHeading = \"root\";\n let currentLevel = 0;\n let currentContent: string[] = [];\n\n for (const line of lines) {\n const headingMatch = line.match(/^(#{1,3})\\s+(.+)/);\n if (headingMatch) {\n if (currentContent.length > 0) {\n sections.push({\n heading: currentHeading,\n content: currentContent.join(\"\\n\").trim(),\n level: currentLevel,\n });\n }\n currentHeading = headingMatch[2].trim();\n currentLevel = headingMatch[1].length;\n currentContent = [];\n } else {\n currentContent.push(line);\n }\n }\n\n if (currentContent.length > 0) {\n sections.push({\n heading: currentHeading,\n content: currentContent.join(\"\\n\").trim(),\n level: currentLevel,\n });\n }\n\n return sections;\n}\n\nfunction inferScope(heading: string, fileName: string): CreateMemoryRequest[\"scope\"] {\n const h = heading.toLowerCase();\n const f = fileName.toLowerCase();\n\n if (h.includes(\"about\") || h.includes(\"personal\")) return \"user\";\n if (h.includes(\"project\")) return \"project\";\n if (h.includes(\"agent\")) return \"agent\";\n if (h.includes(\"session\") || f.match(/^\\d{4}-\\d{2}-\\d{2}/)) return \"session\";\n return \"global\";\n}\n\nfunction inferSource(fileName: string): CreateMemoryRequest[\"source\"] | null {\n if (fileName.match(/^\\d{4}-\\d{2}-\\d{2}/)) return \"daily_digest\";\n return \"migration\";\n}\n\nfunction inferTags(heading: string, fileName: string): string[] {\n const tags: string[] = [\"migration\"];\n if (fileName.match(/^\\d{4}-\\d{2}-\\d{2}/)) {\n tags.push(\"daily\", fileName);\n }\n if (heading !== \"root\") {\n tags.push(heading.toLowerCase().replace(/[^a-z0-9]+/g, \"-\"));\n }\n return tags;\n}\n"]}
|
package/dist/cli/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var _chunkLA5OP5VIcjs = require('../chunk-LA5OP5VI.cjs');
|
|
8
8
|
|
|
9
9
|
// src/cli/index.ts
|
|
10
10
|
var _commander = require('commander');
|
|
@@ -39,7 +39,7 @@ function bullet(label, value, status) {
|
|
|
39
39
|
console.log(` ${dot} ${_picocolors2.default.bold(label)} ${value}`);
|
|
40
40
|
}
|
|
41
41
|
function getServerPid() {
|
|
42
|
-
const pidPath =
|
|
42
|
+
const pidPath = _chunkLA5OP5VIcjs.getPidFilePath.call(void 0, );
|
|
43
43
|
if (!_fs2.default.existsSync(pidPath)) return null;
|
|
44
44
|
try {
|
|
45
45
|
const pid = parseInt(_fs2.default.readFileSync(pidPath, "utf-8").trim(), 10);
|
|
@@ -113,8 +113,8 @@ function initCommand() {
|
|
|
113
113
|
return new (0, _commander.Command)("init").description("Interactive setup wizard").option("--tier <tier>", "Tier: lite, standard, or full").option("--non-interactive", "Skip prompts, use defaults + flags").action(async (opts) => {
|
|
114
114
|
header("Setup Wizard");
|
|
115
115
|
const tier = opts.tier || "lite";
|
|
116
|
-
const dataDir =
|
|
117
|
-
const sqlitePath =
|
|
116
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
117
|
+
const sqlitePath = _chunkLA5OP5VIcjs.getDefaultSqlitePath.call(void 0, );
|
|
118
118
|
_fs2.default.mkdirSync(dataDir, { recursive: true });
|
|
119
119
|
info(`Data directory: ${dataDir}`);
|
|
120
120
|
let qdrantAvailable = false;
|
|
@@ -184,7 +184,7 @@ function initCommand() {
|
|
|
184
184
|
}
|
|
185
185
|
function generateConfig(tier, sqlitePath) {
|
|
186
186
|
const lines = [
|
|
187
|
-
`import { defineConfig } from 'openclaw-memory';`,
|
|
187
|
+
`import { defineConfig } from '@poprobertdaniel/openclaw-memory';`,
|
|
188
188
|
``,
|
|
189
189
|
`export default defineConfig({`,
|
|
190
190
|
` tier: '${tier}',`,
|
|
@@ -208,7 +208,7 @@ function generateConfig(tier, sqlitePath) {
|
|
|
208
208
|
lines.push(` },`);
|
|
209
209
|
lines.push(` extraction: {`);
|
|
210
210
|
lines.push(` apiKey: process.env.OPENAI_API_KEY || '',`);
|
|
211
|
-
lines.push(` model: 'gpt-
|
|
211
|
+
lines.push(` model: 'gpt-5-nano',`);
|
|
212
212
|
lines.push(` enabled: true,`);
|
|
213
213
|
lines.push(` },`);
|
|
214
214
|
}
|
|
@@ -251,7 +251,7 @@ function generateEnvExample(tier) {
|
|
|
251
251
|
lines.push(`# EMBEDDING_BASE_URL=https://api.openai.com/v1`);
|
|
252
252
|
lines.push(``);
|
|
253
253
|
lines.push(`# Entity extraction`);
|
|
254
|
-
lines.push(`# EXTRACTION_MODEL=gpt-
|
|
254
|
+
lines.push(`# EXTRACTION_MODEL=gpt-5-nano`);
|
|
255
255
|
lines.push(``);
|
|
256
256
|
}
|
|
257
257
|
if (tier === "full") {
|
|
@@ -290,12 +290,12 @@ async function startForeground(opts) {
|
|
|
290
290
|
const port = opts.port ? parseInt(opts.port, 10) : config.port;
|
|
291
291
|
app.listen(port);
|
|
292
292
|
console.log(`[server] Listening on http://0.0.0.0:${port}`);
|
|
293
|
-
const dataDir =
|
|
293
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
294
294
|
_fs2.default.mkdirSync(dataDir, { recursive: true });
|
|
295
|
-
_fs2.default.writeFileSync(
|
|
295
|
+
_fs2.default.writeFileSync(_chunkLA5OP5VIcjs.getPidFilePath.call(void 0, ), String(process.pid), "utf-8");
|
|
296
296
|
const cleanup = () => {
|
|
297
297
|
try {
|
|
298
|
-
_fs2.default.unlinkSync(
|
|
298
|
+
_fs2.default.unlinkSync(_chunkLA5OP5VIcjs.getPidFilePath.call(void 0, ));
|
|
299
299
|
} catch (e6) {
|
|
300
300
|
}
|
|
301
301
|
process.exit(0);
|
|
@@ -305,7 +305,7 @@ async function startForeground(opts) {
|
|
|
305
305
|
}
|
|
306
306
|
async function startBackground(opts) {
|
|
307
307
|
header("Starting Server (background)");
|
|
308
|
-
const dataDir =
|
|
308
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
309
309
|
_fs2.default.mkdirSync(dataDir, { recursive: true });
|
|
310
310
|
const args = ["run", "src/server.ts"];
|
|
311
311
|
const env = { ...process.env };
|
|
@@ -324,9 +324,9 @@ async function startBackground(opts) {
|
|
|
324
324
|
});
|
|
325
325
|
child.unref();
|
|
326
326
|
if (child.pid) {
|
|
327
|
-
_fs2.default.writeFileSync(
|
|
327
|
+
_fs2.default.writeFileSync(_chunkLA5OP5VIcjs.getPidFilePath.call(void 0, ), String(child.pid), "utf-8");
|
|
328
328
|
success(`Server started in background (PID: ${child.pid})`);
|
|
329
|
-
info(`PID file: ${
|
|
329
|
+
info(`PID file: ${_chunkLA5OP5VIcjs.getPidFilePath.call(void 0, )}`);
|
|
330
330
|
info(`Stop with: openclaw-memory stop`);
|
|
331
331
|
} else {
|
|
332
332
|
error("Failed to start server");
|
|
@@ -340,7 +340,7 @@ async function startBackground(opts) {
|
|
|
340
340
|
function stopCommand() {
|
|
341
341
|
return new (0, _commander.Command)("stop").description("Stop the running server").action(async () => {
|
|
342
342
|
header("Stopping Server");
|
|
343
|
-
const pidPath =
|
|
343
|
+
const pidPath = _chunkLA5OP5VIcjs.getPidFilePath.call(void 0, );
|
|
344
344
|
if (!_fs2.default.existsSync(pidPath)) {
|
|
345
345
|
warn("No PID file found \u2014 server may not be running");
|
|
346
346
|
return;
|
|
@@ -393,7 +393,7 @@ function statusCommand() {
|
|
|
393
393
|
header("Status");
|
|
394
394
|
let config;
|
|
395
395
|
try {
|
|
396
|
-
config = await
|
|
396
|
+
config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, opts.config);
|
|
397
397
|
} catch (e10) {
|
|
398
398
|
config = null;
|
|
399
399
|
}
|
|
@@ -503,7 +503,7 @@ function storeCommand() {
|
|
|
503
503
|
console.error("Error: content is required (pass as argument or pipe via stdin)");
|
|
504
504
|
process.exit(1);
|
|
505
505
|
}
|
|
506
|
-
const config = await
|
|
506
|
+
const config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, opts.config);
|
|
507
507
|
const baseUrl = getBaseUrl(config.port);
|
|
508
508
|
const serverUp = await isServerRunning(baseUrl);
|
|
509
509
|
const body = {
|
|
@@ -519,7 +519,7 @@ function storeCommand() {
|
|
|
519
519
|
const result = await apiPost(baseUrl, "/api/memories", body, config.auth.token);
|
|
520
520
|
output(result, opts.format);
|
|
521
521
|
} else {
|
|
522
|
-
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-
|
|
522
|
+
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-B2BAEKR2.cjs")));
|
|
523
523
|
const service = new MemoryService();
|
|
524
524
|
await service.init();
|
|
525
525
|
try {
|
|
@@ -545,7 +545,7 @@ function storeCommand() {
|
|
|
545
545
|
function searchCommand() {
|
|
546
546
|
const cmd = new (0, _commander.Command)("search").description("Search memories");
|
|
547
547
|
cmd.argument("<query>", "Search query").requiredOption("--agent <id>", "Agent ID").option("--limit <n>", "Max results", "10").option("--strategy <s>", "Search strategy (auto, semantic, fulltext, graph, all)", "auto").option("--scopes <scopes>", "Comma-separated scopes").option("--subject <id>", "Subject ID filter").option("--cross-agent", "Search across all agents").option("--no-graph", "Exclude graph results").option("--recall", "Format output for LLM context injection").option("--format <fmt>", "Output format (json, text)", "json").option("--config <path>", "Path to config file").action(async (query, opts) => {
|
|
548
|
-
const config = await
|
|
548
|
+
const config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, opts.config);
|
|
549
549
|
const baseUrl = getBaseUrl(config.port);
|
|
550
550
|
const serverUp = await isServerRunning(baseUrl);
|
|
551
551
|
const body = {
|
|
@@ -562,7 +562,7 @@ function searchCommand() {
|
|
|
562
562
|
if (serverUp) {
|
|
563
563
|
result = await apiPost(baseUrl, "/api/search", body, config.auth.token);
|
|
564
564
|
} else {
|
|
565
|
-
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-
|
|
565
|
+
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-B2BAEKR2.cjs")));
|
|
566
566
|
const service = new MemoryService();
|
|
567
567
|
await service.init();
|
|
568
568
|
try {
|
|
@@ -602,7 +602,7 @@ function searchCommand() {
|
|
|
602
602
|
|
|
603
603
|
function migrateCommand() {
|
|
604
604
|
return new (0, _commander.Command)("migrate").description("Import memories from markdown files").requiredOption("--paths <paths>", "Comma-separated file paths").requiredOption("--agent <id>", "Agent ID").option("--dry-run", "Preview without writing").option("--format <fmt>", "Output format (json, text)", "json").option("--config <path>", "Path to config file").action(async (opts) => {
|
|
605
|
-
const config = await
|
|
605
|
+
const config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, opts.config);
|
|
606
606
|
const baseUrl = getBaseUrl(config.port);
|
|
607
607
|
const serverUp = await isServerRunning(baseUrl);
|
|
608
608
|
const paths = opts.paths.split(",").map((p) => p.trim());
|
|
@@ -618,7 +618,7 @@ function migrateCommand() {
|
|
|
618
618
|
if (serverUp) {
|
|
619
619
|
result = await apiPost(baseUrl, "/api/admin/migrate-markdown", body, config.auth.token);
|
|
620
620
|
} else {
|
|
621
|
-
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-
|
|
621
|
+
const { MemoryService } = await Promise.resolve().then(() => _interopRequireWildcard(require("../memory-service-B2BAEKR2.cjs")));
|
|
622
622
|
const service = new MemoryService();
|
|
623
623
|
await service.init();
|
|
624
624
|
try {
|
|
@@ -662,7 +662,7 @@ function infraCommand() {
|
|
|
662
662
|
let tier = opts.tier;
|
|
663
663
|
if (!tier) {
|
|
664
664
|
try {
|
|
665
|
-
const config = await
|
|
665
|
+
const config = await _chunkLA5OP5VIcjs.loadConfig.call(void 0, );
|
|
666
666
|
tier = config.tier;
|
|
667
667
|
} catch (e13) {
|
|
668
668
|
tier = "standard";
|
|
@@ -679,7 +679,7 @@ function infraCommand() {
|
|
|
679
679
|
error("Expected in ./docker/ or ./templates/ directory");
|
|
680
680
|
process.exit(1);
|
|
681
681
|
}
|
|
682
|
-
const dataDir =
|
|
682
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
683
683
|
_fs2.default.mkdirSync(dataDir, { recursive: true });
|
|
684
684
|
const targetPath = _path2.default.join(dataDir, "docker-compose.yml");
|
|
685
685
|
_fs2.default.copyFileSync(templatePath, targetPath);
|
|
@@ -698,7 +698,7 @@ function infraCommand() {
|
|
|
698
698
|
});
|
|
699
699
|
infra.command("down").description("Stop Docker containers").action(async () => {
|
|
700
700
|
header("Infrastructure Down");
|
|
701
|
-
const dataDir =
|
|
701
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
702
702
|
const composePath = _path2.default.join(dataDir, "docker-compose.yml");
|
|
703
703
|
if (!_fs2.default.existsSync(composePath)) {
|
|
704
704
|
warn("No docker-compose.yml found in data directory");
|
|
@@ -717,7 +717,7 @@ function infraCommand() {
|
|
|
717
717
|
});
|
|
718
718
|
infra.command("status").description("Show Docker container status").action(async () => {
|
|
719
719
|
header("Infrastructure Status");
|
|
720
|
-
const dataDir =
|
|
720
|
+
const dataDir = _chunkLA5OP5VIcjs.getDataDir.call(void 0, );
|
|
721
721
|
const composePath = _path2.default.join(dataDir, "docker-compose.yml");
|
|
722
722
|
if (!_fs2.default.existsSync(composePath)) {
|
|
723
723
|
info("No docker-compose.yml found \u2014 infrastructure not set up");
|