mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 11:18:37 +00:00
refactor(agents): share sandboxed session tool context
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
import { callGateway } from "../../gateway/call.js";
|
import { callGateway } from "../../gateway/call.js";
|
||||||
import { isAcpSessionKey, normalizeMainKey } from "../../routing/session-key.js";
|
import {
|
||||||
|
isAcpSessionKey,
|
||||||
|
isSubagentSessionKey,
|
||||||
|
normalizeMainKey,
|
||||||
|
} from "../../routing/session-key.js";
|
||||||
import { sanitizeUserFacingText } from "../pi-embedded-helpers.js";
|
import { sanitizeUserFacingText } from "../pi-embedded-helpers.js";
|
||||||
import {
|
import {
|
||||||
stripDowngradedToolCallText,
|
stripDowngradedToolCallText,
|
||||||
@@ -69,6 +73,39 @@ export function resolveInternalSessionKey(params: { key: string; alias: string;
|
|||||||
return params.key;
|
return params.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveSandboxSessionToolsVisibility(cfg: OpenClawConfig): "spawned" | "all" {
|
||||||
|
return cfg.agents?.defaults?.sandbox?.sessionToolsVisibility ?? "spawned";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveSandboxedSessionToolContext(params: {
|
||||||
|
cfg: OpenClawConfig;
|
||||||
|
agentSessionKey?: string;
|
||||||
|
sandboxed?: boolean;
|
||||||
|
}): {
|
||||||
|
mainKey: string;
|
||||||
|
alias: string;
|
||||||
|
visibility: "spawned" | "all";
|
||||||
|
requesterInternalKey: string | undefined;
|
||||||
|
restrictToSpawned: boolean;
|
||||||
|
} {
|
||||||
|
const { mainKey, alias } = resolveMainSessionAlias(params.cfg);
|
||||||
|
const visibility = resolveSandboxSessionToolsVisibility(params.cfg);
|
||||||
|
const requesterInternalKey =
|
||||||
|
typeof params.agentSessionKey === "string" && params.agentSessionKey.trim()
|
||||||
|
? resolveInternalSessionKey({
|
||||||
|
key: params.agentSessionKey,
|
||||||
|
alias,
|
||||||
|
mainKey,
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
const restrictToSpawned =
|
||||||
|
params.sandboxed === true &&
|
||||||
|
visibility === "spawned" &&
|
||||||
|
!!requesterInternalKey &&
|
||||||
|
!isSubagentSessionKey(requesterInternalKey);
|
||||||
|
return { mainKey, alias, visibility, requesterInternalKey, restrictToSpawned };
|
||||||
|
}
|
||||||
|
|
||||||
export type AgentToAgentPolicy = {
|
export type AgentToAgentPolicy = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
matchesAllow: (agentId: string) => boolean;
|
matchesAllow: (agentId: string) => boolean;
|
||||||
|
|||||||
@@ -3,15 +3,14 @@ import type { AnyAgentTool } from "./common.js";
|
|||||||
import { loadConfig } from "../../config/config.js";
|
import { loadConfig } from "../../config/config.js";
|
||||||
import { callGateway } from "../../gateway/call.js";
|
import { callGateway } from "../../gateway/call.js";
|
||||||
import { capArrayByJsonBytes } from "../../gateway/session-utils.fs.js";
|
import { capArrayByJsonBytes } from "../../gateway/session-utils.fs.js";
|
||||||
import { isSubagentSessionKey, resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||||
import { truncateUtf16Safe } from "../../utils.js";
|
import { truncateUtf16Safe } from "../../utils.js";
|
||||||
import { jsonResult, readStringParam } from "./common.js";
|
import { jsonResult, readStringParam } from "./common.js";
|
||||||
import {
|
import {
|
||||||
createAgentToAgentPolicy,
|
createAgentToAgentPolicy,
|
||||||
resolveSessionReference,
|
resolveSessionReference,
|
||||||
resolveMainSessionAlias,
|
|
||||||
resolveInternalSessionKey,
|
|
||||||
SessionListRow,
|
SessionListRow,
|
||||||
|
resolveSandboxedSessionToolContext,
|
||||||
stripToolMessages,
|
stripToolMessages,
|
||||||
} from "./sessions-helpers.js";
|
} from "./sessions-helpers.js";
|
||||||
|
|
||||||
@@ -24,6 +23,8 @@ const SessionsHistoryToolSchema = Type.Object({
|
|||||||
const SESSIONS_HISTORY_MAX_BYTES = 80 * 1024;
|
const SESSIONS_HISTORY_MAX_BYTES = 80 * 1024;
|
||||||
const SESSIONS_HISTORY_TEXT_MAX_CHARS = 4000;
|
const SESSIONS_HISTORY_TEXT_MAX_CHARS = 4000;
|
||||||
|
|
||||||
|
// sandbox policy handling is shared with sessions-list-tool via sessions-helpers.ts
|
||||||
|
|
||||||
function truncateHistoryText(text: string): { text: string; truncated: boolean } {
|
function truncateHistoryText(text: string): { text: string; truncated: boolean } {
|
||||||
if (text.length <= SESSIONS_HISTORY_TEXT_MAX_CHARS) {
|
if (text.length <= SESSIONS_HISTORY_TEXT_MAX_CHARS) {
|
||||||
return { text, truncated: false };
|
return { text, truncated: false };
|
||||||
@@ -146,10 +147,6 @@ function enforceSessionsHistoryHardCap(params: {
|
|||||||
return { items: placeholder, bytes: jsonUtf8Bytes(placeholder), hardCapped: true };
|
return { items: placeholder, bytes: jsonUtf8Bytes(placeholder), hardCapped: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveSandboxSessionToolsVisibility(cfg: ReturnType<typeof loadConfig>) {
|
|
||||||
return cfg.agents?.defaults?.sandbox?.sessionToolsVisibility ?? "spawned";
|
|
||||||
}
|
|
||||||
|
|
||||||
async function isSpawnedSessionAllowed(params: {
|
async function isSpawnedSessionAllowed(params: {
|
||||||
requesterSessionKey: string;
|
requesterSessionKey: string;
|
||||||
targetSessionKey: string;
|
targetSessionKey: string;
|
||||||
@@ -186,21 +183,12 @@ export function createSessionsHistoryTool(opts?: {
|
|||||||
required: true,
|
required: true,
|
||||||
});
|
});
|
||||||
const cfg = loadConfig();
|
const cfg = loadConfig();
|
||||||
const { mainKey, alias } = resolveMainSessionAlias(cfg);
|
const { mainKey, alias, requesterInternalKey, restrictToSpawned } =
|
||||||
const visibility = resolveSandboxSessionToolsVisibility(cfg);
|
resolveSandboxedSessionToolContext({
|
||||||
const requesterInternalKey =
|
cfg,
|
||||||
typeof opts?.agentSessionKey === "string" && opts.agentSessionKey.trim()
|
agentSessionKey: opts?.agentSessionKey,
|
||||||
? resolveInternalSessionKey({
|
sandboxed: opts?.sandboxed,
|
||||||
key: opts.agentSessionKey,
|
});
|
||||||
alias,
|
|
||||||
mainKey,
|
|
||||||
})
|
|
||||||
: undefined;
|
|
||||||
const restrictToSpawned =
|
|
||||||
opts?.sandboxed === true &&
|
|
||||||
visibility === "spawned" &&
|
|
||||||
!!requesterInternalKey &&
|
|
||||||
!isSubagentSessionKey(requesterInternalKey);
|
|
||||||
const resolvedSession = await resolveSessionReference({
|
const resolvedSession = await resolveSessionReference({
|
||||||
sessionKey: sessionKeyParam,
|
sessionKey: sessionKeyParam,
|
||||||
alias,
|
alias,
|
||||||
@@ -215,7 +203,7 @@ export function createSessionsHistoryTool(opts?: {
|
|||||||
const resolvedKey = resolvedSession.key;
|
const resolvedKey = resolvedSession.key;
|
||||||
const displayKey = resolvedSession.displayKey;
|
const displayKey = resolvedSession.displayKey;
|
||||||
const resolvedViaSessionId = resolvedSession.resolvedViaSessionId;
|
const resolvedViaSessionId = resolvedSession.resolvedViaSessionId;
|
||||||
if (restrictToSpawned && !resolvedViaSessionId) {
|
if (restrictToSpawned && requesterInternalKey && !resolvedViaSessionId) {
|
||||||
const ok = await isSpawnedSessionAllowed({
|
const ok = await isSpawnedSessionAllowed({
|
||||||
requesterSessionKey: requesterInternalKey,
|
requesterSessionKey: requesterInternalKey,
|
||||||
targetSessionKey: resolvedKey,
|
targetSessionKey: resolvedKey,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { AnyAgentTool } from "./common.js";
|
|||||||
import { loadConfig } from "../../config/config.js";
|
import { loadConfig } from "../../config/config.js";
|
||||||
import { resolveSessionFilePath } from "../../config/sessions.js";
|
import { resolveSessionFilePath } from "../../config/sessions.js";
|
||||||
import { callGateway } from "../../gateway/call.js";
|
import { callGateway } from "../../gateway/call.js";
|
||||||
import { isSubagentSessionKey, resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
import { resolveAgentIdFromSessionKey } from "../../routing/session-key.js";
|
||||||
import { jsonResult, readStringArrayParam } from "./common.js";
|
import { jsonResult, readStringArrayParam } from "./common.js";
|
||||||
import {
|
import {
|
||||||
createAgentToAgentPolicy,
|
createAgentToAgentPolicy,
|
||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
deriveChannel,
|
deriveChannel,
|
||||||
resolveDisplaySessionKey,
|
resolveDisplaySessionKey,
|
||||||
resolveInternalSessionKey,
|
resolveInternalSessionKey,
|
||||||
resolveMainSessionAlias,
|
resolveSandboxedSessionToolContext,
|
||||||
type SessionListRow,
|
type SessionListRow,
|
||||||
stripToolMessages,
|
stripToolMessages,
|
||||||
} from "./sessions-helpers.js";
|
} from "./sessions-helpers.js";
|
||||||
@@ -24,10 +24,6 @@ const SessionsListToolSchema = Type.Object({
|
|||||||
messageLimit: Type.Optional(Type.Number({ minimum: 0 })),
|
messageLimit: Type.Optional(Type.Number({ minimum: 0 })),
|
||||||
});
|
});
|
||||||
|
|
||||||
function resolveSandboxSessionToolsVisibility(cfg: ReturnType<typeof loadConfig>) {
|
|
||||||
return cfg.agents?.defaults?.sandbox?.sessionToolsVisibility ?? "spawned";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createSessionsListTool(opts?: {
|
export function createSessionsListTool(opts?: {
|
||||||
agentSessionKey?: string;
|
agentSessionKey?: string;
|
||||||
sandboxed?: boolean;
|
sandboxed?: boolean;
|
||||||
@@ -40,21 +36,12 @@ export function createSessionsListTool(opts?: {
|
|||||||
execute: async (_toolCallId, args) => {
|
execute: async (_toolCallId, args) => {
|
||||||
const params = args as Record<string, unknown>;
|
const params = args as Record<string, unknown>;
|
||||||
const cfg = loadConfig();
|
const cfg = loadConfig();
|
||||||
const { mainKey, alias } = resolveMainSessionAlias(cfg);
|
const { mainKey, alias, requesterInternalKey, restrictToSpawned } =
|
||||||
const visibility = resolveSandboxSessionToolsVisibility(cfg);
|
resolveSandboxedSessionToolContext({
|
||||||
const requesterInternalKey =
|
cfg,
|
||||||
typeof opts?.agentSessionKey === "string" && opts.agentSessionKey.trim()
|
agentSessionKey: opts?.agentSessionKey,
|
||||||
? resolveInternalSessionKey({
|
sandboxed: opts?.sandboxed,
|
||||||
key: opts.agentSessionKey,
|
});
|
||||||
alias,
|
|
||||||
mainKey,
|
|
||||||
})
|
|
||||||
: undefined;
|
|
||||||
const restrictToSpawned =
|
|
||||||
opts?.sandboxed === true &&
|
|
||||||
visibility === "spawned" &&
|
|
||||||
requesterInternalKey &&
|
|
||||||
!isSubagentSessionKey(requesterInternalKey);
|
|
||||||
|
|
||||||
const kindsRaw = readStringArrayParam(params, "kinds")?.map((value) =>
|
const kindsRaw = readStringArrayParam(params, "kinds")?.map((value) =>
|
||||||
value.trim().toLowerCase(),
|
value.trim().toLowerCase(),
|
||||||
|
|||||||
Reference in New Issue
Block a user