dsh-tdai-memory 0.2.13 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +15 -13
  3. package/README.zh.md +9 -7
  4. package/THIRD-PARTY-NOTICES.md +20 -20
  5. package/client.js +21 -4
  6. package/cordis.patch.yml +8 -8
  7. package/index.js +36 -14
  8. package/package.json +77 -78
  9. package/recall-inject.js +86 -86
  10. package/vendor/tdai/adapters/index.js +15 -15
  11. package/vendor/tdai/adapters/openclaw/host-adapter.js +83 -83
  12. package/vendor/tdai/adapters/openclaw/index.js +5 -5
  13. package/vendor/tdai/adapters/openclaw/llm-runner.js +69 -69
  14. package/vendor/tdai/adapters/standalone/host-adapter.js +58 -58
  15. package/vendor/tdai/adapters/standalone/index.js +5 -5
  16. package/vendor/tdai/adapters/standalone/llm-runner.js +34 -6
  17. package/vendor/tdai/config.js +3 -0
  18. package/vendor/tdai/core/conversation/l0-recorder.js +420 -420
  19. package/vendor/tdai/core/hooks/auto-capture.js +236 -236
  20. package/vendor/tdai/core/hooks/auto-recall.js +640 -640
  21. package/vendor/tdai/core/index.js +8 -8
  22. package/vendor/tdai/core/persona/persona-generator.js +184 -184
  23. package/vendor/tdai/core/persona/persona-trigger.js +94 -94
  24. package/vendor/tdai/core/profile/profile-sync.js +200 -200
  25. package/vendor/tdai/core/prompts/l1-dedup.js +72 -72
  26. package/vendor/tdai/core/prompts/l1-extraction.js +34 -34
  27. package/vendor/tdai/core/prompts/persona-generation.js +35 -35
  28. package/vendor/tdai/core/prompts/scene-extraction.js +45 -45
  29. package/vendor/tdai/core/record/l1-dedup.js +318 -318
  30. package/vendor/tdai/core/record/l1-extractor.js +379 -379
  31. package/vendor/tdai/core/record/l1-reader.js +178 -178
  32. package/vendor/tdai/core/record/l1-writer.js +141 -141
  33. package/vendor/tdai/core/report/reporter.js +86 -86
  34. package/vendor/tdai/core/scene/filename-normalizer.js +161 -161
  35. package/vendor/tdai/core/scene/scene-extractor.js +410 -410
  36. package/vendor/tdai/core/scene/scene-format.js +53 -53
  37. package/vendor/tdai/core/scene/scene-index.js +82 -82
  38. package/vendor/tdai/core/scene/scene-navigation.js +57 -57
  39. package/vendor/tdai/core/seed/input.js +404 -404
  40. package/vendor/tdai/core/seed/seed-runtime.js +4 -0
  41. package/vendor/tdai/core/seed/types.js +9 -9
  42. package/vendor/tdai/core/store/bm25-client.js +117 -117
  43. package/vendor/tdai/core/store/bm25-local.js +68 -68
  44. package/vendor/tdai/core/store/embedding.js +632 -632
  45. package/vendor/tdai/core/store/factory.js +95 -95
  46. package/vendor/tdai/core/store/search-utils.js +54 -54
  47. package/vendor/tdai/core/store/sqlite.js +1632 -1632
  48. package/vendor/tdai/core/store/tcvdb-client.js +221 -221
  49. package/vendor/tdai/core/store/tcvdb.js +1047 -1047
  50. package/vendor/tdai/core/store/types.js +17 -17
  51. package/vendor/tdai/core/tdai-core.js +4 -0
  52. package/vendor/tdai/core/tools/conversation-search.js +199 -199
  53. package/vendor/tdai/core/tools/memory-search.js +207 -207
  54. package/vendor/tdai/core/types.js +12 -12
  55. package/vendor/tdai/utils/backup.js +189 -189
  56. package/vendor/tdai/utils/checkpoint.js +360 -360
  57. package/vendor/tdai/utils/clean-context-runner.js +472 -472
  58. package/vendor/tdai/utils/ensure-hook-policy.js +213 -213
  59. package/vendor/tdai/utils/env.js +13 -13
  60. package/vendor/tdai/utils/managed-timer.js +127 -127
  61. package/vendor/tdai/utils/manifest.js +91 -91
  62. package/vendor/tdai/utils/memory-cleaner.js +300 -300
  63. package/vendor/tdai/utils/no-think-fetch.js +109 -109
  64. package/vendor/tdai/utils/openclaw-state-dir.js +26 -26
  65. package/vendor/tdai/utils/pipeline-factory.js +517 -517
  66. package/vendor/tdai/utils/pipeline-manager.js +892 -892
  67. package/vendor/tdai/utils/sanitize.js +360 -360
  68. package/vendor/tdai/utils/serial-queue.js +103 -103
  69. package/vendor/tdai/utils/session-filter.js +88 -88
  70. package/vendor/tdai/utils/session-header-fetch.js +88 -0
  71. package/vendor/tdai/utils/text-utils.js +29 -29
  72. package/vendor/tdai/utils/time.js +252 -252
package/recall-inject.js CHANGED
@@ -1,86 +1,86 @@
1
- /**
2
- * tdai-recall-inject — agent-plane recall injection row for dsh-tdai-memory.
3
- *
4
- * Mounted INSIDE an agent preset (agent.cordis.yml), this row listens on the
5
- * `system-prompt/assemble` waterfall in the preset's scope, so it runs for
6
- * every assembly of every agent joined to that preset (agent -> preset scope
7
- * chain). It asks the `tdaiMemory` service (provided by the root-level
8
- * dsh-tdai-memory plugin) for relevant long-term memories and appends them
9
- * as dynamic context sections (user-role snapshots):
10
- *
11
- * - tdai:recall — relevant L1 memories for the current user message
12
- * - tdai:profile — stable persona / scene navigation context
13
- *
14
- * The recall call is bounded by `recall.timeoutMs`; failures degrade to no
15
- * injection and never break the assembly.
16
- */
17
- import z from "@deepseek-ai/schemastery";
18
-
19
- /** Cordis plugin name. */
20
- const name = "tdai-recall-inject";
21
- /** Services consumed: the prompt registry and the memory core service. */
22
- const inject = ["systemPrompt", "tdaiMemory"];
23
-
24
- /** Runtime schema for the recall-inject row. */
25
- const Config = z.object({
26
- /** Skip recall when the user message is shorter than this. */
27
- minUserTextChars: z.number().default(1),
28
- /** Per-session cache TTL for identical user text (ms). */
29
- cacheTtlMs: z.number().default(30_000),
30
- });
31
-
32
- function apply(ctx, config) {
33
- const cache = new Map();
34
-
35
- ctx.on("system-prompt/assemble", async (assembly, context) => {
36
- try {
37
- const agent = context?.agent;
38
- if (!agent) return assembly;
39
- const session = agent.session;
40
- if (!session) return assembly;
41
- // Only real human input triggers recall. DSH injects synthetic
42
- // user-role context (system reminders, runtime context, skill
43
- // catalogs, …) whose source.kind is not "user"; recalling on those
44
- // would pollute the prompt with irrelevant memories (issue #1).
45
- const lastUser = [...session.deriveMessages()]
46
- .reverse()
47
- .find((m) => m.role === "user" && (m.source == null || m.source.kind === "user"));
48
- if (!lastUser) return assembly;
49
- const text = extractText(lastUser.content);
50
- if (!text || text.length < config.minUserTextChars) return assembly;
51
-
52
- const now = Date.now();
53
- const cached = cache.get(session.id);
54
- if (cached && cached.text === text && now - cached.ts < config.cacheTtlMs) {
55
- return injectRecall(assembly, cached.result);
56
- }
57
- const result = await ctx.tdaiMemory
58
- .handleBeforeRecall(text, session.id)
59
- .catch(() => null);
60
- cache.set(session.id, { text, result: result ?? {}, ts: now });
61
- return injectRecall(assembly, result ?? {});
62
- } catch {
63
- return assembly;
64
- }
65
- });
66
- }
67
-
68
- function extractText(content) {
69
- if (typeof content === "string") return content.trim();
70
- if (!Array.isArray(content)) return "";
71
- return content
72
- .filter((b) => b && b.type === "text" && typeof b.text === "string")
73
- .map((b) => b.text)
74
- .join("\n")
75
- .trim();
76
- }
77
-
78
- function injectRecall(assembly, result) {
79
- const extras = [];
80
- if (result.prependContext) extras.push({ name: "tdai:recall", order: 1000, text: result.prependContext });
81
- if (result.appendSystemContext) extras.push({ name: "tdai:profile", order: 1001, text: result.appendSystemContext });
82
- if (extras.length === 0) return assembly;
83
- return { ...assembly, contexts: [...assembly.contexts, ...extras] };
84
- }
85
-
86
- export { Config, apply, inject, name };
1
+ /**
2
+ * tdai-recall-inject — agent-plane recall injection row for dsh-tdai-memory.
3
+ *
4
+ * Mounted INSIDE an agent preset (agent.cordis.yml), this row listens on the
5
+ * `system-prompt/assemble` waterfall in the preset's scope, so it runs for
6
+ * every assembly of every agent joined to that preset (agent -> preset scope
7
+ * chain). It asks the `tdaiMemory` service (provided by the root-level
8
+ * dsh-tdai-memory plugin) for relevant long-term memories and appends them
9
+ * as dynamic context sections (user-role snapshots):
10
+ *
11
+ * - tdai:recall — relevant L1 memories for the current user message
12
+ * - tdai:profile — stable persona / scene navigation context
13
+ *
14
+ * The recall call is bounded by `recall.timeoutMs`; failures degrade to no
15
+ * injection and never break the assembly.
16
+ */
17
+ import z from "@deepseek-ai/schemastery";
18
+
19
+ /** Cordis plugin name. */
20
+ const name = "tdai-recall-inject";
21
+ /** Services consumed: the prompt registry and the memory core service. */
22
+ const inject = ["systemPrompt", "tdaiMemory"];
23
+
24
+ /** Runtime schema for the recall-inject row. */
25
+ const Config = z.object({
26
+ /** Skip recall when the user message is shorter than this. */
27
+ minUserTextChars: z.number().default(1),
28
+ /** Per-session cache TTL for identical user text (ms). */
29
+ cacheTtlMs: z.number().default(30_000),
30
+ });
31
+
32
+ function apply(ctx, config) {
33
+ const cache = new Map();
34
+
35
+ ctx.on("system-prompt/assemble", async (assembly, context) => {
36
+ try {
37
+ const agent = context?.agent;
38
+ if (!agent) return assembly;
39
+ const session = agent.session;
40
+ if (!session) return assembly;
41
+ // Only real human input triggers recall. DSH injects synthetic
42
+ // user-role context (system reminders, runtime context, skill
43
+ // catalogs, …) whose source.kind is not "user"; recalling on those
44
+ // would pollute the prompt with irrelevant memories (issue #1).
45
+ const lastUser = [...session.deriveMessages()]
46
+ .reverse()
47
+ .find((m) => m.role === "user" && (m.source == null || m.source.kind === "user"));
48
+ if (!lastUser) return assembly;
49
+ const text = extractText(lastUser.content);
50
+ if (!text || text.length < config.minUserTextChars) return assembly;
51
+
52
+ const now = Date.now();
53
+ const cached = cache.get(session.id);
54
+ if (cached && cached.text === text && now - cached.ts < config.cacheTtlMs) {
55
+ return injectRecall(assembly, cached.result);
56
+ }
57
+ const result = await ctx.tdaiMemory
58
+ .handleBeforeRecall(text, session.id)
59
+ .catch(() => null);
60
+ cache.set(session.id, { text, result: result ?? {}, ts: now });
61
+ return injectRecall(assembly, result ?? {});
62
+ } catch {
63
+ return assembly;
64
+ }
65
+ });
66
+ }
67
+
68
+ function extractText(content) {
69
+ if (typeof content === "string") return content.trim();
70
+ if (!Array.isArray(content)) return "";
71
+ return content
72
+ .filter((b) => b && b.type === "text" && typeof b.text === "string")
73
+ .map((b) => b.text)
74
+ .join("\n")
75
+ .trim();
76
+ }
77
+
78
+ function injectRecall(assembly, result) {
79
+ const extras = [];
80
+ if (result.prependContext) extras.push({ name: "tdai:recall", order: 1000, text: result.prependContext });
81
+ if (result.appendSystemContext) extras.push({ name: "tdai:profile", order: 1001, text: result.appendSystemContext });
82
+ if (extras.length === 0) return assembly;
83
+ return { ...assembly, contexts: [...assembly.contexts, ...extras] };
84
+ }
85
+
86
+ export { Config, apply, inject, name };
@@ -1,15 +1,15 @@
1
- /**
2
- * TDAI Adapters — barrel re-export for all host adapter implementations.
3
- *
4
- * Each adapter translates a specific host environment's API into
5
- * the host-neutral HostAdapter interface consumed by TdaiCore.
6
- *
7
- * Directory structure:
8
- * adapters/
9
- * ├── openclaw/ — OpenClaw plugin host (in-process, runEmbeddedPiAgent)
10
- * └── standalone/ — Gateway / Hermes sidecar (HTTP, OpenAI-compatible API)
11
- */
12
- // OpenClaw adapter
13
- export { OpenClawHostAdapter, OpenClawLLMRunner, OpenClawLLMRunnerFactory } from "./openclaw/index.js";
14
- // Standalone adapter
15
- export { StandaloneHostAdapter, StandaloneLLMRunner, StandaloneLLMRunnerFactory } from "./standalone/index.js";
1
+ /**
2
+ * TDAI Adapters — barrel re-export for all host adapter implementations.
3
+ *
4
+ * Each adapter translates a specific host environment's API into
5
+ * the host-neutral HostAdapter interface consumed by TdaiCore.
6
+ *
7
+ * Directory structure:
8
+ * adapters/
9
+ * ├── openclaw/ — OpenClaw plugin host (in-process, runEmbeddedPiAgent)
10
+ * └── standalone/ — Gateway / Hermes sidecar (HTTP, OpenAI-compatible API)
11
+ */
12
+ // OpenClaw adapter
13
+ export { OpenClawHostAdapter, OpenClawLLMRunner, OpenClawLLMRunnerFactory } from "./openclaw/index.js";
14
+ // Standalone adapter
15
+ export { StandaloneHostAdapter, StandaloneLLMRunner, StandaloneLLMRunnerFactory } from "./standalone/index.js";
@@ -1,83 +1,83 @@
1
- /**
2
- * OpenClawHostAdapter — translates OpenClaw's plugin API into TDAI Core's
3
- * unified HostAdapter interface.
4
- *
5
- * This is the "thin shell" that keeps OpenClaw-specific dependencies
6
- * (OpenClawPluginApi, pluginConfig, resolveStateDir, event system)
7
- * confined to the adapter layer while TDAI Core remains host-neutral.
8
- *
9
- * Usage (in index.ts):
10
- * const adapter = new OpenClawHostAdapter({ api, pluginDataDir, config });
11
- * const core = new TdaiCore({ hostAdapter: adapter, config: parsedConfig });
12
- */
13
- import { OpenClawLLMRunnerFactory } from "./llm-runner.js";
14
- // ============================
15
- // OpenClawHostAdapter
16
- // ============================
17
- export class OpenClawHostAdapter {
18
- hostType = "openclaw";
19
- api;
20
- pluginDataDir;
21
- openclawConfig;
22
- runnerFactory;
23
- constructor(opts) {
24
- this.api = opts.api;
25
- this.pluginDataDir = opts.pluginDataDir;
26
- this.openclawConfig = opts.openclawConfig;
27
- this.runnerFactory = new OpenClawLLMRunnerFactory({
28
- config: opts.openclawConfig,
29
- agentRuntime: opts.api.runtime.agent,
30
- logger: opts.api.logger,
31
- });
32
- }
33
- /**
34
- * Build a RuntimeContext from the current OpenClaw session.
35
- *
36
- * In OpenClaw, sessionKey and sessionId come from the event/ctx objects
37
- * passed to hooks. This method returns a context with sensible defaults;
38
- * callers can override sessionKey/sessionId per-hook invocation using
39
- * `buildRuntimeContextForSession()`.
40
- */
41
- getRuntimeContext() {
42
- return {
43
- userId: "default_user",
44
- sessionId: "",
45
- sessionKey: "",
46
- platform: "openclaw",
47
- workspaceDir: process.cwd(),
48
- dataDir: this.pluginDataDir,
49
- };
50
- }
51
- /**
52
- * Build a RuntimeContext for a specific session (used per-hook).
53
- *
54
- * This is an OpenClaw-specific convenience that merges session-level
55
- * identifiers from hook ctx into the base context.
56
- */
57
- buildRuntimeContextForSession(sessionKey, sessionId) {
58
- return {
59
- ...this.getRuntimeContext(),
60
- sessionKey,
61
- sessionId: sessionId ?? "",
62
- };
63
- }
64
- getLogger() {
65
- return this.api.logger;
66
- }
67
- getLLMRunnerFactory() {
68
- return this.runnerFactory;
69
- }
70
- // -- OpenClaw-specific accessors (for index.ts bridge) --------------------
71
- /** Get the raw OpenClaw plugin API (for legacy callers during migration). */
72
- getPluginApi() {
73
- return this.api;
74
- }
75
- /** Get the OpenClaw config object (for legacy callers during migration). */
76
- getOpenClawConfig() {
77
- return this.openclawConfig;
78
- }
79
- /** Get the resolved plugin data directory. */
80
- getPluginDataDir() {
81
- return this.pluginDataDir;
82
- }
83
- }
1
+ /**
2
+ * OpenClawHostAdapter — translates OpenClaw's plugin API into TDAI Core's
3
+ * unified HostAdapter interface.
4
+ *
5
+ * This is the "thin shell" that keeps OpenClaw-specific dependencies
6
+ * (OpenClawPluginApi, pluginConfig, resolveStateDir, event system)
7
+ * confined to the adapter layer while TDAI Core remains host-neutral.
8
+ *
9
+ * Usage (in index.ts):
10
+ * const adapter = new OpenClawHostAdapter({ api, pluginDataDir, config });
11
+ * const core = new TdaiCore({ hostAdapter: adapter, config: parsedConfig });
12
+ */
13
+ import { OpenClawLLMRunnerFactory } from "./llm-runner.js";
14
+ // ============================
15
+ // OpenClawHostAdapter
16
+ // ============================
17
+ export class OpenClawHostAdapter {
18
+ hostType = "openclaw";
19
+ api;
20
+ pluginDataDir;
21
+ openclawConfig;
22
+ runnerFactory;
23
+ constructor(opts) {
24
+ this.api = opts.api;
25
+ this.pluginDataDir = opts.pluginDataDir;
26
+ this.openclawConfig = opts.openclawConfig;
27
+ this.runnerFactory = new OpenClawLLMRunnerFactory({
28
+ config: opts.openclawConfig,
29
+ agentRuntime: opts.api.runtime.agent,
30
+ logger: opts.api.logger,
31
+ });
32
+ }
33
+ /**
34
+ * Build a RuntimeContext from the current OpenClaw session.
35
+ *
36
+ * In OpenClaw, sessionKey and sessionId come from the event/ctx objects
37
+ * passed to hooks. This method returns a context with sensible defaults;
38
+ * callers can override sessionKey/sessionId per-hook invocation using
39
+ * `buildRuntimeContextForSession()`.
40
+ */
41
+ getRuntimeContext() {
42
+ return {
43
+ userId: "default_user",
44
+ sessionId: "",
45
+ sessionKey: "",
46
+ platform: "openclaw",
47
+ workspaceDir: process.cwd(),
48
+ dataDir: this.pluginDataDir,
49
+ };
50
+ }
51
+ /**
52
+ * Build a RuntimeContext for a specific session (used per-hook).
53
+ *
54
+ * This is an OpenClaw-specific convenience that merges session-level
55
+ * identifiers from hook ctx into the base context.
56
+ */
57
+ buildRuntimeContextForSession(sessionKey, sessionId) {
58
+ return {
59
+ ...this.getRuntimeContext(),
60
+ sessionKey,
61
+ sessionId: sessionId ?? "",
62
+ };
63
+ }
64
+ getLogger() {
65
+ return this.api.logger;
66
+ }
67
+ getLLMRunnerFactory() {
68
+ return this.runnerFactory;
69
+ }
70
+ // -- OpenClaw-specific accessors (for index.ts bridge) --------------------
71
+ /** Get the raw OpenClaw plugin API (for legacy callers during migration). */
72
+ getPluginApi() {
73
+ return this.api;
74
+ }
75
+ /** Get the OpenClaw config object (for legacy callers during migration). */
76
+ getOpenClawConfig() {
77
+ return this.openclawConfig;
78
+ }
79
+ /** Get the resolved plugin data directory. */
80
+ getPluginDataDir() {
81
+ return this.pluginDataDir;
82
+ }
83
+ }
@@ -1,5 +1,5 @@
1
- /**
2
- * OpenClaw adapter — barrel exports.
3
- */
4
- export { OpenClawHostAdapter } from "./host-adapter.js";
5
- export { OpenClawLLMRunner, OpenClawLLMRunnerFactory } from "./llm-runner.js";
1
+ /**
2
+ * OpenClaw adapter — barrel exports.
3
+ */
4
+ export { OpenClawHostAdapter } from "./host-adapter.js";
5
+ export { OpenClawLLMRunner, OpenClawLLMRunnerFactory } from "./llm-runner.js";
@@ -1,69 +1,69 @@
1
- /**
2
- * OpenClawLLMRunner — wraps the existing CleanContextRunner as a host-neutral LLMRunner.
3
- *
4
- * This is a compatibility bridge: TDAI Core modules (L1 extractor, L2 scene extractor,
5
- * L3 persona generator, L1 dedup) can depend on the `LLMRunner` interface, while
6
- * OpenClaw continues to use its native `runEmbeddedPiAgent` mechanism under the hood.
7
- *
8
- * Usage:
9
- * const factory = new OpenClawLLMRunnerFactory({ config, agentRuntime, logger });
10
- * const runner = factory.createRunner({ modelRef: "openai/gpt-4o", enableTools: true });
11
- * const result = await runner.run({ prompt: "...", taskId: "l1-extraction" });
12
- */
13
- import { CleanContextRunner } from "../../utils/clean-context-runner.js";
14
- const TAG = "[memory-tdai] [openclaw-runner]";
15
- // ============================
16
- // OpenClawLLMRunner
17
- // ============================
18
- /**
19
- * LLMRunner implementation backed by CleanContextRunner.
20
- *
21
- * Each instance is configured with a fixed model + tools setting.
22
- * Create via `OpenClawLLMRunnerFactory.createRunner()`.
23
- */
24
- export class OpenClawLLMRunner {
25
- runner;
26
- constructor(runner) {
27
- this.runner = runner;
28
- }
29
- async run(params) {
30
- return this.runner.run({
31
- prompt: params.prompt,
32
- systemPrompt: params.systemPrompt,
33
- taskId: params.taskId,
34
- timeoutMs: params.timeoutMs,
35
- maxTokens: params.maxTokens,
36
- workspaceDir: params.workspaceDir,
37
- instanceId: params.instanceId,
38
- });
39
- }
40
- }
41
- /**
42
- * Factory that creates OpenClawLLMRunner instances.
43
- *
44
- * Encapsulates the OpenClaw-specific dependencies (config, agentRuntime)
45
- * so that callers only need to specify model + tools.
46
- */
47
- export class OpenClawLLMRunnerFactory {
48
- config;
49
- agentRuntime;
50
- logger;
51
- constructor(opts) {
52
- this.config = opts.config;
53
- this.agentRuntime = opts.agentRuntime;
54
- this.logger = opts.logger;
55
- }
56
- createRunner(opts) {
57
- const enableTools = opts?.enableTools ?? false;
58
- const modelRef = opts?.modelRef;
59
- this.logger?.debug?.(`${TAG} Creating OpenClawLLMRunner: model=${modelRef ?? "(default)"}, tools=${enableTools}`);
60
- const cleanRunner = new CleanContextRunner({
61
- config: this.config,
62
- modelRef,
63
- enableTools,
64
- agentRuntime: this.agentRuntime,
65
- logger: this.logger,
66
- });
67
- return new OpenClawLLMRunner(cleanRunner);
68
- }
69
- }
1
+ /**
2
+ * OpenClawLLMRunner — wraps the existing CleanContextRunner as a host-neutral LLMRunner.
3
+ *
4
+ * This is a compatibility bridge: TDAI Core modules (L1 extractor, L2 scene extractor,
5
+ * L3 persona generator, L1 dedup) can depend on the `LLMRunner` interface, while
6
+ * OpenClaw continues to use its native `runEmbeddedPiAgent` mechanism under the hood.
7
+ *
8
+ * Usage:
9
+ * const factory = new OpenClawLLMRunnerFactory({ config, agentRuntime, logger });
10
+ * const runner = factory.createRunner({ modelRef: "openai/gpt-4o", enableTools: true });
11
+ * const result = await runner.run({ prompt: "...", taskId: "l1-extraction" });
12
+ */
13
+ import { CleanContextRunner } from "../../utils/clean-context-runner.js";
14
+ const TAG = "[memory-tdai] [openclaw-runner]";
15
+ // ============================
16
+ // OpenClawLLMRunner
17
+ // ============================
18
+ /**
19
+ * LLMRunner implementation backed by CleanContextRunner.
20
+ *
21
+ * Each instance is configured with a fixed model + tools setting.
22
+ * Create via `OpenClawLLMRunnerFactory.createRunner()`.
23
+ */
24
+ export class OpenClawLLMRunner {
25
+ runner;
26
+ constructor(runner) {
27
+ this.runner = runner;
28
+ }
29
+ async run(params) {
30
+ return this.runner.run({
31
+ prompt: params.prompt,
32
+ systemPrompt: params.systemPrompt,
33
+ taskId: params.taskId,
34
+ timeoutMs: params.timeoutMs,
35
+ maxTokens: params.maxTokens,
36
+ workspaceDir: params.workspaceDir,
37
+ instanceId: params.instanceId,
38
+ });
39
+ }
40
+ }
41
+ /**
42
+ * Factory that creates OpenClawLLMRunner instances.
43
+ *
44
+ * Encapsulates the OpenClaw-specific dependencies (config, agentRuntime)
45
+ * so that callers only need to specify model + tools.
46
+ */
47
+ export class OpenClawLLMRunnerFactory {
48
+ config;
49
+ agentRuntime;
50
+ logger;
51
+ constructor(opts) {
52
+ this.config = opts.config;
53
+ this.agentRuntime = opts.agentRuntime;
54
+ this.logger = opts.logger;
55
+ }
56
+ createRunner(opts) {
57
+ const enableTools = opts?.enableTools ?? false;
58
+ const modelRef = opts?.modelRef;
59
+ this.logger?.debug?.(`${TAG} Creating OpenClawLLMRunner: model=${modelRef ?? "(default)"}, tools=${enableTools}`);
60
+ const cleanRunner = new CleanContextRunner({
61
+ config: this.config,
62
+ modelRef,
63
+ enableTools,
64
+ agentRuntime: this.agentRuntime,
65
+ logger: this.logger,
66
+ });
67
+ return new OpenClawLLMRunner(cleanRunner);
68
+ }
69
+ }
@@ -1,58 +1,58 @@
1
- /**
2
- * StandaloneHostAdapter — HostAdapter for the TDAI Gateway (Hermes sidecar).
3
- *
4
- * Does NOT depend on OpenClaw. Context is constructed from Gateway config
5
- * and per-request parameters (session_id, user_id, etc.).
6
- */
7
- import { StandaloneLLMRunnerFactory } from "./llm-runner.js";
8
- // ============================
9
- // StandaloneHostAdapter
10
- // ============================
11
- export class StandaloneHostAdapter {
12
- hostType = "standalone";
13
- dataDir;
14
- logger;
15
- runnerFactory;
16
- defaultUserId;
17
- platform;
18
- constructor(opts) {
19
- this.dataDir = opts.dataDir;
20
- this.logger = opts.logger;
21
- this.defaultUserId = opts.defaultUserId ?? "default_user";
22
- this.platform = opts.platform ?? "gateway";
23
- this.runnerFactory = new StandaloneLLMRunnerFactory({
24
- config: opts.llmConfig,
25
- logger: opts.logger,
26
- });
27
- }
28
- getRuntimeContext() {
29
- return {
30
- userId: this.defaultUserId,
31
- sessionId: "",
32
- sessionKey: "",
33
- platform: this.platform,
34
- workspaceDir: this.dataDir,
35
- dataDir: this.dataDir,
36
- };
37
- }
38
- /**
39
- * Build a RuntimeContext for a specific request.
40
- * Used by Gateway route handlers to scope each request to the correct user/session.
41
- */
42
- buildRuntimeContextForRequest(params) {
43
- return {
44
- userId: params.userId ?? this.defaultUserId,
45
- sessionId: params.sessionId ?? "",
46
- sessionKey: params.sessionKey ?? params.sessionId ?? "",
47
- platform: params.platform ?? this.platform,
48
- workspaceDir: this.dataDir,
49
- dataDir: this.dataDir,
50
- };
51
- }
52
- getLogger() {
53
- return this.logger;
54
- }
55
- getLLMRunnerFactory() {
56
- return this.runnerFactory;
57
- }
58
- }
1
+ /**
2
+ * StandaloneHostAdapter — HostAdapter for the TDAI Gateway (Hermes sidecar).
3
+ *
4
+ * Does NOT depend on OpenClaw. Context is constructed from Gateway config
5
+ * and per-request parameters (session_id, user_id, etc.).
6
+ */
7
+ import { StandaloneLLMRunnerFactory } from "./llm-runner.js";
8
+ // ============================
9
+ // StandaloneHostAdapter
10
+ // ============================
11
+ export class StandaloneHostAdapter {
12
+ hostType = "standalone";
13
+ dataDir;
14
+ logger;
15
+ runnerFactory;
16
+ defaultUserId;
17
+ platform;
18
+ constructor(opts) {
19
+ this.dataDir = opts.dataDir;
20
+ this.logger = opts.logger;
21
+ this.defaultUserId = opts.defaultUserId ?? "default_user";
22
+ this.platform = opts.platform ?? "gateway";
23
+ this.runnerFactory = new StandaloneLLMRunnerFactory({
24
+ config: opts.llmConfig,
25
+ logger: opts.logger,
26
+ });
27
+ }
28
+ getRuntimeContext() {
29
+ return {
30
+ userId: this.defaultUserId,
31
+ sessionId: "",
32
+ sessionKey: "",
33
+ platform: this.platform,
34
+ workspaceDir: this.dataDir,
35
+ dataDir: this.dataDir,
36
+ };
37
+ }
38
+ /**
39
+ * Build a RuntimeContext for a specific request.
40
+ * Used by Gateway route handlers to scope each request to the correct user/session.
41
+ */
42
+ buildRuntimeContextForRequest(params) {
43
+ return {
44
+ userId: params.userId ?? this.defaultUserId,
45
+ sessionId: params.sessionId ?? "",
46
+ sessionKey: params.sessionKey ?? params.sessionId ?? "",
47
+ platform: params.platform ?? this.platform,
48
+ workspaceDir: this.dataDir,
49
+ dataDir: this.dataDir,
50
+ };
51
+ }
52
+ getLogger() {
53
+ return this.logger;
54
+ }
55
+ getLLMRunnerFactory() {
56
+ return this.runnerFactory;
57
+ }
58
+ }
@@ -1,5 +1,5 @@
1
- /**
2
- * Standalone adapter — barrel exports.
3
- */
4
- export { StandaloneHostAdapter } from "./host-adapter.js";
5
- export { StandaloneLLMRunner, StandaloneLLMRunnerFactory } from "./llm-runner.js";
1
+ /**
2
+ * Standalone adapter — barrel exports.
3
+ */
4
+ export { StandaloneHostAdapter } from "./host-adapter.js";
5
+ export { StandaloneLLMRunner, StandaloneLLMRunnerFactory } from "./llm-runner.js";