mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-30 01:06:11 +00:00
Agents: route embedded discovery and compaction ids
This commit is contained in:
@@ -91,6 +91,7 @@ import {
|
||||
import { getDmHistoryLimitFromSessionKey, limitHistoryTurns } from "./history.js";
|
||||
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
||||
import { log } from "./logger.js";
|
||||
import { buildEmbeddedMessageActionDiscoveryInput } from "./message-action-discovery-input.js";
|
||||
import { buildModelAliasLines, resolveModelAsync } from "./model.js";
|
||||
import { buildEmbeddedSandboxInfo } from "./sandbox-info.js";
|
||||
import { prewarmSessionFile, trackSessionManagerAccess } from "./session-manager-cache.js";
|
||||
@@ -116,7 +117,8 @@ export type CompactEmbeddedPiSessionParams = {
|
||||
currentChannelId?: string;
|
||||
currentThreadTs?: string;
|
||||
currentMessageId?: string | number;
|
||||
requesterSenderId?: string;
|
||||
/** Trusted sender id from inbound context for scoped message-tool discovery. */
|
||||
senderId?: string;
|
||||
authProfileId?: string;
|
||||
/** Group id for channel-level tool policy resolution. */
|
||||
groupId?: string | null;
|
||||
@@ -659,18 +661,20 @@ export async function compactEmbeddedPiSessionDirect(
|
||||
});
|
||||
// Resolve channel-specific message actions for system prompt
|
||||
const channelActions = runtimeChannel
|
||||
? listChannelSupportedActions({
|
||||
cfg: params.config,
|
||||
channel: runtimeChannel,
|
||||
currentChannelId: params.currentChannelId,
|
||||
currentThreadTs: params.currentThreadTs,
|
||||
currentMessageId: params.currentMessageId,
|
||||
accountId: params.agentAccountId,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: sessionAgentId,
|
||||
requesterSenderId: params.requesterSenderId,
|
||||
})
|
||||
? listChannelSupportedActions(
|
||||
buildEmbeddedMessageActionDiscoveryInput({
|
||||
cfg: params.config,
|
||||
channel: runtimeChannel,
|
||||
currentChannelId: params.currentChannelId,
|
||||
currentThreadTs: params.currentThreadTs,
|
||||
currentMessageId: params.currentMessageId,
|
||||
accountId: params.agentAccountId,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: sessionAgentId,
|
||||
senderId: params.senderId,
|
||||
}),
|
||||
)
|
||||
: undefined;
|
||||
const messageToolHints = runtimeChannel
|
||||
? resolveChannelMessageToolHints({
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { buildEmbeddedCompactionRuntimeContext } from "./compaction-runtime-context.js";
|
||||
|
||||
describe("buildEmbeddedCompactionRuntimeContext", () => {
|
||||
it("preserves sender and current message routing for compaction", () => {
|
||||
expect(
|
||||
buildEmbeddedCompactionRuntimeContext({
|
||||
sessionKey: "agent:main:thread:1",
|
||||
messageChannel: "slack",
|
||||
messageProvider: "slack",
|
||||
agentAccountId: "acct-1",
|
||||
currentChannelId: "C123",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
authProfileId: "openai:p1",
|
||||
workspaceDir: "/tmp/workspace",
|
||||
agentDir: "/tmp/agent",
|
||||
config: {} as OpenClawConfig,
|
||||
senderIsOwner: true,
|
||||
senderId: "user-123",
|
||||
provider: "openai-codex",
|
||||
modelId: "gpt-5.3-codex",
|
||||
thinkLevel: "off",
|
||||
reasoningLevel: "on",
|
||||
extraSystemPrompt: "extra",
|
||||
ownerNumbers: ["+15555550123"],
|
||||
}),
|
||||
).toMatchObject({
|
||||
sessionKey: "agent:main:thread:1",
|
||||
messageChannel: "slack",
|
||||
messageProvider: "slack",
|
||||
agentAccountId: "acct-1",
|
||||
currentChannelId: "C123",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
authProfileId: "openai:p1",
|
||||
workspaceDir: "/tmp/workspace",
|
||||
agentDir: "/tmp/agent",
|
||||
senderId: "user-123",
|
||||
provider: "openai-codex",
|
||||
model: "gpt-5.3-codex",
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes nullable compaction routing fields to undefined", () => {
|
||||
expect(
|
||||
buildEmbeddedCompactionRuntimeContext({
|
||||
sessionKey: null,
|
||||
messageChannel: null,
|
||||
messageProvider: null,
|
||||
agentAccountId: null,
|
||||
currentChannelId: null,
|
||||
currentThreadTs: null,
|
||||
currentMessageId: null,
|
||||
authProfileId: null,
|
||||
workspaceDir: "/tmp/workspace",
|
||||
agentDir: "/tmp/agent",
|
||||
senderId: null,
|
||||
provider: null,
|
||||
modelId: null,
|
||||
}),
|
||||
).toMatchObject({
|
||||
sessionKey: undefined,
|
||||
messageChannel: undefined,
|
||||
messageProvider: undefined,
|
||||
agentAccountId: undefined,
|
||||
currentChannelId: undefined,
|
||||
currentThreadTs: undefined,
|
||||
currentMessageId: undefined,
|
||||
authProfileId: undefined,
|
||||
senderId: undefined,
|
||||
provider: undefined,
|
||||
model: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
76
src/agents/pi-embedded-runner/compaction-runtime-context.ts
Normal file
76
src/agents/pi-embedded-runner/compaction-runtime-context.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js";
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import type { ExecElevatedDefaults } from "../bash-tools.js";
|
||||
import type { SkillSnapshot } from "../skills.js";
|
||||
|
||||
export type EmbeddedCompactionRuntimeContext = {
|
||||
sessionKey?: string;
|
||||
messageChannel?: string;
|
||||
messageProvider?: string;
|
||||
agentAccountId?: string;
|
||||
currentChannelId?: string;
|
||||
currentThreadTs?: string;
|
||||
currentMessageId?: string | number;
|
||||
authProfileId?: string;
|
||||
workspaceDir: string;
|
||||
agentDir: string;
|
||||
config?: OpenClawConfig;
|
||||
skillsSnapshot?: SkillSnapshot;
|
||||
senderIsOwner?: boolean;
|
||||
senderId?: string;
|
||||
provider?: string;
|
||||
model?: string;
|
||||
thinkLevel?: ThinkLevel;
|
||||
reasoningLevel?: ReasoningLevel;
|
||||
bashElevated?: ExecElevatedDefaults;
|
||||
extraSystemPrompt?: string;
|
||||
ownerNumbers?: string[];
|
||||
};
|
||||
|
||||
export function buildEmbeddedCompactionRuntimeContext(params: {
|
||||
sessionKey?: string | null;
|
||||
messageChannel?: string | null;
|
||||
messageProvider?: string | null;
|
||||
agentAccountId?: string | null;
|
||||
currentChannelId?: string | null;
|
||||
currentThreadTs?: string | null;
|
||||
currentMessageId?: string | number | null;
|
||||
authProfileId?: string | null;
|
||||
workspaceDir: string;
|
||||
agentDir: string;
|
||||
config?: OpenClawConfig;
|
||||
skillsSnapshot?: SkillSnapshot;
|
||||
senderIsOwner?: boolean;
|
||||
senderId?: string | null;
|
||||
provider?: string | null;
|
||||
modelId?: string | null;
|
||||
thinkLevel?: ThinkLevel;
|
||||
reasoningLevel?: ReasoningLevel;
|
||||
bashElevated?: ExecElevatedDefaults;
|
||||
extraSystemPrompt?: string;
|
||||
ownerNumbers?: string[];
|
||||
}): EmbeddedCompactionRuntimeContext {
|
||||
return {
|
||||
sessionKey: params.sessionKey ?? undefined,
|
||||
messageChannel: params.messageChannel ?? undefined,
|
||||
messageProvider: params.messageProvider ?? undefined,
|
||||
agentAccountId: params.agentAccountId ?? undefined,
|
||||
currentChannelId: params.currentChannelId ?? undefined,
|
||||
currentThreadTs: params.currentThreadTs ?? undefined,
|
||||
currentMessageId: params.currentMessageId ?? undefined,
|
||||
authProfileId: params.authProfileId ?? undefined,
|
||||
workspaceDir: params.workspaceDir,
|
||||
agentDir: params.agentDir,
|
||||
config: params.config,
|
||||
skillsSnapshot: params.skillsSnapshot,
|
||||
senderIsOwner: params.senderIsOwner,
|
||||
senderId: params.senderId ?? undefined,
|
||||
provider: params.provider ?? undefined,
|
||||
model: params.modelId ?? undefined,
|
||||
thinkLevel: params.thinkLevel,
|
||||
reasoningLevel: params.reasoningLevel,
|
||||
bashElevated: params.bashElevated,
|
||||
extraSystemPrompt: params.extraSystemPrompt,
|
||||
ownerNumbers: params.ownerNumbers,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildEmbeddedMessageActionDiscoveryInput } from "./message-action-discovery-input.js";
|
||||
|
||||
describe("buildEmbeddedMessageActionDiscoveryInput", () => {
|
||||
it("maps sender and routing scope into message-action discovery context", () => {
|
||||
expect(
|
||||
buildEmbeddedMessageActionDiscoveryInput({
|
||||
channel: "telegram",
|
||||
currentChannelId: "chat-1",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
accountId: "acct-1",
|
||||
sessionKey: "agent:main:thread:1",
|
||||
sessionId: "session-1",
|
||||
agentId: "main",
|
||||
senderId: "user-123",
|
||||
}),
|
||||
).toEqual({
|
||||
cfg: undefined,
|
||||
channel: "telegram",
|
||||
currentChannelId: "chat-1",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
accountId: "acct-1",
|
||||
sessionKey: "agent:main:thread:1",
|
||||
sessionId: "session-1",
|
||||
agentId: "main",
|
||||
requesterSenderId: "user-123",
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes nullable routing fields to undefined", () => {
|
||||
expect(
|
||||
buildEmbeddedMessageActionDiscoveryInput({
|
||||
channel: "slack",
|
||||
currentChannelId: null,
|
||||
currentThreadTs: null,
|
||||
currentMessageId: null,
|
||||
accountId: null,
|
||||
sessionKey: null,
|
||||
sessionId: null,
|
||||
agentId: null,
|
||||
senderId: null,
|
||||
}),
|
||||
).toEqual({
|
||||
cfg: undefined,
|
||||
channel: "slack",
|
||||
currentChannelId: undefined,
|
||||
currentThreadTs: undefined,
|
||||
currentMessageId: undefined,
|
||||
accountId: undefined,
|
||||
sessionKey: undefined,
|
||||
sessionId: undefined,
|
||||
agentId: undefined,
|
||||
requesterSenderId: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
|
||||
export function buildEmbeddedMessageActionDiscoveryInput(params: {
|
||||
cfg?: OpenClawConfig;
|
||||
channel: string;
|
||||
currentChannelId?: string | null;
|
||||
currentThreadTs?: string | null;
|
||||
currentMessageId?: string | number | null;
|
||||
accountId?: string | null;
|
||||
sessionKey?: string | null;
|
||||
sessionId?: string | null;
|
||||
agentId?: string | null;
|
||||
senderId?: string | null;
|
||||
}) {
|
||||
return {
|
||||
cfg: params.cfg,
|
||||
channel: params.channel,
|
||||
currentChannelId: params.currentChannelId ?? undefined,
|
||||
currentThreadTs: params.currentThreadTs ?? undefined,
|
||||
currentMessageId: params.currentMessageId ?? undefined,
|
||||
accountId: params.accountId ?? undefined,
|
||||
sessionKey: params.sessionKey ?? undefined,
|
||||
sessionId: params.sessionId ?? undefined,
|
||||
agentId: params.agentId ?? undefined,
|
||||
requesterSenderId: params.senderId ?? undefined,
|
||||
};
|
||||
}
|
||||
@@ -65,6 +65,7 @@ import {
|
||||
import { ensureRuntimePluginsLoaded } from "../runtime-plugins.js";
|
||||
import { derivePromptTokens, normalizeUsage, type UsageLike } from "../usage.js";
|
||||
import { redactRunIdentifier, resolveRunWorkspaceDir } from "../workspace-run.js";
|
||||
import { buildEmbeddedCompactionRuntimeContext } from "./compaction-runtime-context.js";
|
||||
import { resolveGlobalLane, resolveSessionLane } from "./lanes.js";
|
||||
import { log } from "./logger.js";
|
||||
import { resolveModelAsync } from "./model.js";
|
||||
@@ -1141,24 +1142,30 @@ export async function runEmbeddedPiAgent(
|
||||
force: true,
|
||||
compactionTarget: "budget",
|
||||
runtimeContext: {
|
||||
sessionKey: params.sessionKey,
|
||||
messageChannel: params.messageChannel,
|
||||
messageProvider: params.messageProvider,
|
||||
agentAccountId: params.agentAccountId,
|
||||
authProfileId: lastProfileId,
|
||||
workspaceDir: resolvedWorkspace,
|
||||
agentDir,
|
||||
config: params.config,
|
||||
skillsSnapshot: params.skillsSnapshot,
|
||||
senderIsOwner: params.senderIsOwner,
|
||||
provider,
|
||||
model: modelId,
|
||||
...buildEmbeddedCompactionRuntimeContext({
|
||||
sessionKey: params.sessionKey,
|
||||
messageChannel: params.messageChannel,
|
||||
messageProvider: params.messageProvider,
|
||||
agentAccountId: params.agentAccountId,
|
||||
currentChannelId: params.currentChannelId,
|
||||
currentThreadTs: params.currentThreadTs,
|
||||
currentMessageId: params.currentMessageId,
|
||||
authProfileId: lastProfileId,
|
||||
workspaceDir: resolvedWorkspace,
|
||||
agentDir,
|
||||
config: params.config,
|
||||
skillsSnapshot: params.skillsSnapshot,
|
||||
senderIsOwner: params.senderIsOwner,
|
||||
senderId: params.senderId,
|
||||
provider,
|
||||
modelId,
|
||||
thinkLevel,
|
||||
reasoningLevel: params.reasoningLevel,
|
||||
bashElevated: params.bashElevated,
|
||||
extraSystemPrompt: params.extraSystemPrompt,
|
||||
ownerNumbers: params.ownerNumbers,
|
||||
}),
|
||||
runId: params.runId,
|
||||
thinkLevel,
|
||||
reasoningLevel: params.reasoningLevel,
|
||||
bashElevated: params.bashElevated,
|
||||
extraSystemPrompt: params.extraSystemPrompt,
|
||||
ownerNumbers: params.ownerNumbers,
|
||||
trigger: "overflow",
|
||||
...(observedOverflowTokens !== undefined
|
||||
? { currentTokenCount: observedOverflowTokens }
|
||||
|
||||
@@ -1249,4 +1249,38 @@ describe("buildAfterTurnRuntimeContext", () => {
|
||||
agentDir: "/tmp/agent",
|
||||
});
|
||||
});
|
||||
|
||||
it("preserves sender and channel routing context for scoped compaction discovery", () => {
|
||||
const legacy = buildAfterTurnRuntimeContext({
|
||||
attempt: {
|
||||
sessionKey: "agent:main:session:abc",
|
||||
messageChannel: "slack",
|
||||
messageProvider: "slack",
|
||||
agentAccountId: "acct-1",
|
||||
currentChannelId: "C123",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
authProfileId: "openai:p1",
|
||||
config: {} as OpenClawConfig,
|
||||
skillsSnapshot: undefined,
|
||||
senderIsOwner: true,
|
||||
senderId: "user-123",
|
||||
provider: "openai-codex",
|
||||
modelId: "gpt-5.3-codex",
|
||||
thinkLevel: "off",
|
||||
reasoningLevel: "on",
|
||||
extraSystemPrompt: "extra",
|
||||
ownerNumbers: ["+15555550123"],
|
||||
},
|
||||
workspaceDir: "/tmp/workspace",
|
||||
agentDir: "/tmp/agent",
|
||||
});
|
||||
|
||||
expect(legacy).toMatchObject({
|
||||
senderId: "user-123",
|
||||
currentChannelId: "C123",
|
||||
currentThreadTs: "thread-9",
|
||||
currentMessageId: "msg-42",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -101,6 +101,7 @@ import { DEFAULT_BOOTSTRAP_FILENAME } from "../../workspace.js";
|
||||
import { isRunnerAbortError } from "../abort.js";
|
||||
import { appendCacheTtlTimestamp, isCacheTtlEligibleProvider } from "../cache-ttl.js";
|
||||
import type { CompactEmbeddedPiSessionParams } from "../compact.js";
|
||||
import { buildEmbeddedCompactionRuntimeContext } from "../compaction-runtime-context.js";
|
||||
import { resolveCompactionTimeoutMs } from "../compaction-safety-timeout.js";
|
||||
import { buildEmbeddedExtensionFactories } from "../extensions.js";
|
||||
import { applyExtraParamsToAgent } from "../extra-params.js";
|
||||
@@ -111,6 +112,7 @@ import {
|
||||
} from "../google.js";
|
||||
import { getDmHistoryLimitFromSessionKey, limitHistoryTurns } from "../history.js";
|
||||
import { log } from "../logger.js";
|
||||
import { buildEmbeddedMessageActionDiscoveryInput } from "../message-action-discovery-input.js";
|
||||
import { buildModelAliasLines } from "../model.js";
|
||||
import {
|
||||
clearActiveEmbeddedRun,
|
||||
@@ -1280,9 +1282,13 @@ export function buildAfterTurnRuntimeContext(params: {
|
||||
| "messageChannel"
|
||||
| "messageProvider"
|
||||
| "agentAccountId"
|
||||
| "currentChannelId"
|
||||
| "currentThreadTs"
|
||||
| "currentMessageId"
|
||||
| "config"
|
||||
| "skillsSnapshot"
|
||||
| "senderIsOwner"
|
||||
| "senderId"
|
||||
| "provider"
|
||||
| "modelId"
|
||||
| "thinkLevel"
|
||||
@@ -1295,25 +1301,29 @@ export function buildAfterTurnRuntimeContext(params: {
|
||||
workspaceDir: string;
|
||||
agentDir: string;
|
||||
}): Partial<CompactEmbeddedPiSessionParams> {
|
||||
return {
|
||||
return buildEmbeddedCompactionRuntimeContext({
|
||||
sessionKey: params.attempt.sessionKey,
|
||||
messageChannel: params.attempt.messageChannel,
|
||||
messageProvider: params.attempt.messageProvider,
|
||||
agentAccountId: params.attempt.agentAccountId,
|
||||
currentChannelId: params.attempt.currentChannelId,
|
||||
currentThreadTs: params.attempt.currentThreadTs,
|
||||
currentMessageId: params.attempt.currentMessageId,
|
||||
authProfileId: params.attempt.authProfileId,
|
||||
workspaceDir: params.workspaceDir,
|
||||
agentDir: params.agentDir,
|
||||
config: params.attempt.config,
|
||||
skillsSnapshot: params.attempt.skillsSnapshot,
|
||||
senderIsOwner: params.attempt.senderIsOwner,
|
||||
senderId: params.attempt.senderId,
|
||||
provider: params.attempt.provider,
|
||||
model: params.attempt.modelId,
|
||||
modelId: params.attempt.modelId,
|
||||
thinkLevel: params.attempt.thinkLevel,
|
||||
reasoningLevel: params.attempt.reasoningLevel,
|
||||
bashElevated: params.attempt.bashElevated,
|
||||
extraSystemPrompt: params.attempt.extraSystemPrompt,
|
||||
ownerNumbers: params.attempt.ownerNumbers,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function summarizeMessagePayload(msg: AgentMessage): { textChars: number; imageBlocks: number } {
|
||||
@@ -1620,17 +1630,20 @@ export async function runEmbeddedAttempt(
|
||||
const reasoningTagHint = isReasoningTagProvider(params.provider);
|
||||
// Resolve channel-specific message actions for system prompt
|
||||
const channelActions = runtimeChannel
|
||||
? listChannelSupportedActions({
|
||||
cfg: params.config,
|
||||
channel: runtimeChannel,
|
||||
currentChannelId: params.currentChannelId,
|
||||
currentThreadTs: params.currentThreadTs,
|
||||
currentMessageId: params.currentMessageId,
|
||||
accountId: params.agentAccountId,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: sessionAgentId,
|
||||
})
|
||||
? listChannelSupportedActions(
|
||||
buildEmbeddedMessageActionDiscoveryInput({
|
||||
cfg: params.config,
|
||||
channel: runtimeChannel,
|
||||
currentChannelId: params.currentChannelId,
|
||||
currentThreadTs: params.currentThreadTs,
|
||||
currentMessageId: params.currentMessageId,
|
||||
accountId: params.agentAccountId,
|
||||
sessionKey: params.sessionKey,
|
||||
sessionId: params.sessionId,
|
||||
agentId: sessionAgentId,
|
||||
senderId: params.senderId,
|
||||
}),
|
||||
)
|
||||
: undefined;
|
||||
const messageToolHints = runtimeChannel
|
||||
? resolveChannelMessageToolHints({
|
||||
|
||||
Reference in New Issue
Block a user