feat: release v0.3.3 — Hermes adapter, context offload, core refactor

This commit is contained in:
chrishuan
2026-05-13 01:58:18 +08:00
parent a74b0b3e43
commit db8f3e516a
100 changed files with 29832 additions and 454 deletions
+117
View File
@@ -0,0 +1,117 @@
/**
* OpenClawHostAdapter — translates OpenClaw's plugin API into TDAI Core's
* unified HostAdapter interface.
*
* This is the "thin shell" that keeps OpenClaw-specific dependencies
* (OpenClawPluginApi, pluginConfig, resolveStateDir, event system)
* confined to the adapter layer while TDAI Core remains host-neutral.
*
* Usage (in index.ts):
* const adapter = new OpenClawHostAdapter({ api, pluginDataDir, config });
* const core = new TdaiCore({ hostAdapter: adapter, config: parsedConfig });
*/
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
import { OpenClawLLMRunnerFactory } from "./llm-runner.js";
import type {
HostAdapter,
RuntimeContext,
Logger,
LLMRunnerFactory,
} from "../../core/types.js";
// ============================
// Options
// ============================
export interface OpenClawHostAdapterOptions {
/** OpenClaw plugin API instance. */
api: OpenClawPluginApi;
/** Resolved plugin data directory (e.g. ~/.openclaw/state/memory-tdai). */
pluginDataDir: string;
/** Parsed OpenClaw config (for LLM model resolution). */
openclawConfig: unknown;
}
// ============================
// OpenClawHostAdapter
// ============================
export class OpenClawHostAdapter implements HostAdapter {
readonly hostType = "openclaw" as const;
private api: OpenClawPluginApi;
private pluginDataDir: string;
private openclawConfig: unknown;
private runnerFactory: OpenClawLLMRunnerFactory;
constructor(opts: OpenClawHostAdapterOptions) {
this.api = opts.api;
this.pluginDataDir = opts.pluginDataDir;
this.openclawConfig = opts.openclawConfig;
this.runnerFactory = new OpenClawLLMRunnerFactory({
config: opts.openclawConfig,
agentRuntime: opts.api.runtime.agent,
logger: opts.api.logger,
});
}
/**
* Build a RuntimeContext from the current OpenClaw session.
*
* In OpenClaw, sessionKey and sessionId come from the event/ctx objects
* passed to hooks. This method returns a context with sensible defaults;
* callers can override sessionKey/sessionId per-hook invocation using
* `buildRuntimeContextForSession()`.
*/
getRuntimeContext(): RuntimeContext {
return {
userId: "default_user",
sessionId: "",
sessionKey: "",
platform: "openclaw",
workspaceDir: process.cwd(),
dataDir: this.pluginDataDir,
};
}
/**
* Build a RuntimeContext for a specific session (used per-hook).
*
* This is an OpenClaw-specific convenience that merges session-level
* identifiers from hook ctx into the base context.
*/
buildRuntimeContextForSession(sessionKey: string, sessionId?: string): RuntimeContext {
return {
...this.getRuntimeContext(),
sessionKey,
sessionId: sessionId ?? "",
};
}
getLogger(): Logger {
return this.api.logger;
}
getLLMRunnerFactory(): LLMRunnerFactory {
return this.runnerFactory;
}
// -- OpenClaw-specific accessors (for index.ts bridge) --------------------
/** Get the raw OpenClaw plugin API (for legacy callers during migration). */
getPluginApi(): OpenClawPluginApi {
return this.api;
}
/** Get the OpenClaw config object (for legacy callers during migration). */
getOpenClawConfig(): unknown {
return this.openclawConfig;
}
/** Get the resolved plugin data directory. */
getPluginDataDir(): string {
return this.pluginDataDir;
}
}
+7
View File
@@ -0,0 +1,7 @@
/**
* OpenClaw adapter — barrel exports.
*/
export { OpenClawHostAdapter } from "./host-adapter.js";
export type { OpenClawHostAdapterOptions } from "./host-adapter.js";
export { OpenClawLLMRunner, OpenClawLLMRunnerFactory } from "./llm-runner.js";
export type { OpenClawLLMRunnerFactoryOptions } from "./llm-runner.js";
+104
View File
@@ -0,0 +1,104 @@
/**
* OpenClawLLMRunner — wraps the existing CleanContextRunner as a host-neutral LLMRunner.
*
* This is a compatibility bridge: TDAI Core modules (L1 extractor, L2 scene extractor,
* L3 persona generator, L1 dedup) can depend on the `LLMRunner` interface, while
* OpenClaw continues to use its native `runEmbeddedPiAgent` mechanism under the hood.
*
* Usage:
* const factory = new OpenClawLLMRunnerFactory({ config, agentRuntime, logger });
* const runner = factory.createRunner({ modelRef: "openai/gpt-4o", enableTools: true });
* const result = await runner.run({ prompt: "...", taskId: "l1-extraction" });
*/
import { CleanContextRunner } from "../../utils/clean-context-runner.js";
import type { EmbeddedAgentRuntimeLike } from "../../utils/clean-context-runner.js";
import type {
LLMRunner,
LLMRunParams,
LLMRunnerFactory,
LLMRunnerCreateOptions,
Logger,
} from "../../core/types.js";
const TAG = "[memory-tdai] [openclaw-runner]";
// ============================
// OpenClawLLMRunner
// ============================
/**
* LLMRunner implementation backed by CleanContextRunner.
*
* Each instance is configured with a fixed model + tools setting.
* Create via `OpenClawLLMRunnerFactory.createRunner()`.
*/
export class OpenClawLLMRunner implements LLMRunner {
private runner: CleanContextRunner;
constructor(runner: CleanContextRunner) {
this.runner = runner;
}
async run(params: LLMRunParams): Promise<string> {
return this.runner.run({
prompt: params.prompt,
systemPrompt: params.systemPrompt,
taskId: params.taskId,
timeoutMs: params.timeoutMs,
maxTokens: params.maxTokens,
workspaceDir: params.workspaceDir,
instanceId: params.instanceId,
});
}
}
// ============================
// OpenClawLLMRunnerFactory
// ============================
export interface OpenClawLLMRunnerFactoryOptions {
/** OpenClaw config object (passed to CleanContextRunner). */
config: unknown;
/** Preferred embedded agent runtime (host-injected). */
agentRuntime?: EmbeddedAgentRuntimeLike;
/** Logger for runner tracing. */
logger?: Logger;
}
/**
* Factory that creates OpenClawLLMRunner instances.
*
* Encapsulates the OpenClaw-specific dependencies (config, agentRuntime)
* so that callers only need to specify model + tools.
*/
export class OpenClawLLMRunnerFactory implements LLMRunnerFactory {
private config: unknown;
private agentRuntime?: EmbeddedAgentRuntimeLike;
private logger?: Logger;
constructor(opts: OpenClawLLMRunnerFactoryOptions) {
this.config = opts.config;
this.agentRuntime = opts.agentRuntime;
this.logger = opts.logger;
}
createRunner(opts?: LLMRunnerCreateOptions): LLMRunner {
const enableTools = opts?.enableTools ?? false;
const modelRef = opts?.modelRef;
this.logger?.debug?.(
`${TAG} Creating OpenClawLLMRunner: model=${modelRef ?? "(default)"}, tools=${enableTools}`,
);
const cleanRunner = new CleanContextRunner({
config: this.config,
modelRef,
enableTools,
agentRuntime: this.agentRuntime,
logger: this.logger,
});
return new OpenClawLLMRunner(cleanRunner);
}
}