diff --git a/docs/.generated/plugin-sdk-api-baseline/agent-harness-runtime.json b/docs/.generated/plugin-sdk-api-baseline/agent-harness-runtime.json index 44cb5b153d06..00a1846395c5 100644 --- a/docs/.generated/plugin-sdk-api-baseline/agent-harness-runtime.json +++ b/docs/.generated/plugin-sdk-api-baseline/agent-harness-runtime.json @@ -1 +1 @@ -{"contentHash":"94b1959bd0129a903cc4608ebf04f4107a76e9c63f83ce765ebabaf5d351880d","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime"} +{"contentHash":"7c5c92898e62f52b09c51a1dd55bcb758eb8a40a983cf9c079c913d95dba3b58","entrypoint":"agent-harness-runtime","importSpecifier":"openclaw/plugin-sdk/agent-harness-runtime"} diff --git a/docs/.generated/plugin-sdk-api-baseline/agent-harness.json b/docs/.generated/plugin-sdk-api-baseline/agent-harness.json index a2b89178b392..eb842b6f71af 100644 --- a/docs/.generated/plugin-sdk-api-baseline/agent-harness.json +++ b/docs/.generated/plugin-sdk-api-baseline/agent-harness.json @@ -1 +1 @@ -{"contentHash":"8d05bd692044b96ea39dc57b57d85d5ab0d203890d07e30205f881a36ff1ef9a","entrypoint":"agent-harness","importSpecifier":"openclaw/plugin-sdk/agent-harness"} +{"contentHash":"0069a9c1609324d148c10ae79fed31195bbd8d866a864d546ef8df3a9eb6f2eb","entrypoint":"agent-harness","importSpecifier":"openclaw/plugin-sdk/agent-harness"} diff --git a/docs/.generated/plugin-sdk-api-baseline/agent-runtime.json b/docs/.generated/plugin-sdk-api-baseline/agent-runtime.json index b8b62a9afd99..2d3344a79325 100644 --- a/docs/.generated/plugin-sdk-api-baseline/agent-runtime.json +++ b/docs/.generated/plugin-sdk-api-baseline/agent-runtime.json @@ -1 +1 @@ -{"contentHash":"a74e00e9516ef7432d3328e8427b8b6a9b328fa046be88a0f6f8a9dfb2f9eb93","entrypoint":"agent-runtime","importSpecifier":"openclaw/plugin-sdk/agent-runtime"} +{"contentHash":"c7afeee04708492266b2cb6d742b00d6a1e170971a08b40a6178dae914eb6723","entrypoint":"agent-runtime","importSpecifier":"openclaw/plugin-sdk/agent-runtime"} diff --git a/docs/.generated/plugin-sdk-api-baseline/channel-core.json b/docs/.generated/plugin-sdk-api-baseline/channel-core.json index 170f39f00e10..ea79a9a77bcd 100644 --- a/docs/.generated/plugin-sdk-api-baseline/channel-core.json +++ b/docs/.generated/plugin-sdk-api-baseline/channel-core.json @@ -1 +1 @@ -{"contentHash":"2f55da92897662de7da62b07293cfa08436d4d3d3f2e001f7f17ba9d3f6b857d","entrypoint":"channel-core","importSpecifier":"openclaw/plugin-sdk/channel-core"} +{"contentHash":"7a28969db8490d4b3c3f6f8c05db564ec89508030523a95a8a4248f8d9072edf","entrypoint":"channel-core","importSpecifier":"openclaw/plugin-sdk/channel-core"} diff --git a/docs/.generated/plugin-sdk-api-baseline/channel-entry-contract.json b/docs/.generated/plugin-sdk-api-baseline/channel-entry-contract.json index e7b96725f291..df49669131e1 100644 --- a/docs/.generated/plugin-sdk-api-baseline/channel-entry-contract.json +++ b/docs/.generated/plugin-sdk-api-baseline/channel-entry-contract.json @@ -1 +1 @@ -{"contentHash":"c1581b642422551d651709070c1f514766bb4f8b1839156d108bf21f40385dfd","entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract"} +{"contentHash":"532feed49e6fd72b81b4ce744d7284519158999cebb31db751174470fb63a3cc","entrypoint":"channel-entry-contract","importSpecifier":"openclaw/plugin-sdk/channel-entry-contract"} diff --git a/docs/.generated/plugin-sdk-api-baseline/channel-message.json b/docs/.generated/plugin-sdk-api-baseline/channel-message.json index 8a0f5f193e7e..935ab373e9c6 100644 --- a/docs/.generated/plugin-sdk-api-baseline/channel-message.json +++ b/docs/.generated/plugin-sdk-api-baseline/channel-message.json @@ -1 +1 @@ -{"contentHash":"0cefff48a3bb852d24762e709f6a1a18ec4c5995b58f98cf00e32e802f888b99","entrypoint":"channel-message","importSpecifier":"openclaw/plugin-sdk/channel-message"} +{"contentHash":"68796f883fb54466351cb0a077f3fd1f71ad6d6d1df53248f0d382e77a5f486f","entrypoint":"channel-message","importSpecifier":"openclaw/plugin-sdk/channel-message"} diff --git a/docs/.generated/plugin-sdk-api-baseline/channel-outbound.json b/docs/.generated/plugin-sdk-api-baseline/channel-outbound.json index 25aef6df43ef..9519f5d7802f 100644 --- a/docs/.generated/plugin-sdk-api-baseline/channel-outbound.json +++ b/docs/.generated/plugin-sdk-api-baseline/channel-outbound.json @@ -1 +1 @@ -{"contentHash":"c1cecc011c8dd65c39772504918f421d06f20a19d9a3f69ca8f65c5d0386337c","entrypoint":"channel-outbound","importSpecifier":"openclaw/plugin-sdk/channel-outbound"} +{"contentHash":"69a92cf59ee4dd7c66431a80aed3f32e0b4e830789e4cab7b4173ec2d502bcfc","entrypoint":"channel-outbound","importSpecifier":"openclaw/plugin-sdk/channel-outbound"} diff --git a/docs/.generated/plugin-sdk-api-baseline/channel-plugin-common.json b/docs/.generated/plugin-sdk-api-baseline/channel-plugin-common.json index 18853a22c401..7804a4fc9a80 100644 --- a/docs/.generated/plugin-sdk-api-baseline/channel-plugin-common.json +++ b/docs/.generated/plugin-sdk-api-baseline/channel-plugin-common.json @@ -1 +1 @@ -{"contentHash":"cd8df374743a9e8e837f91554524b5269028ddf956715e73388553285143abcc","entrypoint":"channel-plugin-common","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common"} +{"contentHash":"22ee5f9631d28579af7419f2e1263ecfa903f557b3b3e9962769e3a1fb61489d","entrypoint":"channel-plugin-common","importSpecifier":"openclaw/plugin-sdk/channel-plugin-common"} diff --git a/docs/.generated/plugin-sdk-api-baseline/core.json b/docs/.generated/plugin-sdk-api-baseline/core.json index f536bdc7f560..03b4e2c561c9 100644 --- a/docs/.generated/plugin-sdk-api-baseline/core.json +++ b/docs/.generated/plugin-sdk-api-baseline/core.json @@ -1 +1 @@ -{"contentHash":"2d415a89cd6c86f74c93c53bf1f50542da8c86f6740834523c04c3fff17ce112","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core"} +{"contentHash":"432dc3f2d69b09ae1f8c64bf5c1b4f43d2a748ab79d90862ff2a9aadaa4af43f","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core"} diff --git a/docs/.generated/plugin-sdk-api-baseline/discord.json b/docs/.generated/plugin-sdk-api-baseline/discord.json index 8e550bdad3a8..c4eb214fdeb3 100644 --- a/docs/.generated/plugin-sdk-api-baseline/discord.json +++ b/docs/.generated/plugin-sdk-api-baseline/discord.json @@ -1 +1 @@ -{"contentHash":"774f94ebc272467ca053e63578576e51d14e33c3f7d4b6d3d87bf6dbf8a9ee2c","entrypoint":"discord","importSpecifier":"openclaw/plugin-sdk/discord"} +{"contentHash":"1f02b35bfc99cc8bdeea415dc430d832a74d9b1ff7e52243fea224a7a006425b","entrypoint":"discord","importSpecifier":"openclaw/plugin-sdk/discord"} diff --git a/docs/.generated/plugin-sdk-api-baseline/inbound-reply-dispatch.json b/docs/.generated/plugin-sdk-api-baseline/inbound-reply-dispatch.json index 7aa01fe70bf0..31051a3d2432 100644 --- a/docs/.generated/plugin-sdk-api-baseline/inbound-reply-dispatch.json +++ b/docs/.generated/plugin-sdk-api-baseline/inbound-reply-dispatch.json @@ -1 +1 @@ -{"contentHash":"0f532b319124103380919829d8f11052c67b2481619c10da0be3c15bc1780757","entrypoint":"inbound-reply-dispatch","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch"} +{"contentHash":"6bff1e7ef600d59cfbe7adb7a67ed9ffe8173e50f89ba618f6f190e90fc74da9","entrypoint":"inbound-reply-dispatch","importSpecifier":"openclaw/plugin-sdk/inbound-reply-dispatch"} diff --git a/docs/.generated/plugin-sdk-api-baseline/meeting-runtime.json b/docs/.generated/plugin-sdk-api-baseline/meeting-runtime.json index 576cb60709a6..f1e14495da41 100644 --- a/docs/.generated/plugin-sdk-api-baseline/meeting-runtime.json +++ b/docs/.generated/plugin-sdk-api-baseline/meeting-runtime.json @@ -1 +1 @@ -{"contentHash":"b5d401c0fb43b473847b554efe1b8c543bf4b36936eb63b8cc999b117b8a6cff","entrypoint":"meeting-runtime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime"} +{"contentHash":"8e07f0c6667ff6dfcafdf2dc98be90b0cc6aa8d8449bd1e35227976c63c4f8df","entrypoint":"meeting-runtime","importSpecifier":"openclaw/plugin-sdk/meeting-runtime"} diff --git a/docs/.generated/plugin-sdk-api-baseline/plugin-entry.json b/docs/.generated/plugin-sdk-api-baseline/plugin-entry.json index 9f6ed027176e..793be537e40e 100644 --- a/docs/.generated/plugin-sdk-api-baseline/plugin-entry.json +++ b/docs/.generated/plugin-sdk-api-baseline/plugin-entry.json @@ -1 +1 @@ -{"contentHash":"39f96b2b6eda3ca580e8acaeae00326869852191ddb98e93e2a1fd0859528e26","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry"} +{"contentHash":"9be8b6ce4a747459accac5b8b4a64023f464d437d1117e3148b1199461dbb402","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry"} diff --git a/docs/.generated/plugin-sdk-api-baseline/plugin-runtime.json b/docs/.generated/plugin-sdk-api-baseline/plugin-runtime.json index 22093ac430dd..1e30f507e7b0 100644 --- a/docs/.generated/plugin-sdk-api-baseline/plugin-runtime.json +++ b/docs/.generated/plugin-sdk-api-baseline/plugin-runtime.json @@ -1 +1 @@ -{"contentHash":"623d1669c4d237d6628b2ba36546f173b93f0b589aa8403c166e8d297e8ecb6a","entrypoint":"plugin-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime"} +{"contentHash":"c2e4b880b08c352ba57f781a0c629d15066c5842a287dac3727b1dd5d8561811","entrypoint":"plugin-runtime","importSpecifier":"openclaw/plugin-sdk/plugin-runtime"} diff --git a/docs/.generated/plugin-sdk-api-baseline/provider-catalog-runtime.json b/docs/.generated/plugin-sdk-api-baseline/provider-catalog-runtime.json index 30ef34688d56..973f26435acd 100644 --- a/docs/.generated/plugin-sdk-api-baseline/provider-catalog-runtime.json +++ b/docs/.generated/plugin-sdk-api-baseline/provider-catalog-runtime.json @@ -1 +1 @@ -{"contentHash":"e31e5f3718f4843b3a7290ec60b747e2764585fad20bd2b55d739c12820246e1","entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime"} +{"contentHash":"e4df60d58a485eed9e2b1509dded473da589102ad14a4ae7ba5cedb2250dc33c","entrypoint":"provider-catalog-runtime","importSpecifier":"openclaw/plugin-sdk/provider-catalog-runtime"} diff --git a/docs/.generated/plugin-sdk-api-baseline/tool-plugin.json b/docs/.generated/plugin-sdk-api-baseline/tool-plugin.json index fe5298bec620..d590c1404cc3 100644 --- a/docs/.generated/plugin-sdk-api-baseline/tool-plugin.json +++ b/docs/.generated/plugin-sdk-api-baseline/tool-plugin.json @@ -1 +1 @@ -{"contentHash":"d58f7527e51a8d16f49aaaad6b7bd5d366fd89152539427735e3ffe7090ebf11","entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin"} +{"contentHash":"06fad1eff295b30e25b2aa52c6259e67f2e74c15a5bd7f15e9e5e6c3d9be4934","entrypoint":"tool-plugin","importSpecifier":"openclaw/plugin-sdk/tool-plugin"} diff --git a/docs/.generated/plugin-sdk-api-baseline/webhook-ingress.json b/docs/.generated/plugin-sdk-api-baseline/webhook-ingress.json index 90bf5d34f88a..01d28b4c5232 100644 --- a/docs/.generated/plugin-sdk-api-baseline/webhook-ingress.json +++ b/docs/.generated/plugin-sdk-api-baseline/webhook-ingress.json @@ -1 +1 @@ -{"contentHash":"7a4f8a5c6a523c2440769ca3d6fbd9e5b590207e013c2f00624d3ebcec5a72e6","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress"} +{"contentHash":"6e792826511277b2940a7e788cffdaa647dff60767073ec0a0278d3d6319535d","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress"} diff --git a/src/config/sessions/session-accessor.sqlite-active-events.ts b/src/config/sessions/session-accessor.sqlite-active-events.ts index 24aaf71f2dfe..49e2036f3f3d 100644 --- a/src/config/sessions/session-accessor.sqlite-active-events.ts +++ b/src/config/sessions/session-accessor.sqlite-active-events.ts @@ -63,10 +63,9 @@ export type SessionTranscriptBoundedMessageTailPage = SessionTranscriptMessageEv serializedBytes: number; }; -export type SessionTranscriptBoundedContextMessageTailPage = - SessionTranscriptBoundedMessageTailPage & { - contextSummary?: { text: string; ts: number }; - }; +type SessionTranscriptBoundedContextMessageTailPage = SessionTranscriptBoundedMessageTailPage & { + contextSummary?: { text: string; ts: number }; +}; function parseMessageEventRow(row: { event_json: string; diff --git a/src/gateway/server-runtime-subscriptions.ts b/src/gateway/server-runtime-subscriptions.ts index e21236a09400..16bb3029f525 100644 --- a/src/gateway/server-runtime-subscriptions.ts +++ b/src/gateway/server-runtime-subscriptions.ts @@ -29,6 +29,7 @@ import type { } from "./server-chat-state.js"; import { resolveVisibleActiveSessionRunState } from "./server-methods/session-active-runs.js"; import { mapTaskSummary, type TaskEventPayload } from "./server-methods/task-summary.js"; +import { defaultSessionCompanionContextReader } from "./session-companion-context.js"; import { createSessionCompanion } from "./session-companion.js"; import { createSessionObserver } from "./session-observer.js"; import type { TerminalSessionManager } from "./terminal/session-manager.js"; @@ -96,6 +97,7 @@ export function startGatewayEventSubscriptions(params: { broadcastToConnIds: params.broadcastToConnIds, }); const sessionCompanion = createSessionCompanion({ + contextReader: defaultSessionCompanionContextReader, getConfig: getRuntimeConfig, sessionObserver, }); diff --git a/src/gateway/session-companion-ask.ts b/src/gateway/session-companion-ask.ts index 9a335064efbd..f14a4efab465 100644 --- a/src/gateway/session-companion-ask.ts +++ b/src/gateway/session-companion-ask.ts @@ -10,10 +10,7 @@ import type { OpenClawConfig } from "../config/types.openclaw.js"; import type { Message, Usage } from "../llm/types.js"; import { redactToolPayloadText } from "../logging/redact.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; -import { - defaultSessionCompanionContextReader, - type SessionCompanionContextReader, -} from "./session-companion-context.js"; +import type { SessionCompanionContextReader } from "./session-companion-context.js"; import { buildSessionCompanionRunConfig, SESSION_COMPANION_TOOLS, @@ -58,7 +55,7 @@ export type SessionCompanionAskDeps = { getCompanionSnapshot: (sessionKey: string) => SessionObserverCompanionSnapshot; }; resolveUtilityModelRef?: typeof resolveUtilityModelRefForAgent; - contextReader?: SessionCompanionContextReader; + contextReader: SessionCompanionContextReader; run?: (params: SessionCompanionRunParams) => Promise; now?: () => number; setTimeoutFn?: typeof setTimeout; @@ -366,7 +363,7 @@ function contextError( export function createSessionCompanionAskRuntime(params: SessionCompanionAskRuntimeParams) { const resolveUtilityModelRef = params.resolveUtilityModelRef ?? resolveUtilityModelRefForAgent; - const contextReader = params.contextReader ?? defaultSessionCompanionContextReader; + const contextReader = params.contextReader; const run = params.run ?? defaultRun; const setTimeoutFn = params.setTimeoutFn ?? setTimeout; const clearTimeoutFn = params.clearTimeoutFn ?? clearTimeout; diff --git a/src/gateway/session-companion-context.ts b/src/gateway/session-companion-context.ts index d5ad69459ba4..1f3947974911 100644 --- a/src/gateway/session-companion-context.ts +++ b/src/gateway/session-companion-context.ts @@ -8,6 +8,10 @@ import { readSessionTranscriptBoundedContextMessageTailPage, } from "../config/sessions/session-accessor.sqlite-active-events.js"; import { redactToolPayloadText } from "../logging/redact.js"; +import type { + SessionCompanionContextMessage, + SessionCompanionPreparedContext, +} from "./session-companion-state.js"; import { loadSessionEntryReadOnly } from "./session-utils.js"; const CONTEXT_MAX_MESSAGES = 40; @@ -17,18 +21,6 @@ const CONTEXT_READ_PAGE_MESSAGES = CONTEXT_MAX_MESSAGES * 4; const CONTEXT_READ_MAX_SCANNED_MESSAGES = 4096; const CONTEXT_READ_MAX_BYTES = 1024 * 1024; -type SessionCompanionContextMessage = { - role: "assistant" | "summary" | "user"; - text: string; - ts: number; -}; - -export type SessionCompanionPreparedContext = { - empty: boolean; - messages: SessionCompanionContextMessage[]; - sessionId: string; -}; - type SessionCompanionContextReadResult = | { kind: "ready"; context: SessionCompanionPreparedContext } | { kind: "missing" } diff --git a/src/gateway/session-companion-state.ts b/src/gateway/session-companion-state.ts index ff80661db218..f72f8e19463c 100644 --- a/src/gateway/session-companion-state.ts +++ b/src/gateway/session-companion-state.ts @@ -1,7 +1,19 @@ import type { SessionCompanionExchange } from "../../packages/gateway-protocol/src/schema/sessions.js"; +export type SessionCompanionContextMessage = { + role: "assistant" | "summary" | "user"; + text: string; + ts: number; +}; + +export type SessionCompanionPreparedContext = { + empty: boolean; + messages: SessionCompanionContextMessage[]; + sessionId: string; +}; + export type SessionCompanionThread = { - context: import("./session-companion-context.js").SessionCompanionPreparedContext; + context: SessionCompanionPreparedContext; digestText: string; exchanges: SessionCompanionExchange[]; lastNoteSequence: number; diff --git a/src/gateway/session-companion.test.ts b/src/gateway/session-companion.test.ts index 71f5efcb6a6f..3b0d26240d5b 100644 --- a/src/gateway/session-companion.test.ts +++ b/src/gateway/session-companion.test.ts @@ -62,13 +62,13 @@ function createHarness(overrides?: { })), ); const deps = { + contextReader: { currentSessionId, read: readContext }, getConfig: () => cfg, sessionObserver: { getCompanionSnapshot }, resolveUtilityModelRef: () => "openai/gpt-5.6-luna", run, now: overrides?.now ?? (() => 100), }; - Object.assign(deps, { contextReader: { currentSessionId, read: readContext } }); const service = createSessionCompanion(deps); return { currentSessionId, getCompanionSnapshot, readContext, run, service }; } diff --git a/ui/src/pages/chat/components/chat-session-rail.ts b/ui/src/pages/chat/components/chat-session-rail.ts index b2353ee1e64b..84cf6ca51f02 100644 --- a/ui/src/pages/chat/components/chat-session-rail.ts +++ b/ui/src/pages/chat/components/chat-session-rail.ts @@ -202,23 +202,22 @@ function companionHasActivity(thread: ChatSessionCompanionThread): boolean { ); } +const COMPANION_HINT_KEYS = { + busy: "chat.rail.askBusy", + "history-unavailable": "chat.rail.askHistoryUnavailable", + missing: "chat.rail.askMissing", + "model-unavailable": "chat.rail.askModelUnavailable", + "rate-limited": "chat.rail.askRateLimited", + unavailable: "chat.rail.askUnavailable", +} as const satisfies Record< + NonNullable, + Parameters[0] +>; + function companionHintKey( hint: NonNullable, ): Parameters[0] { - switch (hint) { - case "busy": - return "chat.rail.askBusy"; - case "history-unavailable": - return "chat.rail.askHistoryUnavailable"; - case "missing": - return "chat.rail.askMissing"; - case "model-unavailable": - return "chat.rail.askModelUnavailable"; - case "rate-limited": - return "chat.rail.askRateLimited"; - case "unavailable": - return "chat.rail.askUnavailable"; - } + return COMPANION_HINT_KEYS[hint]; } export class ChatSessionRailElement extends OpenClawLightDomElement {