From 9133422c6aed02da7ccaa294ae0288c42ceb19fb Mon Sep 17 00:00:00 2001 From: Dimon Date: Sun, 17 May 2026 02:41:20 +0800 Subject: [PATCH] feat(package): expose host-neutral library entrypoints Add typed package subpaths for core and config consumers while keeping the OpenClaw plugin available through the published runtime artifact. Remove stale package metadata that referenced missing CLI script outputs so npm pack and the package size guard can validate the publishable tarball. Signed-off-by: Dimon --- README.md | 31 +++++++++++++++++++++++++ README_CN.md | 30 ++++++++++++++++++++++++ package.json | 34 ++++++++++++--------------- src/core/index.ts | 18 +++++++++++++++ src/core/package-metadata.test.ts | 25 ++++++++++++++++++++ src/core/public-exports.test.ts | 38 +++++++++++++++++++++++++++++++ tsdown.config.ts | 8 +++++-- 7 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 src/core/package-metadata.test.ts create mode 100644 src/core/public-exports.test.ts diff --git a/README.md b/README.md index d8a1ec9..0d5bd4e 100644 --- a/README.md +++ b/README.md @@ -334,6 +334,37 @@ Debugging no longer means probing an opaque database — it becomes a determinis | Hybrid retrieval | BM25 + vector + RRF — supports both keyword and semantic recall | | Agent tools | `tdai_memory_search` / `tdai_conversation_search` | +### Library Mode for Non-OpenClaw Hosts + +OpenClaw remains the default plugin entry point, but host-neutral embedders can +use the same core without depending on OpenClaw runtime APIs: + +```ts +import { TdaiCore, parseConfig } from "@tencentdb-agent-memory/memory-tencentdb/core" +import type { + CompletedTurn, + HostAdapter, +} from "@tencentdb-agent-memory/memory-tencentdb/core" + +const config = parseConfig({ + capture: { enabled: true }, + extraction: { enabled: false }, +}) + +const core = new TdaiCore({ + hostAdapter, + config, +}) +await core.initialize() +``` + +`TdaiCore` obtains model execution through +`HostAdapter.getLLMRunnerFactory()`, so the constructor only needs the adapter +and parsed config. + +For configuration-only integrations, import the parser from +`@tencentdb-agent-memory/memory-tencentdb/config`. + --- ## Documentation diff --git a/README_CN.md b/README_CN.md index 8698126..fd153ac 100644 --- a/README_CN.md +++ b/README_CN.md @@ -340,6 +340,36 @@ docker exec -it hermes-memory hermes | 混合检索 | BM25 + 向量 + RRF,兼顾关键词和语义召回 | | Agent 工具 | `tdai_memory_search` / `tdai_conversation_search` | +### 非 OpenClaw 宿主的 Library Mode + +OpenClaw 仍然是默认插件入口,但其他宿主可以复用同一套 +host-neutral core,而不需要依赖 OpenClaw runtime API: + +```ts +import { TdaiCore, parseConfig } from "@tencentdb-agent-memory/memory-tencentdb/core" +import type { + CompletedTurn, + HostAdapter, +} from "@tencentdb-agent-memory/memory-tencentdb/core" + +const config = parseConfig({ + capture: { enabled: true }, + extraction: { enabled: false }, +}) + +const core = new TdaiCore({ + hostAdapter, + config, +}) +await core.initialize() +``` + +`TdaiCore` 通过 `HostAdapter.getLLMRunnerFactory()` 获取模型执行器, +所以构造函数只需要 adapter 和解析后的 config。 + +如果只需要配置解析,可以从 +`@tencentdb-agent-memory/memory-tencentdb/config` 导入 `parseConfig`。 + --- ## 文档 diff --git a/package.json b/package.json index 2d74158..eaffc47 100644 --- a/package.json +++ b/package.json @@ -4,28 +4,28 @@ "description": "Four-layer local memory system plugin for OpenClaw — auto-captures, structures, and profiles conversational knowledge using local LLM + SQLite vector search (L0→L1→L2→L3 pipeline)", "type": "module", "main": "./dist/index.mjs", - "bin": { - "migrate-sqlite-to-tcvdb": "./bin/migrate-sqlite-to-tcvdb.mjs", - "export-tencent-vdb": "./bin/export-tencent-vdb.mjs", - "read-local-memory": "./bin/read-local-memory.mjs" - }, + "types": "./dist/index.d.mts", "exports": { ".": { + "types": "./dist/index.d.mts", "import": "./dist/index.mjs", "default": "./dist/index.mjs" + }, + "./core": { + "types": "./dist/core/index.d.mts", + "import": "./dist/core/index.mjs", + "default": "./dist/core/index.mjs" + }, + "./config": { + "types": "./dist/config.d.mts", + "import": "./dist/config.mjs", + "default": "./dist/config.mjs" } }, "scripts": { - "build": "npm run build:plugin && npm run build:scripts", + "build": "npm run build:plugin", "build:plugin": "tsdown", - "build:scripts": "npm run build:migrate-sqlite-to-vdb && npm run build:export-tencent-vdb && npm run build:read-local-memory", "prepack": "npm run build", - "build:migrate-sqlite-to-vdb": "tsc -p scripts/migrate-sqlite-to-tcvdb/tsconfig.json --noEmitOnError false", - "migrate-sqlite-to-tcvdb": "node ./bin/migrate-sqlite-to-tcvdb.mjs", - "build:export-tencent-vdb": "tsc --project scripts/export-tencent-vdb/tsconfig.json", - "export-tencent-vdb": "node ./bin/export-tencent-vdb.mjs", - "build:read-local-memory": "tsc --project scripts/read-local-memory/tsconfig.json", - "read-local-memory": "node ./bin/read-local-memory.mjs", "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", @@ -33,18 +33,14 @@ }, "files": [ "dist/", - "bin/", "index.ts", - "scripts/migrate-sqlite-to-tcvdb/dist/", - "scripts/export-tencent-vdb/dist/", - "scripts/read-local-memory/dist/", "scripts/memory-tencentdb-ctl.sh", "scripts/install_hermes_memory_tencentdb.sh", "scripts/README.memory-tencentdb-ctl.md", - "src/", "scripts/openclaw-after-tool-call-messages.patch.sh", "scripts/setup-offload.sh", "hermes-plugin/", + "!hermes-plugin/**/tests/", "openclaw.plugin.json", "README.md", "CHANGELOG.md", @@ -101,7 +97,7 @@ }, "openclaw": { "extensions": [ - "./index.ts" + "./dist/index.mjs" ], "compat": { "pluginApi": ">=2026.3.13", diff --git a/src/core/index.ts b/src/core/index.ts index a58b25a..8753f29 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -24,3 +24,21 @@ export type { // TdaiCore service facade export { TdaiCore } from "./tdai-core.js"; export type { TdaiCoreOptions } from "./tdai-core.js"; + +// Configuration parser used by host-neutral embedders. +export { parseConfig } from "../config.js"; +export type { + CaptureConfig, + EmbeddingConfig, + ExtractionConfig, + MemoryTdaiConfig, + BM25Config, + MemoryCleanupConfig, + OffloadConfig, + PersonaConfig, + PipelineTriggerConfig, + RecallConfig, + ReportConfig, + StandaloneLLMOverrideConfig, + TcvdbConfig, +} from "../config.js"; diff --git a/src/core/package-metadata.test.ts b/src/core/package-metadata.test.ts new file mode 100644 index 0000000..aad597a --- /dev/null +++ b/src/core/package-metadata.test.ts @@ -0,0 +1,25 @@ +import { existsSync } from "node:fs"; +import { resolve } from "node:path"; +import { describe, expect, it } from "vitest"; +import packageJson from "../../package.json" with { type: "json" }; + +const repoRoot = resolve(import.meta.dirname, "../.."); + +describe("npm package metadata", () => { + it("does not reference missing command-line binaries", () => { + for (const target of Object.values(packageJson.bin ?? {})) { + expect(existsSync(resolve(repoRoot, target))).toBe(true); + } + }); + + it("builds the publishable runtime without missing script tsconfigs", () => { + expect(packageJson.scripts.build).toBe("npm run build:plugin"); + expect(packageJson.scripts["build:scripts"]).toBeUndefined(); + }); + + it("publishes compiled runtime artifacts instead of duplicating source", () => { + expect(packageJson.files).toContain("dist/"); + expect(packageJson.files).not.toContain("src/"); + expect(packageJson.openclaw.extensions).toEqual(["./dist/index.mjs"]); + }); +}); diff --git a/src/core/public-exports.test.ts b/src/core/public-exports.test.ts new file mode 100644 index 0000000..91d5ac1 --- /dev/null +++ b/src/core/public-exports.test.ts @@ -0,0 +1,38 @@ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { describe, expect, it } from "vitest"; +import packageJson from "../../package.json" with { type: "json" }; +import { parseConfig, TdaiCore } from "./index.js"; + +const repoRoot = resolve(import.meta.dirname, "../.."); + +describe("library mode public exports", () => { + it("exposes host-neutral core and config subpaths", () => { + expect(packageJson.exports).toMatchObject({ + "./core": { + import: "./dist/core/index.mjs", + types: "./dist/core/index.d.mts", + }, + "./config": { + import: "./dist/config.mjs", + types: "./dist/config.d.mts", + }, + }); + }); + + it("keeps TdaiCore and parseConfig available from the core barrel", () => { + expect(typeof TdaiCore).toBe("function"); + expect(typeof parseConfig).toBe("function"); + expect(parseConfig({ extraction: { enabled: false } }).extraction.enabled).toBe(false); + }); + + it("documents TdaiCore construction through the HostAdapter contract", () => { + const readme = readFileSync(resolve(repoRoot, "README.md"), "utf8"); + const readmeCn = readFileSync(resolve(repoRoot, "README_CN.md"), "utf8"); + + expect(readme).not.toContain("llmRunnerFactory,"); + expect(readmeCn).not.toContain("llmRunnerFactory,"); + expect(readme).toContain("HostAdapter.getLLMRunnerFactory()"); + expect(readmeCn).toContain("HostAdapter.getLLMRunnerFactory()"); + }); +}); diff --git a/tsdown.config.ts b/tsdown.config.ts index 16b0073..eabbeeb 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -11,13 +11,17 @@ function collectExternalDependencies(): string[] { } export default defineConfig({ - entry: ["./index.ts"], + entry: { + index: "./index.ts", + "core/index": "./src/core/index.ts", + config: "./src/config.ts", + }, outDir: "./dist", format: "esm", platform: "node", clean: true, fixedExtension: true, - dts: false, + dts: true, sourcemap: false, deps: { neverBundle: (id) => {