fix(cycles): split shared contract seams

This commit is contained in:
Vincent Koc
2026-04-11 01:34:04 +01:00
parent 95bc417944
commit 81235fd923
3 changed files with 43 additions and 133 deletions

View File

@@ -1,61 +1,28 @@
import type { OpenClawConfig } from "../../config/config.js";
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
import type { SandboxBackendHandle, SandboxBackendId } from "./backend-handle.types.js";
import type { SandboxRegistryEntry } from "./registry.js";
import type { SandboxConfig } from "./types.js";
import type {
RegisteredSandboxBackend,
SandboxBackendFactory,
SandboxBackendId,
SandboxBackendManager,
SandboxBackendRegistration,
} from "./backend.types.js";
export type {
CreateSandboxBackendParams,
SandboxBackendFactory,
SandboxBackendId,
SandboxBackendManager,
SandboxBackendRegistration,
SandboxBackendRuntimeInfo,
} from "./backend.types.js";
export type {
SandboxBackendCommandParams,
SandboxBackendCommandResult,
SandboxBackendExecSpec,
SandboxBackendHandle,
SandboxBackendId,
SandboxFsBridgeContext,
} from "./backend-handle.types.js";
export type SandboxBackendRuntimeInfo = {
running: boolean;
actualConfigLabel?: string;
configLabelMatch: boolean;
};
export type SandboxBackendManager = {
describeRuntime(params: {
entry: SandboxRegistryEntry;
config: OpenClawConfig;
agentId?: string;
}): Promise<SandboxBackendRuntimeInfo>;
removeRuntime(params: {
entry: SandboxRegistryEntry;
config: OpenClawConfig;
agentId?: string;
}): Promise<void>;
};
export type CreateSandboxBackendParams = {
sessionKey: string;
scopeKey: string;
workspaceDir: string;
agentWorkspaceDir: string;
cfg: SandboxConfig;
};
export type SandboxBackendFactory = (
params: CreateSandboxBackendParams,
) => Promise<SandboxBackendHandle>;
export type SandboxBackendRegistration =
| SandboxBackendFactory
| {
factory: SandboxBackendFactory;
manager?: SandboxBackendManager;
};
type RegisteredSandboxBackend = {
factory: SandboxBackendFactory;
manager?: SandboxBackendManager;
};
const SANDBOX_BACKEND_FACTORIES = new Map<SandboxBackendId, RegisteredSandboxBackend>();
function normalizeSandboxBackendId(id: string): SandboxBackendId {

View File

@@ -1,10 +1,10 @@
import { buildDockerExecArgs } from "../bash-tools.shared.js";
import type { SandboxBackendCommandParams } from "./backend-handle.types.js";
import type {
CreateSandboxBackendParams,
SandboxBackendManager,
SandboxBackendCommandParams,
SandboxBackendHandle,
} from "./backend.js";
SandboxBackendManager,
} from "./backend.types.js";
import { resolveSandboxConfigForAgent } from "./config.js";
import {
dockerContainerState,

View File

@@ -12,7 +12,6 @@ import type {
} from "../agents/auth-profiles/types.js";
import type { AgentHarness } from "../agents/harness/types.js";
import type { ModelCatalogEntry } from "../agents/model-catalog.types.js";
import type { AgentHarness } from "../agents/harness/types.js";
import type { FailoverReason } from "../agents/pi-embedded-helpers/types.js";
import type { ModelProviderRequestTransportOverrides } from "../agents/provider-request-config.js";
import type { ProviderSystemPromptContribution } from "../agents/system-prompt-contribution.js";
@@ -81,6 +80,18 @@ import type {
import type { DeliveryContext } from "../utils/delivery-context.js";
import type { VideoGenerationProvider } from "../video-generation/types.js";
import type { WizardPrompter } from "../wizard/prompts.js";
import {
PLUGIN_PROMPT_MUTATION_RESULT_FIELDS,
stripPromptMutationFieldsFromLegacyHookResult,
} from "./hook-before-agent-start.types.js";
import type {
PluginHookBeforeAgentStartEvent,
PluginHookBeforeAgentStartResult,
PluginHookBeforeModelResolveEvent,
PluginHookBeforeModelResolveResult,
PluginHookBeforePromptBuildEvent,
PluginHookBeforePromptBuildResult,
} from "./hook-before-agent-start.types.js";
import type { PluginKind } from "./plugin-kind.types.js";
import type { SecretInputMode } from "./provider-auth-types.js";
import type { createVpsAwareOAuthHandlers } from "./provider-oauth-flow.js";
@@ -93,6 +104,19 @@ import type { PluginRuntime } from "./runtime/types.js";
export type { PluginRuntime } from "./runtime/types.js";
export type { AnyAgentTool } from "../agents/tools/common.js";
export type { AgentHarness } from "../agents/harness/types.js";
export type {
PluginHookBeforeAgentStartEvent,
PluginHookBeforeAgentStartOverrideResult,
PluginHookBeforeAgentStartResult,
PluginHookBeforeModelResolveEvent,
PluginHookBeforeModelResolveResult,
PluginHookBeforePromptBuildEvent,
PluginHookBeforePromptBuildResult,
} from "./hook-before-agent-start.types.js";
export {
PLUGIN_PROMPT_MUTATION_RESULT_FIELDS,
stripPromptMutationFieldsFromLegacyHookResult,
} from "./hook-before-agent-start.types.js";
export type ProviderAuthOptionBag = {
token?: string;
@@ -2453,87 +2477,6 @@ export type PluginHookAgentContext = {
channelId?: string;
};
// before_model_resolve hook
export type PluginHookBeforeModelResolveEvent = {
/** User prompt for this run. No session messages are available yet in this phase. */
prompt: string;
};
export type PluginHookBeforeModelResolveResult = {
/** Override the model for this agent run. E.g. "llama3.3:8b" */
modelOverride?: string;
/** Override the provider for this agent run. E.g. "ollama" */
providerOverride?: string;
};
// before_prompt_build hook
export type PluginHookBeforePromptBuildEvent = {
prompt: string;
/** Session messages prepared for this run. */
messages: unknown[];
};
export type PluginHookBeforePromptBuildResult = {
systemPrompt?: string;
prependContext?: string;
/**
* Prepended to the agent system prompt so providers can cache it (e.g. prompt caching).
* Use for static plugin guidance instead of prependContext to avoid per-turn token cost.
*/
prependSystemContext?: string;
/**
* Appended to the agent system prompt so providers can cache it (e.g. prompt caching).
* Use for static plugin guidance instead of prependContext to avoid per-turn token cost.
*/
appendSystemContext?: string;
};
export const PLUGIN_PROMPT_MUTATION_RESULT_FIELDS = [
"systemPrompt",
"prependContext",
"prependSystemContext",
"appendSystemContext",
] as const satisfies readonly (keyof PluginHookBeforePromptBuildResult)[];
type MissingPluginPromptMutationResultFields = Exclude<
keyof PluginHookBeforePromptBuildResult,
(typeof PLUGIN_PROMPT_MUTATION_RESULT_FIELDS)[number]
>;
type AssertAllPluginPromptMutationResultFieldsListed =
MissingPluginPromptMutationResultFields extends never ? true : never;
const assertAllPluginPromptMutationResultFieldsListed: AssertAllPluginPromptMutationResultFieldsListed = true;
void assertAllPluginPromptMutationResultFieldsListed;
// before_agent_start hook (legacy compatibility: combines both phases)
export type PluginHookBeforeAgentStartEvent = {
prompt: string;
/** Optional because legacy hook can run in pre-session phase. */
messages?: unknown[];
};
export type PluginHookBeforeAgentStartResult = PluginHookBeforePromptBuildResult &
PluginHookBeforeModelResolveResult;
export type PluginHookBeforeAgentStartOverrideResult = Omit<
PluginHookBeforeAgentStartResult,
keyof PluginHookBeforePromptBuildResult
>;
export const stripPromptMutationFieldsFromLegacyHookResult = (
result: PluginHookBeforeAgentStartResult | void,
): PluginHookBeforeAgentStartOverrideResult | void => {
if (!result || typeof result !== "object") {
return result;
}
const remaining: Partial<PluginHookBeforeAgentStartResult> = { ...result };
for (const field of PLUGIN_PROMPT_MUTATION_RESULT_FIELDS) {
delete remaining[field];
}
return Object.keys(remaining).length > 0
? (remaining as PluginHookBeforeAgentStartOverrideResult)
: undefined;
};
// before_agent_reply hook
export type PluginHookBeforeAgentReplyEvent = {
/** The final user message text heading to the LLM (after commands/directives). */