refactor(plugins): decouple bundled plugin runtime loading

This commit is contained in:
Peter Steinberger
2026-03-29 09:08:06 +01:00
parent 1738d540f4
commit 8e0ab35b0e
582 changed files with 8057 additions and 22869 deletions

View File

@@ -5,15 +5,16 @@
#
# Multi-stage build produces a minimal runtime image without build tools,
# source code, or Bun. Works with Docker, Buildx, and Podman.
# The ext-deps stage extracts only the package.json files we need from
# extensions/, so the main build layer is not invalidated by unrelated
# extension source changes.
# The ext-deps stage extracts only the package.json files we need from the
# bundled plugin workspace tree, so the main build layer is not invalidated by
# unrelated plugin source changes.
#
# Two runtime variants:
# Default (bookworm): docker build .
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
ARG OPENCLAW_EXTENSIONS=""
ARG OPENCLAW_VARIANT=default
ARG OPENCLAW_BUNDLED_PLUGIN_DIR=extensions
ARG OPENCLAW_DOCKER_APT_UPGRADE=1
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_DIGEST="sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
@@ -27,18 +28,20 @@ ARG OPENCLAW_NODE_BOOKWORM_SLIM_DIGEST="sha256:e8e2e91b1378f83c5b2dd15f0247f3411
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS ext-deps
ARG OPENCLAW_EXTENSIONS
COPY extensions /tmp/extensions
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
COPY ${OPENCLAW_BUNDLED_PLUGIN_DIR} /tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR}
# Copy package.json for opted-in extensions so pnpm resolves their deps.
RUN mkdir -p /out && \
for ext in $OPENCLAW_EXTENSIONS; do \
if [ -f "/tmp/extensions/$ext/package.json" ]; then \
if [ -f "/tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR}/$ext/package.json" ]; then \
mkdir -p "/out/$ext" && \
cp "/tmp/extensions/$ext/package.json" "/out/$ext/package.json"; \
cp "/tmp/${OPENCLAW_BUNDLED_PLUGIN_DIR}/$ext/package.json" "/out/$ext/package.json"; \
fi; \
done
# ── Stage 2: Build ──────────────────────────────────────────────
FROM ${OPENCLAW_NODE_BOOKWORM_IMAGE} AS build
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
# Install Bun (required for build scripts). Retry the whole bootstrap flow to
# tolerate transient 5xx failures from bun.sh/GitHub during CI image builds.
@@ -62,7 +65,7 @@ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
COPY ui/package.json ./ui/package.json
COPY patches ./patches
COPY --from=ext-deps /out/ ./extensions/
COPY --from=ext-deps /out/ ./${OPENCLAW_BUNDLED_PLUGIN_DIR}/
# Reduce OOM risk on low-memory hosts during dependency installation.
# Docker builds on small VMs may otherwise fail with "Killed" (exit 137).
@@ -73,7 +76,7 @@ COPY . .
# Normalize extension paths now so runtime COPY preserves safe modes
# without adding a second full extensions layer.
RUN for dir in /app/extensions /app/.agent /app/.agents; do \
RUN for dir in /app/${OPENCLAW_BUNDLED_PLUGIN_DIR} /app/.agent /app/.agents; do \
if [ -d "$dir" ]; then \
find "$dir" -type d -exec chmod 755 {} +; \
find "$dir" -type f -exec chmod 644 {} +; \
@@ -114,6 +117,7 @@ LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-sli
# ── Stage 3: Runtime ────────────────────────────────────────────
FROM base-${OPENCLAW_VARIANT}
ARG OPENCLAW_VARIANT
ARG OPENCLAW_BUNDLED_PLUGIN_DIR
ARG OPENCLAW_DOCKER_APT_UPGRADE
# OCI base-image metadata for downstream image consumers.
@@ -148,13 +152,13 @@ COPY --from=runtime-assets --chown=node:node /app/dist ./dist
COPY --from=runtime-assets --chown=node:node /app/node_modules ./node_modules
COPY --from=runtime-assets --chown=node:node /app/package.json .
COPY --from=runtime-assets --chown=node:node /app/openclaw.mjs .
COPY --from=runtime-assets --chown=node:node /app/extensions ./extensions
COPY --from=runtime-assets --chown=node:node /app/${OPENCLAW_BUNDLED_PLUGIN_DIR} ./${OPENCLAW_BUNDLED_PLUGIN_DIR}
COPY --from=runtime-assets --chown=node:node /app/skills ./skills
COPY --from=runtime-assets --chown=node:node /app/docs ./docs
# In npm-installed Docker images, prefer the copied source extension tree for
# bundled discovery so package metadata that points at source entries stays valid.
ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/extensions
ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/${OPENCLAW_BUNDLED_PLUGIN_DIR}
# Keep pnpm available in the runtime image for container-local workflows.
# Use a shared Corepack home so the non-root `node` user does not need a

View File

@@ -102,7 +102,7 @@ Required behavior when ACP backend is unavailable:
1. Do not immediately ask the user to pick an alternate path.
2. First attempt automatic local repair:
- ensure plugin-local pinned acpx is installed in `extensions/acpx`
- ensure plugin-local pinned acpx is installed in the bundled ACPX plugin package
- verify `${ACPX_CMD} --version`
3. After reinstall/repair, restart the gateway and explicitly offer to run that restart for the user.
4. Retry ACP thread spawn once after repair.
@@ -120,20 +120,21 @@ Do not default to subagent runtime for these requests.
For this repo, direct `acpx` calls must follow the same pinned policy as the `@openclaw/acpx` extension package.
1. Prefer plugin-local binary, not global PATH:
- `./extensions/acpx/node_modules/.bin/acpx`
- `${ACPX_PLUGIN_ROOT}/node_modules/.bin/acpx`
2. Resolve pinned version from extension dependency:
- `node -e "console.log(require('./extensions/acpx/package.json').dependencies.acpx)"`
- `node -e "console.log(require(process.env.ACPX_PLUGIN_ROOT + '/package.json').dependencies.acpx)"`
3. If binary is missing or version mismatched, install plugin-local pinned version:
- `cd extensions/acpx && npm install --omit=dev --no-save acpx@<pinnedVersion>`
- `cd "$ACPX_PLUGIN_ROOT" && npm install --omit=dev --no-save acpx@<pinnedVersion>`
4. Verify before use:
- `./extensions/acpx/node_modules/.bin/acpx --version`
- `${ACPX_PLUGIN_ROOT}/node_modules/.bin/acpx --version`
5. If install/repair changed ACPX artifacts, restart the gateway and offer to run the restart.
6. Do not run `npm install -g acpx` unless the user explicitly asks for global install.
Set and reuse:
```bash
ACPX_CMD="./extensions/acpx/node_modules/.bin/acpx"
ACPX_PLUGIN_ROOT="<bundled-acpx-plugin-root>"
ACPX_CMD="$ACPX_PLUGIN_ROOT/node_modules/.bin/acpx"
```
## Direct acpx path ("telephone game")
@@ -227,7 +228,7 @@ If your local Cursor install still exposes ACP as `agent acp`, set that as the `
### Failure handling
- `acpx: command not found`:
- for thread-spawn ACP requests, install plugin-local pinned acpx in `extensions/acpx` immediately
- for thread-spawn ACP requests, install plugin-local pinned acpx in the bundled ACPX plugin package immediately
- restart gateway after install and offer to run the restart automatically
- then retry once
- do not ask for install permission first unless policy explicitly requires it

View File

@@ -3,6 +3,10 @@ import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import {
bundledDistPluginRootAt,
bundledPluginRootAt,
} from "../../../test/helpers/bundled-plugin-paths.js";
import {
ACPX_BUNDLED_BIN,
ACPX_PINNED_VERSION,
@@ -39,10 +43,10 @@ describe("acpx plugin config parsing", () => {
}
});
it("prefers the workspace plugin root for dist/extensions/acpx bundles", () => {
it("prefers the workspace plugin root for dist plugin bundles", () => {
const repoRoot = fs.mkdtempSync(path.join(os.tmpdir(), "acpx-root-workspace-"));
const workspacePluginRoot = path.join(repoRoot, "extensions", "acpx");
const bundledPluginRoot = path.join(repoRoot, "dist", "extensions", "acpx");
const workspacePluginRoot = bundledPluginRootAt(repoRoot, "acpx");
const bundledPluginRoot = bundledDistPluginRootAt(repoRoot, "acpx");
try {
fs.mkdirSync(workspacePluginRoot, { recursive: true });
fs.mkdirSync(bundledPluginRoot, { recursive: true });

View File

@@ -3,9 +3,10 @@ import { chmod, mkdtemp, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { bundledPluginFile } from "../../../../test/helpers/bundled-plugin-paths.js";
const tempDirs: string[] = [];
const proxyPath = path.resolve("extensions/acpx/src/runtime-internals/mcp-proxy.mjs");
const proxyPath = path.resolve(bundledPluginFile("acpx", "src/runtime-internals/mcp-proxy.mjs"));
async function makeTempScript(name: string, content: string): Promise<string> {
const dir = await mkdtemp(path.join(os.tmpdir(), "openclaw-acpx-mcp-proxy-"));

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { registerSingleProviderPlugin } from "../../test/helpers/extensions/plugin-registration.js";
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
import amazonBedrockPlugin from "./index.js";
describe("amazon-bedrock provider plugin", () => {

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("amazon-bedrock");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "anthropic",

View File

@@ -1,3 +1,3 @@
import { describeAnthropicProviderRuntimeContract } from "../../test/helpers/extensions/provider-runtime-contract.js";
import { describeAnthropicProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
describeAnthropicProviderRuntimeContract();

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("anthropic");

View File

@@ -1,6 +1,6 @@
# BlueBubbles extension (developer reference)
This directory contains the **BlueBubbles external channel plugin** for OpenClaw.
This package contains the **BlueBubbles external channel plugin** for OpenClaw.
If youre looking for **how to use BlueBubbles as an agent/tool user**, see:
@@ -8,22 +8,22 @@ If youre looking for **how to use BlueBubbles as an agent/tool user**, see:
## Layout
- Extension package: `extensions/bluebubbles/` (entry: `index.ts`).
- Channel implementation: `extensions/bluebubbles/src/channel.ts`.
- Webhook handling: `extensions/bluebubbles/src/monitor.ts` (register per-account route via `registerPluginHttpRoute`).
- REST helpers: `extensions/bluebubbles/src/send.ts` + `extensions/bluebubbles/src/probe.ts`.
- Runtime bridge: `extensions/bluebubbles/src/runtime.ts` (set via `api.runtime`).
- Package entry: `index.ts`.
- Channel implementation: `src/channel.ts`.
- Webhook handling: `src/monitor.ts` (register per-account route via `registerPluginHttpRoute`).
- REST helpers: `src/send.ts` + `src/probe.ts`.
- Runtime bridge: `src/runtime.ts` (set via `api.runtime`).
- Catalog entry for setup selection: `src/channels/plugins/catalog.ts`.
## Internal helpers (use these, not raw API calls)
- `probeBlueBubbles` in `extensions/bluebubbles/src/probe.ts` for health checks.
- `sendMessageBlueBubbles` in `extensions/bluebubbles/src/send.ts` for text delivery.
- `resolveChatGuidForTarget` in `extensions/bluebubbles/src/send.ts` for chat lookup.
- `sendBlueBubblesReaction` in `extensions/bluebubbles/src/reactions.ts` for tapbacks.
- `sendBlueBubblesTyping` + `markBlueBubblesChatRead` in `extensions/bluebubbles/src/chat.ts`.
- `downloadBlueBubblesAttachment` in `extensions/bluebubbles/src/attachments.ts` for inbound media.
- `buildBlueBubblesApiUrl` + `blueBubblesFetchWithTimeout` in `extensions/bluebubbles/src/types.ts` for shared REST plumbing.
- `probeBlueBubbles` in `src/probe.ts` for health checks.
- `sendMessageBlueBubbles` in `src/send.ts` for text delivery.
- `resolveChatGuidForTarget` in `src/send.ts` for chat lookup.
- `sendBlueBubblesReaction` in `src/reactions.ts` for tapbacks.
- `sendBlueBubblesTyping` + `markBlueBubblesChatRead` in `src/chat.ts`.
- `downloadBlueBubblesAttachment` in `src/attachments.ts` for inbound media.
- `buildBlueBubblesApiUrl` + `blueBubblesFetchWithTimeout` in `src/types.ts` for shared REST plumbing.
## Webhooks

View File

@@ -1,4 +1,4 @@
import { describePackageManifestContract } from "../../test/helpers/extensions/package-manifest-contract.js";
import { describePackageManifestContract } from "../../test/helpers/plugins/package-manifest-contract.js";
describePackageManifestContract({
pluginId: "bluebubbles",

View File

@@ -38,7 +38,6 @@
},
"install": {
"npmSpec": "@openclaw/bluebubbles",
"localPath": "extensions/bluebubbles",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.28"
},

View File

@@ -5,7 +5,7 @@ import {
EMPTY_DISPATCH_RESULT,
resetBlueBubblesMonitorTestState,
type DispatchReplyParams,
} from "../../../test/helpers/extensions/bluebubbles-monitor.js";
} from "../../../test/helpers/plugins/bluebubbles-monitor.js";
import type { ResolvedBlueBubblesAccount } from "./accounts.js";
import { fetchBlueBubblesHistory } from "./history.js";
import { createBlueBubblesDebounceRegistry } from "./monitor-debounce.js";

View File

@@ -4,7 +4,7 @@ import {
EMPTY_DISPATCH_RESULT,
resetBlueBubblesMonitorTestState,
type DispatchReplyParams,
} from "../../../test/helpers/extensions/bluebubbles-monitor.js";
} from "../../../test/helpers/plugins/bluebubbles-monitor.js";
import type { ResolvedBlueBubblesAccount } from "./accounts.js";
import { fetchBlueBubblesHistory } from "./history.js";
import { handleBlueBubblesWebhookRequest, resolveBlueBubblesMessageId } from "./monitor.js";

View File

@@ -6,7 +6,7 @@ import {
createTestWizardPrompter,
runSetupWizardConfigure,
type WizardPrompter,
} from "../../../test/helpers/extensions/setup-wizard.js";
} from "../../../test/helpers/plugins/setup-wizard.js";
import { resolveBlueBubblesAccount } from "./accounts.js";
import { BlueBubblesConfigSchema } from "./config-schema.js";
import {

View File

@@ -1,3 +1,3 @@
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/extensions/bundled-web-search-fast-path-contract.js";
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/plugins/bundled-web-search-fast-path-contract.js";
describeBundledWebSearchFastPathContract("brave");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "brave",

View File

@@ -1,3 +1,3 @@
import { describeWebSearchProviderContracts } from "../../test/helpers/extensions/web-search-provider-contract.js";
import { describeWebSearchProviderContracts } from "../../test/helpers/plugins/web-search-provider-contract.js";
describeWebSearchProviderContracts("brave");

View File

@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from "vitest";
import { createTestPluginApi } from "../../test/helpers/extensions/plugin-api.js";
import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js";
import type { OpenClawPluginApi } from "./runtime-api.js";
const runtimeApiMocks = vi.hoisted(() => ({

View File

@@ -5,7 +5,7 @@ export {
type CliRuntimeCapture,
} from "../../src/cli/test-runtime-capture.js";
export type { OpenClawConfig } from "openclaw/plugin-sdk/browser-support";
export { expectGeneratedTokenPersistedToGatewayAuth } from "../../test/helpers/extensions/auth-token-assertions.ts";
export { withEnv, withEnvAsync } from "../../test/helpers/extensions/env.ts";
export { withFetchPreconnect, type FetchMock } from "../../test/helpers/extensions/fetch-mock.ts";
export { createTempHomeEnv, type TempHomeEnv } from "../../test/helpers/extensions/temp-home.ts";
export { expectGeneratedTokenPersistedToGatewayAuth } from "../../test/helpers/plugins/auth-token-assertions.ts";
export { withEnv, withEnvAsync } from "../../test/helpers/plugins/env.ts";
export { withFetchPreconnect, type FetchMock } from "../../test/helpers/plugins/fetch-mock.ts";
export { createTempHomeEnv, type TempHomeEnv } from "../../test/helpers/plugins/temp-home.ts";

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("byteplus");

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("chutes");

View File

@@ -1,3 +1,3 @@
import { describeCloudflareAiGatewayProviderDiscoveryContract } from "../../test/helpers/extensions/provider-discovery-contract.js";
import { describeCloudflareAiGatewayProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
describeCloudflareAiGatewayProviderDiscoveryContract();

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("cloudflare-ai-gateway");

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("copilot-proxy");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "deepgram",

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { resolveProviderPluginChoice } from "../../src/plugins/provider-wizard.js";
import { registerSingleProviderPlugin } from "../../test/helpers/extensions/plugin-registration.js";
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
import deepseekPlugin from "./index.js";
describe("deepseek provider plugin", () => {

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("deepseek");

View File

@@ -6,7 +6,7 @@ import type {
PluginCommandContext,
} from "openclaw/plugin-sdk/core";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createTestPluginApi } from "../../test/helpers/extensions/plugin-api.js";
import { createTestPluginApi } from "../../test/helpers/plugins/plugin-api.js";
import type { OpenClawPluginApi } from "./api.js";
import type { PendingPairingRequest } from "./notify.ts";

View File

@@ -2,8 +2,8 @@ import fs from "node:fs/promises";
import type { IncomingMessage } from "node:http";
import path from "node:path";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { createMockServerResponse } from "../../../test/helpers/extensions/mock-http-response.js";
import { createTestPluginApi } from "../../../test/helpers/extensions/plugin-api.js";
import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js";
import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js";
import type { OpenClawConfig } from "../api.js";
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "../api.js";
import plugin from "../index.js";

View File

@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
import type { IncomingMessage } from "node:http";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createMockServerResponse } from "../../../test/helpers/extensions/mock-http-response.js";
import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js";
import { createDiffsHttpHandler } from "./http.js";
import { DiffArtifactStore } from "./store.js";
import { createDiffStoreHarness } from "./test-helpers.js";

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createTestPluginApi } from "../../../test/helpers/extensions/plugin-api.js";
import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js";
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "../api.js";
import type { DiffScreenshotter } from "./browser.js";
import { DEFAULT_DIFFS_TOOL_DEFAULTS } from "./config.js";

View File

@@ -1,4 +1,4 @@
import { describePackageManifestContract } from "../../test/helpers/extensions/package-manifest-contract.js";
import { describePackageManifestContract } from "../../test/helpers/plugins/package-manifest-contract.js";
describePackageManifestContract({
pluginId: "discord",

View File

@@ -39,7 +39,6 @@
},
"install": {
"npmSpec": "@openclaw/discord",
"localPath": "extensions/discord",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.28"
},

View File

@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
import { withFetchPreconnect } from "../../../test/helpers/plugins/fetch-mock.js";
import { fetchDiscord } from "./api.js";
import { jsonResponse } from "./test-http-helpers.js";

View File

@@ -4,7 +4,7 @@ import type {
PluginApprovalResolved,
} from "../../../src/infra/plugin-approvals.js";
import type { PluginRuntime } from "../../../src/plugins/runtime/types.js";
import { createStartAccountContext } from "../../../test/helpers/extensions/start-account-context.js";
import { createStartAccountContext } from "../../../test/helpers/plugins/start-account-context.js";
import type { ResolvedDiscordAccount } from "./accounts.js";
import type { OpenClawConfig } from "./runtime-api.js";
let discordPlugin: typeof import("./channel.js").discordPlugin;

View File

@@ -1,8 +1,5 @@
import { describe, expect, it } from "vitest";
import {
countLines,
hasBalancedFences,
} from "../../../test/helpers/extensions/chunk-test-helpers.js";
import { countLines, hasBalancedFences } from "../../../test/helpers/plugins/chunk-test-helpers.js";
import { chunkDiscordText, chunkDiscordTextWithMode } from "./chunk.js";
describe("chunkDiscordText", () => {

View File

@@ -1,6 +1,6 @@
import { ChannelType, type Guild } from "@buape/carbon";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { typedCases } from "../../../test/helpers/extensions/typed-cases.js";
import { typedCases } from "../../../test/helpers/plugins/typed-cases.js";
import {
allowListMatches,
buildDiscordMediaPayload,

View File

@@ -1,6 +1,6 @@
import * as conversationRuntime from "openclaw/plugin-sdk/conversation-runtime";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createConfiguredBindingConversationRuntimeModuleMock } from "../../../../test/helpers/extensions/configured-binding-runtime.js";
import { createConfiguredBindingConversationRuntimeModuleMock } from "../../../../test/helpers/plugins/configured-binding-runtime.js";
const ensureConfiguredBindingRouteReadyMock = vi.hoisted(() => vi.fn());
const resolveConfiguredBindingRouteMock = vi.hoisted(() => vi.fn());

View File

@@ -6,12 +6,12 @@ import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
import * as securityRuntime from "openclaw/plugin-sdk/security-runtime";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { peekSystemEvents, resetSystemEventsForTest } from "../../../../src/infra/system-events.ts";
import { expectPairingReplyText } from "../../../../test/helpers/pairing-reply.js";
import {
readAllowFromStoreMock,
resetDiscordComponentRuntimeMocks,
upsertPairingRequestMock,
} from "../../../../test/helpers/extensions/discord-component-runtime.js";
import { expectPairingReplyText } from "../../../../test/helpers/pairing-reply.js";
} from "../../../../test/helpers/plugins/discord-component-runtime.js";
import { createAgentComponentButton, createAgentSelectMenu } from "./agent-components.js";
describe("agent components", () => {

View File

@@ -18,7 +18,7 @@ import {
resetDiscordComponentRuntimeMocks,
resolvePluginConversationBindingApprovalMock,
upsertPairingRequestMock,
} from "../../../../test/helpers/extensions/discord-component-runtime.js";
} from "../../../../test/helpers/plugins/discord-component-runtime.js";
import { type DiscordComponentEntry, type DiscordModalEntry } from "../components.js";
import type { DiscordChannelConfigResolved } from "./allow-list.js";
import {

View File

@@ -9,7 +9,7 @@ import {
} from "../../../../src/auto-reply/commands-registry.js";
import type { OpenClawConfig, loadConfig } from "../../../../src/config/config.js";
import { clearSessionStoreCacheForTest } from "../../../../src/config/sessions/store.js";
import { createConfiguredBindingConversationRuntimeModuleMock } from "../../../../test/helpers/extensions/configured-binding-runtime.js";
import { createConfiguredBindingConversationRuntimeModuleMock } from "../../../../test/helpers/plugins/configured-binding-runtime.js";
import { createNoopThreadBindingManager } from "./thread-bindings.js";
const ensureConfiguredBindingRouteReadyMock = vi.hoisted(() =>

View File

@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { RuntimeEnv } from "../../../../src/runtime.js";
import { createNonExitingTypedRuntimeEnv } from "../../../../test/helpers/extensions/runtime-env.js";
import { createNonExitingTypedRuntimeEnv } from "../../../../test/helpers/plugins/runtime-env.js";
import * as resolveChannelsModule from "../resolve-channels.js";
import * as resolveUsersModule from "../resolve-users.js";
import { resolveDiscordAllowlistConfig } from "./provider.allowlist.js";

View File

@@ -9,7 +9,7 @@ import {
getFirstDiscordMessageHandlerParams,
getProviderMonitorTestMocks,
resetDiscordProviderMonitorMocks,
} from "../../../../test/helpers/extensions/discord-provider.test-support.js";
} from "../../../../test/helpers/plugins/discord-provider.test-support.js";
const {
clientConstructorOptionsMock,

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
import { withFetchPreconnect } from "../../../test/helpers/plugins/fetch-mock.js";
import { resolveDiscordChannelAllowlist } from "./resolve-channels.js";
import { jsonResponse, urlToString } from "./test-http-helpers.js";

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
import { withFetchPreconnect } from "../../../test/helpers/plugins/fetch-mock.js";
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
import { jsonResponse, urlToString } from "./test-http-helpers.js";

View File

@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import {
getRequiredHookHandler,
registerHookHandlersForTest,
} from "../../../test/helpers/extensions/subagent-hooks.js";
} from "../../../test/helpers/plugins/subagent-hooks.js";
type ThreadBindingRecord = {
accountId: string;

View File

@@ -1,2 +1,3 @@
export { buildFinalizedDiscordDirectInboundContext } from "./src/monitor/inbound-context.test-helpers.js";
export { __testing as discordThreadBindingTesting } from "./src/monitor/thread-bindings.manager.js";
export { discordOutbound } from "./src/outbound-adapter.js";

View File

@@ -1,3 +1,3 @@
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/extensions/bundled-web-search-fast-path-contract.js";
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/plugins/bundled-web-search-fast-path-contract.js";
describeBundledWebSearchFastPathContract("duckduckgo");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "duckduckgo",

View File

@@ -1,3 +1,3 @@
import { describeWebSearchProviderContracts } from "../../test/helpers/extensions/web-search-provider-contract.js";
import { describeWebSearchProviderContracts } from "../../test/helpers/plugins/web-search-provider-contract.js";
describeWebSearchProviderContracts("duckduckgo");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "elevenlabs",

View File

@@ -1,3 +1,3 @@
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/extensions/bundled-web-search-fast-path-contract.js";
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/plugins/bundled-web-search-fast-path-contract.js";
describeBundledWebSearchFastPathContract("exa");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "exa",

View File

@@ -1,3 +1,3 @@
import { describeWebSearchProviderContracts } from "../../test/helpers/extensions/web-search-provider-contract.js";
import { describeWebSearchProviderContracts } from "../../test/helpers/plugins/web-search-provider-contract.js";
describeWebSearchProviderContracts("exa");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "fal",

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("fal");

View File

@@ -1,4 +1,4 @@
import { describePackageManifestContract } from "../../test/helpers/extensions/package-manifest-contract.js";
import { describePackageManifestContract } from "../../test/helpers/plugins/package-manifest-contract.js";
describePackageManifestContract({
pluginId: "feishu",

View File

@@ -39,7 +39,6 @@
},
"install": {
"npmSpec": "@openclaw/feishu",
"localPath": "extensions/feishu",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.28"
},

View File

@@ -1,7 +1,7 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { EnvelopeFormatOptions } from "../../../src/auto-reply/envelope.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, PluginRuntime } from "../runtime-api.js";
import type { FeishuMessageEvent } from "./bot.js";
import { handleFeishuMessage } from "./bot.js";

View File

@@ -1,5 +1,5 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import {
handleFeishuCardAction,

View File

@@ -1,8 +1,8 @@
import type * as ConversationRuntime from "openclaw/plugin-sdk/conversation-runtime";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { ResolvedAgentRoute } from "../../../src/routing/resolve-route.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, PluginRuntime, RuntimeEnv } from "../runtime-api.js";
import type { FeishuMessageEvent } from "./bot.js";
import {

View File

@@ -1,5 +1,5 @@
import { describe, expect, it, vi, beforeEach } from "vitest";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import {
createQuickActionLauncherCard,

View File

@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createTestPluginApi } from "../../../test/helpers/extensions/plugin-api.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import type { OpenClawPluginApi } from "../runtime-api.js";
const createFeishuClientMock = vi.hoisted(() => vi.fn());

View File

@@ -1,6 +1,6 @@
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { createTestPluginApi } from "../../../test/helpers/extensions/plugin-api.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import type { OpenClawPluginApi } from "../runtime-api.js";
import { FeishuConfigSchema } from "./config-schema.js";
import type { FeishuConfig, ResolvedFeishuAccount } from "./types.js";

View File

@@ -8,8 +8,8 @@ import {
restoreFeishuLifecycleStateDir,
setFeishuLifecycleStateDir,
setupFeishuLifecycleHandler,
} from "../../../test/helpers/extensions/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { getFeishuLifecycleTestMocks } from "./lifecycle.test-support.js";
import type { ResolvedFeishuAccount } from "./types.js";

View File

@@ -12,8 +12,8 @@ import {
restoreFeishuLifecycleStateDir,
setFeishuLifecycleStateDir,
setupFeishuLifecycleHandler,
} from "../../../test/helpers/extensions/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { getFeishuLifecycleTestMocks } from "./lifecycle.test-support.js";
import type { ResolvedFeishuAccount } from "./types.js";

View File

@@ -4,7 +4,7 @@ import {
createInboundDebouncer,
resolveInboundDebounceMs,
} from "../../../src/auto-reply/inbound-debounce.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { monitorSingleAccount } from "./monitor.account.js";
import { setFeishuRuntime } from "./runtime.js";

View File

@@ -9,8 +9,8 @@ import {
runFeishuLifecycleSequence,
setFeishuLifecycleStateDir,
setupFeishuLifecycleHandler,
} from "../../../test/helpers/extensions/feishu-lifecycle.js";
import { createNonExitingRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/feishu-lifecycle.js";
import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { FeishuConfigSchema } from "./config-schema.js";
import { getFeishuLifecycleTestMocks } from "./lifecycle.test-support.js";

View File

@@ -12,8 +12,8 @@ import {
restoreFeishuLifecycleStateDir,
setFeishuLifecycleStateDir,
setupFeishuLifecycleHandler,
} from "../../../test/helpers/extensions/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { resetProcessedFeishuCardActionTokensForTests } from "./card-action.js";
import { createFeishuCardInteractionEnvelope } from "./card-interaction.js";

View File

@@ -4,11 +4,11 @@ import {
createInboundDebouncer,
resolveInboundDebounceMs,
} from "../../../src/auto-reply/inbound-debounce.js";
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
import { createPluginRuntimeMock } from "../../../test/helpers/plugins/plugin-runtime-mock.js";
import {
createNonExitingTypedRuntimeEnv,
createRuntimeEnv,
} from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { parseFeishuMessageEvent, type FeishuMessageEvent } from "./bot.js";
import * as dedup from "./dedup.js";

View File

@@ -13,8 +13,8 @@ import {
restoreFeishuLifecycleStateDir,
setFeishuLifecycleStateDir,
setupFeishuLifecycleHandler,
} from "../../../test/helpers/extensions/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
} from "../../../test/helpers/plugins/feishu-lifecycle.js";
import { createRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
import { getFeishuLifecycleTestMocks } from "./lifecycle.test-support.js";
import type { ResolvedFeishuAccount } from "./types.js";

View File

@@ -1,5 +1,5 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { createNonExitingRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createNonExitingRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import type { ClawdbotConfig } from "../runtime-api.js";
import { monitorFeishuProvider, stopFeishuMonitor } from "./monitor.js";

View File

@@ -1,11 +1,11 @@
import { describe, expect, it, vi } from "vitest";
import { createNonExitingTypedRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
import { createNonExitingTypedRuntimeEnv } from "../../../test/helpers/plugins/runtime-env.js";
import {
createPluginSetupWizardConfigure,
createPluginSetupWizardStatus,
createTestWizardPrompter,
runSetupWizardConfigure,
} from "../../../test/helpers/extensions/setup-wizard.js";
} from "../../../test/helpers/plugins/setup-wizard.js";
vi.mock("./probe.js", () => ({
probeFeishu: vi.fn(async () => ({ ok: false, error: "mocked" })),

View File

@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import {
getRequiredHookHandler,
registerHookHandlersForTest,
} from "../../../test/helpers/extensions/subagent-hooks.js";
} from "../../../test/helpers/plugins/subagent-hooks.js";
import type { ClawdbotConfig, OpenClawPluginApi } from "../runtime-api.js";
import { registerFeishuSubagentHooks } from "./subagent-hooks.js";
import {

View File

@@ -1,3 +1,3 @@
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/extensions/bundled-web-search-fast-path-contract.js";
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/plugins/bundled-web-search-fast-path-contract.js";
describeBundledWebSearchFastPathContract("firecrawl");

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "firecrawl",

View File

@@ -1,3 +1,3 @@
import { describeWebSearchProviderContracts } from "../../test/helpers/extensions/web-search-provider-contract.js";
import { describeWebSearchProviderContracts } from "../../test/helpers/plugins/web-search-provider-contract.js";
describeWebSearchProviderContracts("firecrawl");

View File

@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import {
createProviderUsageFetch,
makeResponse,
} from "../../test/helpers/extensions/provider-usage-fetch.js";
} from "../../test/helpers/plugins/provider-usage-fetch.js";
import { buildCopilotModelDefinition, getDefaultCopilotModelIds } from "./models-defaults.js";
import { fetchCopilotUsage } from "./usage.js";

View File

@@ -1,3 +1,3 @@
import { describeGithubCopilotProviderAuthContract } from "../../test/helpers/extensions/provider-auth-contract.js";
import { describeGithubCopilotProviderAuthContract } from "../../test/helpers/plugins/provider-auth-contract.js";
describeGithubCopilotProviderAuthContract();

View File

@@ -1,3 +1,3 @@
import { describeGithubCopilotProviderDiscoveryContract } from "../../test/helpers/extensions/provider-discovery-contract.js";
import { describeGithubCopilotProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
describeGithubCopilotProviderDiscoveryContract();

View File

@@ -1,3 +1,3 @@
import { describeGithubCopilotProviderRuntimeContract } from "../../test/helpers/extensions/provider-runtime-contract.js";
import { describeGithubCopilotProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
describeGithubCopilotProviderRuntimeContract();

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("github-copilot");

View File

@@ -1,3 +1,3 @@
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/extensions/bundled-web-search-fast-path-contract.js";
import { describeBundledWebSearchFastPathContract } from "../../test/helpers/plugins/bundled-web-search-fast-path-contract.js";
describeBundledWebSearchFastPathContract("google");

View File

@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import * as ssrf from "../../src/infra/net/ssrf.js";
import { withFetchPreconnect } from "../../test/helpers/extensions/fetch-mock.js";
import { createRequestCaptureJsonFetch } from "../../test/helpers/extensions/media-understanding.js";
import { withFetchPreconnect } from "../../test/helpers/plugins/fetch-mock.js";
import { createRequestCaptureJsonFetch } from "../../test/helpers/plugins/media-understanding.js";
import { describeGeminiVideo } from "./media-understanding-provider.js";
const TEST_NET_IP = "203.0.113.10";

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "google",

View File

@@ -1,3 +1,3 @@
import { describeGoogleProviderRuntimeContract } from "../../test/helpers/extensions/provider-runtime-contract.js";
import { describeGoogleProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
describeGoogleProviderRuntimeContract();

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("google");

View File

@@ -1,3 +1,3 @@
import { describeWebSearchProviderContracts } from "../../test/helpers/extensions/web-search-provider-contract.js";
import { describeWebSearchProviderContracts } from "../../test/helpers/plugins/web-search-provider-contract.js";
describeWebSearchProviderContracts("google");

View File

@@ -1,4 +1,4 @@
import { describePackageManifestContract } from "../../test/helpers/extensions/package-manifest-contract.js";
import { describePackageManifestContract } from "../../test/helpers/plugins/package-manifest-contract.js";
describePackageManifestContract({
pluginId: "googlechat",

View File

@@ -41,7 +41,6 @@
},
"install": {
"npmSpec": "@openclaw/googlechat",
"localPath": "extensions/googlechat",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.28"
}

View File

@@ -2,7 +2,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import {
createDirectoryTestRuntime,
expectDirectorySurface,
} from "../../../test/helpers/extensions/directory.ts";
} from "../../../test/helpers/plugins/directory.ts";
import type { OpenClawConfig, PluginRuntime } from "../runtime-api.js";
const uploadGoogleChatAttachmentMock = vi.hoisted(() => vi.fn());

View File

@@ -3,7 +3,7 @@ import type { IncomingMessage } from "node:http";
import { afterEach, describe, expect, it, vi } from "vitest";
import { createEmptyPluginRegistry } from "../../../src/plugins/registry.js";
import { setActivePluginRegistry } from "../../../src/plugins/runtime.js";
import { createMockServerResponse } from "../../../test/helpers/extensions/mock-http-response.js";
import { createMockServerResponse } from "../../../test/helpers/plugins/mock-http-response.js";
import type { OpenClawConfig, PluginRuntime } from "../runtime-api.js";
import type { ResolvedGoogleChatAccount } from "./accounts.js";
import { verifyGoogleChatRequest } from "./auth.js";

View File

@@ -5,13 +5,13 @@ import {
createTestWizardPrompter,
runSetupWizardConfigure,
type WizardPrompter,
} from "../../../test/helpers/extensions/setup-wizard.js";
} from "../../../test/helpers/plugins/setup-wizard.js";
import {
expectLifecyclePatch,
expectPendingUntilAbort,
startAccountAndTrackLifecycle,
waitForStartedMocks,
} from "../../../test/helpers/extensions/start-account-lifecycle.js";
} from "../../../test/helpers/plugins/start-account-lifecycle.js";
import type { OpenClawConfig } from "../runtime-api.js";
import { resolveGoogleChatAccount, type ResolvedGoogleChatAccount } from "./accounts.js";
import { googlechatPlugin } from "./channel.js";

View File

@@ -1,4 +1,4 @@
import { describePluginRegistrationContract } from "../../test/helpers/extensions/plugin-registration-contract.js";
import { describePluginRegistrationContract } from "../../test/helpers/plugins/plugin-registration-contract.js";
describePluginRegistrationContract({
pluginId: "groq",

View File

@@ -1,3 +1,3 @@
import { describeProviderContracts } from "../../test/helpers/extensions/provider-contract.js";
import { describeProviderContracts } from "../../test/helpers/plugins/provider-contract.js";
describeProviderContracts("huggingface");

View File

@@ -1,4 +1,4 @@
import { describePackageManifestContract } from "../../test/helpers/extensions/package-manifest-contract.js";
import { describePackageManifestContract } from "../../test/helpers/plugins/package-manifest-contract.js";
describePackageManifestContract({
pluginId: "irc",

View File

@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { createSendCfgThreadingRuntime } from "../../../test/helpers/extensions/send-config.js";
import { createSendCfgThreadingRuntime } from "../../../test/helpers/plugins/send-config.js";
import type { IrcClient } from "./client.js";
import { setIrcRuntime } from "./runtime.js";
import type { CoreConfig } from "./types.js";

View File

@@ -5,12 +5,12 @@ import {
promptSetupWizardAllowFrom,
runSetupWizardConfigure,
type WizardPrompter,
} from "../../../test/helpers/extensions/setup-wizard.js";
} from "../../../test/helpers/plugins/setup-wizard.js";
import {
expectStopPendingUntilAbort,
startAccountAndTrackLifecycle,
waitForStartedMocks,
} from "../../../test/helpers/extensions/start-account-lifecycle.js";
} from "../../../test/helpers/plugins/start-account-lifecycle.js";
import type { ResolvedIrcAccount } from "./accounts.js";
import { ircPlugin } from "./channel.js";
import { setIrcRuntime } from "./runtime.js";
@@ -351,9 +351,6 @@ describe("irc setup", () => {
it("keeps startAccount pending until abort, then stops the monitor", async () => {
const stop = vi.fn();
vi.resetModules();
vi.doMock("../../../src/generated/bundled-channel-entries.generated.ts", () => ({
GENERATED_BUNDLED_CHANNEL_ENTRIES: [],
}));
hoisted.monitorIrcProvider.mockResolvedValue({ stop });
installIrcRuntime();
const { ircPlugin: runtimeMockedPlugin } = await import("./channel.js");

View File

@@ -12,7 +12,7 @@ import {
KILOCODE_DEFAULT_COST,
KILOCODE_DEFAULT_MODEL_ID,
} from "../../src/plugin-sdk/kilocode.js";
import { captureEnv } from "../../test/helpers/extensions/env.js";
import { captureEnv } from "../../test/helpers/plugins/env.js";
import {
applyKilocodeProviderConfig,
applyKilocodeConfig,

Some files were not shown because too many files have changed in this diff Show More