From 25490297f192d3157dd03e2ea27ba2565329add7 Mon Sep 17 00:00:00 2001 From: Galin Iliev Date: Fri, 14 Aug 2026 09:26:33 -0700 Subject: [PATCH] feat(memory): complete explicit sharing and postbox --- docs/.generated/plugin-sdk-api-baseline.jsonl | 348 +++++---- docs/concepts/2026-07-29-memory-impl-plan.md | 20 +- docs/plugins/sdk-subpaths.md | 1 + .../src/app-server/run-attempt-connection.ts | 18 +- extensions/memory-core/index.test.ts | 42 +- extensions/memory-core/index.ts | 13 +- extensions/memory-core/src/cli.ts | 3 + .../src/dreaming-startup-cleanup.test.ts | 3 + .../src/memory-sharing-cli.test.ts | 158 ++++ .../memory-core/src/memory-sharing-cli.ts | 252 +++++++ .../src/memory/scoped-memory-db.ts | 11 + .../src/memory/scoped-memory-resources.ts | 1 + .../src/memory/scoped-memory-runtime.test.ts | 364 +++++++++- .../src/memory/scoped-memory-runtime.ts | 59 +- .../scoped-memory-sharing-gateway.test.ts | 438 +++++++++++ .../memory/scoped-memory-sharing-gateway.ts | 542 ++++++++++++++ .../src/memory/scoped-memory-sharing.test.ts | 570 ++++++++++++++- .../src/memory/scoped-memory-sharing.ts | 687 ++++++++++++++++-- extensions/memory-wiki/src/bridge.test.ts | 4 +- package.json | 4 + scripts/lib/plugin-sdk-entrypoints.json | 1 + ...lugin-sdk-private-local-only-subpaths.json | 1 + scripts/plugin-sdk-surface-report.mts | 3 +- src/agents/agent-tools.ts | 33 +- src/agents/apply-patch.test-support.ts | 2 + .../compact.hooks.harness.ts | 12 +- .../run/attempt-setup.test.ts | 2 +- ...memory-projection-isolation.docker.test.ts | 2 +- ...horized-virtual-projection-staging.test.ts | 12 +- src/auto-reply/dispatch.memory-egress.test.ts | 2 - .../reply/agent-runner-embedded-candidate.ts | 28 +- src/auto-reply/reply/get-reply-run-execute.ts | 21 +- .../reply/get-reply-run.media-only.test.ts | 114 +++ src/auto-reply/reply/source-turn-id.test.ts | 1 + src/channels/direct-dm.ts | 3 + src/channels/feedback-reflection.ts | 1 + src/channels/inbound-event/context.test.ts | 12 + src/channels/inbound-event/context.ts | 11 +- src/commands/doctor-memory-isolation.test.ts | 5 +- ...ion-accessor.sqlite-archive.worker.test.ts | 10 +- .../session-transcript-memory-policy.test.ts | 13 +- .../session-transcript-memory-policy.ts | 1 + .../memory-postbox-turn-capability.test.ts | 222 +++++- src/gateway/memory-postbox-turn-capability.ts | 160 +++- src/plugin-sdk/direct-dm.test.ts | 5 + .../memory-sharing-control-runtime.ts | 5 + src/plugins/memory-invocation.test.ts | 182 +++-- src/plugins/memory-invocation.ts | 23 +- src/plugins/memory-state.test.ts | 4 +- src/plugins/tools.optional.test.ts | 8 +- src/state/openclaw-agent-db.generated.d.ts | 10 + src/state/openclaw-agent-schema.sql | 36 +- ...penclaw-agent-scoped-memory-schema.test.ts | 55 ++ .../openclaw-agent-scoped-memory-schema.ts | 43 ++ ui/src/i18n/locales/en.ts | 50 ++ ui/src/pages/config/memory-page.ts | 5 + ui/src/pages/config/memory-sharing-host.ts | 40 + ui/src/pages/config/memory-sharing.test.ts | 215 ++++++ ui/src/pages/config/memory-sharing.ts | 644 ++++++++++++++++ ui/src/pages/config/memory.test.ts | 1 + ui/src/pages/config/memory.ts | 4 +- 61 files changed, 5081 insertions(+), 459 deletions(-) create mode 100644 extensions/memory-core/src/memory-sharing-cli.test.ts create mode 100644 extensions/memory-core/src/memory-sharing-cli.ts create mode 100644 extensions/memory-core/src/memory/scoped-memory-sharing-gateway.test.ts create mode 100644 extensions/memory-core/src/memory/scoped-memory-sharing-gateway.ts create mode 100644 src/plugin-sdk/memory-sharing-control-runtime.ts create mode 100644 ui/src/pages/config/memory-sharing-host.ts create mode 100644 ui/src/pages/config/memory-sharing.test.ts create mode 100644 ui/src/pages/config/memory-sharing.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index d34b0beb8677..7d7eb0a3a61e 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -53,17 +53,17 @@ {"closureHash":"ff3c4616cd6212a6d698831a8b287ad87e3968c8663f4090d095bb30ec40fc1c","declaration":"export function abortAndDrainAgentHarnessRun(params: { sessionId: string; sessionKey?: string; settleMs?: number; forceClear?: boolean; reason?: string; }): Promise;","entrypoint":"agent-harness","exportName":"abortAndDrainAgentHarnessRun","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"58989e3fa91eecf2e05202e36548e6e64a3b9219e83154bd99866c851604e34e","declaration":"export function createAgentToolResultMiddlewareRunner(ctx: AgentToolResultMiddlewareContext, handlers?: AgentToolResultMiddleware[]): { applyToolResultMiddleware(event: AgentToolResultMiddlewareEvent): Promise; };","entrypoint":"agent-harness","exportName":"createAgentToolResultMiddlewareRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"b8f6355d7ad1700aceecddaa6e9ccf43091a792d5b481a1ee3f55294a881a67d","declaration":"export function createCodexAppServerToolResultExtensionRunner(ctx: CodexAppServerExtensionContext, factories?: CodexAppServerExtensionFactory[]): { applyToolResultExtensions(event: CodexAppServerToolResultEvent): Promise>; };","entrypoint":"agent-harness","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} -{"closureHash":"d0cc2d1a92a55bfe73ad51bb32078cf4e8911a2a5a2f1c2f3190ba044922e56b","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} +{"closureHash":"1b2cd35345f87a8ab4ff0b56aa58d03f90441974df6ee88724bfe43ac8883187","declaration":"export function createOpenClawCodingTools(options?: OpenClawCodingToolsOptions): AnyAgentTool[];","entrypoint":"agent-harness","exportName":"createOpenClawCodingTools","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"13649ee853485319e7449fda25c106b3f3f53d3090e53cdbb28e220a8529eb80","declaration":"export function disposeRegisteredAgentHarnesses(): Promise;","entrypoint":"agent-harness","exportName":"disposeRegisteredAgentHarnesses","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"f255a91162ece4c239bb8fa745efa14a1054bc024a291e9954f75f239b2b87c3","declaration":"export function resolveActiveEmbeddedRunSessionId(sessionKey: string): string | undefined;","entrypoint":"agent-harness","exportName":"resolveActiveEmbeddedRunSessionId","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} {"closureHash":"27d9f61df9ccf68615cb2002a6da891e36ab0c07623bc37c4d07aa980b446881","declaration":"export function resolveWebSearchToolPolicy(params: WebSearchToolPolicyParams): WebSearchToolPolicyResolution;","entrypoint":"agent-harness","exportName":"resolveWebSearchToolPolicy","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"function","recordType":"export"} -{"closureHash":"d759a25775cb15d3f1804e39e98518f83b67b29ba3ab2fd84d4bf16106d9fdb9","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} -{"closureHash":"bd666466495cef203461f4484eb439faa6a4fd10756c44a64a45ddef3b65961c","declaration":"export type AgentHarnessV2 = AgentHarnessV2;","entrypoint":"agent-harness","exportName":"AgentHarnessV2","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"cff7e843ff24f7db2fd0f413d247310c86216bd9b51393b64c22f0ef85cda68e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"7a05a2ecbd984f18210eca5d9c4e06b0f051279e1a9d830c4924969eb3982f76","declaration":"export type AgentHarnessV2 = AgentHarnessV2;","entrypoint":"agent-harness","exportName":"AgentHarnessV2","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"4ad0f830bf11a2db48faefb1439b7fbb08d9f22d22083f5e301327e1696f2310","declaration":"export type AgentToolResultMiddleware = AgentToolResultMiddleware;","entrypoint":"agent-harness","exportName":"AgentToolResultMiddleware","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"008b6c78d5e44a9d1df1d7e32e6015382ee9ba1cb9b10bd4c2b467619d1c89d4","declaration":"export type AgentToolResultMiddlewareEvent = AgentToolResultMiddlewareEvent;","entrypoint":"agent-harness","exportName":"AgentToolResultMiddlewareEvent","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"7414a2a79c2d78c1d52538250c827305bba1a2bb25010448837c8524a9f95b3c","declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"agent-harness","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} -{"closureHash":"7cce5f7355df47a66ed208855889b16b2c40782a75575e8e1a8dce43517b801f","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} -{"closureHash":"b56f77aa308700cc9ea82f50957a860852d0c83c006b5020d97f0d9b2d6c9d6a","declaration":"export type EmbeddedRunAttemptParamsV2 = EmbeddedRunAttemptParamsV2;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"02942c94049e128ca9e7ed1421bc3f6f6bcbb8b3818da0d727265be34a83ca04","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} +{"closureHash":"bcbecd46dae3e3baa0c248d56356292426a63609aad44039fd6f5f1276bff73f","declaration":"export type EmbeddedRunAttemptParamsV2 = EmbeddedRunAttemptParamsV2;","entrypoint":"agent-harness","exportName":"EmbeddedRunAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"closureHash":"25c6985c3bef2c6efc6a96e70af6d66fe073be0b0d311681cfc0dfc186528d9a","declaration":"export type OpenClawAgentToolResult = OpenClawAgentToolResult;","entrypoint":"agent-harness","exportName":"OpenClawAgentToolResult","importSpecifier":"openclaw/plugin-sdk/agent-harness","kind":"type","recordType":"export"} {"category":"runtime","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","recordType":"module"} {"closureHash":"fab99dfcb01d475a1bfdbe7a8fac9be10a93dac5f12ac78c2dea673c8ab86abf","declaration":"export function abortAgentHarnessRun(sessionId: string): boolean;\nexport function abortAgentHarnessRun(sessionId: undefined, opts: { mode: \"all\" | \"compacting\"; reason?: \"restart\"; }): boolean;","entrypoint":"agent-harness-runtime","exportName":"abortAgentHarnessRun","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -74,16 +74,16 @@ {"closureHash":"155d94754b1411dd9b9fdae11ca094cbce25610ffb1dd9a617f293596b3a78f7","declaration":"export function assertContextEngineHostSupport(params: { contextEngine: ContextEngine; operation: ContextEngineOperation; host: ContextEngineHostSupport; }): void;","entrypoint":"agent-harness-runtime","exportName":"assertContextEngineHostSupport","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"3209ee56dbd86be4de23a2de59903a4d310fc99ed912d220ebe57efd308ff14f","declaration":"export function assignMcpCatalogSafeServerNames(serverNames: Iterable): Map;","entrypoint":"agent-harness-runtime","exportName":"assignMcpCatalogSafeServerNames","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"911838521fabe5f74acfeadabfa855fd9857fa21671b3f0cad08779f3402825a","declaration":"export function attachModelProviderRequestTransport(model: TModel, request: ModelProviderRequestTransportOverrides | undefined): TModel;","entrypoint":"agent-harness-runtime","exportName":"attachModelProviderRequestTransport","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"64e007f47389deb6c1a022f914aaff14269e34e906cd29a71464276a9f756560","declaration":"export function awaitAgentEndSideEffects(params: AgentEndSideEffectsParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"awaitAgentEndSideEffects","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"ef4cde7cdb9402c3651d90cd36780563d7650cbbd3b83820c5cd94d74e8a9ee8","declaration":"export function awaitAgentHarnessAgentEndHook(params: { event: PluginHookAgentEndEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"awaitAgentHarnessAgentEndHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"37f81c8f07bf6b905fb9d0752476e2dc666023a3a2a4f42cbb7d7fc9d494c32d","declaration":"export function awaitAgentEndSideEffects(params: AgentEndSideEffectsParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"awaitAgentEndSideEffects","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"e1ac85abf4da9fd8720aa48d9a3d16f3e519c04ddf121c0c9422a6137d0877fb","declaration":"export function awaitAgentHarnessAgentEndHook(params: { event: PluginHookAgentEndEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"awaitAgentHarnessAgentEndHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"73d8efb2d4171745da0c8f433ec80363cd9ce26b0d76be0cdddaa077489a5134","declaration":"export function bootstrapHarnessContextEngine(params: { hadSessionFile: boolean; contextEngine?: HarnessContextEngine; sessionId: string; sessionKey?: string; sessionTarget?: ContextEngineSessionTarget; sessionFile: string; sessionManager?: unknown; runtimeContext?: ContextEngineRuntimeContext; transcriptReadFence?: UserTurnTranscriptAdmissionReceipt; runtimeSettings?: ContextEngineRuntimeSettings; contextEngineHostSupport?: ContextEngineHostSupport; harnessId?: string | null; runtimeId?: string | null; providerId?: string | null; requestedModelId?: string | null; modelId?: string | null; maxOutputTokens?: number | null; fallbackReason?: string | null; degradedReason?: string | null; runMaintenance?: typeof runHarnessContextEngineMaintenance; config?: OpenClawConfig; warn: (message: string) => void; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"bootstrapHarnessContextEngine","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"fdd485fc00b19e46356354d24cc924c694fbb8c01a01e16048183880a3fbf50d","declaration":"export function buildAgentHarnessUserInputAnswers(questions: readonly AgentHarnessUserInputQuestion[], inputText: string): AgentHarnessUserInputAnswers;","entrypoint":"agent-harness-runtime","exportName":"buildAgentHarnessUserInputAnswers","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"bcc8554c0316257b42e7ca95e16c6b1f3bfb9794e5db7f41cf2bcdd2464bb218","declaration":"export function buildAgentHookContextChannelFields(params: { sessionKey?: string | null; messageChannel?: string | null; messageProvider?: string | null; currentChannelId?: string | null; messageTo?: string | null; senderId?: string | null; agentAccountId?: string | null; }): Pick;","entrypoint":"agent-harness-runtime","exportName":"buildAgentHookContextChannelFields","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"3d5e7938f471abeda3976e1fa572ef53e7c95f51349e4419506b626913d1060f","declaration":"export function buildAgentHookContextChannelFields(params: { sessionKey?: string | null; messageChannel?: string | null; messageProvider?: string | null; currentChannelId?: string | null; messageTo?: string | null; senderId?: string | null; agentAccountId?: string | null; }): Pick;","entrypoint":"agent-harness-runtime","exportName":"buildAgentHookContextChannelFields","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"f8ad3d762c9753fdc36b2b9af0980167fdc54090c7bcca2f3dbe7c8951e86821","declaration":"export function buildAgentRuntimePlan(params: BuildAgentRuntimePlanParams): AgentRuntimePlan;","entrypoint":"agent-harness-runtime","exportName":"buildAgentRuntimePlan","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"528d11abf061b0b303722737de5a6406e7e55bffa38c45144c77d896ae1b3b0a","declaration":"export function buildBootstrapContextForFiles(bootstrapFiles: WorkspaceBootstrapFile[], params: { config?: OpenClawConfig; agentId?: string | null; warn?: (message: string) => void; }): EmbeddedContextFile[];","entrypoint":"agent-harness-runtime","exportName":"buildBootstrapContextForFiles","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"44d5a4667d2f3dc3a28e5c9d7b46765b1fb3c62820288e40251f5174911c8a6a","declaration":"export function buildEmbeddedAttemptToolRunContext(params: { trigger?: EmbeddedRunTrigger; jobId?: string; memoryFlushWritePath?: string; toolsAllow?: string[]; conversationToolPolicy?: GroupToolPolicyConfig; trace?: DiagnosticTraceContext; }): { trigger?: EmbeddedRunTrigger; jobId?: string; memoryFlushWritePath?: string; runtimeToolAllowlist?: string[]; conversationToolPolicy?: GroupToolPolicyConfig; trace?: DiagnosticTraceContext; };","entrypoint":"agent-harness-runtime","exportName":"buildEmbeddedAttemptToolRunContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"273bc789e32d09355911a553f30e7fd13f0ac7fc7d08f76d6c6ea96b8ab4e1d3","declaration":"export function buildHarnessContextEngineRuntimeContext(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"9cd796a6dc567e647776b5d9af435e8c179796142948b64b088eb9e91c42ba66","declaration":"export function buildHarnessContextEngineRuntimeContextFromUsage(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContextFromUsage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"558119b330dcc6a677a91f88a180b67d63299880b8fc0efc0d4616c3d6ffab30","declaration":"export function buildHarnessContextEngineRuntimeContext(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"a3814447de0f4815068e05a01453fe8e5bc87216e2d88613f21f8f7982ed94b2","declaration":"export function buildHarnessContextEngineRuntimeContextFromUsage(params: Parameters[0]): ContextEngineRuntimeContext;","entrypoint":"agent-harness-runtime","exportName":"buildHarnessContextEngineRuntimeContextFromUsage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"33a7cd8d63d4ef045ee3a42f806026a8b621e7dd32d8d6fbf4e7b44452d5e0ce","declaration":"export function buildNativeHookRelayCommand(params: { provider: NativeHookRelayProvider; relayId: string; generation?: string; event: NativeHookRelayEvent; preToolUseUnavailable?: \"noop\"; timeoutMs?: number; executable?: string; nice?: number | false; nodeExecutable?: string; }): string;","entrypoint":"agent-harness-runtime","exportName":"buildNativeHookRelayCommand","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"3846647c3c2fb0242f70591cf95c2e02f2a5a3c44447efb4cf7a31b2dc2122fd","declaration":"export function buildSkillWorkshopPromptSection(): string[];","entrypoint":"agent-harness-runtime","exportName":"buildSkillWorkshopPromptSection","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"32e977ece65144a83ae1b0a3c8d1b9b00a2a2506ad9ef1db3b2b9770ce762dbe","declaration":"export function buildWatchedSessionsHarnessContext(params: { config?: OpenClawConfig; sessionKey?: string; sandboxed?: boolean; toolNames: Iterable; capabilityToolNames?: Iterable; }): string | undefined;","entrypoint":"agent-harness-runtime","exportName":"buildWatchedSessionsHarnessContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -100,7 +100,7 @@ {"closureHash":"51f76e9e37b65b358f0313e10152d950b003bc3e50f4bb26fe29a988237772e2","declaration":"export function consumePreExecutionBlockedToolCall(toolCallId: string, runId?: string): boolean;","entrypoint":"agent-harness-runtime","exportName":"consumePreExecutionBlockedToolCall","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"58989e3fa91eecf2e05202e36548e6e64a3b9219e83154bd99866c851604e34e","declaration":"export function createAgentToolResultMiddlewareRunner(ctx: AgentToolResultMiddlewareContext, handlers?: AgentToolResultMiddleware[]): { applyToolResultMiddleware(event: AgentToolResultMiddlewareEvent): Promise; };","entrypoint":"agent-harness-runtime","exportName":"createAgentToolResultMiddlewareRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"b8f6355d7ad1700aceecddaa6e9ccf43091a792d5b481a1ee3f55294a881a67d","declaration":"export function createCodexAppServerToolResultExtensionRunner(ctx: CodexAppServerExtensionContext, factories?: CodexAppServerExtensionFactory[]): { applyToolResultExtensions(event: CodexAppServerToolResultEvent): Promise>; };","entrypoint":"agent-harness-runtime","exportName":"createCodexAppServerToolResultExtensionRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"1368f69c7a2b975961e4bec1a8709522669fed0df0eca2d669159c9e65eb1cf3","declaration":"export function deliverAgentHarnessUserInputPrompt(params: PromptDeliveryParams, questions: readonly AgentHarnessUserInputQuestion[], options?: AgentHarnessUserInputPromptOptions): Promise;","entrypoint":"agent-harness-runtime","exportName":"deliverAgentHarnessUserInputPrompt","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"173e3b60315d73b59d370d8ee1101efb7e4653e01dd5d504c0cbe1cd8e04a5bf","declaration":"export function deliverAgentHarnessUserInputPrompt(params: PromptDeliveryParams, questions: readonly AgentHarnessUserInputQuestion[], options?: AgentHarnessUserInputPromptOptions): Promise;","entrypoint":"agent-harness-runtime","exportName":"deliverAgentHarnessUserInputPrompt","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"6f436485257f69fa07a18203b91d4341690522f12aff4f25805c7a1e21326ee3","declaration":"export function detectAndLoadAgentHarnessPromptImages(params: { prompt: string; workspaceDir: string; model: { input?: string[]; }; existingImages?: ImageContent[]; imageOrder?: PromptImageOrderEntry[]; media?: MediaFact[]; config?: OpenClawConfig; workspaceOnly?: boolean; localRoots?: readonly string[]; sandbox?: { root: string; bridge: SandboxFsBridge; }; }): Promise<{ images: ImageContent[]; detectedRefs: Array<{ raw: string; resolved: string; type: \"path\" | \"media-uri\"; }>; loadedCount: number; skippedCount: number; }>;","entrypoint":"agent-harness-runtime","exportName":"detectAndLoadAgentHarnessPromptImages","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"13649ee853485319e7449fda25c106b3f3f53d3090e53cdbb28e220a8529eb80","declaration":"export function disposeRegisteredAgentHarnesses(): Promise;","entrypoint":"agent-harness-runtime","exportName":"disposeRegisteredAgentHarnesses","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"c38cd390190bb07ddcd247420d6e0b489a0229bd402ddca0440417217a57251a","declaration":"export function emitAgentEvent(event: Omit): void;","entrypoint":"agent-harness-runtime","exportName":"emitAgentEvent","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -123,7 +123,7 @@ {"closureHash":"5fa61424d7471cf6f3b142964294cca4723eefc5b673eff97b2b1a8b3f139172","declaration":"export function formatToolAggregate(toolName?: string, metas?: string[], options?: ToolAggregateOptions): string;","entrypoint":"agent-harness-runtime","exportName":"formatToolAggregate","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"cb9c705d6862116c7c61a3cc3941f8fea1c834ad14a628441cff1d1a697eb00b","declaration":"export function formatToolExecutionErrorMessage(error: unknown, fallback: string): string;","entrypoint":"agent-harness-runtime","exportName":"formatToolExecutionErrorMessage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"16ca31a0ec0bec339d1a9ac63252eec5665d00d763c20075a93be176dc098239","declaration":"export function formatToolProgressOutput(output: string, options?: { maxChars?: number; }): string | undefined;","entrypoint":"agent-harness-runtime","exportName":"formatToolProgressOutput","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"ed37bb17e6b49e1120950b88390fa7e9cb14202bf2aeab1bded96c07eb774f47","declaration":"export function getAgentHarnessHookRunner(): AgentHarnessHookRunner;","entrypoint":"agent-harness-runtime","exportName":"getAgentHarnessHookRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"5163319f5736536c61ca48eb7dd744b84ea3d5e386dc283c7de6c9389becd121","declaration":"export function getAgentHarnessHookRunner(): AgentHarnessHookRunner;","entrypoint":"agent-harness-runtime","exportName":"getAgentHarnessHookRunner","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"37c1f0f87fd002e7de9ddb6ec0e4389e7add214dd3ceb6001077038f395d8451","declaration":"export function getBeforeToolCallFailureDisposition(error: unknown): BeforeToolCallFailureDisposition | undefined;","entrypoint":"agent-harness-runtime","exportName":"getBeforeToolCallFailureDisposition","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"2f995f2a9777cac11240f0dd375d2041fdc11ca0ad57c65e102db3d0be6b6f62","declaration":"export function getBeforeToolCallPolicyDiagnosticState(): BeforeToolCallPolicyDiagnosticState;","entrypoint":"agent-harness-runtime","exportName":"getBeforeToolCallPolicyDiagnosticState","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"45828b5ebf771446b493a1af9dee71e58aa8b96a28957a633e5fd5f3d6bfcaa4","declaration":"export function getChannelAgentToolMeta(tool: ChannelAgentTool): ChannelAgentToolMeta | undefined;","entrypoint":"agent-harness-runtime","exportName":"getChannelAgentToolMeta","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -162,7 +162,7 @@ {"closureHash":"40154c3b7b2a7179df33f4a3fbef5e56078be2759d5aab29f39eb0f3c92fc631","declaration":"export function projectRuntimeToolInputSchema(schema: unknown, path?: string): RuntimeToolInputSchemaProjection;","entrypoint":"agent-harness-runtime","exportName":"projectRuntimeToolInputSchema","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"e42e3dc63e8545bb9a6056336fbd6c1dc8f356dce4f0f1c6d9765254c974390e","declaration":"export function projectSettledTurnFinalizationAttemptResult(result: AgentHarnessAttemptResult): AgentHarnessSettledTurnFinalizationResult;","entrypoint":"agent-harness-runtime","exportName":"projectSettledTurnFinalizationAttemptResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"28fce991efc7c1c2e4d24a5380acdeca72aea42a3e3b14d053ec352a84ab5211","declaration":"export function queueAgentHarnessMessage(sessionId: string, text: string, options?: EmbeddedAgentQueueMessageOptions): boolean;","entrypoint":"agent-harness-runtime","exportName":"queueAgentHarnessMessage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"a5942178bfa7de60f6b738d58d5f511a7baa1abf25119454180b81daec365833","declaration":"export function registerNativeHookRelay(params: RegisterNativeHookRelayParams): ActiveNativeHookRelayRegistrationHandle;","entrypoint":"agent-harness-runtime","exportName":"registerNativeHookRelay","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"304995888df64b5f779a8fcc35c3548dfc64d478e793003de1cacf4a5bcc8668","declaration":"export function registerNativeHookRelay(params: RegisterNativeHookRelayParams): ActiveNativeHookRelayRegistrationHandle;","entrypoint":"agent-harness-runtime","exportName":"registerNativeHookRelay","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"b7cc6c35506dc6955e0359aa5c53c15a4d0db23639da8c1717f8fefda953c119","declaration":"export function requestDeferredPluginToolApproval(params: { deferredApproval: DeferredPluginToolApproval; signal?: AbortSignal; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"requestDeferredPluginToolApproval","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"a2306cba08cb05ff8430c8362c0cc3c821706da5a4e65a06849ad0d0fb007ae3","declaration":"export function resetAgentEventsForTest(options?: { preserveListeners?: boolean; }): void;","entrypoint":"agent-harness-runtime","exportName":"resetAgentEventsForTest","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"f255a91162ece4c239bb8fa745efa14a1054bc024a291e9954f75f239b2b87c3","declaration":"export function resolveActiveEmbeddedRunSessionId(sessionKey: string): string | undefined;","entrypoint":"agent-harness-runtime","exportName":"resolveActiveEmbeddedRunSessionId","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -181,7 +181,7 @@ {"closureHash":"a36f94a5d2408964d52b23e38f02c8e9467266d8e06e6fee0fdf16946eae9e79","declaration":"export function resolveModelAuthMode(provider?: string, cfg?: OpenClawConfig, store?: AuthProfileStore, options?: { workspaceDir?: string; }): ModelAuthMode | undefined;","entrypoint":"agent-harness-runtime","exportName":"resolveModelAuthMode","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"714a04276dcddc15a1079835050cdef88837b7159d24a72db8938bb3b45c764f","declaration":"export function resolveNativeHookRelayDeferredToolApproval(params: { relayId: string; toolUseId?: string; signal?: AbortSignal; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"resolveNativeHookRelayDeferredToolApproval","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"fbda2ecc8054053facbdaf406268fb2d50f3f68e6e2446f23a90f385278fcc24","declaration":"export function resolveNodeIdFromList(nodes: NodeListNode[], query?: string, allowDefault?: boolean, options?: { allowCompactDisplayName?: boolean; }): string;","entrypoint":"agent-harness-runtime","exportName":"resolveNodeIdFromList","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"b325a6d70ba080e1b2687c21048c06fe8a913eee1c6bfd9166bad6a4b2864675","declaration":"export function resolveSandboxContext(params: { config?: OpenClawConfig; agentId?: string; execOverrides?: ExecPolicyOverrides; requireCurrentConfig?: boolean; sessionKey?: string; skillsSnapshot?: SkillSnapshot; workspaceDir?: string; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"resolveSandboxContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"929e9f5ae2814b89c43ed24e9b29f72463644875911d384773114510796d7e1d","declaration":"export function resolveSandboxContext(params: { config?: OpenClawConfig; agentId?: string; execOverrides?: ExecPolicyOverrides; requireCurrentConfig?: boolean; sessionKey?: string; skillsSnapshot?: SkillSnapshot; authorizedVirtualProjectionMountPlan?: AuthorizedVirtualProjectionMountPlan; prepareAuthorizedVirtualProjectionMountPlan?: (params: { agentWorkspaceDir: string; }) => Promise; workspaceDir?: string; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"resolveSandboxContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"9aab8cf42913a365a7e26efdea7abee4445cf9a47a34067e952ea7ee2ed44731","declaration":"export function resolveSessionAgentIds(params: { sessionKey?: string; config?: OpenClawConfig; agentId?: string; fallbackAgentId?: string; }): { defaultAgentId: string; sessionAgentId: string; };","entrypoint":"agent-harness-runtime","exportName":"resolveSessionAgentIds","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"a34704c97920f0c3cb70407476fb16ebf1a6fb8a74f01c3ab5425bdbf08e9612","declaration":"export function resolveSessionWriteLockAcquireTimeoutMs(_config?: SessionWriteLockAcquireTimeoutConfig, _env?: NodeJS.ProcessEnv): number;","entrypoint":"agent-harness-runtime","exportName":"resolveSessionWriteLockAcquireTimeoutMs","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"2eb76630485e36b410dd663450f0c34b126593961069622cc6bef762f84a71cd","declaration":"export function resolveSessionWriteLockOptions(_config?: SessionWriteLockAcquireTimeoutConfig, _params?: { env?: NodeJS.ProcessEnv; maxHoldMsFallback?: number; }): { timeoutMs: number; staleMs: number; maxHoldMs: number; };","entrypoint":"agent-harness-runtime","exportName":"resolveSessionWriteLockOptions","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -190,16 +190,16 @@ {"closureHash":"f2fb5a4e5546086c8a69600795e5b6cde1817b2ba5a4680600c41297005b3ee2","declaration":"export function resolveUserPath(input: string, env?: NodeJS.ProcessEnv, homedir?: () => string): string;","entrypoint":"agent-harness-runtime","exportName":"resolveUserPath","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"4204798ce3bf40e0b488d6642a9617f361e53931f634042fcd09dde69f3924c4","declaration":"export function resolveWritableSandboxBindHostRoots(binds: readonly string[] | undefined): string[];","entrypoint":"agent-harness-runtime","exportName":"resolveWritableSandboxBindHostRoots","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"10e5de5d2202452344eca9023fccecd19bcede51b031fe7926bd6335e7767158","declaration":"export function runAgentCleanupStep(params: { runId: string; sessionId: string; step: string; cleanup: () => Promise; getTimeoutDetails?: () => string | undefined; log: AgentCleanupLogger; env?: NodeJS.ProcessEnv; timeoutMs?: number; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentCleanupStep","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"8158f730012e93bff519315eb8188240fdd033e288ab0bb7350d41d693987f74","declaration":"export function runAgentEndSideEffects(params: AgentEndSideEffectsParams): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentEndSideEffects","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"0aa9bec0d281a8caa28e34bd4eb6a7906518fde20decf351ed1e52eaf2112760","declaration":"export function runAgentEndSideEffects(params: AgentEndSideEffectsParams): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentEndSideEffects","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"a88818cc62232eeb75281bb6ccfbaf7928a4bb1390313c73c08b14c73e4e92bb","declaration":"export function runAgentHarnessAfterCompactionHook(params: { sessionFile: string; messages?: AgentMessage[]; ctx: AgentHarnessHookContext; compactedCount: number; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessAfterCompactionHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"d6517f30fc90c4fa8ef89ac0fe3d6499adcfad71fd3ab46cc66d3e4a2472a844","declaration":"export function runAgentHarnessAfterToolCallHook(params: { toolName: string; toolCallId: string; runId?: string; agentId?: string; sessionId?: string; sessionKey?: string; channelId?: string; startArgs: Record; result?: unknown; error?: string; startedAt?: number; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessAfterToolCallHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"63e138290e4629046b4b6f56e8601979be5e851ea930d9f95daef8eb8d6527c3","declaration":"export function runAgentHarnessAgentEndHook(params: { event: PluginHookAgentEndEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessAgentEndHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"da8b724c5858691b8a1c71c63294a397631c031270db92fdff9ef4493efa2492","declaration":"export function runAgentHarnessBeforeAgentFinalizeHook(params: { event: PluginHookBeforeAgentFinalizeEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeAgentFinalizeHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"5037ec4d780f518767d676d52ac55627dd4bf515aee344145b928156b7eef5fc","declaration":"export function runAgentHarnessAgentEndHook(params: { event: PluginHookAgentEndEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessAgentEndHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"d542c7e8b4994cd135222d0914e3714cb39f61a867aee5822e2594b5a008633d","declaration":"export function runAgentHarnessBeforeAgentFinalizeHook(params: { event: PluginHookBeforeAgentFinalizeEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeAgentFinalizeHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"8fec73ee8c7c9be3335bd6dc1bac9278f0be5beef22a5975eb06e56f504f4bd6","declaration":"export function runAgentHarnessBeforeCompactionHook(params: { sessionFile: string; messages?: AgentMessage[]; ctx: AgentHarnessHookContext; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeCompactionHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"021b81820bef2e8d54c50a5fc159d6665b23b50a1f5c40dae76a4833839d89c9","declaration":"export function runAgentHarnessBeforeMessageWriteHook(params: { message: AgentMessage; agentId?: string; sessionKey?: string; }): AgentMessage | null;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessBeforeMessageWriteHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"234d68d071e378bce7a3780dd308a39e6f611b722d86203c3366951420d9f1b1","declaration":"export function runAgentHarnessGatewayQuestion(params: RunAgentHarnessGatewayQuestionParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessGatewayQuestion","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"89aa32c12a44b446777bc4cfbb106a048dd9cbc668260525798a895a433256f4","declaration":"export function runAgentHarnessLlmInputHook(params: { event: PluginHookLlmInputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmInputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} -{"closureHash":"ba63f9cdd34249fba984af87a039494b75b3f93c0c70b925e884f3f98935b984","declaration":"export function runAgentHarnessLlmOutputHook(params: { event: PluginHookLlmOutputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmOutputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"0c380a0011acae57282121d702249d2ab7e978452fe7f32e8853d9945c5558b9","declaration":"export function runAgentHarnessGatewayQuestion(params: RunAgentHarnessGatewayQuestionParams): Promise;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessGatewayQuestion","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"78e0698de386b8af9caccebe1e0738fc8f88e7ae9f65187759acf7cefea7b578","declaration":"export function runAgentHarnessLlmInputHook(params: { event: PluginHookLlmInputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmInputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} +{"closureHash":"7347dbea4eac7869440c0db74f329e9fb1389bc8524f398d65961ae98ee80d7d","declaration":"export function runAgentHarnessLlmOutputHook(params: { event: PluginHookLlmOutputEvent; ctx: AgentHarnessHookContext; hookRunner?: AgentHarnessHookRunner; }): void;","entrypoint":"agent-harness-runtime","exportName":"runAgentHarnessLlmOutputHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"c4c5131ab7065decd8d8e935ac3779e3baa2c52fbbbd95a6ccb624377db09ca1","declaration":"export function runBeforeToolCallHook(args: { toolName: string; params: unknown; toolKind?: PluginHookToolKind; toolInputKind?: PluginHookToolInputKind; toolCallId?: string; ctx?: HookContext; signal?: AbortSignal; approvalMode?: \"request\" | \"report\" | \"deny\" | \"defer\"; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runBeforeToolCallHook","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"35268edd668bcf1981dff5f000b8bbb5847a1a9bb7e8923769edc378e21108aa","declaration":"export function runHarnessContextEngineMaintenance(params: { contextEngine?: HarnessContextEngine; sessionId: string; sessionKey?: string; sessionTarget?: ContextEngineSessionTarget; sessionFile: string; reason: \"bootstrap\" | \"compaction\" | \"turn\"; sessionManager?: unknown; runtimeContext?: ContextEngineRuntimeContext; runtimeSettings?: ContextEngineRuntimeSettings; contextEngineHostSupport?: ContextEngineHostSupport; harnessId?: string | null; runtimeId?: string | null; providerId?: string | null; requestedModelId?: string | null; modelId?: string | null; tokenBudget?: number | null; maxOutputTokens?: number | null; fallbackReason?: string | null; degradedReason?: string | null; executionMode?: \"foreground\" | \"background\"; onDeferredMaintenance?: (promise: Promise) => void; withSessionManagerRewriteLock?: (operation: () => Promise | T) => Promise; config?: OpenClawConfig; }): Promise;","entrypoint":"agent-harness-runtime","exportName":"runHarnessContextEngineMaintenance","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} {"closureHash":"ac1ea146e8b2031b307790d708076df67f0120365804edffacbf9841edd86185","declaration":"export function sanitizeToolResult(result: unknown): unknown;","entrypoint":"agent-harness-runtime","exportName":"sanitizeToolResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"function","recordType":"export"} @@ -219,13 +219,13 @@ {"closureHash":"0701a22057edc3b733da7e05948db94aa98b337b224a5718efdd85212a8602bf","declaration":"export const TRANSCRIPT_CREDENTIAL_SAFETY_PROMPT: string;","entrypoint":"agent-harness-runtime","exportName":"TRANSCRIPT_CREDENTIAL_SAFETY_PROMPT","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"const","recordType":"export"} {"closureHash":"b5845c99df6c2a834a16678c320e0111bad96a3a7ac245d379aa5e6d2555d29b","declaration":"export const agentHarnessAttemptTerminal: { merge: (current: AgentRunAttemptTerminal, incoming: AgentRunAttemptTerminal) => AgentRunAttemptTerminal; normalize: (input: { aborted?: boolean; externalAbort?: boolean; idleTimedOut?: boolean; promptError?: unknown; promptErrorSource?: AgentRunAttemptFailureSource | null; timedOut?: boolean; timedOutByRunBudget?: boolean; timedOutDuringCompaction?: boolean; timedOutDuringToolExecution?: boolean; }) => AgentRunAttemptTerminal; project: (terminal: AgentRunAttemptTerminal) => { aborted: boolean; cleanupYieldAborted: boolean; externalAbort: boolean; failed: boolean; idleTimedOut: boolean; interrupted: boolean; promptError: unknown; promptErrorSource: AgentRunAttemptFailureSource | null; timedOut: boolean; timedOutByRunBudget: boolean; timedOutDuringCompaction: boolean; timedOutDuringToolExecution: boolean; }; setFailure: (terminal: AgentRunAttemptTerminal, failure: { source: AgentRunAttemptFailureSource; error: unknown; } | null) => AgentRunAttemptTerminal;};","entrypoint":"agent-harness-runtime","exportName":"agentHarnessAttemptTerminal","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"const","recordType":"export"} {"closureHash":"22bcf962aa76c76074c4ed4ad7d6558edbc3588e239263e09af74c1000bbe012","declaration":"export const embeddedAgentLog: SubsystemLogger;","entrypoint":"agent-harness-runtime","exportName":"embeddedAgentLog","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"const","recordType":"export"} -{"closureHash":"c0f6b29e20cd3f18f1f123bc1e5d458f391013e2812541fd58698155bd72fe96","declaration":"export const nativeHookRelayTesting: { readonly clearNativeHookRelaysForTests: () => void; readonly getNativeHookRelayInvocationsForTests: () => NativeHookRelayInvocation[]; readonly getNativeHookRelayRegistrationForTests: (relayId: string) => NativeHookRelayRegistration | undefined; readonly getNativeHookRelayBridgeDirForTests: () => string; readonly getNativeHookRelayBridgeRegistryPathForTests: (relayId: string) => string; readonly getNativeHookRelayBridgeRecordForTests: (relayId: string) => Record | undefined; readonly isNativeHookRelayBridgeLookupRetryableForTests: (error: unknown, elapsedMs?: number) => boolean; readonly formatPermissionApprovalDescriptionForTests: (request: NativeHookRelayPermissionApprovalRequest) => string; readonly permissionRequestContentFingerprintForTests: (request: NativeHookRelayPermissionApprovalRequest) => string; readonly permissionRequestToolInputKeyFingerprintForTests: (toolInput: Record) => string; readonly setNativeHookRelayPermissionApprovalRequesterForTests: (requester: NativeHookRelayPermissionApprovalRequester) => void; readonly setNativeHookRelayDeferredToolApprovalRequesterForTests: (requester: NativeHookRelayDeferredToolApprovalRequester) => void;};","entrypoint":"agent-harness-runtime","exportName":"nativeHookRelayTesting","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"const","recordType":"export"} +{"closureHash":"3e5249851db00013b4755ad9834fcd8bb1f596a83154ab6525f69fcec12fe234","declaration":"export const nativeHookRelayTesting: { readonly clearNativeHookRelaysForTests: () => void; readonly getNativeHookRelayInvocationsForTests: () => NativeHookRelayInvocation[]; readonly getNativeHookRelayRegistrationForTests: (relayId: string) => NativeHookRelayRegistration | undefined; readonly getNativeHookRelayBridgeDirForTests: () => string; readonly getNativeHookRelayBridgeRegistryPathForTests: (relayId: string) => string; readonly getNativeHookRelayBridgeRecordForTests: (relayId: string) => Record | undefined; readonly isNativeHookRelayBridgeLookupRetryableForTests: (error: unknown, elapsedMs?: number) => boolean; readonly formatPermissionApprovalDescriptionForTests: (request: NativeHookRelayPermissionApprovalRequest) => string; readonly permissionRequestContentFingerprintForTests: (request: NativeHookRelayPermissionApprovalRequest) => string; readonly permissionRequestToolInputKeyFingerprintForTests: (toolInput: Record) => string; readonly setNativeHookRelayPermissionApprovalRequesterForTests: (requester: NativeHookRelayPermissionApprovalRequester) => void; readonly setNativeHookRelayDeferredToolApprovalRequesterForTests: (requester: NativeHookRelayDeferredToolApprovalRequester) => void;};","entrypoint":"agent-harness-runtime","exportName":"nativeHookRelayTesting","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"const","recordType":"export"} {"closureHash":"f237bbc11e1d389679cd4e2ad7aa9055951b3029348e3374b81f769786a51d55","declaration":"export type AbortAndDrainAgentHarnessRunResult = AbortAndDrainEmbeddedAgentRunResult;","entrypoint":"agent-harness-runtime","exportName":"AbortAndDrainAgentHarnessRunResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"6f802f46717d28d260bbcb2cf4790dfed4e9ab28c4fe822d259228189cca4665","declaration":"export type AgentApprovalEventData = AgentApprovalEventData;","entrypoint":"agent-harness-runtime","exportName":"AgentApprovalEventData","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"12aac3a57ce200b0f082002be237625729f84ed7c337f1bac90bcd0688a53319","declaration":"export type AgentEventPayload = AgentEventPayload;","entrypoint":"agent-harness-runtime","exportName":"AgentEventPayload","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"d759a25775cb15d3f1804e39e98518f83b67b29ba3ab2fd84d4bf16106d9fdb9","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness-runtime","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"d759a25775cb15d3f1804e39e98518f83b67b29ba3ab2fd84d4bf16106d9fdb9","declaration":"export type AgentHarnessAttemptParams = AgentHarnessAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"acb796810881f352798f8026ebebc9ba1ce3faf3286785e4b9a964367ebd24d9","declaration":"export type AgentHarnessAttemptParamsV2 = AgentHarnessAttemptParamsV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"cff7e843ff24f7db2fd0f413d247310c86216bd9b51393b64c22f0ef85cda68e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"agent-harness-runtime","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"cff7e843ff24f7db2fd0f413d247310c86216bd9b51393b64c22f0ef85cda68e","declaration":"export type AgentHarnessAttemptParams = AgentHarnessAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"9bb57b4386260763227e18aa2ba12bb785f760210844d4f9d25f931db493c8aa","declaration":"export type AgentHarnessAttemptParamsV2 = AgentHarnessAttemptParamsV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"2dc2a62deea63b316142cc28d40afb88fb0d1e5ce3e048f141420726cda38248","declaration":"export type AgentHarnessAttemptResult = AgentHarnessAttemptResult;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAttemptResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"c7e642234081160830fd9e18a301900f8ee1ea8c88382e5a286f0102de65b714","declaration":"export type AgentHarnessAuthBindingFingerprintParams = AgentHarnessAuthBindingFingerprintParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessAuthBindingFingerprintParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"8f496ce75f294f2aa440a49c3c5b065ddff3a4714df775116af5e53f7fd14fe5","declaration":"export type AgentHarnessCompactParams = CompactEmbeddedAgentSessionParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessCompactParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -239,8 +239,8 @@ {"closureHash":"95741b872a194687696eba4a96d6e887ec6e81922695fa0282cb2f0a46ff9f97","declaration":"export type AgentHarnessSessionForkParams = AgentHarnessSessionForkParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSessionForkParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"f3c46fef2a6c3393b0b6ad09915abcd6f57bb58ddddde1d60ebd113c7a1c5fa6","declaration":"export type AgentHarnessSessionForkResult = AgentHarnessSessionForkResult;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSessionForkResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"4b5a59730309e446f59a8ec1c554c3193aca1959916594cc657347098bd67a35","declaration":"export type AgentHarnessSettledTurnFinalizationResult = AgentHarnessSettledTurnFinalizationResult;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSettledTurnFinalizationResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"e2c320165e7f072dd5d053d82be3fa5db3b3648112d39a3b40e393d92b07033a","declaration":"export type AgentHarnessSideQuestionParams = AgentHarnessSideQuestionParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSideQuestionParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"1311982296ef9a93957c4559b85e87fc6f3e414476b5c77418df522d2312f795","declaration":"export type AgentHarnessSideQuestionParamsV2 = AgentHarnessSideQuestionParamsV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSideQuestionParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"717e607091ebd5563ff5d922e2da88958e15d038f02fb07cb4efc21f307f5ad3","declaration":"export type AgentHarnessSideQuestionParams = AgentHarnessSideQuestionParams;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSideQuestionParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"cbcf0defea227508b796290592c85270b2947c4ab1d4bf20edd409aee14a1de0","declaration":"export type AgentHarnessSideQuestionParamsV2 = AgentHarnessSideQuestionParamsV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSideQuestionParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"e84173055503c40dd0ef1cb67c6d333e9257fcf995252b27c1d58f5c904e8de9","declaration":"export type AgentHarnessSideQuestionResult = AgentHarnessSideQuestionResult;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSideQuestionResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"50214d08dac98e3c1031ac7bc733b85cb2247d2eef3b6b2045758ae403af7647","declaration":"export type AgentHarnessSupport = AgentHarnessSupport;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSupport","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"50ce26ea22bc225e6064d2e5f37356b6f4ce4a57f8b9fa42baa4c421da48aad5","declaration":"export type AgentHarnessSupportContext = AgentHarnessSupportContext;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessSupportContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -250,7 +250,7 @@ {"closureHash":"20a8a7c9d5ebf425c30d04eea3856c6c889a210f1fa53c99299df24882afbf92","declaration":"export type AgentHarnessUserInputOption = AgentHarnessUserInputOption;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessUserInputOption","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"6224f51b4189f10a642ad7a8f50a902ec9c6a6a4f8dac0c0de5f7bc0271a27e5","declaration":"export type AgentHarnessUserInputPromptOptions = AgentHarnessUserInputPromptOptions;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessUserInputPromptOptions","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"d8f1d0d118e1536d1f442d11aeae5334a1ed7949a6c61824f547e12931278e1d","declaration":"export type AgentHarnessUserInputQuestion = AgentHarnessUserInputQuestion;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessUserInputQuestion","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"bd666466495cef203461f4484eb439faa6a4fd10756c44a64a45ddef3b65961c","declaration":"export type AgentHarnessV2 = AgentHarnessV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"7a05a2ecbd984f18210eca5d9c4e06b0f051279e1a9d830c4924969eb3982f76","declaration":"export type AgentHarnessV2 = AgentHarnessV2;","entrypoint":"agent-harness-runtime","exportName":"AgentHarnessV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"6f2af683e6a31cde5a473c77e4f03b8f0ec0351a43ea6c0af979d5b394a33f95","declaration":"export type AgentMessage = AgentMessage;","entrypoint":"agent-harness-runtime","exportName":"AgentMessage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"4ad0f830bf11a2db48faefb1439b7fbb08d9f22d22083f5e301327e1696f2310","declaration":"export type AgentToolResultMiddleware = AgentToolResultMiddleware;","entrypoint":"agent-harness-runtime","exportName":"AgentToolResultMiddleware","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"185abd2870d4df65e9f94623061a30167d17ef1279a395201fe429398bf23500","declaration":"export type AgentToolResultMiddlewareContext = AgentToolResultMiddlewareContext;","entrypoint":"agent-harness-runtime","exportName":"AgentToolResultMiddlewareContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -276,8 +276,8 @@ {"closureHash":"f30b66fd82f4cd61c60880c42a3b8f152ca64a2216036c99ab4129648ed329e7","declaration":"export type EmbeddedAgentCompactResult = EmbeddedAgentCompactResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedAgentCompactResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"1bbefad0193436f7340f9d0dec50be5d482973325c3c65170b1053dd05566f0a","declaration":"export type EmbeddedContextFile = EmbeddedContextFile;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedContextFile","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"f30b66fd82f4cd61c60880c42a3b8f152ca64a2216036c99ab4129648ed329e7","declaration":"export type EmbeddedPiCompactResult = EmbeddedAgentCompactResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedPiCompactResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"7cce5f7355df47a66ed208855889b16b2c40782a75575e8e1a8dce43517b801f","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"b56f77aa308700cc9ea82f50957a860852d0c83c006b5020d97f0d9b2d6c9d6a","declaration":"export type EmbeddedRunAttemptParamsV2 = EmbeddedRunAttemptParamsV2;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"02942c94049e128ca9e7ed1421bc3f6f6bcbb8b3818da0d727265be34a83ca04","declaration":"export type EmbeddedRunAttemptParams = EmbeddedRunAttemptParams;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParams","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"bcbecd46dae3e3baa0c248d56356292426a63609aad44039fd6f5f1276bff73f","declaration":"export type EmbeddedRunAttemptParamsV2 = EmbeddedRunAttemptParamsV2;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptParamsV2","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"a6cd2eebe0d06e6578ec8438a207c5acda10ddf01041102d84e4c576a0b6a42f","declaration":"export type EmbeddedRunAttemptResult = EmbeddedRunAttemptResult;","entrypoint":"agent-harness-runtime","exportName":"EmbeddedRunAttemptResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"f6cb2d6411db22cb04220777720d97bcca977351de1cb344ce2ff6ab126a3a08","declaration":"export type ExecApprovalDecision = ExecApprovalDecision;","entrypoint":"agent-harness-runtime","exportName":"ExecApprovalDecision","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"7acb0dffc7bcda6c727e4afc49c955fa8e14f4f8b7b45d197ed794dfa0d73b8e","declaration":"export type ExecAutoReviewDecision = ExecAutoReviewDecision;","entrypoint":"agent-harness-runtime","exportName":"ExecAutoReviewDecision","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -293,7 +293,7 @@ {"closureHash":"d8a720bf250da8daf4dc6a52087aa8728ec33b650b3ad3906fcb40e184de66a0","declaration":"export type NativeHookRelayEvent = \"pre_tool_use\" | \"post_tool_use\" | \"permission_request\" | \"before_agent_finalize\";","entrypoint":"agent-harness-runtime","exportName":"NativeHookRelayEvent","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"cb72ca18e056e52e779d0bf5b67606e1dc160f225225b55937304541105027f4","declaration":"export type NativeHookRelayProcessResponse = NativeHookRelayProcessResponse;","entrypoint":"agent-harness-runtime","exportName":"NativeHookRelayProcessResponse","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"6ee390ae4784b987e22255c16884fb4171033bbfaefaef655e3dd2a2513814a5","declaration":"export type NativeHookRelayProvider = \"codex\";","entrypoint":"agent-harness-runtime","exportName":"NativeHookRelayProvider","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"389e3f59bfd6a95d6edeeb1afc2dbd51e6b26828fda9bbcdef480d7314962976","declaration":"export type NativeHookRelayRegistrationHandle = NativeHookRelayRegistrationHandle;","entrypoint":"agent-harness-runtime","exportName":"NativeHookRelayRegistrationHandle","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"67a6d6b90ddec773f8be410c658c95c7632bf87cc2558f364e35f0dd8ce14e7b","declaration":"export type NativeHookRelayRegistrationHandle = NativeHookRelayRegistrationHandle;","entrypoint":"agent-harness-runtime","exportName":"NativeHookRelayRegistrationHandle","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"90fea3155b5d32c22da90460fdaea94e4fd6895d1ca18613d5036ba9835153f9","declaration":"export type NodeListNode = NodeListNode;","entrypoint":"agent-harness-runtime","exportName":"NodeListNode","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"cefe1325c866f0cf7edbec5dcca2fe420237eedc0da172e54094e365894d205d","declaration":"export type NormalizedUsage = NormalizedUsage;","entrypoint":"agent-harness-runtime","exportName":"NormalizedUsage","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"25c6985c3bef2c6efc6a96e70af6d66fe073be0b0d311681cfc0dfc186528d9a","declaration":"export type OpenClawAgentToolResult = OpenClawAgentToolResult;","entrypoint":"agent-harness-runtime","exportName":"OpenClawAgentToolResult","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -301,7 +301,7 @@ {"closureHash":"76ea2a9e92e8e8830b281d6aba00c33594e680d13600004ac1d7c8403f7d1d97","declaration":"export type RuntimeToolInputSchemaJson = RuntimeToolInputSchemaJson;","entrypoint":"agent-harness-runtime","exportName":"RuntimeToolInputSchemaJson","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"8890b76e12d09d7be78431b1d3f6cda33f01f42ab77e663d00d994aaec19450b","declaration":"export type RuntimeToolInputSchemaProjection = RuntimeToolInputSchemaProjection;","entrypoint":"agent-harness-runtime","exportName":"RuntimeToolInputSchemaProjection","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"4bafe42be9314992dc91904c0e819dc8fde9622f64d6a0692b3464d6c5960b68","declaration":"export type RuntimeToolSchemaDiagnostic = RuntimeToolSchemaDiagnostic;","entrypoint":"agent-harness-runtime","exportName":"RuntimeToolSchemaDiagnostic","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} -{"closureHash":"703fc83a60b9cb59fdf456118c011fd77bebdf23ce631c2fd39809974cc415ba","declaration":"export type SandboxContext = SandboxContext;","entrypoint":"agent-harness-runtime","exportName":"SandboxContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} +{"closureHash":"8047a139df75cf6122dca8f9a2bf94d771e7d0d22b0920445ff4bbda24c5cd30","declaration":"export type SandboxContext = SandboxContext;","entrypoint":"agent-harness-runtime","exportName":"SandboxContext","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"20064efc037fedb3317e41819e22f77dece60d79d5d9a0cb15ae45b2ddd5ed36","declaration":"export type SandboxWorkspaceAccess = SandboxWorkspaceAccess;","entrypoint":"agent-harness-runtime","exportName":"SandboxWorkspaceAccess","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"c0a9b60ee19d241903cd8393d8b0f47c8bd2c93975fb0d8610d9b118bb4bde30","declaration":"export type SessionMcpRuntime = SessionMcpRuntime;","entrypoint":"agent-harness-runtime","exportName":"SessionMcpRuntime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} {"closureHash":"aad0f56093883431bcc1b035a2c99371c3c58cb1d53d7dc71c6fccb93722dd01","declaration":"export type SessionWriteLockAcquireTimeoutConfig = OpenClawConfig;","entrypoint":"agent-harness-runtime","exportName":"SessionWriteLockAcquireTimeoutConfig","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime","kind":"type","recordType":"export"} @@ -315,7 +315,7 @@ {"closureHash":"666634000ee5bf317dabcbd70524833961fad58edc2b3cd66fe5fa0172e89602","declaration":"export function getAgentScopedMediaLocalRoots(cfg: OpenClawConfig, agentId?: string): readonly string[];","entrypoint":"agent-media-payload","exportName":"getAgentScopedMediaLocalRoots","importSpecifier":"openclaw/plugin-sdk/agent-media-payload","kind":"function","recordType":"export"} {"closureHash":"160c685c3f4e7ed80fb24d3d76655a182116efe6a7b985bb3bc57b89fe436d2a","declaration":"export type AgentMediaPayload = AgentMediaPayload;","entrypoint":"agent-media-payload","exportName":"AgentMediaPayload","importSpecifier":"openclaw/plugin-sdk/agent-media-payload","kind":"type","recordType":"export"} {"category":"runtime","entrypoint":"agent-runtime","importSpecifier":"openclaw/plugin-sdk/agent-runtime","recordType":"module"} -{"closureHash":"d676259fd3157772725733326c64420d7b5d750225551ac6501664954281135a","declaration":"export function agentCommandFromIngress(opts: AgentCommandIngressOpts, runtime?: RuntimeEnv, deps?: CliDeps): Promise<{ payloads: ReturnType; meta: EmbeddedAgentRunMeta; didSendViaMessagingTool?: boolean; messagingToolSentTexts?: string[]; messagingToolSentMediaUrls?: string[]; messagingToolSentTargets?: MessagingToolSend[]; deliverySucceeded?: boolean; deliveryStatus?: { requested: true; attempted: boolean; status: \"sent\" | \"suppressed\" | \"partial_failed\" | \"failed\"; succeeded: true | false | \"partial\"; error?: true; errorMessage?: string; reason?: string; resultCount?: number; sentBeforeError?: true; payloadOutcomes?: SerializedDurableMessagePayloadOutcome[]; }; }>;","entrypoint":"agent-runtime","exportName":"agentCommandFromIngress","importSpecifier":"openclaw/plugin-sdk/agent-runtime","kind":"function","recordType":"export"} +{"closureHash":"026d8014866b7337c12525e09ed5cf46e6211558fc80a05cb3c842b7b967ff0e","declaration":"export function agentCommandFromIngress(opts: AgentCommandIngressOpts, runtime?: RuntimeEnv, deps?: CliDeps): Promise<{ payloads: ReturnType; meta: EmbeddedAgentRunMeta; didSendViaMessagingTool?: boolean; messagingToolSentTexts?: string[]; messagingToolSentMediaUrls?: string[]; messagingToolSentTargets?: MessagingToolSend[]; deliverySucceeded?: boolean; deliveryStatus?: { requested: true; attempted: boolean; status: \"sent\" | \"suppressed\" | \"partial_failed\" | \"failed\"; succeeded: true | false | \"partial\"; error?: true; errorMessage?: string; reason?: string; resultCount?: number; sentBeforeError?: true; payloadOutcomes?: SerializedDurableMessagePayloadOutcome[]; }; }>;","entrypoint":"agent-runtime","exportName":"agentCommandFromIngress","importSpecifier":"openclaw/plugin-sdk/agent-runtime","kind":"function","recordType":"export"} {"closureHash":"cb95256473d5489ef80ec3e1d93c6a612b2cc733c26ab535f945f8797995b5cb","declaration":"export function buildConfiguredModelCatalog(params: { cfg: OpenClawConfig; workspaceDir?: string; manifestPlugins?: ModelManifestPlugins; }): ModelCatalogEntry[];","entrypoint":"agent-runtime","exportName":"buildConfiguredModelCatalog","importSpecifier":"openclaw/plugin-sdk/agent-runtime","kind":"function","recordType":"export"} {"closureHash":"4a71b73b60d846e9d99fa3881cb72eb7eaaebe7b3386b6bcbaa6cfa46eb3a073","declaration":"export function buildModelAliasIndex(params: BuildModelAliasIndexParams): ModelAliasIndex;","entrypoint":"agent-runtime","exportName":"buildModelAliasIndex","importSpecifier":"openclaw/plugin-sdk/agent-runtime","kind":"function","recordType":"export"} {"closureHash":"ae0f930ec291a0345c4e99e247711465a5d29a8bbdd63968900fa69f382b3a78","declaration":"export function clearExpiredCooldowns(store: AuthProfileStore, now?: number): boolean;","entrypoint":"agent-runtime","exportName":"clearExpiredCooldowns","importSpecifier":"openclaw/plugin-sdk/agent-runtime","kind":"function","recordType":"export"} @@ -762,7 +762,7 @@ {"closureHash":"9fc7e45343d7bfbc6ed56d05c9f824e2f9cf6dafc3ca4b25437d1f65c2200727","declaration":"export function clearAccountEntryFields(params: { accounts?: Record; accountId: string; fields: string[]; isValueSet?: (value: unknown) => boolean; markClearedOnFieldPresence?: boolean; }): { nextAccounts?: Record; changed: boolean; cleared: boolean; };","entrypoint":"channel-core","exportName":"clearAccountEntryFields","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"f4e084b64b5376268885a73fe507aa5d72bee17a88ec2d7ae1d19b36ea5f1ccb","declaration":"export function createChannelConfigUiHints(params: { channelLabel: string; dmPolicy?: { channelKey: string; includeLegacyNestedPolicy?: boolean; legacyNestedPolicyOrder?: \"before\" | \"after\"; }; configWrites?: boolean; mentionPatterns?: { targetDescription: string; policyTargetDescription?: string; policyNote?: string; denyNote?: string; }; nativeCommands?: boolean; implicitMentions?: boolean; progress?: { includeCommentary?: boolean; commentaryOrder?: \"before-command\" | \"after-command\"; labels?: \"openclaw\"; titleWording?: boolean; }; streaming?: Partial>; retry?: boolean; }): HintMap;","entrypoint":"channel-core","exportName":"createChannelConfigUiHints","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"9e93bcdfc6299e65ef2a3d267047a9e8c856f0b2f8e9b79d570fb2a4cd238c74","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"channel-core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} -{"closureHash":"ad9a5a09235e9a426da9b310cd466830ad103dda2e5ce4891ef4131fdf50deda","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"channel-core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} +{"closureHash":"cb5d7b4d9caafb5d1eaa57839fe6cb95e714bac30f9b697c720b32913c22eec5","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"channel-core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"0e0a9f6b22c433bdb1165e7707b1f9a1ddac1a544a8add00b503048cf157921f","declaration":"export function defineSetupPluginEntry(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"channel-core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"8895f7af11b994dcd383ebc45d8cfb3c3b1e6d88a64a001b04f604a83f77e517","declaration":"export function parseOptionalDelimitedEntries(value?: string): string[] | undefined;","entrypoint":"channel-core","exportName":"parseOptionalDelimitedEntries","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} {"closureHash":"3f97534b10d08eda6a556044eaba623b3744b200a2033877e48d2f2ca924d298","declaration":"export function recoverCurrentThreadSessionId(params: { route: ChannelOutboundSessionRoute; currentSessionKey?: string | null; canRecover?: (context: ThreadAwareOutboundSessionRouteRecoveryContext) => boolean; }): string | undefined;","entrypoint":"channel-core","exportName":"recoverCurrentThreadSessionId","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"function","recordType":"export"} @@ -774,26 +774,26 @@ {"closureHash":"8126b651a679d5435eaa5d346916792c3600e5f0f75d8492b077dd361854f7dd","declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; currentSessionKey?: string; resolvedTarget?: { to: string; kind: ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"channel-core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"d02e5c7a995847180696d2a05d8ea092b364ef32b36753e4091fc97ffdaf44ab","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"channel-core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} -{"closureHash":"d9d24565b06f891a687f49672129beac9d38ccb817526ed1a6579efcb5825eb0","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} +{"closureHash":"5c7a4e89ddfb6bed00f2ca8e67e43f150fedb3182275a525411365855d581c22","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-core","kind":"type","recordType":"export"} {"category":"channel","entrypoint":"channel-dm-policy","importSpecifier":"openclaw/plugin-sdk/channel-dm-policy","recordType":"module"} {"closureHash":"821fe6ccd0d9323322bf70c4d1ca5697071a0e32032f44c1e14157162c2c729d","declaration":"export function createChannelDmPolicy(params: CreateChannelDmPolicyParams): ChannelSetupDmPolicy & { promptAllowFrom: NonNullable; };","entrypoint":"channel-dm-policy","exportName":"createChannelDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-dm-policy","kind":"function","recordType":"export"} {"category":null,"entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","recordType":"module"} -{"closureHash":"5885bf21e94629126fa96a1a953d2c913eeeaac3fc603e9d23846e0700b53835","declaration":"export function defineBundledChannelEntry({ id, name, description, importMetaUrl, plugin, outbound, secrets, configSchema, runtime, accountInspect, features, registerCliMetadata, registerFull, registerCapabilities, }: DefineBundledChannelEntryOptions): BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} -{"closureHash":"237c32c30b7f6979b8e955acfd6520db3ac2d98a3c46539c3b083d5d1af48247","declaration":"export function defineBundledChannelSetupEntry({ importMetaUrl, plugin, secrets, runtime, legacyStateMigrations, legacySessionSurface, registerSetupRuntime, features, }: DefineBundledChannelSetupEntryOptions): BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelSetupEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} +{"closureHash":"f77c4528b2e7bb9a16d6fd36f1ac0dc1651c33907ffaf66111bdb28c2406aee8","declaration":"export function defineBundledChannelEntry({ id, name, description, importMetaUrl, plugin, outbound, secrets, configSchema, runtime, accountInspect, features, registerCliMetadata, registerFull, registerCapabilities, }: DefineBundledChannelEntryOptions): BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} +{"closureHash":"25ffae2b8663333380eae5ee2286e6b0cb4d06bfac849a69574dd29d950b39cd","declaration":"export function defineBundledChannelSetupEntry({ importMetaUrl, plugin, secrets, runtime, legacyStateMigrations, legacySessionSurface, registerSetupRuntime, features, }: DefineBundledChannelSetupEntryOptions): BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"defineBundledChannelSetupEntry","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} {"closureHash":"cd150287d7e286e7a0d7d6caeb05d0a1efa63b5f351f75f69ba932510a108afd","declaration":"export function loadBundledEntryExportSync(importMetaUrl: string, reference: BundledEntryModuleRef, options?: BundledEntryModuleLoadOptions): T;","entrypoint":"channel-entry-contract","exportName":"loadBundledEntryExportSync","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"function","recordType":"export"} {"closureHash":"7781a3d570d08929af5b3b6cffbb9ef4b9c8e8f1bed55234e0015a681868c812","declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"channel-entry-contract","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"4b7913e3376b2de7370a5970d8330e81f65574e173a313aec21d5dc5428007dd","declaration":"export type BundledChannelEntryContract = BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"03429702fb0781aa0d7082d1ff87b45591c87a19e466c0905ddd3150eb52ceed","declaration":"export type BundledChannelEntryContract = BundledChannelEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"f4b82dfd995bd6f08b232984743389d1c854866cb845a8dbb3605acb28818688","declaration":"export type BundledChannelEntryFeatures = BundledChannelEntryFeatures;","entrypoint":"channel-entry-contract","exportName":"BundledChannelEntryFeatures","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"960693591b9bdc974bf3f0097076d90490078db3dceb35349a4f851736cde4fc","declaration":"export type BundledChannelLegacySessionSurface = BundledChannelLegacySessionSurface;","entrypoint":"channel-entry-contract","exportName":"BundledChannelLegacySessionSurface","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"edf79e6a736e5c4977e3b86ef21e7fdf0c0b2bc7deacd8edbee2ca76cb8cef43","declaration":"export type BundledChannelLegacyStateMigrationDetector = BundledChannelLegacyStateMigrationDetector;","entrypoint":"channel-entry-contract","exportName":"BundledChannelLegacyStateMigrationDetector","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"882a849a3b180ad11b9622cd5d38b932012672f8a7b7b67c229874bb1862ac48","declaration":"export type BundledChannelSetupEntryContract = BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"eb8b57b4881cd186859785495a839aef13bf2e0e2db73970f0b3c804d4f1ea0a","declaration":"export type BundledChannelSetupEntryContract = BundledChannelSetupEntryContract;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryContract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"24679ecdf2ff34157b6345a37b58ec1363ec8cb1969b522599d0d92bb7a113b7","declaration":"export type BundledChannelSetupEntryFeatures = BundledChannelSetupEntryFeatures;","entrypoint":"channel-entry-contract","exportName":"BundledChannelSetupEntryFeatures","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"closureHash":"367219c821915e5be4d1ba3a86754475a5f8a4194512f0401de3be11cc649c60","declaration":"export type BundledEntryModuleLoadOptions = BundledEntryModuleLoadOptions;","entrypoint":"channel-entry-contract","exportName":"BundledEntryModuleLoadOptions","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"d092260da21786feb5266e642269dc90807ac6a33131fffa66641d95b7544145","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"2a50f49bf524a67b6554ad9e3afc32487403828d09f966191930f7bb701032a1","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} -{"closureHash":"627f955848f6970b3fce5e72f1ccccc136636d67355114ce38aedd886be38db8","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-entry-contract","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"e8d7213538f783ac83a73a2ca082cacdb2011c278d1473a07bc3d667e54a9e09","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"250bf729ec31603b908f4a24cfcd7b732b58c7d362d2fd6aebbb9a82a6948895","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"channel-entry-contract","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} +{"closureHash":"cd8d3f56a957044d8c5b62e8f212989ffa77c2ea4d865c094d417097f3d45758","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"channel-entry-contract","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-feedback","importSpecifier":"openclaw/plugin-sdk/channel-feedback","recordType":"module"} {"closureHash":"83654579574c8101c8158b4d1a49bd0f72918c26e588d86ac0079aab94bf04de","declaration":"export function createAckReactionHandle(params: { ackReactionValue: string; send: () => Promise; remove: () => Promise; onSendError?: (err: unknown) => void; }): AckReactionHandle | null;","entrypoint":"channel-feedback","exportName":"createAckReactionHandle","importSpecifier":"openclaw/plugin-sdk/channel-feedback","kind":"function","recordType":"export"} {"closureHash":"16650e7e9aa18195bea992878a273fa2ef564d088dcb872d895387f033fa76f0","declaration":"export function createStatusReactionController(params: { enabled: boolean; adapter: StatusReactionAdapter; initialEmoji: string; emojis?: StatusReactionEmojis; timing?: StatusReactionTiming; onError?: (err: unknown) => void; }): StatusReactionController;","entrypoint":"channel-feedback","exportName":"createStatusReactionController","importSpecifier":"openclaw/plugin-sdk/channel-feedback","kind":"function","recordType":"export"} @@ -821,9 +821,9 @@ {"closureHash":"4f135bb1dd373312335c02196378368edc69f7512f48bf6d4f6a498c14340484","declaration":"export type StatusReactionEmojis = StatusReactionEmojis;","entrypoint":"channel-feedback","exportName":"StatusReactionEmojis","importSpecifier":"openclaw/plugin-sdk/channel-feedback","kind":"type","recordType":"export"} {"closureHash":"b673ec55cb115a9cb6b6cba97c839410e36e4d4ddfcca5998ff01876521c9e72","declaration":"export type StatusReactionTiming = StatusReactionTiming;","entrypoint":"channel-feedback","exportName":"StatusReactionTiming","importSpecifier":"openclaw/plugin-sdk/channel-feedback","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-inbound","importSpecifier":"openclaw/plugin-sdk/channel-inbound","recordType":"module"} -{"closureHash":"5012e0bfbfba5f68bff8032ccc56082af2a293e314c340bf250c6a2431ca9c7f","declaration":"export function buildChannelInboundEventContext(params: BuildChannelInboundEventContextAsyncParams): Promise;\nexport function buildChannelInboundEventContext(params: BuildChannelInboundEventContextParams): BuiltChannelInboundEventContext;","entrypoint":"channel-inbound","exportName":"buildChannelInboundEventContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} +{"closureHash":"b44ede4b85c989679776daa75f72997abbb657747753d3ef1569c03799efd36b","declaration":"export function buildChannelInboundEventContext(params: BuildChannelInboundEventContextAsyncParams): Promise;\nexport function buildChannelInboundEventContext(params: BuildChannelInboundEventContextParams): BuiltChannelInboundEventContext;","entrypoint":"channel-inbound","exportName":"buildChannelInboundEventContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"8daae3e9dc0e1f6e45f95615d485e25486f261bae83544e6cda331000426a252","declaration":"export function buildChannelInboundMediaPayload(media: readonly InboundMediaFacts[] | null | undefined): ChannelInboundMediaPayload;","entrypoint":"channel-inbound","exportName":"buildChannelInboundMediaPayload","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} -{"closureHash":"a52bb66fff7d6657b879035a98d4cdbe9d40b2675972e1b2f00d79a8e8e1368c","declaration":"export function buildChannelTurnContext(params: BuildChannelTurnContextParams): BuiltChannelTurnContext;","entrypoint":"channel-inbound","exportName":"buildChannelTurnContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} +{"closureHash":"29ed4d823625495cacf13271ae6966e83cc68b75aaf14c8d1b1333eb9326c168","declaration":"export function buildChannelTurnContext(params: BuildChannelTurnContextParams): BuiltChannelTurnContext;","entrypoint":"channel-inbound","exportName":"buildChannelTurnContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"8daae3e9dc0e1f6e45f95615d485e25486f261bae83544e6cda331000426a252","declaration":"export function buildChannelTurnMediaPayload(media: readonly InboundMediaFacts[] | null | undefined): ChannelInboundMediaPayload;","entrypoint":"channel-inbound","exportName":"buildChannelTurnMediaPayload","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"72ebf6b52c0fade0e853243f6d6b499827686a0209a76f1f78b4942226a348eb","declaration":"export function buildMentionRegexes(cfg: OpenClawConfig | undefined, agentId?: string, options?: BuildMentionRegexesOptions): RegExp[];","entrypoint":"channel-inbound","exportName":"buildMentionRegexes","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"dcdbfc4a83fac3936097c3976f2400ac22afd9e953c8a6ba3bd91da42822b32c","declaration":"export function classifyChannelInboundEvent(params: ClassifyChannelInboundEventParams): InboundEventKind;","entrypoint":"channel-inbound","exportName":"classifyChannelInboundEvent","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} @@ -837,7 +837,7 @@ {"closureHash":"552aa82911f9aba585fee69fc351990ad892bd0ba4dd20e69ce6d3c286efc6d4","declaration":"export function dispatchChannelInboundReply(params: AssembledInboundReply): Promise;","entrypoint":"channel-inbound","exportName":"dispatchChannelInboundReply","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"3090e3a3315715d8cc2107bf9a577446dc8bc30b05642f5c643b797f79fbb97e","declaration":"export function dispatchChannelInboundTurn(params: ChannelInboundTurnPlan<\"provider_message_sending\">): Promise;\nexport function dispatchChannelInboundTurn(params: ChannelInboundTurnPlan): Promise;","entrypoint":"channel-inbound","exportName":"dispatchChannelInboundTurn","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"2f997d08980c2c3f531382428c58204ca04e423a64ca201798f7667da15e774e","declaration":"export function dispatchInboundDirectDm(params: DispatchInboundDirectDmParams): Promise<{ route: DirectDmRoute; ctxPayload: FinalizedMsgContext; }>;","entrypoint":"channel-inbound","exportName":"dispatchInboundDirectDm","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} -{"closureHash":"cdf4018d7d355ec02e9126fa21dc9061acda9d2f5612ef590ce0fb4011edf2b3","declaration":"export function dispatchInboundDirectDmWithRuntime(params: DispatchInboundDirectDmParams & { runtime: PluginRuntime; }): Promise<{ route: DirectDmRoute; storePath: string; ctxPayload: FinalizedMsgContext; }>;","entrypoint":"channel-inbound","exportName":"dispatchInboundDirectDmWithRuntime","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} +{"closureHash":"7a8053396c7d9845b096cfe7f930b8e78dbe2401f69c1371a72a810845bfeba3","declaration":"export function dispatchInboundDirectDmWithRuntime(params: DispatchInboundDirectDmParams & { runtime: PluginRuntime; }): Promise<{ route: DirectDmRoute; storePath: string; ctxPayload: FinalizedMsgContext; }>;","entrypoint":"channel-inbound","exportName":"dispatchInboundDirectDmWithRuntime","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"33cb9d760233f3d322599f7745a42e0b9fe2c653ffb9310d8b579f2d70f7638c","declaration":"export function filterChannelInboundQuoteContext(contextVisibility: ContextVisibilityMode | undefined, quote: SupplementalContextFacts[\"quote\"] | undefined): SupplementalContextFacts[\"quote\"] | undefined;","entrypoint":"channel-inbound","exportName":"filterChannelInboundQuoteContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"793b9b84aacb8f5b12daf857de82efc579fa018ba6b2357b0acd044be3dcec5f","declaration":"export function filterChannelInboundSupplementalContext(params: { supplemental?: SupplementalContextFacts; contextVisibility?: ContextVisibilityMode; }): SupplementalContextFacts | undefined;","entrypoint":"channel-inbound","exportName":"filterChannelInboundSupplementalContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"ff1797f8e6adf2331d98af9947dcefef02d743c2c7619fc8b5a2462980cb7126","declaration":"export function finalizeChannelInboundContext>(params: FinalizeChannelInboundContextAsyncParams): Promise>;\nexport function finalizeChannelInboundContext>(params: FinalizeChannelInboundContextParams): FinalizeChannelInboundContextResult;","entrypoint":"channel-inbound","exportName":"finalizeChannelInboundContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} @@ -862,7 +862,7 @@ {"closureHash":"6b537112d5d84ed07c0b9fd24787eabc2f893f7bfdce1ed5915f88574a7e101c","declaration":"export function normalizeMentionText(text: string): string;","entrypoint":"channel-inbound","exportName":"normalizeMentionText","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"92900098c3cc5b73fba7622a3aa5a1a8c48462ff7ec0cfae8ee0a3aa6f8277f0","declaration":"export function normalizeOutboundLocation(value: unknown, label?: string): OutboundLocation | undefined;","entrypoint":"channel-inbound","exportName":"normalizeOutboundLocation","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"65f5f2725c1124096e437bcf5894983eee1023f7033be886f1a506044b77c58e","declaration":"export function recordChannelBotPairLoopAndCheckSuppression(params: ChannelBotLoopProtectionFacts): PairLoopGuardResult;","entrypoint":"channel-inbound","exportName":"recordChannelBotPairLoopAndCheckSuppression","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} -{"closureHash":"b8271620147b917162fda83897092229d5691a4e418288a79912ae41775e83da","declaration":"export function recordChannelFeedbackEvent(params: { cfg: OpenClawConfig; agentId: string; sessionKey: string; event: Parameters[1]; }): Promise;","entrypoint":"channel-inbound","exportName":"recordChannelFeedbackEvent","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} +{"closureHash":"8fdc2a5a83820b372e4047777ed9fc1bd8e530c68e76da89abb3b6653546e2ab","declaration":"export function recordChannelFeedbackEvent(params: { cfg: OpenClawConfig; agentId: string; sessionKey: string; event: Parameters[1]; }): Promise;","entrypoint":"channel-inbound","exportName":"recordChannelFeedbackEvent","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"33b4280a69de6a4a87acf915c6d694b9ee41fc4f0262a1bb9836c46d53fe337c","declaration":"export function recordDroppedChannelInboundHistory(params: { input: NormalizedTurnInput; preflight: PreflightFacts; admission?: ChannelTurnAdmission; }): Promise;","entrypoint":"channel-inbound","exportName":"recordDroppedChannelInboundHistory","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"33b4280a69de6a4a87acf915c6d694b9ee41fc4f0262a1bb9836c46d53fe337c","declaration":"export function recordDroppedChannelTurnHistory(params: { input: NormalizedTurnInput; preflight: PreflightFacts; admission?: ChannelTurnAdmission; }): Promise;","entrypoint":"channel-inbound","exportName":"recordDroppedChannelTurnHistory","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} {"closureHash":"54b920fd80ac659a03000356b64e34d4a44ec22ae39a77accdd2ac97dc5a094e","declaration":"export function resolveChannelInboundRouteEnvelope(params: ResolveAgentRouteInput): { route: ResolvedAgentRoute; buildEnvelope: (input: ChannelInboundEnvelopeInput) => string; };","entrypoint":"channel-inbound","exportName":"resolveChannelInboundRouteEnvelope","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"function","recordType":"export"} @@ -887,9 +887,9 @@ {"closureHash":"03bfa4a5365916c2d9f59e4e3c5c6ae3ee7952b2aec209c232bf73a5ccd2ae94","declaration":"export const filterChannelTurnSupplementalContext: (params: { supplemental?: SupplementalContextFacts; contextVisibility?: ContextVisibilityMode;}) => SupplementalContextFacts | undefined;","entrypoint":"channel-inbound","exportName":"filterChannelTurnSupplementalContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"const","recordType":"export"} {"closureHash":"b028978582295be29c22e06673b8f1b48819511b6b8c26cfff9e322ddc2834e3","declaration":"export type AccessGroupMembershipResolver = AccessGroupMembershipResolver;","entrypoint":"channel-inbound","exportName":"AccessGroupMembershipResolver","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} {"closureHash":"10d47ee68a65fa2df62012bf98988026560dd0bc30d2be56783ed4132864a149","declaration":"export type AssembledInboundReply = AssembledChannelTurn;","entrypoint":"channel-inbound","exportName":"AssembledInboundReply","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} -{"closureHash":"16e04f044a9af3553fa26fec210bf6d2e6e101c4fe4db18b8914fce21dce573f","declaration":"export type BuildChannelInboundEventContextAsyncParams = BuildChannelInboundEventContextAsyncParams;","entrypoint":"channel-inbound","exportName":"BuildChannelInboundEventContextAsyncParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} -{"closureHash":"bfda516454e1d03a16f685f9470c8ce4329328d5658b5ca26bc703c70c5d17c8","declaration":"export type BuildChannelInboundEventContextParams = BuildChannelInboundEventContextParams;","entrypoint":"channel-inbound","exportName":"BuildChannelInboundEventContextParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} -{"closureHash":"b6ce3464585a1f042b94574c385dd57ca9be83740ef0fc929db769710dc78061","declaration":"export type BuildChannelTurnContextParams = BuildChannelTurnContextParams;","entrypoint":"channel-inbound","exportName":"BuildChannelTurnContextParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} +{"closureHash":"daa855f59ea9d4082f745a763edd8468bd10ef51e0d18740261067cbe39d712b","declaration":"export type BuildChannelInboundEventContextAsyncParams = BuildChannelInboundEventContextAsyncParams;","entrypoint":"channel-inbound","exportName":"BuildChannelInboundEventContextAsyncParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} +{"closureHash":"ea286077c4c5222cec3f60186d2920ea535e78e29b3ddc0097c6189f8bd36815","declaration":"export type BuildChannelInboundEventContextParams = BuildChannelInboundEventContextParams;","entrypoint":"channel-inbound","exportName":"BuildChannelInboundEventContextParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} +{"closureHash":"90bafa21f065ea6c027f3e40923c34807f265f09f45d4e9bfbb99a0c1179f691","declaration":"export type BuildChannelTurnContextParams = BuildChannelTurnContextParams;","entrypoint":"channel-inbound","exportName":"BuildChannelTurnContextParams","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} {"closureHash":"6d2f3cd2420a24adc0336afba6a24ec41301e83c2796d56c18d1aee69b7eba4b","declaration":"export type BuildMentionRegexesOptions = BuildMentionRegexesOptions;","entrypoint":"channel-inbound","exportName":"BuildMentionRegexesOptions","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} {"closureHash":"c7356eefdaeb352d2552e3f5df112db261cc7043ed4c488b3f3212cc981f112a","declaration":"export type BuiltChannelInboundEventContext = BuiltChannelInboundEventContext;","entrypoint":"channel-inbound","exportName":"BuiltChannelInboundEventContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} {"closureHash":"30712d6ebecf99636dd58269720814c94af71ef9d8bcb818dad50bd3dc82aaca","declaration":"export type BuiltChannelTurnContext = BuiltChannelTurnContext;","entrypoint":"channel-inbound","exportName":"BuiltChannelTurnContext","importSpecifier":"openclaw/plugin-sdk/channel-inbound","kind":"type","recordType":"export"} @@ -1034,7 +1034,7 @@ {"closureHash":"acd64a0d6ce6dbd9db22f9e4a4497cef2110a9e962f240c6f5e90cef31505459","declaration":"export function createFinalizableDraftStreamControlsForState(params: { throttleMs: number; state: FinalizableDraftStreamState; sendOrEditStreamMessage: (value: T) => Promise; emptyValue?: T; isEmpty?: (value: T) => boolean; }): { loop: DraftStreamLoop & { takePending: () => T; }; update: (value: T) => void; stop: () => Promise; seal: () => Promise; discardPending: () => Promise; stopForClear: () => Promise; };","entrypoint":"channel-message","exportName":"createFinalizableDraftStreamControlsForState","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"f2bb1868ec1cf7d97e6b8eb0a9a8a37122ec53c9cd4e2bbfc8448c1555f3d382","declaration":"export function createMessageReceiptFromOutboundResults(params: { results: readonly MessageReceiptInputResult[]; kind?: MessageReceiptPartKind; threadId?: string; replyToId?: string; sentAt?: number; }): MessageReceipt;","entrypoint":"channel-message","exportName":"createMessageReceiptFromOutboundResults","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"3c150fb027a4e4a1685b572d26aa1f70b3838641bd7629434c4265bfda549d0a","declaration":"export function createMessageReceiveContext(params: { id: string; channel: string; accountId?: string; message: TMessage; ackPolicy?: MessageAckPolicy; receivedAt?: number; signal?: AbortSignal; onAck?: () => Promise | void; onNack?: (error: unknown) => Promise | void; }): MessageReceiveContext;","entrypoint":"channel-message","exportName":"createMessageReceiveContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} -{"closureHash":"93906d2c7105382007072ea3e79787732a62828361034e59306d3cd0f5b05a25","declaration":"export function createOutboundPayloadPlan(payloads: readonly ReplyPayload[], context?: OutboundPayloadPlanContext): OutboundPayloadPlan[];","entrypoint":"channel-message","exportName":"createOutboundPayloadPlan","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} +{"closureHash":"1df70a2d9c8a3d6bb0813a5f03c8eea7ed85334428c8cf8e4004c567212a1448","declaration":"export function createOutboundPayloadPlan(payloads: readonly ReplyPayload[], context?: OutboundPayloadPlanContext): OutboundPayloadPlan[];","entrypoint":"channel-message","exportName":"createOutboundPayloadPlan","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"7abc004852a9162c3f4241d6c80b9962c9732dd03d2d38a56e4080a4e92758a1","declaration":"export function createPreviewMessageReceipt(params: { id: unknown; threadId?: string; replyToId?: string; sentAt?: number; raw?: unknown; }): MessageReceipt;","entrypoint":"channel-message","exportName":"createPreviewMessageReceipt","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"449a8d46d726b3de6fdf7aabf60939d37565ef5701ef58dd91b817040712ab87","declaration":"export function createReplyPrefixContext(params: { cfg: OpenClawConfig; agentId: string; channel?: string; accountId?: string; }): ReplyPrefixContextBundle;","entrypoint":"channel-message","exportName":"createReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"acb4b6a4562c6a6ac30594fcd9431a9aabb031135fff7faa41a74067139ab572","declaration":"export function createReplyPrefixOptions(params: { cfg: OpenClawConfig; agentId: string; channel?: string; accountId?: string; }): ReplyPrefixOptions;","entrypoint":"channel-message","exportName":"createReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} @@ -1063,7 +1063,7 @@ {"closureHash":"844a3251dcba84a9735c855d7b6c930570cc486f3a1c5fc49b541572d52bb7d7","declaration":"export function normalizeAgentPlanSteps(value: unknown): AgentPlanStep[] | undefined;","entrypoint":"channel-message","exportName":"normalizeAgentPlanSteps","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"b19d38e15e2054e826fd132198c606165fc369fb5a96f4e6bbbf7b89bee35ac2","declaration":"export function normalizeChannelProgressDraftLineIdentity(line: string | ChannelProgressDraftLine | undefined): string;","entrypoint":"channel-message","exportName":"normalizeChannelProgressDraftLineIdentity","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"ba2389600eeea10867e3891e411bd84e8fd07dcd410249c29ca92ba59ef27bad","declaration":"export function processPidFromOwnerId(ownerId: string): number;","entrypoint":"channel-message","exportName":"processPidFromOwnerId","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} -{"closureHash":"70bfbeeee4a0a2290cbf9620933c2bf7d00fbcaf3c20958c2064f5e2ce5a0bb8","declaration":"export function projectOutboundPayloadPlanForDelivery(plan: readonly OutboundPayloadPlan[]): ReplyPayload[];","entrypoint":"channel-message","exportName":"projectOutboundPayloadPlanForDelivery","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} +{"closureHash":"56fc827d94dd02fdb7eda0269d63e67eed7716da3e373b74b6d2e68ebf797661","declaration":"export function projectOutboundPayloadPlanForDelivery(plan: readonly OutboundPayloadPlan[]): ReplyPayload[];","entrypoint":"channel-message","exportName":"projectOutboundPayloadPlanForDelivery","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"bc16377d8f9c3467da5115ff2d6b3ef0423980794a0f5af287b1f1e8ee9533ef","declaration":"export function recordOutboundMessageIdentity(identity: OutboundMessageIdentity): void;","entrypoint":"channel-message","exportName":"recordOutboundMessageIdentity","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"3090faaaca1e2c970a0eadbb7792c531a053746df6df83a082d8564a8313b401","declaration":"export function resolveAgentOutboundIdentity(cfg: OpenClawConfig, agentId: string): OutboundIdentity | undefined;","entrypoint":"channel-message","exportName":"resolveAgentOutboundIdentity","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} {"closureHash":"ba763bf7ff1dee852fb9b58f5995f9df744028d47ca29f687b215ba316c66723","declaration":"export function resolveChannelDraftStreamingChunking(cfg: OpenClawConfig | undefined, channelId: ChannelId, accountId: string | null | undefined, opts: { fallbackLimit: number; }): ChannelDraftStreamingChunking;","entrypoint":"channel-message","exportName":"resolveChannelDraftStreamingChunking","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"function","recordType":"export"} @@ -1103,7 +1103,7 @@ {"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-message","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-message","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} -{"closureHash":"64792a0c33912731a154f8e8e1b3f598b3396d2e0b93ed35fb4cc67a150bf9e2","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} +{"closureHash":"8b9f39e06d068cd2497a07a2f0ee78c2e5497a58eca6e7e6c2da2ba93535f23c","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-message","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"const","recordType":"export"} {"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-message","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} {"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-message","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} {"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-message","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-message","kind":"type","recordType":"export"} @@ -1166,7 +1166,7 @@ {"closureHash":"acd64a0d6ce6dbd9db22f9e4a4497cef2110a9e962f240c6f5e90cef31505459","declaration":"export function createFinalizableDraftStreamControlsForState(params: { throttleMs: number; state: FinalizableDraftStreamState; sendOrEditStreamMessage: (value: T) => Promise; emptyValue?: T; isEmpty?: (value: T) => boolean; }): { loop: DraftStreamLoop & { takePending: () => T; }; update: (value: T) => void; stop: () => Promise; seal: () => Promise; discardPending: () => Promise; stopForClear: () => Promise; };","entrypoint":"channel-outbound","exportName":"createFinalizableDraftStreamControlsForState","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"f2bb1868ec1cf7d97e6b8eb0a9a8a37122ec53c9cd4e2bbfc8448c1555f3d382","declaration":"export function createMessageReceiptFromOutboundResults(params: { results: readonly MessageReceiptInputResult[]; kind?: MessageReceiptPartKind; threadId?: string; replyToId?: string; sentAt?: number; }): MessageReceipt;","entrypoint":"channel-outbound","exportName":"createMessageReceiptFromOutboundResults","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"3c150fb027a4e4a1685b572d26aa1f70b3838641bd7629434c4265bfda549d0a","declaration":"export function createMessageReceiveContext(params: { id: string; channel: string; accountId?: string; message: TMessage; ackPolicy?: MessageAckPolicy; receivedAt?: number; signal?: AbortSignal; onAck?: () => Promise | void; onNack?: (error: unknown) => Promise | void; }): MessageReceiveContext;","entrypoint":"channel-outbound","exportName":"createMessageReceiveContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} -{"closureHash":"93906d2c7105382007072ea3e79787732a62828361034e59306d3cd0f5b05a25","declaration":"export function createOutboundPayloadPlan(payloads: readonly ReplyPayload[], context?: OutboundPayloadPlanContext): OutboundPayloadPlan[];","entrypoint":"channel-outbound","exportName":"createOutboundPayloadPlan","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} +{"closureHash":"1df70a2d9c8a3d6bb0813a5f03c8eea7ed85334428c8cf8e4004c567212a1448","declaration":"export function createOutboundPayloadPlan(payloads: readonly ReplyPayload[], context?: OutboundPayloadPlanContext): OutboundPayloadPlan[];","entrypoint":"channel-outbound","exportName":"createOutboundPayloadPlan","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"7abc004852a9162c3f4241d6c80b9962c9732dd03d2d38a56e4080a4e92758a1","declaration":"export function createPreviewMessageReceipt(params: { id: unknown; threadId?: string; replyToId?: string; sentAt?: number; raw?: unknown; }): MessageReceipt;","entrypoint":"channel-outbound","exportName":"createPreviewMessageReceipt","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"449a8d46d726b3de6fdf7aabf60939d37565ef5701ef58dd91b817040712ab87","declaration":"export function createReplyPrefixContext(params: { cfg: OpenClawConfig; agentId: string; channel?: string; accountId?: string; }): ReplyPrefixContextBundle;","entrypoint":"channel-outbound","exportName":"createReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"acb4b6a4562c6a6ac30594fcd9431a9aabb031135fff7faa41a74067139ab572","declaration":"export function createReplyPrefixOptions(params: { cfg: OpenClawConfig; agentId: string; channel?: string; accountId?: string; }): ReplyPrefixOptions;","entrypoint":"channel-outbound","exportName":"createReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} @@ -1193,7 +1193,7 @@ {"closureHash":"844a3251dcba84a9735c855d7b6c930570cc486f3a1c5fc49b541572d52bb7d7","declaration":"export function normalizeAgentPlanSteps(value: unknown): AgentPlanStep[] | undefined;","entrypoint":"channel-outbound","exportName":"normalizeAgentPlanSteps","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"b19d38e15e2054e826fd132198c606165fc369fb5a96f4e6bbbf7b89bee35ac2","declaration":"export function normalizeChannelProgressDraftLineIdentity(line: string | ChannelProgressDraftLine | undefined): string;","entrypoint":"channel-outbound","exportName":"normalizeChannelProgressDraftLineIdentity","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"ba2389600eeea10867e3891e411bd84e8fd07dcd410249c29ca92ba59ef27bad","declaration":"export function processPidFromOwnerId(ownerId: string): number;","entrypoint":"channel-outbound","exportName":"processPidFromOwnerId","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} -{"closureHash":"70bfbeeee4a0a2290cbf9620933c2bf7d00fbcaf3c20958c2064f5e2ce5a0bb8","declaration":"export function projectOutboundPayloadPlanForDelivery(plan: readonly OutboundPayloadPlan[]): ReplyPayload[];","entrypoint":"channel-outbound","exportName":"projectOutboundPayloadPlanForDelivery","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} +{"closureHash":"56fc827d94dd02fdb7eda0269d63e67eed7716da3e373b74b6d2e68ebf797661","declaration":"export function projectOutboundPayloadPlanForDelivery(plan: readonly OutboundPayloadPlan[]): ReplyPayload[];","entrypoint":"channel-outbound","exportName":"projectOutboundPayloadPlanForDelivery","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"bc16377d8f9c3467da5115ff2d6b3ef0423980794a0f5af287b1f1e8ee9533ef","declaration":"export function recordOutboundMessageIdentity(identity: OutboundMessageIdentity): void;","entrypoint":"channel-outbound","exportName":"recordOutboundMessageIdentity","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"3090faaaca1e2c970a0eadbb7792c531a053746df6df83a082d8564a8313b401","declaration":"export function resolveAgentOutboundIdentity(cfg: OpenClawConfig, agentId: string): OutboundIdentity | undefined;","entrypoint":"channel-outbound","exportName":"resolveAgentOutboundIdentity","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} {"closureHash":"ba763bf7ff1dee852fb9b58f5995f9df744028d47ca29f687b215ba316c66723","declaration":"export function resolveChannelDraftStreamingChunking(cfg: OpenClawConfig | undefined, channelId: ChannelId, accountId: string | null | undefined, opts: { fallbackLimit: number; }): ChannelDraftStreamingChunking;","entrypoint":"channel-outbound","exportName":"resolveChannelDraftStreamingChunking","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"function","recordType":"export"} @@ -1232,7 +1232,7 @@ {"closureHash":"9555a73ba2717bba0bf94888017be4cecef2c51cc3887ed34f8d8ef3c79d6abf","declaration":"export const DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS: number;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_DEAD_LETTER_MIN_AGE_MS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"3a2df3ab656149630c004d2d9f71b8ceda99aa81eb6b72b0cc7b3982ed0ce044","declaration":"export const DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS: 8;","entrypoint":"channel-outbound","exportName":"DEFAULT_INGRESS_RETRY_MAX_ATTEMPTS","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"38c735a14c65067aa7825390d1c5c8876c651d0603e84980dfaf947f5235747a","declaration":"export const INGRESS_CLAIM_PROCESS_ID: string;","entrypoint":"channel-outbound","exportName":"INGRESS_CLAIM_PROCESS_ID","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} -{"closureHash":"64792a0c33912731a154f8e8e1b3f598b3396d2e0b93ed35fb4cc67a150bf9e2","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} +{"closureHash":"8b9f39e06d068cd2497a07a2f0ee78c2e5497a58eca6e7e6c2da2ba93535f23c","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"channel-outbound","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"const","recordType":"export"} {"closureHash":"2c52eff200a5b9bd2d93ee72209c2626bbe165f59b538591db661b94773023b0","declaration":"export type AgentPlanStep = AgentPlanStep;","entrypoint":"channel-outbound","exportName":"AgentPlanStep","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} {"closureHash":"1e8bcb2c8d8f5327f5b81b8c217f722f090dccba21ba3943324010f4f80a5a50","declaration":"export type AgentPlanStepStatus = AgentPlanStepStatus;","entrypoint":"channel-outbound","exportName":"AgentPlanStepStatus","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} {"closureHash":"b036fc26e5330dfd7da1af8839bb3c23e85283b9e16e252a659dd4bb0c35cd5e","declaration":"export type ChannelDeliveryStreamingConfig = ChannelDeliveryStreamingConfig;","entrypoint":"channel-outbound","exportName":"ChannelDeliveryStreamingConfig","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} @@ -1276,13 +1276,13 @@ {"closureHash":"424d0b4b21b078d07a49a7bc52c3b63250be032a3e17f47c0cc824178b828ded","declaration":"export type TextChunkMode = TextChunkMode;","entrypoint":"channel-outbound","exportName":"TextChunkMode","importSpecifier":"openclaw/plugin-sdk/channel-outbound","kind":"type","recordType":"export"} {"category":"channel","entrypoint":"channel-pairing","importSpecifier":"openclaw/plugin-sdk/channel-pairing","recordType":"module"} {"closureHash":"3d2325df85dcb397e7df5c9f380c5d6c517976527acbe7d94d59df8777810d1f","declaration":"export function createChannelPairingChallengeIssuer(params: { channel: ChannelId; accountId?: string; upsertPairingRequest: Parameters[0][\"upsertPairingRequest\"]; }): (challenge: Omit[0], \"channel\" | \"accountId\" | \"upsertPairingRequest\">) => Promise<{ created: boolean; code?: string; }>;","entrypoint":"channel-pairing","exportName":"createChannelPairingChallengeIssuer","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} -{"closureHash":"3445b7e876a52e005ac43b3864407134c832f481c7883123f77f06121197a229","declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} +{"closureHash":"f1d737696e5df256426c5de34feda92285556bf334e5a2a391313c4db7c24f2c","declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} {"closureHash":"39648d8f2d5ec14a204569c6266100fef1e455dd53dd6b05ae3034dc98986875","declaration":"export function createLoggedPairingApprovalNotifier(format: string | ((params: PairingNotifyParams) => string), log?: (message: string) => void): NonNullable;","entrypoint":"channel-pairing","exportName":"createLoggedPairingApprovalNotifier","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} {"closureHash":"d5198bb50f3f1c60b384feb93ae07621ceeca6f7d7f7c729ec96dabe984eca10","declaration":"export function createPairingPrefixStripper(prefixRe: RegExp, map?: (entry: string) => string): NonNullable;","entrypoint":"channel-pairing","exportName":"createPairingPrefixStripper","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} {"closureHash":"b914a433d104666e368d9e2c85d328e0015168b8ad3ade34bc993d3cc7141513","declaration":"export function createTextPairingAdapter(params: { idLabel: string; message: string; normalizeAllowEntry?: ChannelPairingAdapter[\"normalizeAllowEntry\"]; notify: (params: PairingNotifyParams & { message: string; }) => Promise | void; }): ChannelPairingAdapter;","entrypoint":"channel-pairing","exportName":"createTextPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} {"closureHash":"ec2b230fc869584bf4114bc30b34546f3e3e9369d7b6f49d9ff3bc8b19dd1989","declaration":"export function readChannelAllowFromStore(channel: PairingChannel, env?: NodeJS.ProcessEnv, accountId?: string): Promise;","entrypoint":"channel-pairing","exportName":"readChannelAllowFromStore","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} {"closureHash":"efe4915252d6eb26af5b1c52dadf22e05b4a13f1668a10cc508c0aa4bae11e39","declaration":"export function readChannelAllowFromStoreSync(channel: PairingChannel, env?: NodeJS.ProcessEnv, accountId?: string): string[];","entrypoint":"channel-pairing","exportName":"readChannelAllowFromStoreSync","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export"} -{"closureHash":"45a75829d749deafc60692dcff0404d0cbc717cecac807b87e607a5dcc8ff611","declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export"} +{"closureHash":"fec0eda83190d6050123f4a2802bca17cc9fa3d0a062fca218e8d1c59d490398","declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-plugin-common","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","recordType":"module"} {"closureHash":"19a3d4c1fdad2b565e7428da26e0dafa76f08498bcf06ac3df098486ff4afc2c","declaration":"export function applyAccountNameToChannelSection(params: { cfg: OpenClawConfig; channelKey: string; accountId: string; name?: string; alwaysUseAccounts?: boolean; }): OpenClawConfig;","entrypoint":"channel-plugin-common","exportName":"applyAccountNameToChannelSection","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"function","recordType":"export"} {"closureHash":"e97ff96104ab3b7f8462f20d39d2596908a59cb03a634c6c2fb0d7ff80e5bb54","declaration":"export function buildChannelConfigSchema(schema: ZodTypeAny, options?: BuildChannelConfigSchemaOptions): ChannelConfigSchema;","entrypoint":"channel-plugin-common","exportName":"buildChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"function","recordType":"export"} @@ -1298,8 +1298,8 @@ {"closureHash":"cd6b0d3f962c8cb40d405e92bb06bb8e9285b386200897f550d21036022262c1","declaration":"export const PAIRING_APPROVED_MESSAGE: \"โœ… OpenClaw access approved. Send a message to start chatting.\";","entrypoint":"channel-plugin-common","exportName":"PAIRING_APPROVED_MESSAGE","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"const","recordType":"export"} {"closureHash":"712435252d2fe5135542ca6b5a4375a6edea24e83829338011dc6ae7e9802fbb","declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-plugin-common","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} {"closureHash":"d02e5c7a995847180696d2a05d8ea092b364ef32b36753e4091fc97ffdaf44ab","declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"channel-plugin-common","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-plugin-common","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-plugin-common","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"channel-plugin-common","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"channel-plugin-common","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common","kind":"type","recordType":"export"} {"category":null,"entrypoint":"channel-policy","importSpecifier":"openclaw/plugin-sdk/channel-policy","recordType":"module"} {"closureHash":"017ab29d16d0f3d02d60f3513e65a373868d26496bc93d020d8fc8c17fd875f4","declaration":"export function buildAccountScopedDmSecurityPolicy(params: { cfg: OpenClawConfig; channelKey: string; accountId?: string | null; fallbackAccountId?: string | null; policy?: string | null; allowFrom?: Array | null; defaultPolicy?: string; allowFromPathSuffix?: string; policyPathSuffix?: string; approveChannelId?: string; approveHint?: string; normalizeEntry?: (raw: string) => string; inheritSharedDefaultsFromDefaultAccount?: boolean; }): ChannelSecurityDmPolicy;","entrypoint":"channel-policy","exportName":"buildAccountScopedDmSecurityPolicy","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} {"closureHash":"628863a501a389d1fee7ab465a4e9da1751189011e9086a54ab22bfc1f970c8a","declaration":"export function buildChannelGroupsScopeTree(cfg: OpenClawConfig, channel: ChannelId, accountId?: string | null): ScopeTree;","entrypoint":"channel-policy","exportName":"buildChannelGroupsScopeTree","importSpecifier":"openclaw/plugin-sdk/channel-policy","kind":"function","recordType":"export"} @@ -1871,7 +1871,7 @@ {"closureHash":"1722c0b0bd09f4a630f5b60e68840478287323ddd401d05fa8d69a9b26d27a74","declaration":"export function resolveThreadBindingThreadName(params: { agentId?: string; label?: string; }): string;","entrypoint":"conversation-runtime","exportName":"resolveThreadBindingThreadName","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"function","recordType":"export"} {"closureHash":"98acce64bde4ebfd62ed516fc45829c52c58630c06db6039e282721215af18e4","declaration":"export function resolveThreadBindingsEnabled(params: { channelEnabledRaw: unknown; sessionEnabledRaw: unknown; }): boolean;","entrypoint":"conversation-runtime","exportName":"resolveThreadBindingsEnabled","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"function","recordType":"export"} {"closureHash":"6f1d515e9f84bd96d6c6dddca3ebdecc3919838ae043f04c3b7fe9dd8def64a6","declaration":"export function unregisterSessionBindingAdapter(params: { channel: string; accountId: string; adapter?: SessionBindingAdapter; }): void;","entrypoint":"conversation-runtime","exportName":"unregisterSessionBindingAdapter","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"function","recordType":"export"} -{"closureHash":"9fa1d7adb6620d769dd78db2b1612cdd262871d0d956b5a2e38a18dae4231f2b","declaration":"export function upsertChannelPairingRequest(params: { channel: PairingChannel; id: string | number; accountId: string; meta?: Record; env?: NodeJS.ProcessEnv; pairingAdapter?: ChannelPairingAdapter; }): Promise<{ code: string; created: boolean; }>;","entrypoint":"conversation-runtime","exportName":"upsertChannelPairingRequest","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"function","recordType":"export"} +{"closureHash":"1a40df66a0a0fa20308f970b74c9df993d312ef3e4d67db751e0ddbde3af3461","declaration":"export function upsertChannelPairingRequest(params: { channel: PairingChannel; id: string | number; accountId: string; meta?: Record; env?: NodeJS.ProcessEnv; pairingAdapter?: ChannelPairingAdapter; memoryIdentityAdmission?: unknown; }): Promise<{ code: string; created: boolean; }>;","entrypoint":"conversation-runtime","exportName":"upsertChannelPairingRequest","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"function","recordType":"export"} {"closureHash":"95a50e38ff0a3b6f23130bce09088e1480cffeef9ac6f4cf447317627f96b58a","declaration":"export const testing: { resetSessionBindingAdaptersForTests(): void; getRegisteredAdapterKeys(): string[];};","entrypoint":"conversation-runtime","exportName":"testing","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"const","recordType":"export"} {"closureHash":"003fe46b2233b284dfa7a8b91ed47770d2841dca6aa8764a45f6417f94f529e7","declaration":"export type BindingTargetKind = BindingTargetKind;","entrypoint":"conversation-runtime","exportName":"BindingTargetKind","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"type","recordType":"export"} {"closureHash":"0c252e3774705f4c7ff23efe753348ccc467f2c6c829fbcb1ba5788bdb84ece5","declaration":"export type ConfiguredBindingRouteResult = ConfiguredBindingRouteResult;","entrypoint":"conversation-runtime","exportName":"ConfiguredBindingRouteResult","importSpecifier":"openclaw/plugin-sdk/conversation-runtime","kind":"type","recordType":"export"} @@ -1886,7 +1886,7 @@ {"closureHash":"d734ae6f08592256df8498061c3417f0914fca32019a24b5dc39edcb5d0c118c","declaration":"export function buildChannelOutboundSessionRoute(params: { cfg: OpenClawConfig; agentId: string; channel: string; accountId?: string | null; recipientSessionExact?: boolean | \"direct-alias\" | \"delivery-identity\"; peer: { kind: \"direct\" | \"group\" | \"channel\"; id: string; }; chatType: \"direct\" | \"group\" | \"channel\"; from: string; to: string; threadId?: string | number; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"90d3722f2e13daa2c010659f41d63c50b35a238eac51b8137b1f7824da23055c","declaration":"export function buildJsonChannelConfigSchema(schema: JsonSchemaObject, options?: BuildJsonChannelConfigSchemaOptions): ChannelConfigSchema;","entrypoint":"core","exportName":"buildJsonChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"3d27406644141af2733cfca6e8c1240fc62327910109f585ce9073cafd7fd89c","declaration":"export function buildJsonPluginConfigSchema(schema: JsonSchemaObject, options?: BuildJsonPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"buildJsonPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"f26e2150ba5824e830978cd15a8d5ed83d5150c44050a5050d6653b773ea4765","declaration":"export function buildMemorySystemPromptAddition(params: MemoryPromptSectionParams): string | undefined;","entrypoint":"core","exportName":"buildMemorySystemPromptAddition","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"f0e859e945b5f950a5ed8ee5070dc19ed16e685400b41dfa35554f26867b83d4","declaration":"export function buildMemorySystemPromptAddition(params: MemoryPromptSectionParams): string | undefined;","entrypoint":"core","exportName":"buildMemorySystemPromptAddition","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"aff66c792d532642afb9c6e5a03c8d220f219250c3a8b49733f32058f22f98ca","declaration":"export function buildPluginConfigSchema(schema: ZodTypeAny, options?: BuildPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"buildPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"3ec2c091f2139a6c20b090ef4aa8a7e052440040bc620ce6cb7b8fd5ced3efa3","declaration":"export function buildThreadAwareOutboundSessionRoute(params: { route: ChannelOutboundSessionRoute; replyToId?: string | number | null; threadId?: string | number | null; currentSessionKey?: string | null; precedence?: readonly ThreadAwareOutboundSessionRouteThreadSource[]; useSuffix?: boolean; parentSessionKey?: string; normalizeThreadId?: (threadId: string) => string; canRecoverCurrentThread?: (context: ThreadAwareOutboundSessionRouteRecoveryContext) => boolean; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildThreadAwareOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"42e686a8f08f2bf03a7b25d14cdcfa089bb6bd8e2654eab8ca9d786df65580d6","declaration":"export function channelTargetSchema(options?: { description?: string; }): Type.TString;","entrypoint":"core","exportName":"channelTargetSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} @@ -1897,8 +1897,8 @@ {"closureHash":"9e93bcdfc6299e65ef2a3d267047a9e8c856f0b2f8e9b79d570fb2a4cd238c74","declaration":"export function createChatChannelPlugin(params: { base: ChatChannelPluginBase; security?: ChannelSecurityAdapter | ChatChannelSecurityOptions; pairing?: ChannelPairingAdapter | ChatChannelPairingOptions; threading?: ChannelThreadingAdapter | ChatChannelThreadingOptions; outbound?: ChannelOutboundAdapter | ChatChannelAttachedOutboundOptions; }): ChannelPlugin;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"785b0f750c5bd20f9f3ca081886a5af79ee0e4d2c38f78f769bf994b234f5076","declaration":"export function createDedupeCache(options: DedupeCacheOptions): DedupeCache;","entrypoint":"core","exportName":"createDedupeCache","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"e2df8d235401aebf58eb71652fbeaedb42ca00aaa5042a76909ff2c48ba6fd54","declaration":"export function createSubsystemLogger(subsystem: string): SubsystemLogger;","entrypoint":"core","exportName":"createSubsystemLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"ad9a5a09235e9a426da9b310cd466830ad103dda2e5ce4891ef4131fdf50deda","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"fd766c74118002291fa28dcd19a9677cdf9f615fe09994862f95b989dd36479a","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"cb5d7b4d9caafb5d1eaa57839fe6cb95e714bac30f9b697c720b32913c22eec5","declaration":"export function defineChannelPluginEntry({ id, name, description, plugin, configSchema, setRuntime, registerCliMetadata, registerFull, registerCapabilities, }: DefineChannelPluginEntryOptions): DefinedChannelPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"bcdcc487ce9eee949611005455c7cb794c78852875f5749d1712e27c02ce4cf8","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"0e0a9f6b22c433bdb1165e7707b1f9a1ddac1a544a8add00b503048cf157921f","declaration":"export function defineSetupPluginEntry(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"3c5ce0c3733cbb038aeb914af1df5d701f362f0521921b8abd0c9214db9cc4b8","declaration":"export function delegateCompactionToRuntime(params: Parameters[0]): Promise;","entrypoint":"core","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"2c282e0e308f9442bca7cdeb8e89a097531b1d54a692c9d86e5f39a8db1c2537","declaration":"export function deleteAccountFromConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; clearBaseFields?: string[]; }): OpenClawConfig;","entrypoint":"core","exportName":"deleteAccountFromConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} @@ -1922,7 +1922,7 @@ {"closureHash":"0a8fd5850a674bce2d579cfe904dee5e0feb1ea240f4efb5d9df3ba99b5e8791","declaration":"export function optionalStringEnum(values: T, options?: StringEnumOptions): Type.TOptional | Type.TEnum>;","entrypoint":"core","exportName":"optionalStringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"8895f7af11b994dcd383ebc45d8cfb3c3b1e6d88a64a001b04f604a83f77e517","declaration":"export function parseOptionalDelimitedEntries(value?: string): string[] | undefined;","entrypoint":"core","exportName":"parseOptionalDelimitedEntries","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"7024da55c2fffd041869aa12cca99a6ebbe4e961ce255e08c83aadc48e3bc574","declaration":"export function parseStrictPositiveInteger(value: unknown): number | undefined;","entrypoint":"core","exportName":"parseStrictPositiveInteger","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} -{"closureHash":"c7378a8a76cf3588080a64f47c77acc7b01c692a0495eff64f25205bca6d5217","declaration":"export function prepareMemorySystemPromptAddition(params: MemoryPromptSectionParams): Promise;","entrypoint":"core","exportName":"prepareMemorySystemPromptAddition","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} +{"closureHash":"ffdcce01aaf21322f1dd5ee373cac4e05fbd0289616724547bf40605fc8917fa","declaration":"export function prepareMemorySystemPromptAddition(params: MemoryPromptSectionParams): Promise;","entrypoint":"core","exportName":"prepareMemorySystemPromptAddition","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"824b72afe6f331a51be4b6fc77fc8ee98570526d2ee63bf0404ed3432c11515c","declaration":"export function readNumberParam(params: Record, key: string, options?: { required?: boolean; label?: string; integer?: boolean; strict?: boolean; positiveInteger?: boolean; nonNegativeInteger?: boolean; }): number | undefined;","entrypoint":"core","exportName":"readNumberParam","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"650210a986670f4fc6928fcb58f076c28653cc5c1a7cd605120c714b589b7b14","declaration":"export function readReactionParams(params: Record, options: { emojiKey?: string; removeKey?: string; removeErrorMessage: string; }): ReactionParams;","entrypoint":"core","exportName":"readReactionParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":null,"declaration":"export function readSecretFileSync(filePath: string, label: string, options?: SecretFileReadOptions): string;","entrypoint":"core","exportName":"readSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} @@ -1945,7 +1945,7 @@ {"closureHash":"2e6ce1f4c1692270a00dc0cf08e2752a26739c3143f8091cb270063c6034605d","declaration":"export function tryReadSecretFileSync(filePath: string | undefined, label: string, options: CredentialFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options?: FsSafeSecretFileReadOptions): string | undefined;\nexport function tryReadSecretFileSync(filePath: string, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): ConfiguredCredentialResult;\nexport function tryReadSecretFileSync(filePath: string | undefined, label: string, options: FsSafeSecretFileReadOptions | undefined, diagnostic: { configPath: string; }): CredentialResult;","entrypoint":"core","exportName":"tryReadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export"} {"closureHash":"b40933a11984425d14a7a479bda0d2cd14cbfa9371164774f39bebbf12861df7","declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"core","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export"} {"closureHash":null,"declaration":"export const DEFAULT_SECRET_FILE_MAX_BYTES: number;","entrypoint":"core","exportName":"DEFAULT_SECRET_FILE_MAX_BYTES","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export"} -{"closureHash":"d759a25775cb15d3f1804e39e98518f83b67b29ba3ab2fd84d4bf16106d9fdb9","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"core","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"cff7e843ff24f7db2fd0f413d247310c86216bd9b51393b64c22f0ef85cda68e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"core","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"d2ff4de9ee3fd111c2cc64a3ee7e557d9f161af1b6b437ee7886bcb16e426317","declaration":"export type AgentPromptGuidance = AgentPromptGuidance;","entrypoint":"core","exportName":"AgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"2841127a90e04467adfea8126cbf03655f44ddb089ad9e0d48833c2beea39cbd","declaration":"export type AgentPromptGuidanceEntry = AgentPromptGuidanceEntry;","entrypoint":"core","exportName":"AgentPromptGuidanceEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"aa0412acefe62caff12e5271ead0545504874e824380dc21cfc0566388a05f33","declaration":"export type AgentPromptSurfaceKind = \"openclaw_main\" | \"pi_main\" | \"codex_app_server\" | \"cli_backend\" | \"acp_backend\" | \"subagent\";","entrypoint":"core","exportName":"AgentPromptSurfaceKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -1971,23 +1971,23 @@ {"closureHash":"78083326f70178db2368226b2fe443362e976e63949ab31ebe46dbc4c8efc7f0","declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"db78504773a1bbfa02018d7352dadbbdae4fcaded93f514c97ba126cbc849f3b","declaration":"export type HistoryEntry = HistoryEntry;","entrypoint":"core","exportName":"HistoryEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"c241077e3f27058240f750d07561778eccb3e7a2dc99be94023eac84cbab7c73","declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"0b824778ee420a4a199233d8fe4635960ed53a0c96964a9e90e8e9e31c9ffe4b","declaration":"export type MemoryPluginCapability = MemoryPluginCapability;","entrypoint":"core","exportName":"MemoryPluginCapability","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"786e9bcb90b7e3c4a6bda0a54b84bfad4a6d968a0bb05b2a6649e0107cce0f8d","declaration":"export type MemoryPluginCapability = MemoryPluginCapability;","entrypoint":"core","exportName":"MemoryPluginCapability","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"77d2bdba5dec3f7c4ce6b6f5d9607f693dd84be375c74387eec5dcc04c0ce2aa","declaration":"export type MemoryPluginPublicArtifact = MemoryPluginPublicArtifact;","entrypoint":"core","exportName":"MemoryPluginPublicArtifact","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"975832a2ade859a8066356ef270fdd8edbc8d5f764a3c4dbbbeef52c001d950c","declaration":"export type MemoryPluginPublicArtifactsProvider = MemoryPluginPublicArtifactsProvider;","entrypoint":"core","exportName":"MemoryPluginPublicArtifactsProvider","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"54ea426dde51859b572b4c1079d2b70b412096f73da2b8c265f2749d9f01cbb5","declaration":"export type NormalizedLocation = NormalizedLocation;","entrypoint":"core","exportName":"NormalizedLocation","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"5189698d102b8b064eefe1442b008312973c3994fd6b203d2205725d7ee9d118","declaration":"export type OpenClawPluginActiveModelContext = OpenClawPluginActiveModelContext;","entrypoint":"core","exportName":"OpenClawPluginActiveModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"647007b989ba3d08c520ec68873f65f22f231b0274daf10f5d219074fd2fcba6","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"1b85aede0a5709f8de9905bcedb2b1acbbdb6db5fdcdd7321e2294c2f8866424","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"ccae64ce42b52f34fc0f2adffe6202985c2c8464e3e2df19f43ae1eb0005e808","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"87cbaf84f362b665d7e0a8c8d62835b297f00629a3d4200d6d07f3938b439f9c","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"a7ed83f0924f818b23cecb5a1f3591ff28b9499ccac9667a2b8505c2bc608ea9","declaration":"export type OpenClawPluginGatewayEventScope = OpenClawPluginGatewayEventScope;","entrypoint":"core","exportName":"OpenClawPluginGatewayEventScope","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"f81f224d9b837e6353b7a546c5a76b124bcf568fd1f1fd0c6881fda30c53120a","declaration":"export type OpenClawPluginGatewayEvents = OpenClawPluginGatewayEvents;","entrypoint":"core","exportName":"OpenClawPluginGatewayEvents","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"ddc2738dd0ece94ddde9a7c655f92c15ec6416645ecf932d4aa404c7b7761159","declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"26dd6974af3127ca18835b3f7294f2dae0f7fab63c6d326e999e90366999dc6e","declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"3bb6d68fc7970af9b14ace77e71698b7dbc45c447102a74505e872b692753f07","declaration":"export type OpenClawPluginSessionsChangedEvent = OpenClawPluginSessionsChangedEvent;","entrypoint":"core","exportName":"OpenClawPluginSessionsChangedEvent","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"4b4e5425c1e19a0d00f99e3b1f078f101a87a38dbf3cb81e124665ac11bb68d9","declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"cf4bb672a5d6622273e847afbab9b823e0fdb7bbecd43eebb2620c7711924273","declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"d0230fba39834d6c8e620d19799a0006eeea6a7a75a954930cb10acc0138b09f","declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"709aac28446af536b23ee9673d2e3ed3ca733faab5c47be6ccbf14b424f48798","declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"747b0a0e9cf9bca79463e90a0850940820d68a35dd4facde3776428d4a18e8e4","declaration":"export type OutboundIdentity = OutboundIdentity;","entrypoint":"core","exportName":"OutboundIdentity","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"e906dde715d40209703e3ddff8afa7f7288c7ed1870416773794b3817b5e1e80","declaration":"export type OutboundLocation = OutboundLocation;","entrypoint":"core","exportName":"OutboundLocation","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"b749d0cceb7b02f8e2e810c9a1f4fea64effc4a2ddb0da972d873781d2a70471","declaration":"export type PluginAgentEventEmitParams = PluginAgentEventEmitParams;","entrypoint":"core","exportName":"PluginAgentEventEmitParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -1995,7 +1995,7 @@ {"closureHash":"028cd39dd470117f37aff9d199e99c7eadaa99a2af56810c3033e488587e56e2","declaration":"export type PluginAgentEventSubscriptionRegistration = PluginAgentEventSubscriptionRegistration;","entrypoint":"core","exportName":"PluginAgentEventSubscriptionRegistration","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"3d9f3c666f1a8f37cd4fd2bf621d793b6626ce36edc96bd3922498a8f4ebfc19","declaration":"export type PluginAgentTurnPrepareEvent = PluginAgentTurnPrepareEvent;","entrypoint":"core","exportName":"PluginAgentTurnPrepareEvent","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"dd9b818f8b19ced207493eea1b75da8a38b24a5dc4c9ac46288f9329ba06f0f3","declaration":"export type PluginAgentTurnPrepareResult = PluginAgentTurnPrepareResult;","entrypoint":"core","exportName":"PluginAgentTurnPrepareResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"d9d24565b06f891a687f49672129beac9d38ccb817526ed1a6579efcb5825eb0","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"5c7a4e89ddfb6bed00f2ca8e67e43f150fedb3182275a525411365855d581c22","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"a50f802cdb46fb073ccba3d7b5c2a3c66c2b5aeccca3368222f9a520e66055ca","declaration":"export type PluginCommandResult = PluginCommandResult;","entrypoint":"core","exportName":"PluginCommandResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"b9a7fd2bdde1d99b58227e6ff01853420fee36357c2fa5e2d9ef5fbcef11ac65","declaration":"export type PluginControlUiDescriptor = PluginControlUiDescriptor;","entrypoint":"core","exportName":"PluginControlUiDescriptor","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"83237187559904a1350b07bfcaa20eb473e397884361e9543ccdaeddd6c2c12e","declaration":"export type PluginHeartbeatPromptContributionEvent = PluginHeartbeatPromptContributionEvent;","entrypoint":"core","exportName":"PluginHeartbeatPromptContributionEvent","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -2014,7 +2014,7 @@ {"closureHash":"f361587d79916f3d1cb73b4d296e1f37f86d799a641ce4a590ee784413d0b7ef","declaration":"export type PluginNextTurnInjectionRecord = PluginNextTurnInjectionRecord;","entrypoint":"core","exportName":"PluginNextTurnInjectionRecord","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"e4f6093e70826c8c7c02433082b9ac1b91755640096339111331fc45a494ca88","declaration":"export type PluginRunContextGetParams = PluginRunContextGetParams;","entrypoint":"core","exportName":"PluginRunContextGetParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"f9d14d70abca2a8771c0763736871361e4c223a8e4cbe3ae5c7a17751630b68e","declaration":"export type PluginRunContextPatch = PluginRunContextPatch;","entrypoint":"core","exportName":"PluginRunContextPatch","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"4a005fd56ceaa1de7ff2c6b45f08a48f48d7ff30e21d0e88d783d86a49e274f4","declaration":"export type PluginRuntimeLifecycleRegistration = PluginRuntimeLifecycleRegistration;","entrypoint":"core","exportName":"PluginRuntimeLifecycleRegistration","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"c599fdbfd9439bdcbbbf621dca995d2d6f87c7aba9606dc1970e1205dfea6357","declaration":"export type PluginSessionActionContext = PluginSessionActionContext;","entrypoint":"core","exportName":"PluginSessionActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} {"closureHash":"85a706fb9b56d5c5f41756729736cd4581b98d5cb0ab9a693b8261e4d936e499","declaration":"export type PluginSessionActionRegistration = PluginSessionActionRegistration;","entrypoint":"core","exportName":"PluginSessionActionRegistration","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export"} @@ -2215,8 +2215,8 @@ {"closureHash":"0db968dad99d84ecef5202167daadd092e3b4f456270283d3fd61585ac2bbd5a","declaration":"export type DiscordComponentSendResult = DiscordComponentSendResult;","entrypoint":"discord","exportName":"DiscordComponentSendResult","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"084b46d7dd510eb182a4705559251e824220b57dbfa6dc54392507b72ba1815e","declaration":"export type DiscordOutboundTargetResolution = DiscordOutboundTargetResolution;","entrypoint":"discord","exportName":"DiscordOutboundTargetResolution","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"discord","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"discord","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"discord","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"discord","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"discord","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"6b9967e919c1cd420c8356b4f9d40dbc81932b4b15a733eecdcfb2ad84f8e5d8","declaration":"export type ResolvedDiscordAccount = ResolvedDiscordAccount;","entrypoint":"discord","exportName":"ResolvedDiscordAccount","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"6bed5ca896b7034117e4757e2c6b4111dd5293dbad9416e3828dd6afa4e858ce","declaration":"export type ThreadBindingRecord = ThreadBindingRecord;","entrypoint":"discord","exportName":"ThreadBindingRecord","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} {"closureHash":"eaabd6155d6f25cbba09ef3c8f2b306f2202affdca4b47e5d67311ff4073fb0d","declaration":"export type ThreadBindingTargetKind = ThreadBindingTargetKind;","entrypoint":"discord","exportName":"ThreadBindingTargetKind","importSpecifier":"openclaw/plugin-sdk/discord","kind":"type","recordType":"export"} @@ -2289,7 +2289,7 @@ {"closureHash":"a8874cc3b2cb522f6ca38ba5e353ec290aad0495c56087396ecaeb1cee9981b6","declaration":"export type NodeMatchCandidate = NodeMatchCandidate;","entrypoint":"gateway-runtime","exportName":"NodeMatchCandidate","importSpecifier":"openclaw/plugin-sdk/gateway-runtime","kind":"type","recordType":"export"} {"closureHash":"909e9434e956f1dfde4cc24f68879e7c3a1aac8aea4ff2d887b37824fdef1994","declaration":"export type NodeSession = NodeSession;","entrypoint":"gateway-runtime","exportName":"NodeSession","importSpecifier":"openclaw/plugin-sdk/gateway-runtime","kind":"type","recordType":"export"} {"closureHash":"6cfef265e2aebd53c1e7ce29cb204228ac175b07f9d2f22b861e98cac0eaee4a","declaration":"export type NormalizedPluginNodeCapabilityUrl = NormalizedPluginNodeCapabilityUrl;","entrypoint":"gateway-runtime","exportName":"NormalizedPluginNodeCapabilityUrl","importSpecifier":"openclaw/plugin-sdk/gateway-runtime","kind":"type","recordType":"export"} -{"closureHash":"a8ddb69632bf607e66ad3c640b2e676060c1dd1f6be25a70acd31b8a4b1e9fff","declaration":"export class GatewayClient {\n #client: BaseGatewayClient;\n constructor(opts: GatewayClientOptions);\n start(): void;\n stop(): void;\n stopAndWait(opts?: {\n timeoutMs?: number;\n }): Promise;\n request>(method: string, params?: unknown, opts?: GatewayClientRequestOptions): Promise;\n getConnectionMetadata(): GatewayClientConnectionMetadata;\n updateNodeManifest(manifest: {\n caps: string[];\n commands: string[];\n }): void;\n}","entrypoint":"gateway-runtime","exportName":"GatewayClient","importSpecifier":"openclaw/plugin-sdk/gateway-runtime","kind":"class","recordType":"export"} +{"closureHash":"50249daea218a2c3a9219bd6e4b946b38995a089d412b543619bfba3eb7fb39d","declaration":"export class GatewayClient {\n #client: BaseGatewayClient;\n constructor(opts: GatewayClientOptions);\n start(): void;\n stop(): void;\n stopAndWait(opts?: {\n timeoutMs?: number;\n }): Promise;\n request>(method: string, params?: unknown, opts?: GatewayClientRequestOptions): Promise;\n getConnectionMetadata(): GatewayClientConnectionMetadata;\n updateNodeManifest(manifest: {\n caps: string[];\n commands: string[];\n }): void;\n}","entrypoint":"gateway-runtime","exportName":"GatewayClient","importSpecifier":"openclaw/plugin-sdk/gateway-runtime","kind":"class","recordType":"export"} {"category":null,"entrypoint":"group-access","importSpecifier":"openclaw/plugin-sdk/group-access","recordType":"module"} {"closureHash":"b6b34cd3844debbe7cda17ad7703e4fcffe4489789ae1763df8f8ab027150203","declaration":"export function evaluateGroupRouteAccessForPolicy(params: { groupPolicy: GroupPolicy; routeAllowlistConfigured: boolean; routeMatched: boolean; routeEnabled?: boolean; }): GroupRouteAccessDecision;","entrypoint":"group-access","exportName":"evaluateGroupRouteAccessForPolicy","importSpecifier":"openclaw/plugin-sdk/group-access","kind":"function","recordType":"export"} {"closureHash":"bf1a463ce98bf23d639d6e80112ffca836df6d63049bae6fef2a11a2ef1bb74c","declaration":"export function evaluateMatchedGroupAccessForPolicy(params: { groupPolicy: GroupPolicy; allowlistConfigured: boolean; allowlistMatched: boolean; requireMatchInput?: boolean; hasMatchInput?: boolean; }): MatchedGroupAccessDecision;","entrypoint":"group-access","exportName":"evaluateMatchedGroupAccessForPolicy","importSpecifier":"openclaw/plugin-sdk/group-access","kind":"function","recordType":"export"} @@ -2334,7 +2334,7 @@ {"closureHash":"4e9774b442212bd9346cf95095a42ece3c0e1df29f25e1a81e857981503b4a82","declaration":"export function deriveInboundMessageHookContext(ctx: FinalizedMsgContext, overrides?: { content?: string; messageId?: string; }): CanonicalInboundMessageHookContext;","entrypoint":"hook-runtime","exportName":"deriveInboundMessageHookContext","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} {"closureHash":"9bb995aaaf485864e8c02dc5cc71fe5bff42e4d202c20554efc2f3d2d5c2576d","declaration":"export function fireAndForgetBoundedHook(task: () => Promise, label: string, logger?: (message: string) => void, options?: FireAndForgetBoundedHookOptions): void;","entrypoint":"hook-runtime","exportName":"fireAndForgetBoundedHook","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} {"closureHash":"46f0ed9dbb3fb5cd6d3898f8dd762508eb93dac3255841d96ae9b25d2ed84c96","declaration":"export function fireAndForgetHook(task: Promise, label: string, logger?: (message: string) => void): void;","entrypoint":"hook-runtime","exportName":"fireAndForgetHook","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} -{"closureHash":"819ef2075c836ea71b03cb8cf6247c4d3064e208f9086d0a9d7ed612f4a6844c","declaration":"export function initializeGlobalHookRunner(registry: GlobalHookRunnerRegistry): void;","entrypoint":"hook-runtime","exportName":"initializeGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} +{"closureHash":"fedfb0278bb4e6fe5606d3abb29eee611787747b1a14d3e7f7c70b5a08df2abe","declaration":"export function initializeGlobalHookRunner(registry: GlobalHookRunnerRegistry): void;","entrypoint":"hook-runtime","exportName":"initializeGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} {"closureHash":"05bb072b6ae34d0271798d98d9083ec8290d4123c349862722097a7e87866d07","declaration":"export function registerInternalHook(eventKey: string, handler: InternalHookHandler): void;","entrypoint":"hook-runtime","exportName":"registerInternalHook","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} {"closureHash":"f573a2f2542169912da9757a6aac432d067434e759cf40035079ea1d107b7e38","declaration":"export function resetGlobalHookRunner(): void;","entrypoint":"hook-runtime","exportName":"resetGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} {"closureHash":"e26c70aedd4d93db7a26367de5a935f8335b657b6333f34797a5349f04589b20","declaration":"export function toInternalMessageReceivedContext(canonical: CanonicalInboundMessageHookContext): MessageReceivedHookContext;","entrypoint":"hook-runtime","exportName":"toInternalMessageReceivedContext","importSpecifier":"openclaw/plugin-sdk/hook-runtime","kind":"function","recordType":"export"} @@ -2360,7 +2360,7 @@ {"closureHash":"98e0cc16352b7dfcceb4957f8cd2acfe3c2b3acb223c42a5cfb885e088fcb04c","declaration":"export function resolveInboundReplyDispatchCounts(result: ChannelTurnDispatchResultLike): Record;","entrypoint":"inbound-reply-dispatch","exportName":"resolveInboundReplyDispatchCounts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"871d3ff30c14af1a605fdb47c50923a910a7886f7cc886ba1cd9c2eff1ea8334","declaration":"export function runChannelInboundEvent(params: RunChannelTurnParams): Promise>;\nexport function runChannelInboundEvent(params: ChannelInboundEventRunnerParams): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runChannelInboundEvent","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} {"closureHash":"2c68496a174872b31aaf1ac8fad2789deb79d490c5ffbcb157325f1c95d1b51f","declaration":"export function runPreparedInboundReply(params: PreparedChannelTurn): Promise>;","entrypoint":"inbound-reply-dispatch","exportName":"runPreparedInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"function","recordType":"export"} -{"closureHash":"64792a0c33912731a154f8e8e1b3f598b3396d2e0b93ed35fb4cc67a150bf9e2","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"} +{"closureHash":"8b9f39e06d068cd2497a07a2f0ee78c2e5497a58eca6e7e6c2da2ba93535f23c","declaration":"export const deliverInboundReplyWithMessageSendContext: (params: DurableInboundReplyDeliveryParams) => Promise<{ status: \"not_applicable\"; reason: \"non_final\";} | { status: \"unsupported\"; reason: \"missing_channel\" | \"missing_target\" | \"missing_outbound_handler\" | \"capability_mismatch\"; capability?: DurableFinalDeliveryRequirement;} | { status: \"handled_visible\"; delivery: ChannelDeliveryResult;} | { status: \"handled_no_send\"; reason: \"no_visible_result\"; delivery: ChannelDeliveryResult;} | { status: \"failed\"; error: unknown; sentBeforeError?: true;}>;","entrypoint":"inbound-reply-dispatch","exportName":"deliverInboundReplyWithMessageSendContext","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"const","recordType":"export"} {"closureHash":"10d47ee68a65fa2df62012bf98988026560dd0bc30d2be56783ed4132864a149","declaration":"export type AssembledInboundReply = AssembledChannelTurn;","entrypoint":"inbound-reply-dispatch","exportName":"AssembledInboundReply","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} {"closureHash":"3de0d6d1bb8f9a83bd1c6e57aa8618e3fea71054236cd530c555e348bd0b7702","declaration":"export type ChannelBotLoopProtectionFacts = ChannelBotLoopProtectionFacts;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelBotLoopProtectionFacts","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} {"closureHash":"f0da845bbdf49b30f6718a4b7ff012a0536deb98f65418583555dc90825797ca","declaration":"export type ChannelInboundDroppedHistoryOptions = ChannelTurnDroppedHistoryOptions;","entrypoint":"inbound-reply-dispatch","exportName":"ChannelInboundDroppedHistoryOptions","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch","kind":"type","recordType":"export"} @@ -3192,34 +3192,34 @@ {"closureHash":"0a8eee30ac3d7beb17a67ed364602e375580d8fe64711e4a88bb77eabb1354f0","declaration":"export function addMeetingSetupCheck(status: MeetingSetupStatus, check: MeetingSetupCheck): MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"addMeetingSetupCheck","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"a4294716c3bb64b8732f33b331506a14e4f2fba59f382699961c9db8677e6774","declaration":"export function asMeetingBrowserTabs(result: unknown): MeetingBrowserCandidateTab[];","entrypoint":"meeting-runtime","exportName":"asMeetingBrowserTabs","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"b39bf4bdb91f0aeabac8cbd0ee8dc21afceae20faf463c6a2657258f2aa07976","declaration":"export function buildMeetingSoxAudioCommands(params: MeetingSoxAudioCommandParams): { inputCommand: string[]; outputCommand: string[]; };","entrypoint":"meeting-runtime","exportName":"buildMeetingSoxAudioCommands","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"66f0964725c2b9640e8ab8cfb803a421a9e58a2238ea4fbf7ffa97d0c4d33df0","declaration":"export function callMeetingBrowserProxyOnNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; } & MeetingBrowserRequestParams): Promise;","entrypoint":"meeting-runtime","exportName":"callMeetingBrowserProxyOnNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"68da4dfc0e0c799f6810dc070c63a429798a1e1e858e5225426f0b21c424caf4","declaration":"export function callMeetingBrowserProxyOnNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; } & MeetingBrowserRequestParams): Promise;","entrypoint":"meeting-runtime","exportName":"callMeetingBrowserProxyOnNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c5fcd1d157edcb4773235adfaf8051e3ec7ca428cb7916b6d55f2511affab56c","declaration":"export function convertMeetingBridgeAudioForStt(audio: Buffer, audioFormat: MeetingRealtimeAudioFormat): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingBridgeAudioForStt","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"aa9063c27c5ff714d3653571c4a2a71e9d2eea5609b161f03e4738e15411358b","declaration":"export function convertMeetingTtsAudioForBridge(audio: Buffer, sampleRate: number, audioFormat: MeetingRealtimeAudioFormat, outputFormat?: string, platformName?: string): Buffer;","entrypoint":"meeting-runtime","exportName":"convertMeetingTtsAudioForBridge","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"c7e8cad42fa48c1be4ae1b1f7f87339c849cacf81a53ad53df76e188f4dd4629","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"eaf5cff3027412d66a1e6488a71c1fb21ae1efb16d5c7415afed7370a1641dbf","declaration":"export function createMeetingBrowserNodeCaller(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; }): MeetingBrowserRequestCaller;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeCaller","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"992b3300a22ff822840971e86089e57352000b2402625860ef32230d0b48362c","declaration":"export function createLocalMeetingRealtimeAudioTransport(params: { inputCommand: string[]; outputCommand: string[]; bargeInInputCommand?: string[]; bargeInRmsThreshold: number; bargeInPeakThreshold: number; bargeInCooldownMs: number; logger: RuntimeLogger; logScope: string; audioFormat?: MeetingRealtimeAudioFormat; spawn?: MeetingRealtimeAudioSpawn; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createLocalMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"c24206770d1401a9b9e1f698345b6df96665676348368e2051844bc6477ff92c","declaration":"export function createMeetingBrowserNodeCaller(params: { runtime: PluginRuntime; adapter: NodeAdapter; nodeId: string; }): MeetingBrowserRequestCaller;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeCaller","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"f244ca8c47f556c9f388953cf9a7581c7d4d413af93e0dfa1462779e6a687a7c","declaration":"export function createMeetingBrowserNodeInvokePolicy(options: MeetingBrowserNodePolicyOptions): OpenClawPluginNodeInvokePolicy;","entrypoint":"meeting-runtime","exportName":"createMeetingBrowserNodeInvokePolicy","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"1aa4e3ff39a2cbe162421c62b1fa4a362973381d4d9ff15c671249b1ebd566bc","declaration":"export function createMeetingNodeHost(options: MeetingNodeHostOptions): { handleCommand(paramsJSON?: string | null): Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingNodeHost","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"2ce663d0c867849f055335c2e964429a31516c653e0628173149d4f991067808","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"d2d5079b8025340a7d77b1342f53aed7b012d14399b3ec3c60805d16ffbac40c","declaration":"export function createMeetingRealtimeEngineBindings(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { agentId?: string; toolPolicy: RealtimeVoiceAgentConsultToolPolicy; }; }; fullConfig: OpenClawConfig; runtime: PluginRuntime; logger: RuntimeLogger; }): { platform: MeetingRuntimePlatform; consultAgent: (consult: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (call: MeetingRealtimeToolCallParams) => Promise; };","entrypoint":"meeting-runtime","exportName":"createMeetingRealtimeEngineBindings","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"9124db05923060c467edb149bd8abdc8be1d00d00f867cf84600972923a58489","declaration":"export function createMeetingSession(params: { platform: MeetingPlatformRuntimeMetadata; config: { realtime: { provider?: string; voiceProvider?: string; transcriptionProvider?: string; model?: string; toolPolicy: TToolPolicy; }; }; resolved: MeetingResolvedJoin; createdAt: string; }): MeetingSessionRecord;","entrypoint":"meeting-runtime","exportName":"createMeetingSession","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"fb276e07e395ab19177b3d7967fd0a8fcda79130883f15092a4a306b826481b9","declaration":"export function createMeetingSetupStatus(checks: MeetingSetupCheck[]): MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"createMeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"abfbbc6b5eca3947bed22ea782cf5ad582b6a364f554d8851c92c2d3cbc3c6f7","declaration":"export function createMeetingVoiceCallGateway(params: { config: MeetingVoiceCallConfig; runtime: PluginRuntime; surface: MeetingVoiceCallSurface; connectClient: (params: { config: MeetingVoiceCallConfig; surface: MeetingVoiceCallSurface; }) => Promise; }): MeetingVoiceCallGateway;","entrypoint":"meeting-runtime","exportName":"createMeetingVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"364dbe49fce073de6aff2b666e2e80b9d188f04458f179f0569506702b2e5075","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"877c0cd3bcc04f1ffe33a7c54d6e87034066d27a50fa0c069338cc64815ac2ab","declaration":"export function createMeetingVoiceCallGateway(params: { config: MeetingVoiceCallConfig; runtime: PluginRuntime; surface: MeetingVoiceCallSurface; connectClient: (params: { config: MeetingVoiceCallConfig; surface: MeetingVoiceCallSurface; }) => Promise; }): MeetingVoiceCallGateway;","entrypoint":"meeting-runtime","exportName":"createMeetingVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"2327df59b7e4bd680d52b939e9b6709ed6a075eb5538dbc8576ce451168d4fe8","declaration":"export function createNodeMeetingRealtimeAudioTransport(params: { runtime: PluginRuntime; nodeId: string; bridgeId: string; logger: RuntimeLogger; commandName: string; logScope: string; logPrefix: string; audioFormat?: MeetingRealtimeAudioFormat; }): MeetingRealtimeAudioTransport;","entrypoint":"meeting-runtime","exportName":"createNodeMeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c0987b15a391a92d53d3e4e12b61eb122f9547fcf4f45478cdd3c5a8973a3e52","declaration":"export function endMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"endMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"b3ebc10fe7ab372e1317eaa8f78621cf277bba1e33fda57acf2254f6759d1e9d","declaration":"export function getMeetingVoiceCallGatewayCall(params: { gateway: MeetingVoiceCallGateway; callId: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"getMeetingVoiceCallGatewayCall","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"aac088df8e80d9ce89c45feccdb04ace3ae4417b3fcdd0f058410ddf25c96b46","declaration":"export function isMeetingVoiceCallMissingError(error: unknown): boolean;","entrypoint":"meeting-runtime","exportName":"isMeetingVoiceCallMissingError","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"c571be67deff656fc2e53aecb61d02bd58b468d4b548860b37b61eafa18f8d6b","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"892e54d8bf726606994141005217facb41eef3c0d21c06e186f90c82c7a10127","declaration":"export function joinMeetingViaVoiceCallGateway(params: { config: MeetingVoiceCallConfig; gateway: MeetingVoiceCallGateway; surface: MeetingVoiceCallSurface; dialInNumber: string; dtmfSequence?: string; logger?: RuntimeLogger; message?: string; requesterSessionKey?: string; agentId?: string; sessionKey?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"joinMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"bac9621cd025754fbcd4c21409b06eb0503405db81f35cac993aaf0b881ab3e1","declaration":"export function leaveMeetingWithBrowser(params: { adapter: BrowserAdapter; callBrowser: MeetingBrowserRequestCaller; launch: boolean; meetingSessionId?: string; meetingUrl: string; tab: MeetingBrowserTab; timeoutMs: number; }): Promise<{ left: boolean; note: string; }>;","entrypoint":"meeting-runtime","exportName":"leaveMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"c7b1aeac134b2070d053adf33026d876998b852ccd65cd2c9667119b1a1abee2","declaration":"export function openMeetingWithBrowser, Mode extends string, Health extends MeetingBrowserHealth & { browserTitle?: string; browserUrl?: string; notes?: string[]; }, Transcript extends MeetingTranscriptSnapshot>(params: { adapter: BrowserAdapter; callBrowser: MeetingBrowserRequestCaller; config: MeetingBrowserControllerConfig; session: Session; }): Promise<{ launched: boolean; browser?: Health; tab?: MeetingBrowserTab; }>;","entrypoint":"meeting-runtime","exportName":"openMeetingWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"34858979bd248799c2215d9c7bdd5d4a6b27660c9173bfca2e50dd4373ac27db","declaration":"export function readMeetingBrowserTab(result: unknown): MeetingBrowserCandidateTab | undefined;","entrypoint":"meeting-runtime","exportName":"readMeetingBrowserTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"566d131fb9ec888fb5441ac6e7ae1623e8f5d12a2870d3fc94db607d57f70205","declaration":"export function readMeetingTranscriptWithBrowser(params: { adapter: BrowserAdapter; callBrowser: MeetingBrowserRequestCaller; finalize: boolean; meetingUrl: string; meetingSessionId: string; tab: MeetingBrowserTab; timeoutMs: number; }): Promise;","entrypoint":"meeting-runtime","exportName":"readMeetingTranscriptWithBrowser","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"0b42493cc0197096c4847c2d6e149c5581580abdda448d07eb1c6d77a775bc4a","declaration":"export function recoverMeetingBrowserTab(params: { adapter: BrowserAdapter; allowSessionAdoption?: boolean; autoJoin?: boolean; callBrowser: MeetingBrowserRequestCaller; captureCaptions?: boolean; config: MeetingBrowserControllerConfig; locationLabel: string; meetingSessionId?: string; mode: Mode; requestedMeetingUrl: string | undefined; readOnly?: boolean; timeoutMs?: number; trackedMeetingUrl: string | undefined; trackedTargetId: string | undefined; }): Promise<{ found: boolean; targetId?: string; tab?: MeetingBrowserCandidateTab; browser?: Health; message: string; }>;","entrypoint":"meeting-runtime","exportName":"recoverMeetingBrowserTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"dd5fb0b5816311a03a3ae754c03331e11afae96acc63338bbde9111a919d2060","declaration":"export function resolveLocalMeetingBrowserRequest(runtime: PluginRuntime): Promise;","entrypoint":"meeting-runtime","exportName":"resolveLocalMeetingBrowserRequest","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"019720abfc1f5af9638270dbeb6d42b6e2c089b6250fff6a936c2a1758acf1a5","declaration":"export function resolveMeetingBrowserNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"120055d3915ab89e6960d454ba75088f5d000e2abe1715901b791f86ab0f2ba5","declaration":"export function resolveMeetingBrowserNodeInfo(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNodeInfo","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"9a4c04e7a643c00f4b5fc18eb605a04e1fadf6be2bd9ffc7df7f72804ee2af49","declaration":"export function resolveLocalMeetingBrowserRequest(runtime: PluginRuntime): Promise;","entrypoint":"meeting-runtime","exportName":"resolveLocalMeetingBrowserRequest","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"0c3b2b99e995c6d0ec4549e09ef96007bf2eaafc565eea1161d0b1184dc32b1a","declaration":"export function resolveMeetingBrowserNode(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNode","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"4e175840f739613f81bc3eda9b7e19726a23dee0dde0f6421e400eb5563a97dd","declaration":"export function resolveMeetingBrowserNodeInfo(params: { runtime: PluginRuntime; adapter: NodeAdapter; requestedNode?: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"resolveMeetingBrowserNodeInfo","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"f21196c9ea8ab90248ffdcdef3e942f1247ee2b9064ddb9757fffe352362c779","declaration":"export function resolveMeetingRealtimeAudioFormat(audioFormat: MeetingRealtimeAudioFormat): RealtimeVoiceAudioFormat;","entrypoint":"meeting-runtime","exportName":"resolveMeetingRealtimeAudioFormat","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"521dc5c262524a709cdd27cdc88e95004073da8223537bcbc73d5d423172dc2b","declaration":"export function speakMeetingViaVoiceCallGateway(params: { gateway: MeetingVoiceCallGateway; callId: string; message: string; }): Promise;","entrypoint":"meeting-runtime","exportName":"speakMeetingViaVoiceCallGateway","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"c64d9bc7f2e478a5affc01a910f49882aef707b077d8ebc0da889985cfaf9595","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} -{"closureHash":"20dff0ae02d5d945273bedcb54a853efed1f43cf1f03754a52e0eb3e584c7b88","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"3a54658889eb2e0a998f08ae0d0b1d7e7f16a428e40083462bdc9e2c9be1ce6e","declaration":"export function startMeetingAgentRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeTranscriptionProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingAgentRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} +{"closureHash":"896073bc541994b82669b2d3971ac486a05e3be2eb7e551020041d368830cb14","declaration":"export function startMeetingRealtimeEngine(params: { config: MeetingRealtimeEngineConfig; fullConfig: OpenClawConfig; runtime: PluginRuntime; platform: MeetingRuntimePlatform; meetingSessionId: string; requesterSessionKey?: string; logPrefix?: \"node\"; talkSessionId?: string; talkContext?: { nodeId: string; bridgeId: string; }; transport: MeetingRealtimeAudioTransport; logger: RuntimeLogger; providers?: RealtimeVoiceProviderPlugin[]; consultAgent: (params: MeetingAgentConsultParams) => Promise<{ text: string; }>; tools: RealtimeVoiceTool[]; handleToolCall: (params: MeetingRealtimeToolCallParams) => Promise; }): Promise;","entrypoint":"meeting-runtime","exportName":"startMeetingRealtimeEngine","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"function","recordType":"export"} {"closureHash":"663b9c77231b21af697efd5042e22d1c33e9ee972adeb312ad86d81a2b2e36f7","declaration":"export type MeetingAgentConsultParams = MeetingAgentConsultParams;","entrypoint":"meeting-runtime","exportName":"MeetingAgentConsultParams","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"adf0745c611bf737fc28978d766fc2a25b7104e71b6b2fed4e9b95e519c7b115","declaration":"export type MeetingBrowserCandidateTab = MeetingBrowserCandidateTab;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserCandidateTab","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"59b1526172b7491b85f14f13c1ee26d8d6726f33093770748580c767b1689a17","declaration":"export type MeetingBrowserControllerConfig = MeetingBrowserControllerConfig;","entrypoint":"meeting-runtime","exportName":"MeetingBrowserControllerConfig","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} @@ -3251,7 +3251,7 @@ {"closureHash":"8244b408803f57cf2004157e96f2ce11bb036cdf864123b15ba2fac7f03b5d43","declaration":"export type MeetingSessionRuntimeHandles = MeetingSessionRuntimeHandles;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeHandles","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"aa8054fc2c442891197e89bdad61e79999ea15d813c4b127fb6150607b9e67e7","declaration":"export type MeetingSessionRuntimeJoinContext, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab> = MeetingSessionRuntimeJoinContext;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeJoinContext","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"325241724edd38da439c5df03d225e2a7cb8e56d817e98ed7c37850656d3744b","declaration":"export type MeetingSessionRuntimeMessages = MeetingSessionRuntimeMessages;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeMessages","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} -{"closureHash":"8d3f6abdbf39603c6f28a69b9bb8f0b214d978dc10dd83ca3f6a692f565a7cb0","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} +{"closureHash":"f9bbaf0fd4cc34d647d2721a373df74f61814f497be0af92b548a0ba4461d08f","declaration":"export type MeetingSessionRuntimeOptions, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> = MeetingSessionRuntimeOptions;","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntimeOptions","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"d3c730cba02d30512c4cdae6e2367c662982e2c25671833ecd8701283924c642","declaration":"export type MeetingSessionState = MeetingSessionState;","entrypoint":"meeting-runtime","exportName":"MeetingSessionState","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"2496931157bf64fdb16013172ab9c023e60c5f85b98f46a3ee9532ce58d636d6","declaration":"export type MeetingSetupCheck = MeetingSetupCheck;","entrypoint":"meeting-runtime","exportName":"MeetingSetupCheck","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"f0aed6f7955a43fc387d8bbc072cb6276b0f2d18e7f829441a2ad45974bb3831","declaration":"export type MeetingSetupStatus = MeetingSetupStatus;","entrypoint":"meeting-runtime","exportName":"MeetingSetupStatus","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} @@ -3265,9 +3265,75 @@ {"closureHash":"20c70a94483aeddda4d1500cfcc5e71fab844b474ba4061c55d6c8693d40821b","declaration":"export type MeetingVoiceCallJoinResult = MeetingVoiceCallJoinResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallJoinResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"4fb2c5928aa6f809dd4c604d71c5c99cdfe3e98b6e9c1662601c9b4ad9738162","declaration":"export type MeetingVoiceCallStatusResult = MeetingVoiceCallStatusResult;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallStatusResult","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} {"closureHash":"5ef812397b6409a4ca228943dd1080661365959477b42e705a9aaa219757d14f","declaration":"export type MeetingVoiceCallSurface = MeetingVoiceCallSurface;","entrypoint":"meeting-runtime","exportName":"MeetingVoiceCallSurface","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"type","recordType":"export"} -{"closureHash":"376e9dae283ed91fb2a5e5769c33f09bed27db7a0d42afe7d305bb1f6d58167e","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} +{"closureHash":"8c336f7da129c74739921825e397570d057e91a5fb5420dcc83faf10f5529f9a","declaration":"export interface MeetingPlatformAdapter extends MeetingPlatformAdapterContract {\n}","entrypoint":"meeting-runtime","exportName":"MeetingPlatformAdapter","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} {"closureHash":"79884bd1df1ea0d07d5ceb4c62d93c1ee744b75d31c94c988845869c0f3cbd2d","declaration":"export interface MeetingRealtimeAudioTransport {\n onFatal(handler: () => void): void;\n startInput(onAudio: (audio: Buffer) => void): void;\n beginOutput?(): void;\n stop(): Promise;\n writeOutput(audio: Buffer): Promise;\n clearOutput(): Promise;\n dispose(): Promise;\n getHealth?(): MeetingRealtimeAudioTransportHealth;\n startBargeInMonitor?(onBargeIn: (audio: Buffer) => boolean): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingRealtimeAudioTransport","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"interface","recordType":"export"} -{"closureHash":"2bf79ddb49656aafb6210e91b35334500af758fbe90bc6da026a8660fd3ed5b4","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"} +{"closureHash":"3cc6f9a12eabf0fda13fc2b5b2ae36daf143c0878f78375800dd071da4b006b0","declaration":"export class MeetingSessionRuntime, TRequest, TTransport extends string, TMode extends string, THealth extends MeetingBrowserHealth, TTab extends MeetingBrowserTab, TManualReason extends string, TSpeechBlockedReason extends string> {\n readonly #sessions: Map;\n readonly #sessionLeaves: Map>>;\n readonly #sessionCleanup: MeetingSessionCleanupTracker;\n readonly #meetingLock: MeetingSessionJoinLock;\n readonly #sessionStops: Map Promise>;\n readonly #sessionSpeakers: Map void>;\n readonly #sessionHealth: Map Partial>;\n readonly #durableTranscripts: MeetingSessionDurableTranscripts;\n readonly #transcriptStore: MeetingSessionTranscriptStore;\n constructor(private readonly options: MeetingSessionRuntimeOptions);\n list(): TSession[];\n getSession(sessionId: string): TSession | undefined;\n async status(sessionId?: string): Promise<{\n found: boolean;\n session?: TSession;\n sessions?: TSession[];\n }>;\n async transcript(sessionId: string, options: {\n sinceIndex?: number;\n }): Promise<{ found: boolean; sessionId?: string; startIndex?: number; nextIndex?: number; droppedLines?: number; evicted?: boolean; lines?: MeetingTranscriptLine[]; }>;\n async startTranscriptSource(request: TranscriptStartRequest): Promise;\n async stopTranscriptSource(request: TranscriptStopRequest): Promise;\n isReusableSession(session: TSession, resolved: MeetingResolvedJoin): boolean;\n async join(request: TRequest): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async leave(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async speak(sessionId: string, instructions?: string): Promise<{\n found: boolean;\n spoken: boolean;\n session?: TSession;\n }>;\n async speakWhenReady(session: TSession, instructions: string): Promise;\n hasHealthHandle(sessionId: string): boolean;\n refreshHealth(sessionId?: string): void;\n async refreshBrowserHealth(session: TSession, options: {\n force?: boolean;\n readOnly?: boolean;\n }): Promise;\n async refreshCaptionHealth(session: TSession): Promise;\n refreshSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n markSessionEnded(session: TSession, reason: string): void;\n async #joinUnlocked(request: TRequest, resolved: MeetingResolvedJoin): Promise<{\n session: TSession;\n spoken?: boolean;\n }>;\n async #leaveUnlocked(sessionId: string, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n async #leaveSession(session: TSession, options?: {\n keepBrowserTab?: boolean;\n }): Promise>;\n #meetingKey(transport: TTransport, url: string): string;\n #inheritBrowserTabOwnership(params: {\n session: TSession;\n transport: TTransport;\n nodeId?: string;\n meetingUrl: string;\n tab?: TTab;\n }): TTab | undefined;\n async #settleRetainedBrowserTabs(retained: Array<{\n session: TSession;\n tab: TTab;\n }>, adopted?: {\n transport: TTransport;\n nodeId?: string;\n tab: TTab;\n }): Promise;\n async #rollbackFailedJoinSession(session: TSession): Promise;\n async #settleRetainedBrowserTabsAfterFailure(retained: Array<{\n session: TSession;\n tab: TTab;\n }>): Promise;\n #attachRuntimeHandles(session: TSession, handles: MeetingSessionRuntimeHandles): void;\n #dropRuntimeHandles(sessionId: string): void;\n #isManagedBrowserSession(session: TSession): boolean;\n #evaluateSpeechReadiness(session: TSession): {\n ready: boolean;\n reason?: TSpeechBlockedReason;\n message?: string;\n };\n #noteSession(session: TSession, note: string): void;\n}","entrypoint":"meeting-runtime","exportName":"MeetingSessionRuntime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime","kind":"class","recordType":"export"} +{"category":null,"entrypoint":"memory-authorization","importSpecifier":"openclaw/plugin-sdk/memory-authorization","recordType":"module"} +{"closureHash":"0ee4b1ca0b2e0ced619eeebbf22d86bd20e4c2e3c59d49d0d67c06641041cd79","declaration":"export function hasCompleteMemoryAuthorizationCapabilities(capabilities: unknown): capabilities is MemoryAuthorizationCapabilities;","entrypoint":"memory-authorization","exportName":"hasCompleteMemoryAuthorizationCapabilities","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"function","recordType":"export"} +{"closureHash":"f39104a379c1ed53a7b6d31d5ba2d13e9944364fabaff21d52b56b62c3a1b0e6","declaration":"export function isMemoryAuthorizationCapabilities(value: unknown): value is MemoryAuthorizationCapabilities;","entrypoint":"memory-authorization","exportName":"isMemoryAuthorizationCapabilities","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"function","recordType":"export"} +{"closureHash":"7b98d3a2271904e42ee6000ccfa2f4383771864de13e5242be1e39c81d55ee5b","declaration":"export function listMissingMemoryAuthorizationCapabilities(capabilities: unknown): MemoryAuthorizationCapabilityName[];","entrypoint":"memory-authorization","exportName":"listMissingMemoryAuthorizationCapabilities","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"function","recordType":"export"} +{"closureHash":"83604f54c1dba09754a2ddc68a84e70a8673c70735cf1865208345d65857e2f5","declaration":"export const COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES: Readonly<{ version: 1; scopedCandidates: true; exactReadByAuthorizedHandle: true; scopedSync: true; scopedWrite: true; scopedImport: true; scopedExport: true; scopedStatus: true; exposureReceipts: true; egressReceipts: true;}>;","entrypoint":"memory-authorization","exportName":"COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"const","recordType":"export"} +{"closureHash":"9e7240f7d047945d7a8e82f5c871d587777973d9bd846f030bfa311a0c85e0ef","declaration":"export const LEGACY_MEMORY_AUTHORIZATION_CAPABILITIES: Readonly<{ version: 1; scopedCandidates: false; exactReadByAuthorizedHandle: false; scopedSync: false; scopedWrite: false; scopedImport: false; scopedExport: false; scopedStatus: false; exposureReceipts: false; egressReceipts: false;}>;","entrypoint":"memory-authorization","exportName":"LEGACY_MEMORY_AUTHORIZATION_CAPABILITIES","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"const","recordType":"export"} +{"closureHash":"02866d9e60292c5a245bd16b0f8698e5af08e6d17a9d1508188ca6393b75f58e","declaration":"export const MEMORY_AUTHORIZATION_CAPABILITY_NAMES: readonly [\"scopedCandidates\", \"exactReadByAuthorizedHandle\", \"scopedSync\", \"scopedWrite\", \"scopedImport\", \"scopedExport\", \"scopedStatus\", \"exposureReceipts\", \"egressReceipts\"];","entrypoint":"memory-authorization","exportName":"MEMORY_AUTHORIZATION_CAPABILITY_NAMES","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"const","recordType":"export"} +{"closureHash":"838951bf75cc80db9dd24d7bd91663da443dce8df59c5203ff0c75ee04253001","declaration":"export const MEMORY_AUTHORIZATION_CONTRACT_VERSION: 1;","entrypoint":"memory-authorization","exportName":"MEMORY_AUTHORIZATION_CONTRACT_VERSION","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"const","recordType":"export"} +{"closureHash":"0576d5ff05ae40e2f584df67ade98e053cae556dad8e6dc27fed1bed6e8540fa","declaration":"export const MEMORY_OPERATIONS: readonly [\"retrieve\", \"read\", \"append\", \"replace\", \"derive\", \"deposit\", \"project\", \"publish\", \"import\", \"export\", \"delete\", \"sync\", \"status\", \"policy-admin\"];","entrypoint":"memory-authorization","exportName":"MEMORY_OPERATIONS","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"const","recordType":"export"} +{"closureHash":"c49dbc4a64dd5f1f9c130b5b1fc30d21d98057d37fc0c5b6fef1cd2801463300","declaration":"export type AudienceRef = Readonly<{ kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; id: string;}>;","entrypoint":"memory-authorization","exportName":"AudienceRef","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"95c8d6d814558ffa3176bb5d9ba0682fa263e5655033205bbcfe52f941f1db25","declaration":"export type AuthorizedMemoryContentPlan = AuthorizedMemoryContentPlan;","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryContentPlan","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"c78173eba0c1ee6e71cb96f5bf1876cbaa19906b73877f309d1089caab6f4f8e","declaration":"export type AuthorizedMemoryMount = { readonly version: 1; readonly agentId: string; readonly mountHandle: string; readonly capabilities: readonly (\"replace\" | \"status\" | \"read\" | \"delete\" | \"project\" | \"retrieve\" | \"append\" | \"derive\" | \"deposit\" | \"publish\" | \"import\" | \"export\" | \"sync\" | \"policy-admin\")[]; readonly audienceRevision: string;};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryMount","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"b6dffdcb79f550769a4549e065779f7c93af135ae6f72ef441cba89a5718e13b","declaration":"export type AuthorizedMemoryMutation = AuthorizedMemoryMutation;","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryMutation","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"4b774e18e8524a1bb8414d81067b2a89ae881a6c3353ece57816759d8c4009f1","declaration":"export type AuthorizedMemoryPlan = { readonly version: 1; readonly planId: string; readonly contextFingerprint: string; readonly runId: string; readonly agentId: string; readonly sessionId: string; readonly sessionIdentityRevision: string; readonly subjectRevision: string; readonly memoryPolicyRevision: string; readonly deliveryRevision: string; readonly operation: MemoryOperation; readonly mounts: readonly { readonly version: 1; readonly agentId: string; readonly mountHandle: string; readonly capabilities: readonly (\"replace\" | \"status\" | \"read\" | \"delete\" | \"project\" | \"retrieve\" | \"append\" | \"derive\" | \"deposit\" | \"publish\" | \"import\" | \"export\" | \"sync\" | \"policy-admin\")[]; readonly audienceRevision: string; }[]; readonly bootstrapResourceHandles: readonly { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string; }[]; readonly allowedEgressAudiences: readonly { readonly kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; readonly id: string; }[]; readonly expiresAt: string;};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryPlan","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"9aceb3a04da45b6cb8cb2142bb847b7e5036f92dc934bff47278da3c7b02e332","declaration":"export type AuthorizedMemoryPlanForContext = AuthorizedMemoryPlanForContext;","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryPlanForContext","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"de16c3afd4ac7c724b38053e2daa9085c40013b4dd387cfac98c0fad205ca3f0","declaration":"export type AuthorizedMemoryReadParams = Readonly<{ context: MemoryContentAccessContext; plan: AuthorizedMemoryContentPlan; handle: AuthorizedResourceHandle; from?: number; lines?: number;}>;","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryReadParams","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"31fdaf7321c8ebf7b709ad9e20429dd03506d6738c59429300ef62cb91128b1f","declaration":"export type AuthorizedMemoryResultEnvelope = { readonly version: 1; readonly value: DeepReadonly; readonly exposureReceipt: { readonly version: 1; readonly receiptId: string; readonly contextFingerprint: string; readonly planId: string; readonly runId: string; readonly runExposureRevision: string; readonly sourcePolicySetId: string; readonly exposedRevisionHandles: readonly string[]; readonly recordedAt: string; }; readonly egressReceipt: { readonly version: 1; readonly receiptId: string; readonly contextFingerprint: string; readonly planId: string; readonly runId: string; readonly runExposureRevision: string; readonly sourcePolicySetId: string; readonly allowedAudiences: readonly { readonly kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; readonly id: string; }[]; readonly deliveryRevision: string; readonly egressRegistryRevision: string; readonly expiresAt: string; };};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryResultEnvelope","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"6aa0dea8474477db4c20fdf56bb77f39e6474da7e736f54923c941948af47264","declaration":"export type AuthorizedMemorySearchParams = Readonly<{ context: MemoryContentAccessContext; plan: AuthorizedMemoryContentPlan; query: string; subjectHandles?: readonly string[]; sources?: readonly MemorySource[]; limit: number; signal?: AbortSignal;}>;","entrypoint":"memory-authorization","exportName":"AuthorizedMemorySearchParams","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"83e30cb96c283397c5d415a0ec813f69f682280b34cf1449c7d9155167b8b779","declaration":"export type AuthorizedMemorySearchResult = { readonly path: string; readonly startLine: number; readonly endLine: number; readonly score: number; readonly vectorScore?: number | undefined; readonly textScore?: number | undefined; readonly snippet: string; readonly source: MemorySource; readonly importance?: number | undefined; readonly triggers?: string | undefined; readonly projectKey?: string | undefined; readonly originClass?: string | undefined; readonly citation?: string | undefined; readonly provenance?: { readonly originClass: MemoryOriginClass; readonly sessionKind: MemorySessionKind; readonly observedAt: number; readonly supersedesKey?: string | undefined; } | undefined; readonly resourceHandle: { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string; };};","entrypoint":"memory-authorization","exportName":"AuthorizedMemorySearchResult","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"29f68c2597192844ee117e1ff56238287c53ed94b57cc5d9c4a97664b18da5fa","declaration":"export type AuthorizedMemoryStatus = { readonly version: 1; readonly backend: string; readonly provider?: string | undefined; readonly model?: string | undefined; readonly files?: number | undefined; readonly chunks?: number | undefined; readonly dirty?: boolean | undefined;};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryStatus","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"2a5a77be5b8e6de4357da098ba75efccdd4bc68b0cfd7044b648548c9d9d6343","declaration":"export type AuthorizedMemoryVirtualFile = { readonly version: 1; readonly mountHandle: string; readonly virtualPath: string;};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryVirtualFile","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"63be70bf8253ab66473fda6aa2d64b4d8ab6f483c9987e9d2cfd01bc5b11847e","declaration":"export type AuthorizedMemoryVirtualRoot = { readonly version: 1; readonly mountHandle: string; readonly virtualRoot: string; readonly access: \"read\";};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryVirtualRoot","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"cfc64d41fd6e47993eda1c7d39326e1d9a927e1538d5a330ecb2a6ed3e48e843","declaration":"export type AuthorizedMemoryVirtualView = { readonly version: 1; readonly viewId: string; readonly planId: string; readonly contextFingerprint: string; readonly revision: string; readonly roots: readonly { readonly version: 1; readonly mountHandle: string; readonly virtualRoot: string; readonly access: \"read\"; }[]; readonly files: readonly { readonly version: 1; readonly mountHandle: string; readonly virtualPath: string; }[]; readonly expiresAt: string;};","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryVirtualView","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"9e964b706d37f163c6045083b55e9115f5319fcaa72fb86d4595d2ff70f3f0b3","declaration":"export type AuthorizedResourceHandle = { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string;};","entrypoint":"memory-authorization","exportName":"AuthorizedResourceHandle","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"e610c8719f9e2a3b6782001cc4f990586db95c2b514c13427129ba8ca70f171c","declaration":"export type AuthorizedSealedCompactionArtifact = Readonly<{ resourceRevisionId: string; commitInTransaction(params: Readonly<{ database: DatabaseSync; compactionPolicyId: string; eventSeq: number; }>): void;}>;","entrypoint":"memory-authorization","exportName":"AuthorizedSealedCompactionArtifact","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"de26a2e6f50bd0a83387a778b2992ec3d1f7013b96759cdeff421166682d304c","declaration":"export type AuthorizedSealedCompactionStageParams = Readonly<{ context: MemoryAccessContext & Readonly<{ operation: \"derive\"; }>; plan: AuthorizedMemoryPlan & Readonly<{ operation: \"derive\"; }>; content: string; transcriptSource: AuthorizedTranscriptDerivationSource;}>;","entrypoint":"memory-authorization","exportName":"AuthorizedSealedCompactionStageParams","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"6851c7c333fe553520246da63ff16465009570a161f72cb95e0d101659ed7674","declaration":"export type AuthorizedTranscriptDerivationPurpose = AuthorizedTranscriptDerivationPurpose;","entrypoint":"memory-authorization","exportName":"AuthorizedTranscriptDerivationPurpose","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"683eff40eb7ca73217bc8befe198b86adcaff89381eab2191639ac20865ca5d3","declaration":"export type AuthorizedTranscriptDerivationSource = Readonly<{ kind: \"transcript\"; sessionId: string; eventSeqs: readonly number[]; sourcePolicySetId: string; deliveryAudiencesJson: string;}>;","entrypoint":"memory-authorization","exportName":"AuthorizedTranscriptDerivationSource","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"d456f5de097a9c2e255bf770b74f13c41c9e80c35143227375c33d7b14ac42b4","declaration":"export type MemoryAccessContext = { readonly version: 1; readonly contextId: string; readonly contextFingerprint: string; readonly requestId: string; readonly runId: string; readonly agentId: string; readonly sessionKey: string; readonly sessionId: string; readonly sessionIdentityRevision: string; readonly subjectRevision: string; readonly subject: { readonly version: 1; readonly kind: \"user\"; readonly principalId: string; readonly creationEvidence: { readonly kind: \"gateway-profile\" | \"channel-binding\" | \"adapter-attested\" | \"explicit-service\"; readonly revision: string; }; } | { readonly version: 1; readonly kind: \"conversation\"; readonly conversationPrincipalId: string; readonly channel: string; readonly accountId: string; } | { readonly version: 1; readonly kind: \"service\" | \"agent\" | \"system\"; readonly principalId: string; } | { readonly version: 1; readonly kind: \"ambiguous\"; readonly reason: \"shared-main\" | \"unbound\" | \"conflicting-bindings\"; }; readonly actor: { readonly kind: \"principal\"; readonly actorKind: \"human\" | \"agent\" | \"service\" | \"system\"; readonly principalId: string; readonly assurance: VerifiedPrincipalRef[\"assurance\"]; readonly evidenceRevision: string; readonly expiresAt?: string | undefined; } | { readonly kind: \"unattributed\"; readonly transportAuditRef: string; readonly evidenceRevision: string; }; readonly verifiedPrincipals: readonly { readonly principalId: string; readonly assurance: \"gateway-profile\" | \"adapter-attested\" | \"oidc\" | \"service\"; readonly evidenceRevision: string; readonly expiresAt?: string | undefined; }[]; readonly conversation?: { readonly conversationPrincipalId: string; readonly channel: string; readonly accountId: string; readonly evidenceRevision: string; } | undefined; readonly delivery: { readonly sinkKind: \"private\" | \"channel\" | \"session\" | \"internal\"; readonly audiences: readonly { readonly kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; readonly id: string; }[]; readonly egressCapabilityIds: readonly string[]; readonly egressRegistryRevision: string; readonly deliveryRevision: string; }; readonly collaboration: { readonly kind: \"gateway-session\"; readonly mode: \"shared\" | \"read-only\" | \"suggest\" | \"draft\"; readonly role: \"admin\" | \"owner\" | \"member\" | \"viewer\"; readonly decisionRevision: string; } | { readonly kind: \"not-applicable\"; }; readonly verifiedMemberships: readonly { readonly principalId: string; readonly groupId: string; readonly provider: string; readonly evidenceRevision: string; readonly observedAt: string; readonly expiresAt: string; }[]; readonly delegation?: { readonly rootPrincipalId: string; readonly rootContextId: string; readonly parentContextId: string; readonly parentMemoryPlanId: string; readonly capabilitySnapshotId: string; readonly allowedOperations: readonly (\"replace\" | \"status\" | \"read\" | \"delete\" | \"project\" | \"retrieve\" | \"append\" | \"derive\" | \"deposit\" | \"publish\" | \"import\" | \"export\" | \"sync\" | \"policy-admin\")[]; readonly maximumAudiences: readonly { readonly kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; readonly id: string; }[]; readonly storeCapToken: string; readonly depth: number; } | undefined; readonly operation: MemoryOperation; readonly hostFactsRevision: string;};","entrypoint":"memory-authorization","exportName":"MemoryAccessContext","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"19869d17f0c94844d6355891de03422eca742e0834cba0a3772759aba2b45e02","declaration":"export type MemoryActorEvidence = MemoryActorEvidence;","entrypoint":"memory-authorization","exportName":"MemoryActorEvidence","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"239657c141f6a0cd85bfb4a594877ce1dc082d3e9af0f252cf2d4899a640409b","declaration":"export type MemoryAuthorizationCapabilities = Readonly<{ version: 1;} & Record<\"scopedCandidates\" | \"exactReadByAuthorizedHandle\" | \"scopedSync\" | \"scopedWrite\" | \"scopedImport\" | \"scopedExport\" | \"scopedStatus\" | \"exposureReceipts\" | \"egressReceipts\", boolean>>;","entrypoint":"memory-authorization","exportName":"MemoryAuthorizationCapabilities","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"dd3ce6c8966f40b776e6b64a236e5328c65f21046d0001cd90c727c64dfd7c3c","declaration":"export type MemoryAuthorizationCapabilityName = \"scopedCandidates\" | \"exactReadByAuthorizedHandle\" | \"scopedSync\" | \"scopedWrite\" | \"scopedImport\" | \"scopedExport\" | \"scopedStatus\" | \"exposureReceipts\" | \"egressReceipts\";","entrypoint":"memory-authorization","exportName":"MemoryAuthorizationCapabilityName","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"6d309f78ab8354775900934f2dd78ec6c86fa7645870f47949d953c18f42aec7","declaration":"export type MemoryAuthorizationReasonCode = MemoryAuthorizationReasonCode;","entrypoint":"memory-authorization","exportName":"MemoryAuthorizationReasonCode","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"c1b4e16ab116affc8446ce2484b234feda6c09274ba1f6dab5119f2ee880cd6c","declaration":"export type MemoryContentAccessContext = MemoryContentAccessContext;","entrypoint":"memory-authorization","exportName":"MemoryContentAccessContext","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"f2cf3f330fd30e4887ea1242bee1867fcc4c285e8f665d263b06a5e4d974f1a0","declaration":"export type MemoryContentAccessOperation = MemoryContentAccessOperation;","entrypoint":"memory-authorization","exportName":"MemoryContentAccessOperation","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"70bd8ae0683e645aaaa30457d19d82ed7e1e97fb6b03d3d702597fca93fa9728","declaration":"export type MemoryEgressAuthorizationReceipt = { readonly version: 1; readonly receiptId: string; readonly contextFingerprint: string; readonly planId: string; readonly runId: string; readonly runExposureRevision: string; readonly sourcePolicySetId: string; readonly allowedAudiences: readonly { readonly kind: \"user\" | \"conversation\" | \"role\" | \"agent-shared\" | \"agent\" | \"internal\"; readonly id: string; }[]; readonly deliveryRevision: string; readonly egressRegistryRevision: string; readonly expiresAt: string;};","entrypoint":"memory-authorization","exportName":"MemoryEgressAuthorizationReceipt","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"9199f85b00d1d24dd60ac881e5374d0cfde151c88bb7235cbc5f9b3d6b35e298","declaration":"export type MemoryExportResult = { readonly version: 1; readonly exportId: string; readonly contentType: \"application/json\" | \"application/x-ndjson\" | \"text/markdown\" | \"text/plain\"; readonly encoding: \"utf8\" | \"base64\"; readonly payload: string; readonly exportedHandles: readonly { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string; }[];};","entrypoint":"memory-authorization","exportName":"MemoryExportResult","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"414d871aba310f6e260efa3c416adb3840bea1eb0ea81d99938e96d72b39067b","declaration":"export type MemoryExposureReceipt = { readonly version: 1; readonly receiptId: string; readonly contextFingerprint: string; readonly planId: string; readonly runId: string; readonly runExposureRevision: string; readonly sourcePolicySetId: string; readonly exposedRevisionHandles: readonly string[]; readonly recordedAt: string;};","entrypoint":"memory-authorization","exportName":"MemoryExposureReceipt","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"acc267c6c3a9c5633a29e054a4d00c9ab983e85dfb049dac492fc80af6358768","declaration":"export type MemoryOperation = \"retrieve\" | \"read\" | \"append\" | \"replace\" | \"derive\" | \"deposit\" | \"project\" | \"publish\" | \"import\" | \"export\" | \"delete\" | \"sync\" | \"status\" | \"policy-admin\";","entrypoint":"memory-authorization","exportName":"MemoryOperation","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"5611711171b3cda58d8d54c2599eaf8db079cb65b0e9fa1007efc6bcaeca573d","declaration":"export type MemorySyncResult = { readonly version: 1; readonly status: \"completed\" | \"unchanged\"; readonly synchronizedHandles: readonly { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string; }[];};","entrypoint":"memory-authorization","exportName":"MemorySyncResult","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"05f1dc697f60a89a2deb005466d8028f5e08070e9ed6fd0d1412b262d9ea7a07","declaration":"export type MemoryVerifiedMembership = Readonly<{ principalId: string; groupId: string; provider: string; evidenceRevision: string; observedAt: string; expiresAt: string;}>;","entrypoint":"memory-authorization","exportName":"MemoryVerifiedMembership","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"44e0a9cd2eccc2fe0cce205b11ce26d4c0f35857a0ff5d33c27ee21431ddd882","declaration":"export type MemoryWriteResult = { readonly version: 1; readonly mutationId: string; readonly status: \"committed\" | \"unchanged\"; readonly resourceHandle?: { readonly version: 1; readonly handleId: string; readonly planId: string; readonly contextFingerprint: string; readonly resourceRevision: string; readonly policyRevision: string; readonly expiresAt: string; } | undefined; readonly policyRevision: string; readonly committedAt: string;};","entrypoint":"memory-authorization","exportName":"MemoryWriteResult","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"581e1fee88fe8dd94a4da7d97673296aa5ccf2f7a72284e43eaa88f3c03bbd77","declaration":"export type SessionMemorySubject = SessionMemorySubject;","entrypoint":"memory-authorization","exportName":"SessionMemorySubject","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"eab5f1c3a7592549e4734f1743575fcc93a77757eeea037fe8116233f380969d","declaration":"export type SubjectEvidenceRef = Readonly<{ kind: \"gateway-profile\" | \"channel-binding\" | \"adapter-attested\" | \"explicit-service\"; revision: string;}>;","entrypoint":"memory-authorization","exportName":"SubjectEvidenceRef","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"2a8e34b1960be304fc69b9736d88eb761fe8573087e61cdcc501aae8bf6e1077","declaration":"export type VerifiedPrincipalRef = Readonly<{ principalId: string; assurance: \"gateway-profile\" | \"adapter-attested\" | \"oidc\" | \"service\"; evidenceRevision: string; expiresAt?: string;}>;","entrypoint":"memory-authorization","exportName":"VerifiedPrincipalRef","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"type","recordType":"export"} +{"closureHash":"37a05c3acd7b7ceec314f5021aa39c374aab4abbe6c1f78b501e544538db8368","declaration":"export interface AuthorizedMemoryRuntime {\n authorize(context: Context): Promise>;\n searchAuthorized(params: AuthorizedMemorySearchParams<\"read\">): Promise>;\n searchAuthorized(params: AuthorizedMemorySearchParams<\"derive\">): Promise>;\n readAuthorized(params: AuthorizedMemoryReadParams<\"read\">): Promise>;\n readAuthorized(params: AuthorizedMemoryReadParams<\"derive\">): Promise>;\n writeAuthorized(params: AuthorizedMemoryWriteParams): Promise;\n stageSealedCompaction?(params: AuthorizedSealedCompactionStageParams): Promise;\n importAuthorized(params: AuthorizedMemoryOperationParams<\"import\"> & Readonly<{\n mutation: AuthorizedMemoryMutationForOperation<\"import\">;\n }>): Promise;\n syncAuthorized(params: AuthorizedMemoryOperationParams<\"sync\">): Promise>;\n exportAuthorized(params: AuthorizedMemoryOperationParams<\"export\"> & Readonly<{\n handles: readonly AuthorizedResourceHandle[];\n }>): Promise>;\n statusAuthorized(params: AuthorizedMemoryOperationParams<\"status\">): Promise>;\n}","entrypoint":"memory-authorization","exportName":"AuthorizedMemoryRuntime","importSpecifier":"openclaw/plugin-sdk/memory-authorization","kind":"interface","recordType":"export"} +{"category":null,"entrypoint":"memory-authorization-conformance","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","recordType":"module"} +{"closureHash":"220abd980950edd8979ea98d46ab63ad78767a5651cb1db7d24dfeb509bd432a","declaration":"export function createMemoryAuthorizationConformanceCases(): MemoryAuthorizationConformanceCase[];","entrypoint":"memory-authorization-conformance","exportName":"createMemoryAuthorizationConformanceCases","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"function","recordType":"export"} +{"closureHash":"728fcf57235b18c416589bb51add99e71d7b94759bf6b10d9310d7accf2dc8e4","declaration":"export function evaluateMemoryAuthorizationConformanceScenario(params: { scenario: MemoryAuthorizationConformanceScenario; resource: MemoryAuthorizationConformanceResource; }): MemoryAuthorizationConformanceDecision;","entrypoint":"memory-authorization-conformance","exportName":"evaluateMemoryAuthorizationConformanceScenario","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"function","recordType":"export"} +{"closureHash":"38bd0c840f5acc11b948614acc6640ddfbece2bb714f210158c1567d8dfab951","declaration":"export function runMemoryAuthorizationConformanceSuite(adapter: MemoryAuthorizationConformanceAdapter): Promise;","entrypoint":"memory-authorization-conformance","exportName":"runMemoryAuthorizationConformanceSuite","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"function","recordType":"export"} +{"closureHash":"de2c9641d3cbeae10f03e26c84e23fa030dfdc480bacf96920c3b952aa09694e","declaration":"export const referenceMemoryAuthorizationConformanceAdapter: Readonly<{ evaluate(params: { scenario: MemoryAuthorizationConformanceScenario; resource: MemoryAuthorizationConformanceResource; }): MemoryAuthorizationConformanceDecision | Promise; prefilter(scenario: MemoryAuthorizationConformanceScenario): readonly string[] | Promise;}>;","entrypoint":"memory-authorization-conformance","exportName":"referenceMemoryAuthorizationConformanceAdapter","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"const","recordType":"export"} +{"closureHash":"2d85822c0d9795c9ebbcbb4bfd0ebc2309267e9c200f3724ff02c60e5c54b2a2","declaration":"export type MemoryAuthorizationConformanceAdapter = Readonly<{ evaluate(params: { scenario: MemoryAuthorizationConformanceScenario; resource: MemoryAuthorizationConformanceResource; }): MemoryAuthorizationConformanceDecision | Promise; prefilter(scenario: MemoryAuthorizationConformanceScenario): readonly string[] | Promise;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceAdapter","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"d66b228cc415b31989a4ce0d7d0b5e0ea49f02f8182f8fb19716d6a6b9920160","declaration":"export type MemoryAuthorizationConformanceCase = Readonly<{ id: string; scenario: MemoryAuthorizationConformanceScenario; expected: Readonly>;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceCase","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"25539e655f697ef3b6c68feb4882db3140b311e8bc3890268e8a782190b36499","declaration":"export type MemoryAuthorizationConformanceDecision = MemoryAuthorizationConformanceDecision;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceDecision","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"914489e7481f6046eca15567a93cf0655df61b77d971f63c318a2fdcca53150a","declaration":"export type MemoryAuthorizationConformanceMembership = MemoryAuthorizationConformanceMembership;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceMembership","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"c927a82e0761858d5954226eeaee64d8eac550de45c143c56572637565a40025","declaration":"export type MemoryAuthorizationConformanceMembershipRef = Readonly<{ principalId: string; groupId: string; provider: string; evidenceRevision: string; hostFactsRevision: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceMembershipRef","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"2cb07913d3e7138a4f5c9c196981bae9946a14b8166f2b0555fe572d67c30676","declaration":"export type MemoryAuthorizationConformanceMembershipRequirement = Readonly<{ principalId: string; groupId: string; provider: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceMembershipRequirement","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"03f48f3d2160893185e0ac410e6a399df5932adae7d6e9cb464998320a93fbf6","declaration":"export type MemoryAuthorizationConformanceMount = Readonly<{ storeId: string; agentId: string; capabilities: readonly MemoryOperation[]; audienceRevision: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceMount","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"504c8d5dd8649c198c92083968994bd057fb63d4bc6f4c7250d7ab1199cb904b","declaration":"export type MemoryAuthorizationConformancePlanBinding = Readonly<{ planId: string; contextFingerprint: string; runId: string; agentId: string; sessionId: string; sessionIdentityRevision: string; subjectRevision: string; deliveryRevision: string; policyRevision: string; hostFactsRevision: string; operation: MemoryOperation; mounts: readonly MemoryAuthorizationConformanceMount[]; allowedEgressAudiences: readonly AudienceRef[]; expiresAt: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformancePlanBinding","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"8f2d6477be1f462e8bd2f1d86a15e3e2cc8bf52458a1bbadac0655c8a4ef375d","declaration":"export type MemoryAuthorizationConformancePolicyEntry = Readonly<{ effect: \"allow\" | \"deny\"; principalId: string; resourceId: string; operation: MemoryOperation; expiresAt?: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformancePolicyEntry","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"b9e4de7a89bf78c81a03d7913ec5c99840f8bf780567afc605c3c5a893e0c06b","declaration":"export type MemoryAuthorizationConformancePrincipal = MemoryAuthorizationConformancePrincipal;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformancePrincipal","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"138f37fe5b61b377ee6c15dd423d40620b1384e5306d281c48333a87b4003a2a","declaration":"export type MemoryAuthorizationConformancePrincipalRef = Readonly<{ principalId: string; evidenceRevision: string;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformancePrincipalRef","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"ae1c0a4753980acbbe6c9387273b864cfd2bf0b883cc2b438d45a3c8e5117ac2","declaration":"export type MemoryAuthorizationConformanceReport = Readonly<{ ok: boolean; failures: readonly Readonly<{ caseId: string; invariant: \"decision\" | \"authorized-handle\" | \"denial-non-disclosure\" | \"prefilter-superset\" | \"duplicate-prefilter-candidate\"; }>[];}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceReport","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"e50237c8f181b774429a0a61250734f43a4984c9735c33fe71e58565870db46f","declaration":"export type MemoryAuthorizationConformanceResource = Readonly<{ resourceId: string; agentId: string; storeId: string; revision: string; audiences: readonly AudienceRef[]; expiresAt?: string; requiredLineagePolicySetIds?: readonly string[];}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceResource","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"1a2bd8bee6cf9faf9781d128c573d05bdea1bc65984474c5c1b8f2961e373f20","declaration":"export type MemoryAuthorizationConformanceScenario = Readonly<{ id: string; now: string; principals: readonly MemoryAuthorizationConformancePrincipal[]; memberships: readonly MemoryAuthorizationConformanceMembership[]; stores: readonly MemoryAuthorizationConformanceStore[]; resources: readonly MemoryAuthorizationConformanceResource[]; policyEntries: readonly MemoryAuthorizationConformancePolicyEntry[]; viewMounts: readonly MemoryAuthorizationConformanceMount[]; context: Readonly<{ contextFingerprint: string; runId: string; agentId: string; sessionId: string; sessionIdentityRevision: string; subjectRevision: string; deliveryRevision: string; policyRevision: string; hostFactsRevision: string; operation: MemoryOperation; principalRefs: readonly MemoryAuthorizationConformancePrincipalRef[]; membershipRefs: readonly MemoryAuthorizationConformanceMembershipRef[]; deliveryAudiences: readonly AudienceRef[]; lineagePolicySetIds: readonly string[]; delegation?: Readonly<{ allowedOperations: readonly MemoryOperation[]; maximumAudiences: readonly AudienceRef[]; }>; }>; plan: MemoryAuthorizationConformancePlanBinding;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceScenario","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} +{"closureHash":"74fbcee9ac3780ed7306763c7edd61bc1edbda2068fcaeab34cdc237a0809746","declaration":"export type MemoryAuthorizationConformanceStore = Readonly<{ storeId: string; agentId: string; placementCapabilities: readonly MemoryOperation[]; requiredMembership?: MemoryAuthorizationConformanceMembershipRequirement;}>;","entrypoint":"memory-authorization-conformance","exportName":"MemoryAuthorizationConformanceStore","importSpecifier":"openclaw/plugin-sdk/memory-authorization-conformance","kind":"type","recordType":"export"} {"category":null,"entrypoint":"memory-core-host-engine-foundation","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","recordType":"module"} {"closureHash":"e2df8d235401aebf58eb71652fbeaedb42ca00aaa5042a76909ff2c48ba6fd54","declaration":"export function createSubsystemLogger(subsystem: string): SubsystemLogger;","entrypoint":"memory-core-host-engine-foundation","exportName":"createSubsystemLogger","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"} {"closureHash":null,"declaration":"export function isPathInside(root: string, target: string): boolean;","entrypoint":"memory-core-host-engine-foundation","exportName":"isPathInside","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"function","recordType":"export"} @@ -3287,19 +3353,19 @@ {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"memory-core-host-engine-foundation","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"type","recordType":"export"} {"closureHash":"7cedbd544d48277997e5b1733b7f51b7720829ef7652ab5223112b904ad55597","declaration":"export type ResolvedMemorySearchConfig = ResolvedMemorySearchConfig;","entrypoint":"memory-core-host-engine-foundation","exportName":"ResolvedMemorySearchConfig","importSpecifier":"openclaw/plugin-sdk/memory-core-host-engine-foundation","kind":"type","recordType":"export"} {"category":null,"entrypoint":"memory-host-core","importSpecifier":"openclaw/plugin-sdk/memory-host-core","recordType":"module"} -{"closureHash":"709f31174b216fbe79ea496787a503e71a5edc85d87bc324cde87db533accb09","declaration":"export function buildActiveMemoryPromptSection(params: MemoryPromptSectionParams, prepared?: PreparedMemoryPromptSection): string[];","entrypoint":"memory-host-core","exportName":"buildActiveMemoryPromptSection","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} +{"closureHash":"85eb87c60f459ce9f171d8bfcd9d6fed25646e5500e929f49c2979783e9c9f25","declaration":"export function buildActiveMemoryPromptSection(params: MemoryPromptSectionParams, prepared?: PreparedMemoryPromptSection): string[];","entrypoint":"memory-host-core","exportName":"buildActiveMemoryPromptSection","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"5e8ea9cbb8511d5dccde893e744ff1f6787e8e28511c5bd2e6785f045f9c0950","declaration":"export function clearMemoryPluginState(): void;","entrypoint":"memory-host-core","exportName":"clearMemoryPluginState","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} -{"closureHash":"4122847b080b5b047e86beaee53535457df1529d8a21dd713c9887c8211ba122","declaration":"export function getMemoryCapabilityRegistration(): MemoryPluginCapabilityRegistration | undefined;","entrypoint":"memory-host-core","exportName":"getMemoryCapabilityRegistration","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} +{"closureHash":"9e1c668214a630630cffa5ef460f0ca13fd086ef6002f93b3ac68587f8b4bca5","declaration":"export function getMemoryCapabilityRegistration(): MemoryPluginCapabilityRegistration | undefined;","entrypoint":"memory-host-core","exportName":"getMemoryCapabilityRegistration","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"fe74b96393cbd8de5b55715478d08bd70fb0e7351188e6deef5eabf5cb07f714","declaration":"export function listActiveMemoryPublicArtifacts(params: { cfg: OpenClawConfig; }): Promise;","entrypoint":"memory-host-core","exportName":"listActiveMemoryPublicArtifacts","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"1175762bd3ca71bbe283f24c09d09fc4ca76908e837b6e63786d8dc5cc15d1e1","declaration":"export function listMemoryHostPublicArtifacts(params: { cfg: OpenClawConfig; }): Promise;","entrypoint":"memory-host-core","exportName":"listMemoryHostPublicArtifacts","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} -{"closureHash":"45dcda94b94389bfd3b01640d03914fb291b7f62e4d4d9119281dba1aea632a4","declaration":"export function registerMemoryCapability(requestedPluginId: string, capability: MemoryPluginCapability): void;","entrypoint":"memory-host-core","exportName":"registerMemoryCapability","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} -{"closureHash":"06eef00cf3100a307eb9ff6a53f4511d8943e153845d21cb8199022975ed2096","declaration":"export function registerMemoryCorpusSupplement(requestedPluginId: string, supplement: MemoryCorpusSupplement): void;","entrypoint":"memory-host-core","exportName":"registerMemoryCorpusSupplement","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} +{"closureHash":"c3ccc1ba311065620d7d7bd25d9046aa206b43ff107db1a3580f7a5ba7657cd2","declaration":"export function registerMemoryCapability(requestedPluginId: string, capability: MemoryPluginCapability): void;","entrypoint":"memory-host-core","exportName":"registerMemoryCapability","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} +{"closureHash":"5c8bb50b82c6b2a67cbc7d592f0ac02aef0fddf590b3a2e3e8463f15aa8200dc","declaration":"export function registerMemoryCorpusSupplement(requestedPluginId: string, supplement: MemoryCorpusSupplement): void;","entrypoint":"memory-host-core","exportName":"registerMemoryCorpusSupplement","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"851fc50d9816836a9c2e923d4223eb86c15411c2d94153f64bf0171013dfc031","declaration":"export function resolveDefaultAgentId(cfg: OpenClawConfig): string;","entrypoint":"memory-host-core","exportName":"resolveDefaultAgentId","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"78ce37a08eff2ab75b9aa6141c90a2ee96898844625bc714e872b90809338b16","declaration":"export function resolveSessionAgentId(params: { sessionKey?: string; config?: OpenClawConfig; agentId?: string; fallbackAgentId?: string; }): string;","entrypoint":"memory-host-core","exportName":"resolveSessionAgentId","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} {"closureHash":"bb27dfb37540b04bb34f8281a3acd97a37ffb4ab7a5acdab529859f6474a0c1d","declaration":"export function resolveSessionTranscriptsDirForAgent(agentId: string, env?: NodeJS.ProcessEnv, homedir?: () => string): string;","entrypoint":"memory-host-core","exportName":"resolveSessionTranscriptsDirForAgent","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"function","recordType":"export"} -{"closureHash":"0b824778ee420a4a199233d8fe4635960ed53a0c96964a9e90e8e9e31c9ffe4b","declaration":"export type MemoryPluginCapability = MemoryPluginCapability;","entrypoint":"memory-host-core","exportName":"MemoryPluginCapability","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"type","recordType":"export"} +{"closureHash":"786e9bcb90b7e3c4a6bda0a54b84bfad4a6d968a0bb05b2a6649e0107cce0f8d","declaration":"export type MemoryPluginCapability = MemoryPluginCapability;","entrypoint":"memory-host-core","exportName":"MemoryPluginCapability","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"type","recordType":"export"} {"closureHash":"77d2bdba5dec3f7c4ce6b6f5d9607f693dd84be375c74387eec5dcc04c0ce2aa","declaration":"export type MemoryPluginPublicArtifact = MemoryPluginPublicArtifact;","entrypoint":"memory-host-core","exportName":"MemoryPluginPublicArtifact","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"type","recordType":"export"} -{"closureHash":"4a0bc9cba08233a3c603680a77414170971151fb785bd601ffe26de8d031b0c3","declaration":"export type MemoryPromptSectionBuilder = MemoryPromptSectionBuilder;","entrypoint":"memory-host-core","exportName":"MemoryPromptSectionBuilder","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"type","recordType":"export"} +{"closureHash":"19d10efd8ccd6dac324fb7c843b6b0394761d4ce407cbf76d4b18cdbfa2ea051","declaration":"export type MemoryPromptSectionBuilder = MemoryPromptSectionBuilder;","entrypoint":"memory-host-core","exportName":"MemoryPromptSectionBuilder","importSpecifier":"openclaw/plugin-sdk/memory-host-core","kind":"type","recordType":"export"} {"category":null,"entrypoint":"messaging-targets","importSpecifier":"openclaw/plugin-sdk/messaging-targets","recordType":"module"} {"closureHash":"dfc00563b0442ebf2e740c87499b5b5be99ebb2e8a0ad3b1a5456ed577666f6c","declaration":"export function buildMessagingTarget(kind: MessagingTargetKind, id: string, raw: string): MessagingTarget;","entrypoint":"messaging-targets","exportName":"buildMessagingTarget","importSpecifier":"openclaw/plugin-sdk/messaging-targets","kind":"function","recordType":"export"} {"closureHash":"a4b0c494578e7b33fbcf91fbb24d779092dd8710870bb37a92e7e6523f3c43ec","declaration":"export function ensureTargetId(params: { candidate: string; pattern: RegExp; errorMessage: string; }): string;","entrypoint":"messaging-targets","exportName":"ensureTargetId","importSpecifier":"openclaw/plugin-sdk/messaging-targets","kind":"function","recordType":"export"} @@ -3385,14 +3451,14 @@ {"closureHash":"e982df4834c8e5e2b45ccc4cde433658e190dcf2a7f3b0d2c700d4ef6eb1632d","declaration":"export type PersistentDedupeOptions = PersistentDedupeOptions;","entrypoint":"persistent-dedupe","exportName":"PersistentDedupeOptions","importSpecifier":"openclaw/plugin-sdk/persistent-dedupe","kind":"type","recordType":"export"} {"closureHash":"dfc56d38508426a6a78afd761e1a1288222c4467ffda62eb27d7eac30671bc21","declaration":"export type PersistentDedupePluginStateOptions = PersistentDedupePluginStateOptions;","entrypoint":"persistent-dedupe","exportName":"PersistentDedupePluginStateOptions","importSpecifier":"openclaw/plugin-sdk/persistent-dedupe","kind":"type","recordType":"export"} {"category":"runtime","entrypoint":"plugin-command-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","recordType":"module"} -{"closureHash":"4a8d8b3f396313777190457525e0a155e8ee8ff0692608c97b9d3a2d7ad2ab56","declaration":"export function createPluginCommandRuntime(): PluginCommandRuntime;","entrypoint":"plugin-command-runtime","exportName":"createPluginCommandRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"function","recordType":"export"} +{"closureHash":"93a9965aea93f7823ff6e0f15ec6bc3586281101f6774cb86329e6af2b01362d","declaration":"export function createPluginCommandRuntime(): PluginCommandRuntime;","entrypoint":"plugin-command-runtime","exportName":"createPluginCommandRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"function","recordType":"export"} {"closureHash":"00d993432f711b0223902a7d79b6da2e8ce785bac94b048d069ad8fcbe75db6f","declaration":"export const PLUGIN_COMMAND_DISPATCH: typeof PLUGIN_COMMAND_DISPATCH;","entrypoint":"plugin-command-runtime","exportName":"PLUGIN_COMMAND_DISPATCH","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"const","recordType":"export"} -{"closureHash":"bf2b23c7135b820678675698ff83436b2cb9ee65974575eb5d80fa0f01973549","declaration":"export type PluginCommandCatalogDecision = PluginCommandCatalogDecision;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandCatalogDecision","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} -{"closureHash":"ec1b62205ef1465fac3a939cec5af0db61cc246b298284164f2b25537d503236","declaration":"export type PluginCommandDispatch = Readonly<{ kind: \"plugin\"; execute: (context: PluginCommandDispatchContext) => Promise; [pluginCommandDispatchBrand]: true;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandDispatch","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} -{"closureHash":"1e583a3ad9edb24b54ae0b988c89515953bb09f162718ef76dca2dce529e612e","declaration":"export type PluginCommandDispatchContext = Readonly<{ senderId?: string; channel: string; channelId?: PluginCommandContext[\"channelId\"]; isAuthorizedSender: boolean; senderIsOwner?: boolean; gatewayClientScopes?: PluginCommandContext[\"gatewayClientScopes\"]; agentId?: string; sessionKey?: PluginCommandContext[\"sessionKey\"]; sessionId?: PluginCommandContext[\"sessionId\"]; sessionTarget?: PluginCommandContext[\"sessionTarget\"]; sessionFile?: PluginCommandContext[\"sessionFile\"]; authProfileId?: string; commandBody: string; config: OpenClawConfig; from?: PluginCommandContext[\"from\"]; to?: PluginCommandContext[\"to\"]; originatingTo?: string; accountId?: PluginCommandContext[\"accountId\"]; messageThreadId?: PluginCommandContext[\"messageThreadId\"]; threadParentId?: PluginCommandContext[\"threadParentId\"]; diagnosticsSessions?: PluginCommandContext[\"diagnosticsSessions\"]; diagnosticsUploadApproved?: PluginCommandContext[\"diagnosticsUploadApproved\"]; diagnosticsPreviewOnly?: PluginCommandContext[\"diagnosticsPreviewOnly\"]; diagnosticsPrivateRouted?: PluginCommandContext[\"diagnosticsPrivateRouted\"];}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandDispatchContext","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} -{"closureHash":"7114202fdc199ed3fb7b772e488aad4b0ae5b6142086279a5653832339de78b1","declaration":"export type PluginCommandNativeCandidate = Readonly<{ name: string; description: string; descriptionLocalizations?: Readonly>; acceptsArgs: boolean; requireAuth: boolean; progressMessage?: string; prepareDispatch: (rawArgs?: string) => PluginCommandCatalogDecision;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandNativeCandidate","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} +{"closureHash":"ae80c13f972aceaa33ba8f814bafe2c1e5d9f6c6f5bf4b36de44c5a217cd075b","declaration":"export type PluginCommandCatalogDecision = PluginCommandCatalogDecision;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandCatalogDecision","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} +{"closureHash":"c82316b00a069c77be9d701e35a1db15df936c5ae25682536a191e6bfaf181dd","declaration":"export type PluginCommandDispatch = Readonly<{ kind: \"plugin\"; execute: (context: PluginCommandDispatchContext) => Promise; [pluginCommandDispatchBrand]: true;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandDispatch","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} +{"closureHash":"c1bdb21a3a5349518b40e9584b3363dce566c4a9d13adf02f465faa4cb3b694f","declaration":"export type PluginCommandDispatchContext = Readonly<{ senderId?: string; channel: string; channelId?: PluginCommandContext[\"channelId\"]; isAuthorizedSender: boolean; senderIsOwner?: boolean; gatewayClientScopes?: PluginCommandContext[\"gatewayClientScopes\"]; agentId?: string; sessionKey?: PluginCommandContext[\"sessionKey\"]; sessionId?: PluginCommandContext[\"sessionId\"]; sessionTarget?: PluginCommandContext[\"sessionTarget\"]; sessionFile?: PluginCommandContext[\"sessionFile\"]; authProfileId?: string; commandBody: string; config: OpenClawConfig; from?: PluginCommandContext[\"from\"]; to?: PluginCommandContext[\"to\"]; originatingTo?: string; accountId?: PluginCommandContext[\"accountId\"]; messageThreadId?: PluginCommandContext[\"messageThreadId\"]; threadParentId?: PluginCommandContext[\"threadParentId\"]; diagnosticsSessions?: PluginCommandContext[\"diagnosticsSessions\"]; diagnosticsUploadApproved?: PluginCommandContext[\"diagnosticsUploadApproved\"]; diagnosticsPreviewOnly?: PluginCommandContext[\"diagnosticsPreviewOnly\"]; diagnosticsPrivateRouted?: PluginCommandContext[\"diagnosticsPrivateRouted\"];}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandDispatchContext","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} +{"closureHash":"9cd03a24480d9f60eb50ef65bd1c0b280d7171387bf34d90f25a44a606c2be31","declaration":"export type PluginCommandNativeCandidate = Readonly<{ name: string; description: string; descriptionLocalizations?: Readonly>; acceptsArgs: boolean; requireAuth: boolean; progressMessage?: string; prepareDispatch: (rawArgs?: string) => PluginCommandCatalogDecision;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandNativeCandidate","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} {"closureHash":"02fc8b5c9bcf5902ce275b0e26f7c219025d431dbecc4d9a605062b03904df3b","declaration":"export type PluginCommandReplyOptions = Readonly<{ [PLUGIN_COMMAND_DISPATCH]?: Readonly<{ kind: \"plugin\" | \"non-plugin\"; }>;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandReplyOptions","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} -{"closureHash":"e392a0cdd1b2504b72d99d2f342670333602919e6005400e69b9017da01439b2","declaration":"export type PluginCommandRuntime = Readonly<{ listNativeCandidates: (provider: string) => readonly PluginCommandNativeCandidate[]; retainNativeCatalog: (provider: string) => void;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} +{"closureHash":"85bc80ebe71a49e20bd694b8e26ce92236d0c399766a95b68d40fc7a780934db","declaration":"export type PluginCommandRuntime = Readonly<{ listNativeCandidates: (provider: string) => readonly PluginCommandNativeCandidate[]; retainNativeCatalog: (provider: string) => void;}>;","entrypoint":"plugin-command-runtime","exportName":"PluginCommandRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-command-runtime","kind":"type","recordType":"export"} {"category":null,"entrypoint":"plugin-config-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-config-runtime","recordType":"module"} {"closureHash":"5f7bee4e3a0121f16c56af8da4317eab4a9b874f72e1936866231412b1299d3e","declaration":"export function mergeDeep(base: unknown, override: unknown, options?: DeepMergeOptions): unknown;","entrypoint":"plugin-config-runtime","exportName":"mergeDeep","importSpecifier":"openclaw/plugin-sdk/plugin-config-runtime","kind":"function","recordType":"export"} {"closureHash":"605ebf4cd3d4d4028a5355b3b3520b99543cf4572b64afcf346b228c1f5cfab3","declaration":"export function requireRuntimeConfig(config: OpenClawConfig, context: string): OpenClawConfig;","entrypoint":"plugin-config-runtime","exportName":"requireRuntimeConfig","importSpecifier":"openclaw/plugin-sdk/plugin-config-runtime","kind":"function","recordType":"export"} @@ -3403,9 +3469,9 @@ {"category":"core","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","recordType":"module"} {"closureHash":"3d27406644141af2733cfca6e8c1240fc62327910109f585ce9073cafd7fd89c","declaration":"export function buildJsonPluginConfigSchema(schema: JsonSchemaObject, options?: BuildJsonPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"buildJsonPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} {"closureHash":"aff66c792d532642afb9c6e5a03c8d220f219250c3a8b49733f32058f22f98ca","declaration":"export function buildPluginConfigSchema(schema: ZodTypeAny, options?: BuildPluginConfigSchemaOptions): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"buildPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} -{"closureHash":"fd766c74118002291fa28dcd19a9677cdf9f615fe09994862f95b989dd36479a","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} +{"closureHash":"bcdcc487ce9eee949611005455c7cb794c78852875f5749d1712e27c02ce4cf8","declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, reload, nodeHostCommands, securityAuditCollectors, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} {"closureHash":"0ef1dfa3b5deeb456480e292c0e835c3cd6d13e7bb7059fc735546507da51594","declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export"} -{"closureHash":"d759a25775cb15d3f1804e39e98518f83b67b29ba3ab2fd84d4bf16106d9fdb9","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"plugin-entry","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"cff7e843ff24f7db2fd0f413d247310c86216bd9b51393b64c22f0ef85cda68e","declaration":"export type AgentHarness = AgentHarness;","entrypoint":"plugin-entry","exportName":"AgentHarness","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"d2ff4de9ee3fd111c2cc64a3ee7e557d9f161af1b6b437ee7886bcb16e426317","declaration":"export type AgentPromptGuidance = AgentPromptGuidance;","entrypoint":"plugin-entry","exportName":"AgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"2841127a90e04467adfea8126cbf03655f44ddb089ad9e0d48833c2beea39cbd","declaration":"export type AgentPromptGuidanceEntry = AgentPromptGuidanceEntry;","entrypoint":"plugin-entry","exportName":"AgentPromptGuidanceEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"aa0412acefe62caff12e5271ead0545504874e824380dc21cfc0566388a05f33","declaration":"export type AgentPromptSurfaceKind = \"openclaw_main\" | \"pi_main\" | \"codex_app_server\" | \"cli_backend\" | \"acp_backend\" | \"subagent\";","entrypoint":"plugin-entry","exportName":"AgentPromptSurfaceKind","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} @@ -3415,16 +3481,16 @@ {"closureHash":"732f3c1b0e4942089773fad9da886d7b7bed41e7f1bb45d79c26deac15f6770b","declaration":"export type MigrationDetection = MigrationDetection;","entrypoint":"plugin-entry","exportName":"MigrationDetection","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"f40046e61c3037ec599a627e1088b8c78d1fe057d858e13cfaff1eab800e9f1f","declaration":"export type MigrationItem = MigrationItem;","entrypoint":"plugin-entry","exportName":"MigrationItem","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"934363b212df1e356365d44e0684401985228a2aeaf859aa13c840bae6e2190b","declaration":"export type MigrationPlan = MigrationPlan;","entrypoint":"plugin-entry","exportName":"MigrationPlan","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"5f753d95db38cc2d1ce2d35f8603c1599eb108cbb8fab484e9f0f04d2eb7783a","declaration":"export type MigrationProviderContext = MigrationProviderContext;","entrypoint":"plugin-entry","exportName":"MigrationProviderContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"428402413735d12151b028f2c301ec73c0e7cce87e63e105397c626d287a8ba2","declaration":"export type MigrationProviderPlugin = MigrationProviderPlugin;","entrypoint":"plugin-entry","exportName":"MigrationProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"359b28bf96434ed6f2e65c68a0619e7833f775cc585c7706160a26a0f012f367","declaration":"export type MigrationProviderContext = MigrationProviderContext;","entrypoint":"plugin-entry","exportName":"MigrationProviderContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"2ebb80fd4f82783977822aa52e98416a10567df49a7190a8546ca5be6723113b","declaration":"export type MigrationProviderPlugin = MigrationProviderPlugin;","entrypoint":"plugin-entry","exportName":"MigrationProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"cea9632d824ebf247f131958f8db4916ae60a37d4d5493e06f789d883dab6574","declaration":"export type MigrationSummary = MigrationSummary;","entrypoint":"plugin-entry","exportName":"MigrationSummary","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"8054ffbe71b91afced900ef8a06f5e368ac10c4f99ffc1c6f538a802856f61c6","declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"2f6e368fff73e942044cdf95c7c751b46c741e22ac0d2d4d97f45a3158f758ae","declaration":"export type OpenClawGatewayDiscoveryAdvertiseContext = OpenClawGatewayDiscoveryAdvertiseContext;","entrypoint":"plugin-entry","exportName":"OpenClawGatewayDiscoveryAdvertiseContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"b198058e0065e5c60b729a5bdf568f7e2436a006d8c4a7c63de764c7283f96ba","declaration":"export type OpenClawGatewayDiscoveryService = OpenClawGatewayDiscoveryService;","entrypoint":"plugin-entry","exportName":"OpenClawGatewayDiscoveryService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"647007b989ba3d08c520ec68873f65f22f231b0274daf10f5d219074fd2fcba6","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"1b85aede0a5709f8de9905bcedb2b1acbbdb6db5fdcdd7321e2294c2f8866424","declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"ccae64ce42b52f34fc0f2adffe6202985c2c8464e3e2df19f43ae1eb0005e808","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"87cbaf84f362b665d7e0a8c8d62835b297f00629a3d4200d6d07f3938b439f9c","declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"a7ed83f0924f818b23cecb5a1f3591ff28b9499ccac9667a2b8505c2bc608ea9","declaration":"export type OpenClawPluginGatewayEventScope = OpenClawPluginGatewayEventScope;","entrypoint":"plugin-entry","exportName":"OpenClawPluginGatewayEventScope","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"f81f224d9b837e6353b7a546c5a76b124bcf568fd1f1fd0c6881fda30c53120a","declaration":"export type OpenClawPluginGatewayEvents = OpenClawPluginGatewayEvents;","entrypoint":"plugin-entry","exportName":"OpenClawPluginGatewayEvents","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"7470b211ac4d3449cd0fc353ee2eb48e9fbc2dbc9259d21c680d0203577aa94f","declaration":"export type OpenClawPluginHttpRouteHandler = OpenClawPluginHttpRouteHandler;","entrypoint":"plugin-entry","exportName":"OpenClawPluginHttpRouteHandler","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} @@ -3438,14 +3504,14 @@ {"closureHash":"06e75d118c92e256eb6fe3c706844b4f03c2cba936f07c571702e1e606138cde","declaration":"export type OpenClawPluginSecurityAuditContext = OpenClawPluginSecurityAuditContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginSecurityAuditContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"ddc2738dd0ece94ddde9a7c655f92c15ec6416645ecf932d4aa404c7b7761159","declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"26dd6974af3127ca18835b3f7294f2dae0f7fab63c6d326e999e90366999dc6e","declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"4b4e5425c1e19a0d00f99e3b1f078f101a87a38dbf3cb81e124665ac11bb68d9","declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"cf4bb672a5d6622273e847afbab9b823e0fdb7bbecd43eebb2620c7711924273","declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"d0230fba39834d6c8e620d19799a0006eeea6a7a75a954930cb10acc0138b09f","declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"709aac28446af536b23ee9673d2e3ed3ca733faab5c47be6ccbf14b424f48798","declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"plugin-entry","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"b749d0cceb7b02f8e2e810c9a1f4fea64effc4a2ddb0da972d873781d2a70471","declaration":"export type PluginAgentEventEmitParams = PluginAgentEventEmitParams;","entrypoint":"plugin-entry","exportName":"PluginAgentEventEmitParams","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"402087ed5375c1fadc768f11ff28215402b3db725b9e8f924d195623993aa611","declaration":"export type PluginAgentEventEmitResult = PluginAgentEventEmitResult;","entrypoint":"plugin-entry","exportName":"PluginAgentEventEmitResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"028cd39dd470117f37aff9d199e99c7eadaa99a2af56810c3033e488587e56e2","declaration":"export type PluginAgentEventSubscriptionRegistration = PluginAgentEventSubscriptionRegistration;","entrypoint":"plugin-entry","exportName":"PluginAgentEventSubscriptionRegistration","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"3d9f3c666f1a8f37cd4fd2bf621d793b6626ce36edc96bd3922498a8f4ebfc19","declaration":"export type PluginAgentTurnPrepareEvent = PluginAgentTurnPrepareEvent;","entrypoint":"plugin-entry","exportName":"PluginAgentTurnPrepareEvent","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"dd9b818f8b19ced207493eea1b75da8a38b24a5dc4c9ac46288f9329ba06f0f3","declaration":"export type PluginAgentTurnPrepareResult = PluginAgentTurnPrepareResult;","entrypoint":"plugin-entry","exportName":"PluginAgentTurnPrepareResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} -{"closureHash":"d9d24565b06f891a687f49672129beac9d38ccb817526ed1a6579efcb5825eb0","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} +{"closureHash":"5c7a4e89ddfb6bed00f2ca8e67e43f150fedb3182275a525411365855d581c22","declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"a50f802cdb46fb073ccba3d7b5c2a3c66c2b5aeccca3368222f9a520e66055ca","declaration":"export type PluginCommandResult = PluginCommandResult;","entrypoint":"plugin-entry","exportName":"PluginCommandResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"b9a7fd2bdde1d99b58227e6ff01853420fee36357c2fa5e2d9ef5fbcef11ac65","declaration":"export type PluginControlUiDescriptor = PluginControlUiDescriptor;","entrypoint":"plugin-entry","exportName":"PluginControlUiDescriptor","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} {"closureHash":"f06379ada10ce0eca4e66bdf978db2c0035e054a135dc044c6d831ac7797c08f","declaration":"export type PluginConversationBinding = PluginConversationBinding;","entrypoint":"plugin-entry","exportName":"PluginConversationBinding","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export"} @@ -3571,23 +3637,23 @@ {"closureHash":"4754c7eecdfeb9bec0f26a3238e6ad00ffcab19368487e8b5263e305b505a0f9","declaration":"export function createChannelInteractiveDispatcher, TResult extends { handled?: boolean; } | void = void | { handled?: boolean; }, TDispatchInteractiveKey extends PropertyKey = TInteractiveKey>(config: { channel: TChannel; interactiveKey: TInteractiveKey; dispatchInteractiveKey?: TDispatchInteractiveKey; }): (params: { data: string; dedupeId: string; ctx: ChannelInteractiveDispatchContext; respond: TContext[\"respond\"]; conversation?: Parameters[0][\"conversation\"]; onMatched?: () => Promise | void; afterInvoke?: (result: TResult) => Promise | void; }) => Promise>;","entrypoint":"plugin-runtime","exportName":"createChannelInteractiveDispatcher","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"0c3a6112c7f680fed5c23a712088c1190973f4bb8d95cae4c334952f332159ad","declaration":"export function createInteractiveConversationBindingHelpers(params: { registration: RegisteredInteractiveMetadata; senderId?: string; conversation: PluginBindingConversation; }): { requestConversationBinding: (binding?: PluginConversationBindingRequestParams) => Promise; detachConversationBinding: () => Promise<{ removed: boolean; }>; getCurrentConversationBinding: () => Promise; };","entrypoint":"plugin-runtime","exportName":"createInteractiveConversationBindingHelpers","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"fb50ceec196dacc19da2cb48813071d009170fcb1663d646715a7cfce9d6d956","declaration":"export function dispatchPluginInteractiveHandler(params: { channel: TRegistration[\"channel\"]; data: string; dedupeId?: string; onMatched?: () => Promise | void; invoke: (match: PluginInteractiveMatch) => Promise | TResult; afterInvoke?: (result: TResult) => Promise | void; }): Promise>;","entrypoint":"plugin-runtime","exportName":"dispatchPluginInteractiveHandler","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"983131a9d5c2971ecd7f2fb04f9d664d6854535d1abe2099baf2292014c30b23","declaration":"export function executePluginCommand(params: { command: RegisteredPluginCommand; args?: string; senderId?: string; channel: string; channelId?: PluginCommandContext[\"channelId\"]; isAuthorizedSender: boolean; senderIsOwner?: boolean; gatewayClientScopes?: PluginCommandContext[\"gatewayClientScopes\"]; agentId?: string; sessionKey?: PluginCommandContext[\"sessionKey\"]; sessionId?: PluginCommandContext[\"sessionId\"]; sessionTarget?: PluginCommandContext[\"sessionTarget\"]; sessionFile?: PluginCommandContext[\"sessionFile\"]; authProfileId?: string; commandBody: string; config: OpenClawConfig; from?: PluginCommandContext[\"from\"]; to?: PluginCommandContext[\"to\"]; originatingTo?: string; accountId?: PluginCommandContext[\"accountId\"]; messageThreadId?: PluginCommandContext[\"messageThreadId\"]; threadParentId?: PluginCommandContext[\"threadParentId\"]; diagnosticsSessions?: PluginCommandContext[\"diagnosticsSessions\"]; diagnosticsUploadApproved?: PluginCommandContext[\"diagnosticsUploadApproved\"]; diagnosticsPreviewOnly?: PluginCommandContext[\"diagnosticsPreviewOnly\"]; diagnosticsPrivateRouted?: PluginCommandContext[\"diagnosticsPrivateRouted\"]; }): Promise;","entrypoint":"plugin-runtime","exportName":"executePluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"dfc8fc733f281bfbe0cc270964f0f657f17c2b97f21bc1b316aee6e9de8ff6ba","declaration":"export function getGlobalHookRunner(): HookRunner | null;","entrypoint":"plugin-runtime","exportName":"getGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"ad89f0a3d6986be8ac3e462a7e58771c2b205055cefaaa181c00ab0b8cf9126e","declaration":"export function executePluginCommand(params: { command: RegisteredPluginCommand; args?: string; senderId?: string; channel: string; channelId?: PluginCommandContext[\"channelId\"]; isAuthorizedSender: boolean; senderIsOwner?: boolean; gatewayClientScopes?: PluginCommandContext[\"gatewayClientScopes\"]; agentId?: string; sessionKey?: PluginCommandContext[\"sessionKey\"]; sessionId?: PluginCommandContext[\"sessionId\"]; sessionTarget?: PluginCommandContext[\"sessionTarget\"]; sessionFile?: PluginCommandContext[\"sessionFile\"]; authProfileId?: string; commandBody: string; config: OpenClawConfig; from?: PluginCommandContext[\"from\"]; to?: PluginCommandContext[\"to\"]; originatingTo?: string; accountId?: PluginCommandContext[\"accountId\"]; messageThreadId?: PluginCommandContext[\"messageThreadId\"]; threadParentId?: PluginCommandContext[\"threadParentId\"]; diagnosticsSessions?: PluginCommandContext[\"diagnosticsSessions\"]; diagnosticsUploadApproved?: PluginCommandContext[\"diagnosticsUploadApproved\"]; diagnosticsPreviewOnly?: PluginCommandContext[\"diagnosticsPreviewOnly\"]; diagnosticsPrivateRouted?: PluginCommandContext[\"diagnosticsPrivateRouted\"]; }): Promise;","entrypoint":"plugin-runtime","exportName":"executePluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"79b4dc5c92ca4df7380b2b5b9ef0f47ce05c32399ecdb9358d5ace007f6ac5a0","declaration":"export function getGlobalHookRunner(): HookRunner | null;","entrypoint":"plugin-runtime","exportName":"getGlobalHookRunner","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"db6583607237e4081814e2c5d4f8fb6f216ad3bbfe623bf16fc1a9c09c15f64b","declaration":"export function getPluginCommandSpecs(provider?: string, options?: PluginCommandSpecOptions): Array<{ name: string; description: string; descriptionLocalizations?: Record; acceptsArgs: boolean; }>;","entrypoint":"plugin-runtime","exportName":"getPluginCommandSpecs","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"8240e99e361a089d6dacdaecb1d367e31bdce8be4d3b137a5b0065904bac11c6","declaration":"export function getPluginRuntimeGatewayRequestScope(): PluginRuntimeGatewayRequestScope | undefined;","entrypoint":"plugin-runtime","exportName":"getPluginRuntimeGatewayRequestScope","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"cd4663caa45fa74583e45884af8ad4f7b257c541f9fc6e2d3e94e36b8f5c0348","declaration":"export function getPluginRuntimeGatewayRequestScope(): PluginRuntimeGatewayRequestScope | undefined;","entrypoint":"plugin-runtime","exportName":"getPluginRuntimeGatewayRequestScope","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"cfe277ce6de0c6ed50f1f54b66c889f6c95e91b058e8bcdc27aa37317a93a447","declaration":"export function listRegisteredPluginAgentPromptGuidance(params?: { surface?: AgentPromptSurfaceKind; includeLegacyGlobalGuidance?: boolean; }): string[];","entrypoint":"plugin-runtime","exportName":"listRegisteredPluginAgentPromptGuidance","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"c53214cb523257e979580c6683f378f2f8e85c154e18c8e30ad84ae0eba28c28","declaration":"export function matchPluginCommand(commandBody: string, options?: { channel?: string; }): { command: RegisteredPluginCommand; args?: string; } | null;","entrypoint":"plugin-runtime","exportName":"matchPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} -{"closureHash":"94e8ab88f5f42afc3ba7300ea0da6364722360be9083d89aade693b82c3e162f","declaration":"export function registerPluginCommand(pluginId: string, command: OpenClawPluginCommandDefinition, opts?: { pluginName?: string; pluginRoot?: string; allowReservedCommandNames?: boolean; allowOwnerStatusExposure?: boolean; }): CommandRegistrationResult;","entrypoint":"plugin-runtime","exportName":"registerPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"58b1f1492289993c25025fb63fcc64bc3027e882ca04926493ae9edc60dfd378","declaration":"export function matchPluginCommand(commandBody: string, options?: { channel?: string; }): { command: RegisteredPluginCommand; args?: string; } | null;","entrypoint":"plugin-runtime","exportName":"matchPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} +{"closureHash":"b9c2311f14f5fbed83650554e94f5323ad37956c527ffb532f0bcecd7a060c76","declaration":"export function registerPluginCommand(pluginId: string, command: OpenClawPluginCommandDefinition, opts?: { pluginName?: string; pluginRoot?: string; allowReservedCommandNames?: boolean; allowOwnerStatusExposure?: boolean; }): CommandRegistrationResult;","entrypoint":"plugin-runtime","exportName":"registerPluginCommand","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"16986e5d431f584c2d5053289eca3d2225bbe47a92cdfbbc2af91b264a165846","declaration":"export function registerPluginInteractiveHandler(pluginId: string, registration: PluginInteractiveHandlerRegistration, opts?: { pluginName?: string; pluginRoot?: string; }): InteractiveRegistrationResult;","entrypoint":"plugin-runtime","exportName":"registerPluginInteractiveHandler","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"f20c07a48e2c949fbc889e7a32760f4e52339d9f6d3eab49e00ff249266e2396","declaration":"export function startLazyPluginServiceModule(params: { skipEnvVar?: string; overrideEnvVar?: string; validateOverrideSpecifier?: (specifier: string) => string; loadDefaultModule: () => Promise; loadOverrideModule?: (specifier: string) => Promise; startExportNames: string[]; stopExportNames?: string[]; }): Promise;","entrypoint":"plugin-runtime","exportName":"startLazyPluginServiceModule","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"function","recordType":"export"} {"closureHash":"bad43ffe69d1d9d6c92c79df4c388b3dda685013a92392daef456f1622ade659","declaration":"export type LazyPluginServiceHandle = LazyPluginServiceHandle;","entrypoint":"plugin-runtime","exportName":"LazyPluginServiceHandle","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} -{"closureHash":"2ddf03be75f0d46c8a7e1d7a3d3e70122001b190dcb361132cef2f1d23d8ddec","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} +{"closureHash":"aded5b666490cf7e5cca6bf3942c5190ad1fc30fc73f542505c53e5999f649a9","declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"365beb5cee974639c2f35fc7a39088721ca8e9c618442830298b98033e9c768c","declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-runtime","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"f06379ada10ce0eca4e66bdf978db2c0035e054a135dc044c6d831ac7797c08f","declaration":"export type PluginConversationBinding = PluginConversationBinding;","entrypoint":"plugin-runtime","exportName":"PluginConversationBinding","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"a1223d674b2b66918a576ae05b04318d7b8cbe9b1d3bc6dd7a08d1a4fa79b291","declaration":"export type PluginConversationBindingRequestParams = PluginConversationBindingRequestParams;","entrypoint":"plugin-runtime","exportName":"PluginConversationBindingRequestParams","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"93c034724a937bb1239a3b4a386a20ac75fbcf66229842cc4c702c3360409e4c","declaration":"export type PluginConversationBindingRequestResult = PluginConversationBindingRequestResult;","entrypoint":"plugin-runtime","exportName":"PluginConversationBindingRequestResult","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"590c148a7b82d14242a172bee5027840ddd5366025200e48704ef4ae8f4bf0ee","declaration":"export type PluginInteractiveRegistration = PluginInteractiveRegistration;","entrypoint":"plugin-runtime","exportName":"PluginInteractiveRegistration","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"plugin-runtime","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"plugin-runtime","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"closureHash":"f16f4b33d2dd78e5d5da7b1aaeee0441ab35cd232b032e8a33219def7cf65f0f","declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"plugin-runtime","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk/plugin-runtime","kind":"type","recordType":"export"} {"category":null,"entrypoint":"provider-auth","importSpecifier":"openclaw/plugin-sdk/provider-auth","recordType":"module"} {"closureHash":"d5f31c750f1d545b3a51177ba4a008d6cf646165a8fc0c0c1328fa9999b8d6e2","declaration":"export function applyAuthProfileConfig(cfg: OpenClawConfig, params: { profileId: string; provider: string; mode: \"api_key\" | \"aws-sdk\" | \"oauth\" | \"token\"; email?: string; displayName?: string; preferProfileFirst?: boolean; }): OpenClawConfig;","entrypoint":"provider-auth","exportName":"applyAuthProfileConfig","importSpecifier":"openclaw/plugin-sdk/provider-auth","kind":"function","recordType":"export"} @@ -3671,10 +3737,10 @@ {"closureHash":"e66adcb55dec79be73a52bc76594b7e9210fd93c69a85b56098fbb58cecbb354","declaration":"export type WriteOAuthCredentialsOptions = WriteOAuthCredentialsOptions;","entrypoint":"provider-auth","exportName":"WriteOAuthCredentialsOptions","importSpecifier":"openclaw/plugin-sdk/provider-auth","kind":"type","recordType":"export"} {"category":null,"entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","recordType":"module"} {"closureHash":"b5665596a3f011454a5614681513516acd50b6c749536c43842d811980cf7ad3","declaration":"export function augmentModelCatalogWithProviderPlugins(params: { config?: OpenClawConfig; workspaceDir?: string; env?: NodeJS.ProcessEnv; metadataSnapshot?: PluginMetadataSnapshot; context: ProviderAugmentModelCatalogContext; }): Promise;","entrypoint":"provider-catalog-runtime","exportName":"augmentModelCatalogWithProviderPlugins","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"720c33e7d2fb1f65d8fd6c7949e9498fda0a1b4eb0ccf6a7635b2dce58d68d05","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"228e8e3d4bd122168da916b923639accece60b5706df52fb437fff2b2a46f18f","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"b066e2fa15256bc32e1fa098c5302922f0db5ccbca4a59c3331860e822c779fc","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} -{"closureHash":"b7e37ed1adcc928a9a65520f5c288051f01e873a99bcb559488de03869bb6cf7","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"bf54f4d4fa91bb7622264448c1d6c8c0877e6c6da7c49017411e4bfbf92440ea","declaration":"export function isPluginProvidersLoadInFlight(params: Parameters[0]): boolean;","entrypoint":"provider-catalog-runtime","exportName":"isPluginProvidersLoadInFlight","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"173301408b9dde514a93cd380e45fed805b669a49db3a120089510d82ad8eba5","declaration":"export function resolveCatalogHookProviderPluginIds(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; metadataSnapshot?: ProviderManifestLoadParams[\"metadataSnapshot\"]; }): string[];","entrypoint":"provider-catalog-runtime","exportName":"resolveCatalogHookProviderPluginIds","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"f37df52cd2e01f2d5a93820aba9cd86666219819bb973d56bca16660ff9e8adf","declaration":"export function resolveOwningPluginIdsForProvider(params: { provider: string; config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; manifestRegistry?: PluginManifestRegistry; metadataSnapshot?: Pick; }): string[] | undefined;","entrypoint":"provider-catalog-runtime","exportName":"resolveOwningPluginIdsForProvider","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} +{"closureHash":"20fd48026e5e6f620a182ccb85f178477954f31b382c38ab2dddb2340474783b","declaration":"export function resolvePluginProviders(params: { config?: PluginLoadOptions[\"config\"]; workspaceDir?: string; env?: PluginLoadOptions[\"env\"]; bundledProviderVitestCompat?: boolean; onlyPluginIds?: string[]; providerRefs?: readonly string[]; modelRefs?: readonly string[]; activate?: boolean; cache?: boolean; applyAutoEnable?: boolean; pluginSdkResolution?: PluginLoadOptions[\"pluginSdkResolution\"]; mode?: \"runtime\" | \"setup\"; includeUntrustedWorkspacePlugins?: boolean; pluginMetadataSnapshot?: PluginMetadataRegistryView; skipIfLoadInFlight?: boolean; }): ProviderPlugin[];","entrypoint":"provider-catalog-runtime","exportName":"resolvePluginProviders","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime","kind":"function","recordType":"export"} {"category":null,"entrypoint":"proxy-capture","importSpecifier":"openclaw/plugin-sdk/proxy-capture","recordType":"module"} {"closureHash":"d0e4e026d736bc00b1758d1089c44c3c5f3a09c7254291584de8cb297365804c","declaration":"export function acquireDebugProxyCaptureStore(dbPath: string, blobDir: string): { store: LegacyDebugProxyCaptureStore; release: () => void; };\nexport function acquireDebugProxyCaptureStore(options?: DebugProxyCaptureStoreOptions): { store: SharedDebugProxyCaptureStore; release: () => void; };","entrypoint":"proxy-capture","exportName":"acquireDebugProxyCaptureStore","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"} {"closureHash":"d41cbb9de51b7aee1c6cf8c713b0bc44f27ac926fbb6422c05726f196d11964e","declaration":"export function captureHttpExchange(params: { url: string; method: string; requestHeaders?: Headers | Record | undefined; requestBody?: BodyInit | Buffer | string | null; response: Response; transport?: \"http\" | \"sse\"; flowId?: string; meta?: Record; }, resolved?: DebugProxySettings, deps?: DebugProxyCaptureRuntimeDeps): void;","entrypoint":"proxy-capture","exportName":"captureHttpExchange","importSpecifier":"openclaw/plugin-sdk/proxy-capture","kind":"function","recordType":"export"} @@ -3923,7 +3989,7 @@ {"closureHash":"47c7a11095835696862fe7b72fccf28736af6308347543c26b5b2f538d76860b","declaration":"export const GROUP_POLICY_BLOCKED_LABEL: { readonly group: \"group messages\"; readonly guild: \"guild messages\"; readonly room: \"room messages\"; readonly channel: \"channel messages\"; readonly space: \"space messages\";};","entrypoint":"runtime-group-policy","exportName":"GROUP_POLICY_BLOCKED_LABEL","importSpecifier":"openclaw/plugin-sdk/runtime-group-policy","kind":"const","recordType":"export"} {"category":"runtime","entrypoint":"runtime-store","importSpecifier":"openclaw/plugin-sdk/runtime-store","recordType":"module"} {"closureHash":"e11d2c2694b927c79b6e07789be6bb56269d5ef1ec95b395a6e9c46f43883cbc","declaration":"export function createPluginRuntimeStore(errorMessage: string): { setRuntime: (next: T) => void; clearRuntime: () => void; tryGetRuntime: () => T | null; getRuntime: () => T; };\nexport function createPluginRuntimeStore(options: PluginRuntimeStoreOptions): { setRuntime: (next: T) => void; clearRuntime: () => void; tryGetRuntime: () => T | null; getRuntime: () => T; };","entrypoint":"runtime-store","exportName":"createPluginRuntimeStore","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"function","recordType":"export"} -{"closureHash":"b94637421f524b48f7e497e449491475a2cc35f3d6dc43bdf5274b401b9424b0","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export"} +{"closureHash":"8d8f8c012d739749de557261960af8c0c714403fefa6fa15bd06ddbaee90aee3","declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export"} {"category":null,"entrypoint":"secret-file","importSpecifier":"openclaw/plugin-sdk/secret-file","recordType":"module"} {"closureHash":null,"declaration":"export function createSecretFileAtomic(params: SecretFileWriteParams): Promise;","entrypoint":"secret-file","exportName":"createSecretFileAtomic","importSpecifier":"openclaw/plugin-sdk/secret-file","kind":"function","recordType":"export"} {"closureHash":null,"declaration":"export function readSecretFile(filePath: string, label: string, options?: SecretFileReadOptions): Promise;","entrypoint":"secret-file","exportName":"readSecretFile","importSpecifier":"openclaw/plugin-sdk/secret-file","kind":"function","recordType":"export"} @@ -4034,8 +4100,8 @@ {"closureHash":"a7a32cdc228b5a4b027448fe2e79e332d7b5c5ff50f2afdcb9684bf8eb3e1fce","declaration":"export function deleteSessionUpstreamLink(sessionKey: string, agentId: string, options?: OpenClawStateDatabaseOptions): void;","entrypoint":"session-catalog","exportName":"deleteSessionUpstreamLink","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} {"closureHash":"194cb8ed04679bd319517a0e228373ac6da06736200610a11a4d274339c92f87","declaration":"export function importSessionCatalogHistory(params: { catalogId: string; threadId: string; read: (params: { cursor?: string; limit: number; }) => Promise; sessionId: string; sessionKey: string; agentId: string; cwd?: string; config: OpenClawConfig; }): Promise;","entrypoint":"session-catalog","exportName":"importSessionCatalogHistory","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} {"closureHash":"fb9a9c6a327c81eb3ccfb3550b0d6a3c4b62d7db43f5c248d41ff2abecf0bbc2","declaration":"export function isExternalUserText(probe: SessionUpstreamProbe, text: string | undefined): boolean;","entrypoint":"session-catalog","exportName":"isExternalUserText","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} -{"closureHash":"31fb6209d427f4ed44b9b1f7b65e7245c67bdcfdd65050106f0f4c54d38ad7a4","declaration":"export function listAdoptedSessionCatalogSessions(params: { config: OpenClawConfig; pluginId: string; runtime: PluginRuntime; sessionEntries?: SessionCatalogEntrySnapshot; sourceFromEntry: (entry: SessionCatalogEntry) => SessionCatalogAdoptedSource | undefined; }): Map;","entrypoint":"session-catalog","exportName":"listAdoptedSessionCatalogSessions","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} -{"closureHash":"35b393e6be657b65d68f37c1c7726777418db4faafff412a11bba91c44af488a","declaration":"export function listSessionCatalogEntries(params: { config: OpenClawConfig; runtime: PluginRuntime; sessionEntries?: SessionCatalogEntrySnapshot; }): SessionCatalogAgentEntry[];","entrypoint":"session-catalog","exportName":"listSessionCatalogEntries","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} +{"closureHash":"1988a5c5a4b562ce48446bfa75561c662f80390933c09a0ff3b7c1f0e0e35fa1","declaration":"export function listAdoptedSessionCatalogSessions(params: { config: OpenClawConfig; pluginId: string; runtime: PluginRuntime; sessionEntries?: SessionCatalogEntrySnapshot; sourceFromEntry: (entry: SessionCatalogEntry) => SessionCatalogAdoptedSource | undefined; }): Map;","entrypoint":"session-catalog","exportName":"listAdoptedSessionCatalogSessions","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} +{"closureHash":"81606f18d8675970e5cefba546a1dfffb9a53ce4e3020e906fb026746df816cb","declaration":"export function listSessionCatalogEntries(params: { config: OpenClawConfig; runtime: PluginRuntime; sessionEntries?: SessionCatalogEntrySnapshot; }): SessionCatalogAgentEntry[];","entrypoint":"session-catalog","exportName":"listSessionCatalogEntries","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} {"closureHash":"bcb164340d2d8ff229bd4bb7c68126cfc44cfb171a76f363ef7c78c1cdf16f37","declaration":"export function normalizeUserText(text: string): string;","entrypoint":"session-catalog","exportName":"normalizeUserText","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} {"closureHash":"7fdcd1b85ee1e56ea8faf0afba025d3a9be0a34a8b7fda9f5f9ead922729ecdc","declaration":"export function sessionCatalogAdoptedSessionKey(prefix: string, source: string): string;","entrypoint":"session-catalog","exportName":"sessionCatalogAdoptedSessionKey","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} {"closureHash":"1e09ce9731a5b5932ec01307e90f9ab93ec0a100616a2a6f3b6416b768e5170b","declaration":"export function sessionCatalogAdoptedSourceKey(hostId: string, threadId: string): string;","entrypoint":"session-catalog","exportName":"sessionCatalogAdoptedSourceKey","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"function","recordType":"export"} @@ -4049,9 +4115,9 @@ {"closureHash":"1b1c2b933616e206af0fa0f9d5f50435c041013b9699e19891c1117af32f2d42","declaration":"export type SessionCatalogDescriptor = { id: string; capabilities: { createSession?: { startTerminal?: boolean | undefined; model: string; } | undefined; openTerminal?: boolean | undefined; archive: boolean; continueSession: boolean; }; label: string;};","entrypoint":"session-catalog","exportName":"SessionCatalogDescriptor","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"4c50703512f3f7448ea7fe80c0938082c2c962a233848c2dfad992411ca99723","declaration":"export type SessionCatalogEntrySnapshot = SessionCatalogEntrySnapshot;","entrypoint":"session-catalog","exportName":"SessionCatalogEntrySnapshot","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"7761b7c4cccd9df93de1309fe9544bc17ed08fe87f1d833d621f335d52a78512","declaration":"export type SessionCatalogHost = { error?: { message: string; code: string; } | undefined; nextCursor?: string | undefined; nodeId?: string | undefined; sessions: { source?: string | undefined; name?: string | undefined; cwd?: string | undefined; sessionKey?: string | undefined; updatedAt?: number | undefined; createdActor?: { id?: string | undefined; label?: string | undefined; avatarUrl?: string | undefined; type: \"system\" | \"agent\" | \"human\"; } | undefined; createdAt?: number | undefined; modelProvider?: string | undefined; recencyAt?: number | undefined; cliVersion?: string | undefined; gitBranch?: string | undefined; customGroup?: string | undefined; pullRequest?: { state: \"open\" | \"draft\" | \"closed\" | \"merged\"; numbers: number[]; } | undefined; canOpenTerminal?: boolean | undefined; status: string; archived: boolean; threadId: string; canContinue: boolean; canArchive: boolean; }[]; kind: \"gateway\" | \"node\"; label: string; hostId: string; connected: boolean;};","entrypoint":"session-catalog","exportName":"SessionCatalogHost","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} -{"closureHash":"83641e5089f40055ca1f8ec0ce6e2d5879026106694e3d9ecdc806d660b06899","declaration":"export type SessionCatalogListProviderParams = SessionCatalogListProviderParams;","entrypoint":"session-catalog","exportName":"SessionCatalogListProviderParams","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} +{"closureHash":"582baad7ecdbdea2ac131ab8352c741e046b159a8e6d8e08ae95856d11f89478","declaration":"export type SessionCatalogListProviderParams = SessionCatalogListProviderParams;","entrypoint":"session-catalog","exportName":"SessionCatalogListProviderParams","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"1b8060a038d38a9dfcdb65119d42049deeb0fa9410a78298cd29bfd9639d2721","declaration":"export type SessionCatalogLocator = { threadId: string; catalogId: string; hostId: string;};","entrypoint":"session-catalog","exportName":"SessionCatalogLocator","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} -{"closureHash":"1dc27982cf3b5451c7f9b18d9c6416bca9a6b7af08cbbf0eb79f36adbbb00624","declaration":"export type SessionCatalogProvider = SessionCatalogProvider;","entrypoint":"session-catalog","exportName":"SessionCatalogProvider","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} +{"closureHash":"4dd4278241875f3607098638b50f9d7a8903b6bbd38ca7c3a1f56086bc3574b7","declaration":"export type SessionCatalogProvider = SessionCatalogProvider;","entrypoint":"session-catalog","exportName":"SessionCatalogProvider","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"031fa3a50e41f0c7d5672cfbfefe6b5f3a74d7b09824d3a0cf386ab08bdc2ce6","declaration":"export type SessionCatalogPullRequestSummary = { state: \"open\" | \"draft\" | \"closed\" | \"merged\"; numbers: number[];};","entrypoint":"session-catalog","exportName":"SessionCatalogPullRequestSummary","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"2fddff39ee355ab2f5efa463b1a2ff1fdce03da36515d6b4d21988ea28bcd45f","declaration":"export type SessionCatalogReadProviderParams = SessionCatalogReadProviderParams;","entrypoint":"session-catalog","exportName":"SessionCatalogReadProviderParams","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} {"closureHash":"c5e0c59d9f38e43b780d5d9cbf38ebd4299694e0f52221eee8c72e3a29d27e42","declaration":"export type SessionCatalogSession = { source?: string | undefined; name?: string | undefined; cwd?: string | undefined; sessionKey?: string | undefined; updatedAt?: number | undefined; createdActor?: { id?: string | undefined; label?: string | undefined; avatarUrl?: string | undefined; type: \"system\" | \"agent\" | \"human\"; } | undefined; createdAt?: number | undefined; modelProvider?: string | undefined; recencyAt?: number | undefined; cliVersion?: string | undefined; gitBranch?: string | undefined; customGroup?: string | undefined; pullRequest?: { state: \"open\" | \"draft\" | \"closed\" | \"merged\"; numbers: number[]; } | undefined; canOpenTerminal?: boolean | undefined; status: string; archived: boolean; threadId: string; canContinue: boolean; canArchive: boolean;};","entrypoint":"session-catalog","exportName":"SessionCatalogSession","importSpecifier":"openclaw/plugin-sdk/session-catalog","kind":"type","recordType":"export"} @@ -4639,16 +4705,16 @@ {"closureHash":"e365d7ad911453b5139ba700931b061e560cff80b50d4cbe5e9615b5d7e13a52","declaration":"export type ScopedExpiringIdCache = ScopedExpiringIdCache;","entrypoint":"text-runtime","exportName":"ScopedExpiringIdCache","importSpecifier":"openclaw/plugin-sdk/text-runtime","kind":"type","recordType":"export"} {"closureHash":"af5502c92594c2e9049a4b4994e17c00d3adee3f6d1e68edd818a539c74c8787","declaration":"export interface CodeRegion {\n start: number;\n end: number;\n}","entrypoint":"text-runtime","exportName":"CodeRegion","importSpecifier":"openclaw/plugin-sdk/text-runtime","kind":"interface","recordType":"export"} {"category":null,"entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","recordType":"module"} -{"closureHash":"296a332a70c3af6ed244dc40f665226c3fec4c68ee1e6f836ce62ff9504cbabc","declaration":"export function defineToolPlugin(definition: DefineToolPluginOptions): DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"defineToolPlugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} +{"closureHash":"490bd22ff071a126c5a97c9e0df661be490be69d85b92eb6c1b20491b7402e8b","declaration":"export function defineToolPlugin(definition: DefineToolPluginOptions): DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"defineToolPlugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} {"closureHash":"36ef907ce20f885b5f3068cbf0475dc442a68da9652579bb5bf8fb83ad34c38b","declaration":"export function getToolPluginMetadata(entry: unknown): ToolPluginMetadata | undefined;","entrypoint":"tool-plugin","exportName":"getToolPluginMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"function","recordType":"export"} {"closureHash":"bdc58154e36b2625fb3daccca3eab248d981077d04d747f0ad507cb2ff565198","declaration":"export const toolPluginMetadataSymbol: typeof toolPluginMetadataSymbol;","entrypoint":"tool-plugin","exportName":"toolPluginMetadataSymbol","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"const","recordType":"export"} -{"closureHash":"6c3a1859eedd030e8f47fd172946ab37de66367752388c459eac4c3261e929e2","declaration":"export type DefineToolPluginOptions = DefineToolPluginOptions;","entrypoint":"tool-plugin","exportName":"DefineToolPluginOptions","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"dbb9e65a5f0c657542d4f2ee7a9ecc287476375dc2100984c162c2c9c00447db","declaration":"export type DefinedToolPluginEntry = DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"DefinedToolPluginEntry","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"724409d65bf50cf7dcf9c9031c780f03824af1a7e82c7b7024844c57260f5c34","declaration":"export type ToolPluginExecutionContext = ToolPluginExecutionContext;","entrypoint":"tool-plugin","exportName":"ToolPluginExecutionContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"53cee5e8cd018ab1ae19f13012dcaed6e1837f7bd01098e63ceae66ce61237fa","declaration":"export type ToolPluginFactoryContext = ToolPluginFactoryContext;","entrypoint":"tool-plugin","exportName":"ToolPluginFactoryContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"041a48bbd824537af3458c931016026a328d39516ea0077198ace12988ab3a67","declaration":"export type DefineToolPluginOptions = DefineToolPluginOptions;","entrypoint":"tool-plugin","exportName":"DefineToolPluginOptions","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"682523157781bddc30d75747c1aa27883e627223fc59f813ff2c5f63460b25f1","declaration":"export type DefinedToolPluginEntry = DefinedToolPluginEntry;","entrypoint":"tool-plugin","exportName":"DefinedToolPluginEntry","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"afccffd717ef9dbc1ff199a8e14d14435dda1ed8053d42152574b7433e535382","declaration":"export type ToolPluginExecutionContext = ToolPluginExecutionContext;","entrypoint":"tool-plugin","exportName":"ToolPluginExecutionContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"d10d9555479e89485366f0a924d0cecbf897ad9ecf616ded56211dc0450b584b","declaration":"export type ToolPluginFactoryContext = ToolPluginFactoryContext;","entrypoint":"tool-plugin","exportName":"ToolPluginFactoryContext","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"closureHash":"f774bd092f51a31fbb34847213f9583234f585f66918d0af55e81bbbae40463b","declaration":"export type ToolPluginMetadata = ToolPluginMetadata;","entrypoint":"tool-plugin","exportName":"ToolPluginMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"closureHash":"414a89d0c80eaaf682dc25d306e7223c981c6fd25366adb973a106f4268a6a54","declaration":"export type ToolPluginStaticToolMetadata = ToolPluginStaticToolMetadata;","entrypoint":"tool-plugin","exportName":"ToolPluginStaticToolMetadata","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} -{"closureHash":"5cb770b85f7a568f9563c0d6d746ab8f10bb551e61c5ee07b28683ec50a28d00","declaration":"export type ToolPluginToolDefinition = ToolPluginToolDefinition;","entrypoint":"tool-plugin","exportName":"ToolPluginToolDefinition","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} +{"closureHash":"2250e3fd73eb98ecb4d731f13c8b16158321df14234ad1260131d287f101bb55","declaration":"export type ToolPluginToolDefinition = ToolPluginToolDefinition;","entrypoint":"tool-plugin","exportName":"ToolPluginToolDefinition","importSpecifier":"openclaw/plugin-sdk/tool-plugin","kind":"type","recordType":"export"} {"category":null,"entrypoint":"tool-results","importSpecifier":"openclaw/plugin-sdk/tool-results","recordType":"module"} {"closureHash":"c5b0951c3629834dff78f92317cf1421a6bbc0faf9307be1cabb915055665280","declaration":"export function jsonResult(payload: TDetails): AgentToolResult;","entrypoint":"tool-results","exportName":"jsonResult","importSpecifier":"openclaw/plugin-sdk/tool-results","kind":"function","recordType":"export"} {"closureHash":"b9aefc637a694c74e028e92006004bef18185ed569af48ac43d36b646b0af2f3","declaration":"export function textResult(text: string, details: TDetails): AgentToolResult;","entrypoint":"tool-results","exportName":"textResult","importSpecifier":"openclaw/plugin-sdk/tool-results","kind":"function","recordType":"export"} @@ -4682,9 +4748,9 @@ {"closureHash":"9f9174f1023a8a451232f5d97d1e922b7faa88b76b58cffbfbe246a1488e0ddd","declaration":"export function readJsonWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse; maxBytes?: number; timeoutMs?: number; profile?: WebhookBodyReadProfile; emptyObjectOnEmpty?: boolean; invalidJsonMessage?: string; }): Promise<{ ok: true; value: unknown; } | { ok: false; }>;","entrypoint":"webhook-ingress","exportName":"readJsonWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"1bbddd5d1c8297e315275db4d5e1c8748ff09c0be7c37b0cf456db4fc69f8909","declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"e8a1174cac83ce346a231fd25e82bb5f7618ffb57cdd9af6eaa208411f70646d","declaration":"export function readWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse; maxBytes?: number; timeoutMs?: number; profile?: WebhookBodyReadProfile; invalidBodyMessage?: string; }): Promise<{ ok: true; value: string; } | { ok: false; }>;","entrypoint":"webhook-ingress","exportName":"readWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} -{"closureHash":"137a9d7b92bee027864e6b3ed9dab727b82cec93e88d72099ea796f3cba761cf","declaration":"export function registerPluginHttpRoute(params: { path?: string | null; fallbackPath?: string | null; handler: PluginHttpRouteHandler; auth: PluginHttpRouteRegistration[\"auth\"]; match?: PluginHttpRouteRegistration[\"match\"]; gatewayRuntimeScopeSurface?: PluginHttpRouteRegistration[\"gatewayRuntimeScopeSurface\"]; replaceExisting?: boolean; reuseExistingSameOwner?: boolean; throwOnFailure?: boolean; pluginId?: string; source?: string; accountId?: string; log?: (message: string) => void; registry?: PluginRegistry; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} +{"closureHash":"6a64a3cae4fcbcbb8b6f8cfa74f92730415d2e8a19740b8b8d0945081e3706af","declaration":"export function registerPluginHttpRoute(params: { path?: string | null; fallbackPath?: string | null; handler: PluginHttpRouteHandler; auth: PluginHttpRouteRegistration[\"auth\"]; match?: PluginHttpRouteRegistration[\"match\"]; gatewayRuntimeScopeSurface?: PluginHttpRouteRegistration[\"gatewayRuntimeScopeSurface\"]; replaceExisting?: boolean; reuseExistingSameOwner?: boolean; throwOnFailure?: boolean; pluginId?: string; source?: string; accountId?: string; log?: (message: string) => void; registry?: PluginRegistry; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"05835f2f66f906f736b82b332a84a9714bc3a6b211890a62d8fc4dbf9258a7d4","declaration":"export function registerWebhookTarget(targetsByPath: Map, target: T, opts?: RegisterWebhookTargetOptions): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} -{"closureHash":"081f16d31a0ae6a890fa372cde3100a3544fe95d584bbaef196009b56a60d275","declaration":"export function registerWebhookTargetWithPluginRoute(params: { targetsByPath: Map; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: RegisterWebhookTargetOptions[\"onLastPathTargetRemoved\"]; }): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} +{"closureHash":"e01955489104aaa3f3650084dadc2002c82d4b13cda23ba1a20d1e9dd823d204","declaration":"export function registerWebhookTargetWithPluginRoute(params: { targetsByPath: Map; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: RegisterWebhookTargetOptions[\"onLastPathTargetRemoved\"]; }): RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"ec2f47e9bd7a075a3dd4302ac9e4c0bfe20630445db6735cf803f2d354275841","declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"5e1f3b468d56eb0f82104184077fdf4b6bd0c1444aa10b71a65fcaa2ec0298a2","declaration":"export function resolveRequestClientIp(req?: IncomingMessage, trustedProxies?: string[], allowRealIpFallback?: boolean): string | undefined;","entrypoint":"webhook-ingress","exportName":"resolveRequestClientIp","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} {"closureHash":"56c3e9868dfa6ee2a7a128eb02039a16b52696759adadbd3fe0a3bd7a6a07eeb","declaration":"export function resolveSingleWebhookTarget(targets: readonly T[], isMatch: (target: T) => boolean): WebhookTargetMatchResult;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export"} @@ -4702,7 +4768,7 @@ {"closureHash":"efb74e84339c15d6f607b38d1d477b0504d47d04ae78e77083a1893c756a0b54","declaration":"export const WEBHOOK_RATE_LIMIT_DEFAULTS: Readonly<{ windowMs: 60000; maxRequests: 120; maxTrackedKeys: 4096;}>;","entrypoint":"webhook-ingress","exportName":"WEBHOOK_RATE_LIMIT_DEFAULTS","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"const","recordType":"export"} {"closureHash":"13b28ec9acae43c3bdcd683b9831154f88118dee8142e42b7eebfd59f08c602c","declaration":"export type BoundedCounter = BoundedCounter;","entrypoint":"webhook-ingress","exportName":"BoundedCounter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"9e737ae8c17038ef7becbd2bf1b756cfeaed571e2ded368c0fe3a446ebd1f666","declaration":"export type FixedWindowRateLimiter = FixedWindowRateLimiter;","entrypoint":"webhook-ingress","exportName":"FixedWindowRateLimiter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} -{"closureHash":"9357b6c5e08176f9f4416d77f22dfce793961da76bf7b88ea1b3a756be25d924","declaration":"export type RegisterWebhookPluginRouteOptions = RegisterWebhookPluginRouteOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookPluginRouteOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} +{"closureHash":"84c1a1bc93ba8d51365cb2f9100fd65159236ba35a82a1ddc42880fb5338b476","declaration":"export type RegisterWebhookPluginRouteOptions = RegisterWebhookPluginRouteOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookPluginRouteOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"b3e98619854462acfac6538ac9a2d0cefb88704a0eac712563f0996b07364152","declaration":"export type RegisterWebhookTargetOptions = RegisterWebhookTargetOptions;","entrypoint":"webhook-ingress","exportName":"RegisterWebhookTargetOptions","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"964c2bfd8f268c411ee7b982c9de02c207f4bec402dd62c9f998a59752bb9d1f","declaration":"export type RegisteredWebhookTarget = RegisteredWebhookTarget;","entrypoint":"webhook-ingress","exportName":"RegisteredWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} {"closureHash":"aa552e5bdaefc9eb94d3b5a5cdf8c413fad555d9f452c6a2a6af5a3ce695c9d1","declaration":"export type WebhookAnomalyTracker = WebhookAnomalyTracker;","entrypoint":"webhook-ingress","exportName":"WebhookAnomalyTracker","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"type","recordType":"export"} diff --git a/docs/concepts/2026-07-29-memory-impl-plan.md b/docs/concepts/2026-07-29-memory-impl-plan.md index 1bf6fb75f66e..8835a0d87c50 100644 --- a/docs/concepts/2026-07-29-memory-impl-plan.md +++ b/docs/concepts/2026-07-29-memory-impl-plan.md @@ -1636,26 +1636,26 @@ Do not add direct user-to-user private-store grant APIs. Phase 3 is complete only when all of the following are demonstrated: -- [ ] Agent-shared and role writes require explicit publisher authority +- [x] Agent-shared and role writes require explicit publisher authority independent of read authority. -- [ ] Every projection names one audience, purpose, source revision, publisher, +- [x] Every projection names one audience, purpose, source revision, publisher, expiry/no-expiry decision, and revocation behavior. -- [ ] A projection exposes only its reviewed copy; the target cannot read or +- [x] A projection exposes only its reviewed copy; the target cannot read or mutate the private source. -- [ ] Projection refresh creates a new reviewed revision, while expiry or +- [x] Projection refresh creates a new reviewed revision, while expiry or revocation removes all new reads and enumerates affected prior exposures. -- [ ] Postbox remains `off` by default and supports review-required mode before +- [x] Postbox remains `off` by default and supports review-required mode before any labeled automatic-use mode. -- [ ] A source session can deposit only through a current server-issued source +- [x] A source session can deposit only through a current server-issued source message handle and receives no list/read/exact-get capability over the result. -- [ ] Postbox rate limits, provenance, review, purge, and no-auto-promotion +- [x] Postbox rate limits, provenance, review, purge, and no-auto-promotion behavior are persisted and tested. -- [ ] Owner/admin CLI, API, and UI operations authenticate and use authorized +- [x] Owner/admin CLI, API, and UI operations authenticate and use authorized plans. -- [ ] No tool, SDK, API, CLI, UI, plugin, or raw argument can create direct +- [x] No tool, SDK, API, CLI, UI, plugin, or raw argument can create direct private user-to-user store access. -- [ ] Projection, publisher, postbox, expiry, revocation, forged-handle, and +- [x] Projection, publisher, postbox, expiry, revocation, forged-handle, and prior-exposure tests pass. ### Phase 3 rollback diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index dd3a86cf08ce..1659887d08f9 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -378,6 +378,7 @@ Use `isLoopbackHost(host)` when a plugin must accept only the local machine. It | `plugin-sdk/memory-authorization` | Versioned serializable memory-authorization contracts and selected-capability declarations. This contract alone does not enable isolation, capability admission, or an authorization mode. | | `plugin-sdk/memory-authorization-conformance` | Pure backend conformance helpers for the memory-authorization contract. | | `plugin-sdk/memory-postbox-runtime` | Private-local runtime resolver and scoped binding keys for core-issued, turn-bound memory postbox source capabilities. | + | `plugin-sdk/memory-sharing-control-runtime` | Private-local Gateway-profile resolver for selected memory-plugin sharing controls. | | `plugin-sdk/memory-core-host-embedding-registry` | Private-local after July 2026; Lightweight memory embedding provider registry helpers | | `plugin-sdk/memory-core-host-engine-curated` | Private-local focused curated-memory annotation parsing for doctor and promotion paths | | `plugin-sdk/memory-core-host-engine-foundation` | Memory host foundation engine exports | diff --git a/extensions/codex/src/app-server/run-attempt-connection.ts b/extensions/codex/src/app-server/run-attempt-connection.ts index 514c097d3061..ef9ebef6d130 100644 --- a/extensions/codex/src/app-server/run-attempt-connection.ts +++ b/extensions/codex/src/app-server/run-attempt-connection.ts @@ -399,16 +399,14 @@ export async function prepareCodexAttemptConnection({ params, options }: CodexRu model: reviewerPolicyContext.model, }); policyAppServer = resolvePolicyAppServer(); - appServer = fenceCodexProjectDocumentsForMemoryIsolation({ - agentId: sessionAgentId, - appServer: resolveCodexAppServerForModelProvider({ - appServer: policyAppServer, - provider: reviewerPolicyContext.modelProvider, - model: reviewerPolicyContext.model, - config: params.config, - env: process.env, - agentDir, - }), + assertCodexMemoryIsolationSupported(sessionAgentId); + appServer = resolveCodexAppServerForModelProvider({ + appServer: policyAppServer, + provider: reviewerPolicyContext.modelProvider, + model: reviewerPolicyContext.model, + config: params.config, + env: process.env, + agentDir, }); approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted"; diff --git a/extensions/memory-core/index.test.ts b/extensions/memory-core/index.test.ts index 4b5d3b837f73..7fc0f6f3d065 100644 --- a/extensions/memory-core/index.test.ts +++ b/extensions/memory-core/index.test.ts @@ -1,6 +1,10 @@ // Memory Core tests cover index plugin behavior. import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; -import type { OpenClawPluginApi, OpenClawPluginCommandDefinition } from "openclaw/plugin-sdk/core"; +import type { + OpenClawPluginApi, + OpenClawPluginCommandDefinition, + OpenClawPluginToolContext, +} from "openclaw/plugin-sdk/core"; import type { MemoryPluginRuntime } from "openclaw/plugin-sdk/memory-core-host-runtime-core"; import type { MemoryPluginCapability } from "openclaw/plugin-sdk/memory-host-core"; import { @@ -202,7 +206,9 @@ describe("memory-core plugin runtime registration", () => { it("hides intent create, list, and cancel from non-owner turns", () => { let intentFactory: - | ((ctx: { config?: OpenClawConfig; senderIsOwner?: boolean }) => unknown) + | (( + ctx: Pick, + ) => unknown) | undefined; plugin.register( createTestPluginApi({ @@ -277,7 +283,7 @@ describe("memory-core plugin runtime registration", () => { expect(host.remember).toHaveBeenCalledWith({ content: "durable fact" }); }); - it("exposes postbox deposit only with the memory-core-scoped host binding", () => { + it("exposes postbox deposit only with the memory-core-scoped host binding and no readback", async () => { const factories = new Map unknown>(); plugin.register( createTestPluginApi({ @@ -292,16 +298,26 @@ describe("memory-core plugin runtime registration", () => { ); const postbox = factories.get("memory_postbox_deposit"); expect(postbox?.({ agentId: "main", sessionKey: "session" } as never)).toBeNull(); - expect( - postbox?.({ - agentId: "main", - sessionKey: "session", - toolBindings: { - [MEMORY_POSTBOX_TURN_CAPABILITY_BINDING]: "opaque-turn-capability", - [MEMORY_POSTBOX_RUN_ID_BINDING]: "run-1", - }, - } as never), - ).toMatchObject({ name: "memory_postbox_deposit" }); + const tool = postbox?.({ + agentId: "main", + sessionKey: "session", + sessionId: "session-1", + toolBindings: { + [MEMORY_POSTBOX_TURN_CAPABILITY_BINDING]: "opaque-turn-capability", + [MEMORY_POSTBOX_RUN_ID_BINDING]: "run-1", + }, + } as never) as + | { + name: string; + description: string; + execute: (id: string, params: unknown) => Promise<{ details?: unknown }>; + } + | null + | undefined; + expect(tool).toMatchObject({ name: "memory_postbox_deposit" }); + expect(tool?.description).toContain("cannot list, read, or identify postbox items"); + const result = await tool?.execute("postbox-call", { content: "one-way observation" }); + expect(result?.details).toEqual({ accepted: false }); }); it("keeps memory manager initialization demand-driven", () => { diff --git a/extensions/memory-core/index.ts b/extensions/memory-core/index.ts index e36ee0976b53..46000b6132ca 100644 --- a/extensions/memory-core/index.ts +++ b/extensions/memory-core/index.ts @@ -30,6 +30,7 @@ import { builtinScopedMemoryAuthorizedRuntime, builtinScopedMemoryVirtualView, } from "./src/memory/scoped-memory-runtime.js"; +import { registerScopedMemorySharingGatewayMethods } from "./src/memory/scoped-memory-sharing-gateway.js"; import { buildPromptSection } from "./src/prompt-section.js"; import { registerSessionBackfillGatewayMethods } from "./src/session-backfill-gateway.js"; @@ -224,7 +225,14 @@ function createMemoryPostboxDepositTool(ctx: OpenClawPluginToolContext): AnyAgen const runId = ctx.toolBindings?.[MEMORY_POSTBOX_RUN_ID_BINDING]; const agentId = ctx.agentId?.trim(); const sessionKey = ctx.sessionKey?.trim(); - if (typeof turnCapability !== "string" || typeof runId !== "string" || !agentId || !sessionKey) { + const sessionId = ctx.sessionId?.trim(); + if ( + typeof turnCapability !== "string" || + typeof runId !== "string" || + !agentId || + !sessionKey || + !sessionId + ) { return null; } return { @@ -248,7 +256,7 @@ function createMemoryPostboxDepositTool(ctx: OpenClawPluginToolContext): AnyAgen agentId, runId, sessionKey, - ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}), + sessionId, turnCapability, content, }), @@ -399,6 +407,7 @@ export default definePluginEntry({ const memoryRuntime = createLazyMemoryRuntime(host); registerShortTermPromotionDreaming(api); registerSessionBackfillGatewayMethods(api); + registerScopedMemorySharingGatewayMethods(api); api.registerMemoryCapability({ authorization: MEMORY_CORE_AUTHORIZATION_CAPABILITIES, // Phase 1B publishes the tested policy adapter; Phase 1C owns admitting it for reads. diff --git a/extensions/memory-core/src/cli.ts b/extensions/memory-core/src/cli.ts index 737914be9f89..f491d6cb145e 100644 --- a/extensions/memory-core/src/cli.ts +++ b/extensions/memory-core/src/cli.ts @@ -19,6 +19,7 @@ import type { MemorySearchCommandOptions, } from "./cli.types.js"; import { configureMemoryCoreDreamingState } from "./dreaming-state.js"; +import { registerMemorySharingCli } from "./memory-sharing-cli.js"; import type { MemoryCoreRuntimeHost } from "./memory/runtime-host.js"; import type { MemorySessionBackfillOptions } from "./session-backfill.js"; import { @@ -322,6 +323,8 @@ export function registerMemoryCli(program: Command, hostOptions?: MemoryCoreRunt await runMemorySessionBackfill(opts, hostOptions); }); + registerMemorySharingCli(memory); + memory.action(() => { memory.outputHelp(); process.exitCode = 0; diff --git a/extensions/memory-core/src/dreaming-startup-cleanup.test.ts b/extensions/memory-core/src/dreaming-startup-cleanup.test.ts index 5af3ea01feac..fe7fd661be47 100644 --- a/extensions/memory-core/src/dreaming-startup-cleanup.test.ts +++ b/extensions/memory-core/src/dreaming-startup-cleanup.test.ts @@ -318,6 +318,9 @@ describe("dreaming gateway restart cleanup", () => { }), ), ); + if (!cutOver || !legacy) { + throw new Error("fixture expected both configured agents"); + } isLegacyMemorySurfaceDisabledMock.mockImplementation((agentId) => agentId === "main"); const gateway = createGateway({ agentIds: ["main", "researcher"] }); diff --git a/extensions/memory-core/src/memory-sharing-cli.test.ts b/extensions/memory-core/src/memory-sharing-cli.test.ts new file mode 100644 index 000000000000..78aad31e7c43 --- /dev/null +++ b/extensions/memory-core/src/memory-sharing-cli.test.ts @@ -0,0 +1,158 @@ +import { Command } from "commander"; +import type { callGatewayFromCli as CallGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { registerMemorySharingCli } from "./memory-sharing-cli.js"; + +const callGatewayFromCli = vi.hoisted(() => + vi.fn(async () => ({ ok: true })), +); + +vi.mock("openclaw/plugin-sdk/gateway-runtime", () => ({ + addGatewayClientOptions(command: Command) { + return command + .option("--url ") + .option("--token ") + .option("--password ") + .option("--timeout ") + .option("--expect-final"); + }, + callGatewayFromCli, +})); + +function createProgram(): Command { + const program = new Command(); + program.name("test"); + registerMemorySharingCli(program.command("memory")); + return program; +} + +async function run(args: string[]) { + const program = createProgram(); + await program.parseAsync(["memory", "sharing", ...args], { from: "user" }); +} + +describe("memory sharing CLI", () => { + afterEach(() => { + callGatewayFromCli.mockClear(); + vi.restoreAllMocks(); + }); + + it("exposes the complete Gateway-only projection and postbox workflow", () => { + const memory = createProgram().commands[0]; + const sharing = memory?.commands.find((command) => command.name() === "sharing"); + expect(sharing?.commands.map((command) => command.name())).toEqual([ + "projection", + "postbox", + "status", + ]); + expect( + sharing?.commands + .find((command) => command.name() === "projection") + ?.commands.map((command) => command.name()), + ).toEqual(["target-register", "preview", "create", "refresh", "revoke", "impact"]); + expect( + sharing?.commands + .find((command) => command.name() === "postbox") + ?.commands.map((command) => command.name()), + ).toEqual(["mode", "inspect", "review", "purge"]); + }); + + it("sends an edited approval only through the profile-authenticated Gateway method", async () => { + const write = vi + .spyOn(process.stdout, "write") + .mockImplementation((() => true) as typeof process.stdout.write); + try { + await run([ + "postbox", + "review", + "--agent", + "main", + "--item-id", + "postbox-1", + "--decision", + "approve", + "--reviewed-content", + "owner-edited copy", + ]); + } finally { + write.mockRestore(); + } + + expect(callGatewayFromCli).toHaveBeenCalledWith( + "memory.sharing.postbox.review", + expect.objectContaining({ agent: "main" }), + { + agentId: "main", + itemId: "postbox-1", + decision: "approve", + reviewedContent: "owner-edited copy", + }, + { scopes: ["operator.admin"] }, + ); + const payload = callGatewayFromCli.mock.calls[0]?.[2] as Record; + expect(payload).not.toHaveProperty("principalId"); + expect(payload).not.toHaveProperty("storeId"); + expect(payload).not.toHaveProperty("reviewerPrincipalId"); + }); + + it("preserves the required audited no-expiry decision despite Commander no-prefix parsing", async () => { + const write = vi + .spyOn(process.stdout, "write") + .mockImplementation((() => true) as typeof process.stdout.write); + try { + await run([ + "projection", + "preview", + "--agent", + "main", + "--source-revision-id", + "revision-1", + "--target-kind", + "conversation", + "--target-id", + "conversation-team", + "--purpose", + "share", + "--preview", + "approved summary", + "--no-expiry-audit-reason", + "owner approved durable reference", + ]); + } finally { + write.mockRestore(); + } + + expect(callGatewayFromCli).toHaveBeenCalledWith( + "memory.sharing.projection.preview", + expect.objectContaining({ agent: "main" }), + { + agentId: "main", + sourceRevisionId: "revision-1", + targetKind: "conversation", + targetId: "conversation-team", + purpose: "share", + preview: "approved summary", + noExpiryAuditReason: "owner approved durable reference", + }, + { scopes: ["operator.admin"] }, + ); + }); + + it("rejects a raw private-user target before making any Gateway request", async () => { + await expect( + run([ + "projection", + "target-register", + "--agent", + "main", + "--target-kind", + "user", + "--target-id", + "principal-bob", + "--store-id", + "store-bob", + ]), + ).rejects.toThrow("--target-kind must be conversation, role, or agent-shared."); + expect(callGatewayFromCli).not.toHaveBeenCalled(); + }); +}); diff --git a/extensions/memory-core/src/memory-sharing-cli.ts b/extensions/memory-core/src/memory-sharing-cli.ts new file mode 100644 index 000000000000..8f256b6de12d --- /dev/null +++ b/extensions/memory-core/src/memory-sharing-cli.ts @@ -0,0 +1,252 @@ +import type { Command } from "commander"; +import { + addGatewayClientOptions, + callGatewayFromCli, + type GatewayRpcOpts, +} from "openclaw/plugin-sdk/gateway-runtime"; + +type SharingCliOptions = GatewayRpcOpts & { + agent: string; + itemId?: string; + projectionId?: string; + sourceRevisionId?: string; + storeId?: string; + targetKind?: string; + targetId?: string; + purpose?: string; + preview?: string; + content?: string; + reviewedContent?: string; + expiresAt?: string; + expiryAuditReason?: string; + mode?: string; + decision?: string; +}; + +const ADMIN_SCOPE = ["operator.admin"] as const; + +function requireOption(value: string | undefined, option: string): string { + const normalized = value?.trim(); + if (!normalized) { + throw new Error(`${option} is required.`); + } + return normalized; +} + +function requireProjectionTargetKind(value: string | undefined): "conversation" | "role" | "agent-shared" { + const kind = requireOption(value, "--target-kind"); + if (kind !== "conversation" && kind !== "role" && kind !== "agent-shared") { + throw new Error("--target-kind must be conversation, role, or agent-shared."); + } + return kind; +} + +function print(value: unknown): void { + process.stdout.write(`${JSON.stringify(value, null, 2)}\n`); +} + +function addGatewayOptions(command: Command): Command { + return addGatewayClientOptions(command) + .requiredOption("--agent ", "Agent id") + .option("--json", "Print JSON", false); +} + +function registerGatewayAction( + command: Command, + method: string, + params: (options: SharingCliOptions) => Record, +): void { + command.action(async (options: SharingCliOptions) => { + const result = await callGatewayFromCli( + method, + options, + { agentId: requireOption(options.agent, "--agent"), ...params(options) }, + { scopes: [...ADMIN_SCOPE] }, + ); + print(result); + }); +} + +function projectionParams(options: SharingCliOptions, options2: { content: boolean }) { + const expiresAt = options.expiresAt?.trim(); + // Commander reserves a `--no-*` option as a negation and removes the prefix + // from its attribute name, even when the option takes a required value. + const noExpiryAuditReason = options.expiryAuditReason?.trim(); + if ((expiresAt ? 1 : 0) + (noExpiryAuditReason ? 1 : 0) !== 1) { + throw new Error("provide exactly one of --expires-at or --no-expiry-audit-reason."); + } + return { + sourceRevisionId: requireOption(options.sourceRevisionId, "--source-revision-id"), + purpose: requireOption(options.purpose, "--purpose"), + preview: requireOption(options.preview, "--preview"), + ...(options2.content ? { content: requireOption(options.content, "--content") } : {}), + ...(expiresAt ? { expiresAt } : { noExpiryAuditReason }), + }; +} + +/** Gateway-only operator client for explicit sharing and quarantined postbox review. */ +export function registerMemorySharingCli(memory: Command): void { + const sharing = memory + .command("sharing") + .description("Review explicit memory projections and quarantined postbox items"); + const projection = sharing.command("projection").description("Manage reviewed projection copies"); + const postbox = sharing.command("postbox").description("Review quarantined postbox items"); + + registerGatewayAction( + addGatewayOptions(sharing.command("status").description("Show redacted sharing status")), + "memory.sharing.status", + () => ({}), + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("target-register") + .description("Register one existing non-private store as a reviewed projection target") + .requiredOption("--target-kind ", "conversation, role, or agent-shared") + .requiredOption("--target-id ", "Named target audience") + .requiredOption("--store-id ", "Existing store with the same non-private audience"), + ), + "memory.sharing.projection.target.register", + (options) => ({ + targetKind: requireProjectionTargetKind(options.targetKind), + targetId: requireOption(options.targetId, "--target-id"), + storeId: requireOption(options.storeId, "--store-id"), + }), + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("preview") + .description("Validate the source and target before creating a reviewed projection") + .requiredOption("--source-revision-id ", "Immutable source revision") + .requiredOption("--target-kind ", "conversation, role, or agent-shared") + .requiredOption("--target-id ", "Named target audience") + .requiredOption("--purpose ", "Human-readable purpose") + .requiredOption("--preview ", "Human-readable preview") + .option("--expires-at ", "Future ISO timestamp") + .option("--no-expiry-audit-reason ", "Audited reason for no expiry"), + ), + "memory.sharing.projection.preview", + (options) => { + const params = projectionParams(options, { content: false }); + return { + ...params, + targetKind: requireProjectionTargetKind(options.targetKind), + targetId: requireOption(options.targetId, "--target-id"), + }; + }, + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("create") + .description("Create one reviewed projection copy") + .requiredOption("--source-revision-id ", "Immutable source revision") + .requiredOption("--target-kind ", "conversation, role, or agent-shared") + .requiredOption("--target-id ", "Named target audience") + .requiredOption("--purpose ", "Human-readable purpose") + .requiredOption("--preview ", "Human-readable preview") + .requiredOption("--content ", "Reviewed copy content") + .option("--expires-at ", "Future ISO timestamp") + .option("--no-expiry-audit-reason ", "Audited reason for no expiry"), + ), + "memory.sharing.projection.create", + (options) => ({ + ...projectionParams(options, { content: true }), + targetKind: requireProjectionTargetKind(options.targetKind), + targetId: requireOption(options.targetId, "--target-id"), + }), + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("refresh") + .description("Create a new reviewed copy and revoke the replaced projection") + .requiredOption("--projection-id ", "Projection to replace") + .requiredOption("--source-revision-id ", "Immutable source revision") + .requiredOption("--purpose ", "Human-readable purpose") + .requiredOption("--preview ", "Human-readable preview") + .requiredOption("--content ", "Reviewed copy content") + .option("--expires-at ", "Future ISO timestamp") + .option("--no-expiry-audit-reason ", "Audited reason for no expiry"), + ), + "memory.sharing.projection.refresh", + (options) => ({ + ...projectionParams(options, { content: true }), + projectionId: requireOption(options.projectionId, "--projection-id"), + }), + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("revoke") + .description("Revoke a projection and report prior exposure ids") + .requiredOption("--projection-id ", "Projection id"), + ), + "memory.sharing.projection.revoke", + (options) => ({ projectionId: requireOption(options.projectionId, "--projection-id") }), + ); + registerGatewayAction( + addGatewayOptions( + projection + .command("impact") + .description("Show redacted prior exposure ids for one projection") + .requiredOption("--projection-id ", "Projection id"), + ), + "memory.sharing.projection.impact", + (options) => ({ projectionId: requireOption(options.projectionId, "--projection-id") }), + ); + + registerGatewayAction( + addGatewayOptions( + postbox + .command("mode") + .description("Set postbox mode") + .requiredOption("--mode ", "off or review-required"), + ), + "memory.sharing.postbox.mode.set", + (options) => ({ mode: requireOption(options.mode, "--mode") }), + ); + registerGatewayAction( + addGatewayOptions( + postbox + .command("inspect") + .description("Read one pending postbox item for authorized review") + .requiredOption("--item-id ", "Postbox item id"), + ), + "memory.sharing.postbox.inspect", + (options) => ({ itemId: requireOption(options.itemId, "--item-id") }), + ); + registerGatewayAction( + addGatewayOptions( + postbox + .command("review") + .description("Approve an original or edited reviewed copy, or reject one quarantined item") + .requiredOption("--item-id ", "Postbox item id") + .requiredOption("--decision ", "approve or reject") + .option("--reviewed-content ", "Edited content to promote only on approval"), + ), + "memory.sharing.postbox.review", + (options) => ({ + itemId: requireOption(options.itemId, "--item-id"), + decision: requireOption(options.decision, "--decision"), + ...(options.reviewedContent?.trim() + ? { reviewedContent: options.reviewedContent.trim() } + : {}), + }), + ); + registerGatewayAction( + addGatewayOptions( + postbox + .command("purge") + .description("Purge a quarantined or reviewed postbox item") + .requiredOption("--item-id ", "Postbox item id"), + ), + "memory.sharing.postbox.purge", + (options) => ({ itemId: requireOption(options.itemId, "--item-id") }), + ); + + sharing.action(() => sharing.outputHelp()); + projection.action(() => projection.outputHelp()); + postbox.action(() => postbox.outputHelp()); +} diff --git a/extensions/memory-core/src/memory/scoped-memory-db.ts b/extensions/memory-core/src/memory/scoped-memory-db.ts index bd9ab2189963..18ee9707e68b 100644 --- a/extensions/memory-core/src/memory/scoped-memory-db.ts +++ b/extensions/memory-core/src/memory/scoped-memory-db.ts @@ -315,6 +315,16 @@ export type MemoryPostboxItemRow = { purged_at: number | null; }; +/** Immutable link between a reviewed postbox item and the revision it admitted. */ +export type MemoryPostboxReviewedCopyRow = { + item_id: string; + agent_id: string; + resource_id: string; + revision_id: string; + reviewed_content_hash: string; + created_at: number; +}; + /** Local, idempotent audit delivery queue. Memory content is deliberately absent. */ export type MemoryAuditOutboxRow = { event_id: string; @@ -374,6 +384,7 @@ export type ScopedMemoryDatabase = { memory_postbox_source_handles: MemoryPostboxSourceHandleRow; memory_postbox_rate_limits: MemoryPostboxRateLimitRow; memory_postbox_items: MemoryPostboxItemRow; + memory_postbox_reviewed_copies: MemoryPostboxReviewedCopyRow; memory_audit_outbox: MemoryAuditOutboxRow; memory_migrations: MemoryMigrationRow; }; diff --git a/extensions/memory-core/src/memory/scoped-memory-resources.ts b/extensions/memory-core/src/memory/scoped-memory-resources.ts index 327842cc5071..4765fb788fdc 100644 --- a/extensions/memory-core/src/memory/scoped-memory-resources.ts +++ b/extensions/memory-core/src/memory/scoped-memory-resources.ts @@ -1,6 +1,7 @@ import { createHash, randomUUID } from "node:crypto"; import fs from "node:fs"; import path from "node:path"; +import type { DatabaseSync } from "node:sqlite"; import { normalizeAgentId } from "openclaw/plugin-sdk/routing"; import { executeSqliteQuerySync, diff --git a/extensions/memory-core/src/memory/scoped-memory-runtime.test.ts b/extensions/memory-core/src/memory/scoped-memory-runtime.test.ts index c742029f0596..d432a6f5a9b0 100644 --- a/extensions/memory-core/src/memory/scoped-memory-runtime.test.ts +++ b/extensions/memory-core/src/memory/scoped-memory-runtime.test.ts @@ -23,9 +23,12 @@ import { import { appendSqliteTranscriptMessage } from "../../../../src/config/sessions/session-accessor.sqlite-transcript-write.js"; import { readAuthorizedTranscriptDerivation } from "../../../../src/config/sessions/session-transcript-memory-policy.js"; import { withOwnedSessionTranscriptWrites } from "../../../../src/config/sessions/transcript-write-context.js"; +import { + registerAgentRunContext, + resetAgentRunRegistryForTest, +} from "../../../../src/infra/agent-run-registry.js"; import { admitMemoryAuthorizationReadRuntime } from "../../../../src/plugins/memory-authorization-runtime.js"; import { resetMemoryIsolationCutoverForTest } from "../../../../src/plugins/memory-cutover.js"; -import { registerAgentRunContext, resetAgentRunRegistryForTest } from "../../../../src/infra/agent-run-registry.js"; import { persistMemoryRunExposureBeforeContentInDatabase, readLatestDurableMemoryRunExposure, @@ -52,6 +55,7 @@ import { } from "../../../../src/state/openclaw-state-db.js"; import { ensureProfileForEmail } from "../../../../src/state/user-profiles.js"; import { MEMORY_CORE_AUTHORIZATION_CAPABILITIES } from "../authorization.js"; +import { createMemoryRuntime } from "../runtime-provider.js"; import { resolveScopedMemoryArtifactBase, withScopedMemoryDatabase } from "./scoped-memory-db.js"; import { builtinScopedMemoryConformanceAdapter } from "./scoped-memory-policy.js"; import { @@ -59,12 +63,16 @@ import { readBuiltinScopedMemoryRevisionSnapshot, setBuiltinScopedMemoryRevisionLifecycle, } from "./scoped-memory-resources.js"; -import { registerBuiltinMemoryProjectionTarget } from "./scoped-memory-sharing.js"; import { builtinScopedMemoryAuthorizedRuntime, builtinScopedMemoryVirtualView, resetBuiltinScopedMemoryAuthorizedRuntimeForTest, } from "./scoped-memory-runtime.js"; +import { + createBuiltinMemoryProjection, + inspectBuiltinMemoryProjectionImpact, + registerBuiltinMemoryProjectionTarget, +} from "./scoped-memory-sharing.js"; import { createBuiltinScopedMemoryStore } from "./scoped-memory-store.js"; const dispatchReplyFromConfig = vi.hoisted(() => vi.fn()); @@ -117,7 +125,7 @@ describe("builtin scoped authorized runtime", () => { authorization: MEMORY_CORE_AUTHORIZATION_CAPABILITIES, authorizationConformance: builtinScopedMemoryConformanceAdapter, virtualView: builtinScopedMemoryVirtualView, - runtime: builtinScopedMemoryAuthorizedRuntime, + runtime: { ...createMemoryRuntime(), ...builtinScopedMemoryAuthorizedRuntime }, }, }); setActivePluginRegistry(registry); @@ -128,6 +136,7 @@ describe("builtin scoped authorized runtime", () => { sessionId: string; chatType: "direct" | "group" | "channel"; primaryConversationId?: string; + primaryConversationTarget?: string; }) { const database = openOpenClawAgentDatabase({ agentId: "main" }); database.db @@ -145,8 +154,8 @@ describe("builtin scoped authorized runtime", () => { .run( params.primaryConversationId, params.chatType, - `${params.chatType}-peer`, - `${params.chatType}-target`, + `${params.primaryConversationId}-peer`, + params.primaryConversationTarget ?? `${params.primaryConversationId}-target`, ); } database.db @@ -216,12 +225,14 @@ describe("builtin scoped authorized runtime", () => { sessionKey: string; sessionId: string; conversationId: string; + conversationTarget?: string; }) { createSession({ sessionKey: params.sessionKey, sessionId: params.sessionId, chatType: "group", primaryConversationId: params.conversationId, + primaryConversationTarget: params.conversationTarget, }); const admitted = admitInboundMemorySessionContext({ context: { @@ -624,6 +635,28 @@ describe("builtin scoped authorized runtime", () => { }, }), ).rejects.toThrow("projection is unavailable"); + await expect( + builtinScopedMemoryAuthorizedRuntime.writeAuthorized({ + context: projectContext, + plan: projectPlan, + mutation: { + version: 1, + kind: "project", + mutationId: "project-private-target", + idempotencyKey: "project-private-target-request", + content: "PRIVATE_TARGET_MUST_NOT_CREATE_A_COPY", + contentType: "markdown", + sourceHandles: [sourceHandle], + target: { + // A JS caller can bypass the SDK union. The runtime remains the final boundary. + audience: { kind: "user", id: "principal-other" }, + purpose: "forged private share", + preview: "forged private share", + expiry: { kind: "no-expiry", auditReason: "forged" }, + }, + } as never, + }), + ).rejects.toThrow("memory projection target is unavailable"); }); it("authorizes compaction sources with derive rather than downgrading them to read", async () => { @@ -808,7 +841,11 @@ describe("builtin scoped authorized runtime", () => { }, async () => { await appendSqliteTranscriptMessage( - { agentId: context.agentId, sessionId: context.sessionId, sessionKey: context.sessionKey }, + { + agentId: context.agentId, + sessionId: context.sessionId, + sessionKey: context.sessionKey, + }, { message: { role: "assistant", @@ -1041,16 +1078,19 @@ describe("builtin scoped authorized runtime", () => { expect(activeDispatcher.sendFinalReply({ text: read.results[0]!.snippet })).toBe(true); return { queuedFinal: true, counts: { tool: 0, block: 0, final: 1 } }; }); - await dispatchInboundMessage({ - ctx: buildTestCtx({ + const directReplyContext = Object.assign( + buildTestCtx({ AgentId: "main", - SessionId: session.sessionId, SessionKey: session.sessionKey, Surface: "telegram", OriginatingChannel: "telegram", OriginatingTo: "alice", AccountId: "default", }), + { SessionId: session.sessionId }, + ); + await dispatchInboundMessage({ + ctx: directReplyContext, cfg: {} as never, dispatcher, replyOptions: { runId }, @@ -1069,16 +1109,19 @@ describe("builtin scoped authorized runtime", () => { ctx.OriginatingTo = "mallory"; return { queuedFinal: true, counts: { tool: 0, block: 0, final: 1 } }; }); - await dispatchInboundMessage({ - ctx: buildTestCtx({ + const reboundReplyContext = Object.assign( + buildTestCtx({ AgentId: "main", - SessionId: session.sessionId, SessionKey: session.sessionKey, Surface: "telegram", OriginatingChannel: "telegram", OriginatingTo: "alice", AccountId: "default", }), + { SessionId: session.sessionId }, + ); + await dispatchInboundMessage({ + ctx: reboundReplyContext, cfg: {} as never, dispatcher: reboundDispatcher, replyOptions: { runId }, @@ -1094,6 +1137,7 @@ describe("builtin scoped authorized runtime", () => { const conversationPrincipalId = createConversationSession({ ...session, conversationId: "telegram-group-1", + conversationTarget: "group-target", }); const channelStore = createBuiltinScopedMemoryStore({ agentId: "main", @@ -1114,23 +1158,35 @@ describe("builtin scoped authorized runtime", () => { authorityKind: "conversation", authorityOwnerId: conversationPrincipalId, defaultCapabilities: ["retrieve", "read"], + policyEntries: [ + { + kind: "publish", + effect: "allow", + principalId: "projection-publisher", + operation: "publish", + grantorPrincipalId: "projection-publisher", + reason: "named projection publisher", + }, + { + effect: "allow", + principalId: "projection-publisher", + operation: "policy-admin", + grantorPrincipalId: "projection-publisher", + reason: "named projection administrator", + }, + ], actor: { kind: "unattributed" }, reason: "explicitly addressed projection placement", }); - const alicePrincipal = ensureMemoryOperationalPrincipal({ - kind: "service", - stableRef: "alice-role-shaped-sender", - options: { agentId: "main" }, - }); const alicePrivate = createBuiltinScopedMemoryStore({ agentId: "main", scopeKind: "user", audienceKind: "user", - audienceId: alicePrincipal.principalId, + audienceId: "projection-publisher", authorityKind: "user", - authorityOwnerId: alicePrincipal.principalId, - defaultCapabilities: ["retrieve", "read"], - actor: { kind: "human", id: alicePrincipal.principalId }, + authorityOwnerId: "projection-publisher", + defaultCapabilities: ["retrieve", "read", "project"], + actor: { kind: "human", id: "projection-publisher" }, reason: "private placement", }); const ownerRole = createBuiltinScopedMemoryStore({ @@ -1146,17 +1202,11 @@ describe("builtin scoped authorized runtime", () => { }); for (const [store, logicalLocator, content, actor] of [ [channelStore, "channel.md", "GROUP_CHANNEL_ONLY", { kind: "unattributed" }], - [ - projectionStore, - "projection.md", - "GROUP_EXPLICITLY_ADDRESSED_PROJECTION", - { kind: "unattributed" }, - ], [ alicePrivate, "alice-private.md", "GROUP_DENIED_ALICE_PRIVATE_PATH_TITLE_SNIPPET_SCORE_COUNT_CITATION_CURSOR", - { kind: "human", id: alicePrincipal.principalId }, + { kind: "human", id: "projection-publisher" }, ], [ownerRole, "owner-role.md", "GROUP_DENIED_OWNER_ROLE_FROM_LATEST_ACTOR", { kind: "system" }], ] as const) { @@ -1168,6 +1218,30 @@ describe("builtin scoped authorized runtime", () => { actor, }); } + const privateRevision = createBuiltinScopedMemoryResource({ + agentId: "main", + store: alicePrivate, + logicalLocator: "projection-private.md", + content: "GROUP_DENIED_PRIVATE_PROJECTION_SOURCE", + actor: { kind: "human", id: "projection-publisher" }, + }); + registerBuiltinMemoryProjectionTarget({ + agentId: "main", + target: { kind: "conversation", id: conversationPrincipalId }, + store: projectionStore, + operatorPrincipalId: "projection-publisher", + }); + const projection = createBuiltinMemoryProjection({ + agentId: "main", + sourceRevisionId: privateRevision.revisionId, + target: { kind: "conversation", id: conversationPrincipalId }, + publisherPrincipalId: "projection-publisher", + reviewedByPrincipalId: "projection-publisher", + purpose: "approved group reference", + preview: "approved group reference", + content: "GROUP_EXPLICITLY_ADDRESSED_PROJECTION", + expiry: { kind: "no-expiry", auditReason: "fixture owner approval" }, + }); markCutOver(); installBuiltinSelectedRuntime(); @@ -1190,12 +1264,203 @@ describe("builtin scoped authorized runtime", () => { expect(serialized).not.toContain( "GROUP_DENIED_ALICE_PRIVATE_PATH_TITLE_SNIPPET_SCORE_COUNT_CITATION_CURSOR", ); + expect(serialized).not.toContain("GROUP_DENIED_PRIVATE_PROJECTION_SOURCE"); expect(serialized).not.toContain("GROUP_DENIED_OWNER_ROLE_FROM_LATEST_ACTOR"); + + const unrelatedSession = { + sessionKey: "agent:main:telegram:group:unrelated", + sessionId: "unrelated-group-session", + }; + createConversationSession({ + ...unrelatedSession, + conversationId: "telegram-group-unrelated", + conversationTarget: "unrelated-group-target", + }); + const unrelatedHost = createAuthorizedMemoryReadHost({ + agentId: "main", + ...unrelatedSession, + deliveryContext: { channel: "telegram", accountId: "default", to: "unrelated-group-target" }, + }); + if (!unrelatedHost) { + throw new Error("fixture failed to build an unrelated group memory host"); + } + const unrelatedResult = await unrelatedHost.search({ + query: "GROUP_EXPLICITLY_ADDRESSED_PROJECTION", + limit: 10, + }); + expect(JSON.stringify(unrelatedResult)).not.toContain("GROUP_EXPLICITLY_ADDRESSED_PROJECTION"); + + const writeHost = createAuthorizedMemoryWriteHost({ + agentId: "main", + ...session, + deliveryContext: { channel: "telegram", accountId: "default", to: "group-target" }, + }); + if (!writeHost) { + throw new Error("fixture failed to build a group memory write host"); + } + await expect(writeHost.remember({ content: "GROUP_FORGED_TARGET_MUTATION" })).resolves.toEqual({ + disabled: true, + unavailable: true, + error: "memory unavailable", + }); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId: "main", + storeIds: [alicePrivate.storeId], + revisionId: privateRevision.revisionId, + })?.content, + ).toBe("GROUP_DENIED_PRIVATE_PROJECTION_SOURCE"); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId: "main", + storeIds: [projectionStore.storeId], + revisionId: projection.copyRevisionId, + })?.content, + ).toBe("GROUP_EXPLICITLY_ADDRESSED_PROJECTION"); + }); + + it("durably expires a due projection before a fresh authorized group read", async () => { + vi.useFakeTimers(); + try { + const nowMs = Date.now(); + const session = { + sessionKey: "agent:main:telegram:group:expiring-projection", + sessionId: "expiring-projection-session", + }; + const conversationPrincipalId = createConversationSession({ + ...session, + conversationId: "telegram-group-expiring-projection", + conversationTarget: "group-target", + }); + const target = createBuiltinScopedMemoryStore({ + agentId: "main", + scopeKind: "conversation", + audienceKind: "conversation", + audienceId: conversationPrincipalId, + authorityKind: "conversation", + authorityOwnerId: conversationPrincipalId, + defaultCapabilities: ["retrieve", "read"], + policyEntries: [ + { + kind: "publish", + effect: "allow", + principalId: "projection-publisher", + operation: "publish", + grantorPrincipalId: "projection-publisher", + reason: "named projection publisher", + }, + { + effect: "allow", + principalId: "projection-publisher", + operation: "policy-admin", + grantorPrincipalId: "projection-publisher", + reason: "projection administrator", + }, + ], + actor: { kind: "unattributed" }, + reason: "expiring projection target", + }); + const source = createBuiltinScopedMemoryStore({ + agentId: "main", + scopeKind: "user", + audienceKind: "user", + audienceId: "projection-publisher", + authorityKind: "user", + authorityOwnerId: "projection-publisher", + defaultCapabilities: ["retrieve", "read", "project"], + actor: { kind: "human", id: "projection-publisher" }, + reason: "private projection source", + }); + const sourceRevision = createBuiltinScopedMemoryResource({ + agentId: "main", + store: source, + logicalLocator: "private-expiring-projection.md", + content: "PRIVATE_EXPIRING_PROJECTION_SOURCE", + actor: { kind: "human", id: "projection-publisher" }, + nowMs, + }); + registerBuiltinMemoryProjectionTarget({ + agentId: "main", + target: { kind: "conversation", id: conversationPrincipalId }, + store: target, + operatorPrincipalId: "projection-publisher", + nowMs, + }); + const projection = createBuiltinMemoryProjection({ + agentId: "main", + sourceRevisionId: sourceRevision.revisionId, + target: { kind: "conversation", id: conversationPrincipalId }, + publisherPrincipalId: "projection-publisher", + reviewedByPrincipalId: "projection-publisher", + purpose: "short-lived group reference", + preview: "short-lived group reference", + content: "EXPIRED_PROJECTION_MUST_NOT_READ", + expiry: { kind: "expires", expiresAt: nowMs + 1 }, + nowMs, + }); + const database = openOpenClawAgentDatabase({ agentId: "main" }); + database.db + .prepare( + `INSERT INTO memory_policy_sets + (policy_set_id, agent_id, memory_policy_revision, member_policy_set_ids_json, created_at) + VALUES ('runtime-expiry-policy-set', 'main', 'policy-revision', '[]', ?)`, + ) + .run(nowMs); + database.db + .prepare( + `INSERT INTO memory_run_exposures + (exposure_set_id, agent_id, run_id, context_fingerprint, plan_id, revision_number, + previous_exposure_set_id, source_policy_set_ids_json, effective_source_policy_set_id, + exposed_resource_revisions_json, exposure_receipt_ids_json, egress_receipt_ids_json, + delivery_audiences_json, delivery_revision, egress_registry_revision, created_at) + VALUES ('runtime-expiry-exposure', 'main', 'run-expiry', 'context', 'plan', 1, NULL, + '[]', 'runtime-expiry-policy-set', '[]', '[]', '[]', '[]', 'delivery', 'egress', ?)`, + ) + .run(nowMs); + database.db + .prepare( + `INSERT INTO memory_run_exposure_resources + (exposure_set_id, resource_revision_id, policy_set_id, created_at) + VALUES ('runtime-expiry-exposure', ?, 'runtime-expiry-policy-set', ?)`, + ) + .run(projection.copyRevisionId, nowMs); + markCutOver(); + installBuiltinSelectedRuntime(); + + vi.advanceTimersByTime(1); + const host = createAuthorizedMemoryReadHost({ + agentId: "main", + ...session, + deliveryContext: { channel: "telegram", accountId: "default", to: "group-target" }, + }); + if (!host) { + throw new Error("fixture failed to build an expiring group memory host"); + } + const result = await host.search({ query: "EXPIRED_PROJECTION_MUST_NOT_READ", limit: 10 }); + expect(JSON.stringify(result)).not.toContain("EXPIRED_PROJECTION_MUST_NOT_READ"); + expect( + database.db + .prepare("SELECT state FROM memory_projections WHERE projection_id = ?") + .get(projection.projectionId), + ).toEqual({ state: "expired" }); + expect( + inspectBuiltinMemoryProjectionImpact({ + agentId: "main", + projectionId: projection.projectionId, + operatorPrincipalId: "projection-publisher", + }), + ).toEqual({ + projectionId: projection.projectionId, + exposureSetIds: ["runtime-expiry-exposure"], + }); + } finally { + vi.useRealTimers(); + } }); it("selects the subject store itself and commits remember/delete through one durable lifecycle", async () => { const principalId = "writer"; - createBuiltinScopedMemoryStore({ + const subjectStore = createBuiltinScopedMemoryStore({ agentId: "main", scopeKind: "user", audienceKind: "user", @@ -1206,6 +1471,28 @@ describe("builtin scoped authorized runtime", () => { actor: { kind: "human", id: principalId }, reason: "authorized write fixture", }); + const roleStore = createBuiltinScopedMemoryStore({ + agentId: "main", + scopeKind: "role", + audienceKind: "role", + audienceId: "writers", + authorityKind: "role", + authorityOwnerId: "writers", + defaultCapabilities: ["append"], + actor: { kind: "system" }, + reason: "ordinary capture must not select a role store", + }); + const agentSharedStore = createBuiltinScopedMemoryStore({ + agentId: "main", + scopeKind: "agent-shared", + audienceKind: "agent-shared", + audienceId: "main", + authorityKind: "agent-shared", + authorityOwnerId: "main", + defaultCapabilities: ["append"], + actor: { kind: "system" }, + reason: "ordinary capture must not select an agent-shared store", + }); const appendContext = { ...createContext(principalId), operation: "append" as const, @@ -1253,6 +1540,16 @@ describe("builtin scoped authorized runtime", () => { .prepare("SELECT text FROM memory_scoped_chunks WHERE revision_id = ?") .all(handle.resourceRevision), ).toEqual([{ text: "durable write sentinel" }]); + expect( + database + .prepare("SELECT count(*) AS count FROM memory_resources WHERE store_id IN (?, ?)") + .get(roleStore.storeId, agentSharedStore.storeId), + ).toEqual({ count: 0 }); + expect( + database + .prepare("SELECT count(*) AS count FROM memory_resources WHERE store_id = ?") + .get(subjectStore.storeId), + ).toEqual({ count: 1 }); }); const audit = openOpenClawStateDatabase({ env: { OPENCLAW_STATE_DIR: stateDir } }); expect( @@ -1433,7 +1730,8 @@ describe("builtin scoped authorized runtime", () => { contentType: "markdown", }, }); - if (!written.resourceHandle) { + const writtenHandle = written.resourceHandle; + if (!writtenHandle) { throw new Error("fixture expected an authorized write handle"); } const unlinkError = Object.assign(new Error("unlink denied"), { code: "EACCES" }); @@ -1455,7 +1753,7 @@ describe("builtin scoped authorized runtime", () => { kind: "delete", mutationId: "tombstone-delete", idempotencyKey: "tombstone-delete-request", - target: written.resourceHandle, + target: writtenHandle, }, }), ).resolves.toMatchObject({ status: "committed" }); @@ -1466,12 +1764,12 @@ describe("builtin scoped authorized runtime", () => { expect( database .prepare("SELECT lifecycle_state FROM memory_resource_revisions WHERE revision_id = ?") - .get(written.resourceHandle.resourceRevision), + .get(writtenHandle.resourceRevision), ).toEqual({ lifecycle_state: "tombstoned" }); expect( database .prepare("SELECT * FROM memory_scoped_chunks WHERE revision_id = ?") - .all(written.resourceHandle.resourceRevision), + .all(writtenHandle.resourceRevision), ).toEqual([]); expect( database diff --git a/extensions/memory-core/src/memory/scoped-memory-runtime.ts b/extensions/memory-core/src/memory/scoped-memory-runtime.ts index b429049dd6b1..504a4c875fbe 100644 --- a/extensions/memory-core/src/memory/scoped-memory-runtime.ts +++ b/extensions/memory-core/src/memory/scoped-memory-runtime.ts @@ -45,7 +45,10 @@ import { readBuiltinScopedMemoryRevisionSnapshot, resolveBuiltinScopedMemoryArtifactPath, } from "./scoped-memory-resources.js"; -import { createBuiltinMemoryProjection } from "./scoped-memory-sharing.js"; +import { + createBuiltinMemoryProjection, + expireBuiltinMemoryProjections, +} from "./scoped-memory-sharing.js"; import { createScopedMemorySourcePolicySetId } from "./scoped-memory-store.js"; const PLAN_TTL_MS = 60_000; @@ -137,6 +140,9 @@ function listAuthorizedStores(params: { context: MemoryAccessContext; nowMs: number; }): readonly AuthorizedStore[] { + // Expiry owns a durable tombstone and prior-exposure impact. Run it before every new + // authorization snapshot so a clock-only filter cannot leave an expired projection active. + expireBuiltinMemoryProjections({ agentId: params.context.agentId, nowMs: params.nowMs }); return withScopedMemoryDatabase(params.context.agentId, (database) => { const rows = database .prepare( @@ -241,7 +247,7 @@ function createPlan(context: MemoryAccessContext): PlanState { ? (["retrieve", "read"] as const) : context.operation === "derive" ? (["retrieve", "read", "derive"] as const) - : ([context.operation] as const), + : ([context.operation] as const), ), audienceRevision: store.audienceRevision, }), @@ -971,7 +977,10 @@ function resolveTranscriptDerivationSource(params: { .where("policy_set_id", "=", source.sourcePolicySetId) .orderBy("policy_id"), ).rows; - if (requirements.length === 0 || requirements.some((requirement) => requirement.retention_state !== "retained")) { + if ( + requirements.length === 0 || + requirements.some((requirement) => requirement.retention_state !== "retained") + ) { throw new Error("authorized transcript derivation is unavailable"); } for (const requirement of requirements) { @@ -984,7 +993,11 @@ function resolveTranscriptDerivationSource(params: { "revision.revision_id", "policy.current_revision_id", ) - .select(["policy.lifecycle_state", "policy.revocation_epoch", "revision.lifecycle_state as revision_state"]) + .select([ + "policy.lifecycle_state", + "policy.revocation_epoch", + "revision.lifecycle_state as revision_state", + ]) .where("policy.policy_id", "=", requirement.policy_id) .where("policy.current_revision_id", "=", requirement.expected_revision_id) .where("policy.revocation_epoch", "=", requirement.expected_revocation_epoch) @@ -1014,7 +1027,9 @@ function resolveTranscriptDerivationSource(params: { ).rows; const nowMs = Date.now(); if ( - exposureSetIds.some((exposureSetId) => !exposures.some((row) => row.exposure_set_id === exposureSetId)) || + exposureSetIds.some( + (exposureSetId) => !exposures.some((row) => row.exposure_set_id === exposureSetId), + ) || exposures.some( (exposure) => exposure.lifecycle_state !== "active" || @@ -1931,16 +1946,14 @@ async function writeAuthorizedMutation(params: { ); executeSqliteQuerySync( database, - db - .insertInto("memory_revision_policy_requirements") - .values({ - revision_id: revisionId, - policy_id: store.policyId, - expected_revision_id: store.policyRevisionId, - expected_revocation_epoch: store.policyRevocationEpoch, - requirement_kind: "output-policy", - created_at: nowMs, - }), + db.insertInto("memory_revision_policy_requirements").values({ + revision_id: revisionId, + policy_id: store.policyId, + expected_revision_id: store.policyRevisionId, + expected_revocation_epoch: store.policyRevocationEpoch, + requirement_kind: "output-policy", + created_at: nowMs, + }), ); for (const source of derivationSources) { for (const requirement of source.policyRequirements) { @@ -1956,7 +1969,9 @@ async function writeAuthorizedMutation(params: { requirement_kind: "source-policy", created_at: nowMs, }) - .onConflict((conflict) => conflict.columns(["revision_id", "policy_id"]).doNothing()), + .onConflict((conflict) => + conflict.columns(["revision_id", "policy_id"]).doNothing(), + ), ); } executeSqliteQuerySync( @@ -1984,7 +1999,9 @@ async function writeAuthorizedMutation(params: { requirement_kind: "source-policy", created_at: nowMs, }) - .onConflict((conflict) => conflict.columns(["revision_id", "policy_id"]).doNothing()), + .onConflict((conflict) => + conflict.columns(["revision_id", "policy_id"]).doNothing(), + ), ); } for (const sourceRevisionId of transcriptDerivationSource.sourceRevisionIds) { @@ -2006,9 +2023,7 @@ async function writeAuthorizedMutation(params: { parent_kind: "transcript-policy-set", parent_id: transcriptDerivationSource.sourcePolicySetId, relation_kind: - transcriptDerivationPurpose === "compaction" - ? "compacted-from" - : "flushed-from", + transcriptDerivationPurpose === "compaction" ? "compacted-from" : "flushed-from", created_at: nowMs, }), ); @@ -2355,9 +2370,7 @@ async function stageSealedCompaction( requirement_kind: "source-policy", created_at: nowMs, }) - .onConflict((conflict) => - conflict.columns(["revision_id", "policy_id"]).doNothing(), - ), + .onConflict((conflict) => conflict.columns(["revision_id", "policy_id"]).doNothing()), ); } const lineage = [ diff --git a/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.test.ts b/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.test.ts new file mode 100644 index 000000000000..0bcfbde5998f --- /dev/null +++ b/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.test.ts @@ -0,0 +1,438 @@ +import type { GatewayRequestHandlerOptions } from "openclaw/plugin-sdk/gateway-runtime"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { createEmptyPluginRegistry } from "../../../../src/plugins/registry-empty.js"; +import { + resetPluginRuntimeStateForTest, + setActivePluginRegistry, +} from "../../../../src/plugins/runtime.js"; +import { + createGatewayMethodRegistry, + createPluginGatewayMethodDescriptor, +} from "../../../../src/gateway/methods/registry.js"; +import { handleGatewayRequest } from "../../../../src/gateway/server-methods.js"; +import { registerScopedMemorySharingGatewayMethods } from "./scoped-memory-sharing-gateway.js"; + +const resolveMemoryPrincipalForUserProfile = vi.hoisted(() => vi.fn()); +const inspectBuiltinMemorySharingStatus = vi.hoisted(() => vi.fn()); +const registerBuiltinMemoryProjectionTargetStore = vi.hoisted(() => vi.fn()); +const setBuiltinMemoryPostboxModeForPrincipal = vi.hoisted(() => vi.fn()); +const previewBuiltinMemoryProjection = vi.hoisted(() => vi.fn()); +const createBuiltinMemoryProjection = vi.hoisted(() => vi.fn()); +const refreshBuiltinMemoryProjection = vi.hoisted(() => vi.fn()); +const revokeBuiltinMemoryProjection = vi.hoisted(() => vi.fn()); +const inspectBuiltinMemoryProjectionImpact = vi.hoisted(() => vi.fn()); +const inspectBuiltinMemoryPostboxItem = vi.hoisted(() => vi.fn()); +const reviewBuiltinMemoryPostboxItem = vi.hoisted(() => vi.fn()); + +vi.mock("openclaw/plugin-sdk/memory-sharing-control-runtime", () => ({ + resolveMemoryPrincipalForUserProfile, +})); + +vi.mock("./scoped-memory-sharing.js", () => ({ + inspectBuiltinMemorySharingStatus, + registerBuiltinMemoryProjectionTargetStore, + setBuiltinMemoryPostboxModeForPrincipal, + previewBuiltinMemoryProjection, + createBuiltinMemoryProjection, + refreshBuiltinMemoryProjection, + revokeBuiltinMemoryProjection, + inspectBuiltinMemoryProjectionImpact, + inspectBuiltinMemoryPostboxItem, + reviewBuiltinMemoryPostboxItem, +})); + +type RegisteredMethod = { + handler: (options: GatewayRequestHandlerOptions) => Promise; + scope: NonNullable[2]>["scope"]; +}; + +function createHarness() { + const methods = new Map(); + const api = { + registerGatewayMethod( + method: string, + handler: RegisteredMethod["handler"], + options?: NonNullable[2]>, + ) { + methods.set(method, { handler, scope: options?.scope }); + }, + } as unknown as OpenClawPluginApi; + registerScopedMemorySharingGatewayMethods(api); + return methods; +} + +async function invoke(params: { method: RegisteredMethod; request: unknown; profileId?: string }) { + const respond = vi.fn(); + await params.method.handler({ + params: params.request, + client: params.profileId + ? ({ authenticatedUserProfile: { profileId: params.profileId } } as never) + : null, + respond, + } as unknown as GatewayRequestHandlerOptions); + return respond; +} + +describe("memory sharing gateway methods", () => { + beforeEach(() => { + vi.clearAllMocks(); + resolveMemoryPrincipalForUserProfile.mockReturnValue({ + principalId: "principal-alice", + kind: "user", + revision: "principal-revision", + }); + }); + + afterEach(() => { + resetPluginRuntimeStateForTest(); + }); + + it("registers read-only status and admin mode controls", () => { + const methods = createHarness(); + expect([...methods.entries()].map(([name, value]) => [name, value.scope])).toEqual([ + ["memory.sharing.status", "operator.read"], + ["memory.sharing.projection.target.register", "operator.admin"], + ["memory.sharing.projection.preview", "operator.admin"], + ["memory.sharing.projection.create", "operator.admin"], + ["memory.sharing.projection.refresh", "operator.admin"], + ["memory.sharing.projection.revoke", "operator.admin"], + ["memory.sharing.projection.impact", "operator.read"], + ["memory.sharing.postbox.mode.set", "operator.admin"], + ["memory.sharing.postbox.inspect", "operator.read"], + ["memory.sharing.postbox.review", "operator.admin"], + ["memory.sharing.postbox.purge", "operator.admin"], + ]); + }); + + it("stops an operator.read client at Gateway dispatch before an admin mutation handler", async () => { + const methods = createHarness(); + const registered = methods.get("memory.sharing.projection.create")!; + const handler = vi.fn(registered.handler); + const pluginRegistry = createEmptyPluginRegistry(); + pluginRegistry.gatewayHandlers["memory.sharing.projection.create"] = handler; + pluginRegistry.gatewayMethodDescriptors.push( + createPluginGatewayMethodDescriptor({ + pluginId: "memory-core", + name: "memory.sharing.projection.create", + handler, + scope: registered.scope!, + }), + ); + setActivePluginRegistry(pluginRegistry); + const respond = vi.fn(); + + await handleGatewayRequest({ + req: { + type: "req", + id: "memory-sharing-read-denied", + method: "memory.sharing.projection.create", + params: {}, + }, + respond, + client: { + connId: "operator-read", + connect: { + role: "operator", + scopes: ["operator.read"], + client: { id: "test", version: "test", platform: "linux", mode: "cli" }, + minProtocol: 1, + maxProtocol: 1, + }, + }, + isWebchatConnect: () => false, + context: { logGateway: { warn: vi.fn() } } as never, + methodRegistry: createGatewayMethodRegistry([]), + }); + + expect(handler).not.toHaveBeenCalled(); + expect(respond).toHaveBeenCalledWith(false, undefined, { + code: "FORBIDDEN", + message: "missing scope: operator.admin", + details: { + code: "MISSING_SCOPE", + missingScope: "operator.admin", + requiredScopes: ["operator.admin"], + }, + }); + }); + + it("registers only a profile-authorized non-private projection target store", async () => { + const methods = createHarness(); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.target.register")!, + request: { + agentId: "main", + targetKind: "conversation", + targetId: "conversation-team", + storeId: "store-team", + }, + profileId: "profile-alice", + }); + + expect(registerBuiltinMemoryProjectionTargetStore).toHaveBeenCalledWith({ + agentId: "main", + target: { kind: "conversation", id: "conversation-team" }, + storeId: "store-team", + operatorPrincipalId: "principal-alice", + }); + expect(respond).toHaveBeenCalledWith(true, { + target: { kind: "conversation", id: "conversation-team" }, + }); + }); + + it("derives the status principal from the authenticated profile and rejects caller principal input", async () => { + const methods = createHarness(); + inspectBuiltinMemorySharingStatus.mockReturnValue({ + postboxMode: "off", + projections: [], + postboxItems: [], + }); + const status = methods.get("memory.sharing.status")!; + const valid = await invoke({ + method: status, + request: { agentId: "main" }, + profileId: "profile-alice", + }); + const injectedPrincipal = await invoke({ + method: status, + request: { agentId: "main", principalId: "principal-bob" }, + profileId: "profile-alice", + }); + + expect(resolveMemoryPrincipalForUserProfile).toHaveBeenCalledWith({ + userProfileId: "profile-alice", + }); + expect(inspectBuiltinMemorySharingStatus).toHaveBeenCalledWith({ + agentId: "main", + operatorPrincipalId: "principal-alice", + }); + expect(valid).toHaveBeenCalledWith(true, { + postboxMode: "off", + projections: [], + postboxItems: [], + }); + expect(injectedPrincipal.mock.calls[0]?.[2]).toMatchObject({ + code: "INVALID_REQUEST", + message: "unexpected parameter: principalId", + }); + }); + + it("requires an authenticated profile and derives postbox ownership without a store argument", async () => { + const methods = createHarness(); + const mode = methods.get("memory.sharing.postbox.mode.set")!; + const unauthenticated = await invoke({ + method: mode, + request: { agentId: "main", mode: "review-required" }, + }); + const valid = await invoke({ + method: mode, + request: { agentId: "main", mode: "review-required" }, + profileId: "profile-alice", + }); + + expect(unauthenticated.mock.calls[0]?.[2]).toMatchObject({ + code: "FORBIDDEN", + message: "memory sharing requires an authenticated Gateway profile.", + }); + expect(setBuiltinMemoryPostboxModeForPrincipal).toHaveBeenCalledWith({ + agentId: "main", + principalId: "principal-alice", + mode: "review-required", + }); + expect(valid).toHaveBeenCalledWith(true, { mode: "review-required" }); + }); + + it("derives publisher and reviewer from the Gateway profile for a projection", async () => { + const methods = createHarness(); + createBuiltinMemoryProjection.mockReturnValue({ projectionId: "projection-1" }); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.create")!, + request: { + agentId: "main", + sourceRevisionId: "revision-private", + targetKind: "conversation", + targetId: "conversation-team", + purpose: "share contact detail", + preview: "approved contact detail", + content: "reviewed copy", + expiresAt: "2030-01-01T00:00:00.000Z", + }, + profileId: "profile-alice", + }); + + expect(createBuiltinMemoryProjection).toHaveBeenCalledWith({ + agentId: "main", + sourceRevisionId: "revision-private", + target: { kind: "conversation", id: "conversation-team" }, + purpose: "share contact detail", + preview: "approved contact detail", + content: "reviewed copy", + expiry: { kind: "expires", expiresAt: Date.parse("2030-01-01T00:00:00.000Z") }, + publisherPrincipalId: "principal-alice", + reviewedByPrincipalId: "principal-alice", + }); + expect(respond).toHaveBeenCalledWith(true, { projectionId: "projection-1" }); + }); + + it("rejects a raw private-user target before projection creation", async () => { + const methods = createHarness(); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.create")!, + request: { + agentId: "main", + sourceRevisionId: "revision-private", + targetKind: "user", + targetId: "principal-bob", + purpose: "share contact detail", + preview: "approved contact detail", + content: "reviewed copy", + expiresAt: "2030-01-01T00:00:00.000Z", + }, + profileId: "profile-alice", + }); + + expect(createBuiltinMemoryProjection).not.toHaveBeenCalled(); + expect(respond.mock.calls[0]?.[2]).toMatchObject({ + code: "INVALID_REQUEST", + message: "targetKind must be conversation, role, or agent-shared.", + }); + }); + + it("previews with only the profile-derived publisher and no private source body", async () => { + const methods = createHarness(); + previewBuiltinMemoryProjection.mockReturnValue({ preview: "approved contact detail" }); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.preview")!, + request: { + agentId: "main", + sourceRevisionId: "revision-private", + targetKind: "conversation", + targetId: "conversation-team", + purpose: "share contact detail", + preview: "approved contact detail", + noExpiryAuditReason: "owner approved durable reference", + }, + profileId: "profile-alice", + }); + + expect(previewBuiltinMemoryProjection).toHaveBeenCalledWith({ + agentId: "main", + sourceRevisionId: "revision-private", + target: { kind: "conversation", id: "conversation-team" }, + purpose: "share contact detail", + preview: "approved contact detail", + expiry: { kind: "no-expiry", auditReason: "owner approved durable reference" }, + publisherPrincipalId: "principal-alice", + }); + expect(respond).toHaveBeenCalledWith(true, { preview: "approved contact detail" }); + }); + + it("reads projection impact through the profile-derived operator", async () => { + const methods = createHarness(); + inspectBuiltinMemoryProjectionImpact.mockReturnValue({ + projectionId: "projection-1", + exposureSetIds: ["exposure-1"], + }); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.impact")!, + request: { agentId: "main", projectionId: "projection-1" }, + profileId: "profile-alice", + }); + + expect(inspectBuiltinMemoryProjectionImpact).toHaveBeenCalledWith({ + agentId: "main", + projectionId: "projection-1", + operatorPrincipalId: "principal-alice", + }); + expect(respond).toHaveBeenCalledWith(true, { + projectionId: "projection-1", + exposureSetIds: ["exposure-1"], + }); + }); + + it("sends edited review content only to the profile-derived target owner", async () => { + const methods = createHarness(); + const respond = await invoke({ + method: methods.get("memory.sharing.postbox.review")!, + request: { + agentId: "main", + itemId: "postbox-1", + decision: "approve", + reviewedContent: "owner-edited copy", + }, + profileId: "profile-alice", + }); + + expect(reviewBuiltinMemoryPostboxItem).toHaveBeenCalledWith({ + agentId: "main", + itemId: "postbox-1", + decision: "approve", + reviewedContent: "owner-edited copy", + operatorPrincipalId: "principal-alice", + }); + expect(respond).toHaveBeenCalledWith(true, { itemId: "postbox-1", decision: "approve" }); + }); + + it("rejects edited content with a rejection decision", async () => { + const methods = createHarness(); + const respond = await invoke({ + method: methods.get("memory.sharing.postbox.review")!, + request: { + agentId: "main", + itemId: "postbox-1", + decision: "reject", + reviewedContent: "must not be promoted", + }, + profileId: "profile-alice", + }); + + expect(reviewBuiltinMemoryPostboxItem).not.toHaveBeenCalled(); + expect(respond.mock.calls[0]?.[2]).toMatchObject({ + code: "INVALID_REQUEST", + message: "reviewedContent is available only for approve.", + }); + }); + + it("rejects caller-supplied publisher and reviewer fields before projection creation", async () => { + const methods = createHarness(); + const respond = await invoke({ + method: methods.get("memory.sharing.projection.create")!, + request: { + agentId: "main", + sourceRevisionId: "revision-private", + targetKind: "conversation", + targetId: "conversation-team", + purpose: "share contact detail", + preview: "approved contact detail", + content: "reviewed copy", + expiresAt: "2030-01-01T00:00:00.000Z", + publisherPrincipalId: "principal-mallory", + }, + profileId: "profile-alice", + }); + + expect(createBuiltinMemoryProjection).not.toHaveBeenCalled(); + expect(respond.mock.calls[0]?.[2]).toMatchObject({ + code: "INVALID_REQUEST", + message: "unexpected parameter: publisherPrincipalId", + }); + }); + + it("denies a profile that has no current memory principal", async () => { + const methods = createHarness(); + resolveMemoryPrincipalForUserProfile.mockReturnValue(undefined); + + const respond = await invoke({ + method: methods.get("memory.sharing.status")!, + request: { agentId: "main" }, + profileId: "profile-without-memory", + }); + + expect(inspectBuiltinMemorySharingStatus).not.toHaveBeenCalled(); + expect(respond.mock.calls[0]?.[2]).toMatchObject({ + code: "FORBIDDEN", + message: "memory sharing is unavailable for this profile.", + }); + }); +}); diff --git a/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.ts b/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.ts new file mode 100644 index 000000000000..be4b926e3472 --- /dev/null +++ b/extensions/memory-core/src/memory/scoped-memory-sharing-gateway.ts @@ -0,0 +1,542 @@ +import { + ErrorCodes, + errorShape, + type GatewayRequestHandlerOptions, +} from "openclaw/plugin-sdk/gateway-runtime"; +import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; +import { resolveMemoryPrincipalForUserProfile } from "openclaw/plugin-sdk/memory-sharing-control-runtime"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; +import { normalizeAgentId } from "openclaw/plugin-sdk/routing"; + +const MEMORY_SHARING_GATEWAY_METHODS = { + status: "memory.sharing.status", + projectionTargetRegister: "memory.sharing.projection.target.register", + projectionPreview: "memory.sharing.projection.preview", + projectionCreate: "memory.sharing.projection.create", + projectionRefresh: "memory.sharing.projection.refresh", + projectionRevoke: "memory.sharing.projection.revoke", + projectionImpact: "memory.sharing.projection.impact", + postboxMode: "memory.sharing.postbox.mode.set", + postboxInspect: "memory.sharing.postbox.inspect", + postboxReview: "memory.sharing.postbox.review", + postboxPurge: "memory.sharing.postbox.purge", +} as const; + +const loadSharing = createLazyRuntimeModule(() => import("./scoped-memory-sharing.js")); + +class InvalidMemorySharingRequestError extends Error {} +class ForbiddenMemorySharingRequestError extends Error {} + +function paramsRecord(value: unknown): Record { + if (!value || typeof value !== "object" || Array.isArray(value)) { + throw new InvalidMemorySharingRequestError("params must be an object."); + } + return value as Record; +} + +function assertOnlyKeys(params: Record, keys: readonly string[]) { + const allowed = new Set(keys); + const unexpected = Object.keys(params).find((key) => !allowed.has(key)); + if (unexpected) { + throw new InvalidMemorySharingRequestError(`unexpected parameter: ${unexpected}`); + } +} + +function readRequiredString(params: Record, key: string): string { + const value = params[key]; + if (typeof value !== "string" || !value.trim()) { + throw new InvalidMemorySharingRequestError(`${key} must be a non-empty string.`); + } + return value.trim(); +} + +function readAgentId(params: Record): string { + try { + return normalizeAgentId(readRequiredString(params, "agentId")); + } catch (error) { + throw new InvalidMemorySharingRequestError( + error instanceof Error ? error.message : "agentId is invalid.", + ); + } +} + +function readProjectionTarget(params: Record, agentId: string) { + const kind = readRequiredString(params, "targetKind"); + if (kind !== "conversation" && kind !== "role" && kind !== "agent-shared") { + throw new InvalidMemorySharingRequestError( + "targetKind must be conversation, role, or agent-shared.", + ); + } + const id = readRequiredString(params, "targetId"); + if (id === "*" || (kind === "agent-shared" && id !== agentId)) { + throw new InvalidMemorySharingRequestError("projection target is unavailable."); + } + return { kind, id } as const; +} + +function readExpiry(params: Record) { + const expiresAt = params.expiresAt; + const noExpiryAuditReason = params.noExpiryAuditReason; + if (typeof expiresAt === "string" && expiresAt.trim() && noExpiryAuditReason === undefined) { + const parsed = Date.parse(expiresAt); + if (!Number.isSafeInteger(parsed) || parsed <= Date.now()) { + throw new InvalidMemorySharingRequestError("expiresAt must be a future ISO timestamp."); + } + return { kind: "expires" as const, expiresAt: parsed }; + } + if ( + expiresAt === undefined && + typeof noExpiryAuditReason === "string" && + noExpiryAuditReason.trim() + ) { + return { kind: "no-expiry" as const, auditReason: noExpiryAuditReason.trim() }; + } + throw new InvalidMemorySharingRequestError( + "provide either a future expiresAt or a noExpiryAuditReason.", + ); +} + +type ProjectionDraftRequest = Readonly<{ + agentId: string; + sourceRevisionId: string; + purpose: string; + preview: string; + expiry: ReturnType; +}>; + +type ProjectionCreateRequest = ProjectionDraftRequest & + Readonly<{ target: ReturnType; content: string }>; +type ProjectionPreviewRequest = ProjectionDraftRequest & + Readonly<{ target: ReturnType }>; +type ProjectionRefreshRequest = ProjectionDraftRequest & + Readonly<{ projectionId: string; content: string }>; + +function readProjectionDraftRequest(value: unknown) { + const request = paramsRecord(value); + return { + agentId: readAgentId(request), + sourceRevisionId: readRequiredString(request, "sourceRevisionId"), + purpose: readRequiredString(request, "purpose"), + preview: readRequiredString(request, "preview"), + expiry: readExpiry(request), + } satisfies ProjectionDraftRequest; +} + +function readProjectionPreviewRequest(value: unknown): ProjectionPreviewRequest { + const request = paramsRecord(value); + const draft = readProjectionDraftRequest(value); + assertOnlyKeys(request, [ + "agentId", + "sourceRevisionId", + "targetKind", + "targetId", + "purpose", + "preview", + "expiresAt", + "noExpiryAuditReason", + ]); + return { ...draft, target: readProjectionTarget(request, draft.agentId) }; +} + +function readProjectionCreateRequest(value: unknown): ProjectionCreateRequest { + const request = paramsRecord(value); + const draft = readProjectionDraftRequest(value); + assertOnlyKeys(request, [ + "agentId", + "sourceRevisionId", + "targetKind", + "targetId", + "purpose", + "preview", + "content", + "expiresAt", + "noExpiryAuditReason", + ]); + return { + ...draft, + target: readProjectionTarget(request, draft.agentId), + content: readRequiredString(request, "content"), + }; +} + +function readProjectionRefreshRequest(value: unknown): ProjectionRefreshRequest { + const request = paramsRecord(value); + const draft = readProjectionDraftRequest(value); + assertOnlyKeys(request, [ + "agentId", + "projectionId", + "sourceRevisionId", + "purpose", + "preview", + "content", + "expiresAt", + "noExpiryAuditReason", + ]); + return { + ...draft, + projectionId: readRequiredString(request, "projectionId"), + content: readRequiredString(request, "content"), + }; +} + +function readProjectionIdRequest(value: unknown) { + const request = paramsRecord(value); + assertOnlyKeys(request, ["agentId", "projectionId"]); + return { + agentId: readAgentId(request), + projectionId: readRequiredString(request, "projectionId"), + }; +} + +function readProjectionTargetRegisterRequest(value: unknown) { + const request = paramsRecord(value); + assertOnlyKeys(request, ["agentId", "targetKind", "targetId", "storeId"]); + const agentId = readAgentId(request); + return { + agentId, + target: readProjectionTarget(request, agentId), + storeId: readRequiredString(request, "storeId"), + }; +} + +function readPostboxItemIdRequest(value: unknown) { + const request = paramsRecord(value); + assertOnlyKeys(request, ["agentId", "itemId"]); + return { + agentId: readAgentId(request), + itemId: readRequiredString(request, "itemId"), + }; +} + +function readPostboxReviewRequest(value: unknown): { + agentId: string; + itemId: string; + decision: "approve" | "reject"; + reviewedContent?: string; +} { + const request = paramsRecord(value); + assertOnlyKeys(request, ["agentId", "itemId", "decision", "reviewedContent"]); + const decision = readRequiredString(request, "decision"); + if (decision !== "approve" && decision !== "reject") { + throw new InvalidMemorySharingRequestError("decision must be approve or reject."); + } + const reviewedContent = request.reviewedContent; + if (decision === "reject" && reviewedContent !== undefined) { + throw new InvalidMemorySharingRequestError("reviewedContent is available only for approve."); + } + return { + agentId: readAgentId(request), + itemId: readRequiredString(request, "itemId"), + decision, + ...(reviewedContent === undefined + ? {} + : { reviewedContent: readRequiredString(request, "reviewedContent") }), + }; +} + +function resolveGatewayPrincipal( + client: { + authenticatedUserProfile?: { profileId: string }; + } | null, +): string { + const profileId = client?.authenticatedUserProfile?.profileId; + if (!profileId) { + throw new ForbiddenMemorySharingRequestError( + "memory sharing requires an authenticated Gateway profile.", + ); + } + const principal = resolveMemoryPrincipalForUserProfile({ userProfileId: profileId }); + if (!principal) { + throw new ForbiddenMemorySharingRequestError("memory sharing is unavailable for this profile."); + } + return principal.principalId; +} + +function respondInvalid(respond: GatewayRequestHandlerOptions["respond"], error: unknown) { + const message = error instanceof Error ? error.message : "invalid memory sharing request"; + respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, message)); +} + +function respondForbidden(respond: GatewayRequestHandlerOptions["respond"], error: unknown) { + const message = error instanceof Error ? error.message : "memory sharing is unavailable"; + respond(false, undefined, errorShape(ErrorCodes.FORBIDDEN, message)); +} + +function respondUnavailable(respond: GatewayRequestHandlerOptions["respond"]) { + respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, "memory sharing is unavailable")); +} + +/** Register profile-derived, redacted sharing controls. No handler accepts a principal or private-store id. */ +export function registerScopedMemorySharingGatewayMethods(api: OpenClawPluginApi): void { + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.status, + async ({ params, client, respond }) => { + try { + const request = paramsRecord(params); + assertOnlyKeys(request, ["agentId"]); + const agentId = readAgentId(request); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { inspectBuiltinMemorySharingStatus } = await loadSharing(); + respond(true, inspectBuiltinMemorySharingStatus({ agentId, operatorPrincipalId })); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.read" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionTargetRegister, + async ({ params, client, respond }) => { + try { + const request = readProjectionTargetRegisterRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { registerBuiltinMemoryProjectionTargetStore } = await loadSharing(); + registerBuiltinMemoryProjectionTargetStore({ ...request, operatorPrincipalId }); + respond(true, { target: request.target }); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionPreview, + async ({ params, client, respond }) => { + try { + const request = readProjectionPreviewRequest(params); + const publisherPrincipalId = resolveGatewayPrincipal(client); + const { previewBuiltinMemoryProjection } = await loadSharing(); + respond(true, previewBuiltinMemoryProjection({ ...request, publisherPrincipalId })); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionCreate, + async ({ params, client, respond }) => { + try { + const request = readProjectionCreateRequest(params); + const publisherPrincipalId = resolveGatewayPrincipal(client); + const { createBuiltinMemoryProjection } = await loadSharing(); + respond( + true, + createBuiltinMemoryProjection({ + agentId: request.agentId, + sourceRevisionId: request.sourceRevisionId, + target: request.target, + purpose: request.purpose, + preview: request.preview, + content: request.content, + expiry: request.expiry, + publisherPrincipalId, + reviewedByPrincipalId: publisherPrincipalId, + }), + ); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionRefresh, + async ({ params, client, respond }) => { + try { + const request = readProjectionRefreshRequest(params); + const publisherPrincipalId = resolveGatewayPrincipal(client); + const { refreshBuiltinMemoryProjection } = await loadSharing(); + respond( + true, + refreshBuiltinMemoryProjection({ + agentId: request.agentId, + projectionId: request.projectionId, + sourceRevisionId: request.sourceRevisionId, + purpose: request.purpose, + preview: request.preview, + content: request.content, + expiry: request.expiry, + publisherPrincipalId, + reviewedByPrincipalId: publisherPrincipalId, + }), + ); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionRevoke, + async ({ params, client, respond }) => { + try { + const request = readProjectionIdRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { revokeBuiltinMemoryProjection } = await loadSharing(); + respond(true, { + projectionId: request.projectionId, + exposureSetIds: revokeBuiltinMemoryProjection({ ...request, operatorPrincipalId }), + }); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.projectionImpact, + async ({ params, client, respond }) => { + try { + const request = readProjectionIdRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { inspectBuiltinMemoryProjectionImpact } = await loadSharing(); + respond(true, inspectBuiltinMemoryProjectionImpact({ ...request, operatorPrincipalId })); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.read" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.postboxMode, + async ({ params, client, respond }) => { + try { + const request = paramsRecord(params); + assertOnlyKeys(request, ["agentId", "mode"]); + const agentId = readAgentId(request); + const mode = readRequiredString(request, "mode"); + if (mode !== "off" && mode !== "review-required") { + throw new InvalidMemorySharingRequestError("mode must be off or review-required."); + } + const principalId = resolveGatewayPrincipal(client); + const { setBuiltinMemoryPostboxModeForPrincipal } = await loadSharing(); + setBuiltinMemoryPostboxModeForPrincipal({ agentId, principalId, mode }); + respond(true, { mode }); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.postboxInspect, + async ({ params, client, respond }) => { + try { + const request = readPostboxItemIdRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { inspectBuiltinMemoryPostboxItem } = await loadSharing(); + respond(true, inspectBuiltinMemoryPostboxItem({ ...request, operatorPrincipalId })); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.read" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.postboxReview, + async ({ params, client, respond }) => { + try { + const request = readPostboxReviewRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { reviewBuiltinMemoryPostboxItem } = await loadSharing(); + reviewBuiltinMemoryPostboxItem({ ...request, operatorPrincipalId }); + respond(true, { itemId: request.itemId, decision: request.decision }); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); + + api.registerGatewayMethod( + MEMORY_SHARING_GATEWAY_METHODS.postboxPurge, + async ({ params, client, respond }) => { + try { + const request = readPostboxItemIdRequest(params); + const operatorPrincipalId = resolveGatewayPrincipal(client); + const { reviewBuiltinMemoryPostboxItem } = await loadSharing(); + reviewBuiltinMemoryPostboxItem({ ...request, operatorPrincipalId, decision: "purge" }); + respond(true, { itemId: request.itemId, state: "purged" }); + } catch (error) { + if (error instanceof InvalidMemorySharingRequestError) { + respondInvalid(respond, error); + } else if (error instanceof ForbiddenMemorySharingRequestError) { + respondForbidden(respond, error); + } else { + respondUnavailable(respond); + } + } + }, + { scope: "operator.admin" }, + ); +} diff --git a/extensions/memory-core/src/memory/scoped-memory-sharing.test.ts b/extensions/memory-core/src/memory/scoped-memory-sharing.test.ts index 7837bdb3f00c..40a9e12ee3f7 100644 --- a/extensions/memory-core/src/memory/scoped-memory-sharing.test.ts +++ b/extensions/memory-core/src/memory/scoped-memory-sharing.test.ts @@ -4,12 +4,14 @@ import path from "node:path"; import { closeOpenClawAgentDatabasesForTest } from "openclaw/plugin-sdk/sqlite-runtime-testing"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { + admitMemoryPostboxTurnIngress, mintMemoryPostboxTurnCapability, resetMemoryPostboxTurnCapabilitiesForTest, } from "../../../../src/gateway/memory-postbox-turn-capability.js"; import { openOpenClawAgentDatabase } from "../../../../src/state/openclaw-agent-db.js"; import { createBuiltinScopedMemoryResource, + createBuiltinScopedMemoryResourceRevision, readBuiltinScopedMemoryRevisionSnapshot, } from "./scoped-memory-resources.js"; import { @@ -17,14 +19,25 @@ import { depositBuiltinMemoryPostbox, depositBuiltinMemoryPostboxFromTurnCapability, expireBuiltinMemoryProjections, + inspectBuiltinMemoryProjectionImpact, + inspectBuiltinMemorySharingStatus, + inspectBuiltinMemoryPostboxItem, + previewBuiltinMemoryProjection, refreshBuiltinMemoryProjection, registerBuiltinMemoryProjectionTarget, revokeBuiltinMemoryProjection, reviewBuiltinMemoryPostboxItem, setBuiltinMemoryPostboxMode, + setBuiltinMemoryPostboxModeForPrincipal, } from "./scoped-memory-sharing.js"; import { createBuiltinScopedMemoryStore } from "./scoped-memory-store.js"; +const createCurrentMemorySessionContext = vi.hoisted(() => vi.fn()); + +vi.mock("../../../../src/state/memory-session-subject.js", () => ({ + createCurrentMemorySessionContext, +})); + describe("builtin scoped memory sharing", () => { let stateDir = ""; const agentId = "main"; @@ -34,11 +47,20 @@ describe("builtin scoped memory sharing", () => { beforeEach(() => { stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-memory-sharing-")); vi.stubEnv("OPENCLAW_STATE_DIR", stateDir); + createCurrentMemorySessionContext.mockReturnValue({ + kind: "current", + context: { + subject: { kind: "user" }, + principalId: alice, + fingerprint: "alice-current-session", + }, + }); }); afterEach(() => { closeOpenClawAgentDatabasesForTest(); resetMemoryPostboxTurnCapabilitiesForTest(); + createCurrentMemorySessionContext.mockReset(); vi.unstubAllEnvs(); fs.rmSync(stateDir, { recursive: true, force: true }); }); @@ -153,16 +175,29 @@ describe("builtin scoped memory sharing", () => { function depositFromVerifiedTurn(params: { content: string; sourceMessageRef: string }) { const runId = `run-${params.sourceMessageRef}`; const sessionKey = "agent:main:direct:alice"; + const sourceContext = {}; + const sourceTurnId = `channel-user:v1:${params.sourceMessageRef}`; + admitMemoryPostboxTurnIngress({ + context: sourceContext, + agentId, + sessionKey, + sessionId: "session-alice", + provider: "telegram", + inputProvenance: { kind: "external_user" }, + sourceTurnId, + sourceChannelRef: "telegram:account:direct-alice", + senderEvidenceRef: "telegram:sender-alice", + }); const token = mintMemoryPostboxTurnCapability({ agentId, runId, sessionKey, sessionId: "session-alice", - sourceChannelRef: "telegram:alice", - sourceMessageRef: params.sourceMessageRef, - senderEvidenceRef: "telegram:sender-alice", - targetPrincipalId: alice, + sourceContext, }); + if (!token) { + throw new Error("expected verified turn capability"); + } return depositBuiltinMemoryPostboxFromTurnCapability({ agentId, runId, @@ -220,13 +255,24 @@ describe("builtin scoped memory sharing", () => { expect( database.db .prepare( - "SELECT source_revision_id, reviewed_by_principal_id, expiry_kind FROM memory_projections", + `SELECT target_audience_kind, target_audience_id, source_revision_id, publisher_principal_id, + reviewed_by_principal_id, purpose, preview, expiry_kind, expiry_audit_reason, + revocation_behavior, state + FROM memory_projections`, ) .get(), ).toEqual({ + target_audience_kind: "conversation", + target_audience_id: channel, source_revision_id: privateRevision.revisionId, + publisher_principal_id: alice, reviewed_by_principal_id: alice, + purpose: "share approved contact detail", + preview: "one approved detail", expiry_kind: "no-expiry", + expiry_audit_reason: "owner approved durable reference", + revocation_behavior: "tombstone-copy", + state: "active", }); expect( database.db @@ -237,6 +283,59 @@ describe("builtin scoped memory sharing", () => { ).toEqual({ parent_id: privateRevision.revisionId }); }); + it("previews the authorized projection metadata without reading or changing the private source", () => { + const source = sourceStore(); + const target = projectionStore(); + const privateRevision = createBuiltinScopedMemoryResource({ + agentId, + store: source, + logicalLocator: "private.md", + content: "private source that must not appear in preview", + actor: { kind: "human", id: alice }, + }); + registerBuiltinMemoryProjectionTarget({ + agentId, + target: { kind: "conversation", id: channel }, + store: target, + operatorPrincipalId: alice, + }); + + expect( + previewBuiltinMemoryProjection({ + agentId, + sourceRevisionId: privateRevision.revisionId, + target: { kind: "conversation", id: channel }, + publisherPrincipalId: alice, + purpose: "share approved contact detail", + preview: "one approved detail", + expiry: { kind: "no-expiry", auditReason: "owner approved durable reference" }, + }), + ).toEqual({ + sourceRevisionId: privateRevision.revisionId, + target: { kind: "conversation", id: channel }, + purpose: "share approved contact detail", + preview: "one approved detail", + expiry: "no-expiry", + }); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT COUNT(*) AS count FROM memory_projections") + .get(), + ).toEqual({ count: 0 }); + }); + + it("refuses raw private-user projection targets before a helper can create a direct grant", () => { + const privateTarget = privateTargetStore(); + expect(() => + registerBuiltinMemoryProjectionTarget({ + agentId, + target: { kind: "user", id: "principal-bob" } as never, + store: privateTarget, + operatorPrincipalId: alice, + }), + ).toThrow("memory projection target is unavailable"); + }); + it("requires independent source project and target publisher authority", () => { const source = createBuiltinScopedMemoryStore({ agentId, @@ -395,6 +494,24 @@ describe("builtin scoped memory sharing", () => { operatorPrincipalId: alice, }), ).toEqual(["projection-impact-exposure"]); + expect( + inspectBuiltinMemoryProjectionImpact({ + agentId, + projectionId: projection.projectionId, + operatorPrincipalId: alice, + }), + ).toEqual({ + projectionId: projection.projectionId, + exposureSetIds: ["projection-impact-exposure"], + }); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: projection.copyRevisionId, + }), + ).toBeUndefined(); + closeOpenClawAgentDatabasesForTest(); expect( readBuiltinScopedMemoryRevisionSnapshot({ agentId, @@ -515,6 +632,30 @@ describe("builtin scoped memory sharing", () => { expiry: { kind: "no-expiry", auditReason: "initial review" }, }); + const editedSource = createBuiltinScopedMemoryResourceRevision({ + agentId, + resourceId: firstSource.resourceId, + content: "private v1 edited", + actor: { kind: "human", id: alice }, + }); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: original.copyRevisionId, + }), + ).toBeUndefined(); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT count(*) AS count FROM memory_projections") + .get(), + ).toEqual({ count: 1 }); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT count(*) AS count FROM memory_projections WHERE source_revision_id = ?") + .get(editedSource.revisionId), + ).toEqual({ count: 0 }); + const refreshed = refreshBuiltinMemoryProjection({ agentId, projectionId: original.projectionId, @@ -546,7 +687,98 @@ describe("builtin scoped memory sharing", () => { ).toBe("approved v2"); }); - it("keeps postbox off by default and makes review-required deposits one-way", () => { + it("rolls back a replacement when the old projection no longer has the same audience", () => { + const source = sourceStore(); + const target = projectionStore(); + const otherChannel = "conversation-other"; + const otherTarget = createBuiltinScopedMemoryStore({ + agentId, + scopeKind: "conversation", + audienceKind: "conversation", + audienceId: otherChannel, + authorityKind: "conversation", + authorityOwnerId: otherChannel, + defaultCapabilities: ["read"], + policyEntries: [ + { + kind: "publish", + effect: "allow", + principalId: alice, + operation: "publish", + grantorPrincipalId: alice, + reason: "named publisher", + }, + { + effect: "allow", + principalId: alice, + operation: "policy-admin", + grantorPrincipalId: alice, + reason: "projection administrator", + }, + ], + actor: { kind: "human", id: alice }, + reason: "different projection target", + }); + const sourceRevision = createBuiltinScopedMemoryResource({ + agentId, + store: source, + logicalLocator: "private.md", + content: "private source", + actor: { kind: "human", id: alice }, + }); + registerBuiltinMemoryProjectionTarget({ + agentId, + target: { kind: "conversation", id: channel }, + store: target, + operatorPrincipalId: alice, + }); + registerBuiltinMemoryProjectionTarget({ + agentId, + target: { kind: "conversation", id: otherChannel }, + store: otherTarget, + operatorPrincipalId: alice, + }); + const original = createBuiltinMemoryProjection({ + agentId, + sourceRevisionId: sourceRevision.revisionId, + target: { kind: "conversation", id: channel }, + publisherPrincipalId: alice, + reviewedByPrincipalId: alice, + purpose: "share", + preview: "original", + content: "original approved copy", + expiry: { kind: "no-expiry", auditReason: "approved" }, + }); + + expect(() => + createBuiltinMemoryProjection({ + agentId, + sourceRevisionId: sourceRevision.revisionId, + target: { kind: "conversation", id: otherChannel }, + publisherPrincipalId: alice, + reviewedByPrincipalId: alice, + purpose: "share", + preview: "replacement", + content: "must never become readable", + expiry: { kind: "no-expiry", auditReason: "approved" }, + replaceActiveProjectionId: original.projectionId, + }), + ).toThrow("memory projection is unavailable"); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT COUNT(*) AS count FROM memory_projections") + .get(), + ).toEqual({ count: 1 }); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: original.copyRevisionId, + })?.content, + ).toBe("original approved copy"); + }); + + it("keeps postbox off by default and promotes only an explicitly approved reviewed copy", () => { const target = privateTargetStore(); expect( depositFromVerifiedTurn({ content: "observation", sourceMessageRef: "message-ref-off" }), @@ -558,6 +790,7 @@ describe("builtin scoped memory sharing", () => { operatorPrincipalId: alice, mode: "review-required", }); + closeOpenClawAgentDatabasesForTest(); expect( depositBuiltinMemoryPostbox({ agentId, sourceHandleId: "forged", content: "observation" }), ).toEqual({ accepted: false }); @@ -579,12 +812,260 @@ describe("builtin scoped memory sharing", () => { itemId: item.item_id, operatorPrincipalId: alice, decision: "approve", + reviewedContent: "owner-edited review copy", }); expect(database.db.prepare("SELECT state FROM memory_postbox_items").get()).toEqual({ state: "reviewed", }); - expect(database.db.prepare("SELECT COUNT(*) AS count FROM memory_resources").get()).toEqual({ - count: 0, + const reviewedCopy = database.db + .prepare(`SELECT revision_id FROM memory_postbox_reviewed_copies WHERE item_id = ?`) + .get(item.item_id) as { revision_id: string }; + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: reviewedCopy.revision_id, + })?.content, + ).toBe("owner-edited review copy"); + closeOpenClawAgentDatabasesForTest(); + expect(() => + inspectBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + }), + ).toThrow("memory postbox item is unavailable"); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT state FROM memory_postbox_items WHERE item_id = ?") + .get(item.item_id), + ).toEqual({ state: "reviewed" }); + reviewBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + decision: "purge", + }); + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: reviewedCopy.revision_id, + }), + ).toBeUndefined(); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT item_id FROM memory_postbox_reviewed_copies WHERE item_id = ?") + .get(item.item_id), + ).toEqual({ item_id: item.item_id }); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT state, content, purged_at FROM memory_postbox_items WHERE item_id = ?") + .get(item.item_id), + ).toMatchObject({ state: "purged", content: "", purged_at: expect.any(Number) }); + }); + + it("rolls back a purge when the durable postbox redaction cannot commit", () => { + const target = privateTargetStore(); + setBuiltinMemoryPostboxMode({ + agentId, + targetStoreId: target.storeId, + operatorPrincipalId: alice, + mode: "review-required", + }); + expect( + depositFromVerifiedTurn({ + content: "review body", + sourceMessageRef: "message-purge-rollback", + }), + ).toEqual({ accepted: true }); + + const database = openOpenClawAgentDatabase({ agentId }); + const item = database.db.prepare("SELECT item_id FROM memory_postbox_items").get() as { + item_id: string; + }; + reviewBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + decision: "approve", + reviewedContent: "owner-reviewed body", + }); + const reviewedCopy = database.db + .prepare("SELECT revision_id FROM memory_postbox_reviewed_copies WHERE item_id = ?") + .get(item.item_id) as { revision_id: string }; + database.db.exec(` + CREATE TRIGGER fail_postbox_purge_redaction + BEFORE UPDATE OF state ON memory_postbox_items + WHEN NEW.state = 'purged' + BEGIN + SELECT RAISE(ABORT, 'forced postbox purge redaction failure'); + END; + `); + + try { + expect(() => + reviewBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + decision: "purge", + }), + ).toThrow("forced postbox purge redaction failure"); + } finally { + database.db.exec("DROP TRIGGER fail_postbox_purge_redaction"); + } + + expect( + readBuiltinScopedMemoryRevisionSnapshot({ + agentId, + storeIds: [target.storeId], + revisionId: reviewedCopy.revision_id, + })?.content, + ).toBe("owner-reviewed body"); + expect( + database.db + .prepare( + "SELECT state, content, content_hash, purged_at FROM memory_postbox_items WHERE item_id = ?", + ) + .get(item.item_id), + ).toMatchObject({ + state: "reviewed", + content: "review body", + content_hash: expect.any(String), + purged_at: null, + }); + expect( + database.db + .prepare( + "SELECT lifecycle_state, retired_at FROM memory_resource_revisions WHERE revision_id = ?", + ) + .get(reviewedCopy.revision_id), + ).toEqual({ lifecycle_state: "active", retired_at: null }); + expect( + database.db + .prepare("SELECT revision_id FROM memory_postbox_reviewed_copies WHERE item_id = ?") + .get(item.item_id), + ).toEqual({ revision_id: reviewedCopy.revision_id }); + const remainingChunks = database.db + .prepare("SELECT COUNT(*) AS count FROM memory_scoped_chunks WHERE revision_id = ?") + .get(reviewedCopy.revision_id) as { count: number }; + expect(remainingChunks.count).toBeGreaterThan(0); + }); + + it("denies forged, stale, cross-run, cross-session, and replayed postbox capabilities", () => { + const target = privateTargetStore(); + setBuiltinMemoryPostboxMode({ + agentId, + targetStoreId: target.storeId, + operatorPrincipalId: alice, + mode: "review-required", + }); + const sourceContext = {}; + const sourceTurnId = "channel-user:v1:message-capability"; + admitMemoryPostboxTurnIngress({ + context: sourceContext, + agentId, + sessionKey: "agent:main:direct:alice", + sessionId: "session-alice", + provider: "telegram", + inputProvenance: { kind: "external_user" }, + sourceTurnId, + sourceChannelRef: "telegram:account:direct-alice", + senderEvidenceRef: "telegram:sender-alice", + }); + const token = mintMemoryPostboxTurnCapability({ + agentId, + runId: "run-capability", + sessionKey: "agent:main:direct:alice", + sessionId: "session-alice", + sourceContext, + }); + if (!token) { + throw new Error("expected verified turn capability"); + } + const deposit = ( + overrides: Partial<{ + runId: string; + sessionKey: string; + sessionId: string; + turnCapability: string; + }> = {}, + ) => + depositBuiltinMemoryPostboxFromTurnCapability({ + agentId, + runId: "run-capability", + sessionKey: "agent:main:direct:alice", + sessionId: "session-alice", + turnCapability: token, + content: "one-way observation", + ...overrides, + }); + + expect(deposit({ turnCapability: "forged" })).toEqual({ accepted: false }); + expect(deposit({ runId: "other-run" })).toEqual({ accepted: false }); + expect(deposit({ sessionId: "other-session" })).toEqual({ accepted: false }); + createCurrentMemorySessionContext.mockReturnValueOnce({ + kind: "current", + context: { + subject: { kind: "user" }, + principalId: alice, + fingerprint: "rebound-session", + }, + }); + expect(deposit()).toEqual({ accepted: false }); + expect(deposit()).toEqual({ accepted: true }); + expect(deposit()).toEqual({ accepted: false }); + }); + + it("derives the owner quarantine internally and returns only redacted sharing status", () => { + const source = sourceStore(); + const target = projectionStore(); + privateTargetStore(); + const sourceRevision = createBuiltinScopedMemoryResource({ + agentId, + store: source, + logicalLocator: "private.md", + content: "private source", + actor: { kind: "human", id: alice }, + }); + registerBuiltinMemoryProjectionTarget({ + agentId, + target: { kind: "conversation", id: channel }, + store: target, + operatorPrincipalId: alice, + }); + const projection = createBuiltinMemoryProjection({ + agentId, + sourceRevisionId: sourceRevision.revisionId, + target: { kind: "conversation", id: channel }, + publisherPrincipalId: alice, + reviewedByPrincipalId: alice, + purpose: "share approved detail", + preview: "approved detail", + content: "reviewed copy only", + expiry: { kind: "no-expiry", auditReason: "durable approved reference" }, + }); + + setBuiltinMemoryPostboxModeForPrincipal({ + agentId, + principalId: alice, + mode: "review-required", + }); + + expect(inspectBuiltinMemorySharingStatus({ agentId, operatorPrincipalId: alice })).toEqual({ + postboxMode: "review-required", + projections: [ + { + projectionId: projection.projectionId, + target: { kind: "conversation", id: channel }, + purpose: "share approved detail", + preview: "approved detail", + state: "active", + expiresAt: null, + }, + ], + postboxItems: [], }); }); @@ -615,5 +1096,78 @@ describe("builtin scoped memory sharing", () => { count: 12, }, ); + closeOpenClawAgentDatabasesForTest(); + expect( + depositFromVerifiedTurn({ + content: "observation-after-reopen", + sourceMessageRef: "message-after-reopen", + }), + ).toEqual({ accepted: false }); + expect( + openOpenClawAgentDatabase({ agentId }) + .db.prepare("SELECT deposit_count FROM memory_postbox_rate_limits") + .get(), + ).toEqual({ deposit_count: 12 }); + }); + + it("limits postbox body inspection to the target owner and persists a purged audit record", () => { + const target = privateTargetStore(); + setBuiltinMemoryPostboxMode({ + agentId, + targetStoreId: target.storeId, + operatorPrincipalId: alice, + mode: "review-required", + }); + expect( + depositFromVerifiedTurn({ + content: "private review body", + sourceMessageRef: "message-inspect", + }), + ).toEqual({ accepted: true }); + const database = openOpenClawAgentDatabase({ agentId }); + const item = database.db.prepare("SELECT item_id FROM memory_postbox_items").get() as { + item_id: string; + }; + + expect( + inspectBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + }), + ).toMatchObject({ + itemId: item.item_id, + content: "private review body", + sourceChannelRef: "telegram:account:direct-alice", + }); + expect(() => + inspectBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: "principal-mallory", + }), + ).toThrow("memory sharing authorization is unavailable"); + + reviewBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + decision: "purge", + nowMs: 1_700_000_000_000, + }); + expect( + database.db.prepare("SELECT state, content, purged_at FROM memory_postbox_items").get(), + ).toEqual({ + state: "purged", + content: "", + purged_at: 1_700_000_000_000, + }); + expect(() => + inspectBuiltinMemoryPostboxItem({ + agentId, + itemId: item.item_id, + operatorPrincipalId: alice, + }), + ).toThrow("memory postbox item is unavailable"); }); }); diff --git a/extensions/memory-core/src/memory/scoped-memory-sharing.ts b/extensions/memory-core/src/memory/scoped-memory-sharing.ts index bc6e4d9c1bc3..f7836ae427b2 100644 --- a/extensions/memory-core/src/memory/scoped-memory-sharing.ts +++ b/extensions/memory-core/src/memory/scoped-memory-sharing.ts @@ -12,8 +12,8 @@ import { evaluateBuiltinScopedMemoryPolicy } from "./scoped-memory-policy.js"; import { createBuiltinScopedMemoryResource, readBuiltinScopedMemoryRevisionSnapshot, + setBuiltinScopedMemoryRevisionLifecycle, type BuiltinScopedMemoryDerivedSource, - type BuiltinScopedMemoryRevision, } from "./scoped-memory-resources.js"; import { createScopedMemorySourcePolicySetId, @@ -37,15 +37,50 @@ export type BuiltinMemoryProjection = Readonly<{ sourceRevisionId: string; target: ProjectionAudience; expiresAt?: number; + /** Present only for a refresh: the old copy's prior exposure ids under the replacement fence. */ + replacedExposureSetIds?: readonly string[]; +}>; + +export type BuiltinMemoryProjectionPreview = Readonly<{ + sourceRevisionId: string; + target: ProjectionAudience; + purpose: string; + preview: string; + expiry: "expires" | "no-expiry"; }>; export type BuiltinMemoryPostboxDeposit = Readonly<{ accepted: boolean }>; +export type BuiltinMemoryPostboxInspection = Readonly<{ + itemId: string; + content: string; + sourceChannelRef: string; + createdAt: number; +}>; + export type BuiltinMemoryProjectionImpact = Readonly<{ projectionId: string; exposureSetIds: readonly string[]; }>; +export type BuiltinMemorySharingStatus = Readonly<{ + postboxMode: "off" | "review-required"; + projections: readonly Readonly<{ + projectionId: string; + target: ProjectionAudience; + purpose: string; + preview: string; + state: "active" | "revoked" | "expired"; + expiresAt: number | null; + }>[]; + postboxItems: readonly Readonly<{ + itemId: string; + state: "postbox" | "reviewed" | "rejected" | "purged"; + sourceChannelRef: string; + createdAt: number; + }>[]; +}>; + function hash(value: string): string { return createHash("sha256").update(value).digest("hex"); } @@ -119,7 +154,7 @@ function readPostboxTargetStore(params: { targetPrincipalId: string; }) { const db = getNodeSqliteKysely(params.database); - return executeSqliteQueryTakeFirstSync( + const candidates = executeSqliteQuerySync( params.database, db .selectFrom("memory_stores") @@ -128,7 +163,58 @@ function readPostboxTargetStore(params: { .where("audience_kind", "=", "user") .where("audience_id", "=", params.targetPrincipalId) .where("lifecycle_state", "=", "active"), + ).rows; + const eligible = candidates.filter( + (store) => + evaluateBuiltinScopedMemoryPolicy({ + agentId: params.agentId, + storeId: store.store_id, + principalIds: [params.targetPrincipalId], + deliveryAudiences: [{ kind: "user", id: params.targetPrincipalId }], + operation: "policy-admin", + }).allowed, ); + // A verified principal may own more than one user store. Selecting a first + // row would make quarantine depend on database order; ambiguous targets fail closed. + return eligible.length === 1 ? eligible[0] : undefined; +} + +function readPostboxTargetMemoryStore(params: { + database: Parameters>[0]; + agentId: string; + storeId: string; +}): BuiltinScopedMemoryStore | undefined { + const db = getNodeSqliteKysely(params.database); + const store = executeSqliteQueryTakeFirstSync( + params.database, + db + .selectFrom("memory_stores as store") + .innerJoin("memory_policies as policy", "policy.policy_id", "store.policy_id") + .select([ + "store.store_id", + "store.storage_root_id", + "store.policy_id", + "store.audience_kind", + "policy.current_revision_id", + "policy.revocation_epoch", + ]) + .where("store.agent_id", "=", params.agentId) + .where("store.store_id", "=", params.storeId) + .where("store.lifecycle_state", "=", "active") + .where("store.audience_kind", "=", "user") + .where("policy.lifecycle_state", "=", "active"), + ); + if (!store) { + return undefined; + } + return Object.freeze({ + storageRootId: store.storage_root_id, + storeId: store.store_id, + policyId: store.policy_id, + policyRevisionId: store.current_revision_id, + policyRevocationEpoch: store.revocation_epoch, + sourcePolicySetId: createScopedMemorySourcePolicySetId(store.current_revision_id), + }); } function readSource(params: { @@ -191,17 +277,28 @@ export function registerBuiltinMemoryProjectionTarget(params: { store: BuiltinScopedMemoryStore; operatorPrincipalId: string; nowMs?: number; +}): void { + registerBuiltinMemoryProjectionTargetStore({ + agentId: params.agentId, + target: params.target, + storeId: params.store.storeId, + operatorPrincipalId: params.operatorPrincipalId, + nowMs: params.nowMs, + }); +} + +/** Register a pre-existing non-private store as the sole reviewed-copy target for its audience. */ +export function registerBuiltinMemoryProjectionTargetStore(params: { + agentId: string; + target: ProjectionAudience; + storeId: string; + operatorPrincipalId: string; + nowMs?: number; }): void { const target = targetAudience(params.target); + const storeId = normalize(params.storeId, "projection target store id"); const operatorPrincipalId = normalize(params.operatorPrincipalId, "operator principal id"); const nowMs = params.nowMs ?? Date.now(); - assertStoreOperation({ - agentId: params.agentId, - storeId: params.store.storeId, - principalId: operatorPrincipalId, - audience: target, - operation: "policy-admin", - }); withScopedMemoryDatabase(params.agentId, (database) => { const db = getNodeSqliteKysely(database); runSqliteImmediateTransactionSync(database, () => { @@ -210,13 +307,20 @@ export function registerBuiltinMemoryProjectionTarget(params: { db .selectFrom("memory_stores") .select(["store_id", "audience_kind", "audience_id"]) - .where("store_id", "=", params.store.storeId) + .where("store_id", "=", storeId) .where("agent_id", "=", params.agentId) .where("lifecycle_state", "=", "active"), ); if (!store || store.audience_kind !== target.kind || store.audience_id !== target.id) { throw new Error("memory projection target is unavailable"); } + assertStoreOperation({ + agentId: params.agentId, + storeId, + principalId: operatorPrincipalId, + audience: target, + operation: "policy-admin", + }); executeSqliteQuerySync( database, db @@ -225,13 +329,13 @@ export function registerBuiltinMemoryProjectionTarget(params: { agent_id: params.agentId, audience_kind: target.kind, audience_id: target.id, - store_id: params.store.storeId, + store_id: storeId, configured_by_principal_id: operatorPrincipalId, created_at: nowMs, }) .onConflict((conflict) => conflict.columns(["agent_id", "audience_kind", "audience_id"]).doUpdateSet({ - store_id: params.store.storeId, + store_id: storeId, configured_by_principal_id: operatorPrincipalId, created_at: nowMs, }), @@ -254,12 +358,17 @@ export function createBuiltinMemoryProjection(params: { expiry: | Readonly<{ kind: "expires"; expiresAt: number }> | Readonly<{ kind: "no-expiry"; auditReason: string }>; + /** Refresh-only: atomically tombstone this still-active copy while committing the replacement. */ + replaceActiveProjectionId?: string; nowMs?: number; }): BuiltinMemoryProjection { const target = targetAudience(params.target); const sourceRevisionId = normalize(params.sourceRevisionId, "source revision id"); const publisherPrincipalId = normalize(params.publisherPrincipalId, "publisher principal id"); const reviewedByPrincipalId = normalize(params.reviewedByPrincipalId, "reviewer principal id"); + const replaceActiveProjectionId = params.replaceActiveProjectionId + ? normalize(params.replaceActiveProjectionId, "projection id") + : undefined; const purpose = normalize(params.purpose, "projection purpose"); const preview = normalize(params.preview, "projection preview"); const nowMs = params.nowMs ?? Date.now(); @@ -323,6 +432,7 @@ export function createBuiltinMemoryProjection(params: { policyRevocationEpoch: targetStore.revocation_epoch, sourcePolicySetId: createScopedMemorySourcePolicySetId(targetStore.current_revision_id), }); + let replacedExposureSetIds: readonly string[] | undefined; const copy = createBuiltinScopedMemoryResource({ agentId: params.agentId, store, @@ -334,6 +444,33 @@ export function createBuiltinMemoryProjection(params: { derivedSources: [sourceEvidence], commitAdditionalState: ({ database: transactionDatabase, revision }) => { const db = getNodeSqliteKysely(transactionDatabase); + if (replaceActiveProjectionId) { + const replaced = executeSqliteQueryTakeFirstSync( + transactionDatabase, + db + .selectFrom("memory_projections") + .selectAll() + .where("agent_id", "=", params.agentId) + .where("projection_id", "=", replaceActiveProjectionId), + ); + // Recheck the current projection under the replacement transaction. If it was revoked, + // retargeted, or expired after planning, do not create a second readable copy. + if ( + !replaced || + replaced.state !== "active" || + replaced.target_store_id !== targetStore.store_id || + replaced.target_audience_kind !== target.kind || + replaced.target_audience_id !== target.id + ) { + throw new Error("memory projection is unavailable"); + } + replacedExposureSetIds = tombstoneProjectionCopy({ + database: transactionDatabase, + projection: replaced, + state: "revoked", + nowMs, + }); + } executeSqliteQuerySync( transactionDatabase, db.insertInto("memory_projections").values({ @@ -365,10 +502,120 @@ export function createBuiltinMemoryProjection(params: { sourceRevisionId, target, ...(expiry.kind === "expires" ? { expiresAt: expiry.expiresAt } : {}), + ...(replacedExposureSetIds ? { replacedExposureSetIds } : {}), }); }); } +/** Validate a proposed reviewed copy without reading its source content or mutating sharing state. */ +export function previewBuiltinMemoryProjection(params: { + agentId: string; + sourceRevisionId: string; + target: ProjectionAudience; + publisherPrincipalId: string; + purpose: string; + preview: string; + expiry: + | Readonly<{ kind: "expires"; expiresAt: number }> + | Readonly<{ kind: "no-expiry"; auditReason: string }>; + nowMs?: number; +}): BuiltinMemoryProjectionPreview { + const target = targetAudience(params.target); + const sourceRevisionId = normalize(params.sourceRevisionId, "source revision id"); + const publisherPrincipalId = normalize(params.publisherPrincipalId, "publisher principal id"); + const purpose = normalize(params.purpose, "projection purpose"); + const preview = normalize(params.preview, "projection preview"); + const nowMs = params.nowMs ?? Date.now(); + if ( + (params.expiry.kind === "expires" && + (!Number.isSafeInteger(params.expiry.expiresAt) || params.expiry.expiresAt <= nowMs)) || + (params.expiry.kind === "no-expiry" && !params.expiry.auditReason.trim()) + ) { + throw new Error("memory projection expiry is unavailable"); + } + return withScopedMemoryDatabase(params.agentId, (database) => { + const source = readSource({ database, agentId: params.agentId, revisionId: sourceRevisionId }); + assertStoreOperation({ + agentId: params.agentId, + storeId: source.store_id, + principalId: publisherPrincipalId, + audience: { kind: source.audience_kind, id: source.audience_id }, + operation: "project", + }); + const targetStore = readTargetStore({ database, agentId: params.agentId, target }); + if (!targetStore) { + throw new Error("memory projection target is unavailable"); + } + assertStoreOperation({ + agentId: params.agentId, + storeId: targetStore.store_id, + principalId: publisherPrincipalId, + audience: target, + operation: "publish", + }); + return Object.freeze({ + sourceRevisionId, + target, + purpose, + preview, + expiry: params.expiry.kind, + }); + }); +} + +/** Return only redacted prior-exposure ids after checking publisher or target policy administration. */ +export function inspectBuiltinMemoryProjectionImpact(params: { + agentId: string; + projectionId: string; + operatorPrincipalId: string; +}): BuiltinMemoryProjectionImpact { + const projectionId = normalize(params.projectionId, "projection id"); + const operatorPrincipalId = normalize(params.operatorPrincipalId, "operator principal id"); + return withScopedMemoryDatabase(params.agentId, (database) => { + const db = getNodeSqliteKysely(database); + const projection = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_projections") + .select([ + "projection_id", + "copy_revision_id", + "publisher_principal_id", + "target_store_id", + "target_audience_kind", + "target_audience_id", + ]) + .where("agent_id", "=", params.agentId) + .where("projection_id", "=", projectionId), + ); + if (!projection) { + throw new Error("memory projection is unavailable"); + } + const target = targetAudience({ + kind: projection.target_audience_kind, + id: projection.target_audience_id, + }); + if (projection.publisher_principal_id !== operatorPrincipalId) { + assertStoreOperation({ + agentId: params.agentId, + storeId: projection.target_store_id, + principalId: operatorPrincipalId, + audience: target, + operation: "policy-admin", + }); + } + const exposureSetIds = executeSqliteQuerySync( + database, + db + .selectFrom("memory_run_exposure_resources") + .select("exposure_set_id") + .where("resource_revision_id", "=", projection.copy_revision_id) + .orderBy("exposure_set_id"), + ).rows.map((row) => row.exposure_set_id); + return Object.freeze({ projectionId, exposureSetIds: Object.freeze(exposureSetIds) }); + }); +} + /** Tombstones one copy and reads its recorded impact under the caller's write fence. */ function tombstoneProjectionCopy(params: { database: Parameters>[0]; @@ -507,7 +754,7 @@ export function expireBuiltinMemoryProjections(params: { }); } -/** Refresh explicitly creates a new reviewed copy, then revokes the previous copy and reports its impact. */ +/** Refresh commits the new reviewed copy and old-copy tombstone under one revision transaction. */ export function refreshBuiltinMemoryProjection(params: { agentId: string; projectionId: string; @@ -562,15 +809,13 @@ export function refreshBuiltinMemoryProjection(params: { preview: params.preview, content: params.content, expiry: params.expiry, + replaceActiveProjectionId: projectionId, nowMs: params.nowMs, }); - const replacedExposureSetIds = revokeBuiltinMemoryProjection({ - agentId: params.agentId, - projectionId, - operatorPrincipalId: publisherPrincipalId, - nowMs: params.nowMs, + return Object.freeze({ + projection, + replacedExposureSetIds: projection.replacedExposureSetIds ?? [], }); - return Object.freeze({ projection, replacedExposureSetIds }); } /** Postbox stays off until an authenticated owner/admin explicitly enables review-required deposits. */ @@ -624,6 +869,121 @@ export function setBuiltinMemoryPostboxMode(params: { }); } +/** The target quarantine is derived from the authenticated owner's principal, never RPC input. */ +export function setBuiltinMemoryPostboxModeForPrincipal(params: { + agentId: string; + principalId: string; + mode: "off" | "review-required"; + nowMs?: number; +}): void { + const targetStoreId = withScopedMemoryDatabase( + params.agentId, + (database) => + readPostboxTargetStore({ + database, + agentId: params.agentId, + targetPrincipalId: normalize(params.principalId, "operator principal id"), + })?.store_id, + ); + if (!targetStoreId) { + throw new Error("memory postbox target is unavailable"); + } + setBuiltinMemoryPostboxMode({ + agentId: params.agentId, + targetStoreId, + operatorPrincipalId: params.principalId, + mode: params.mode, + nowMs: params.nowMs, + }); +} + +/** Redacted owner inspection: no source revision, private copy, or postbox body leaves this path. */ +export function inspectBuiltinMemorySharingStatus(params: { + agentId: string; + operatorPrincipalId: string; +}): BuiltinMemorySharingStatus { + const operatorPrincipalId = normalize(params.operatorPrincipalId, "operator principal id"); + return withScopedMemoryDatabase(params.agentId, (database) => { + const db = getNodeSqliteKysely(database); + const target = readPostboxTargetStore({ + database, + agentId: params.agentId, + targetPrincipalId: operatorPrincipalId, + }); + if (!target) { + throw new Error("memory sharing is unavailable"); + } + assertStoreOperation({ + agentId: params.agentId, + storeId: target.store_id, + principalId: operatorPrincipalId, + audience: { kind: "user", id: operatorPrincipalId }, + operation: "policy-admin", + }); + const settings = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_postbox_settings") + .select("mode") + .where("agent_id", "=", params.agentId) + .where("target_store_id", "=", target.store_id), + ); + const projections = executeSqliteQuerySync( + database, + db + .selectFrom("memory_projections") + .select([ + "projection_id", + "target_audience_kind", + "target_audience_id", + "purpose", + "preview", + "state", + "expires_at", + ]) + .where("agent_id", "=", params.agentId) + .where("publisher_principal_id", "=", operatorPrincipalId) + .orderBy("created_at", "desc"), + ).rows.map((projection) => + Object.freeze({ + projectionId: projection.projection_id, + target: Object.freeze({ + kind: targetAudience({ + kind: projection.target_audience_kind, + id: projection.target_audience_id, + }).kind, + id: projection.target_audience_id, + }), + purpose: projection.purpose, + preview: projection.preview, + state: projection.state, + expiresAt: projection.expires_at, + }), + ); + const postboxItems = executeSqliteQuerySync( + database, + db + .selectFrom("memory_postbox_items") + .select(["item_id", "state", "source_channel_ref", "created_at"]) + .where("agent_id", "=", params.agentId) + .where("target_store_id", "=", target.store_id) + .orderBy("created_at", "desc"), + ).rows.map((item) => + Object.freeze({ + itemId: item.item_id, + state: item.state, + sourceChannelRef: item.source_channel_ref, + createdAt: item.created_at, + }), + ); + return Object.freeze({ + postboxMode: settings?.mode ?? "off", + projections: Object.freeze(projections), + postboxItems: Object.freeze(postboxItems), + }); + }); +} + /** Only core/channel ingress may mint this opaque handle from current verified sender evidence. */ function issueBuiltinMemoryPostboxSourceHandle(params: { agentId: string; @@ -677,7 +1037,7 @@ export function depositBuiltinMemoryPostboxFromTurnCapability(params: { agentId: string; runId: string; sessionKey: string; - sessionId?: string; + sessionId: string; turnCapability: string; content: string; nowMs?: number; @@ -707,9 +1067,11 @@ export function depositBuiltinMemoryPostboxFromTurnCapability(params: { } const sourceHandleId = issueBuiltinMemoryPostboxSourceHandle({ agentId: params.agentId, - sourceSessionId: params.sessionId ?? params.sessionKey, + sourceSessionId: params.sessionId, + // These facts are carried by the private ingress marker; never reconstruct route or sender + // identity from model-visible or reply-context strings. sourceChannelRef: source.sourceChannelRef, - sourceMessageRef: source.sourceMessageRef, + sourceMessageRef: source.sourceTurnId, senderEvidenceRef: source.senderEvidenceRef, targetStoreId, nowMs: params.nowMs, @@ -834,16 +1196,259 @@ export function depositBuiltinMemoryPostbox(params: { }); } -/** Owner/admin review changes quarantine state only; it never promotes postbox content into recall. */ +/** + * Approval is the one explicit promotion boundary: it writes an immutable owner-reviewed copy, + * while the original channel deposit remains quarantined and immutable. Reject never promotes. + */ export function reviewBuiltinMemoryPostboxItem(params: { agentId: string; itemId: string; operatorPrincipalId: string; decision: "approve" | "reject" | "purge"; + reviewedContent?: string; nowMs?: number; }): void { + const operatorPrincipalId = normalize(params.operatorPrincipalId, "operator principal id"); const nowMs = params.nowMs ?? Date.now(); + const itemId = normalize(params.itemId, "postbox item id"); + if (params.decision === "reject" && params.reviewedContent !== undefined) { + throw new Error("memory postbox review is unavailable"); + } + if (params.decision === "approve") { + const approval = withScopedMemoryDatabase(params.agentId, (database) => { + const db = getNodeSqliteKysely(database); + const item = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_postbox_items as item") + .innerJoin("memory_stores as store", "store.store_id", "item.target_store_id") + .select([ + "item.item_id", + "item.content", + "item.state", + "item.target_store_id", + "store.audience_kind", + "store.audience_id", + ]) + .where("item.item_id", "=", itemId) + .where("item.agent_id", "=", params.agentId), + ); + if (!item || item.state !== "postbox" || item.audience_kind !== "user") { + throw new Error("memory postbox item is unavailable"); + } + assertStoreOperation({ + agentId: params.agentId, + storeId: item.target_store_id, + principalId: operatorPrincipalId, + audience: { kind: "user", id: item.audience_id }, + operation: "policy-admin", + }); + const store = readPostboxTargetMemoryStore({ + database, + agentId: params.agentId, + storeId: item.target_store_id, + }); + if (!store) { + throw new Error("memory postbox item is unavailable"); + } + const content = + params.reviewedContent === undefined + ? item.content + : normalize(params.reviewedContent, "reviewed postbox content"); + if (Buffer.byteLength(content) > POSTBOX_MAX_CONTENT_BYTES) { + throw new Error("memory postbox review is unavailable"); + } + return Object.freeze({ item, store, content }); + }); + const copy = createBuiltinScopedMemoryResource({ + agentId: params.agentId, + store: approval.store, + logicalLocator: `postbox-reviewed/${approval.item.item_id}.md`, + content: approval.content, + lifecycleState: "pending", + actor: { kind: "human", id: operatorPrincipalId }, + nowMs, + }); + try { + withScopedMemoryDatabase(params.agentId, (database) => { + const db = getNodeSqliteKysely(database); + runSqliteImmediateTransactionSync(database, () => { + const item = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_postbox_items as item") + .innerJoin("memory_stores as store", "store.store_id", "item.target_store_id") + .select([ + "item.item_id", + "item.state", + "item.target_store_id", + "store.audience_kind", + "store.audience_id", + ]) + .where("item.item_id", "=", itemId) + .where("item.agent_id", "=", params.agentId), + ); + if ( + !item || + item.state !== "postbox" || + item.target_store_id !== approval.item.target_store_id || + item.audience_kind !== "user" + ) { + throw new Error("memory postbox item is unavailable"); + } + assertStoreOperation({ + agentId: params.agentId, + storeId: item.target_store_id, + principalId: operatorPrincipalId, + audience: { kind: "user", id: item.audience_id }, + operation: "policy-admin", + }); + const activated = executeSqliteQuerySync( + database, + db + .updateTable("memory_resource_revisions") + .set({ lifecycle_state: "active", activated_at: nowMs }) + .where("revision_id", "=", copy.revisionId) + .where("lifecycle_state", "=", "pending"), + ); + if (activated.numAffectedRows !== 1n) { + throw new Error("memory postbox item is unavailable"); + } + executeSqliteQuerySync( + database, + db.insertInto("memory_postbox_reviewed_copies").values({ + item_id: item.item_id, + agent_id: params.agentId, + resource_id: copy.resourceId, + revision_id: copy.revisionId, + reviewed_content_hash: hash(approval.content), + created_at: nowMs, + }), + ); + const reviewed = executeSqliteQuerySync( + database, + db + .updateTable("memory_postbox_items") + .set({ + state: "reviewed", + reviewed_by_principal_id: operatorPrincipalId, + reviewed_at: nowMs, + }) + .where("item_id", "=", item.item_id) + .where("state", "=", "postbox"), + ); + if (reviewed.numAffectedRows !== 1n) { + throw new Error("memory postbox item is unavailable"); + } + }); + }); + } catch (error) { + setBuiltinScopedMemoryRevisionLifecycle({ + agentId: params.agentId, + revisionId: copy.revisionId, + lifecycleState: "tombstoned", + nowMs, + }); + throw error; + } + return; + } withScopedMemoryDatabase(params.agentId, (database) => { + const db = getNodeSqliteKysely(database); + runSqliteImmediateTransactionSync(database, () => { + const item = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_postbox_items as item") + .innerJoin("memory_stores as store", "store.store_id", "item.target_store_id") + .select([ + "item.item_id", + "item.state", + "item.target_store_id", + "store.audience_kind", + "store.audience_id", + ]) + .where("item.item_id", "=", itemId) + .where("item.agent_id", "=", params.agentId), + ); + if (!item || item.audience_kind !== "user") { + throw new Error("memory postbox item is unavailable"); + } + assertStoreOperation({ + agentId: params.agentId, + storeId: item.target_store_id, + principalId: operatorPrincipalId, + audience: { kind: item.audience_kind, id: item.audience_id }, + operation: "policy-admin", + }); + if (params.decision === "purge") { + const approvedCopy = executeSqliteQueryTakeFirstSync( + database, + db + .selectFrom("memory_postbox_reviewed_copies") + .select("revision_id") + .where("item_id", "=", item.item_id) + .where("agent_id", "=", params.agentId), + ); + if (approvedCopy) { + executeSqliteQuerySync( + database, + db + .updateTable("memory_resource_revisions") + .set({ lifecycle_state: "tombstoned", retired_at: nowMs }) + .where("revision_id", "=", approvedCopy.revision_id) + .where("lifecycle_state", "=", "active"), + ); + executeSqliteQuerySync( + database, + db + .deleteFrom("memory_scoped_chunks") + .where("revision_id", "=", approvedCopy.revision_id), + ); + } + const purged = executeSqliteQuerySync( + database, + db + .updateTable("memory_postbox_items") + // A purge is one irreversible transition: never tombstone its reviewed copy unless + // this provenance row is redacted in the same transaction. + .set({ state: "purged", content: "", content_hash: "", purged_at: nowMs }) + .where("item_id", "=", item.item_id) + .where("state", "in", ["postbox", "reviewed", "rejected"]), + ); + if (purged.numAffectedRows !== 1n) { + throw new Error("memory postbox item is unavailable"); + } + return; + } + const updated = executeSqliteQuerySync( + database, + db + .updateTable("memory_postbox_items") + .set({ + state: "rejected", + reviewed_by_principal_id: operatorPrincipalId, + reviewed_at: nowMs, + }) + .where("item_id", "=", item.item_id) + .where("state", "in", ["postbox"]), + ); + if (updated.numAffectedRows !== 1n) { + throw new Error("memory postbox item is unavailable"); + } + }); + }); +} + +/** Only the authorized target owner/admin can read one pending quarantine body for review. */ +export function inspectBuiltinMemoryPostboxItem(params: { + agentId: string; + itemId: string; + operatorPrincipalId: string; +}): BuiltinMemoryPostboxInspection { + const itemId = normalize(params.itemId, "postbox item id"); + const operatorPrincipalId = normalize(params.operatorPrincipalId, "operator principal id"); + return withScopedMemoryDatabase(params.agentId, (database) => { const db = getNodeSqliteKysely(database); const item = executeSqliteQueryTakeFirstSync( database, @@ -852,42 +1457,32 @@ export function reviewBuiltinMemoryPostboxItem(params: { .innerJoin("memory_stores as store", "store.store_id", "item.target_store_id") .select([ "item.item_id", + "item.content", + "item.source_channel_ref", + "item.created_at", "item.state", "item.target_store_id", "store.audience_kind", "store.audience_id", ]) - .where("item.item_id", "=", params.itemId) + .where("item.item_id", "=", itemId) .where("item.agent_id", "=", params.agentId), ); - if (!item || item.audience_kind !== "user") { + if (!item || item.state !== "postbox" || item.audience_kind !== "user") { throw new Error("memory postbox item is unavailable"); } assertStoreOperation({ agentId: params.agentId, storeId: item.target_store_id, - principalId: normalize(params.operatorPrincipalId, "operator principal id"), - audience: { kind: item.audience_kind, id: item.audience_id }, + principalId: operatorPrincipalId, + audience: { kind: "user", id: item.audience_id }, operation: "policy-admin", }); - const state = - params.decision === "approve" - ? "reviewed" - : params.decision === "reject" - ? "rejected" - : "purged"; - executeSqliteQuerySync( - database, - db - .updateTable("memory_postbox_items") - .set({ - state, - reviewed_by_principal_id: normalize(params.operatorPrincipalId, "operator principal id"), - reviewed_at: nowMs, - ...(state === "purged" ? { purged_at: nowMs } : {}), - }) - .where("item_id", "=", item.item_id) - .where("state", "=", "postbox"), - ); + return Object.freeze({ + itemId: item.item_id, + content: item.content, + sourceChannelRef: item.source_channel_ref, + createdAt: item.created_at, + }); }); } diff --git a/extensions/memory-wiki/src/bridge.test.ts b/extensions/memory-wiki/src/bridge.test.ts index c657ed4fb34a..afe4952ee4e7 100644 --- a/extensions/memory-wiki/src/bridge.test.ts +++ b/extensions/memory-wiki/src/bridge.test.ts @@ -12,7 +12,9 @@ import type { OpenClawConfig } from "../api.js"; import { syncMemoryWikiBridgeSources } from "./bridge.js"; import { createMemoryWikiTestHarness } from "./test-helpers.js"; -const isLegacyMemorySurfaceDisabledMock = vi.hoisted(() => vi.fn(() => false)); +const isLegacyMemorySurfaceDisabledMock = vi.hoisted(() => + vi.fn<(agentId: string) => boolean>(() => false), +); vi.mock("openclaw/plugin-sdk/memory-core-host-runtime-core", () => ({ isLegacyMemorySurfaceDisabled: isLegacyMemorySurfaceDisabledMock, diff --git a/package.json b/package.json index 6db83d34fe02..41fe04e65776 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,7 @@ "!dist/plugin-sdk/markdown-table-runtime.d.ts", "!dist/plugin-sdk/media-generation-runtime.d.ts", "!dist/plugin-sdk/memory-postbox-runtime.d.ts", + "!dist/plugin-sdk/memory-sharing-control-runtime.d.ts", "!dist/plugin-sdk/memory-core-host-embedding-registry.d.ts", "!dist/plugin-sdk/memory-core-host-engine-curated.d.ts", "!dist/plugin-sdk/memory-core-host-engine-embeddings.d.ts", @@ -1240,6 +1241,9 @@ "./plugin-sdk/memory-postbox-runtime": { "default": "./dist/plugin-sdk/memory-postbox-runtime.js" }, + "./plugin-sdk/memory-sharing-control-runtime": { + "default": "./dist/plugin-sdk/memory-sharing-control-runtime.js" + }, "./plugin-sdk/memory-core-host-embedding-registry": { "default": "./dist/plugin-sdk/memory-core-host-embedding-registry.js" }, diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index 3f19b431e7f3..958943fa744f 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -261,6 +261,7 @@ "memory-authorization", "memory-authorization-conformance", "memory-postbox-runtime", + "memory-sharing-control-runtime", "memory-core-host-embedding-registry", "memory-core-host-engine-embeddings", "memory-core-host-engine-curated", diff --git a/scripts/lib/plugin-sdk-private-local-only-subpaths.json b/scripts/lib/plugin-sdk-private-local-only-subpaths.json index 8c900b1dbe6d..a79a0cbceb18 100644 --- a/scripts/lib/plugin-sdk-private-local-only-subpaths.json +++ b/scripts/lib/plugin-sdk-private-local-only-subpaths.json @@ -64,6 +64,7 @@ "markdown-table-runtime", "media-generation-runtime", "memory-postbox-runtime", + "memory-sharing-control-runtime", "memory-core-host-embedding-registry", "memory-core-host-engine-curated", "memory-core-host-engine-embeddings", diff --git a/scripts/plugin-sdk-surface-report.mts b/scripts/plugin-sdk-surface-report.mts index c83b8b5f5851..6b143a34b0e4 100644 --- a/scripts/plugin-sdk-surface-report.mts +++ b/scripts/plugin-sdk-surface-report.mts @@ -272,7 +272,8 @@ export function readPluginSdkSurfaceBudgets(env: NodeJS.ProcessEnv = process.env // +3: add canonical coercion exports while retaining the shipped asString compatibility name. // +57: versioned serializable memory-authorization contract and reusable backend-conformance // types, capability declarations, and helpers. - 4923, + // +7: reconcile the existing public memory-authorization contract surface with this ratchet. + 4930, env, ), publicFunctionExports: readPluginSdkSurfaceBudgetEnv( diff --git a/src/agents/agent-tools.ts b/src/agents/agent-tools.ts index cadd8e212a06..6e912d26b26e 100644 --- a/src/agents/agent-tools.ts +++ b/src/agents/agent-tools.ts @@ -18,15 +18,15 @@ import type { DiagnosticTraceContext } from "../infra/diagnostic-trace-context.j import { resolveEventSessionRoutingPolicy } from "../infra/event-session-routing.js"; import { applyExecPolicyLayer } from "../infra/exec-policy.js"; import { logWarn } from "../logger.js"; -import { - MEMORY_POSTBOX_RUN_ID_BINDING, - MEMORY_POSTBOX_TURN_CAPABILITY_BINDING, -} from "../plugins/memory-postbox-tool-binding.js"; import type { PluginHookChannelContext, PluginHookToolRequesterContext, } from "../plugins/hook-types.js"; import { isMemoryIsolationCutoverAgent } from "../plugins/memory-cutover.js"; +import { + MEMORY_POSTBOX_RUN_ID_BINDING, + MEMORY_POSTBOX_TURN_CAPABILITY_BINDING, +} from "../plugins/memory-postbox-tool-binding.js"; import { resolveMemoryFlushPlan } from "../plugins/memory-state.js"; import { appendRuntimePluginToolGrant } from "../plugins/tool-grant-allowlist.js"; import type { AuthorizedMemoryReadHost, AuthorizedMemoryWriteHost } from "../plugins/tool-types.js"; @@ -413,12 +413,33 @@ type OpenClawCodingToolsOptions = { function resolvePluginToolBindings(options: OpenClawCodingToolsOptions | undefined) { const turnCapability = options?.memoryPostboxTurnCapability?.trim(); const runId = options?.runId?.trim(); + const callerBindings = options?.pluginToolBindings; + const memoryCoreBindings = callerBindings?.["memory-core"]; + const { ["memory-core"]: _callerMemoryCoreBindings, ...otherCallerBindings } = + callerBindings ?? {}; + const { + [MEMORY_POSTBOX_TURN_CAPABILITY_BINDING]: _ignoredPublicPostboxCapability, + [MEMORY_POSTBOX_RUN_ID_BINDING]: _ignoredPublicPostboxRunId, + ...safeMemoryCoreBindings + } = memoryCoreBindings ?? {}; + const inheritedBindings = + memoryCoreBindings === undefined + ? callerBindings + : { + ...otherCallerBindings, + ...(Object.keys(safeMemoryCoreBindings).length > 0 + ? { "memory-core": safeMemoryCoreBindings } + : {}), + }; if (!turnCapability || !runId) { - return options?.pluginToolBindings; + return inheritedBindings; } + // Gateway-provided plugin bindings are serializable request input. Only the runner may inject + // these reserved names, so a retained or forged token cannot manufacture the postbox tool. return { - ...options?.pluginToolBindings, + ...inheritedBindings, "memory-core": { + ...safeMemoryCoreBindings, [MEMORY_POSTBOX_TURN_CAPABILITY_BINDING]: turnCapability, [MEMORY_POSTBOX_RUN_ID_BINDING]: runId, }, diff --git a/src/agents/apply-patch.test-support.ts b/src/agents/apply-patch.test-support.ts index d6011685b447..3e91c1704517 100644 --- a/src/agents/apply-patch.test-support.ts +++ b/src/agents/apply-patch.test-support.ts @@ -1,11 +1,13 @@ import type { ApplyPatchSummary } from "./apply-patch.js"; import "./apply-patch.js"; +import type { MemoryFileMutationGuard } from "./memory-file-mutation-guard.js"; import type { SandboxFsBridge } from "./sandbox/fs-bridge.js"; type ApplyPatchOptions = { cwd: string; sandbox?: { root: string; bridge: SandboxFsBridge }; workspaceOnly?: boolean; + memoryFileMutationGuard?: MemoryFileMutationGuard; signal?: AbortSignal; }; diff --git a/src/agents/embedded-agent-runner/compact.hooks.harness.ts b/src/agents/embedded-agent-runner/compact.hooks.harness.ts index 43a60fcc94dc..61a799033577 100644 --- a/src/agents/embedded-agent-runner/compact.hooks.harness.ts +++ b/src/agents/embedded-agent-runner/compact.hooks.harness.ts @@ -42,10 +42,16 @@ export const contextEngineCompactMock = vi.fn(async () => ({ })); export const isMemoryIsolationCutoverAgentMock = vi.fn(() => false); -export const readAuthorizedTranscriptDerivationMock = vi.fn(() => undefined); +export const readAuthorizedTranscriptDerivationMock = vi.fn< + typeof import("../../config/sessions/session-transcript-memory-policy.js").readAuthorizedTranscriptDerivation +>(() => undefined); export const admitAuthorizedMemoryDerivationMock = vi.fn(async () => true); -export const createAuthorizedMemoryDerivationHostMock = vi.fn(() => undefined); -export const prepareAuthorizedSealedCompactionHostMock = vi.fn(async () => undefined); +export const createAuthorizedMemoryDerivationHostMock = vi.fn< + typeof import("../memory-authorized-read-host.js").createAuthorizedMemoryDerivationHost +>(() => undefined); +export const prepareAuthorizedSealedCompactionHostMock = vi.fn< + typeof import("../memory-authorized-read-host.js").prepareAuthorizedSealedCompactionHost +>(async () => undefined); export const hookRunner = { hasHooks: vi.fn<(hookName?: string) => boolean>(), diff --git a/src/agents/embedded-agent-runner/run/attempt-setup.test.ts b/src/agents/embedded-agent-runner/run/attempt-setup.test.ts index aa4a31620269..0c5912677c2e 100644 --- a/src/agents/embedded-agent-runner/run/attempt-setup.test.ts +++ b/src/agents/embedded-agent-runner/run/attempt-setup.test.ts @@ -5,7 +5,7 @@ import type { ProviderRuntimePluginHandle } from "../../../plugins/provider-hook import type { EmbeddedRunAttemptParams } from "./types.js"; const resolveProviderRuntimePluginHandle = vi.hoisted(() => vi.fn()); -const resolveSandboxContext = vi.hoisted(() => vi.fn(async () => null)); +const resolveSandboxContext = vi.hoisted(() => vi.fn()); const createAuthorizedMemoryReadHost = vi.hoisted(() => vi.fn()); const resolveAuthorizedMemoryVirtualFileBroker = vi.hoisted(() => vi.fn()); const stageAuthorizedVirtualProjectionMountPlan = vi.hoisted(() => vi.fn()); diff --git a/src/agents/sandbox/authorized-memory-projection-isolation.docker.test.ts b/src/agents/sandbox/authorized-memory-projection-isolation.docker.test.ts index 3341f28624d1..c2f66f094e5d 100644 --- a/src/agents/sandbox/authorized-memory-projection-isolation.docker.test.ts +++ b/src/agents/sandbox/authorized-memory-projection-isolation.docker.test.ts @@ -119,7 +119,7 @@ test.runIf(dockerAvailable)( const { execDocker } = await import("./docker.js"); const inspected = await execDocker(["inspect", runtimeId]); - const mounts = JSON.parse(inspected.stdout.toString("utf8")) as Array<{ + const mounts = JSON.parse(inspected.stdout) as Array<{ Mounts?: Array<{ Destination?: string; Source?: string; RW?: boolean }>; }>; expect(mounts[0]?.Mounts).toContainEqual( diff --git a/src/agents/sandbox/authorized-virtual-projection-staging.test.ts b/src/agents/sandbox/authorized-virtual-projection-staging.test.ts index 67275ca75bd8..a35d1b43b0d4 100644 --- a/src/agents/sandbox/authorized-virtual-projection-staging.test.ts +++ b/src/agents/sandbox/authorized-virtual-projection-staging.test.ts @@ -7,7 +7,10 @@ import { resolveAuthorizedVirtualProjectionRoot, resolveAuthorizedVirtualProjectionSourcePath, } from "./authorized-virtual-projection-mounts.js"; -import { stageAuthorizedVirtualProjectionMountPlan } from "./authorized-virtual-projection-staging.js"; +import { + stageAuthorizedVirtualProjectionMountPlan, + type AuthorizedVirtualProjectionBroker, +} from "./authorized-virtual-projection-staging.js"; const tmpDirs: string[] = []; @@ -17,7 +20,10 @@ function makeTempDir(): string { return dir; } -function createBroker(readFile = vi.fn(async (virtualPath: string) => `contents:${virtualPath}`)) { +function createBroker( + readFile: AuthorizedVirtualProjectionBroker["readFile"] = async (virtualPath) => + `contents:${virtualPath}`, +) { return { view: { version: 1 as const, @@ -45,7 +51,7 @@ function createBroker(readFile = vi.fn(async (virtualPath: string) => `contents: ], expiresAt: "2099-01-01T00:00:00.000Z", }, - readFile, + readFile: vi.fn(readFile), }; } diff --git a/src/auto-reply/dispatch.memory-egress.test.ts b/src/auto-reply/dispatch.memory-egress.test.ts index 389836a10813..8028c776e6dd 100644 --- a/src/auto-reply/dispatch.memory-egress.test.ts +++ b/src/auto-reply/dispatch.memory-egress.test.ts @@ -57,7 +57,6 @@ function allowedFinalAdmission(): MemoryEgressAdmission { capabilityId: "reply.final", agentId: "memory-agent", sessionId: "session-1", - sessionKey: "agent:memory-agent:direct:alice", runId: "run-1", deliveryRevision: "delivery-1", egressRegistryRevision: "registry-1", @@ -72,7 +71,6 @@ describe("memory egress at final dispatch", () => { const dispatcher = createReplyDispatcher({ deliver: delivered }); const ctx = buildTestCtx({ AgentId: "memory-agent", - SessionId: "session-1", SessionKey: "agent:memory-agent:direct:alice", Surface: "telegram", OriginatingChannel: "telegram", diff --git a/src/auto-reply/reply/agent-runner-embedded-candidate.ts b/src/auto-reply/reply/agent-runner-embedded-candidate.ts index 971fbb888e57..2c2322e76092 100644 --- a/src/auto-reply/reply/agent-runner-embedded-candidate.ts +++ b/src/auto-reply/reply/agent-runner-embedded-candidate.ts @@ -14,17 +14,16 @@ import { } from "../../agents/run-termination.js"; import { resolveGroupSessionKey } from "../../config/sessions.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; +import { + mintMemoryPostboxTurnCapability, + revokeMemoryPostboxTurnCapability, +} from "../../gateway/memory-postbox-turn-capability.js"; import { isTrustedMessageActionTurnIngress, mintMessageActionTurnCapability, resolveMessageActionTurnCapabilityLifetime, revokeMessageActionTurnCapability, } from "../../gateway/message-action-turn-capability.js"; -import { - mintMemoryPostboxTurnCapability, - resolveMemoryPostboxTargetPrincipal, - revokeMemoryPostboxTurnCapability, -} from "../../gateway/memory-postbox-turn-capability.js"; import { logVerbose } from "../../globals.js"; import { isMarkdownCapableMessageChannel, @@ -176,34 +175,19 @@ export async function runEmbeddedFallbackCandidate(params: { ...resolveMessageActionTurnCapabilityLifetime(runBaseParams.timeoutMs), }) : undefined; - const memoryPostboxTargetPrincipal = - embeddedContext.agentId && messageActionCapabilitySessionKey && embeddedContext.sessionId - ? resolveMemoryPostboxTargetPrincipal({ - agentId: embeddedContext.agentId, - sessionKey: messageActionCapabilitySessionKey, - sessionId: embeddedContext.sessionId, - }) - : undefined; const memoryPostboxTurnCapability = isTrustedMessageActionTurnIngress(turn.sessionCtx.Provider) && !turn.isHeartbeat && embeddedContext.agentId && messageActionCapabilitySessionKey && embeddedContext.sessionId && - embeddedContext.messageProvider && - embeddedContext.currentChannelId && - embeddedContext.currentMessageId !== undefined && - senderContext.senderId && - memoryPostboxTargetPrincipal + embeddedContext.currentSourceTurnId ? mintMemoryPostboxTurnCapability({ agentId: embeddedContext.agentId, runId: params.runId, sessionKey: messageActionCapabilitySessionKey, sessionId: embeddedContext.sessionId, - sourceChannelRef: `${embeddedContext.messageProvider}:${embeddedContext.currentChannelId}`, - sourceMessageRef: String(embeddedContext.currentMessageId), - senderEvidenceRef: `${embeddedContext.messageProvider}:${senderContext.senderId}`, - targetPrincipalId: memoryPostboxTargetPrincipal, + sourceContext: turn.sessionCtx, ...resolveMessageActionTurnCapabilityLifetime(runBaseParams.timeoutMs), }) : undefined; diff --git a/src/auto-reply/reply/get-reply-run-execute.ts b/src/auto-reply/reply/get-reply-run-execute.ts index 4e91497a1f05..f9cce6321456 100644 --- a/src/auto-reply/reply/get-reply-run-execute.ts +++ b/src/auto-reply/reply/get-reply-run-execute.ts @@ -8,6 +8,7 @@ import { runAgentHarnessBeforeMessageWriteHook } from "../../agents/harness/hook import { resolveOwnerPromptNumbers } from "../../agents/owner-display.js"; import { conversationIdentityFromMsgContext } from "../../config/sessions/conversation-identity.js"; import { resolveGroupSessionKey } from "../../config/sessions/group.js"; +import { admitMemoryPostboxTurnIngress } from "../../gateway/memory-postbox-turn-capability.js"; import { normalizeMediaFacts } from "../../media/media-facts.js"; import { MEDIA_ONLY_USER_TEXT } from "../../sessions/user-turn-media.js"; import { @@ -178,6 +179,7 @@ export async function executePreparedReplyRun(state: PreparedReplyRunAdmission) const sourceMessageId = normalizeOptionalString(sessionCtx.MessageSidFull) ?? normalizeOptionalString(sessionCtx.MessageSid); + const inputProvenance = ctx.InputProvenance ?? sessionCtx.InputProvenance; const sourceTurnId = readChannelSourceTurnId(sessionCtx) ?? (shouldMintChannelSourceTurnId(ctx.Provider ?? ctx.Surface ?? promptSessionCtx.Provider) @@ -189,6 +191,24 @@ export async function executePreparedReplyRun(state: PreparedReplyRunAdmission) }) : undefined); setChannelSourceTurnId(sessionCtx, sourceTurnId); + const senderEvidenceRef = normalizeOptionalString(ctx.SenderId); + const sourceChannelRef = + sourceTurnId && messageProvider && replyRoute.accountId && replyRoute.to + ? `${messageProvider}:${replyRoute.accountId}:${replyRoute.to}` + : undefined; + admitMemoryPostboxTurnIngress({ + context: sessionCtx, + agentId, + // The embedded runner redeems against the runtime-policy key when one is present. + // Bind admission to that same key so an alias cannot transplant this ingress record. + sessionKey: runtimePolicySessionKey ?? sessionKey ?? preparedSessionState.sessionId, + sessionId: preparedSessionState.sessionId, + provider: ctx.Provider ?? ctx.Surface ?? promptSessionCtx.Provider, + inputProvenance, + sourceTurnId, + sourceChannelRef, + senderEvidenceRef, + }); const persistGroupSender = replyRoute.chatType === "group" || replyRoute.chatType === "channel"; const ctxMediaForPersistence = normalizeMediaFacts(ctx.media); const userTurnMediaForPersistence = [...ctxMediaForPersistence, ...(opts?.media ?? [])]; @@ -199,7 +219,6 @@ export async function executePreparedReplyRun(state: PreparedReplyRunAdmission) imageOrder: currentTurnImages.imageOrder, imageSourceIndexes: currentTurnImages.imageSourceIndexes, }); - const inputProvenance = ctx.InputProvenance ?? sessionCtx.InputProvenance; const userTurnTimestamp = normalizeMessageTimestampMs(ctx.Timestamp); // prompt-prelude substitutes MEDIA_ONLY_USER_TEXT as transcriptBody for // bodyless turns; storage stays bare (the LLM boundary re-injects it), while diff --git a/src/auto-reply/reply/get-reply-run.media-only.test.ts b/src/auto-reply/reply/get-reply-run.media-only.test.ts index 062f4ed69329..df6540ec5466 100644 --- a/src/auto-reply/reply/get-reply-run.media-only.test.ts +++ b/src/auto-reply/reply/get-reply-run.media-only.test.ts @@ -8,7 +8,13 @@ import { clearActiveEmbeddedRun, setActiveEmbeddedRun, } from "../../agents/embedded-agent-runner/runs.js"; +import { buildChannelInboundEventContext } from "../../channels/inbound-event/context.js"; import type { SessionEntry } from "../../config/sessions.js"; +import { + mintMemoryPostboxTurnCapability, + resetMemoryPostboxTurnCapabilitiesForTest, + resolveMemoryPostboxTurnCapability, +} from "../../gateway/memory-postbox-turn-capability.js"; import { withSystemEventOwner } from "../../infra/system-event-ownership.js"; import { enqueueSystemEvent, @@ -67,6 +73,7 @@ vi.mock("../../config/sessions/paths.js", () => ({ const loadSessionEntryMock = vi.hoisted(() => vi.fn()); const updateAmbientTranscriptWatermarkMock = vi.hoisted(() => vi.fn().mockResolvedValue(null)); +const createCurrentMemorySessionContextMock = vi.hoisted(() => vi.fn()); vi.mock("../../config/sessions/session-accessor.js", () => ({ listSessionEntries: vi.fn().mockReturnValue([]), @@ -79,6 +86,10 @@ vi.mock("../../config/sessions/ambient-transcript-watermark.js", () => ({ updateAmbientTranscriptWatermark: updateAmbientTranscriptWatermarkMock, })); +vi.mock("../../state/memory-session-subject.js", () => ({ + createCurrentMemorySessionContext: createCurrentMemorySessionContextMock, +})); + vi.mock("../../globals.js", () => ({ logVerbose: vi.fn(), })); @@ -356,11 +367,21 @@ describe("runPreparedReply media-only handling", () => { vi.mocked(resolveInboundUserContextPromptJoiner).mockReturnValue(undefined); vi.mocked(hasControlCommand).mockReturnValue(false); replyRunTesting.resetReplyRunRegistry(); + resetMemoryPostboxTurnCapabilitiesForTest(); + createCurrentMemorySessionContextMock.mockReturnValue({ + kind: "current", + context: { + subject: { kind: "user" }, + principalId: "principal-alice", + fingerprint: "alice-session-fingerprint", + }, + }); }); afterEach(() => { vi.useRealTimers(); resetSystemEventsForTest(); + resetMemoryPostboxTurnCapabilitiesForTest(); const paths = cleanupPaths.splice(0); return Promise.all(paths.map((entry) => rm(entry, { recursive: true, force: true }))); }); @@ -381,6 +402,99 @@ describe("runPreparedReply media-only handling", () => { }); }); + it.each([ + { name: "native external channel input", inputProvenance: undefined, expected: true }, + { + name: "synthetic channel reflection", + inputProvenance: { + kind: "internal_system" as const, + sourceTool: "channel_feedback_reflection", + }, + expected: false, + }, + { + name: "restart continuation", + inputProvenance: { kind: "internal_system" as const, sourceTool: "restart-sentinel" }, + expected: false, + }, + ])("admits a postbox source only for $name", async ({ inputProvenance, expected }) => { + const inbound = buildChannelInboundEventContext({ + channel: "telegram", + accountId: "default", + provider: "telegram", + messageId: "message-postbox-ingress", + from: "telegram:alice", + sender: { id: "alice" }, + conversation: { kind: "direct", id: "alice" }, + route: { + agentId: "main", + routeSessionKey: "agent:main:telegram:direct:alice", + }, + reply: { to: "telegram:alice", originatingTo: "telegram:alice" }, + message: { body: "remember this", rawBody: "remember this" }, + ...(inputProvenance ? { inputProvenance } : {}), + }); + let token: string | undefined; + let runIdentity: { agentId: string; sessionKey: string; sessionId: string } | undefined; + vi.mocked(runReplyAgent).mockImplementationOnce(async (params) => { + const run = params.followupRun.run; + const sessionKey = params.runtimePolicySessionKey ?? params.sessionKey ?? run.sessionId; + runIdentity = { agentId: run.agentId, sessionKey, sessionId: run.sessionId }; + token = mintMemoryPostboxTurnCapability({ + agentId: run.agentId, + runId: "postbox-ingress-composition", + sessionKey, + sessionId: run.sessionId, + sourceContext: params.sessionCtx, + }); + return { text: "ok" }; + }); + + await runPrepared({ + ctx: inbound, + sessionCtx: inbound, + agentId: "main", + sessionId: "session-postbox-ingress", + sessionKey: "agent:main:telegram:direct:alice", + command: { + surface: "telegram", + channel: "telegram", + isAuthorizedSender: true, + abortKey: "agent:main:telegram:direct:alice", + ownerList: [], + senderIsOwner: false, + rawBodyNormalized: "remember this", + commandBodyNormalized: "remember this", + } as never, + }); + + if (!expected) { + expect(token).toBeUndefined(); + return; + } + expect(token).toEqual(expect.any(String)); + expect(runIdentity).toBeDefined(); + expect( + resolveMemoryPostboxTurnCapability({ + token, + agentId: runIdentity!.agentId, + runId: "postbox-ingress-composition", + sessionKey: runIdentity!.sessionKey, + sessionId: runIdentity!.sessionId, + }), + ).toEqual({ + sourceTurnId: buildChannelSourceTurnId({ + provider: "telegram", + accountId: "default", + conversationId: "telegram:alice", + messageId: "message-postbox-ingress", + }), + sourceChannelRef: "telegram:default:telegram:alice", + senderEvidenceRef: "alice", + targetPrincipalId: "principal-alice", + }); + }); + it("includes current exec overrides in the queued runner prompt", async () => { await runPrepared({ execOverrides: { diff --git a/src/auto-reply/reply/source-turn-id.test.ts b/src/auto-reply/reply/source-turn-id.test.ts index dc8aba2ebb47..0b9f339a2e0c 100644 --- a/src/auto-reply/reply/source-turn-id.test.ts +++ b/src/auto-reply/reply/source-turn-id.test.ts @@ -69,6 +69,7 @@ describe("buildChannelSourceTurnId", () => { expect(readChannelSourceTurnSameThreadRequired({ ...context })).toBe(true); expect(JSON.stringify(context)).toBe('{"MessageSid":"7"}'); }); + it("does not mint channel source-turn ids for internal-origin ingress", () => { // Gateway chat.send stamps the internal channel as the ingress provider and // keys the persisted user turn by run id; minting a channel id there would diff --git a/src/channels/direct-dm.ts b/src/channels/direct-dm.ts index 1a79e9dc2520..c3bd42564fc4 100644 --- a/src/channels/direct-dm.ts +++ b/src/channels/direct-dm.ts @@ -205,6 +205,9 @@ export async function dispatchInboundDirectDmWithRuntime( OriginatingTo: params.originatingTo ?? params.recipientAddress, NativeDirectUserId: params.peer.id, ...params.extraContext, + // This legacy facade is still a native channel ingress boundary. Do not let an adapter-provided + // context relabel a user message as an internal continuation before postbox admission. + InputProvenance: { kind: "external_user", sourceChannel: params.channel }, }); const plan = buildDirectDmTurnPlan(params, route, ctxPayload); await params.runtime.channel.inbound.run({ diff --git a/src/channels/feedback-reflection.ts b/src/channels/feedback-reflection.ts index eec175fcf4b2..b72e866ad8ee 100644 --- a/src/channels/feedback-reflection.ts +++ b/src/channels/feedback-reflection.ts @@ -148,6 +148,7 @@ export async function runChannelFeedbackReflection(params: { }, reply: { to: target, originatingTo: target }, message: { body, bodyForAgent: prompt, rawBody: prompt, commandBody: prompt }, + inputProvenance: { kind: "internal_system", sourceTool: "channel_feedback_reflection" }, access: { commands: { authorized: false } }, }); const responses: string[] = []; diff --git a/src/channels/inbound-event/context.test.ts b/src/channels/inbound-event/context.test.ts index 3d5f92475b7b..4077ff685fb7 100644 --- a/src/channels/inbound-event/context.test.ts +++ b/src/channels/inbound-event/context.test.ts @@ -108,6 +108,18 @@ describe("resolveInboundSupplementalSenderAllowed", () => { }); describe("buildChannelInboundEventContext", () => { + it("records native channel messages as external-user ingress and preserves synthetic provenance", () => { + expect(buildTestInboundEventContext().InputProvenance).toEqual({ + kind: "external_user", + sourceChannel: "test", + }); + expect( + buildTestInboundEventContext({ + inputProvenance: { kind: "internal_system", sourceTool: "channel_feedback_reflection" }, + }).InputProvenance, + ).toEqual({ kind: "internal_system", sourceTool: "channel_feedback_reflection" }); + }); + it("maps normalized inbound facts into a finalized message context", async () => { const ctx = buildChannelInboundEventContext({ channel: "test", diff --git a/src/channels/inbound-event/context.ts b/src/channels/inbound-event/context.ts index 7f78ebeb0ece..92282e915ed1 100644 --- a/src/channels/inbound-event/context.ts +++ b/src/channels/inbound-event/context.ts @@ -23,6 +23,7 @@ import type { ContextVisibilityMode } from "../../config/types.base.js"; import type { GroupToolPolicyConfig } from "../../config/types.tools.js"; import type { PluginHookChannelContext } from "../../plugins/hook-channel-context.types.js"; import { shouldIncludeSupplementalContext } from "../../security/context-visibility.js"; +import type { InputProvenance } from "../../sessions/input-provenance.js"; import type { InboundImplicitMentionKind } from "../mention-gating.js"; import type { ChannelIngressCommandAccess } from "../message-access/runtime-types.js"; import type { @@ -98,6 +99,8 @@ export type BuildChannelInboundEventContextParams = { supplemental?: ChannelInboundSupplementalFacts; channelContext?: PluginHookChannelContext; contextVisibility?: ContextVisibilityMode; + /** Trusted source classification for synthetic channel events; native channel messages default external. */ + inputProvenance?: InputProvenance; finalize?: FinalizeInboundContextFn; finalizeOptions?: FinalizeInboundContextOptions; extra?: Record; @@ -548,10 +551,14 @@ export function buildChannelInboundEventContext( OriginatingChannel: params.channel, OriginatingTo: params.reply.originatingTo ?? params.reply.to, ThreadParentId: params.reply.threadParentId ?? params.conversation.parentId, - // This builder is the post-admission boundary for channel events. Preserve - // that fact so interceptors cannot bypass sender, route, or pairing gates. + // This builder is the post-admission boundary for channel events. Native messages are + // external-user input; synthetic owners must classify themselves before dispatch. InboundAccessAuthorized: true, ...params.extra, + InputProvenance: params.inputProvenance ?? { + kind: "external_user" as const, + sourceChannel: params.channel, + }, }; const finalizeParams = { finalize: params.finalize, diff --git a/src/commands/doctor-memory-isolation.test.ts b/src/commands/doctor-memory-isolation.test.ts index ca8bb74bc17c..c0d0eaa67e55 100644 --- a/src/commands/doctor-memory-isolation.test.ts +++ b/src/commands/doctor-memory-isolation.test.ts @@ -2,6 +2,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import type { OpenClawConfig } from "../config/types.openclaw.js"; import { resetMemoryIsolationCutoverForTest } from "../plugins/memory-cutover.js"; import { closeOpenClawAgentDatabasesForTest, @@ -11,9 +12,9 @@ import { runDoctorMemoryIsolation } from "./doctor-memory-isolation.js"; describe("runDoctorMemoryIsolation", () => { let stateDir = ""; - const cfg = { + const cfg: OpenClawConfig = { agents: { list: [{ id: "main", default: true }, { id: "support" }] }, - } as const; + }; beforeEach(() => { stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-doctor-memory-isolation-")); diff --git a/src/config/sessions/session-accessor.sqlite-archive.worker.test.ts b/src/config/sessions/session-accessor.sqlite-archive.worker.test.ts index 7bb9e80615a3..54306440c6a7 100644 --- a/src/config/sessions/session-accessor.sqlite-archive.worker.test.ts +++ b/src/config/sessions/session-accessor.sqlite-archive.worker.test.ts @@ -203,7 +203,9 @@ describe("SQLite transcript archive worker", () => { const legacyArchive = materializeSqliteTranscriptArchiveInWorker( planArchiveWorker(database, path.dirname(storePath), legacySessionId), ); - expect(readArchiveLines(legacyArchive.archivedPath)).toEqual([JSON.stringify(legacyEvent)]); + const legacyArchivePath = legacyArchive.archivedPath; + expect(legacyArchivePath).not.toBeNull(); + expect(readArchiveLines(legacyArchivePath ?? undefined)).toEqual([JSON.stringify(legacyEvent)]); const sessionId = "enforced-policy-archive-session"; const sessionKey = "agent:main:enforced-policy-archive"; @@ -215,7 +217,9 @@ describe("SQLite transcript archive worker", () => { const archive = materializeSqliteTranscriptArchiveInWorker( planArchiveWorker(database, path.dirname(storePath), sessionId), ); - const lines = readArchiveLines(archive.archivedPath); + const archivePath = archive.archivedPath; + expect(archivePath).not.toBeNull(); + const lines = readArchiveLines(archivePath ?? undefined); expect(lines).toHaveLength(2); expect(lines[0]).toBe(JSON.stringify(event)); expect(JSON.parse(lines[1] ?? "")).toMatchObject({ @@ -272,7 +276,7 @@ describe("SQLite transcript archive worker", () => { { agentId: database.agentId, path: database.path }, ); expect(readAuthorizedTranscriptEventSeqs(database.db, sessionId)).toEqual(new Set([eventSeq])); - expect(readArchiveLines(archive.archivedPath)).toHaveLength(2); + expect(readArchiveLines(archivePath ?? undefined)).toHaveLength(2); }); it("restores a confirmed archive only through its original immutable session subject", async () => { diff --git a/src/config/sessions/session-transcript-memory-policy.test.ts b/src/config/sessions/session-transcript-memory-policy.test.ts index ff9b550fa0c4..a89b10fcdbd5 100644 --- a/src/config/sessions/session-transcript-memory-policy.test.ts +++ b/src/config/sessions/session-transcript-memory-policy.test.ts @@ -1,6 +1,7 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; +import { expectDefined } from "@openclaw/normalization-core"; import { afterEach, describe, expect, it, vi } from "vitest"; import { runDoctorMemoryIsolation } from "../../commands/doctor-memory-isolation.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; @@ -363,6 +364,10 @@ describe("transcript memory policy companions", () => { if (!source) { throw new Error("fixture expected an authorized compaction source"); } + const sourceEventSeq = expectDefined( + source.eventSeqs[0], + "authorized compaction source event at index zero", + ); const sourceCompanion = database.db .prepare( `SELECT policy.run_id, detail.source_event_seq @@ -371,7 +376,7 @@ describe("transcript memory policy companions", () => { ON detail.session_id = policy.session_id AND detail.event_seq = policy.event_seq WHERE policy.session_id = ? AND policy.event_seq = ?`, ) - .get(SESSION_ID, source.eventSeqs[0]); + .get(SESSION_ID, sourceEventSeq); let committed: { eventSeq: number; policyId: string } | undefined; const commit = async () => await withOwnedSessionTranscriptWrites( @@ -421,6 +426,10 @@ describe("transcript memory policy companions", () => { compactionPolicy: { compactionPolicyId: "sealed-compaction-policy" }, }); expect(committed).toEqual({ eventSeq: expect.any(Number), policyId: "sealed-compaction-policy" }); + const committedEventSeq = expectDefined( + committed?.eventSeq, + "committed sealed compaction event sequence", + ); expect( readSessionEntryRow(database, SESSION_KEY)?.entry.compactionCheckpoints?.map( (checkpoint) => checkpoint.checkpointId, @@ -456,7 +465,7 @@ describe("transcript memory policy companions", () => { ON detail.session_id = policy.session_id AND detail.event_seq = policy.event_seq WHERE policy.session_id = ? AND policy.event_seq = ?`, ) - .get(SESSION_ID, committed?.eventSeq), + .get(SESSION_ID, committedEventSeq), ).toEqual(sourceCompanion); expect( loadSqliteTranscriptEventsSync(scope(env)).some( diff --git a/src/config/sessions/session-transcript-memory-policy.ts b/src/config/sessions/session-transcript-memory-policy.ts index 53306ac7ce2f..f6e36b4922d7 100644 --- a/src/config/sessions/session-transcript-memory-policy.ts +++ b/src/config/sessions/session-transcript-memory-policy.ts @@ -19,6 +19,7 @@ type TranscriptMemoryPolicyDatabase = Pick< | "memory_policy_set_members" | "memory_policy_sets" | "memory_compaction_policies" + | "memory_compaction_policy_sources" | "memory_resource_revisions" | "memory_run_exposure_resources" | "memory_run_exposures" diff --git a/src/gateway/memory-postbox-turn-capability.test.ts b/src/gateway/memory-postbox-turn-capability.test.ts index 971dd6b1ea7d..366dc212e37d 100644 --- a/src/gateway/memory-postbox-turn-capability.test.ts +++ b/src/gateway/memory-postbox-turn-capability.test.ts @@ -7,6 +7,7 @@ vi.mock("../state/memory-session-subject.js", () => ({ })); import { + admitMemoryPostboxTurnIngress, mintMemoryPostboxTurnCapability, resetMemoryPostboxTurnCapabilitiesForTest, resolveMemoryPostboxTurnCapability, @@ -20,16 +21,41 @@ describe("memory postbox turn capability", () => { sessionContextMock.mockReset(); }); + function admittedUserContext() { + return { + kind: "current" as const, + context: { + subject: { kind: "user" as const }, + principalId: "principal-alice", + fingerprint: "current-user-fingerprint", + }, + }; + } + + function sourceContext(sourceTurnId = "channel-user:v1:source-1") { + const context = {}; + admitMemoryPostboxTurnIngress({ + context, + agentId: "main", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + provider: "telegram", + inputProvenance: { kind: "external_user" }, + sourceTurnId, + sourceChannelRef: "telegram:account:team", + senderEvidenceRef: "telegram:sender-alice", + }); + return context; + } + it("binds trusted source evidence to one live agent run and session", () => { + sessionContextMock.mockReturnValue(admittedUserContext()); const token = mintMemoryPostboxTurnCapability({ agentId: "main", runId: "run-1", sessionKey: "agent:main:group:team", sessionId: "session-1", - sourceChannelRef: "telegram:team", - sourceMessageRef: "message-1", - senderEvidenceRef: "sender-evidence-1", - targetPrincipalId: "principal-alice", + sourceContext: sourceContext(), nowMs: 100, ttlMs: 1_000, }); @@ -44,18 +70,40 @@ describe("memory postbox turn capability", () => { nowMs: 101, }), ).toEqual({ - sourceChannelRef: "telegram:team", - sourceMessageRef: "message-1", - senderEvidenceRef: "sender-evidence-1", + sourceTurnId: "channel-user:v1:source-1", + sourceChannelRef: "telegram:account:team", + senderEvidenceRef: "telegram:sender-alice", targetPrincipalId: "principal-alice", }); for (const mismatch of [ - { agentId: "other", runId: "run-1", sessionKey: "agent:main:group:team", sessionId: "session-1" }, - { agentId: "main", runId: "run-2", sessionKey: "agent:main:group:team", sessionId: "session-1" }, - { agentId: "main", runId: "run-1", sessionKey: "agent:main:group:other", sessionId: "session-1" }, - { agentId: "main", runId: "run-1", sessionKey: "agent:main:group:team", sessionId: "session-2" }, + { + agentId: "other", + runId: "run-1", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + }, + { + agentId: "main", + runId: "run-2", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + }, + { + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:group:other", + sessionId: "session-1", + }, + { + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:group:team", + sessionId: "session-2", + }, ]) { - expect(resolveMemoryPostboxTurnCapability({ token, ...mismatch, nowMs: 101 })).toBeUndefined(); + expect( + resolveMemoryPostboxTurnCapability({ token, ...mismatch, nowMs: 101 }), + ).toBeUndefined(); } expect( resolveMemoryPostboxTurnCapability({ @@ -70,14 +118,13 @@ describe("memory postbox turn capability", () => { }); it("cannot be redeemed after explicit terminal revocation", () => { + sessionContextMock.mockReturnValue(admittedUserContext()); const token = mintMemoryPostboxTurnCapability({ agentId: "main", runId: "run-1", sessionKey: "agent:main:group:team", - sourceChannelRef: "telegram:team", - sourceMessageRef: "message-1", - senderEvidenceRef: "sender-evidence-1", - targetPrincipalId: "principal-alice", + sessionId: "session-1", + sourceContext: sourceContext(), }); expect(revokeMemoryPostboxTurnCapability(token)).toBe(true); expect( @@ -86,15 +133,144 @@ describe("memory postbox turn capability", () => { agentId: "main", runId: "run-1", sessionKey: "agent:main:group:team", + sessionId: "session-1", + }), + ).toBeUndefined(); + }); + + it("requires a private ingress source marker and rechecks the current user subject", () => { + sessionContextMock.mockReturnValue(admittedUserContext()); + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:direct:alice", + sessionId: "session-1", + sourceContext: {}, + }), + ).toBeUndefined(); + + const source = {}; + admitMemoryPostboxTurnIngress({ + context: source, + agentId: "main", + sessionKey: "agent:main:direct:alice", + sessionId: "session-1", + provider: "telegram", + inputProvenance: { kind: "external_user" }, + sourceTurnId: "channel-user:v1:direct-alice", + sourceChannelRef: "telegram:account:alice", + senderEvidenceRef: "telegram:sender-alice", + }); + const token = mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:direct:alice", + sessionId: "session-1", + sourceContext: source, + }); + expect(token).toEqual(expect.any(String)); + sessionContextMock.mockReturnValue({ + kind: "current", + context: { + subject: { kind: "user" }, + principalId: "principal-alice", + fingerprint: "rebound-user-fingerprint", + }, + }); + + expect( + resolveMemoryPostboxTurnCapability({ + token, + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:direct:alice", + sessionId: "session-1", + }), + ).toBeUndefined(); + }); + + it("binds provenance to the exact admitted external-user context and session", () => { + sessionContextMock.mockReturnValue(admittedUserContext()); + const source = sourceContext(); + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-1", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + sourceContext: source, + }), + ).toEqual(expect.any(String)); + + for (const context of [{ ...source }, {}]) { + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-2", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + sourceContext: context, + }), + ).toBeUndefined(); + } + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-2", + sessionKey: "agent:main:direct:alice", + sessionId: "session-1", + sourceContext: source, + }), + ).toBeUndefined(); + + const internal = {}; + admitMemoryPostboxTurnIngress({ + context: internal, + agentId: "main", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + provider: "telegram", + inputProvenance: { kind: "internal_system", sourceTool: "restart-sentinel" }, + sourceTurnId: "channel-user:v1:restarted", + sourceChannelRef: "telegram:account:team", + senderEvidenceRef: "telegram:sender-alice", + }); + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-3", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + sourceContext: internal, + }), + ).toBeUndefined(); + + const missingProvenance = {}; + admitMemoryPostboxTurnIngress({ + context: missingProvenance, + agentId: "main", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + provider: "telegram", + inputProvenance: undefined, + sourceTurnId: "channel-user:v1:unknown-provenance", + sourceChannelRef: "telegram:account:team", + senderEvidenceRef: "telegram:sender-alice", + }); + expect( + mintMemoryPostboxTurnCapability({ + agentId: "main", + runId: "run-4", + sessionKey: "agent:main:group:team", + sessionId: "session-1", + sourceContext: missingProvenance, }), ).toBeUndefined(); }); it("selects a postbox target only from the current verified direct-user session", () => { - sessionContextMock.mockReturnValue({ - kind: "current", - context: { subject: { kind: "user" }, principalId: "principal-alice" }, - }); + sessionContextMock.mockReturnValue(admittedUserContext()); expect( resolveMemoryPostboxTargetPrincipal({ @@ -111,7 +287,11 @@ describe("memory postbox turn capability", () => { sessionContextMock.mockReturnValue({ kind: "current", - context: { subject: { kind: "conversation" }, principalId: "conversation-team" }, + context: { + subject: { kind: "conversation" }, + principalId: "conversation-team", + fingerprint: "conversation-fingerprint", + }, }); expect( resolveMemoryPostboxTargetPrincipal({ diff --git a/src/gateway/memory-postbox-turn-capability.ts b/src/gateway/memory-postbox-turn-capability.ts index 6f2459b09fc2..1dfcadf7d388 100644 --- a/src/gateway/memory-postbox-turn-capability.ts +++ b/src/gateway/memory-postbox-turn-capability.ts @@ -2,7 +2,9 @@ import { randomBytes } from "node:crypto"; import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce"; import { pruneMapToMaxSize } from "../infra/map-size.js"; import { normalizeAgentId } from "../routing/session-key.js"; +import type { InputProvenance } from "../sessions/input-provenance.js"; import { createCurrentMemorySessionContext } from "../state/memory-session-subject.js"; +import { isTrustedMessageActionTurnIngress } from "./message-action-turn-capability.js"; const DEFAULT_TTL_MS = 15 * 60_000; const MAX_TTL_MS = 24 * 60 * 60_000; @@ -13,23 +15,35 @@ type MemoryPostboxTurnCapability = Readonly<{ agentId: string; runId: string; sessionKey: string; - sessionId?: string; + sessionId: string; + sourceTurnId: string; sourceChannelRef: string; - sourceMessageRef: string; senderEvidenceRef: string; targetPrincipalId: string; + sessionContextFingerprint: string; expiresAtMs: number; }>; export type ResolvedMemoryPostboxSource = Readonly<{ + /** Opaque, account-and-conversation-scoped identity minted at trusted channel ingress. */ + sourceTurnId: string; sourceChannelRef: string; - sourceMessageRef: string; senderEvidenceRef: string; /** The core-selected private subject whose quarantine receives this source. */ targetPrincipalId: string; }>; const capabilitiesByToken = new Map(); +const admittedIngressByContext = new WeakMap(); + +type AdmittedMemoryPostboxIngress = Readonly< + ResolvedMemoryPostboxSource & { + agentId: string; + sessionKey: string; + sessionId: string; + sessionContextFingerprint: string; + } +>; function resolveTtlMs(value: number | undefined): number { if (!Number.isFinite(value) || value === undefined || value <= 0) { @@ -46,6 +60,75 @@ function required(value: string | undefined, label: string): string { return normalized; } +function readCurrentUserSubject(params: { + agentId: string; + sessionKey: string; + sessionId: string; +}) { + const session = createCurrentMemorySessionContext({ + sessionKey: params.sessionKey, + sessionId: params.sessionId, + options: { agentId: params.agentId }, + }); + return session.kind === "current" && session.context.subject.kind === "user" + ? Object.freeze({ + principalId: session.context.principalId, + fingerprint: session.context.fingerprint, + }) + : undefined; +} + +/** + * Stamps one exact inbound context after channel routing has selected both the source message and + * the current user subject. A copied symbol field or caller-supplied session tuple cannot recover + * this record, and non-user/system continuations intentionally receive no postbox authority. + */ +export function admitMemoryPostboxTurnIngress(params: { + context: object; + agentId: string; + sessionKey: string; + sessionId: string; + provider: string | undefined; + inputProvenance: InputProvenance | undefined; + sourceTurnId: string | undefined; + sourceChannelRef: string | undefined; + senderEvidenceRef: string | undefined; +}): void { + admittedIngressByContext.delete(params.context); + if ( + !isTrustedMessageActionTurnIngress(params.provider) || + params.inputProvenance?.kind !== "external_user" + ) { + return; + } + const sourceTurnId = normalizeOptionalString(params.sourceTurnId); + const sourceChannelRef = normalizeOptionalString(params.sourceChannelRef); + const senderEvidenceRef = normalizeOptionalString(params.senderEvidenceRef); + if (!sourceTurnId || !sourceChannelRef || !senderEvidenceRef) { + return; + } + const agentId = normalizeAgentId(params.agentId); + const sessionKey = required(params.sessionKey, "session identity"); + const sessionId = required(params.sessionId, "session generation"); + const subject = readCurrentUserSubject({ agentId, sessionKey, sessionId }); + if (!subject) { + return; + } + admittedIngressByContext.set( + params.context, + Object.freeze({ + agentId, + sessionKey, + sessionId, + sourceTurnId, + sourceChannelRef, + senderEvidenceRef, + targetPrincipalId: subject.principalId, + sessionContextFingerprint: subject.fingerprint, + }), + ); +} + function sweepExpiredMemoryPostboxTurnCapabilities(nowMs: number = Date.now()): void { for (const [token, capability] of capabilitiesByToken) { if (nowMs >= capability.expiresAtMs) { @@ -55,26 +138,41 @@ function sweepExpiredMemoryPostboxTurnCapabilities(nowMs: number = Date.now()): } /** - * Minted only from an admitted inbound user turn. The opaque token is later scoped to the selected - * memory plugin, which redeems current channel/sender evidence without accepting it from tool args. + * Minted only from the exact context admitted at trusted external-user ingress. Neither callers nor + * models may select the source, sender evidence, target principal, or the session it belongs to. */ export function mintMemoryPostboxTurnCapability(params: { agentId: string; runId: string; sessionKey: string; - sessionId?: string; - sourceChannelRef: string; - sourceMessageRef: string; - senderEvidenceRef: string; - /** Resolved only by core from the current verified user session subject. */ - targetPrincipalId: string; + sessionId: string; + /** The inbound context whose private marker is written only by trusted channel ingress. */ + sourceContext: object; expiresWithRun?: boolean; ttlMs?: number; nowMs?: number; -}): string { +}): string | undefined { const agentId = normalizeAgentId(params.agentId); const runId = required(params.runId, "run identity"); const sessionKey = required(params.sessionKey, "session identity"); + const sessionId = required(params.sessionId, "session generation"); + const source = admittedIngressByContext.get(params.sourceContext); + if ( + !source || + source.agentId !== agentId || + source.sessionKey !== sessionKey || + source.sessionId !== sessionId + ) { + return undefined; + } + const subject = readCurrentUserSubject({ agentId, sessionKey, sessionId }); + if ( + !subject || + subject.principalId !== source.targetPrincipalId || + subject.fingerprint !== source.sessionContextFingerprint + ) { + return undefined; + } const nowMs = params.nowMs ?? Date.now(); sweepExpiredMemoryPostboxTurnCapabilities(nowMs); pruneMapToMaxSize(capabilitiesByToken, MAX_ACTIVE_CAPABILITIES - 1); @@ -85,11 +183,12 @@ export function mintMemoryPostboxTurnCapability(params: { agentId, runId, sessionKey, - sessionId: normalizeOptionalString(params.sessionId), - sourceChannelRef: required(params.sourceChannelRef, "source channel evidence"), - sourceMessageRef: required(params.sourceMessageRef, "source message evidence"), - senderEvidenceRef: required(params.senderEvidenceRef, "sender evidence"), - targetPrincipalId: required(params.targetPrincipalId, "target principal"), + sessionId, + sourceTurnId: source.sourceTurnId, + sourceChannelRef: source.sourceChannelRef, + senderEvidenceRef: source.senderEvidenceRef, + targetPrincipalId: source.targetPrincipalId, + sessionContextFingerprint: source.sessionContextFingerprint, expiresAtMs: params.expiresWithRun ? RUN_LIFETIME_EXPIRES_AT_MS : nowMs + resolveTtlMs(params.ttlMs), @@ -98,7 +197,7 @@ export function mintMemoryPostboxTurnCapability(params: { return token; } -/** Rejects forged, stale, cross-agent, cross-run, and cross-session tokens without disclosure. */ +/** Rejects forged, stale, rebound, cross-agent, cross-run, and cross-session tokens without disclosure. */ export function resolveMemoryPostboxTurnCapability(params: { token?: string; agentId: string; @@ -121,16 +220,28 @@ export function resolveMemoryPostboxTurnCapability(params: { capability.agentId !== normalizeAgentId(params.agentId) || capability.runId !== normalizeOptionalString(params.runId) || capability.sessionKey !== normalizeOptionalString(params.sessionKey) || - (capability.sessionId && capability.sessionId !== normalizeOptionalString(params.sessionId)) + capability.sessionId !== normalizeOptionalString(params.sessionId) ) { if (nowMs >= capability.expiresAtMs) { capabilitiesByToken.delete(token); } return undefined; } + const subject = readCurrentUserSubject({ + agentId: capability.agentId, + sessionKey: capability.sessionKey, + sessionId: capability.sessionId, + }); + if ( + !subject || + subject.principalId !== capability.targetPrincipalId || + subject.fingerprint !== capability.sessionContextFingerprint + ) { + return undefined; + } return Object.freeze({ + sourceTurnId: capability.sourceTurnId, sourceChannelRef: capability.sourceChannelRef, - sourceMessageRef: capability.sourceMessageRef, senderEvidenceRef: capability.senderEvidenceRef, targetPrincipalId: capability.targetPrincipalId, }); @@ -145,14 +256,7 @@ export function resolveMemoryPostboxTargetPrincipal(params: { sessionKey: string; sessionId: string; }): string | undefined { - const session = createCurrentMemorySessionContext({ - sessionKey: params.sessionKey, - sessionId: params.sessionId, - options: { agentId: params.agentId }, - }); - return session.kind === "current" && session.context.subject.kind === "user" - ? session.context.principalId - : undefined; + return readCurrentUserSubject(params)?.principalId; } export function revokeMemoryPostboxTurnCapability(token: string | undefined): boolean { diff --git a/src/plugin-sdk/direct-dm.test.ts b/src/plugin-sdk/direct-dm.test.ts index dd00bcdf2c50..911d6a5d6c9f 100644 --- a/src/plugin-sdk/direct-dm.test.ts +++ b/src/plugin-sdk/direct-dm.test.ts @@ -265,6 +265,7 @@ describe("channel-inbound direct-message helpers", () => { ReplyToId: "event-parent", ReplyToIdFull: "event-parent", MessageThreadId: "thread-7", + InputProvenance: { kind: "internal_system", sourceTool: "forged-adapter-context" }, }, timestamp: 1_710_000_000_000, commandAuthorized: true, @@ -288,6 +289,10 @@ describe("channel-inbound direct-message helpers", () => { expect(result.ctxPayload.NativeDirectUserId).toBe("sender-1"); expect(result.ctxPayload.OriginatingTo).toBe("nostr:bot-1"); expect(result.ctxPayload.CommandAuthorized).toBe(true); + expect(result.ctxPayload.InputProvenance).toEqual({ + kind: "external_user", + sourceChannel: "nostr", + }); expect(recordInboundSession).toHaveBeenCalledTimes(1); expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledTimes(1); expect(deliver).toHaveBeenCalledWith({ text: "reply text" }); diff --git a/src/plugin-sdk/memory-sharing-control-runtime.ts b/src/plugin-sdk/memory-sharing-control-runtime.ts new file mode 100644 index 000000000000..470bdcf557d1 --- /dev/null +++ b/src/plugin-sdk/memory-sharing-control-runtime.ts @@ -0,0 +1,5 @@ +/** Core-owned Gateway-profile resolver for selected memory sharing controls. */ +export { + resolveMemoryPrincipalForUserProfile, + type MemoryPrincipal, +} from "../state/memory-identity.js"; diff --git a/src/plugins/memory-invocation.test.ts b/src/plugins/memory-invocation.test.ts index fa90e30811b1..db9f2822a0b7 100644 --- a/src/plugins/memory-invocation.test.ts +++ b/src/plugins/memory-invocation.test.ts @@ -4,8 +4,14 @@ import { type AuthorizedMemoryPlan, type AuthorizedMemoryResultEnvelope, type AuthorizedMemorySearchResult, + type AuthorizedMemoryVirtualView, type MemoryAccessContext, } from "../plugin-sdk/memory-authorization.js"; +import type { + AuthorizedMemoryReadInvocation, + AuthorizedMemoryWriteInvocation, + MemoryInvocationUnavailable, +} from "./memory-invocation.js"; const mocks = vi.hoisted(() => ({ admit: vi.fn(), @@ -44,6 +50,7 @@ const { readAuthorizedMemoryForInvocation, readAuthorizedMemoryRunExposure, searchAuthorizedMemoryForInvocation, + stageAuthorizedMemorySealedCompactionForInvocation, writeAuthorizedMemoryForInvocation, } = await import("./memory-invocation.js"); const { clearMemoryRunExposureForTest } = await import("./memory-run-exposure.js"); @@ -118,10 +125,18 @@ function createWritePlan(): AuthorizedMemoryPlan & Readonly<{ operation: "append return { ...createPlan(), operation: "append" }; } +function createDeriveContext(): MemoryAccessContext & Readonly<{ operation: "derive" }> { + return { ...createContext(), operation: "derive" }; +} + +function createDerivePlan(): AuthorizedMemoryPlan & Readonly<{ operation: "derive" }> { + return { ...createPlan(), operation: "derive" }; +} + let receiptSequence = 0; function createEnvelope( - value: T, + value: AuthorizedMemoryResultEnvelope["value"], overrides?: Readonly<{ exposureReceipt?: Partial["exposureReceipt"]>; egressReceipt?: Partial["egressReceipt"]>; @@ -160,6 +175,32 @@ function createEnvelope( }; } +function assertMemoryInvocationAvailable( + value: AuthorizedMemoryReadInvocation | MemoryInvocationUnavailable, + message?: string, +): asserts value is AuthorizedMemoryReadInvocation; +function assertMemoryInvocationAvailable( + value: AuthorizedMemoryWriteInvocation | MemoryInvocationUnavailable, + message?: string, +): asserts value is AuthorizedMemoryWriteInvocation; +function assertMemoryInvocationAvailable( + value: AuthorizedMemoryVirtualView | MemoryInvocationUnavailable, + message?: string, +): asserts value is AuthorizedMemoryVirtualView; +function assertMemoryInvocationAvailable( + value: + | AuthorizedMemoryReadInvocation + | AuthorizedMemoryWriteInvocation + | AuthorizedMemoryVirtualView + | MemoryInvocationUnavailable, + message = "fixture failed to create an authorized memory value", +): void { + expect(value).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); + if ("unavailable" in value) { + throw new Error(message); + } +} + describe("authorized memory read invocation", () => { afterEach(() => { clearMemoryRunExposureForTest(); @@ -243,10 +284,7 @@ describe("authorized memory read invocation", () => { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES, }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "allowed" }), ).resolves.toEqual({ @@ -311,10 +349,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); const response = await searchAuthorizedMemoryForInvocation({ invocation, query: "private" }); @@ -365,10 +400,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "private" }), ).resolves.toEqual( @@ -426,10 +458,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "private" }), ).resolves.toEqual( @@ -485,10 +514,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect(searchAuthorizedMemoryForInvocation({ invocation, query: "first" })).resolves.toBe( MEMORY_INVOCATION_UNAVAILABLE, ); @@ -534,10 +560,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "private" }), ).resolves.toBe(MEMORY_INVOCATION_UNAVAILABLE); @@ -559,10 +582,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "private" }), @@ -611,10 +631,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "allowed" }), ).resolves.toEqual({ @@ -689,10 +706,7 @@ describe("authorized memory read invocation", () => { context: {} as never, capability: { authorization: COMPLETE_MEMORY_AUTHORIZATION_CAPABILITIES }, }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( searchAuthorizedMemoryForInvocation({ invocation, query: "allowed" }), ).resolves.toMatchObject({ @@ -722,7 +736,7 @@ describe("authorized memory read invocation", () => { files: [{ version: 1 as const, mountHandle: "mount-1", virtualPath: "private/1.md" }], expiresAt: new Date(Date.now() + 60_000).toISOString(), })), - readAuthorizedVirtualFile: vi.fn(async () => + readAuthorizedVirtualFile: vi.fn(async (_params) => createEnvelope({ text: "allowed", path: "memory/private/1.md" }), ), }; @@ -748,13 +762,9 @@ describe("authorized memory read invocation", () => { mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryReadInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to admit virtual provider"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to admit virtual provider"); const view = await materializeAuthorizedMemoryVirtualView({ invocation }); - if (view === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to materialize virtual view"); - } + assertMemoryInvocationAvailable(view, "fixture failed to materialize virtual view"); await expect( readAuthorizedMemoryVirtualFile({ invocation, view, virtualPath: "private/2.md" }), ).resolves.toBe(MEMORY_INVOCATION_UNAVAILABLE); @@ -786,9 +796,7 @@ describe("authorized memory read invocation", () => { }); const invocation = await createAuthorizedMemoryDeriveInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to admit derive invocation"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to admit derive invocation"); await expect(materializeAuthorizedMemoryVirtualView({ invocation })).resolves.toBe( MEMORY_INVOCATION_UNAVAILABLE, @@ -841,9 +849,7 @@ describe("authorized memory read invocation", () => { mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryReadInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to admit virtual provider"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to admit virtual provider"); await expect(materializeAuthorizedMemoryVirtualView({ invocation })).resolves.toBe( MEMORY_INVOCATION_UNAVAILABLE, ); @@ -870,7 +876,7 @@ describe("authorized memory read invocation", () => { }; const admittedVirtualView = { materializeAuthorizedVirtualView: vi.fn(async () => issuedView), - readAuthorizedVirtualFile: vi.fn(async () => + readAuthorizedVirtualFile: vi.fn(async (_params) => createEnvelope({ text: "allowed", path: "memory/private/1.md" }), ), }; @@ -895,13 +901,9 @@ describe("authorized memory read invocation", () => { mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryReadInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to admit virtual provider"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to admit virtual provider"); const view = await materializeAuthorizedMemoryVirtualView({ invocation }); - if (view === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to materialize virtual view"); - } + assertMemoryInvocationAvailable(view, "fixture failed to materialize virtual view"); issuedView.revision = "replacement-revision"; issuedView.files[0]!.virtualPath = "private/replacement.md"; @@ -968,9 +970,7 @@ describe("authorized memory read invocation", () => { mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryReadInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to admit virtual provider"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to admit virtual provider"); runtime.virtualView = replacement; await expect(materializeAuthorizedMemoryVirtualView({ invocation })).resolves.toMatchObject({ viewId: "view-admitted", @@ -1001,10 +1001,7 @@ describe("authorized memory write invocation", () => { mocks.materialize.mockReturnValue(createWriteContext()); mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryWriteInvocation({ context: {} as never }); - expect(invocation).not.toBe(MEMORY_INVOCATION_UNAVAILABLE); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - return; - } + assertMemoryInvocationAvailable(invocation); await expect( writeAuthorizedMemoryForInvocation({ invocation, @@ -1041,9 +1038,7 @@ describe("authorized memory write invocation", () => { mocks.materialize.mockReturnValueOnce(context).mockReturnValueOnce(undefined); mocks.admit.mockResolvedValue({ ok: true, runtime }); const invocation = await createAuthorizedMemoryWriteInvocation({ context: {} as never }); - if (invocation === MEMORY_INVOCATION_UNAVAILABLE) { - throw new Error("fixture failed to create a write invocation"); - } + assertMemoryInvocationAvailable(invocation, "fixture failed to create a write invocation"); await expect( writeAuthorizedMemoryForInvocation({ invocation, @@ -1059,4 +1054,57 @@ describe("authorized memory write invocation", () => { ).resolves.toBe(MEMORY_INVOCATION_UNAVAILABLE); expect(runtime.writeAuthorized).not.toHaveBeenCalled(); }); + + it("stages sealed compaction only for a revalidated derive invocation", async () => { + const artifact = { + resourceRevisionId: "revision-derive-1", + commitInTransaction: vi.fn(), + }; + const deriveRuntime = { + authorize: vi.fn().mockResolvedValue(createDerivePlan()), + stageSealedCompaction: vi.fn().mockResolvedValue(artifact), + }; + mocks.materialize.mockReturnValue(createDeriveContext()); + mocks.admit.mockResolvedValue({ ok: true, runtime: deriveRuntime }); + const deriveInvocation = await createAuthorizedMemoryWriteInvocation({ context: {} as never }); + assertMemoryInvocationAvailable(deriveInvocation, "fixture failed to create a derive invocation"); + const transcriptSource = { + kind: "transcript" as const, + sessionId: "session-1", + eventSeqs: [1], + sourcePolicySetId: "policy-set-1", + deliveryAudiencesJson: '[{"kind":"user","id":"alice"}]', + }; + await expect( + stageAuthorizedMemorySealedCompactionForInvocation({ + invocation: deriveInvocation, + content: "sealed summary", + transcriptSource, + }), + ).resolves.toBe(artifact); + expect(deriveRuntime.stageSealedCompaction).toHaveBeenCalledWith( + expect.objectContaining({ + context: expect.objectContaining({ operation: "derive" }), + plan: expect.objectContaining({ operation: "derive" }), + transcriptSource, + }), + ); + + const appendRuntime = { + authorize: vi.fn().mockResolvedValue(createWritePlan()), + stageSealedCompaction: vi.fn(), + }; + mocks.materialize.mockReturnValue(createWriteContext()); + mocks.admit.mockResolvedValue({ ok: true, runtime: appendRuntime }); + const appendInvocation = await createAuthorizedMemoryWriteInvocation({ context: {} as never }); + assertMemoryInvocationAvailable(appendInvocation, "fixture failed to create an append invocation"); + await expect( + stageAuthorizedMemorySealedCompactionForInvocation({ + invocation: appendInvocation, + content: "must not stage", + transcriptSource, + }), + ).resolves.toBe(MEMORY_INVOCATION_UNAVAILABLE); + expect(appendRuntime.stageSealedCompaction).not.toHaveBeenCalled(); + }); }); diff --git a/src/plugins/memory-invocation.ts b/src/plugins/memory-invocation.ts index 5397c90b0595..ad2befd2f935 100644 --- a/src/plugins/memory-invocation.ts +++ b/src/plugins/memory-invocation.ts @@ -104,6 +104,12 @@ type WriteInvocationState = Readonly<{ runtime: Readonly; }>; +type DeriveWriteInvocationState = Omit & + Readonly<{ + context: MemoryAccessContext & Readonly<{ operation: "derive" }>; + plan: AuthorizedMemoryPlan & Readonly<{ operation: "derive" }>; + }>; + const writeInvocationStates = new WeakMap(); type MemoryInvocationDiagnostic = @@ -171,6 +177,18 @@ function readCurrentWriteContext(state: WriteInvocationState): MemoryAccessConte return current; } +function isDeriveWriteInvocationState( + state: WriteInvocationState, +): state is DeriveWriteInvocationState { + return state.context.operation === "derive" && state.plan.operation === "derive"; +} + +function isDeriveMemoryAccessContext( + context: MemoryAccessContext, +): context is MemoryAccessContext & Readonly<{ operation: "derive" }> { + return context.operation === "derive"; +} + function readCurrentContext( state: InvocationState, ): MemoryContentAccessContext | undefined { @@ -585,7 +603,8 @@ export async function stageAuthorizedMemorySealedCompactionForInvocation(params: if ( !state || !context || - context.operation !== "derive" || + !isDeriveMemoryAccessContext(context) || + !isDeriveWriteInvocationState(state) || !state.runtime.stageSealedCompaction || !isCurrentPlan({ context, plan: state.plan, nowMs: Date.now() }) ) { @@ -594,7 +613,7 @@ export async function stageAuthorizedMemorySealedCompactionForInvocation(params: try { return await state.runtime.stageSealedCompaction({ context, - plan: state.plan as AuthorizedMemoryPlan & Readonly<{ operation: "derive" }>, + plan: state.plan, content: params.content, transcriptSource: params.transcriptSource, }); diff --git a/src/plugins/memory-state.test.ts b/src/plugins/memory-state.test.ts index 734e88d7b873..2fd3be1b863c 100644 --- a/src/plugins/memory-state.test.ts +++ b/src/plugins/memory-state.test.ts @@ -1,7 +1,9 @@ // Covers plugin-backed memory state registration and reset behavior. import { afterEach, describe, expect, it, vi } from "vitest"; -const isMemoryIsolationCutoverAgentMock = vi.hoisted(() => vi.fn(() => false)); +const isMemoryIsolationCutoverAgentMock = vi.hoisted(() => + vi.fn<(agentId: string) => boolean>(() => false), +); vi.mock("./memory-cutover.js", () => ({ isMemoryIsolationCutoverAgent: isMemoryIsolationCutoverAgentMock, diff --git a/src/plugins/tools.optional.test.ts b/src/plugins/tools.optional.test.ts index fc555311365e..a2cb8aa8ce83 100644 --- a/src/plugins/tools.optional.test.ts +++ b/src/plugins/tools.optional.test.ts @@ -2016,8 +2016,12 @@ describe("resolvePluginTools optional tools", () => { }); it("delivers a host binding only to its selected plugin factory", () => { - const memoryFactory = vi.fn(() => makeTool("memory_postbox_deposit")); - const otherFactory = vi.fn(() => makeTool("other_tool")); + const memoryFactory = vi.fn((_context) => + makeTool("memory_postbox_deposit"), + ); + const otherFactory = vi.fn((_context) => + makeTool("other_tool"), + ); setRegistry([ { pluginId: "memory-core", diff --git a/src/state/openclaw-agent-db.generated.d.ts b/src/state/openclaw-agent-db.generated.d.ts index f32906d1bb87..e4eb2b2a7760 100644 --- a/src/state/openclaw-agent-db.generated.d.ts +++ b/src/state/openclaw-agent-db.generated.d.ts @@ -199,6 +199,15 @@ export interface MemoryPostboxRateLimits { window_started_at: number; } +export interface MemoryPostboxReviewedCopies { + agent_id: string; + created_at: number; + item_id: string; + resource_id: string; + reviewed_content_hash: string; + revision_id: string; +} + export interface MemoryPostboxSettings { agent_id: string; mode: string; @@ -912,6 +921,7 @@ export interface DB { memory_compaction_policy_sources: MemoryCompactionPolicySources; memory_postbox_items: MemoryPostboxItems; memory_postbox_rate_limits: MemoryPostboxRateLimits; + memory_postbox_reviewed_copies: MemoryPostboxReviewedCopies; memory_postbox_settings: MemoryPostboxSettings; memory_postbox_source_handles: MemoryPostboxSourceHandles; memory_embedding_cache: MemoryEmbeddingCache; diff --git a/src/state/openclaw-agent-schema.sql b/src/state/openclaw-agent-schema.sql index 68719564123d..ba8965f9bc90 100644 --- a/src/state/openclaw-agent-schema.sql +++ b/src/state/openclaw-agent-schema.sql @@ -1388,7 +1388,9 @@ CREATE TABLE IF NOT EXISTS memory_postbox_source_handles ( used_at INTEGER, created_at INTEGER NOT NULL, FOREIGN KEY (target_store_id) REFERENCES memory_stores(store_id) ON DELETE RESTRICT, - UNIQUE (agent_id, source_session_id, source_message_ref, target_store_id) + -- source_message_ref is the opaque route-scoped source-turn id, so a reset session + -- cannot deposit the same inbound message a second time. + UNIQUE (agent_id, source_message_ref, target_store_id) ) STRICT; CREATE INDEX IF NOT EXISTS idx_memory_postbox_source_handles_live @@ -1426,10 +1428,42 @@ CREATE TABLE IF NOT EXISTS memory_postbox_items ( CREATE INDEX IF NOT EXISTS idx_memory_postbox_items_review ON memory_postbox_items(agent_id, target_store_id, state, created_at); +CREATE TABLE IF NOT EXISTS memory_postbox_reviewed_copies ( + item_id TEXT NOT NULL PRIMARY KEY, + agent_id TEXT NOT NULL, + resource_id TEXT NOT NULL, + revision_id TEXT NOT NULL, + reviewed_content_hash TEXT NOT NULL, + created_at INTEGER NOT NULL, + FOREIGN KEY (item_id) REFERENCES memory_postbox_items(item_id) ON DELETE CASCADE, + FOREIGN KEY (resource_id) REFERENCES memory_resources(resource_id) ON DELETE RESTRICT, + FOREIGN KEY (revision_id) REFERENCES memory_resource_revisions(revision_id) ON DELETE RESTRICT +) STRICT; + +CREATE INDEX IF NOT EXISTS idx_memory_postbox_reviewed_copies_revision + ON memory_postbox_reviewed_copies(agent_id, revision_id); + CREATE TRIGGER IF NOT EXISTS memory_postbox_items_immutable_provenance BEFORE UPDATE OF item_id, agent_id, source_handle_id, target_store_id, source_channel_ref, sender_evidence_ref, content, content_hash, created_at ON memory_postbox_items +WHEN + NEW.item_id <> OLD.item_id OR + NEW.agent_id <> OLD.agent_id OR + NEW.source_handle_id <> OLD.source_handle_id OR + NEW.target_store_id <> OLD.target_store_id OR + NEW.source_channel_ref <> OLD.source_channel_ref OR + NEW.sender_evidence_ref <> OLD.sender_evidence_ref OR + NEW.created_at <> OLD.created_at OR + ( + (NEW.content <> OLD.content OR NEW.content_hash <> OLD.content_hash) AND + NOT ( + OLD.state IN ('postbox', 'reviewed', 'rejected') AND + NEW.state = 'purged' AND + NEW.content = '' AND + NEW.content_hash = '' + ) + ) BEGIN SELECT RAISE(ABORT, 'memory postbox provenance is immutable'); END; diff --git a/src/state/openclaw-agent-scoped-memory-schema.test.ts b/src/state/openclaw-agent-scoped-memory-schema.test.ts index b1bd84c25b8c..6bffb84f39dc 100644 --- a/src/state/openclaw-agent-scoped-memory-schema.test.ts +++ b/src/state/openclaw-agent-scoped-memory-schema.test.ts @@ -145,6 +145,61 @@ describe("scoped memory additive agent schema", () => { ); }); + it("repairs the legacy postbox trigger so purge can erase a body without changing provenance", () => { + const database = createDatabase(); + ensureOpenClawAgentScopedMemorySchema(database); + database.exec(` + DROP TRIGGER memory_postbox_items_immutable_provenance; + CREATE TRIGGER memory_postbox_items_immutable_provenance + BEFORE UPDATE OF item_id, agent_id, source_handle_id, target_store_id, source_channel_ref, + sender_evidence_ref, content, content_hash, created_at + ON memory_postbox_items + BEGIN + SELECT RAISE(ABORT, 'memory postbox provenance is immutable'); + END; + `); + + ensureOpenClawAgentScopedMemorySchema(database); + database.exec("PRAGMA foreign_keys = OFF"); + database + .prepare( + `INSERT INTO memory_postbox_items + (item_id, agent_id, source_handle_id, target_store_id, source_channel_ref, + sender_evidence_ref, content, content_hash, state, created_at) + VALUES ('postbox-1', 'main', 'handle-1', 'store-1', 'channel-1', + 'sender-1', 'secret', 'digest-1', 'postbox', 1)`, + ) + .run(); + + expect(() => + database + .prepare( + "UPDATE memory_postbox_items SET content = 'replacement' WHERE item_id = 'postbox-1'", + ) + .run(), + ).toThrow(/immutable/u); + database + .prepare( + `UPDATE memory_postbox_items + SET state = 'purged', content = '', content_hash = '', purged_at = 2 + WHERE item_id = 'postbox-1'`, + ) + .run(); + expect( + database + .prepare( + "SELECT state, content, content_hash, sender_evidence_ref, purged_at FROM memory_postbox_items", + ) + .get(), + ).toEqual({ + state: "purged", + content: "", + content_hash: "", + sender_evidence_ref: "sender-1", + purged_at: 2, + }); + }); + it("keeps the pre-output exposure ledger in the canonical scoped schema payload", () => { expect(AGENT_SCOPED_MEMORY_SCHEMA_SQL).toContain( "CREATE TABLE IF NOT EXISTS memory_preoutput_exposure_ledger (", diff --git a/src/state/openclaw-agent-scoped-memory-schema.ts b/src/state/openclaw-agent-scoped-memory-schema.ts index f5d6d2ffc536..12e8ed628ff7 100644 --- a/src/state/openclaw-agent-scoped-memory-schema.ts +++ b/src/state/openclaw-agent-scoped-memory-schema.ts @@ -35,6 +35,7 @@ export const AGENT_SCOPED_MEMORY_TABLES = [ "memory_postbox_source_handles", "memory_postbox_rate_limits", "memory_postbox_items", + "memory_postbox_reviewed_copies", ] as const; export const AGENT_SCOPED_MEMORY_FTS_TABLE = "memory_scoped_chunks_fts"; @@ -97,11 +98,53 @@ function extractScopedMemorySchema(): string { /** Canonical additive schema for scoped resources, policy, indexes, and receipts. */ export const AGENT_SCOPED_MEMORY_SCHEMA_SQL = extractScopedMemorySchema(); +const POSTBOX_PURGE_TRIGGER_MARKER = "NEW.state = 'purged'"; +const POSTBOX_PURGE_TRIGGER_SQL = ` + CREATE TRIGGER memory_postbox_items_immutable_provenance + BEFORE UPDATE OF item_id, agent_id, source_handle_id, target_store_id, source_channel_ref, + sender_evidence_ref, content, content_hash, created_at + ON memory_postbox_items + WHEN + NEW.item_id <> OLD.item_id OR + NEW.agent_id <> OLD.agent_id OR + NEW.source_handle_id <> OLD.source_handle_id OR + NEW.target_store_id <> OLD.target_store_id OR + NEW.source_channel_ref <> OLD.source_channel_ref OR + NEW.sender_evidence_ref <> OLD.sender_evidence_ref OR + NEW.created_at <> OLD.created_at OR + ( + (NEW.content <> OLD.content OR NEW.content_hash <> OLD.content_hash) AND + NOT ( + OLD.state IN ('postbox', 'reviewed', 'rejected') AND + NEW.state = 'purged' AND + NEW.content = '' AND + NEW.content_hash = '' + ) + ) + BEGIN + SELECT RAISE(ABORT, 'memory postbox provenance is immutable'); + END; +`; + +function repairPostboxPurgeTrigger(db: DatabaseSync): void { + const trigger = db + .prepare("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = ?") + .get("memory_postbox_items_immutable_provenance") as { sql?: unknown } | undefined; + if (typeof trigger?.sql === "string" && trigger.sql.includes(POSTBOX_PURGE_TRIGGER_MARKER)) { + return; + } + // Existing additive databases have the older immutable trigger. Replace only that trigger so + // a purge can redact the body/digest while every identity-bearing provenance field stays fixed. + db.exec("DROP TRIGGER IF EXISTS memory_postbox_items_immutable_provenance"); + db.exec(POSTBOX_PURGE_TRIGGER_SQL); // sqlite-allow-raw -- canonical trigger convergence. +} + /** Lazily install the full idempotent group; do not cache transaction-local success. */ export function ensureOpenClawAgentScopedMemorySchema(db: DatabaseSync): void { const ensure = () => { // A partially applied group is completed rather than inferred from one marker table. db.exec(AGENT_SCOPED_MEMORY_SCHEMA_SQL); // sqlite-allow-raw -- Canonical additive DDL only. + repairPostboxPurgeTrigger(db); }; if (db.isTransaction) { ensure(); diff --git a/ui/src/i18n/locales/en.ts b/ui/src/i18n/locales/en.ts index 46d432ed8cc1..5c0c66d700c5 100644 --- a/ui/src/i18n/locales/en.ts +++ b/ui/src/i18n/locales/en.ts @@ -2577,6 +2577,56 @@ export const en: TranslationMap = { search: { intro: "Embedding and retrieval defaults shared by every agent that has no memory override.", }, + sharing: { + title: "Sharing and postbox", + intro: + "Create reviewed projection copies and review one-way postbox deposits without granting access to a private store.", + statusTitle: "Sharing status", + postboxMode: "Postbox mode", + postboxOff: "Off", + postboxReviewRequired: "Review required", + projectionCount: "Projections", + postboxCount: "Postbox items", + requestFailed: "The sharing request could not be completed.", + completeRequiredFields: + "Complete the required projection fields and choose either an expiry or an audited no-expiry reason.", + invalidAgentSharedTarget: "Agent-shared projections must target the selected agent.", + previewRequired: "Preview the projection before creating it.", + targets: { + conversation: "Conversation", + role: "Role", + agentShared: "Agent shared", + }, + projection: { + title: "Reviewed projection", + description: "A projection creates one reviewed copy for a named non-private audience.", + id: "Projection to refresh", + sourceRevision: "Source revision", + targetKind: "Target kind", + targetId: "Target id", + targetStoreId: "Reviewed-copy target store id", + purpose: "Purpose", + preview: "Human-readable preview", + expiry: "Expiry", + noExpiryReason: "No-expiry audit reason", + content: "Reviewed copy", + previewAction: "Preview", + registerTarget: "Register target store", + create: "Create projection", + refresh: "Refresh projection", + }, + projections: "Existing projections", + emptyProjections: "No projections are available for this profile.", + impact: "Prior exposure impact", + priorExposure: "{count} prior exposure records", + revoke: "Revoke", + postbox: "Postbox review", + emptyPostbox: "No quarantined postbox items are available.", + inspect: "Inspect", + approve: "Approve", + reject: "Reject", + purge: "Purge", + }, dreaming: { intro: "Dreaming runs as one managed automation across every agent workspace, so these settings are global. They are owned by the {plugin} plugin.", diff --git a/ui/src/pages/config/memory-page.ts b/ui/src/pages/config/memory-page.ts index b68ce0388375..6d9b64e160fc 100644 --- a/ui/src/pages/config/memory-page.ts +++ b/ui/src/pages/config/memory-page.ts @@ -47,6 +47,7 @@ import { type MemoryEngineSelection, type MemoryTab, } from "./memory-schema.ts"; +import { renderMemorySharingHost } from "./memory-sharing-host.ts"; import { buildMemoryAddonRows, buildMemoryEngineOptions, @@ -697,6 +698,10 @@ class MemorySettingsPage extends OpenClawLightDomElement { editor: activeTab === "settings" ? this.buildEditor(memorySchemaKeysForTab("settings")) : html``, dreamingSettings: activeTab === "settings" ? this.renderDreamingControls() : html``, + sharing: + activeTab === "settings" + ? renderMemorySharingHost(this.context.gateway.snapshot, agentId) + : html``, }); } } diff --git a/ui/src/pages/config/memory-sharing-host.ts b/ui/src/pages/config/memory-sharing-host.ts new file mode 100644 index 000000000000..75132997ba57 --- /dev/null +++ b/ui/src/pages/config/memory-sharing-host.ts @@ -0,0 +1,40 @@ +import { html, type TemplateResult } from "lit"; +import type { ApplicationContext } from "../../app/context.ts"; +import { readGatewayOperatorAccess } from "../../app/operator-access.ts"; +import { isGatewayMethodAdvertised } from "../../lib/gateway-methods.ts"; +import "./memory-sharing.ts"; + +const MEMORY_SHARING_METHODS = [ + "memory.sharing.status", + "memory.sharing.projection.target.register", + "memory.sharing.projection.preview", + "memory.sharing.projection.create", + "memory.sharing.projection.refresh", + "memory.sharing.projection.revoke", + "memory.sharing.projection.impact", + "memory.sharing.postbox.mode.set", + "memory.sharing.postbox.inspect", + "memory.sharing.postbox.review", + "memory.sharing.postbox.purge", +] as const; + +type GatewaySnapshot = ApplicationContext["gateway"]["snapshot"]; + +/** Hide the sharing controls until this Gateway advertises the complete profile-derived contract. */ +export function renderMemorySharingHost( + gateway: GatewaySnapshot, + agentId: string | null, +): TemplateResult { + const methodsAvailable = MEMORY_SHARING_METHODS.every( + (method) => isGatewayMethodAdvertised(gateway, method) === true, + ); + return html` + + `; +} diff --git a/ui/src/pages/config/memory-sharing.test.ts b/ui/src/pages/config/memory-sharing.test.ts new file mode 100644 index 000000000000..40b50c6b41ab --- /dev/null +++ b/ui/src/pages/config/memory-sharing.test.ts @@ -0,0 +1,215 @@ +/* @vitest-environment jsdom */ + +import { html, render } from "lit"; +import { describe, expect, it, vi } from "vitest"; +import { waitForFast } from "../../test-helpers/wait-for.ts"; +import { renderMemorySharingHost } from "./memory-sharing-host.ts"; + +type Request = (method: string, params: Record) => Promise; + +const SHARING_METHODS = [ + "memory.sharing.status", + "memory.sharing.projection.target.register", + "memory.sharing.projection.preview", + "memory.sharing.projection.create", + "memory.sharing.projection.refresh", + "memory.sharing.projection.revoke", + "memory.sharing.projection.impact", + "memory.sharing.postbox.mode.set", + "memory.sharing.postbox.inspect", + "memory.sharing.postbox.review", + "memory.sharing.postbox.purge", +] as const; + +type SharingElement = HTMLElement & { + client: { request: Request } | null; + connected: boolean; + canAdmin: boolean; + methodsAvailable: boolean; + agentId: string | null; + updateComplete: Promise; +}; + +function findButton(element: HTMLElement, text: string): HTMLButtonElement { + const button = [...element.querySelectorAll("button")].find( + (candidate) => candidate.textContent?.trim() === text, + ); + if (!button) { + throw new Error(`button ${text} is unavailable`); + } + return button; +} + +function renderSharingHost(params: { + methods: readonly string[]; + scopes?: readonly string[]; + request: Request; +}) { + const container = document.createElement("div"); + render( + renderMemorySharingHost( + { + phase: "connected", + client: { request: params.request }, + hello: { + auth: { role: "operator", scopes: params.scopes ?? ["operator.admin"] }, + features: { methods: [...params.methods] }, + }, + } as never, + "main", + ), + container, + ); + const element = container.querySelector("openclaw-memory-sharing"); + if (!element) { + throw new Error("sharing control is unavailable"); + } + document.body.append(container); + return { container, element }; +} + +describe("MemorySharingElement", () => { + it("stays hidden unless an admin Gateway advertises the complete sharing contract", async () => { + const request = vi.fn(); + const partial = renderSharingHost({ methods: SHARING_METHODS.slice(0, -1), request }); + const readOnly = renderSharingHost({ + methods: SHARING_METHODS, + scopes: ["operator.read"], + request, + }); + try { + await partial.element.updateComplete; + await readOnly.element.updateComplete; + expect(partial.element.textContent).toBe(""); + expect(readOnly.element.textContent).toBe(""); + expect(request).not.toHaveBeenCalled(); + } finally { + partial.container.remove(); + readOnly.container.remove(); + } + }); + + it("uses only agent and reviewed-operation fields in postbox requests", async () => { + const request = vi.fn((method) => { + if (method === "memory.sharing.status") { + return Promise.resolve({ + postboxMode: "off", + projections: [], + postboxItems: [ + { + itemId: "postbox-1", + state: "postbox", + sourceChannelRef: "telegram:alice", + createdAt: 1, + }, + ], + }); + } + if (method === "memory.sharing.postbox.inspect") { + return Promise.resolve({ itemId: "postbox-1", content: "sender observation" }); + } + return Promise.resolve({ itemId: "postbox-1" }); + }); + const { container, element } = renderSharingHost({ methods: SHARING_METHODS, request }); + try { + await waitForFast(() => expect(element.textContent).toContain("telegram:alice")); + expect(request).toHaveBeenCalledWith("memory.sharing.status", { agentId: "main" }); + + request.mockClear(); + findButton(element, "Inspect").click(); + await waitForFast(() => + expect(request).toHaveBeenCalledWith("memory.sharing.postbox.inspect", { + agentId: "main", + itemId: "postbox-1", + }), + ); + const reviewTextarea = () => + [...element.querySelectorAll("textarea")].at(-1); + await waitForFast(() => expect(reviewTextarea()?.value).toBe("sender observation")); + const textarea = reviewTextarea(); + if (!textarea) { + throw new Error("review textarea is unavailable"); + } + textarea.value = "owner-edited copy"; + textarea.dispatchEvent(new Event("input", { bubbles: true })); + + request.mockClear(); + findButton(element, "Approve").click(); + await waitForFast(() => + expect(request).toHaveBeenCalledWith("memory.sharing.postbox.review", { + agentId: "main", + itemId: "postbox-1", + decision: "approve", + reviewedContent: "owner-edited copy", + }), + ); + expect(request.mock.calls.every(([, payload]) => !("principalId" in payload))).toBe(true); + expect(request.mock.calls.every(([, payload]) => !("storeId" in payload))).toBe(true); + } finally { + container.remove(); + } + }); + + it("renders prior projection exposure without accepting a caller-selected audience", async () => { + const request = vi.fn((method) => { + if (method === "memory.sharing.status") { + return Promise.resolve({ + postboxMode: "off", + postboxItems: [], + projections: [ + { + projectionId: "projection-1", + purpose: "handoff", + preview: "reviewed note", + state: "active", + target: { kind: "role", id: "support" }, + expiresAt: null, + }, + ], + }); + } + if (method === "memory.sharing.projection.impact") { + return Promise.resolve({ exposureSetIds: ["exposure-1", "exposure-2"] }); + } + return Promise.resolve({}); + }); + const { container, element } = renderSharingHost({ methods: SHARING_METHODS, request }); + try { + await waitForFast(() => expect(element.textContent).toContain("handoff")); + request.mockClear(); + findButton(element, "Prior exposure impact").click(); + await waitForFast(() => + expect(request).toHaveBeenCalledWith("memory.sharing.projection.impact", { + agentId: "main", + projectionId: "projection-1", + }), + ); + await waitForFast(() => expect(element.textContent).toContain("2 prior exposure records")); + expect(request.mock.calls.every(([, payload]) => !("audience" in payload))).toBe(true); + } finally { + container.remove(); + } + }); + + it("renders no private-user projection target input", async () => { + const request = vi.fn((method) => + Promise.resolve( + method === "memory.sharing.status" + ? { postboxMode: "off", projections: [], postboxItems: [] } + : {}, + ), + ); + const { container, element } = renderSharingHost({ methods: SHARING_METHODS, request }); + try { + await waitForFast(() => expect(element.querySelector("select")).not.toBeNull()); + expect( + [...element.querySelectorAll("select")] + .flatMap((select) => [...select.options].map((option) => option.value)), + ).toEqual(expect.arrayContaining(["conversation", "role", "agent-shared"])); + expect(element.querySelectorAll('option[value="user"]')).toHaveLength(0); + expect(element.textContent).not.toContain("private-user"); + } finally { + container.remove(); + } + }); +}); diff --git a/ui/src/pages/config/memory-sharing.ts b/ui/src/pages/config/memory-sharing.ts new file mode 100644 index 000000000000..d7a2945ba70b --- /dev/null +++ b/ui/src/pages/config/memory-sharing.ts @@ -0,0 +1,644 @@ +import { isRecord } from "@openclaw/normalization-core/record-coerce"; +import { html, nothing, type PropertyValues } from "lit"; +import { property, state } from "lit/decorators.js"; +import type { GatewayBrowserClient } from "../../api/gateway.ts"; +import { + renderSettingsRow, + renderSettingsSection, + renderSettingsValue, +} from "../../components/settings-ui.ts"; +import { t } from "../../i18n/index.ts"; +import { OpenClawLightDomElement } from "../../lit/openclaw-element.ts"; + +type ProjectionTarget = Readonly<{ + kind: "conversation" | "role" | "agent-shared"; + id: string; +}>; + +type SharingStatus = Readonly<{ + postboxMode: "off" | "review-required"; + projections: readonly Readonly<{ + projectionId: string; + target: ProjectionTarget; + purpose: string; + preview: string; + state: string; + expiresAt: number | null; + }>[]; + postboxItems: readonly Readonly<{ + itemId: string; + state: string; + sourceChannelRef: string; + createdAt: number; + }>[]; +}>; + +type ProjectionForm = { + projectionId: string; + sourceRevisionId: string; + targetKind: ProjectionTarget["kind"]; + targetId: string; + targetStoreId: string; + purpose: string; + preview: string; + content: string; + expiresAt: string; + noExpiryAuditReason: string; +}; + +function asText(value: unknown): string | null { + return typeof value === "string" && value.trim() ? value.trim() : null; +} + +function parseTarget(value: unknown): ProjectionTarget | null { + if (!isRecord(value)) { + return null; + } + const kind = value.kind; + const id = asText(value.id); + return (kind === "conversation" || kind === "role" || kind === "agent-shared") && id + ? { kind, id } + : null; +} + +function isProjectionTargetKind(value: string): value is ProjectionTarget["kind"] { + return value === "conversation" || value === "role" || value === "agent-shared"; +} + +function parseStatus(value: unknown): SharingStatus | null { + if ( + !isRecord(value) || + (value.postboxMode !== "off" && value.postboxMode !== "review-required") + ) { + return null; + } + const projections = Array.isArray(value.projections) + ? value.projections.flatMap((entry) => { + if (!isRecord(entry)) { + return []; + } + const projectionId = asText(entry.projectionId); + const target = parseTarget(entry.target); + const purpose = asText(entry.purpose); + const preview = asText(entry.preview); + const state = asText(entry.state); + const expiresAt = entry.expiresAt; + return projectionId && + target && + purpose && + preview && + state && + (expiresAt === null || typeof expiresAt === "number") + ? [{ projectionId, target, purpose, preview, state, expiresAt }] + : []; + }) + : []; + const postboxItems = Array.isArray(value.postboxItems) + ? value.postboxItems.flatMap((entry) => { + if (!isRecord(entry)) { + return []; + } + const itemId = asText(entry.itemId); + const state = asText(entry.state); + const sourceChannelRef = asText(entry.sourceChannelRef); + return itemId && state && sourceChannelRef && typeof entry.createdAt === "number" + ? [{ itemId, state, sourceChannelRef, createdAt: entry.createdAt }] + : []; + }) + : []; + return { postboxMode: value.postboxMode, projections, postboxItems }; +} + +function emptyProjectionForm(): ProjectionForm { + return { + projectionId: "", + sourceRevisionId: "", + targetKind: "conversation", + targetId: "", + targetStoreId: "", + purpose: "", + preview: "", + content: "", + expiresAt: "", + noExpiryAuditReason: "", + }; +} + +/** Profile-derived sharing controls. This element never accepts or renders a principal or store id. */ +class MemorySharingElement extends OpenClawLightDomElement { + @property({ attribute: false }) client: GatewayBrowserClient | null = null; + @property({ type: Boolean }) connected = false; + @property({ type: Boolean }) canAdmin = false; + @property({ type: Boolean }) methodsAvailable = false; + @property() agentId: string | null = null; + + @state() private status: SharingStatus | null = null; + @state() private form = emptyProjectionForm(); + @state() private inspectedBodies = new Map(); + @state() private impact = new Map(); + @state() private previewReady = false; + @state() private busy = false; + @state() private error: string | null = null; + + private loadGeneration = 0; + + protected override willUpdate(changed: PropertyValues) { + if ( + changed.has("client") || + changed.has("connected") || + changed.has("canAdmin") || + changed.has("methodsAvailable") || + changed.has("agentId") + ) { + this.status = null; + this.inspectedBodies = new Map(); + this.impact = new Map(); + this.previewReady = false; + if (changed.has("agentId")) { + this.form = emptyProjectionForm(); + } + void this.load(); + } + } + + private canUse(): this is this & { client: GatewayBrowserClient; agentId: string } { + return Boolean( + this.connected && this.canAdmin && this.methodsAvailable && this.client && this.agentId, + ); + } + + private async load() { + if (!this.canUse()) { + return; + } + const generation = ++this.loadGeneration; + try { + const response = await this.client.request("memory.sharing.status", { + agentId: this.agentId, + }); + if (!this.canUse() || generation !== this.loadGeneration) { + return; + } + const status = parseStatus(response); + if (!status) { + throw new Error("invalid sharing status"); + } + this.status = status; + } catch { + if (generation === this.loadGeneration) { + this.error = t("memoryPage.sharing.requestFailed"); + } + } + } + + private async request(method: string, payload: Record): Promise { + if (!this.canUse() || this.busy) { + return null; + } + this.busy = true; + this.error = null; + try { + return await this.client.request(method, { agentId: this.agentId, ...payload }); + } catch { + this.error = t("memoryPage.sharing.requestFailed"); + return null; + } finally { + this.busy = false; + } + } + + private updateForm(key: keyof ProjectionForm, value: string) { + this.form = { ...this.form, [key]: value }; + this.previewReady = false; + } + + private projectionPayload(options: { + content: boolean; + refresh: boolean; + }): Record | null { + const form = this.form; + const sourceRevisionId = form.sourceRevisionId.trim(); + const purpose = form.purpose.trim(); + const preview = form.preview.trim(); + const expiry = form.expiresAt.trim(); + const noExpiryAuditReason = form.noExpiryAuditReason.trim(); + if ( + !sourceRevisionId || + !purpose || + !preview || + Boolean(expiry) === Boolean(noExpiryAuditReason) || + (options.content && !form.content.trim()) || + (options.refresh && !form.projectionId.trim()) + ) { + this.error = t("memoryPage.sharing.completeRequiredFields"); + return null; + } + if (!options.refresh && !form.targetId.trim()) { + this.error = t("memoryPage.sharing.completeRequiredFields"); + return null; + } + if (!isProjectionTargetKind(form.targetKind)) { + this.error = t("memoryPage.sharing.completeRequiredFields"); + return null; + } + if (form.targetKind === "agent-shared" && form.targetId.trim() !== this.agentId) { + this.error = t("memoryPage.sharing.invalidAgentSharedTarget"); + return null; + } + return { + sourceRevisionId, + purpose, + preview, + ...(options.refresh + ? { projectionId: form.projectionId.trim() } + : { targetKind: form.targetKind, targetId: form.targetId.trim() }), + ...(options.content ? { content: form.content.trim() } : {}), + ...(expiry ? { expiresAt: expiry } : { noExpiryAuditReason }), + }; + } + + private async previewProjection() { + const payload = this.projectionPayload({ content: false, refresh: false }); + if (!payload) { + return; + } + const response = await this.request("memory.sharing.projection.preview", payload); + if (response !== null) { + this.previewReady = true; + } + } + + private async registerProjectionTarget() { + const targetId = this.form.targetId.trim(); + const storeId = this.form.targetStoreId.trim(); + if (!targetId || !storeId) { + this.error = t("memoryPage.sharing.completeRequiredFields"); + return; + } + if (!isProjectionTargetKind(this.form.targetKind)) { + this.error = t("memoryPage.sharing.completeRequiredFields"); + return; + } + if (this.form.targetKind === "agent-shared" && targetId !== this.agentId) { + this.error = t("memoryPage.sharing.invalidAgentSharedTarget"); + return; + } + await this.request("memory.sharing.projection.target.register", { + targetKind: this.form.targetKind, + targetId, + storeId, + }); + } + + private async saveProjection() { + const refreshing = Boolean(this.form.projectionId.trim()); + if (!this.previewReady && !refreshing) { + this.error = t("memoryPage.sharing.previewRequired"); + return; + } + const payload = this.projectionPayload({ content: true, refresh: refreshing }); + if (!payload) { + return; + } + const response = await this.request( + refreshing ? "memory.sharing.projection.refresh" : "memory.sharing.projection.create", + payload, + ); + if (response !== null) { + this.form = emptyProjectionForm(); + this.previewReady = false; + await this.load(); + } + } + + private async revokeProjection(projectionId: string) { + const response = await this.request("memory.sharing.projection.revoke", { projectionId }); + if (response !== null) { + await this.load(); + } + } + + private prepareRefresh(projection: SharingStatus["projections"][number]) { + this.form = { + ...emptyProjectionForm(), + projectionId: projection.projectionId, + purpose: projection.purpose, + preview: projection.preview, + }; + this.previewReady = false; + } + + private async loadImpact(projectionId: string) { + const response = await this.request("memory.sharing.projection.impact", { projectionId }); + if (!isRecord(response) || !Array.isArray(response.exposureSetIds)) { + return; + } + const exposureSetIds = response.exposureSetIds.filter( + (entry): entry is string => typeof entry === "string", + ); + this.impact = new Map(this.impact).set(projectionId, exposureSetIds); + } + + private async setPostboxMode(mode: "off" | "review-required") { + const response = await this.request("memory.sharing.postbox.mode.set", { mode }); + if (response !== null) { + await this.load(); + } + } + + private async inspectPostbox(itemId: string) { + const response = await this.request("memory.sharing.postbox.inspect", { itemId }); + if (!isRecord(response) || typeof response.content !== "string") { + return; + } + this.inspectedBodies = new Map(this.inspectedBodies).set(itemId, response.content); + } + + private async reviewPostbox(itemId: string, decision: "approve" | "reject") { + const reviewedContent = this.inspectedBodies.get(itemId)?.trim(); + const response = await this.request("memory.sharing.postbox.review", { + itemId, + decision, + ...(decision === "approve" && reviewedContent ? { reviewedContent } : {}), + }); + if (response !== null) { + this.inspectedBodies = new Map(this.inspectedBodies); + this.inspectedBodies.delete(itemId); + await this.load(); + } + } + + private async purgePostbox(itemId: string) { + const response = await this.request("memory.sharing.postbox.purge", { itemId }); + if (response !== null) { + this.inspectedBodies = new Map(this.inspectedBodies); + this.inspectedBodies.delete(itemId); + await this.load(); + } + } + + private renderProjectionForm() { + const form = this.form; + const refresh = Boolean(form.projectionId); + return renderSettingsSection( + { + title: t("memoryPage.sharing.projection.title"), + description: t("memoryPage.sharing.projection.description"), + }, + html` +
+ + + ${refresh + ? nothing + : html` + + + + `} + + + + +
+ +

+ ${refresh + ? nothing + : html` + `} + +

+ `, + ); + } + + override render() { + if (!this.canUse()) { + return nothing; + } + const status = this.status; + return html` +
+

${t("memoryPage.sharing.title")}

+

${t("memoryPage.sharing.intro")}

+ ${this.error ? html`

${this.error}

` : nothing} + ${renderSettingsSection( + { title: t("memoryPage.sharing.statusTitle") }, + html` + ${renderSettingsRow({ + title: t("memoryPage.sharing.postboxMode"), + control: html``, + })} + ${renderSettingsRow({ + title: t("memoryPage.sharing.projectionCount"), + control: renderSettingsValue(String(status?.projections.length ?? 0)), + })} + ${renderSettingsRow({ + title: t("memoryPage.sharing.postboxCount"), + control: renderSettingsValue(String(status?.postboxItems.length ?? 0)), + })} + `, + )} + ${this.renderProjectionForm()} + ${renderSettingsSection( + { title: t("memoryPage.sharing.projections") }, + status?.projections.length + ? status.projections.map( + (projection) => html` + ${renderSettingsRow({ + title: projection.purpose, + description: `${projection.target.kind}: ${projection.target.id} ยท ${projection.preview}`, + control: renderSettingsValue(projection.state), + })} +

+ + + +

+ ${(this.impact.get(projection.projectionId) ?? []).length + ? html`

+ ${t("memoryPage.sharing.priorExposure", { + count: String(this.impact.get(projection.projectionId)?.length ?? 0), + })} +

` + : nothing} + `, + ) + : renderSettingsRow({ title: t("memoryPage.sharing.emptyProjections") }), + )} + ${renderSettingsSection( + { title: t("memoryPage.sharing.postbox") }, + status?.postboxItems.length + ? status.postboxItems.map( + (item) => html` + ${renderSettingsRow({ + title: item.sourceChannelRef, + description: item.state, + control: renderSettingsValue(item.itemId, { mono: true }), + })} + ${this.inspectedBodies.has(item.itemId) + ? html`` + : nothing} +

+ + + + +

+ `, + ) + : renderSettingsRow({ title: t("memoryPage.sharing.emptyPostbox") }), + )} +
+ `; + } +} + +if (!customElements.get("openclaw-memory-sharing")) { + customElements.define("openclaw-memory-sharing", MemorySharingElement); +} diff --git a/ui/src/pages/config/memory.test.ts b/ui/src/pages/config/memory.test.ts index bd78269a0238..c1915b1e6c4e 100644 --- a/ui/src/pages/config/memory.test.ts +++ b/ui/src/pages/config/memory.test.ts @@ -57,6 +57,7 @@ function createProps(overrides: Partial = {}): MemoryViewProps dreams: html`
`, editor: html`
`, dreamingSettings: html`
`, + sharing: html`
`, agentId: "main", agents: [ { value: "main", label: "Main" }, diff --git a/ui/src/pages/config/memory.ts b/ui/src/pages/config/memory.ts index cfc53b40accf..69962def2149 100644 --- a/ui/src/pages/config/memory.ts +++ b/ui/src/pages/config/memory.ts @@ -180,6 +180,8 @@ type MemoryViewProps = { editor: TemplateResult; /** Global dreaming controls, sharing runtimeConfig with the editor above. */ dreamingSettings: TemplateResult; + /** Authenticated, profile-derived projection and postbox controls. */ + sharing: TemplateResult; agentId: string | null; agents: readonly AgentSelectOption[]; onAgentChange: (agentId: string | null) => void; @@ -378,7 +380,7 @@ function renderSettingsTab(props: MemoryViewProps) { ${props.editor}
- ${props.dreamingSettings} + ${props.dreamingSettings} ${props.sharing} ${renderSettingsSection( { title: t("memoryPage.import.title"), description: t("memoryPage.import.description") }, renderSettingsRow({