mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
refactor: expose extension sdk boundary seams
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
eab8d67d3601d697253d2cc265ea3b18c719a0fa8ca6e983bf1edcd38b9382e7 plugin-sdk-api-baseline.json
|
||||
8c7e737467cb84d3a1c80c677cb94b26fe4d5739d154245c48d744aef80f53f8 plugin-sdk-api-baseline.jsonl
|
||||
5b59db88172a184e0cbac3301c51304686b6184c952ae5ed9f09b001dd65e3f3 plugin-sdk-api-baseline.json
|
||||
a195e76ddd1e09cb4023b247a684cd4e93c2662971adb4378ec126a78c537582 plugin-sdk-api-baseline.jsonl
|
||||
|
||||
@@ -257,7 +257,7 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview)
|
||||
| `plugin-sdk/webhook-path` | Webhook path normalization helpers |
|
||||
| `plugin-sdk/web-media` | Shared remote/local media loading helpers |
|
||||
| `plugin-sdk/zod` | Re-exported `zod` for plugin SDK consumers |
|
||||
| `plugin-sdk/testing` | Public extension test helpers including `installCommonResolveTargetErrorCases`, `shouldAckReaction`, `writeSkill`, `createTestRegistry`, and live generation env loading |
|
||||
| `plugin-sdk/testing` | Public extension test helpers including plugin registry/runtime mocks, schema/media/live-test helpers, `installCommonResolveTargetErrorCases`, `writeSkill`, `createTestRegistry`, and live generation env loading |
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Memory subpaths">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { AgentMessage } from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
|
||||
export type CodexContextProjection = {
|
||||
developerInstructionAddition?: string;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import type { AssistantMessage, Usage } from "@mariozechner/pi-ai";
|
||||
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
||||
import {
|
||||
@@ -13,6 +12,7 @@ import {
|
||||
runAgentHarnessAfterCompactionHook,
|
||||
runAgentHarnessBeforeCompactionHook,
|
||||
TOOL_PROGRESS_OUTPUT_MAX_CHARS,
|
||||
type AgentMessage,
|
||||
type EmbeddedRunAttemptParams,
|
||||
type EmbeddedRunAttemptResult,
|
||||
type MessagingToolSend,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import fs from "node:fs/promises";
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
||||
import {
|
||||
assembleHarnessContextEngine,
|
||||
@@ -29,6 +28,7 @@ import {
|
||||
registerNativeHookRelay,
|
||||
setActiveEmbeddedRun,
|
||||
supportsModelTools,
|
||||
type AgentMessage,
|
||||
type EmbeddedRunAttemptParams,
|
||||
type EmbeddedRunAttemptResult,
|
||||
type NativeHookRelayEvent,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
||||
import {
|
||||
acquireSessionWriteLock,
|
||||
emitSessionTranscriptUpdate,
|
||||
runAgentHarnessBeforeMessageWriteHook,
|
||||
type AgentMessage,
|
||||
} from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
|
||||
export async function mirrorCodexAppServerTranscript(params: {
|
||||
|
||||
@@ -2,6 +2,8 @@ import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { collectFilesSync, relativeToCwd } from "./check-file-utils.js";
|
||||
|
||||
type Offender = { file: string; hint: string; line?: number; specifier?: string };
|
||||
|
||||
const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
|
||||
{
|
||||
pattern: /["']openclaw\/plugin-sdk["']/,
|
||||
@@ -33,13 +35,10 @@ const FORBIDDEN_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
|
||||
},
|
||||
];
|
||||
|
||||
const FORBIDDEN_TEST_SUPPORT_PATTERNS: Array<{ pattern: RegExp; hint: string }> = [
|
||||
{
|
||||
pattern:
|
||||
/\b(?:import|export)\b[\s\S]*?\bfrom\s*["'](?:\.\.\/){2,}src\/(?:agents|channels|config|infra|plugins|routing|security|test-helpers|test-utils)\/[^"']+["']/,
|
||||
hint: "Use openclaw/plugin-sdk/testing or a focused plugin-sdk test/runtime subpath instead of core internals.",
|
||||
},
|
||||
];
|
||||
const STATIC_RELATIVE_MODULE_PATTERN = /\b(?:import|export)\b[\s\S]*?\bfrom\s*["']([^"']+)["']/g;
|
||||
|
||||
const RELATIVE_CORE_HINT =
|
||||
"Use openclaw/plugin-sdk/testing or a focused plugin-sdk test/runtime subpath instead of core internals.";
|
||||
|
||||
function isExtensionTestFile(filePath: string): boolean {
|
||||
return /\.test\.[cm]?[jt]sx?$/u.test(filePath) || /\.e2e\.test\.[cm]?[jt]sx?$/u.test(filePath);
|
||||
@@ -56,23 +55,57 @@ function collectExtensionTestFiles(rootDir: string): string[] {
|
||||
});
|
||||
}
|
||||
|
||||
function lineNumberForOffset(content: string, offset: number): number {
|
||||
let line = 1;
|
||||
for (let index = 0; index < offset; index += 1) {
|
||||
if (content.charCodeAt(index) === 10) {
|
||||
line += 1;
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
function resolvesToRepoSrc(filePath: string, specifier: string): boolean {
|
||||
if (!specifier.startsWith(".")) {
|
||||
return false;
|
||||
}
|
||||
const resolved = path.resolve(path.dirname(filePath), specifier);
|
||||
const repoRelative = path.relative(process.cwd(), resolved).replaceAll(path.sep, "/");
|
||||
return repoRelative === "src" || repoRelative.startsWith("src/");
|
||||
}
|
||||
|
||||
function collectRelativeCoreImportOffenders(filePath: string, content: string): Offender[] {
|
||||
const offenders: Offender[] = [];
|
||||
for (const match of content.matchAll(STATIC_RELATIVE_MODULE_PATTERN)) {
|
||||
const specifier = match[1];
|
||||
if (!specifier || !resolvesToRepoSrc(filePath, specifier)) {
|
||||
continue;
|
||||
}
|
||||
offenders.push({
|
||||
file: filePath,
|
||||
hint: RELATIVE_CORE_HINT,
|
||||
line: lineNumberForOffset(content, match.index ?? 0),
|
||||
specifier,
|
||||
});
|
||||
}
|
||||
return offenders;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const extensionsDir = path.join(process.cwd(), "extensions");
|
||||
const files = collectExtensionTestFiles(extensionsDir);
|
||||
const offenders: Array<{ file: string; hint: string }> = [];
|
||||
const offenders: Offender[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const content = fs.readFileSync(file, "utf8");
|
||||
const rules = isExtensionTestSupportFile(file)
|
||||
? [...FORBIDDEN_PATTERNS, ...FORBIDDEN_TEST_SUPPORT_PATTERNS]
|
||||
: FORBIDDEN_PATTERNS;
|
||||
for (const rule of rules) {
|
||||
for (const rule of FORBIDDEN_PATTERNS) {
|
||||
if (!rule.pattern.test(content)) {
|
||||
continue;
|
||||
}
|
||||
offenders.push({ file, hint: rule.hint });
|
||||
break;
|
||||
}
|
||||
offenders.push(...collectRelativeCoreImportOffenders(file, content));
|
||||
}
|
||||
|
||||
if (offenders.length > 0) {
|
||||
@@ -80,7 +113,11 @@ function main() {
|
||||
"Extension test files must stay on extension test bridges or public plugin-sdk surfaces.",
|
||||
);
|
||||
for (const offender of offenders.toSorted((a, b) => a.file.localeCompare(b.file))) {
|
||||
console.error(`- ${relativeToCwd(offender.file)}: ${offender.hint}`);
|
||||
const location = offender.line
|
||||
? `${relativeToCwd(offender.file)}:${offender.line}`
|
||||
: relativeToCwd(offender.file);
|
||||
const specifier = offender.specifier ? ` (${offender.specifier})` : "";
|
||||
console.error(`- ${location}${specifier}: ${offender.hint}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { truncateUtf16Safe } from "../utils.js";
|
||||
|
||||
export const TOOL_PROGRESS_OUTPUT_MAX_CHARS = 8_000;
|
||||
|
||||
export type { AgentMessage } from "@mariozechner/pi-agent-core";
|
||||
export type {
|
||||
AgentHarness,
|
||||
AgentHarnessAttemptParams,
|
||||
@@ -24,11 +25,12 @@ export type {
|
||||
EmbeddedRunAttemptParams,
|
||||
EmbeddedRunAttemptResult,
|
||||
} from "../agents/pi-embedded-runner/run/types.js";
|
||||
export type { ContextEngine as HarnessContextEngine } from "../context-engine/types.js";
|
||||
export type { CompactEmbeddedPiSessionParams } from "../agents/pi-embedded-runner/compact.js";
|
||||
export type { EmbeddedPiCompactResult } from "../agents/pi-embedded-runner/types.js";
|
||||
export type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
export type { MessagingToolSend } from "../agents/pi-embedded-messaging.types.js";
|
||||
export type { AgentApprovalEventData } from "../infra/agent-events.js";
|
||||
export type { AgentApprovalEventData, AgentEventPayload } from "../infra/agent-events.js";
|
||||
export type { ExecApprovalDecision } from "../infra/exec-approvals.js";
|
||||
export type { NormalizedUsage } from "../agents/usage.js";
|
||||
export type {
|
||||
@@ -57,8 +59,10 @@ export type {
|
||||
export { VERSION as OPENCLAW_VERSION } from "../version.js";
|
||||
export { formatErrorMessage } from "../infra/errors.js";
|
||||
export { formatApprovalDisplayPath } from "../infra/approval-display-paths.js";
|
||||
export { emitAgentEvent } from "../infra/agent-events.js";
|
||||
export { emitAgentEvent, onAgentEvent, resetAgentEventsForTest } from "../infra/agent-events.js";
|
||||
export { log as embeddedAgentLog } from "../agents/pi-embedded-runner/logger.js";
|
||||
export { buildAgentRuntimePlan } from "../agents/runtime-plan/build.js";
|
||||
export { classifyEmbeddedPiRunResultForModelFallback } from "../agents/pi-embedded-runner/result-fallback-classifier.js";
|
||||
export { resolveEmbeddedAgentRuntime } from "../agents/pi-embedded-runner/runtime.js";
|
||||
export { resolveUserPath } from "../utils.js";
|
||||
export { callGatewayTool } from "../agents/tools/gateway.js";
|
||||
@@ -123,6 +127,7 @@ export {
|
||||
} from "../agents/harness/lifecycle-hook-helpers.js";
|
||||
export {
|
||||
buildNativeHookRelayCommand,
|
||||
__testing as nativeHookRelayTesting,
|
||||
registerNativeHookRelay,
|
||||
} from "../agents/harness/native-hook-relay.js";
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Public agent/model/runtime helpers for plugins that integrate with core agent flows.
|
||||
|
||||
export * from "../agents/agent-scope.js";
|
||||
export { resolveOpenClawAgentDir } from "../agents/agent-paths.js";
|
||||
export * from "../agents/current-time.js";
|
||||
export * from "../agents/date-time.js";
|
||||
export * from "../agents/defaults.js";
|
||||
|
||||
@@ -8,6 +8,7 @@ export {
|
||||
resolvePluginConfigObject,
|
||||
} from "./plugin-config-runtime.js";
|
||||
export {
|
||||
clearConfigCache,
|
||||
clearRuntimeConfigSnapshot,
|
||||
getRuntimeConfigSourceSnapshot,
|
||||
getRuntimeConfigSnapshot,
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
/** Root OpenClaw configuration Zod schema — the full `openclaw.json` shape. */
|
||||
export { OpenClawSchema } from "../config/zod-schema.js";
|
||||
export { validateJsonSchemaValue } from "../plugins/schema-validator.js";
|
||||
export type { JsonSchemaObject } from "../shared/json-schema.types.js";
|
||||
|
||||
@@ -7,8 +7,11 @@ export type {
|
||||
} from "../infra/diagnostic-events.js";
|
||||
export {
|
||||
emitDiagnosticEvent,
|
||||
emitTrustedDiagnosticEvent,
|
||||
isDiagnosticsEnabled,
|
||||
onInternalDiagnosticEvent,
|
||||
onDiagnosticEvent,
|
||||
resetDiagnosticEventsForTest,
|
||||
} from "../infra/diagnostic-events.js";
|
||||
export type { DiagnosticTraceContext } from "../infra/diagnostic-trace-context.js";
|
||||
export {
|
||||
|
||||
@@ -3,3 +3,7 @@
|
||||
export * from "../hooks/fire-and-forget.js";
|
||||
export * from "../hooks/internal-hooks.js";
|
||||
export * from "../hooks/message-hook-mappers.js";
|
||||
export {
|
||||
initializeGlobalHookRunner,
|
||||
resetGlobalHookRunner,
|
||||
} from "../plugins/hook-runner-global.js";
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
export * from "../memory-host-sdk/engine-embeddings.js";
|
||||
export {
|
||||
clearMemoryEmbeddingProviders,
|
||||
registerMemoryEmbeddingProvider,
|
||||
} from "../plugins/memory-embedding-providers.js";
|
||||
|
||||
@@ -5,4 +5,9 @@ export type {
|
||||
MemoryCorpusSupplement,
|
||||
MemoryCorpusSupplementRegistration,
|
||||
} from "../plugins/memory-state.js";
|
||||
export { listMemoryCorpusSupplements } from "../plugins/memory-state.js";
|
||||
export {
|
||||
clearMemoryPluginState,
|
||||
listMemoryCorpusSupplements,
|
||||
registerMemoryCapability,
|
||||
registerMemoryCorpusSupplement,
|
||||
} from "../plugins/memory-state.js";
|
||||
|
||||
@@ -4,4 +4,5 @@ export {
|
||||
getProviderEnvVars,
|
||||
listKnownProviderAuthEnvVarNames,
|
||||
omitEnvKeysCaseInsensitive,
|
||||
resolveProviderAuthEnvVarCandidates,
|
||||
} from "../secrets/provider-env-vars.js";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export { buildGuardedModelFetch } from "../agents/provider-transport-fetch.js";
|
||||
export { buildOpenAICompletionsParams } from "../agents/openai-transport-stream.js";
|
||||
export { stripSystemPromptCacheBoundary } from "../agents/system-prompt-cache-boundary.js";
|
||||
export { transformTransportMessages } from "../agents/transport-message-transform.js";
|
||||
export {
|
||||
|
||||
@@ -6,5 +6,9 @@ export {
|
||||
resolveTextChunkLimit,
|
||||
} from "../auto-reply/chunk.js";
|
||||
export type { ChunkMode } from "../auto-reply/chunk.js";
|
||||
export { isSilentReplyText, SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
|
||||
export {
|
||||
isSilentReplyPayloadText,
|
||||
isSilentReplyText,
|
||||
SILENT_REPLY_TOKEN,
|
||||
} from "../auto-reply/tokens.js";
|
||||
export type { ReplyPayload } from "./reply-payload.js";
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
export { resolveCommandSecretRefsViaGateway } from "../cli/command-secret-gateway.js";
|
||||
export { getChannelsCommandSecretTargetIds } from "../cli/command-secret-targets.js";
|
||||
export { resolveSecretRefValues } from "../secrets/resolve.js";
|
||||
export { applyResolvedAssignments, createResolverContext } from "../secrets/runtime-shared.js";
|
||||
|
||||
@@ -30,6 +30,10 @@ export {
|
||||
resetPluginRuntimeStateForTest,
|
||||
setActivePluginRegistry,
|
||||
} from "../plugins/runtime.js";
|
||||
export {
|
||||
listImportedBundledPluginFacadeIds,
|
||||
resetFacadeRuntimeStateForTest,
|
||||
} from "./facade-runtime.js";
|
||||
export { capturePluginRegistration } from "../plugins/captured-registration.js";
|
||||
export { resolveProviderPluginChoice } from "../plugins/provider-auth-choice.runtime.js";
|
||||
export type { PluginRuntime } from "../plugins/runtime/types.js";
|
||||
@@ -40,9 +44,28 @@ export {
|
||||
createRequestCaptureJsonFetch,
|
||||
installPinnedHostnameTestHooks,
|
||||
} from "../media-understanding/audio.test-helpers.ts";
|
||||
export { isLiveTestEnabled } from "../agents/live-test-helpers.js";
|
||||
export {
|
||||
createSingleUserPromptMessage,
|
||||
extractNonEmptyAssistantText,
|
||||
isLiveProfileKeyModeEnabled,
|
||||
isLiveTestEnabled,
|
||||
} from "../agents/live-test-helpers.js";
|
||||
export { createSandboxTestContext } from "../agents/sandbox/test-fixtures.js";
|
||||
export { writeSkill } from "../agents/skills.e2e-test-helpers.js";
|
||||
export {
|
||||
castAgentMessage,
|
||||
makeAgentAssistantMessage,
|
||||
makeAgentUserMessage,
|
||||
} from "../agents/test-helpers/agent-message-fixtures.js";
|
||||
export { collectProviderApiKeys } from "../agents/live-auth-keys.js";
|
||||
export { isModelNotFoundErrorMessage } from "../agents/live-model-errors.js";
|
||||
export {
|
||||
isAuthErrorMessage,
|
||||
isBillingErrorMessage,
|
||||
isOverloadedErrorMessage,
|
||||
isServerErrorMessage,
|
||||
isTimeoutErrorMessage,
|
||||
} from "../agents/pi-embedded-helpers/failover-matches.js";
|
||||
export { maybeLoadShellEnvForGenerationProviders } from "../test-utils/generation-live-test-helpers.js";
|
||||
export { __testing } from "../acp/control-plane/manager.js";
|
||||
export { __testing as acpManagerTesting } from "../acp/control-plane/manager.js";
|
||||
@@ -50,6 +73,36 @@ export { runAcpRuntimeAdapterContract } from "../acp/runtime/adapter-contract.te
|
||||
export { handleAcpCommand } from "../auto-reply/reply/commands-acp.js";
|
||||
export { buildCommandTestParams } from "../auto-reply/reply/commands-spawn.test-harness.js";
|
||||
export { peekSystemEvents, resetSystemEventsForTest } from "../infra/system-events.js";
|
||||
export { isTruthyEnvValue } from "../infra/env.js";
|
||||
export { getShellEnvAppliedKeys } from "../infra/shell-env.js";
|
||||
export { encodePngRgba, fillPixel } from "../media/png-encode.js";
|
||||
export {
|
||||
parseLiveCsvFilter as parseCsvFilter,
|
||||
parseProviderModelMap,
|
||||
redactLiveApiKey,
|
||||
} from "../media-generation/live-test-helpers.js";
|
||||
export {
|
||||
DEFAULT_LIVE_MUSIC_MODELS,
|
||||
resolveConfiguredLiveMusicModels,
|
||||
resolveLiveMusicAuthStore,
|
||||
} from "../music-generation/live-test-helpers.js";
|
||||
export {
|
||||
canRunBufferBackedImageToVideoLiveLane,
|
||||
canRunBufferBackedVideoToVideoLiveLane,
|
||||
DEFAULT_LIVE_VIDEO_MODELS,
|
||||
resolveConfiguredLiveVideoModels,
|
||||
resolveLiveVideoAuthStore,
|
||||
resolveLiveVideoResolution,
|
||||
} from "../video-generation/live-test-helpers.js";
|
||||
export { normalizeVideoGenerationDuration } from "../video-generation/duration-support.js";
|
||||
export { parseVideoGenerationModelRef } from "../video-generation/model-ref.js";
|
||||
export type {
|
||||
GeneratedVideoAsset,
|
||||
VideoGenerationMode,
|
||||
VideoGenerationModeCapabilities,
|
||||
VideoGenerationProvider,
|
||||
VideoGenerationRequest,
|
||||
} from "../video-generation/types.js";
|
||||
export { jsonResponse, requestBodyText, requestUrl } from "../test-helpers/http.js";
|
||||
export { mockPinnedHostnameResolution } from "../test-helpers/ssrf.js";
|
||||
export { createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||
@@ -62,3 +115,9 @@ export { expectGeneratedTokenPersistedToGatewayAuth } from "../test-utils/auth-t
|
||||
export { captureEnv, withEnv, withEnvAsync } from "../test-utils/env.js";
|
||||
export { withFetchPreconnect, type FetchMock } from "../test-utils/fetch-mock.js";
|
||||
export { createTempHomeEnv, type TempHomeEnv } from "../test-utils/temp-home.js";
|
||||
export { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
|
||||
export { buildPluginApi } from "../plugins/api-builder.js";
|
||||
export {
|
||||
createCapturedPluginRegistration,
|
||||
type CapturedPluginRegistration,
|
||||
} from "../plugins/captured-registration.js";
|
||||
|
||||
Reference in New Issue
Block a user