openclaw-cloudflare-vectorize-memory 0.1.0 → 0.1.1
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 +14 -0
- package/dist/cli.js +119 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloudflare-api.js +24 -0
- package/dist/cloudflare-api.js.map +1 -0
- package/dist/companion-store.js +43 -0
- package/dist/companion-store.js.map +1 -0
- package/dist/config.js +290 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.js +15 -0
- package/dist/constants.js.map +1 -0
- package/dist/doctor.js +40 -0
- package/dist/doctor.js.map +1 -0
- package/dist/embeddings-client.js +28 -0
- package/dist/embeddings-client.js.map +1 -0
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.js +30 -1403
- package/dist/index.js.map +1 -1
- package/dist/migration.js +282 -0
- package/dist/migration.js.map +1 -0
- package/dist/namespace.js +18 -0
- package/dist/namespace.js.map +1 -0
- package/dist/prompt.js +9 -0
- package/dist/prompt.js.map +1 -0
- package/dist/public-artifacts.js +31 -0
- package/dist/public-artifacts.js.map +1 -0
- package/dist/record-mapper.js +98 -0
- package/dist/record-mapper.js.map +1 -0
- package/dist/runtime.js +39 -0
- package/dist/runtime.js.map +1 -0
- package/dist/search-manager.js +74 -0
- package/dist/search-manager.js.map +1 -0
- package/dist/service-factory.js +10 -0
- package/dist/service-factory.js.map +1 -0
- package/dist/service.js +114 -0
- package/dist/service.js.map +1 -0
- package/dist/tools.js +158 -0
- package/dist/tools.js.map +1 -0
- package/dist/vectorize-client.js +68 -0
- package/dist/vectorize-client.js.map +1 -0
- package/hooks/cloudflare-memory-bootstrap/BOOTSTRAP.md +7 -0
- package/hooks/cloudflare-memory-bootstrap/HOOK.md +10 -0
- package/hooks/cloudflare-memory-bootstrap/handler.d.ts +3 -0
- package/hooks/cloudflare-memory-bootstrap/handler.js +17 -0
- package/package.json +5 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","names":[],"sources":["../src/migration.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\r\nimport { glob, readFile, stat } from \"node:fs/promises\";\r\nimport { basename, extname, isAbsolute, relative, resolve } from \"node:path\";\r\nimport { listMemoryFiles } from \"openclaw/plugin-sdk/memory-core\";\r\nimport { sanitizeNamespace } from \"./namespace.js\";\r\nimport type { CloudflareMemoryService } from \"./service.js\";\r\nimport type {\r\n\tDoctorReport,\r\n\tMetadataValue,\r\n\tMigrationDuplicateStrategy,\r\n\tMigrationNamespaceStrategy,\r\n\tMigrationResult,\r\n\tMigrationRunOptions,\r\n\tMigrationSourceMode,\r\n\tMigrationSummary,\r\n} from \"./types.js\";\r\n\r\ntype DiscoveredMigrationFile = {\r\n\tabsolutePath: string;\r\n\trelativePath: string;\r\n};\r\n\r\ntype ParsedMigrationRecord = {\r\n\tinput: {\r\n\t\tid: string;\r\n\t\ttext: string;\r\n\t\ttitle?: string;\r\n\t\tmetadata: Record<string, MetadataValue>;\r\n\t\tnamespace?: string;\r\n\t\tsource?: string;\r\n\t};\r\n\tsourcePath: string;\r\n\trelativePath: string;\r\n};\r\n\r\nconst MARKDOWN_EXTENSIONS = new Set([\".md\", \".markdown\"]);\r\nconst RESERVED_FRONTMATTER_FIELDS = new Set([\"id\", \"namespace\", \"source\", \"title\"]);\r\n\r\nfunction normalizePathForMetadata(value: string): string {\r\n\treturn value.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\r\n}\r\n\r\nfunction normalizeRelativePath(value: string): string {\r\n\tconst normalized = normalizePathForMetadata(value).replace(/^\\/+/, \"\");\r\n\treturn normalized || basename(value);\r\n}\r\n\r\nfunction isMarkdownFile(value: string): boolean {\r\n\treturn MARKDOWN_EXTENSIONS.has(extname(value).toLowerCase());\r\n}\r\n\r\nfunction hasGlobMagic(value: string): boolean {\r\n\treturn /[*?[\\]{}]/.test(value);\r\n}\r\n\r\nfunction shouldIgnoreDiscoveredFile(value: string): boolean {\r\n\tconst normalized = normalizePathForMetadata(value).toLowerCase();\r\n\treturn normalized.includes(\"/node_modules/\") || normalized.includes(\"/.git/\");\r\n}\r\n\r\nasync function statIfExists(path: string) {\r\n\ttry {\r\n\t\treturn await stat(path);\r\n\t} catch {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\nasync function collectDirectoryMarkdownFiles(directory: string): Promise<string[]> {\r\n\tconst matches: string[] = [];\r\n\tfor await (const match of glob(\"**/*.{md,markdown}\", { cwd: directory })) {\r\n\t\tconst absolutePath = resolve(directory, match);\r\n\t\tif (!shouldIgnoreDiscoveredFile(absolutePath)) {\r\n\t\t\tmatches.push(absolutePath);\r\n\t\t}\r\n\t}\r\n\treturn matches;\r\n}\r\n\r\nasync function collectGlobMatches(pattern: string, workspaceDir: string): Promise<string[]> {\r\n\tconst matches: string[] = [];\r\n\tconst normalizedPattern = normalizePathForMetadata(pattern);\r\n\tconst iterator = isAbsolute(pattern) ? glob(normalizedPattern) : glob(normalizedPattern, { cwd: workspaceDir });\r\n\tfor await (const match of iterator) {\r\n\t\tconst absolutePath = isAbsolute(match) ? match : resolve(workspaceDir, match);\r\n\t\tif (shouldIgnoreDiscoveredFile(absolutePath) || !isMarkdownFile(absolutePath)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst fileStats = await statIfExists(absolutePath);\r\n\t\tif (fileStats?.isFile()) {\r\n\t\t\tmatches.push(absolutePath);\r\n\t\t}\r\n\t}\r\n\treturn matches;\r\n}\r\n\r\nexport async function discoverMigrationFiles(params: {\r\n\tworkspaceDir: string;\r\n\tsourceMode: MigrationSourceMode;\r\n\tsourcePaths?: string[];\r\n}): Promise<DiscoveredMigrationFile[]> {\r\n\tconst workspaceDir = resolve(params.workspaceDir);\r\n\tconst discovered = new Map<string, DiscoveredMigrationFile>();\r\n\r\n\tif (params.sourceMode === \"default-provider\") {\r\n\t\tfor (const relPath of await listMemoryFiles(workspaceDir)) {\r\n\t\t\tconst relativePath = normalizeRelativePath(relPath);\r\n\t\t\tconst absolutePath = resolve(workspaceDir, relativePath);\r\n\t\t\tif (shouldIgnoreDiscoveredFile(absolutePath) || !isMarkdownFile(relativePath)) {\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tconst fileStats = await statIfExists(absolutePath);\r\n\t\t\tif (fileStats?.isFile()) {\r\n\t\t\t\tdiscovered.set(absolutePath.toLowerCase(), {\r\n\t\t\t\t\tabsolutePath,\r\n\t\t\t\t\trelativePath,\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor (const input of params.sourcePaths ?? []) {\r\n\t\tconst absoluteInput = resolve(workspaceDir, input);\r\n\t\tconst fileStats = await statIfExists(absoluteInput);\r\n\t\tlet matches: string[] = [];\r\n\t\tif (fileStats?.isDirectory()) {\r\n\t\t\tmatches = await collectDirectoryMarkdownFiles(absoluteInput);\r\n\t\t} else if (fileStats?.isFile()) {\r\n\t\t\tmatches = isMarkdownFile(absoluteInput) ? [absoluteInput] : [];\r\n\t\t} else if (hasGlobMagic(input)) {\r\n\t\t\tmatches = await collectGlobMatches(input, workspaceDir);\r\n\t\t}\r\n\r\n\t\tfor (const match of matches) {\r\n\t\t\tconst relativePath = normalizeRelativePath(relative(workspaceDir, match));\r\n\t\t\tdiscovered.set(match.toLowerCase(), {\r\n\t\t\t\tabsolutePath: match,\r\n\t\t\t\trelativePath,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\treturn [...discovered.values()].sort((left, right) => left.relativePath.localeCompare(right.relativePath));\r\n}\r\n\r\nfunction parseFrontmatterValue(value: string): MetadataValue | undefined {\r\n\tconst trimmed = value.trim();\r\n\tif (!trimmed) {\r\n\t\treturn \"\";\r\n\t}\r\n\tif (/^\"(.*)\"$/.test(trimmed) || /^'(.*)'$/.test(trimmed)) {\r\n\t\treturn trimmed.slice(1, -1);\r\n\t}\r\n\tif (trimmed === \"true\") {\r\n\t\treturn true;\r\n\t}\r\n\tif (trimmed === \"false\") {\r\n\t\treturn false;\r\n\t}\r\n\tconst numeric = Number(trimmed);\r\n\tif (!Number.isNaN(numeric) && trimmed !== \"\") {\r\n\t\treturn numeric;\r\n\t}\r\n\tif (trimmed.startsWith(\"[\") || trimmed.startsWith(\"{\")) {\r\n\t\treturn undefined;\r\n\t}\r\n\treturn trimmed;\r\n}\r\n\r\nfunction parseFrontmatter(content: string): { body: string; attributes: Record<string, MetadataValue> } {\r\n\tconst normalized = content.replace(/\\r\\n/g, \"\\n\");\r\n\tif (!normalized.startsWith(\"---\\n\")) {\r\n\t\treturn { body: normalized, attributes: {} };\r\n\t}\r\n\r\n\tconst lines = normalized.split(\"\\n\");\r\n\tconst closingIndex = lines.findIndex((line, index) => index > 0 && line.trim() === \"---\");\r\n\tif (closingIndex === -1) {\r\n\t\treturn { body: normalized, attributes: {} };\r\n\t}\r\n\r\n\tconst attributes: Record<string, MetadataValue> = {};\r\n\tfor (const line of lines.slice(1, closingIndex)) {\r\n\t\tconst separatorIndex = line.indexOf(\":\");\r\n\t\tif (separatorIndex === -1) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst key = line.slice(0, separatorIndex).trim();\r\n\t\tif (!key) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst parsedValue = parseFrontmatterValue(line.slice(separatorIndex + 1));\r\n\t\tif (parsedValue !== undefined) {\r\n\t\t\tattributes[key] = parsedValue;\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tbody: lines.slice(closingIndex + 1).join(\"\\n\"),\r\n\t\tattributes,\r\n\t};\r\n}\r\n\r\nfunction extractHeadingTitleAndBody(content: string): { title?: string; text: string } {\r\n\tconst lines = content.split(\"\\n\");\r\n\tconst firstContentLine = lines.findIndex((line) => line.trim().length > 0);\r\n\tif (firstContentLine === -1) {\r\n\t\treturn { text: \"\" };\r\n\t}\r\n\r\n\tconst headingMatch = /^#\\s+(.+?)\\s*$/.exec(lines[firstContentLine]?.trim() ?? \"\");\r\n\tif (!headingMatch) {\r\n\t\treturn { text: content.trim() };\r\n\t}\r\n\r\n\tconst remainingLines = [...lines];\r\n\tremainingLines.splice(firstContentLine, 1);\r\n\tif ((remainingLines[firstContentLine] ?? \"\").trim() === \"\") {\r\n\t\tremainingLines.splice(firstContentLine, 1);\r\n\t}\r\n\tconst body = remainingLines.join(\"\\n\").trim();\r\n\treturn {\r\n\t\ttitle: headingMatch[1].trim(),\r\n\t\ttext: body || content.trim(),\r\n\t};\r\n}\r\n\r\nfunction buildStableLogicalId(relativePath: string): string {\r\n\tconst withoutExtension = relativePath.replace(/\\.(md|markdown)$/i, \"\");\r\n\tconst slug = withoutExtension\r\n\t\t.toLowerCase()\r\n\t\t.replace(/[^a-z0-9]+/g, \"-\")\r\n\t\t.replace(/-{2,}/g, \"-\")\r\n\t\t.replace(/^-+|-+$/g, \"\")\r\n\t\t.slice(0, 80);\r\n\tconst hash = createHash(\"sha1\").update(relativePath).digest(\"hex\").slice(0, 10);\r\n\treturn `${slug || \"memory\"}-${hash}`;\r\n}\r\n\r\nfunction pickTitle(relativePath: string, frontmatterTitle: MetadataValue | undefined, headingTitle: string | undefined): string | undefined {\r\n\tif (typeof frontmatterTitle === \"string\" && frontmatterTitle.trim().length > 0) {\r\n\t\treturn frontmatterTitle.trim();\r\n\t}\r\n\tif (headingTitle) {\r\n\t\treturn headingTitle;\r\n\t}\r\n\tconst fileName = basename(relativePath, extname(relativePath)).trim();\r\n\treturn fileName || undefined;\r\n}\r\n\r\nfunction buildTargetNamespace(service: CloudflareMemoryService, options: MigrationRunOptions, workspaceDir: string): string {\r\n\treturn service.resolveNamespace({\r\n\t\tnamespace: options.namespace,\r\n\t\tworkspaceDir,\r\n\t});\r\n}\r\n\r\nfunction deriveRecordNamespace(params: {\r\n\trelativePath: string;\r\n\tfrontmatterNamespace: MetadataValue | undefined;\r\n\ttargetNamespace: string;\r\n\tnamespaceStrategy: MigrationNamespaceStrategy;\r\n}): string {\r\n\tif (params.namespaceStrategy === \"single-target\") {\r\n\t\treturn params.targetNamespace;\r\n\t}\r\n\r\n\tif (typeof params.frontmatterNamespace === \"string\" && params.frontmatterNamespace.trim().length > 0) {\r\n\t\treturn sanitizeNamespace(params.frontmatterNamespace);\r\n\t}\r\n\r\n\tconst firstSegment = normalizeRelativePath(params.relativePath).split(\"/\")[0];\r\n\tif (!firstSegment || firstSegment === \".\" || firstSegment === \"..\") {\r\n\t\treturn params.targetNamespace;\r\n\t}\r\n\treturn sanitizeNamespace(firstSegment);\r\n}\r\n\r\nexport async function parseMigrationFile(params: {\r\n\tfile: DiscoveredMigrationFile;\r\n\tsourceMode: MigrationSourceMode;\r\n\ttargetNamespace: string;\r\n\tnamespaceStrategy: MigrationNamespaceStrategy;\r\n}): Promise<ParsedMigrationRecord | null> {\r\n\tconst raw = await readFile(params.file.absolutePath, \"utf8\");\r\n\tconst { body, attributes } = parseFrontmatter(raw);\r\n\tconst { title: headingTitle, text: extractedText } = extractHeadingTitleAndBody(body);\r\n\tconst title = pickTitle(params.file.relativePath, attributes.title, headingTitle);\r\n\tconst text = extractedText.trim() || title || \"\";\r\n\tif (!text) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tconst metadata: Record<string, MetadataValue> = {\r\n\t\tlegacySourceMode: params.sourceMode,\r\n\t\tlegacySourcePath: params.file.relativePath.startsWith(\"..\") ? params.file.absolutePath : params.file.relativePath,\r\n\t};\r\n\tfor (const [key, value] of Object.entries(attributes)) {\r\n\t\tif (RESERVED_FRONTMATTER_FIELDS.has(key)) {\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tmetadata[key] = value;\r\n\t}\r\n\r\n\tconst logicalId =\r\n\t\ttypeof attributes.id === \"string\" && attributes.id.trim().length > 0 ? attributes.id.trim() : buildStableLogicalId(params.file.relativePath);\r\n\tconst namespace = deriveRecordNamespace({\r\n\t\trelativePath: params.file.relativePath,\r\n\t\tfrontmatterNamespace: attributes.namespace,\r\n\t\ttargetNamespace: params.targetNamespace,\r\n\t\tnamespaceStrategy: params.namespaceStrategy,\r\n\t});\r\n\tconst source =\r\n\t\ttypeof attributes.source === \"string\" && attributes.source.trim().length > 0\r\n\t\t\t? attributes.source.trim()\r\n\t\t\t: params.sourceMode === \"default-provider\"\r\n\t\t\t\t? \"openclaw-default-memory\"\r\n\t\t\t\t: \"markdown-import\";\r\n\r\n\treturn {\r\n\t\tsourcePath: params.file.absolutePath,\r\n\t\trelativePath: params.file.relativePath,\r\n\t\tinput: {\r\n\t\t\tid: logicalId,\r\n\t\t\tnamespace,\r\n\t\t\ttitle,\r\n\t\t\ttext,\r\n\t\t\tsource,\r\n\t\t\tmetadata,\r\n\t\t},\r\n\t};\r\n}\r\n\r\nfunction formatDoctorFailure(report: DoctorReport): string {\r\n\tconst failedChecks = report.checks.filter((check) => check.status === \"fail\");\r\n\treturn failedChecks.map((check) => `${check.name}: ${check.message}`).join(\" | \");\r\n}\r\n\r\nexport async function runCloudflareMemoryMigration(params: {\r\n\tservice: CloudflareMemoryService;\r\n\toptions?: MigrationRunOptions;\r\n}): Promise<MigrationSummary> {\r\n\tconst options = params.options ?? {};\r\n\tconst workspaceDir = resolve(options.workspaceDir ?? process.cwd());\r\n\tconst sourceMode: MigrationSourceMode = (options.sourcePaths?.length ?? 0) > 0 ? \"paths\" : \"default-provider\";\r\n\tconst namespaceStrategy = options.namespaceStrategy ?? \"single-target\";\r\n\tconst duplicateStrategy: MigrationDuplicateStrategy = options.duplicateStrategy ?? \"overwrite\";\r\n\tconst dryRun = options.dryRun ?? false;\r\n\tconst targetNamespace = buildTargetNamespace(params.service, options, workspaceDir);\r\n\tconst doctor = await params.service.doctor({\r\n\t\tcreateIndexIfMissing: options.createIndexIfMissing ?? false,\r\n\t});\r\n\tif (!doctor.ok) {\r\n\t\tthrow new Error(`Migration validation failed. ${formatDoctorFailure(doctor)}`);\r\n\t}\r\n\r\n\tconst discoveredFiles = await discoverMigrationFiles({\r\n\t\tworkspaceDir,\r\n\t\tsourceMode,\r\n\t\tsourcePaths: options.sourcePaths,\r\n\t});\r\n\tif (discoveredFiles.length === 0) {\r\n\t\tthrow new Error(\r\n\t\t\tsourceMode === \"default-provider\"\r\n\t\t\t\t? `No default OpenClaw markdown memory files were found under ${workspaceDir}.`\r\n\t\t\t\t: \"No markdown files matched the provided migration sources.\",\r\n\t\t);\r\n\t}\r\n\r\n\tconst results: MigrationResult[] = [];\r\n\tlet preparedRecords = 0;\r\n\tlet imported = 0;\r\n\tlet skipped = 0;\r\n\tlet failed = 0;\r\n\r\n\tfor (const file of discoveredFiles) {\r\n\t\ttry {\r\n\t\t\tconst parsed = await parseMigrationFile({\r\n\t\t\t\tfile,\r\n\t\t\t\tsourceMode,\r\n\t\t\t\ttargetNamespace,\r\n\t\t\t\tnamespaceStrategy,\r\n\t\t\t});\r\n\t\t\tif (!parsed) {\r\n\t\t\t\tskipped += 1;\r\n\t\t\t\tresults.push({\r\n\t\t\t\t\taction: \"skipped\",\r\n\t\t\t\t\tsourcePath: file.absolutePath,\r\n\t\t\t\t\trelativePath: file.relativePath,\r\n\t\t\t\t\treason: \"File did not contain any importable markdown content.\",\r\n\t\t\t\t});\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tpreparedRecords += 1;\r\n\t\t\tconst logicalId = parsed.input.id;\r\n\t\t\tconst namespace = parsed.input.namespace;\r\n\t\t\tif (!logicalId || !namespace) {\r\n\t\t\t\tthrow new Error(\"Parsed migration record is missing a logical id or namespace.\");\r\n\t\t\t}\r\n\r\n\t\t\tif (duplicateStrategy !== \"overwrite\") {\r\n\t\t\t\tconst existing = await params.service.get({\r\n\t\t\t\t\tid: logicalId,\r\n\t\t\t\t\tnamespace,\r\n\t\t\t\t});\r\n\t\t\t\tif (existing) {\r\n\t\t\t\t\tif (duplicateStrategy === \"skip\") {\r\n\t\t\t\t\t\tskipped += 1;\r\n\t\t\t\t\t\tresults.push({\r\n\t\t\t\t\t\t\taction: \"skipped\",\r\n\t\t\t\t\t\t\tsourcePath: parsed.sourcePath,\r\n\t\t\t\t\t\t\trelativePath: parsed.relativePath,\r\n\t\t\t\t\t\t\tlogicalId,\r\n\t\t\t\t\t\t\tnamespace,\r\n\t\t\t\t\t\t\ttitle: parsed.input.title,\r\n\t\t\t\t\t\t\treason: \"A record with the same logical id already exists.\",\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthrow new Error(`A record with logical id ${logicalId} already exists in namespace ${namespace}.`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (dryRun) {\r\n\t\t\t\tresults.push({\r\n\t\t\t\t\taction: \"would-import\",\r\n\t\t\t\t\tsourcePath: parsed.sourcePath,\r\n\t\t\t\t\trelativePath: parsed.relativePath,\r\n\t\t\t\t\tlogicalId,\r\n\t\t\t\t\tnamespace,\r\n\t\t\t\t\ttitle: parsed.input.title,\r\n\t\t\t\t});\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tawait params.service.upsert({\r\n\t\t\t\tinput: parsed.input,\r\n\t\t\t});\r\n\t\t\timported += 1;\r\n\t\t\tresults.push({\r\n\t\t\t\taction: \"imported\",\r\n\t\t\t\tsourcePath: parsed.sourcePath,\r\n\t\t\t\trelativePath: parsed.relativePath,\r\n\t\t\t\tlogicalId,\r\n\t\t\t\tnamespace,\r\n\t\t\t\ttitle: parsed.input.title,\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tfailed += 1;\r\n\t\t\tresults.push({\r\n\t\t\t\taction: \"failed\",\r\n\t\t\t\tsourcePath: file.absolutePath,\r\n\t\t\t\trelativePath: file.relativePath,\r\n\t\t\t\terror: error instanceof Error ? error.message : \"Unknown migration failure.\",\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\r\n\treturn {\r\n\t\tdryRun,\r\n\t\tsourceMode,\r\n\t\tworkspaceDir,\r\n\t\tnamespaceStrategy,\r\n\t\ttargetNamespace: namespaceStrategy === \"single-target\" ? targetNamespace : undefined,\r\n\t\tdiscoveredFiles: discoveredFiles.length,\r\n\t\tpreparedRecords,\r\n\t\timported,\r\n\t\tskipped,\r\n\t\tfailed,\r\n\t\tdoctor,\r\n\t\tresults,\r\n\t};\r\n}\r\n\r\nexport function formatMigrationSummary(summary: MigrationSummary): string {\r\n\tconst lines = [\r\n\t\t`${summary.dryRun ? \"Dry-run\" : \"Migration\"} ${summary.failed > 0 ? \"completed with failures\" : \"completed\"}.`,\r\n\t\t`Source mode: ${summary.sourceMode}`,\r\n\t\t`Workspace: ${summary.workspaceDir}`,\r\n\t\t`Files scanned: ${summary.discoveredFiles}`,\r\n\t\t`Records prepared: ${summary.preparedRecords}`,\r\n\t\t`Imported: ${summary.imported}`,\r\n\t\t`Skipped: ${summary.skipped}`,\r\n\t\t`Failed: ${summary.failed}`,\r\n\t];\r\n\r\n\tif (summary.targetNamespace) {\r\n\t\tlines.splice(3, 0, `Target namespace: ${summary.targetNamespace}`);\r\n\t}\r\n\r\n\tconst failedResults = summary.results.filter((result) => result.action === \"failed\").slice(0, 10);\r\n\tif (failedResults.length > 0) {\r\n\t\tlines.push(\"\", \"Failures:\");\r\n\t\tfor (const result of failedResults) {\r\n\t\t\tlines.push(`- ${result.relativePath}: ${result.error}`);\r\n\t\t}\r\n\t}\r\n\r\n\treturn lines.join(\"\\n\");\r\n}\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { basename as e } from "node:path";
|
|
2
|
+
import { resolveAgentIdFromSessionKey as t } from "openclaw/plugin-sdk/routing";
|
|
3
|
+
//#region src/namespace.ts
|
|
4
|
+
function n(e) {
|
|
5
|
+
return e.trim().toLowerCase().replace(/[^a-z0-9-_]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").slice(0, 64);
|
|
6
|
+
}
|
|
7
|
+
function r(e) {
|
|
8
|
+
return n(e) || "main";
|
|
9
|
+
}
|
|
10
|
+
function i(n) {
|
|
11
|
+
if (n.fixedNamespace) return r(n.fixedNamespace);
|
|
12
|
+
let i = n.sessionKey ? t(n.sessionKey) : n.agentId;
|
|
13
|
+
return i ? r(`agent-${i}`) : n.workspaceDir ? r(`workspace-${e(n.workspaceDir)}`) : "main";
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { i as resolveDefaultNamespace, r as sanitizeNamespace };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=namespace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.js","names":[],"sources":["../src/namespace.ts"],"sourcesContent":["import { basename } from \"node:path\";\nimport { resolveAgentIdFromSessionKey } from \"openclaw/plugin-sdk/routing\";\n\nfunction normalizeNamespacePart(value: string): string {\n\treturn value\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9-_]+/g, \"-\")\n\t\t.replace(/-{2,}/g, \"-\")\n\t\t.replace(/^-+|-+$/g, \"\")\n\t\t.slice(0, 64);\n}\n\nexport function sanitizeNamespace(value: string): string {\n\tconst normalized = normalizeNamespacePart(value);\n\treturn normalized || \"main\";\n}\n\nexport function resolveDefaultNamespace(params: { fixedNamespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): string {\n\tif (params.fixedNamespace) {\n\t\treturn sanitizeNamespace(params.fixedNamespace);\n\t}\n\tconst agentId = params.sessionKey ? resolveAgentIdFromSessionKey(params.sessionKey) : params.agentId;\n\tif (agentId) {\n\t\treturn sanitizeNamespace(`agent-${agentId}`);\n\t}\n\tif (params.workspaceDir) {\n\t\treturn sanitizeNamespace(`workspace-${basename(params.workspaceDir)}`);\n\t}\n\treturn \"main\";\n}\n"],"mappings":";;;AAGA,SAAS,EAAuB,GAAuB;AACtD,QAAO,EACL,MAAM,CACN,aAAa,CACb,QAAQ,iBAAiB,IAAI,CAC7B,QAAQ,UAAU,IAAI,CACtB,QAAQ,YAAY,GAAG,CACvB,MAAM,GAAG,GAAG;;AAGf,SAAgB,EAAkB,GAAuB;AAExD,QADmB,EAAuB,EAAM,IAC3B;;AAGtB,SAAgB,EAAwB,GAA2G;AAClJ,KAAI,EAAO,eACV,QAAO,EAAkB,EAAO,eAAe;CAEhD,IAAM,IAAU,EAAO,aAAa,EAA6B,EAAO,WAAW,GAAG,EAAO;AAO7F,QANI,IACI,EAAkB,SAAS,IAAU,GAEzC,EAAO,eACH,EAAkB,aAAa,EAAS,EAAO,aAAa,GAAG,GAEhE"}
|
package/dist/prompt.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/prompt.ts
|
|
2
|
+
var e = ({ availableTools: e }) => {
|
|
3
|
+
let t = ["Cloudflare memory is available through Vectorize semantic search and Workers AI embeddings.", "Use the memory tools for recalling past facts, preferences, and durable notes before asking repetitive follow-up questions."];
|
|
4
|
+
return e.has("cloudflare_memory_upsert") && t.push("When the user wants something remembered long-term, store it with cloudflare_memory_upsert."), e.has("cloudflare_memory_search") && t.push("Use cloudflare_memory_search to retrieve prior memories by semantic similarity or metadata filters."), t;
|
|
5
|
+
};
|
|
6
|
+
//#endregion
|
|
7
|
+
export { e as buildPromptSection };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","names":[],"sources":["../src/prompt.ts"],"sourcesContent":["import type { MemoryPromptSectionBuilder } from \"openclaw/plugin-sdk/memory-core\";\n\nexport const buildPromptSection: MemoryPromptSectionBuilder = ({ availableTools }) => {\n\tconst lines = [\n\t\t\"Cloudflare memory is available through Vectorize semantic search and Workers AI embeddings.\",\n\t\t\"Use the memory tools for recalling past facts, preferences, and durable notes before asking repetitive follow-up questions.\",\n\t];\n\n\tif (availableTools.has(\"cloudflare_memory_upsert\")) {\n\t\tlines.push(\"When the user wants something remembered long-term, store it with cloudflare_memory_upsert.\");\n\t}\n\tif (availableTools.has(\"cloudflare_memory_search\")) {\n\t\tlines.push(\"Use cloudflare_memory_search to retrieve prior memories by semantic similarity or metadata filters.\");\n\t}\n\n\treturn lines;\n};\n"],"mappings":";AAEA,IAAa,KAAkD,EAAE,wBAAqB;CACrF,IAAM,IAAQ,CACb,+FACA,8HACA;AASD,QAPI,EAAe,IAAI,2BAA2B,IACjD,EAAM,KAAK,8FAA8F,EAEtG,EAAe,IAAI,2BAA2B,IACjD,EAAM,KAAK,sGAAsG,EAG3G"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createCloudflareMemoryService as e } from "./service-factory.js";
|
|
2
|
+
import { access as t } from "node:fs/promises";
|
|
3
|
+
import { dirname as n } from "node:path";
|
|
4
|
+
//#region src/public-artifacts.ts
|
|
5
|
+
function r(r, i) {
|
|
6
|
+
return { async listArtifacts({ cfg: a }) {
|
|
7
|
+
let o = (await e({
|
|
8
|
+
pluginConfig: r,
|
|
9
|
+
openClawConfig: a,
|
|
10
|
+
env: process.env,
|
|
11
|
+
resolvePath: i
|
|
12
|
+
})).config;
|
|
13
|
+
try {
|
|
14
|
+
await t(o.companionStorePath);
|
|
15
|
+
} catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
return [{
|
|
19
|
+
kind: "cloudflare-companion-store",
|
|
20
|
+
workspaceDir: n(o.companionStorePath),
|
|
21
|
+
relativePath: o.companionStorePath.split(/[/\\]/).at(-1) ?? "companion-store.json",
|
|
22
|
+
absolutePath: o.companionStorePath,
|
|
23
|
+
agentIds: [],
|
|
24
|
+
contentType: "json"
|
|
25
|
+
}];
|
|
26
|
+
} };
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { r as createPublicArtifactsProvider };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=public-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-artifacts.js","names":[],"sources":["../src/public-artifacts.ts"],"sourcesContent":["import { access } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { MemoryPluginPublicArtifact, MemoryPluginPublicArtifactsProvider } from \"openclaw/plugin-sdk/memory-core\";\nimport { createCloudflareMemoryService } from \"./service-factory.js\";\n\nexport function createPublicArtifactsProvider(pluginConfig: unknown, resolvePath?: (input: string) => string): MemoryPluginPublicArtifactsProvider {\n\treturn {\n\t\tasync listArtifacts({ cfg }): Promise<MemoryPluginPublicArtifact[]> {\n\t\t\tconst service = await createCloudflareMemoryService({\n\t\t\t\tpluginConfig,\n\t\t\t\topenClawConfig: cfg,\n\t\t\t\tenv: process.env,\n\t\t\t\tresolvePath,\n\t\t\t});\n\t\t\tconst config = service.config;\n\t\t\ttry {\n\t\t\t\tawait access(config.companionStorePath);\n\t\t\t} catch {\n\t\t\t\treturn [];\n\t\t\t}\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tkind: \"cloudflare-companion-store\",\n\t\t\t\t\tworkspaceDir: dirname(config.companionStorePath),\n\t\t\t\t\trelativePath: config.companionStorePath.split(/[/\\\\]/).at(-1) ?? \"companion-store.json\",\n\t\t\t\t\tabsolutePath: config.companionStorePath,\n\t\t\t\t\tagentIds: [],\n\t\t\t\t\tcontentType: \"json\",\n\t\t\t\t},\n\t\t\t];\n\t\t},\n\t};\n}\n"],"mappings":";;;;AAKA,SAAgB,EAA8B,GAAuB,GAA8E;AAClJ,QAAO,EACN,MAAM,cAAc,EAAE,UAA8C;EAOnE,IAAM,KANU,MAAM,EAA8B;GACnD;GACA,gBAAgB;GAChB,KAAK,QAAQ;GACb;GACA,CAAC,EACqB;AACvB,MAAI;AACH,SAAM,EAAO,EAAO,mBAAmB;UAChC;AACP,UAAO,EAAE;;AAEV,SAAO,CACN;GACC,MAAM;GACN,cAAc,EAAQ,EAAO,mBAAmB;GAChD,cAAc,EAAO,mBAAmB,MAAM,QAAQ,CAAC,GAAG,GAAG,IAAI;GACjE,cAAc,EAAO;GACrB,UAAU,EAAE;GACZ,aAAa;GACb,CACD;IAEF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { RESERVED_METADATA_KEYS as e } from "./constants.js";
|
|
2
|
+
import { RecordSizeError as t } from "./errors.js";
|
|
3
|
+
import { randomUUID as n } from "node:crypto";
|
|
4
|
+
import { Buffer as r } from "node:buffer";
|
|
5
|
+
//#region src/record-mapper.ts
|
|
6
|
+
function i(e) {
|
|
7
|
+
let t = e.trim().replace(/[.$"]/g, "_").replace(/\s+/g, "_");
|
|
8
|
+
return t ? t.startsWith("oc_") ? `user_${t}` : t : "metadata";
|
|
9
|
+
}
|
|
10
|
+
function a(e) {
|
|
11
|
+
if (!e) return {};
|
|
12
|
+
let t = Object.entries(e).filter(([, e]) => [
|
|
13
|
+
"string",
|
|
14
|
+
"number",
|
|
15
|
+
"boolean"
|
|
16
|
+
].includes(typeof e));
|
|
17
|
+
return Object.fromEntries(t.map(([e, t]) => [i(e), t]));
|
|
18
|
+
}
|
|
19
|
+
function o(e, t) {
|
|
20
|
+
return `${e}::${t}`;
|
|
21
|
+
}
|
|
22
|
+
function s(e, t) {
|
|
23
|
+
return `${e}/${t}.md`;
|
|
24
|
+
}
|
|
25
|
+
function c(e) {
|
|
26
|
+
let t = e.replace(/\\/g, "/").replace(/^\//, "").split("/");
|
|
27
|
+
return t.length !== 2 || !t[1].endsWith(".md") ? null : {
|
|
28
|
+
namespace: t[0],
|
|
29
|
+
logicalId: t[1].slice(0, -3)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function l(e, t) {
|
|
33
|
+
let n = e.trim().replace(/\s+/g, " ");
|
|
34
|
+
if (!n) return "";
|
|
35
|
+
let r = n.toLowerCase().indexOf(t.trim().toLowerCase());
|
|
36
|
+
if (r === -1) return n.slice(0, 220);
|
|
37
|
+
let i = Math.max(0, r - 80), a = Math.min(n.length, r + Math.max(t.length, 40) + 80);
|
|
38
|
+
return n.slice(i, a);
|
|
39
|
+
}
|
|
40
|
+
function u(i) {
|
|
41
|
+
let c = i.input.id?.trim() || n(), l = o(i.namespace, c), u = (/* @__PURE__ */ new Date()).toISOString(), d = a(i.input.metadata), f = {
|
|
42
|
+
...d,
|
|
43
|
+
[e.logicalId]: c,
|
|
44
|
+
[e.storageMode]: i.config.storageMode,
|
|
45
|
+
[e.createdAt]: u,
|
|
46
|
+
[e.updatedAt]: u
|
|
47
|
+
};
|
|
48
|
+
i.input.title && (f[e.title] = i.input.title), i.input.source && (f[e.source] = i.input.source);
|
|
49
|
+
let p;
|
|
50
|
+
if (i.config.storageMode === "vectorize-inline") {
|
|
51
|
+
let n = r.byteLength(i.input.text, "utf8");
|
|
52
|
+
if (n > i.config.inlineTextMaxBytes) throw new t(`Memory text is ${n} bytes, which exceeds the inline metadata limit of ${i.config.inlineTextMaxBytes}. Switch storage.mode to "companion-store" or reduce the payload size.`);
|
|
53
|
+
f[e.text] = i.input.text;
|
|
54
|
+
} else {
|
|
55
|
+
let t = s(i.namespace, c);
|
|
56
|
+
f[e.pointer] = t, p = {
|
|
57
|
+
id: c,
|
|
58
|
+
namespace: i.namespace,
|
|
59
|
+
title: i.input.title,
|
|
60
|
+
text: i.input.text,
|
|
61
|
+
metadata: d,
|
|
62
|
+
source: i.input.source,
|
|
63
|
+
createdAt: u,
|
|
64
|
+
updatedAt: u
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
logicalId: c,
|
|
69
|
+
vectorId: l,
|
|
70
|
+
path: s(i.namespace, c),
|
|
71
|
+
vector: {
|
|
72
|
+
id: l,
|
|
73
|
+
namespace: i.namespace,
|
|
74
|
+
values: i.embedding,
|
|
75
|
+
metadata: f
|
|
76
|
+
},
|
|
77
|
+
companionRecord: p
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function d(t) {
|
|
81
|
+
let n = t.metadata ?? {}, r = t.namespace ?? (typeof n[e.pointer] == "string" ? String(n[e.pointer]).split("/")[0] : "main"), i = typeof n[e.logicalId] == "string" ? String(n[e.logicalId]) : String(t.id ?? ""), a = Object.fromEntries(Object.entries(n).filter(([e]) => !e.startsWith("oc_")));
|
|
82
|
+
return {
|
|
83
|
+
logicalId: i,
|
|
84
|
+
vectorId: String(t.id ?? i),
|
|
85
|
+
namespace: r,
|
|
86
|
+
title: typeof n[e.title] == "string" ? String(n[e.title]) : void 0,
|
|
87
|
+
text: typeof n[e.text] == "string" ? String(n[e.text]) : void 0,
|
|
88
|
+
metadata: a,
|
|
89
|
+
source: typeof n[e.source] == "string" ? String(n[e.source]) : void 0,
|
|
90
|
+
createdAt: typeof n[e.createdAt] == "string" ? String(n[e.createdAt]) : void 0,
|
|
91
|
+
updatedAt: typeof n[e.updatedAt] == "string" ? String(n[e.updatedAt]) : void 0,
|
|
92
|
+
path: s(r, i)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { l as buildSnippet, d as hydrateInlineRecord, u as mapRecordForUpsert, c as parseVirtualPath };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=record-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-mapper.js","names":[],"sources":["../src/record-mapper.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\nimport { randomUUID } from \"node:crypto\";\nimport { RESERVED_METADATA_KEYS, RESERVED_METADATA_PREFIX } from \"./constants.js\";\nimport { RecordSizeError } from \"./errors.js\";\nimport type {\n\tCompanionRecord,\n\tHydratedMemoryRecord,\n\tMemoryRecordInput,\n\tMetadataValue,\n\tResolvedPluginConfig,\n\tVectorizeQueryMatch,\n\tVectorizeVector,\n} from \"./types.js\";\n\nfunction sanitizeMetadataKey(key: string): string {\n\tconst sanitized = key.trim().replace(/[.$\"]/g, \"_\").replace(/\\s+/g, \"_\");\n\tif (!sanitized) {\n\t\treturn \"metadata\";\n\t}\n\tif (sanitized.startsWith(RESERVED_METADATA_PREFIX)) {\n\t\treturn `user_${sanitized}`;\n\t}\n\treturn sanitized;\n}\n\nfunction sanitizeMetadata(metadata: Record<string, MetadataValue> | undefined): Record<string, MetadataValue> {\n\tif (!metadata) {\n\t\treturn {};\n\t}\n\tconst entries = Object.entries(metadata).filter(([, value]) => [\"string\", \"number\", \"boolean\"].includes(typeof value));\n\treturn Object.fromEntries(entries.map(([key, value]) => [sanitizeMetadataKey(key), value]));\n}\n\nexport function buildVectorId(namespace: string, logicalId: string): string {\n\treturn `${namespace}::${logicalId}`;\n}\n\nexport function buildVirtualPath(namespace: string, logicalId: string): string {\n\treturn `${namespace}/${logicalId}.md`;\n}\n\nexport function parseVirtualPath(path: string): { namespace: string; logicalId: string } | null {\n\tconst normalized = path.replace(/\\\\/g, \"/\").replace(/^\\//, \"\");\n\tconst segments = normalized.split(\"/\");\n\tif (segments.length !== 2 || !segments[1].endsWith(\".md\")) {\n\t\treturn null;\n\t}\n\treturn {\n\t\tnamespace: segments[0],\n\t\tlogicalId: segments[1].slice(0, -3),\n\t};\n}\n\nexport function buildSnippet(text: string, query: string): string {\n\tconst normalized = text.trim().replace(/\\s+/g, \" \");\n\tif (!normalized) {\n\t\treturn \"\";\n\t}\n\tconst lower = normalized.toLowerCase();\n\tconst index = lower.indexOf(query.trim().toLowerCase());\n\tif (index === -1) {\n\t\treturn normalized.slice(0, 220);\n\t}\n\tconst start = Math.max(0, index - 80);\n\tconst end = Math.min(normalized.length, index + Math.max(query.length, 40) + 80);\n\treturn normalized.slice(start, end);\n}\n\nexport function mapRecordForUpsert(params: { input: MemoryRecordInput; namespace: string; embedding: number[]; config: ResolvedPluginConfig }): {\n\tlogicalId: string;\n\tvectorId: string;\n\tpath: string;\n\tvector: VectorizeVector;\n\tcompanionRecord?: CompanionRecord;\n} {\n\tconst logicalId = params.input.id?.trim() || randomUUID();\n\tconst vectorId = buildVectorId(params.namespace, logicalId);\n\tconst now = new Date().toISOString();\n\tconst userMetadata = sanitizeMetadata(params.input.metadata);\n\tconst metadataBase: Record<string, MetadataValue> = {\n\t\t...userMetadata,\n\t\t[RESERVED_METADATA_KEYS.logicalId]: logicalId,\n\t\t[RESERVED_METADATA_KEYS.storageMode]: params.config.storageMode,\n\t\t[RESERVED_METADATA_KEYS.createdAt]: now,\n\t\t[RESERVED_METADATA_KEYS.updatedAt]: now,\n\t};\n\n\tif (params.input.title) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.title] = params.input.title;\n\t}\n\tif (params.input.source) {\n\t\tmetadataBase[RESERVED_METADATA_KEYS.source] = params.input.source;\n\t}\n\n\tlet companionRecord: CompanionRecord | undefined;\n\tif (params.config.storageMode === \"vectorize-inline\") {\n\t\tconst byteLength = Buffer.byteLength(params.input.text, \"utf8\");\n\t\tif (byteLength > params.config.inlineTextMaxBytes) {\n\t\t\tthrow new RecordSizeError(\n\t\t\t\t`Memory text is ${byteLength} bytes, which exceeds the inline metadata limit of ${params.config.inlineTextMaxBytes}. Switch storage.mode to \"companion-store\" or reduce the payload size.`,\n\t\t\t);\n\t\t}\n\t\tmetadataBase[RESERVED_METADATA_KEYS.text] = params.input.text;\n\t} else {\n\t\tconst pointer = buildVirtualPath(params.namespace, logicalId);\n\t\tmetadataBase[RESERVED_METADATA_KEYS.pointer] = pointer;\n\t\tcompanionRecord = {\n\t\t\tid: logicalId,\n\t\t\tnamespace: params.namespace,\n\t\t\ttitle: params.input.title,\n\t\t\ttext: params.input.text,\n\t\t\tmetadata: userMetadata,\n\t\t\tsource: params.input.source,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t};\n\t}\n\n\treturn {\n\t\tlogicalId,\n\t\tvectorId,\n\t\tpath: buildVirtualPath(params.namespace, logicalId),\n\t\tvector: {\n\t\t\tid: vectorId,\n\t\t\tnamespace: params.namespace,\n\t\t\tvalues: params.embedding,\n\t\t\tmetadata: metadataBase,\n\t\t},\n\t\tcompanionRecord,\n\t};\n}\n\nexport function hydrateInlineRecord(match: VectorizeQueryMatch): Omit<HydratedMemoryRecord, \"text\" | \"path\"> & {\n\ttext?: string;\n\tpath: string;\n} {\n\tconst metadata = match.metadata ?? {};\n\tconst namespace =\n\t\tmatch.namespace ?? (typeof metadata[RESERVED_METADATA_KEYS.pointer] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.pointer]).split(\"/\")[0] : \"main\");\n\tconst logicalId =\n\t\ttypeof metadata[RESERVED_METADATA_KEYS.logicalId] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.logicalId]) : String(match.id ?? \"\");\n\tconst userMetadata = Object.fromEntries(Object.entries(metadata).filter(([key]) => !key.startsWith(RESERVED_METADATA_PREFIX)));\n\treturn {\n\t\tlogicalId,\n\t\tvectorId: String(match.id ?? logicalId),\n\t\tnamespace,\n\t\ttitle: typeof metadata[RESERVED_METADATA_KEYS.title] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.title]) : undefined,\n\t\ttext: typeof metadata[RESERVED_METADATA_KEYS.text] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.text]) : undefined,\n\t\tmetadata: userMetadata,\n\t\tsource: typeof metadata[RESERVED_METADATA_KEYS.source] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.source]) : undefined,\n\t\tcreatedAt: typeof metadata[RESERVED_METADATA_KEYS.createdAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.createdAt]) : undefined,\n\t\tupdatedAt: typeof metadata[RESERVED_METADATA_KEYS.updatedAt] === \"string\" ? String(metadata[RESERVED_METADATA_KEYS.updatedAt]) : undefined,\n\t\tpath: buildVirtualPath(namespace, logicalId),\n\t};\n}\n"],"mappings":"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"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createCloudflareMemoryService as e } from "./service-factory.js";
|
|
2
|
+
import { CloudflareMemorySearchManager as t } from "./search-manager.js";
|
|
3
|
+
//#region src/runtime.ts
|
|
4
|
+
function n(n) {
|
|
5
|
+
let r = /* @__PURE__ */ new Map();
|
|
6
|
+
async function i(i, a) {
|
|
7
|
+
let o = await e({
|
|
8
|
+
pluginConfig: n.pluginConfig,
|
|
9
|
+
openClawConfig: i,
|
|
10
|
+
env: process.env,
|
|
11
|
+
resolvePath: n.resolvePath
|
|
12
|
+
}), s = `${a}::${o.config.indexName}::${o.config.storageMode}`, c = r.get(s);
|
|
13
|
+
if (c) return c;
|
|
14
|
+
let l = new t(o, a);
|
|
15
|
+
return r.set(s, l), l;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
async getMemorySearchManager(e) {
|
|
19
|
+
try {
|
|
20
|
+
return { manager: await i(e.cfg, e.agentId) };
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return {
|
|
23
|
+
manager: null,
|
|
24
|
+
error: e instanceof Error ? e.message : "Unable to create Cloudflare memory manager."
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
resolveMemoryBackendConfig() {
|
|
29
|
+
return { backend: "builtin" };
|
|
30
|
+
},
|
|
31
|
+
async closeAllMemorySearchManagers() {
|
|
32
|
+
await Promise.all([...r.values()].map((e) => e.close?.())), r.clear();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { n as createMemoryRuntime };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport type { MemoryPluginRuntime } from \"openclaw/plugin-sdk/memory-core\";\nimport { CloudflareMemorySearchManager } from \"./search-manager.js\";\nimport { createCloudflareMemoryService } from \"./service-factory.js\";\n\nexport function createMemoryRuntime(params: { pluginConfig: unknown; resolvePath?: (input: string) => string }): MemoryPluginRuntime {\n\tconst managers = new Map<string, CloudflareMemorySearchManager>();\n\n\tasync function getOrCreateManager(openClawConfig: OpenClawConfig, agentId: string): Promise<CloudflareMemorySearchManager> {\n\t\tconst service = await createCloudflareMemoryService({\n\t\t\tpluginConfig: params.pluginConfig,\n\t\t\topenClawConfig,\n\t\t\tenv: process.env,\n\t\t\tresolvePath: params.resolvePath,\n\t\t});\n\t\tconst key = `${agentId}::${service.config.indexName}::${service.config.storageMode}`;\n\t\tconst existing = managers.get(key);\n\t\tif (existing) {\n\t\t\treturn existing;\n\t\t}\n\t\tconst manager = new CloudflareMemorySearchManager(service, agentId);\n\t\tmanagers.set(key, manager);\n\t\treturn manager;\n\t}\n\n\treturn {\n\t\tasync getMemorySearchManager(params) {\n\t\t\ttry {\n\t\t\t\tconst manager = await getOrCreateManager(params.cfg, params.agentId);\n\t\t\t\treturn { manager };\n\t\t\t} catch (error) {\n\t\t\t\treturn {\n\t\t\t\t\tmanager: null,\n\t\t\t\t\terror: error instanceof Error ? error.message : \"Unable to create Cloudflare memory manager.\",\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\tresolveMemoryBackendConfig() {\n\t\t\treturn { backend: \"builtin\" };\n\t\t},\n\t\tasync closeAllMemorySearchManagers() {\n\t\t\tawait Promise.all([...managers.values()].map((manager) => manager.close?.()));\n\t\t\tmanagers.clear();\n\t\t},\n\t};\n}\n"],"mappings":";;;AAKA,SAAgB,EAAoB,GAAiG;CACpI,IAAM,oBAAW,IAAI,KAA4C;CAEjE,eAAe,EAAmB,GAAgC,GAAyD;EAC1H,IAAM,IAAU,MAAM,EAA8B;GACnD,cAAc,EAAO;GACrB;GACA,KAAK,QAAQ;GACb,aAAa,EAAO;GACpB,CAAC,EACI,IAAM,GAAG,EAAQ,IAAI,EAAQ,OAAO,UAAU,IAAI,EAAQ,OAAO,eACjE,IAAW,EAAS,IAAI,EAAI;AAClC,MAAI,EACH,QAAO;EAER,IAAM,IAAU,IAAI,EAA8B,GAAS,EAAQ;AAEnE,SADA,EAAS,IAAI,GAAK,EAAQ,EACnB;;AAGR,QAAO;EACN,MAAM,uBAAuB,GAAQ;AACpC,OAAI;AAEH,WAAO,EAAE,SADO,MAAM,EAAmB,EAAO,KAAK,EAAO,QAAQ,EAClD;YACV,GAAO;AACf,WAAO;KACN,SAAS;KACT,OAAO,aAAiB,QAAQ,EAAM,UAAU;KAChD;;;EAGH,6BAA6B;AAC5B,UAAO,EAAE,SAAS,WAAW;;EAE9B,MAAM,+BAA+B;AAEpC,GADA,MAAM,QAAQ,IAAI,CAAC,GAAG,EAAS,QAAQ,CAAC,CAAC,KAAK,MAAY,EAAQ,SAAS,CAAC,CAAC,EAC7E,EAAS,OAAO;;EAEjB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { buildSnippet as e, parseVirtualPath as t } from "./record-mapper.js";
|
|
2
|
+
//#region src/search-manager.ts
|
|
3
|
+
var n = class {
|
|
4
|
+
constructor(e, t) {
|
|
5
|
+
this.service = e, this.agentId = t;
|
|
6
|
+
}
|
|
7
|
+
async search(t, n) {
|
|
8
|
+
return (await this.service.search({
|
|
9
|
+
query: t,
|
|
10
|
+
maxResults: n?.maxResults,
|
|
11
|
+
minScore: n?.minScore,
|
|
12
|
+
sessionKey: n?.sessionKey,
|
|
13
|
+
agentId: this.agentId
|
|
14
|
+
})).map((n) => ({
|
|
15
|
+
path: n.path,
|
|
16
|
+
startLine: 1,
|
|
17
|
+
endLine: Math.max(1, n.text.split(/\r?\n/).length),
|
|
18
|
+
score: n.score,
|
|
19
|
+
snippet: e(n.text, t),
|
|
20
|
+
source: "memory",
|
|
21
|
+
citation: n.path
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
async readFile(e) {
|
|
25
|
+
let n = t(e.relPath);
|
|
26
|
+
if (!n) throw Error(`Unsupported memory lookup path: ${e.relPath}`);
|
|
27
|
+
let r = await this.service.get({
|
|
28
|
+
id: n.logicalId,
|
|
29
|
+
namespace: n.namespace,
|
|
30
|
+
agentId: this.agentId
|
|
31
|
+
});
|
|
32
|
+
if (!r) throw Error(`Memory record not found for ${e.relPath}`);
|
|
33
|
+
let i = Math.max(1, e.from ?? 1), a = Math.max(1, e.lines ?? r.text.split(/\r?\n/).length);
|
|
34
|
+
return {
|
|
35
|
+
text: r.text.split(/\r?\n/).slice(i - 1, i - 1 + a).join("\n"),
|
|
36
|
+
path: r.path
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
status() {
|
|
40
|
+
return {
|
|
41
|
+
backend: "builtin",
|
|
42
|
+
provider: "cloudflare-vectorize",
|
|
43
|
+
model: this.service.config.model,
|
|
44
|
+
workspaceDir: this.service.config.companionStorePath,
|
|
45
|
+
custom: {
|
|
46
|
+
indexName: this.service.config.indexName,
|
|
47
|
+
storageMode: this.service.config.storageMode,
|
|
48
|
+
fixedNamespace: this.service.config.fixedNamespace
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async probeEmbeddingAvailability() {
|
|
53
|
+
try {
|
|
54
|
+
return await this.service.embeddings.probeDimensions(), { ok: !0 };
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return {
|
|
57
|
+
ok: !1,
|
|
58
|
+
error: e instanceof Error ? e.message : "Embedding probe failed."
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async probeVectorAvailability() {
|
|
63
|
+
try {
|
|
64
|
+
return await this.service.vectorize.describeIndex(), !0;
|
|
65
|
+
} catch {
|
|
66
|
+
return !1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async close() {}
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { n as CloudflareMemorySearchManager };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=search-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-manager.js","names":[],"sources":["../src/search-manager.ts"],"sourcesContent":["import type {\n\tMemoryEmbeddingProbeResult,\n\tMemoryProviderStatus,\n\tMemorySearchManager,\n\tMemorySearchResult,\n} from \"openclaw/plugin-sdk/memory-core-host-engine-storage\";\nimport { buildSnippet, parseVirtualPath } from \"./record-mapper.js\";\nimport type { CloudflareMemoryService } from \"./service.js\";\n\nexport class CloudflareMemorySearchManager implements MemorySearchManager {\n\tconstructor(\n\t\tprivate readonly service: CloudflareMemoryService,\n\t\tprivate readonly agentId: string,\n\t) {}\n\n\tasync search(query: string, opts?: { maxResults?: number; minScore?: number; sessionKey?: string }): Promise<MemorySearchResult[]> {\n\t\tconst records = await this.service.search({\n\t\t\tquery,\n\t\t\tmaxResults: opts?.maxResults,\n\t\t\tminScore: opts?.minScore,\n\t\t\tsessionKey: opts?.sessionKey,\n\t\t\tagentId: this.agentId,\n\t\t});\n\n\t\treturn records.map((record) => ({\n\t\t\tpath: record.path,\n\t\t\tstartLine: 1,\n\t\t\tendLine: Math.max(1, record.text.split(/\\r?\\n/).length),\n\t\t\tscore: record.score,\n\t\t\tsnippet: buildSnippet(record.text, query),\n\t\t\tsource: \"memory\",\n\t\t\tcitation: record.path,\n\t\t}));\n\t}\n\n\tasync readFile(params: { relPath: string; from?: number; lines?: number }): Promise<{ text: string; path: string }> {\n\t\tconst parsed = parseVirtualPath(params.relPath);\n\t\tif (!parsed) {\n\t\t\tthrow new Error(`Unsupported memory lookup path: ${params.relPath}`);\n\t\t}\n\t\tconst record = await this.service.get({\n\t\t\tid: parsed.logicalId,\n\t\t\tnamespace: parsed.namespace,\n\t\t\tagentId: this.agentId,\n\t\t});\n\t\tif (!record) {\n\t\t\tthrow new Error(`Memory record not found for ${params.relPath}`);\n\t\t}\n\n\t\tconst from = Math.max(1, params.from ?? 1);\n\t\tconst lines = Math.max(1, params.lines ?? record.text.split(/\\r?\\n/).length);\n\t\tconst selected = record.text\n\t\t\t.split(/\\r?\\n/)\n\t\t\t.slice(from - 1, from - 1 + lines)\n\t\t\t.join(\"\\n\");\n\t\treturn {\n\t\t\ttext: selected,\n\t\t\tpath: record.path,\n\t\t};\n\t}\n\n\tstatus(): MemoryProviderStatus {\n\t\treturn {\n\t\t\tbackend: \"builtin\",\n\t\t\tprovider: \"cloudflare-vectorize\",\n\t\t\tmodel: this.service.config.model,\n\t\t\tworkspaceDir: this.service.config.companionStorePath,\n\t\t\tcustom: {\n\t\t\t\tindexName: this.service.config.indexName,\n\t\t\t\tstorageMode: this.service.config.storageMode,\n\t\t\t\tfixedNamespace: this.service.config.fixedNamespace,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync probeEmbeddingAvailability(): Promise<MemoryEmbeddingProbeResult> {\n\t\ttry {\n\t\t\tawait this.service.embeddings.probeDimensions();\n\t\t\treturn { ok: true };\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: error instanceof Error ? error.message : \"Embedding probe failed.\",\n\t\t\t};\n\t\t}\n\t}\n\n\tasync probeVectorAvailability(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.service.vectorize.describeIndex();\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tasync close(): Promise<void> {}\n}\n"],"mappings":";;AASA,IAAa,IAAb,MAA0E;CACzE,YACC,GACA,GACC;AADgB,EADA,KAAA,UAAA,GACA,KAAA,UAAA;;CAGlB,MAAM,OAAO,GAAe,GAAuG;AASlI,UARgB,MAAM,KAAK,QAAQ,OAAO;GACzC;GACA,YAAY,GAAM;GAClB,UAAU,GAAM;GAChB,YAAY,GAAM;GAClB,SAAS,KAAK;GACd,CAAC,EAEa,KAAK,OAAY;GAC/B,MAAM,EAAO;GACb,WAAW;GACX,SAAS,KAAK,IAAI,GAAG,EAAO,KAAK,MAAM,QAAQ,CAAC,OAAO;GACvD,OAAO,EAAO;GACd,SAAS,EAAa,EAAO,MAAM,EAAM;GACzC,QAAQ;GACR,UAAU,EAAO;GACjB,EAAE;;CAGJ,MAAM,SAAS,GAAqG;EACnH,IAAM,IAAS,EAAiB,EAAO,QAAQ;AAC/C,MAAI,CAAC,EACJ,OAAU,MAAM,mCAAmC,EAAO,UAAU;EAErE,IAAM,IAAS,MAAM,KAAK,QAAQ,IAAI;GACrC,IAAI,EAAO;GACX,WAAW,EAAO;GAClB,SAAS,KAAK;GACd,CAAC;AACF,MAAI,CAAC,EACJ,OAAU,MAAM,+BAA+B,EAAO,UAAU;EAGjE,IAAM,IAAO,KAAK,IAAI,GAAG,EAAO,QAAQ,EAAE,EACpC,IAAQ,KAAK,IAAI,GAAG,EAAO,SAAS,EAAO,KAAK,MAAM,QAAQ,CAAC,OAAO;AAK5E,SAAO;GACN,MALgB,EAAO,KACtB,MAAM,QAAQ,CACd,MAAM,IAAO,GAAG,IAAO,IAAI,EAAM,CACjC,KAAK,KAAK;GAGX,MAAM,EAAO;GACb;;CAGF,SAA+B;AAC9B,SAAO;GACN,SAAS;GACT,UAAU;GACV,OAAO,KAAK,QAAQ,OAAO;GAC3B,cAAc,KAAK,QAAQ,OAAO;GAClC,QAAQ;IACP,WAAW,KAAK,QAAQ,OAAO;IAC/B,aAAa,KAAK,QAAQ,OAAO;IACjC,gBAAgB,KAAK,QAAQ,OAAO;IACpC;GACD;;CAGF,MAAM,6BAAkE;AACvE,MAAI;AAEH,UADA,MAAM,KAAK,QAAQ,WAAW,iBAAiB,EACxC,EAAE,IAAI,IAAM;WACX,GAAO;AACf,UAAO;IACN,IAAI;IACJ,OAAO,aAAiB,QAAQ,EAAM,UAAU;IAChD;;;CAIH,MAAM,0BAA4C;AACjD,MAAI;AAEH,UADA,MAAM,KAAK,QAAQ,UAAU,eAAe,EACrC;UACA;AACP,UAAO;;;CAIT,MAAM,QAAuB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { resolvePluginConfig as e } from "./config.js";
|
|
2
|
+
import { CloudflareMemoryService as t } from "./service.js";
|
|
3
|
+
//#region src/service-factory.ts
|
|
4
|
+
async function n(n) {
|
|
5
|
+
return new t(await e(n), n.openClawConfig);
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { n as createCloudflareMemoryService };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=service-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-factory.js","names":[],"sources":["../src/service-factory.ts"],"sourcesContent":["import type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { resolvePluginConfig } from \"./config.js\";\nimport { CloudflareMemoryService } from \"./service.js\";\n\nexport async function createCloudflareMemoryService(params: {\n\tpluginConfig: unknown;\n\topenClawConfig: OpenClawConfig;\n\tenv?: NodeJS.ProcessEnv;\n\tresolvePath?: (input: string) => string;\n}): Promise<CloudflareMemoryService> {\n\tconst resolved = await resolvePluginConfig(params);\n\treturn new CloudflareMemoryService(resolved, params.openClawConfig);\n}\n"],"mappings":";;;AAIA,eAAsB,EAA8B,GAKf;AAEpC,QAAO,IAAI,EADM,MAAM,EAAoB,EAAO,EACL,EAAO,eAAe"}
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { resolveDefaultNamespace as e } from "./namespace.js";
|
|
2
|
+
import { isCloudflareNotFoundError as t } from "./cloudflare-api.js";
|
|
3
|
+
import { CompanionStore as n } from "./companion-store.js";
|
|
4
|
+
import { runDoctor as r } from "./doctor.js";
|
|
5
|
+
import { WorkersAiEmbeddingsClient as i } from "./embeddings-client.js";
|
|
6
|
+
import { hydrateInlineRecord as a, mapRecordForUpsert as o } from "./record-mapper.js";
|
|
7
|
+
import { VectorizeClient as s } from "./vectorize-client.js";
|
|
8
|
+
//#region src/service.ts
|
|
9
|
+
var c = class {
|
|
10
|
+
embeddings;
|
|
11
|
+
vectorize;
|
|
12
|
+
companionStore;
|
|
13
|
+
constructor(e, t) {
|
|
14
|
+
this.config = e, this.openClawConfig = t, this.embeddings = new i(e), this.vectorize = new s(e), this.companionStore = new n(e.companionStorePath);
|
|
15
|
+
}
|
|
16
|
+
resolveNamespace(t) {
|
|
17
|
+
return e({
|
|
18
|
+
fixedNamespace: t.namespace ?? this.config.fixedNamespace,
|
|
19
|
+
sessionKey: t.sessionKey,
|
|
20
|
+
agentId: t.agentId,
|
|
21
|
+
workspaceDir: t.workspaceDir
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
async search(e) {
|
|
25
|
+
let t = this.resolveNamespace(e), n = await this.embeddings.embedQuery(e.query), r = await this.vectorize.query({
|
|
26
|
+
vector: n,
|
|
27
|
+
namespace: t,
|
|
28
|
+
topK: e.maxResults ?? this.config.topK,
|
|
29
|
+
filter: e.filter
|
|
30
|
+
});
|
|
31
|
+
return (await Promise.all(r.map(async (e) => {
|
|
32
|
+
let t = a(e), n = t.text ?? (await this.companionStore.get(t.namespace, t.logicalId))?.text ?? "";
|
|
33
|
+
return {
|
|
34
|
+
...t,
|
|
35
|
+
text: n,
|
|
36
|
+
score: e.score ?? 0
|
|
37
|
+
};
|
|
38
|
+
}))).filter((t) => t.score >= (e.minScore ?? this.config.minScore));
|
|
39
|
+
}
|
|
40
|
+
async get(e) {
|
|
41
|
+
let t = `${this.resolveNamespace(e)}::${e.id}`, [n] = await this.vectorize.getByIds([t]);
|
|
42
|
+
if (!n) return null;
|
|
43
|
+
let r = a(n), i = await this.companionStore.get(r.namespace, r.logicalId);
|
|
44
|
+
return {
|
|
45
|
+
...r,
|
|
46
|
+
text: r.text ?? i?.text ?? ""
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async upsert(e) {
|
|
50
|
+
let t = this.resolveNamespace({
|
|
51
|
+
namespace: e.input.namespace,
|
|
52
|
+
sessionKey: e.sessionKey,
|
|
53
|
+
agentId: e.agentId,
|
|
54
|
+
workspaceDir: e.workspaceDir
|
|
55
|
+
}), n = await this.embeddings.embedQuery(e.input.text), r = o({
|
|
56
|
+
input: e.input,
|
|
57
|
+
namespace: t,
|
|
58
|
+
embedding: n,
|
|
59
|
+
config: this.config
|
|
60
|
+
});
|
|
61
|
+
r.companionRecord && await this.companionStore.upsert(r.companionRecord);
|
|
62
|
+
let i = await this.vectorize.upsert([r.vector]);
|
|
63
|
+
return {
|
|
64
|
+
...await this.get({
|
|
65
|
+
id: r.logicalId,
|
|
66
|
+
namespace: t
|
|
67
|
+
}) ?? this.fromCompanionFallback(r.companionRecord, r.logicalId, t, r.path),
|
|
68
|
+
mutationId: i
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async delete(e) {
|
|
72
|
+
let t = this.resolveNamespace(e);
|
|
73
|
+
return await this.companionStore.delete(t, e.id), this.vectorize.deleteByIds([`${t}::${e.id}`]);
|
|
74
|
+
}
|
|
75
|
+
async doctor(e) {
|
|
76
|
+
return r({
|
|
77
|
+
service: this,
|
|
78
|
+
createIndexIfMissing: e.createIndexIfMissing ?? !1
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async ensureIndexExists(e) {
|
|
82
|
+
try {
|
|
83
|
+
return {
|
|
84
|
+
created: !1,
|
|
85
|
+
dimensions: (await this.vectorize.describeIndex()).config.dimensions
|
|
86
|
+
};
|
|
87
|
+
} catch (n) {
|
|
88
|
+
if (!e || !t(n)) throw n;
|
|
89
|
+
let r = this.config.createIndex.dimensions ?? await this.embeddings.probeDimensions();
|
|
90
|
+
return await this.vectorize.createIndex(r), {
|
|
91
|
+
created: !0,
|
|
92
|
+
dimensions: r
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
fromCompanionFallback(e, t, n, r) {
|
|
97
|
+
return {
|
|
98
|
+
logicalId: t,
|
|
99
|
+
vectorId: `${n}::${t}`,
|
|
100
|
+
namespace: n,
|
|
101
|
+
title: e?.title,
|
|
102
|
+
text: e?.text ?? "",
|
|
103
|
+
metadata: e?.metadata ?? {},
|
|
104
|
+
source: e?.source,
|
|
105
|
+
createdAt: e?.createdAt,
|
|
106
|
+
updatedAt: e?.updatedAt,
|
|
107
|
+
path: r
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
//#endregion
|
|
112
|
+
export { c as CloudflareMemoryService };
|
|
113
|
+
|
|
114
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","names":[],"sources":["../src/service.ts"],"sourcesContent":["import type { OpenClawConfig } from \"openclaw/plugin-sdk/config-runtime\";\nimport { isCloudflareNotFoundError } from \"./cloudflare-api.js\";\nimport { CompanionStore } from \"./companion-store.js\";\nimport { runDoctor } from \"./doctor.js\";\nimport { WorkersAiEmbeddingsClient } from \"./embeddings-client.js\";\nimport { resolveDefaultNamespace } from \"./namespace.js\";\nimport { hydrateInlineRecord, mapRecordForUpsert } from \"./record-mapper.js\";\nimport type {\n\tCompanionRecord,\n\tDoctorReport,\n\tHydratedMemoryRecord,\n\tMemoryRecordInput,\n\tMetadataFilter,\n\tResolvedPluginConfig,\n\tUpsertedMemoryRecord,\n} from \"./types.js\";\nimport { VectorizeClient } from \"./vectorize-client.js\";\n\nexport class CloudflareMemoryService {\n\treadonly embeddings: WorkersAiEmbeddingsClient;\n\treadonly vectorize: VectorizeClient;\n\treadonly companionStore: CompanionStore;\n\n\tconstructor(\n\t\treadonly config: ResolvedPluginConfig,\n\t\treadonly openClawConfig: OpenClawConfig,\n\t) {\n\t\tthis.embeddings = new WorkersAiEmbeddingsClient(config);\n\t\tthis.vectorize = new VectorizeClient(config);\n\t\tthis.companionStore = new CompanionStore(config.companionStorePath);\n\t}\n\n\tresolveNamespace(params: { namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): string {\n\t\treturn resolveDefaultNamespace({\n\t\t\tfixedNamespace: params.namespace ?? this.config.fixedNamespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t}\n\n\tasync search(params: {\n\t\tquery: string;\n\t\tnamespace?: string;\n\t\tmaxResults?: number;\n\t\tminScore?: number;\n\t\tfilter?: MetadataFilter;\n\t\tsessionKey?: string;\n\t\tagentId?: string;\n\t\tworkspaceDir?: string;\n\t}): Promise<Array<HydratedMemoryRecord & { score: number }>> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vector = await this.embeddings.embedQuery(params.query);\n\t\tconst matches = await this.vectorize.query({\n\t\t\tvector,\n\t\t\tnamespace,\n\t\t\ttopK: params.maxResults ?? this.config.topK,\n\t\t\tfilter: params.filter,\n\t\t});\n\n\t\tconst hydrated = await Promise.all(\n\t\t\tmatches.map(async (match) => {\n\t\t\t\tconst base = hydrateInlineRecord(match);\n\t\t\t\tconst text = base.text ?? (await this.companionStore.get(base.namespace, base.logicalId))?.text ?? \"\";\n\t\t\t\treturn {\n\t\t\t\t\t...base,\n\t\t\t\t\ttext,\n\t\t\t\t\tscore: match.score ?? 0,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn hydrated.filter((record) => record.score >= (params.minScore ?? this.config.minScore));\n\t}\n\n\tasync get(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<HydratedMemoryRecord | null> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tconst vectorId = `${namespace}::${params.id}`;\n\t\tconst [match] = await this.vectorize.getByIds([vectorId]);\n\t\tif (!match) {\n\t\t\treturn null;\n\t\t}\n\t\tconst base = hydrateInlineRecord(match);\n\t\tconst companion = await this.companionStore.get(base.namespace, base.logicalId);\n\t\treturn {\n\t\t\t...base,\n\t\t\ttext: base.text ?? companion?.text ?? \"\",\n\t\t};\n\t}\n\n\tasync upsert(params: { input: MemoryRecordInput; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<UpsertedMemoryRecord> {\n\t\tconst namespace = this.resolveNamespace({\n\t\t\tnamespace: params.input.namespace,\n\t\t\tsessionKey: params.sessionKey,\n\t\t\tagentId: params.agentId,\n\t\t\tworkspaceDir: params.workspaceDir,\n\t\t});\n\t\tconst embedding = await this.embeddings.embedQuery(params.input.text);\n\t\tconst mapped = mapRecordForUpsert({\n\t\t\tinput: params.input,\n\t\t\tnamespace,\n\t\t\tembedding,\n\t\t\tconfig: this.config,\n\t\t});\n\n\t\tif (mapped.companionRecord) {\n\t\t\tawait this.companionStore.upsert(mapped.companionRecord);\n\t\t}\n\n\t\tconst mutationId = await this.vectorize.upsert([mapped.vector]);\n\t\tconst hydrated = await this.get({\n\t\t\tid: mapped.logicalId,\n\t\t\tnamespace,\n\t\t});\n\n\t\treturn {\n\t\t\t...(hydrated ?? this.fromCompanionFallback(mapped.companionRecord, mapped.logicalId, namespace, mapped.path)),\n\t\t\tmutationId,\n\t\t};\n\t}\n\n\tasync delete(params: { id: string; namespace?: string; sessionKey?: string; agentId?: string; workspaceDir?: string }): Promise<string | undefined> {\n\t\tconst namespace = this.resolveNamespace(params);\n\t\tawait this.companionStore.delete(namespace, params.id);\n\t\treturn this.vectorize.deleteByIds([`${namespace}::${params.id}`]);\n\t}\n\n\tasync doctor(options: { createIndexIfMissing?: boolean }): Promise<DoctorReport> {\n\t\treturn runDoctor({\n\t\t\tservice: this,\n\t\t\tcreateIndexIfMissing: options.createIndexIfMissing ?? false,\n\t\t});\n\t}\n\n\tasync ensureIndexExists(createIfMissing: boolean): Promise<{ created: boolean; dimensions: number }> {\n\t\ttry {\n\t\t\tconst description = await this.vectorize.describeIndex();\n\t\t\treturn {\n\t\t\t\tcreated: false,\n\t\t\t\tdimensions: description.config.dimensions,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (!createIfMissing || !isCloudflareNotFoundError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tconst dimensions = this.config.createIndex.dimensions ?? (await this.embeddings.probeDimensions());\n\t\t\tawait this.vectorize.createIndex(dimensions);\n\t\t\treturn {\n\t\t\t\tcreated: true,\n\t\t\t\tdimensions,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate fromCompanionFallback(companionRecord: CompanionRecord | undefined, logicalId: string, namespace: string, path: string): UpsertedMemoryRecord {\n\t\treturn {\n\t\t\tlogicalId,\n\t\t\tvectorId: `${namespace}::${logicalId}`,\n\t\t\tnamespace,\n\t\t\ttitle: companionRecord?.title,\n\t\t\ttext: companionRecord?.text ?? \"\",\n\t\t\tmetadata: companionRecord?.metadata ?? {},\n\t\t\tsource: companionRecord?.source,\n\t\t\tcreatedAt: companionRecord?.createdAt,\n\t\t\tupdatedAt: companionRecord?.updatedAt,\n\t\t\tpath,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|