Merge branch 'main' into memory-chunking-phase1
This commit is contained in:
commit
7068cf5b59
32
.github/workflows/ci.yml
vendored
32
.github/workflows/ci.yml
vendored
@ -273,7 +273,9 @@ jobs:
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Run changed extension tests
|
||||
run: pnpm test:extension ${{ matrix.extension }}
|
||||
env:
|
||||
EXTENSION_ID: ${{ matrix.extension }}
|
||||
run: pnpm test:extension "$EXTENSION_ID"
|
||||
|
||||
# Types, lint, and format check.
|
||||
check:
|
||||
@ -458,30 +460,30 @@ jobs:
|
||||
run: pre-commit run --all-files detect-private-key
|
||||
|
||||
- name: Audit changed GitHub workflows with zizmor
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BASE="$(
|
||||
python - <<'PY'
|
||||
import json
|
||||
import os
|
||||
if [ -z "${BASE_SHA:-}" ] || [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "No usable base SHA detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
with open(os.environ["GITHUB_EVENT_PATH"], "r", encoding="utf-8") as fh:
|
||||
event = json.load(fh)
|
||||
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
|
||||
echo "Base SHA ${BASE_SHA} is unavailable; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if os.environ["GITHUB_EVENT_NAME"] == "push":
|
||||
print(event["before"])
|
||||
else:
|
||||
print(event["pull_request"]["base"]["sha"])
|
||||
PY
|
||||
)"
|
||||
|
||||
mapfile -t workflow_files < <(git diff --name-only "$BASE" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml')
|
||||
mapfile -t workflow_files < <(
|
||||
git diff --name-only "${BASE_SHA}" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
||||
)
|
||||
if [ "${#workflow_files[@]}" -eq 0 ]; then
|
||||
echo "No workflow changes detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'Auditing workflow files:\n%s\n' "${workflow_files[@]}"
|
||||
pre-commit run zizmor --files "${workflow_files[@]}"
|
||||
|
||||
- name: Audit production dependencies
|
||||
|
||||
@ -34,11 +34,13 @@ Docs: https://docs.openclaw.ai
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` seam for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
|
||||
### Breaking
|
||||
|
||||
- Browser/Chrome MCP: remove the legacy Chrome extension relay path, bundled extension assets, `driver: "extension"`, and `browser.relayBindHost`. Run `openclaw doctor --fix` to migrate host-local browser config to `existing-session` / `user`; Docker, headless, sandbox, and remote browser flows still use raw CDP. (#47893) Thanks @vincentkoc.
|
||||
- Plugins/runtime: remove the public `openclaw/extension-api` surface with no compatibility shim. Bundled plugins must use injected runtime for host-side operations (for example `api.runtime.agent.runEmbeddedPiAgent`) and any remaining direct imports must come from narrow `openclaw/plugin-sdk/*` subpaths instead of the monolithic SDK root.
|
||||
- Tools/image generation: standardize the stock image create/edit path on the core `image_generate` tool. The old `nano-banana-pro` docs/examples are gone; if you previously copied that sample-skill config, switch to `agents.defaults.imageGenerationModel` for built-in image generation or install a separate third-party skill explicitly.
|
||||
|
||||
### Fixes
|
||||
|
||||
@ -119,6 +121,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Agents/bootstrap warnings: move bootstrap truncation warnings out of the system prompt and into the per-turn prompt body so prompt-cache reuse stays stable when truncation warnings appear or disappear. (#48753) Thanks @scoootscooob and @obviyus.
|
||||
- Telegram/DM topic session keys: route named-account DM topics through the same per-account base session key across inbound messages, native commands, and session-state lookups so `/status` and thread recovery stop creating phantom `agent:main:main:thread:...` sessions. (#48204) Thanks @vincentkoc.
|
||||
|
||||
## 2026.3.13
|
||||
|
||||
|
||||
@ -434,7 +434,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
|
||||
nodeManager: "npm",
|
||||
},
|
||||
entries: {
|
||||
"nano-banana-pro": {
|
||||
"image-lab": {
|
||||
enabled: true,
|
||||
apiKey: "GEMINI_KEY_HERE",
|
||||
env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" },
|
||||
|
||||
@ -2371,7 +2371,7 @@ See [Local Models](/gateway/local-models). TL;DR: run MiniMax M2.5 via LM Studio
|
||||
nodeManager: "npm", // npm | pnpm | yarn
|
||||
},
|
||||
entries: {
|
||||
"nano-banana-pro": {
|
||||
"image-lab": {
|
||||
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // or plaintext string
|
||||
env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" },
|
||||
},
|
||||
|
||||
@ -597,11 +597,11 @@ Rules:
|
||||
},
|
||||
skills: {
|
||||
entries: {
|
||||
"nano-banana-pro": {
|
||||
"image-lab": {
|
||||
apiKey: {
|
||||
source: "file",
|
||||
provider: "filemain",
|
||||
id: "/skills/entries/nano-banana-pro/apiKey",
|
||||
id: "/skills/entries/image-lab/apiKey",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -360,14 +360,29 @@ If you want to rely on env keys (e.g. exported in your `~/.profile`), run local
|
||||
- Enable: `BYTEPLUS_API_KEY=... BYTEPLUS_LIVE_TEST=1 pnpm test:live src/agents/byteplus.live.test.ts`
|
||||
- Optional model override: `BYTEPLUS_CODING_MODEL=ark-code-latest`
|
||||
|
||||
## Google image generation live
|
||||
## Image generation live
|
||||
|
||||
- Test: `src/image-generation/providers/google.live.test.ts`
|
||||
- Enable: `GOOGLE_LIVE_TEST=1 pnpm test:live src/image-generation/providers/google.live.test.ts`
|
||||
- Key source: `GEMINI_API_KEY` or `GOOGLE_API_KEY`
|
||||
- Optional overrides:
|
||||
- `GOOGLE_IMAGE_GENERATION_MODEL=gemini-3.1-flash-image-preview`
|
||||
- `GOOGLE_IMAGE_BASE_URL=https://generativelanguage.googleapis.com/v1beta`
|
||||
- Test: `src/image-generation/runtime.live.test.ts`
|
||||
- Command: `pnpm test:live src/image-generation/runtime.live.test.ts`
|
||||
- Scope:
|
||||
- Enumerates every registered image-generation provider plugin
|
||||
- Loads missing provider env vars from your login shell (`~/.profile`) before probing
|
||||
- Uses live/env API keys ahead of stored auth profiles by default, so stale test keys in `auth-profiles.json` do not mask real shell credentials
|
||||
- Skips providers with no usable auth/profile/model
|
||||
- Runs the stock image-generation variants through the shared runtime capability:
|
||||
- `google:flash-generate`
|
||||
- `google:pro-generate`
|
||||
- `google:pro-edit`
|
||||
- `openai:default-generate`
|
||||
- Current bundled providers covered:
|
||||
- `openai`
|
||||
- `google`
|
||||
- Optional narrowing:
|
||||
- `OPENCLAW_LIVE_IMAGE_GENERATION_PROVIDERS="openai,google"`
|
||||
- `OPENCLAW_LIVE_IMAGE_GENERATION_MODELS="openai/gpt-image-1,google/gemini-3.1-flash-image-preview"`
|
||||
- `OPENCLAW_LIVE_IMAGE_GENERATION_CASES="google:flash-generate,google:pro-edit"`
|
||||
- Optional auth behavior:
|
||||
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` to force profile-store auth and ignore env-only overrides
|
||||
|
||||
## Docker runners (optional “works in Linux” checks)
|
||||
|
||||
|
||||
@ -400,6 +400,30 @@ Notes:
|
||||
- Only available when `agents.defaults.imageModel` is configured (primary or fallbacks), or when an implicit image model can be inferred from your default model + configured auth (best-effort pairing).
|
||||
- Uses the image model directly (independent of the main chat model).
|
||||
|
||||
### `image_generate`
|
||||
|
||||
Generate one or more images with the configured image-generation model.
|
||||
|
||||
Core parameters:
|
||||
|
||||
- `action` (optional: `generate` or `list`; default `generate`)
|
||||
- `prompt` (required)
|
||||
- `image` or `images` (optional reference image path/URL for edit mode)
|
||||
- `model` (optional provider/model override)
|
||||
- `size` (optional size hint)
|
||||
- `resolution` (optional `1K|2K|4K` hint)
|
||||
- `count` (optional, `1-4`, default `1`)
|
||||
|
||||
Notes:
|
||||
|
||||
- Only available when `agents.defaults.imageGenerationModel` is configured.
|
||||
- Use `action: "list"` to inspect registered providers, default models, supported model ids, sizes, resolutions, and edit support.
|
||||
- Returns local `MEDIA:<path>` lines so channels can deliver the generated files directly.
|
||||
- Uses the image-generation model directly (independent of the main chat model).
|
||||
- Google-backed flows support reference-image edits plus explicit `1K|2K|4K` resolution hints.
|
||||
- When editing and `resolution` is omitted, OpenClaw infers a draft/final resolution from the input image size.
|
||||
- This is the built-in replacement for the old sample `nano-banana-pro` skill workflow. Use `agents.defaults.imageGenerationModel`, not `skills.entries`, for stock image generation.
|
||||
|
||||
### `pdf`
|
||||
|
||||
Analyze one or more PDF documents.
|
||||
|
||||
@ -24,7 +24,7 @@ All skills-related configuration lives under `skills` in `~/.openclaw/openclaw.j
|
||||
nodeManager: "npm", // npm | pnpm | yarn | bun (Gateway runtime still Node; bun not recommended)
|
||||
},
|
||||
entries: {
|
||||
"nano-banana-pro": {
|
||||
"image-lab": {
|
||||
enabled: true,
|
||||
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // or plaintext string
|
||||
env: {
|
||||
@ -38,6 +38,10 @@ All skills-related configuration lives under `skills` in `~/.openclaw/openclaw.j
|
||||
}
|
||||
```
|
||||
|
||||
For built-in image generation/editing, prefer `agents.defaults.imageGenerationModel`
|
||||
plus the core `image_generate` tool. `skills.entries.*` is only for custom or
|
||||
third-party skill workflows.
|
||||
|
||||
## Fields
|
||||
|
||||
- `allowBundled`: optional allowlist for **bundled** skills only. When set, only
|
||||
|
||||
@ -81,8 +81,8 @@ that up as `<workspace>/skills` on the next session.
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: nano-banana-pro
|
||||
description: Generate or edit images via Gemini 3 Pro Image
|
||||
name: image-lab
|
||||
description: Generate or edit images via a provider-backed image workflow
|
||||
---
|
||||
```
|
||||
|
||||
@ -109,8 +109,8 @@ OpenClaw **filters skills at load time** using `metadata` (single-line JSON):
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: nano-banana-pro
|
||||
description: Generate or edit images via Gemini 3 Pro Image
|
||||
name: image-lab
|
||||
description: Generate or edit images via a provider-backed image workflow
|
||||
metadata:
|
||||
{
|
||||
"openclaw":
|
||||
@ -194,7 +194,7 @@ Bundled/managed skills can be toggled and supplied with env values:
|
||||
{
|
||||
skills: {
|
||||
entries: {
|
||||
"nano-banana-pro": {
|
||||
"image-lab": {
|
||||
enabled: true,
|
||||
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" }, // or plaintext string
|
||||
env: {
|
||||
@ -214,6 +214,10 @@ Bundled/managed skills can be toggled and supplied with env values:
|
||||
|
||||
Note: if the skill name contains hyphens, quote the key (JSON5 allows quoted keys).
|
||||
|
||||
If you want stock image generation/editing inside OpenClaw itself, use the core
|
||||
`image_generate` tool with `agents.defaults.imageGenerationModel` instead of a
|
||||
bundled skill. Skill examples here are for custom or third-party workflows.
|
||||
|
||||
Config keys match the **skill name** by default. If a skill defines
|
||||
`metadata.openclaw.skillKey`, use that key under `skills.entries`.
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { registerSingleProviderPlugin } from "../test-utils/plugin-registration.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/extensions/plugin-registration.js";
|
||||
import amazonBedrockPlugin from "./index.js";
|
||||
|
||||
describe("amazon-bedrock provider plugin", () => {
|
||||
|
||||
@ -15,87 +15,17 @@ import {
|
||||
sendMessageBlueBubbles as sendMessageBlueBubblesImpl,
|
||||
} from "./send.js";
|
||||
|
||||
type SendBlueBubblesAttachment = typeof import("./attachments.js").sendBlueBubblesAttachment;
|
||||
type AddBlueBubblesParticipant = typeof import("./chat.js").addBlueBubblesParticipant;
|
||||
type EditBlueBubblesMessage = typeof import("./chat.js").editBlueBubblesMessage;
|
||||
type LeaveBlueBubblesChat = typeof import("./chat.js").leaveBlueBubblesChat;
|
||||
type RemoveBlueBubblesParticipant = typeof import("./chat.js").removeBlueBubblesParticipant;
|
||||
type RenameBlueBubblesChat = typeof import("./chat.js").renameBlueBubblesChat;
|
||||
type SetGroupIconBlueBubbles = typeof import("./chat.js").setGroupIconBlueBubbles;
|
||||
type UnsendBlueBubblesMessage = typeof import("./chat.js").unsendBlueBubblesMessage;
|
||||
type ResolveBlueBubblesMessageId = typeof import("./monitor.js").resolveBlueBubblesMessageId;
|
||||
type SendBlueBubblesReaction = typeof import("./reactions.js").sendBlueBubblesReaction;
|
||||
type ResolveChatGuidForTarget = typeof import("./send.js").resolveChatGuidForTarget;
|
||||
type SendMessageBlueBubbles = typeof import("./send.js").sendMessageBlueBubbles;
|
||||
|
||||
export function sendBlueBubblesAttachment(
|
||||
...args: Parameters<SendBlueBubblesAttachment>
|
||||
): ReturnType<SendBlueBubblesAttachment> {
|
||||
return sendBlueBubblesAttachmentImpl(...args);
|
||||
}
|
||||
|
||||
export function addBlueBubblesParticipant(
|
||||
...args: Parameters<AddBlueBubblesParticipant>
|
||||
): ReturnType<AddBlueBubblesParticipant> {
|
||||
return addBlueBubblesParticipantImpl(...args);
|
||||
}
|
||||
|
||||
export function editBlueBubblesMessage(
|
||||
...args: Parameters<EditBlueBubblesMessage>
|
||||
): ReturnType<EditBlueBubblesMessage> {
|
||||
return editBlueBubblesMessageImpl(...args);
|
||||
}
|
||||
|
||||
export function leaveBlueBubblesChat(
|
||||
...args: Parameters<LeaveBlueBubblesChat>
|
||||
): ReturnType<LeaveBlueBubblesChat> {
|
||||
return leaveBlueBubblesChatImpl(...args);
|
||||
}
|
||||
|
||||
export function removeBlueBubblesParticipant(
|
||||
...args: Parameters<RemoveBlueBubblesParticipant>
|
||||
): ReturnType<RemoveBlueBubblesParticipant> {
|
||||
return removeBlueBubblesParticipantImpl(...args);
|
||||
}
|
||||
|
||||
export function renameBlueBubblesChat(
|
||||
...args: Parameters<RenameBlueBubblesChat>
|
||||
): ReturnType<RenameBlueBubblesChat> {
|
||||
return renameBlueBubblesChatImpl(...args);
|
||||
}
|
||||
|
||||
export function setGroupIconBlueBubbles(
|
||||
...args: Parameters<SetGroupIconBlueBubbles>
|
||||
): ReturnType<SetGroupIconBlueBubbles> {
|
||||
return setGroupIconBlueBubblesImpl(...args);
|
||||
}
|
||||
|
||||
export function unsendBlueBubblesMessage(
|
||||
...args: Parameters<UnsendBlueBubblesMessage>
|
||||
): ReturnType<UnsendBlueBubblesMessage> {
|
||||
return unsendBlueBubblesMessageImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveBlueBubblesMessageId(
|
||||
...args: Parameters<ResolveBlueBubblesMessageId>
|
||||
): ReturnType<ResolveBlueBubblesMessageId> {
|
||||
return resolveBlueBubblesMessageIdImpl(...args);
|
||||
}
|
||||
|
||||
export function sendBlueBubblesReaction(
|
||||
...args: Parameters<SendBlueBubblesReaction>
|
||||
): ReturnType<SendBlueBubblesReaction> {
|
||||
return sendBlueBubblesReactionImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveChatGuidForTarget(
|
||||
...args: Parameters<ResolveChatGuidForTarget>
|
||||
): ReturnType<ResolveChatGuidForTarget> {
|
||||
return resolveChatGuidForTargetImpl(...args);
|
||||
}
|
||||
|
||||
export function sendMessageBlueBubbles(
|
||||
...args: Parameters<SendMessageBlueBubbles>
|
||||
): ReturnType<SendMessageBlueBubbles> {
|
||||
return sendMessageBlueBubblesImpl(...args);
|
||||
}
|
||||
export const blueBubblesActionsRuntime = {
|
||||
sendBlueBubblesAttachment: sendBlueBubblesAttachmentImpl,
|
||||
addBlueBubblesParticipant: addBlueBubblesParticipantImpl,
|
||||
editBlueBubblesMessage: editBlueBubblesMessageImpl,
|
||||
leaveBlueBubblesChat: leaveBlueBubblesChatImpl,
|
||||
removeBlueBubblesParticipant: removeBlueBubblesParticipantImpl,
|
||||
renameBlueBubblesChat: renameBlueBubblesChatImpl,
|
||||
setGroupIconBlueBubbles: setGroupIconBlueBubblesImpl,
|
||||
unsendBlueBubblesMessage: unsendBlueBubblesMessageImpl,
|
||||
resolveBlueBubblesMessageId: resolveBlueBubblesMessageIdImpl,
|
||||
sendBlueBubblesReaction: sendBlueBubblesReactionImpl,
|
||||
resolveChatGuidForTarget: resolveChatGuidForTargetImpl,
|
||||
sendMessageBlueBubbles: sendMessageBlueBubblesImpl,
|
||||
};
|
||||
|
||||
@ -11,18 +11,19 @@ import {
|
||||
type ChannelMessageActionAdapter,
|
||||
type ChannelMessageActionName,
|
||||
} from "openclaw/plugin-sdk/bluebubbles";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import { resolveBlueBubblesAccount } from "./accounts.js";
|
||||
import { getCachedBlueBubblesPrivateApiStatus, isMacOS26OrHigher } from "./probe.js";
|
||||
import { normalizeSecretInputString } from "./secret-input.js";
|
||||
import { normalizeBlueBubblesHandle, parseBlueBubblesTarget } from "./targets.js";
|
||||
import type { BlueBubblesSendTarget } from "./types.js";
|
||||
|
||||
let actionsRuntimePromise: Promise<typeof import("./actions.runtime.js")> | null = null;
|
||||
type BlueBubblesActionsRuntime = typeof import("./actions.runtime.js").blueBubblesActionsRuntime;
|
||||
|
||||
function loadBlueBubblesActionsRuntime() {
|
||||
actionsRuntimePromise ??= import("./actions.runtime.js");
|
||||
return actionsRuntimePromise;
|
||||
}
|
||||
const loadBlueBubblesActionsRuntime = createLazyRuntimeSurface(
|
||||
() => import("./actions.runtime.js"),
|
||||
({ blueBubblesActionsRuntime }) => blueBubblesActionsRuntime,
|
||||
);
|
||||
|
||||
const providerId = "bluebubbles";
|
||||
|
||||
|
||||
@ -6,52 +6,14 @@ import {
|
||||
} from "./monitor.js";
|
||||
import { probeBlueBubbles as probeBlueBubblesImpl } from "./probe.js";
|
||||
import { sendMessageBlueBubbles as sendMessageBlueBubblesImpl } from "./send.js";
|
||||
import { blueBubblesSetupWizard as blueBubblesSetupWizardImpl } from "./setup-surface.js";
|
||||
|
||||
export type { BlueBubblesProbe } from "./probe.js";
|
||||
|
||||
type SendBlueBubblesMedia = typeof import("./media-send.js").sendBlueBubblesMedia;
|
||||
type ResolveBlueBubblesMessageId = typeof import("./monitor.js").resolveBlueBubblesMessageId;
|
||||
type MonitorBlueBubblesProvider = typeof import("./monitor.js").monitorBlueBubblesProvider;
|
||||
type ResolveWebhookPathFromConfig = typeof import("./monitor.js").resolveWebhookPathFromConfig;
|
||||
type ProbeBlueBubbles = typeof import("./probe.js").probeBlueBubbles;
|
||||
type SendMessageBlueBubbles = typeof import("./send.js").sendMessageBlueBubbles;
|
||||
type BlueBubblesSetupWizard = typeof import("./setup-surface.js").blueBubblesSetupWizard;
|
||||
|
||||
export function sendBlueBubblesMedia(
|
||||
...args: Parameters<SendBlueBubblesMedia>
|
||||
): ReturnType<SendBlueBubblesMedia> {
|
||||
return sendBlueBubblesMediaImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveBlueBubblesMessageId(
|
||||
...args: Parameters<ResolveBlueBubblesMessageId>
|
||||
): ReturnType<ResolveBlueBubblesMessageId> {
|
||||
return resolveBlueBubblesMessageIdImpl(...args);
|
||||
}
|
||||
|
||||
export function monitorBlueBubblesProvider(
|
||||
...args: Parameters<MonitorBlueBubblesProvider>
|
||||
): ReturnType<MonitorBlueBubblesProvider> {
|
||||
return monitorBlueBubblesProviderImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveWebhookPathFromConfig(
|
||||
...args: Parameters<ResolveWebhookPathFromConfig>
|
||||
): ReturnType<ResolveWebhookPathFromConfig> {
|
||||
return resolveWebhookPathFromConfigImpl(...args);
|
||||
}
|
||||
|
||||
export function probeBlueBubbles(
|
||||
...args: Parameters<ProbeBlueBubbles>
|
||||
): ReturnType<ProbeBlueBubbles> {
|
||||
return probeBlueBubblesImpl(...args);
|
||||
}
|
||||
|
||||
export function sendMessageBlueBubbles(
|
||||
...args: Parameters<SendMessageBlueBubbles>
|
||||
): ReturnType<SendMessageBlueBubbles> {
|
||||
return sendMessageBlueBubblesImpl(...args);
|
||||
}
|
||||
|
||||
export const blueBubblesSetupWizard: BlueBubblesSetupWizard = { ...blueBubblesSetupWizardImpl };
|
||||
export const blueBubblesChannelRuntime = {
|
||||
sendBlueBubblesMedia: sendBlueBubblesMediaImpl,
|
||||
resolveBlueBubblesMessageId: resolveBlueBubblesMessageIdImpl,
|
||||
monitorBlueBubblesProvider: monitorBlueBubblesProviderImpl,
|
||||
resolveWebhookPathFromConfig: resolveWebhookPathFromConfigImpl,
|
||||
probeBlueBubbles: probeBlueBubblesImpl,
|
||||
sendMessageBlueBubbles: sendMessageBlueBubblesImpl,
|
||||
};
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
buildAccountScopedDmSecurityPolicy,
|
||||
collectOpenGroupPolicyRestrictSendersWarnings,
|
||||
} from "openclaw/plugin-sdk/channel-policy";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import {
|
||||
listBlueBubblesAccountIds,
|
||||
type ResolvedBlueBubblesAccount,
|
||||
@ -37,12 +38,12 @@ import {
|
||||
parseBlueBubblesTarget,
|
||||
} from "./targets.js";
|
||||
|
||||
let blueBubblesChannelRuntimePromise: Promise<typeof import("./channel.runtime.js")> | null = null;
|
||||
type BlueBubblesChannelRuntime = typeof import("./channel.runtime.js").blueBubblesChannelRuntime;
|
||||
|
||||
function loadBlueBubblesChannelRuntime() {
|
||||
blueBubblesChannelRuntimePromise ??= import("./channel.runtime.js");
|
||||
return blueBubblesChannelRuntimePromise;
|
||||
}
|
||||
const loadBlueBubblesChannelRuntime = createLazyRuntimeSurface(
|
||||
() => import("./channel.runtime.js"),
|
||||
({ blueBubblesChannelRuntime }) => blueBubblesChannelRuntime,
|
||||
);
|
||||
|
||||
const meta = {
|
||||
id: "bluebubbles",
|
||||
|
||||
@ -2,7 +2,7 @@ import { EventEmitter } from "node:events";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/bluebubbles";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import type { ResolvedBlueBubblesAccount } from "./accounts.js";
|
||||
import { fetchBlueBubblesHistory } from "./history.js";
|
||||
import { resetBlueBubblesSelfChatCache } from "./monitor-self-chat-cache.js";
|
||||
|
||||
@ -2,7 +2,7 @@ import { EventEmitter } from "node:events";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/bluebubbles";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import type { ResolvedBlueBubblesAccount } from "./accounts.js";
|
||||
import { fetchBlueBubblesHistory } from "./history.js";
|
||||
import {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/diffs";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createMockServerResponse } from "../test-utils/mock-http-response.js";
|
||||
import { createTestPluginApi } from "../test-utils/plugin-api.js";
|
||||
import { createMockServerResponse } from "../../test/helpers/extensions/mock-http-response.js";
|
||||
import { createTestPluginApi } from "../../test/helpers/extensions/plugin-api.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
describe("diffs plugin registration", () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { IncomingMessage } from "node:http";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { createMockServerResponse } from "../../test-utils/mock-http-response.js";
|
||||
import { createMockServerResponse } from "../../../test/helpers/extensions/mock-http-response.js";
|
||||
import { createDiffsHttpHandler } from "./http.js";
|
||||
import { DiffArtifactStore } from "./store.js";
|
||||
import { createDiffStoreHarness } from "./test-helpers.js";
|
||||
|
||||
@ -2,7 +2,7 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/diffs";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createTestPluginApi } from "../../test-utils/plugin-api.js";
|
||||
import { createTestPluginApi } from "../../../test/helpers/extensions/plugin-api.js";
|
||||
import type { DiffScreenshotter } from "./browser.js";
|
||||
import { DEFAULT_DIFFS_TOOL_DEFAULTS } from "./config.js";
|
||||
import { DiffArtifactStore } from "./store.js";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
|
||||
import { fetchDiscord } from "./api.js";
|
||||
import { jsonResponse } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { countLines, hasBalancedFences } from "../../test-utils/chunk-test-helpers.js";
|
||||
import {
|
||||
countLines,
|
||||
hasBalancedFences,
|
||||
} from "../../../test/helpers/extensions/chunk-test-helpers.js";
|
||||
import { chunkDiscordText, chunkDiscordTextWithMode } from "./chunk.js";
|
||||
|
||||
describe("chunkDiscordText", () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ChannelType, type Guild } from "@buape/carbon";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { typedCases } from "../../test-utils/typed-cases.js";
|
||||
import { typedCases } from "../../../test/helpers/extensions/typed-cases.js";
|
||||
import {
|
||||
allowListMatches,
|
||||
buildDiscordMediaPayload,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { vi } from "vitest";
|
||||
|
||||
export const sendMock: MockFn = vi.fn();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { vi } from "vitest";
|
||||
|
||||
export const preflightDiscordMessageMock: MockFn = vi.fn();
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
baseRuntime,
|
||||
getProviderMonitorTestMocks,
|
||||
resetDiscordProviderMonitorMocks,
|
||||
} from "./provider.test-support.js";
|
||||
} from "../../../../test/helpers/extensions/discord-provider.test-support.js";
|
||||
|
||||
const { createDiscordNativeCommandMock, clientHandleDeployRequestMock, monitorLifecycleMock } =
|
||||
getProviderMonitorTestMocks();
|
||||
|
||||
@ -1,459 +1 @@
|
||||
import type { Mock } from "vitest";
|
||||
import { expect, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
import type { RuntimeEnv } from "../../../../src/runtime.js";
|
||||
|
||||
export type NativeCommandSpecMock = {
|
||||
name: string;
|
||||
description: string;
|
||||
acceptsArgs: boolean;
|
||||
};
|
||||
|
||||
export type PluginCommandSpecMock = {
|
||||
name: string;
|
||||
description: string;
|
||||
acceptsArgs: boolean;
|
||||
};
|
||||
|
||||
type ProviderMonitorTestMocks = {
|
||||
clientHandleDeployRequestMock: Mock<() => Promise<void>>;
|
||||
clientFetchUserMock: Mock<(target: string) => Promise<{ id: string }>>;
|
||||
clientGetPluginMock: Mock<(name: string) => unknown>;
|
||||
clientConstructorOptionsMock: Mock<(options?: unknown) => void>;
|
||||
createDiscordAutoPresenceControllerMock: Mock<() => unknown>;
|
||||
createDiscordNativeCommandMock: Mock<(params?: { command?: { name?: string } }) => unknown>;
|
||||
createDiscordMessageHandlerMock: Mock<() => unknown>;
|
||||
createNoopThreadBindingManagerMock: Mock<() => { stop: ReturnType<typeof vi.fn> }>;
|
||||
createThreadBindingManagerMock: Mock<() => { stop: ReturnType<typeof vi.fn> }>;
|
||||
reconcileAcpThreadBindingsOnStartupMock: Mock<() => unknown>;
|
||||
createdBindingManagers: Array<{ stop: ReturnType<typeof vi.fn> }>;
|
||||
getAcpSessionStatusMock: Mock<
|
||||
(params: {
|
||||
cfg: OpenClawConfig;
|
||||
sessionKey: string;
|
||||
signal?: AbortSignal;
|
||||
}) => Promise<{ state: string }>
|
||||
>;
|
||||
getPluginCommandSpecsMock: Mock<() => PluginCommandSpecMock[]>;
|
||||
listNativeCommandSpecsForConfigMock: Mock<() => NativeCommandSpecMock[]>;
|
||||
listSkillCommandsForAgentsMock: Mock<() => unknown[]>;
|
||||
monitorLifecycleMock: Mock<(params: { threadBindings: { stop: () => void } }) => Promise<void>>;
|
||||
resolveDiscordAccountMock: Mock<() => unknown>;
|
||||
resolveDiscordAllowlistConfigMock: Mock<() => Promise<unknown>>;
|
||||
resolveNativeCommandsEnabledMock: Mock<() => boolean>;
|
||||
resolveNativeSkillsEnabledMock: Mock<() => boolean>;
|
||||
isVerboseMock: Mock<() => boolean>;
|
||||
shouldLogVerboseMock: Mock<() => boolean>;
|
||||
voiceRuntimeModuleLoadedMock: Mock<() => void>;
|
||||
};
|
||||
|
||||
export function baseDiscordAccountConfig() {
|
||||
return {
|
||||
commands: { native: true, nativeSkills: false },
|
||||
voice: { enabled: false },
|
||||
agentComponents: { enabled: false },
|
||||
execApprovals: { enabled: false },
|
||||
};
|
||||
}
|
||||
|
||||
const providerMonitorTestMocks: ProviderMonitorTestMocks = vi.hoisted(() => {
|
||||
const createdBindingManagers: Array<{ stop: ReturnType<typeof vi.fn> }> = [];
|
||||
const isVerboseMock = vi.fn(() => false);
|
||||
const shouldLogVerboseMock = vi.fn(() => false);
|
||||
|
||||
return {
|
||||
clientHandleDeployRequestMock: vi.fn(async () => undefined),
|
||||
clientFetchUserMock: vi.fn(async (_target: string) => ({ id: "bot-1" })),
|
||||
clientGetPluginMock: vi.fn<(_name: string) => unknown>(() => undefined),
|
||||
clientConstructorOptionsMock: vi.fn(),
|
||||
createDiscordAutoPresenceControllerMock: vi.fn(() => ({
|
||||
enabled: false,
|
||||
start: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
runNow: vi.fn(),
|
||||
})),
|
||||
createDiscordNativeCommandMock: vi.fn((params?: { command?: { name?: string } }) => ({
|
||||
name: params?.command?.name ?? "mock-command",
|
||||
})),
|
||||
createDiscordMessageHandlerMock: vi.fn(() =>
|
||||
Object.assign(
|
||||
vi.fn(async () => undefined),
|
||||
{
|
||||
deactivate: vi.fn(),
|
||||
},
|
||||
),
|
||||
),
|
||||
createNoopThreadBindingManagerMock: vi.fn(() => {
|
||||
const manager = { stop: vi.fn() };
|
||||
createdBindingManagers.push(manager);
|
||||
return manager;
|
||||
}),
|
||||
createThreadBindingManagerMock: vi.fn(() => {
|
||||
const manager = { stop: vi.fn() };
|
||||
createdBindingManagers.push(manager);
|
||||
return manager;
|
||||
}),
|
||||
reconcileAcpThreadBindingsOnStartupMock: vi.fn(() => ({
|
||||
checked: 0,
|
||||
removed: 0,
|
||||
staleSessionKeys: [],
|
||||
})),
|
||||
createdBindingManagers,
|
||||
getAcpSessionStatusMock: vi.fn(
|
||||
async (_params: { cfg: OpenClawConfig; sessionKey: string; signal?: AbortSignal }) => ({
|
||||
state: "idle",
|
||||
}),
|
||||
),
|
||||
getPluginCommandSpecsMock: vi.fn<() => PluginCommandSpecMock[]>(() => []),
|
||||
listNativeCommandSpecsForConfigMock: vi.fn<() => NativeCommandSpecMock[]>(() => [
|
||||
{ name: "cmd", description: "built-in", acceptsArgs: false },
|
||||
]),
|
||||
listSkillCommandsForAgentsMock: vi.fn(() => []),
|
||||
monitorLifecycleMock: vi.fn(async (params: { threadBindings: { stop: () => void } }) => {
|
||||
params.threadBindings.stop();
|
||||
}),
|
||||
resolveDiscordAccountMock: vi.fn(() => ({
|
||||
accountId: "default",
|
||||
token: "cfg-token",
|
||||
config: baseDiscordAccountConfig(),
|
||||
})),
|
||||
resolveDiscordAllowlistConfigMock: vi.fn(async () => ({
|
||||
guildEntries: undefined,
|
||||
allowFrom: undefined,
|
||||
})),
|
||||
resolveNativeCommandsEnabledMock: vi.fn(() => true),
|
||||
resolveNativeSkillsEnabledMock: vi.fn(() => false),
|
||||
isVerboseMock,
|
||||
shouldLogVerboseMock,
|
||||
voiceRuntimeModuleLoadedMock: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
const {
|
||||
clientHandleDeployRequestMock,
|
||||
clientFetchUserMock,
|
||||
clientGetPluginMock,
|
||||
clientConstructorOptionsMock,
|
||||
createDiscordAutoPresenceControllerMock,
|
||||
createDiscordNativeCommandMock,
|
||||
createDiscordMessageHandlerMock,
|
||||
createNoopThreadBindingManagerMock,
|
||||
createThreadBindingManagerMock,
|
||||
reconcileAcpThreadBindingsOnStartupMock,
|
||||
createdBindingManagers,
|
||||
getAcpSessionStatusMock,
|
||||
getPluginCommandSpecsMock,
|
||||
listNativeCommandSpecsForConfigMock,
|
||||
listSkillCommandsForAgentsMock,
|
||||
monitorLifecycleMock,
|
||||
resolveDiscordAccountMock,
|
||||
resolveDiscordAllowlistConfigMock,
|
||||
resolveNativeCommandsEnabledMock,
|
||||
resolveNativeSkillsEnabledMock,
|
||||
isVerboseMock,
|
||||
shouldLogVerboseMock,
|
||||
voiceRuntimeModuleLoadedMock,
|
||||
} = providerMonitorTestMocks;
|
||||
|
||||
export function getProviderMonitorTestMocks(): typeof providerMonitorTestMocks {
|
||||
return providerMonitorTestMocks;
|
||||
}
|
||||
|
||||
export function mockResolvedDiscordAccountConfig(overrides: Record<string, unknown>) {
|
||||
resolveDiscordAccountMock.mockImplementation(() => ({
|
||||
accountId: "default",
|
||||
token: "cfg-token",
|
||||
config: {
|
||||
...baseDiscordAccountConfig(),
|
||||
...overrides,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
export function getFirstDiscordMessageHandlerParams<T extends object>() {
|
||||
expect(createDiscordMessageHandlerMock).toHaveBeenCalledTimes(1);
|
||||
const firstCall = createDiscordMessageHandlerMock.mock.calls.at(0) as [T] | undefined;
|
||||
return firstCall?.[0];
|
||||
}
|
||||
|
||||
export function resetDiscordProviderMonitorMocks(params?: {
|
||||
nativeCommands?: NativeCommandSpecMock[];
|
||||
}) {
|
||||
clientHandleDeployRequestMock.mockClear().mockResolvedValue(undefined);
|
||||
clientFetchUserMock.mockClear().mockResolvedValue({ id: "bot-1" });
|
||||
clientGetPluginMock.mockClear().mockReturnValue(undefined);
|
||||
clientConstructorOptionsMock.mockClear();
|
||||
createDiscordAutoPresenceControllerMock.mockClear().mockImplementation(() => ({
|
||||
enabled: false,
|
||||
start: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
runNow: vi.fn(),
|
||||
}));
|
||||
createDiscordNativeCommandMock.mockClear().mockImplementation((input) => ({
|
||||
name: input?.command?.name ?? "mock-command",
|
||||
}));
|
||||
createDiscordMessageHandlerMock.mockClear().mockImplementation(() =>
|
||||
Object.assign(
|
||||
vi.fn(async () => undefined),
|
||||
{
|
||||
deactivate: vi.fn(),
|
||||
},
|
||||
),
|
||||
);
|
||||
createNoopThreadBindingManagerMock.mockClear();
|
||||
createThreadBindingManagerMock.mockClear();
|
||||
reconcileAcpThreadBindingsOnStartupMock.mockClear().mockReturnValue({
|
||||
checked: 0,
|
||||
removed: 0,
|
||||
staleSessionKeys: [],
|
||||
});
|
||||
createdBindingManagers.length = 0;
|
||||
getAcpSessionStatusMock.mockClear().mockResolvedValue({ state: "idle" });
|
||||
getPluginCommandSpecsMock.mockClear().mockReturnValue([]);
|
||||
listNativeCommandSpecsForConfigMock
|
||||
.mockClear()
|
||||
.mockReturnValue(
|
||||
params?.nativeCommands ?? [{ name: "cmd", description: "built-in", acceptsArgs: false }],
|
||||
);
|
||||
listSkillCommandsForAgentsMock.mockClear().mockReturnValue([]);
|
||||
monitorLifecycleMock.mockClear().mockImplementation(async (monitorParams) => {
|
||||
monitorParams.threadBindings.stop();
|
||||
});
|
||||
resolveDiscordAccountMock.mockClear().mockReturnValue({
|
||||
accountId: "default",
|
||||
token: "cfg-token",
|
||||
config: baseDiscordAccountConfig(),
|
||||
});
|
||||
resolveDiscordAllowlistConfigMock.mockClear().mockResolvedValue({
|
||||
guildEntries: undefined,
|
||||
allowFrom: undefined,
|
||||
});
|
||||
resolveNativeCommandsEnabledMock.mockClear().mockReturnValue(true);
|
||||
resolveNativeSkillsEnabledMock.mockClear().mockReturnValue(false);
|
||||
isVerboseMock.mockClear().mockReturnValue(false);
|
||||
shouldLogVerboseMock.mockClear().mockReturnValue(false);
|
||||
voiceRuntimeModuleLoadedMock.mockClear();
|
||||
}
|
||||
|
||||
export const baseRuntime = (): RuntimeEnv => ({
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
});
|
||||
|
||||
export const baseConfig = (): OpenClawConfig =>
|
||||
({
|
||||
channels: {
|
||||
discord: {
|
||||
accounts: {
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as OpenClawConfig;
|
||||
|
||||
vi.mock("@buape/carbon", () => {
|
||||
class ReadyListener {}
|
||||
class RateLimitError extends Error {
|
||||
status = 429;
|
||||
discordCode?: number;
|
||||
retryAfter: number;
|
||||
scope: string | null;
|
||||
bucket: string | null;
|
||||
constructor(
|
||||
response: Response,
|
||||
body: { message: string; retry_after: number; global: boolean },
|
||||
) {
|
||||
super(body.message);
|
||||
this.retryAfter = body.retry_after;
|
||||
this.scope = body.global ? "global" : response.headers.get("X-RateLimit-Scope");
|
||||
this.bucket = response.headers.get("X-RateLimit-Bucket");
|
||||
}
|
||||
}
|
||||
class Client {
|
||||
listeners: unknown[];
|
||||
rest: { put: ReturnType<typeof vi.fn> };
|
||||
options: unknown;
|
||||
constructor(options: unknown, handlers: { listeners?: unknown[] }) {
|
||||
this.options = options;
|
||||
this.listeners = handlers.listeners ?? [];
|
||||
this.rest = { put: vi.fn(async () => undefined) };
|
||||
clientConstructorOptionsMock(options);
|
||||
}
|
||||
async handleDeployRequest() {
|
||||
return await clientHandleDeployRequestMock();
|
||||
}
|
||||
async fetchUser(target: string) {
|
||||
return await clientFetchUserMock(target);
|
||||
}
|
||||
getPlugin(name: string) {
|
||||
return clientGetPluginMock(name);
|
||||
}
|
||||
}
|
||||
return { Client, RateLimitError, ReadyListener };
|
||||
});
|
||||
|
||||
vi.mock("@buape/carbon/gateway", () => ({
|
||||
GatewayCloseCodes: { DisallowedIntents: 4014 },
|
||||
}));
|
||||
|
||||
vi.mock("@buape/carbon/voice", () => ({
|
||||
VoicePlugin: class VoicePlugin {},
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/acp/control-plane/manager.js", () => ({
|
||||
getAcpSessionManager: () => ({
|
||||
getSessionStatus: getAcpSessionStatusMock,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/auto-reply/chunk.js", () => ({
|
||||
resolveTextChunkLimit: () => 2000,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/auto-reply/commands-registry.js", () => ({
|
||||
listNativeCommandSpecsForConfig: listNativeCommandSpecsForConfigMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/auto-reply/skill-commands.js", () => ({
|
||||
listSkillCommandsForAgents: listSkillCommandsForAgentsMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/config/commands.js", () => ({
|
||||
isNativeCommandsExplicitlyDisabled: () => false,
|
||||
resolveNativeCommandsEnabled: resolveNativeCommandsEnabledMock,
|
||||
resolveNativeSkillsEnabled: resolveNativeSkillsEnabledMock,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/config/config.js", () => ({
|
||||
loadConfig: () => ({}),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/globals.js", () => ({
|
||||
danger: (value: string) => value,
|
||||
isVerbose: isVerboseMock,
|
||||
logVerbose: vi.fn(),
|
||||
shouldLogVerbose: shouldLogVerboseMock,
|
||||
warn: (value: string) => value,
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/infra/errors.js", () => ({
|
||||
formatErrorMessage: (error: unknown) => String(error),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/infra/retry-policy.js", () => ({
|
||||
createDiscordRetryRunner: () => async (run: () => Promise<unknown>) => run(),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/logging/subsystem.js", () => ({
|
||||
createSubsystemLogger: () => {
|
||||
const logger = {
|
||||
child: vi.fn(() => logger),
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
};
|
||||
return logger;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/runtime.js", () => ({
|
||||
createNonExitingRuntime: () => ({ log: vi.fn(), error: vi.fn(), exit: vi.fn() }),
|
||||
}));
|
||||
|
||||
vi.mock("../accounts.js", () => ({
|
||||
resolveDiscordAccount: resolveDiscordAccountMock,
|
||||
}));
|
||||
|
||||
vi.mock("../probe.js", () => ({
|
||||
fetchDiscordApplicationId: async () => "app-1",
|
||||
}));
|
||||
|
||||
vi.mock("../token.js", () => ({
|
||||
normalizeDiscordToken: (value?: string) => value,
|
||||
}));
|
||||
|
||||
vi.mock("../voice/command.js", () => ({
|
||||
createDiscordVoiceCommand: () => ({ name: "voice-command" }),
|
||||
}));
|
||||
|
||||
vi.mock("./agent-components.js", () => ({
|
||||
createAgentComponentButton: () => ({ id: "btn" }),
|
||||
createAgentSelectMenu: () => ({ id: "menu" }),
|
||||
createDiscordComponentButton: () => ({ id: "btn2" }),
|
||||
createDiscordComponentChannelSelect: () => ({ id: "channel" }),
|
||||
createDiscordComponentMentionableSelect: () => ({ id: "mentionable" }),
|
||||
createDiscordComponentModal: () => ({ id: "modal" }),
|
||||
createDiscordComponentRoleSelect: () => ({ id: "role" }),
|
||||
createDiscordComponentStringSelect: () => ({ id: "string" }),
|
||||
createDiscordComponentUserSelect: () => ({ id: "user" }),
|
||||
}));
|
||||
|
||||
vi.mock("./auto-presence.js", () => ({
|
||||
createDiscordAutoPresenceController: createDiscordAutoPresenceControllerMock,
|
||||
}));
|
||||
|
||||
vi.mock("./commands.js", () => ({
|
||||
resolveDiscordSlashCommandConfig: () => ({ ephemeral: false }),
|
||||
}));
|
||||
|
||||
vi.mock("./exec-approvals.js", () => ({
|
||||
createExecApprovalButton: () => ({ id: "exec-approval" }),
|
||||
DiscordExecApprovalHandler: class DiscordExecApprovalHandler {
|
||||
async start() {
|
||||
return undefined;
|
||||
}
|
||||
async stop() {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("./gateway-plugin.js", () => ({
|
||||
createDiscordGatewayPlugin: () => ({ id: "gateway-plugin" }),
|
||||
}));
|
||||
|
||||
vi.mock("./listeners.js", () => ({
|
||||
DiscordMessageListener: class DiscordMessageListener {},
|
||||
DiscordPresenceListener: class DiscordPresenceListener {},
|
||||
DiscordReactionListener: class DiscordReactionListener {},
|
||||
DiscordReactionRemoveListener: class DiscordReactionRemoveListener {},
|
||||
DiscordThreadUpdateListener: class DiscordThreadUpdateListener {},
|
||||
registerDiscordListener: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./message-handler.js", () => ({
|
||||
createDiscordMessageHandler: createDiscordMessageHandlerMock,
|
||||
}));
|
||||
|
||||
vi.mock("./native-command.js", () => ({
|
||||
createDiscordCommandArgFallbackButton: () => ({ id: "arg-fallback" }),
|
||||
createDiscordModelPickerFallbackButton: () => ({ id: "model-fallback-btn" }),
|
||||
createDiscordModelPickerFallbackSelect: () => ({ id: "model-fallback-select" }),
|
||||
createDiscordNativeCommand: createDiscordNativeCommandMock,
|
||||
}));
|
||||
|
||||
vi.mock("./presence.js", () => ({
|
||||
resolveDiscordPresenceUpdate: () => undefined,
|
||||
}));
|
||||
|
||||
vi.mock("./provider.allowlist.js", () => ({
|
||||
resolveDiscordAllowlistConfig: resolveDiscordAllowlistConfigMock,
|
||||
}));
|
||||
|
||||
vi.mock("./provider.lifecycle.js", () => ({
|
||||
runDiscordGatewayLifecycle: monitorLifecycleMock,
|
||||
}));
|
||||
|
||||
vi.mock("./rest-fetch.js", () => ({
|
||||
resolveDiscordRestFetch: () => async () => undefined,
|
||||
}));
|
||||
|
||||
vi.mock("./thread-bindings.js", () => ({
|
||||
createNoopThreadBindingManager: createNoopThreadBindingManagerMock,
|
||||
createThreadBindingManager: createThreadBindingManagerMock,
|
||||
reconcileAcpThreadBindingsOnStartup: reconcileAcpThreadBindingsOnStartupMock,
|
||||
}));
|
||||
export * from "../../../../test/helpers/extensions/discord-provider.test-support.js";
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
getProviderMonitorTestMocks,
|
||||
mockResolvedDiscordAccountConfig,
|
||||
resetDiscordProviderMonitorMocks,
|
||||
} from "./provider.test-support.js";
|
||||
} from "../../../../test/helpers/extensions/discord-provider.test-support.js";
|
||||
|
||||
const {
|
||||
clientConstructorOptionsMock,
|
||||
@ -37,9 +37,15 @@ const {
|
||||
voiceRuntimeModuleLoadedMock,
|
||||
} = getProviderMonitorTestMocks();
|
||||
|
||||
vi.mock("../../../../src/plugins/commands.js", () => ({
|
||||
getPluginCommandSpecs: getPluginCommandSpecsMock,
|
||||
}));
|
||||
vi.mock("openclaw/plugin-sdk/plugin-runtime", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/plugin-runtime")>(
|
||||
"openclaw/plugin-sdk/plugin-runtime",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
getPluginCommandSpecs: getPluginCommandSpecsMock,
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../voice/manager.runtime.js", () => {
|
||||
voiceRuntimeModuleLoadedMock();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
|
||||
import { resolveDiscordChannelAllowlist } from "./resolve-channels.js";
|
||||
import { jsonResponse, urlToString } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
|
||||
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
|
||||
import { jsonResponse, urlToString } from "./test-http-helpers.js";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { vi } from "vitest";
|
||||
|
||||
type DiscordWebMediaMockFactoryResult = {
|
||||
|
||||
@ -2,6 +2,7 @@ import type { DiscordGuildEntry } from "openclaw/plugin-sdk/config-runtime";
|
||||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
createEnvPatchedAccountSetupAdapter,
|
||||
formatDocsLink,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
parseMentionOrPrefixedId,
|
||||
@ -16,7 +17,6 @@ import {
|
||||
type ChannelSetupDmPolicy,
|
||||
type ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||
import { listDiscordAccountIds, resolveDiscordAccount } from "./accounts.js";
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import {
|
||||
formatDocsLink,
|
||||
type OpenClawConfig,
|
||||
promptLegacyChannelAllowFrom,
|
||||
resolveSetupAccountId,
|
||||
type WizardPrompter,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import { resolveDefaultDiscordAccountId, resolveDiscordAccount } from "./accounts.js";
|
||||
import { normalizeDiscordSlug } from "./monitor/allow-list.js";
|
||||
import {
|
||||
|
||||
@ -3,10 +3,12 @@ import {
|
||||
createScopedAccountConfigAccessors,
|
||||
createScopedChannelConfigBase,
|
||||
} from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { buildChannelConfigSchema } from "../../../src/channels/plugins/config-schema.js";
|
||||
import type { ChannelPlugin } from "../../../src/channels/plugins/types.plugin.js";
|
||||
import { getChatChannelMeta } from "../../../src/channels/registry.js";
|
||||
import { DiscordConfigSchema } from "../../../src/config/zod-schema.providers-core.js";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
DiscordConfigSchema,
|
||||
getChatChannelMeta,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/discord";
|
||||
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||
import {
|
||||
listDiscordAccountIds,
|
||||
|
||||
@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
getRequiredHookHandler,
|
||||
registerHookHandlersForTest,
|
||||
} from "../../test-utils/subagent-hooks.js";
|
||||
} from "../../../test/helpers/extensions/subagent-hooks.js";
|
||||
import { registerDiscordSubagentHooks } from "./subagent-hooks.js";
|
||||
|
||||
type ThreadBindingRecord = {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { ClawdbotConfig, PluginRuntime, RuntimeEnv } from "openclaw/plugin-sdk/feishu";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import type { FeishuMessageEvent } from "./bot.js";
|
||||
import {
|
||||
buildBroadcastSessionKey,
|
||||
|
||||
@ -26,104 +26,22 @@ import {
|
||||
sendMessageFeishu as sendMessageFeishuImpl,
|
||||
} from "./send.js";
|
||||
|
||||
type ListFeishuDirectoryGroupsLive = typeof import("./directory.js").listFeishuDirectoryGroupsLive;
|
||||
type ListFeishuDirectoryPeersLive = typeof import("./directory.js").listFeishuDirectoryPeersLive;
|
||||
type FeishuOutbound = typeof import("./outbound.js").feishuOutbound;
|
||||
type CreatePinFeishu = typeof import("./pins.js").createPinFeishu;
|
||||
type ListPinsFeishu = typeof import("./pins.js").listPinsFeishu;
|
||||
type RemovePinFeishu = typeof import("./pins.js").removePinFeishu;
|
||||
type ProbeFeishu = typeof import("./probe.js").probeFeishu;
|
||||
type AddReactionFeishu = typeof import("./reactions.js").addReactionFeishu;
|
||||
type ListReactionsFeishu = typeof import("./reactions.js").listReactionsFeishu;
|
||||
type RemoveReactionFeishu = typeof import("./reactions.js").removeReactionFeishu;
|
||||
type GetChatInfo = typeof import("./chat.js").getChatInfo;
|
||||
type GetChatMembers = typeof import("./chat.js").getChatMembers;
|
||||
type GetFeishuMemberInfo = typeof import("./chat.js").getFeishuMemberInfo;
|
||||
type EditMessageFeishu = typeof import("./send.js").editMessageFeishu;
|
||||
type GetMessageFeishu = typeof import("./send.js").getMessageFeishu;
|
||||
type SendCardFeishu = typeof import("./send.js").sendCardFeishu;
|
||||
type SendMessageFeishu = typeof import("./send.js").sendMessageFeishu;
|
||||
|
||||
export function listFeishuDirectoryGroupsLive(
|
||||
...args: Parameters<ListFeishuDirectoryGroupsLive>
|
||||
): ReturnType<ListFeishuDirectoryGroupsLive> {
|
||||
return listFeishuDirectoryGroupsLiveImpl(...args);
|
||||
}
|
||||
|
||||
export function listFeishuDirectoryPeersLive(
|
||||
...args: Parameters<ListFeishuDirectoryPeersLive>
|
||||
): ReturnType<ListFeishuDirectoryPeersLive> {
|
||||
return listFeishuDirectoryPeersLiveImpl(...args);
|
||||
}
|
||||
|
||||
export const feishuOutbound: FeishuOutbound = { ...feishuOutboundImpl };
|
||||
|
||||
export function createPinFeishu(...args: Parameters<CreatePinFeishu>): ReturnType<CreatePinFeishu> {
|
||||
return createPinFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function listPinsFeishu(...args: Parameters<ListPinsFeishu>): ReturnType<ListPinsFeishu> {
|
||||
return listPinsFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function removePinFeishu(...args: Parameters<RemovePinFeishu>): ReturnType<RemovePinFeishu> {
|
||||
return removePinFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function probeFeishu(...args: Parameters<ProbeFeishu>): ReturnType<ProbeFeishu> {
|
||||
return probeFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function addReactionFeishu(
|
||||
...args: Parameters<AddReactionFeishu>
|
||||
): ReturnType<AddReactionFeishu> {
|
||||
return addReactionFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function listReactionsFeishu(
|
||||
...args: Parameters<ListReactionsFeishu>
|
||||
): ReturnType<ListReactionsFeishu> {
|
||||
return listReactionsFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function removeReactionFeishu(
|
||||
...args: Parameters<RemoveReactionFeishu>
|
||||
): ReturnType<RemoveReactionFeishu> {
|
||||
return removeReactionFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function getChatInfo(...args: Parameters<GetChatInfo>): ReturnType<GetChatInfo> {
|
||||
return getChatInfoImpl(...args);
|
||||
}
|
||||
|
||||
export function getChatMembers(...args: Parameters<GetChatMembers>): ReturnType<GetChatMembers> {
|
||||
return getChatMembersImpl(...args);
|
||||
}
|
||||
|
||||
export function getFeishuMemberInfo(
|
||||
...args: Parameters<GetFeishuMemberInfo>
|
||||
): ReturnType<GetFeishuMemberInfo> {
|
||||
return getFeishuMemberInfoImpl(...args);
|
||||
}
|
||||
|
||||
export function editMessageFeishu(
|
||||
...args: Parameters<EditMessageFeishu>
|
||||
): ReturnType<EditMessageFeishu> {
|
||||
return editMessageFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function getMessageFeishu(
|
||||
...args: Parameters<GetMessageFeishu>
|
||||
): ReturnType<GetMessageFeishu> {
|
||||
return getMessageFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function sendCardFeishu(...args: Parameters<SendCardFeishu>): ReturnType<SendCardFeishu> {
|
||||
return sendCardFeishuImpl(...args);
|
||||
}
|
||||
|
||||
export function sendMessageFeishu(
|
||||
...args: Parameters<SendMessageFeishu>
|
||||
): ReturnType<SendMessageFeishu> {
|
||||
return sendMessageFeishuImpl(...args);
|
||||
}
|
||||
export const feishuChannelRuntime = {
|
||||
listFeishuDirectoryGroupsLive: listFeishuDirectoryGroupsLiveImpl,
|
||||
listFeishuDirectoryPeersLive: listFeishuDirectoryPeersLiveImpl,
|
||||
feishuOutbound: { ...feishuOutboundImpl },
|
||||
createPinFeishu: createPinFeishuImpl,
|
||||
listPinsFeishu: listPinsFeishuImpl,
|
||||
removePinFeishu: removePinFeishuImpl,
|
||||
probeFeishu: probeFeishuImpl,
|
||||
addReactionFeishu: addReactionFeishuImpl,
|
||||
listReactionsFeishu: listReactionsFeishuImpl,
|
||||
removeReactionFeishu: removeReactionFeishuImpl,
|
||||
getChatInfo: getChatInfoImpl,
|
||||
getChatMembers: getChatMembersImpl,
|
||||
getFeishuMemberInfo: getFeishuMemberInfoImpl,
|
||||
editMessageFeishu: editMessageFeishuImpl,
|
||||
getMessageFeishu: getMessageFeishuImpl,
|
||||
sendCardFeishu: sendCardFeishuImpl,
|
||||
sendMessageFeishu: sendMessageFeishuImpl,
|
||||
};
|
||||
|
||||
@ -28,22 +28,28 @@ vi.mock("./client.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("./channel.runtime.js", () => ({
|
||||
addReactionFeishu: addReactionFeishuMock,
|
||||
createPinFeishu: createPinFeishuMock,
|
||||
editMessageFeishu: editMessageFeishuMock,
|
||||
getChatInfo: getChatInfoMock,
|
||||
getChatMembers: getChatMembersMock,
|
||||
getFeishuMemberInfo: getFeishuMemberInfoMock,
|
||||
getMessageFeishu: getMessageFeishuMock,
|
||||
listFeishuDirectoryGroupsLive: listFeishuDirectoryGroupsLiveMock,
|
||||
listFeishuDirectoryPeersLive: listFeishuDirectoryPeersLiveMock,
|
||||
listPinsFeishu: listPinsFeishuMock,
|
||||
listReactionsFeishu: listReactionsFeishuMock,
|
||||
probeFeishu: probeFeishuMock,
|
||||
removePinFeishu: removePinFeishuMock,
|
||||
removeReactionFeishu: removeReactionFeishuMock,
|
||||
sendCardFeishu: sendCardFeishuMock,
|
||||
sendMessageFeishu: sendMessageFeishuMock,
|
||||
feishuChannelRuntime: {
|
||||
addReactionFeishu: addReactionFeishuMock,
|
||||
createPinFeishu: createPinFeishuMock,
|
||||
editMessageFeishu: editMessageFeishuMock,
|
||||
getChatInfo: getChatInfoMock,
|
||||
getChatMembers: getChatMembersMock,
|
||||
getFeishuMemberInfo: getFeishuMemberInfoMock,
|
||||
getMessageFeishu: getMessageFeishuMock,
|
||||
listFeishuDirectoryGroupsLive: listFeishuDirectoryGroupsLiveMock,
|
||||
listFeishuDirectoryPeersLive: listFeishuDirectoryPeersLiveMock,
|
||||
listPinsFeishu: listPinsFeishuMock,
|
||||
listReactionsFeishu: listReactionsFeishuMock,
|
||||
probeFeishu: probeFeishuMock,
|
||||
removePinFeishu: removePinFeishuMock,
|
||||
removeReactionFeishu: removeReactionFeishuMock,
|
||||
sendCardFeishu: sendCardFeishuMock,
|
||||
sendMessageFeishu: sendMessageFeishuMock,
|
||||
feishuOutbound: {
|
||||
sendText: vi.fn(),
|
||||
sendMedia: vi.fn(),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
import { feishuPlugin } from "./channel.js";
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
} from "openclaw/plugin-sdk/feishu";
|
||||
import type { ChannelMessageActionName } from "openclaw/plugin-sdk/feishu";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import {
|
||||
resolveFeishuAccount,
|
||||
resolveFeishuCredentials,
|
||||
@ -41,9 +42,12 @@ const meta: ChannelMeta = {
|
||||
order: 70,
|
||||
};
|
||||
|
||||
async function loadFeishuChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
type FeishuChannelRuntime = typeof import("./channel.runtime.js").feishuChannelRuntime;
|
||||
|
||||
const loadFeishuChannelRuntime = createLazyRuntimeSurface(
|
||||
() => import("./channel.runtime.js"),
|
||||
({ feishuChannelRuntime }) => feishuChannelRuntime,
|
||||
);
|
||||
|
||||
function setFeishuNamedAccountEnabled(
|
||||
cfg: ClawdbotConfig,
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
createInboundDebouncer,
|
||||
resolveInboundDebounceMs,
|
||||
} from "../../../src/auto-reply/inbound-debounce.js";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import { monitorSingleAccount } from "./monitor.account.js";
|
||||
import { setFeishuRuntime } from "./runtime.js";
|
||||
import type { ResolvedFeishuAccount } from "./types.js";
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
createInboundDebouncer,
|
||||
resolveInboundDebounceMs,
|
||||
} from "../../../src/auto-reply/inbound-debounce.js";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import { parseFeishuMessageEvent, type FeishuMessageEvent } from "./bot.js";
|
||||
import * as dedup from "./dedup.js";
|
||||
import { monitorSingleAccount } from "./monitor.account.js";
|
||||
|
||||
@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
getRequiredHookHandler,
|
||||
registerHookHandlersForTest,
|
||||
} from "../../test-utils/subagent-hooks.js";
|
||||
} from "../../../test/helpers/extensions/subagent-hooks.js";
|
||||
import { registerFeishuSubagentHooks } from "./subagent-hooks.js";
|
||||
import {
|
||||
__testing as threadBindingTesting,
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createProviderUsageFetch, makeResponse } from "../test-utils/provider-usage-fetch.js";
|
||||
import {
|
||||
createProviderUsageFetch,
|
||||
makeResponse,
|
||||
} from "../../test/helpers/extensions/provider-usage-fetch.js";
|
||||
import { fetchCopilotUsage } from "./usage.js";
|
||||
|
||||
describe("fetchCopilotUsage", () => {
|
||||
|
||||
@ -8,36 +8,10 @@ import {
|
||||
startGoogleChatMonitor as startGoogleChatMonitorImpl,
|
||||
} from "./monitor.js";
|
||||
|
||||
type ProbeGoogleChat = typeof import("./api.js").probeGoogleChat;
|
||||
type SendGoogleChatMessage = typeof import("./api.js").sendGoogleChatMessage;
|
||||
type UploadGoogleChatAttachment = typeof import("./api.js").uploadGoogleChatAttachment;
|
||||
type ResolveGoogleChatWebhookPath = typeof import("./monitor.js").resolveGoogleChatWebhookPath;
|
||||
type StartGoogleChatMonitor = typeof import("./monitor.js").startGoogleChatMonitor;
|
||||
|
||||
export function probeGoogleChat(...args: Parameters<ProbeGoogleChat>): ReturnType<ProbeGoogleChat> {
|
||||
return probeGoogleChatImpl(...args);
|
||||
}
|
||||
|
||||
export function sendGoogleChatMessage(
|
||||
...args: Parameters<SendGoogleChatMessage>
|
||||
): ReturnType<SendGoogleChatMessage> {
|
||||
return sendGoogleChatMessageImpl(...args);
|
||||
}
|
||||
|
||||
export function uploadGoogleChatAttachment(
|
||||
...args: Parameters<UploadGoogleChatAttachment>
|
||||
): ReturnType<UploadGoogleChatAttachment> {
|
||||
return uploadGoogleChatAttachmentImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveGoogleChatWebhookPath(
|
||||
...args: Parameters<ResolveGoogleChatWebhookPath>
|
||||
): ReturnType<ResolveGoogleChatWebhookPath> {
|
||||
return resolveGoogleChatWebhookPathImpl(...args);
|
||||
}
|
||||
|
||||
export function startGoogleChatMonitor(
|
||||
...args: Parameters<StartGoogleChatMonitor>
|
||||
): ReturnType<StartGoogleChatMonitor> {
|
||||
return startGoogleChatMonitorImpl(...args);
|
||||
}
|
||||
export const googleChatChannelRuntime = {
|
||||
probeGoogleChat: probeGoogleChatImpl,
|
||||
sendGoogleChatMessage: sendGoogleChatMessageImpl,
|
||||
uploadGoogleChatAttachment: uploadGoogleChatAttachmentImpl,
|
||||
resolveGoogleChatWebhookPath: resolveGoogleChatWebhookPathImpl,
|
||||
startGoogleChatMonitor: startGoogleChatMonitorImpl,
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
abortStartedAccount,
|
||||
expectPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
} from "../../../test/helpers/extensions/start-account-lifecycle.js";
|
||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
||||
@ -27,6 +27,7 @@ import {
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/googlechat";
|
||||
import { GoogleChatConfigSchema } from "openclaw/plugin-sdk/googlechat";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import { buildPassiveProbedChannelStatusSummary } from "../../shared/channel-status-summary.js";
|
||||
import {
|
||||
listGoogleChatAccountIds,
|
||||
@ -47,9 +48,12 @@ import {
|
||||
|
||||
const meta = getChatChannelMeta("googlechat");
|
||||
|
||||
async function loadGoogleChatChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
type GoogleChatChannelRuntime = typeof import("./channel.runtime.js").googleChatChannelRuntime;
|
||||
|
||||
const loadGoogleChatChannelRuntime = createLazyRuntimeSurface(
|
||||
() => import("./channel.runtime.js"),
|
||||
({ googleChatChannelRuntime }) => googleChatChannelRuntime,
|
||||
);
|
||||
|
||||
const formatAllowFromEntry = (entry: string) =>
|
||||
entry
|
||||
|
||||
@ -4,7 +4,7 @@ import type { OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/googlech
|
||||
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-utils/mock-http-response.js";
|
||||
import { createMockServerResponse } from "../../../test/helpers/extensions/mock-http-response.js";
|
||||
import type { ResolvedGoogleChatAccount } from "./accounts.js";
|
||||
import { verifyGoogleChatRequest } from "./auth.js";
|
||||
import { handleGoogleChatWebhookRequest, registerGoogleChatWebhookTarget } from "./monitor.js";
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/googlechat";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { buildChannelSetupWizardAdapterFromSetupWizard } from "../../../src/channels/plugins/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createTestWizardPrompter, type WizardPrompter } from "../../test-utils/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import {
|
||||
createTestWizardPrompter,
|
||||
type WizardPrompter,
|
||||
} from "../../../test/helpers/extensions/setup-wizard.js";
|
||||
import { googlechatPlugin } from "./channel.js";
|
||||
|
||||
const googlechatConfigureAdapter = buildChannelSetupWizardAdapterFromSetupWizard({
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
createPatchedAccountSetupAdapter,
|
||||
formatDocsLink,
|
||||
parseSetupEntriesAllowingWildcard,
|
||||
promptParsedAllowFromForScopedChannel,
|
||||
setChannelDmPolicyWithAllowFrom,
|
||||
@ -13,7 +14,6 @@ import type {
|
||||
ChannelSetupWizard,
|
||||
ChannelSetupWizardTextInput,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import {
|
||||
listIMessageAccountIds,
|
||||
resolveDefaultIMessageAccountId,
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { setSetupChannelEnabled, type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { detectBinary } from "../../../src/plugins/setup-binary.js";
|
||||
import {
|
||||
detectBinary,
|
||||
setSetupChannelEnabled,
|
||||
type ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { listIMessageAccountIds, resolveIMessageAccount } from "./accounts.js";
|
||||
import {
|
||||
createIMessageCliPathTextInput,
|
||||
|
||||
@ -3,19 +3,17 @@ import {
|
||||
collectAllowlistProviderRestrictSendersWarnings,
|
||||
} from "openclaw/plugin-sdk/channel-policy";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
deleteAccountFromConfigSection,
|
||||
setAccountEnabledInConfigSection,
|
||||
} from "../../../src/channels/plugins/config-helpers.js";
|
||||
import { buildChannelConfigSchema } from "../../../src/channels/plugins/config-schema.js";
|
||||
import type { ChannelPlugin } from "../../../src/channels/plugins/types.plugin.js";
|
||||
import { getChatChannelMeta } from "../../../src/channels/registry.js";
|
||||
import { IMessageConfigSchema } from "../../../src/config/zod-schema.providers-core.js";
|
||||
import {
|
||||
formatTrimmedAllowFromEntries,
|
||||
getChatChannelMeta,
|
||||
IMessageConfigSchema,
|
||||
resolveIMessageConfigAllowFrom,
|
||||
resolveIMessageConfigDefaultTo,
|
||||
} from "../../../src/plugin-sdk/channel-config-helpers.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "../../../src/routing/session-key.js";
|
||||
setAccountEnabledInConfigSection,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/imessage";
|
||||
import {
|
||||
listIMessageAccountIds,
|
||||
resolveDefaultIMessageAccountId,
|
||||
|
||||
@ -2,7 +2,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
expectStopPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
} from "../../../test/helpers/extensions/start-account-lifecycle.js";
|
||||
import type { ResolvedIrcAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
createSendCfgThreadingRuntime,
|
||||
expectProvidedCfgSkipsRuntimeLoad,
|
||||
expectRuntimeCfgFallback,
|
||||
} from "../../test-utils/send-config.js";
|
||||
} from "../../../test/helpers/extensions/send-config.js";
|
||||
import type { IrcClient } from "./client.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/irc";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { buildChannelSetupWizardAdapterFromSetupWizard } from "../../../src/channels/plugins/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createTestWizardPrompter, type WizardPrompter } from "../../test-utils/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import {
|
||||
createTestWizardPrompter,
|
||||
type WizardPrompter,
|
||||
} from "../../../test/helpers/extensions/setup-wizard.js";
|
||||
import { ircPlugin } from "./channel.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "openclaw/plugin-sdk/line";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import { linePlugin } from "./channel.js";
|
||||
import { setLineRuntime } from "./runtime.js";
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import type {
|
||||
ResolvedLineAccount,
|
||||
} from "openclaw/plugin-sdk/line";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import { linePlugin } from "./channel.js";
|
||||
import { setLineRuntime } from "./runtime.js";
|
||||
|
||||
|
||||
@ -6,8 +6,11 @@ import {
|
||||
resolveDefaultLineAccountId,
|
||||
resolveLineAccount,
|
||||
} from "../../../src/line/accounts.js";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createTestWizardPrompter, type WizardPrompter } from "../../test-utils/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import {
|
||||
createTestWizardPrompter,
|
||||
type WizardPrompter,
|
||||
} from "../../../test/helpers/extensions/setup-wizard.js";
|
||||
import { lineSetupAdapter, lineSetupWizard } from "./setup-surface.js";
|
||||
|
||||
const lineConfigureAdapter = buildChannelSetupWizardAdapterFromSetupWizard({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { PluginRuntime, RuntimeEnv } from "openclaw/plugin-sdk/matrix";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import { matrixPlugin } from "./channel.js";
|
||||
import { setMatrixRuntime } from "./runtime.js";
|
||||
import { createMatrixBotSdkMock } from "./test-mocks.js";
|
||||
|
||||
@ -7,49 +7,12 @@ import { probeMatrix as probeMatrixImpl } from "./matrix/probe.js";
|
||||
import { sendMessageMatrix as sendMessageMatrixImpl } from "./matrix/send.js";
|
||||
import { matrixOutbound as matrixOutboundImpl } from "./outbound.js";
|
||||
import { resolveMatrixTargets as resolveMatrixTargetsImpl } from "./resolve-targets.js";
|
||||
|
||||
type ListMatrixDirectoryGroupsLive =
|
||||
typeof import("./directory-live.js").listMatrixDirectoryGroupsLive;
|
||||
type ListMatrixDirectoryPeersLive =
|
||||
typeof import("./directory-live.js").listMatrixDirectoryPeersLive;
|
||||
type ResolveMatrixAuth = typeof import("./matrix/client.js").resolveMatrixAuth;
|
||||
type ProbeMatrix = typeof import("./matrix/probe.js").probeMatrix;
|
||||
type SendMessageMatrix = typeof import("./matrix/send.js").sendMessageMatrix;
|
||||
type ResolveMatrixTargets = typeof import("./resolve-targets.js").resolveMatrixTargets;
|
||||
type MatrixOutbound = typeof import("./outbound.js").matrixOutbound;
|
||||
|
||||
export function listMatrixDirectoryGroupsLive(
|
||||
...args: Parameters<ListMatrixDirectoryGroupsLive>
|
||||
): ReturnType<ListMatrixDirectoryGroupsLive> {
|
||||
return listMatrixDirectoryGroupsLiveImpl(...args);
|
||||
}
|
||||
|
||||
export function listMatrixDirectoryPeersLive(
|
||||
...args: Parameters<ListMatrixDirectoryPeersLive>
|
||||
): ReturnType<ListMatrixDirectoryPeersLive> {
|
||||
return listMatrixDirectoryPeersLiveImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveMatrixAuth(
|
||||
...args: Parameters<ResolveMatrixAuth>
|
||||
): ReturnType<ResolveMatrixAuth> {
|
||||
return resolveMatrixAuthImpl(...args);
|
||||
}
|
||||
|
||||
export function probeMatrix(...args: Parameters<ProbeMatrix>): ReturnType<ProbeMatrix> {
|
||||
return probeMatrixImpl(...args);
|
||||
}
|
||||
|
||||
export function sendMessageMatrix(
|
||||
...args: Parameters<SendMessageMatrix>
|
||||
): ReturnType<SendMessageMatrix> {
|
||||
return sendMessageMatrixImpl(...args);
|
||||
}
|
||||
|
||||
export function resolveMatrixTargets(
|
||||
...args: Parameters<ResolveMatrixTargets>
|
||||
): ReturnType<ResolveMatrixTargets> {
|
||||
return resolveMatrixTargetsImpl(...args);
|
||||
}
|
||||
|
||||
export const matrixOutbound: MatrixOutbound = { ...matrixOutboundImpl };
|
||||
export const matrixChannelRuntime = {
|
||||
listMatrixDirectoryGroupsLive: listMatrixDirectoryGroupsLiveImpl,
|
||||
listMatrixDirectoryPeersLive: listMatrixDirectoryPeersLiveImpl,
|
||||
resolveMatrixAuth: resolveMatrixAuthImpl,
|
||||
probeMatrix: probeMatrixImpl,
|
||||
sendMessageMatrix: sendMessageMatrixImpl,
|
||||
resolveMatrixTargets: resolveMatrixTargetsImpl,
|
||||
matrixOutbound: { ...matrixOutboundImpl },
|
||||
};
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/matrix";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import { buildTrafficStatusSummary } from "../../shared/channel-status-summary.js";
|
||||
import { matrixMessageActions } from "./actions.js";
|
||||
import { MatrixConfigSchema } from "./config-schema.js";
|
||||
@ -38,9 +39,12 @@ import type { CoreConfig } from "./types.js";
|
||||
// Mutex for serializing account startup (workaround for concurrent dynamic import race condition)
|
||||
let matrixStartupLock: Promise<void> = Promise.resolve();
|
||||
|
||||
async function loadMatrixChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
type MatrixChannelRuntime = typeof import("./channel.runtime.js").matrixChannelRuntime;
|
||||
|
||||
const loadMatrixChannelRuntime = createLazyRuntimeSurface(
|
||||
() => import("./channel.runtime.js"),
|
||||
({ matrixChannelRuntime }) => matrixChannelRuntime,
|
||||
);
|
||||
|
||||
const meta = {
|
||||
id: "matrix",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/mattermost";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createTestPluginApi } from "../test-utils/plugin-api.js";
|
||||
import { createTestPluginApi } from "../../test/helpers/extensions/plugin-api.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
function createApi(
|
||||
|
||||
@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
expectProvidedCfgSkipsRuntimeLoad,
|
||||
expectRuntimeCfgFallback,
|
||||
} from "../../../test-utils/send-config.js";
|
||||
} from "../../../../test/helpers/extensions/send-config.js";
|
||||
import { parseMattermostTarget, sendMessageMattermost } from "./send.js";
|
||||
import { resetMattermostOpaqueTargetCacheForTests } from "./target-resolution.js";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { PluginRuntime, SsrFPolicy } from "openclaw/plugin-sdk/msteams";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import {
|
||||
buildMSTeamsAttachmentPlaceholder,
|
||||
buildMSTeamsGraphMessageUrls,
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import type { OpenClawConfig, RuntimeEnv } from "openclaw/plugin-sdk/msteams";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createDirectoryTestRuntime, expectDirectorySurface } from "../../test-utils/directory.js";
|
||||
import {
|
||||
createDirectoryTestRuntime,
|
||||
expectDirectorySurface,
|
||||
} from "../../../test/helpers/extensions/directory.js";
|
||||
import { msteamsPlugin } from "./channel.js";
|
||||
|
||||
describe("msteams directory", () => {
|
||||
|
||||
@ -8,42 +8,11 @@ import {
|
||||
sendAdaptiveCardMSTeams as sendAdaptiveCardMSTeamsImpl,
|
||||
sendMessageMSTeams as sendMessageMSTeamsImpl,
|
||||
} from "./send.js";
|
||||
|
||||
type ListMSTeamsDirectoryGroupsLive =
|
||||
typeof import("./directory-live.js").listMSTeamsDirectoryGroupsLive;
|
||||
type ListMSTeamsDirectoryPeersLive =
|
||||
typeof import("./directory-live.js").listMSTeamsDirectoryPeersLive;
|
||||
type MSTeamsOutbound = typeof import("./outbound.js").msteamsOutbound;
|
||||
type ProbeMSTeams = typeof import("./probe.js").probeMSTeams;
|
||||
type SendAdaptiveCardMSTeams = typeof import("./send.js").sendAdaptiveCardMSTeams;
|
||||
type SendMessageMSTeams = typeof import("./send.js").sendMessageMSTeams;
|
||||
|
||||
export function listMSTeamsDirectoryGroupsLive(
|
||||
...args: Parameters<ListMSTeamsDirectoryGroupsLive>
|
||||
): ReturnType<ListMSTeamsDirectoryGroupsLive> {
|
||||
return listMSTeamsDirectoryGroupsLiveImpl(...args);
|
||||
}
|
||||
|
||||
export function listMSTeamsDirectoryPeersLive(
|
||||
...args: Parameters<ListMSTeamsDirectoryPeersLive>
|
||||
): ReturnType<ListMSTeamsDirectoryPeersLive> {
|
||||
return listMSTeamsDirectoryPeersLiveImpl(...args);
|
||||
}
|
||||
|
||||
export const msteamsOutbound: MSTeamsOutbound = { ...msteamsOutboundImpl };
|
||||
|
||||
export function probeMSTeams(...args: Parameters<ProbeMSTeams>): ReturnType<ProbeMSTeams> {
|
||||
return probeMSTeamsImpl(...args);
|
||||
}
|
||||
|
||||
export function sendAdaptiveCardMSTeams(
|
||||
...args: Parameters<SendAdaptiveCardMSTeams>
|
||||
): ReturnType<SendAdaptiveCardMSTeams> {
|
||||
return sendAdaptiveCardMSTeamsImpl(...args);
|
||||
}
|
||||
|
||||
export function sendMessageMSTeams(
|
||||
...args: Parameters<SendMessageMSTeams>
|
||||
): ReturnType<SendMessageMSTeams> {
|
||||
return sendMessageMSTeamsImpl(...args);
|
||||
}
|
||||
export const msTeamsChannelRuntime = {
|
||||
listMSTeamsDirectoryGroupsLive: listMSTeamsDirectoryGroupsLiveImpl,
|
||||
listMSTeamsDirectoryPeersLive: listMSTeamsDirectoryPeersLiveImpl,
|
||||
msteamsOutbound: { ...msteamsOutboundImpl },
|
||||
probeMSTeams: probeMSTeamsImpl,
|
||||
sendAdaptiveCardMSTeams: sendAdaptiveCardMSTeamsImpl,
|
||||
sendMessageMSTeams: sendMessageMSTeamsImpl,
|
||||
};
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
MSTeamsConfigSchema,
|
||||
PAIRING_APPROVED_MESSAGE,
|
||||
} from "openclaw/plugin-sdk/msteams";
|
||||
import { createLazyRuntimeSurface } from "../../../src/shared/lazy-runtime.js";
|
||||
import { resolveMSTeamsGroupToolPolicy } from "./policy.js";
|
||||
import type { ProbeMSTeamsResult } from "./probe.js";
|
||||
import {
|
||||
@ -56,9 +57,12 @@ const TEAMS_GRAPH_PERMISSION_HINTS: Record<string, string> = {
|
||||
"Files.Read.All": "files (OneDrive)",
|
||||
};
|
||||
|
||||
async function loadMSTeamsChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
type MSTeamsChannelRuntime = typeof import("./channel.runtime.js").msTeamsChannelRuntime;
|
||||
|
||||
const loadMSTeamsChannelRuntime = createLazyRuntimeSurface(
|
||||
() => import("./channel.runtime.js"),
|
||||
({ msTeamsChannelRuntime }) => msTeamsChannelRuntime,
|
||||
);
|
||||
|
||||
export const msteamsPlugin: ChannelPlugin<ResolvedMSTeamsAccount> = {
|
||||
id: "msteams",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
|
||||
import { uploadToOneDrive, uploadToSharePoint } from "./graph-upload.js";
|
||||
|
||||
describe("graph upload helpers", () => {
|
||||
|
||||
@ -3,7 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { SILENT_REPLY_TOKEN, type PluginRuntime } from "openclaw/plugin-sdk/msteams";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createPluginRuntimeMock } from "../../test-utils/plugin-runtime-mock.js";
|
||||
import { createPluginRuntimeMock } from "../../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import type { StoredConversationReference } from "./conversation-store.js";
|
||||
const graphUploadMockState = vi.hoisted(() => ({
|
||||
uploadAndShareOneDrive: vi.fn(),
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import { createStartAccountContext } from "../../../test/helpers/extensions/start-account-context.js";
|
||||
import {
|
||||
expectStopPendingUntilAbort,
|
||||
startAccountAndTrackLifecycle,
|
||||
} from "../../test-utils/start-account-lifecycle.js";
|
||||
} from "../../../test/helpers/extensions/start-account-lifecycle.js";
|
||||
import type { ResolvedNextcloudTalkAccount } from "./accounts.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
createSendCfgThreadingRuntime,
|
||||
expectProvidedCfgSkipsRuntimeLoad,
|
||||
expectRuntimeCfgFallback,
|
||||
} from "../../test-utils/send-config.js";
|
||||
} from "../../../test/helpers/extensions/send-config.js";
|
||||
|
||||
const hoisted = vi.hoisted(() => ({
|
||||
loadConfig: vi.fn(),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/nostr";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createStartAccountContext } from "../../test-utils/start-account-context.js";
|
||||
import { createStartAccountContext } from "../../../test/helpers/extensions/start-account-context.js";
|
||||
import { nostrPlugin } from "./channel.js";
|
||||
import { setNostrRuntime } from "./runtime.js";
|
||||
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/nostr";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { buildChannelSetupWizardAdapterFromSetupWizard } from "../../../src/channels/plugins/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createTestWizardPrompter, type WizardPrompter } from "../../test-utils/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import {
|
||||
createTestWizardPrompter,
|
||||
type WizardPrompter,
|
||||
} from "../../../test/helpers/extensions/setup-wizard.js";
|
||||
import { nostrPlugin } from "./channel.js";
|
||||
|
||||
const nostrConfigureAdapter = buildChannelSetupWizardAdapterFromSetupWizard({
|
||||
|
||||
@ -7,7 +7,7 @@ import type {
|
||||
PluginCommandContext,
|
||||
} from "openclaw/plugin-sdk/phone-control";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { createTestPluginApi } from "../test-utils/plugin-api.js";
|
||||
import { createTestPluginApi } from "../../test/helpers/extensions/plugin-api.js";
|
||||
import registerPhoneControl from "./index.js";
|
||||
|
||||
function createApi(params: {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { resetSystemEventsForTest } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { resetInboundDedupe } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { beforeEach, vi } from "vitest";
|
||||
import type { SignalDaemonExitEvent, SignalDaemonHandle } from "./daemon.js";
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import {
|
||||
createPatchedAccountSetupAdapter,
|
||||
formatCliCommand,
|
||||
formatDocsLink,
|
||||
normalizeE164,
|
||||
parseSetupEntriesAllowingWildcard,
|
||||
promptParsedAllowFromForScopedChannel,
|
||||
@ -14,8 +16,6 @@ import type {
|
||||
ChannelSetupWizard,
|
||||
ChannelSetupWizardTextInput,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { formatCliCommand } from "../../../src/cli/command-format.js";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import {
|
||||
listSignalAccountIds,
|
||||
resolveDefaultSignalAccountId,
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import { setSetupChannelEnabled, type ChannelSetupWizard } from "openclaw/plugin-sdk/setup";
|
||||
import { detectBinary } from "../../../src/plugins/setup-binary.js";
|
||||
import { installSignalCli } from "../../../src/plugins/signal-cli-install.js";
|
||||
import {
|
||||
detectBinary,
|
||||
installSignalCli,
|
||||
setSetupChannelEnabled,
|
||||
type ChannelSetupWizard,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { listSignalAccountIds, resolveSignalAccount } from "./accounts.js";
|
||||
import {
|
||||
createSignalCliPathTextInput,
|
||||
|
||||
@ -4,15 +4,15 @@ import {
|
||||
collectAllowlistProviderRestrictSendersWarnings,
|
||||
} from "openclaw/plugin-sdk/channel-policy";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
deleteAccountFromConfigSection,
|
||||
getChatChannelMeta,
|
||||
normalizeE164,
|
||||
setAccountEnabledInConfigSection,
|
||||
} from "../../../src/channels/plugins/config-helpers.js";
|
||||
import { buildChannelConfigSchema } from "../../../src/channels/plugins/config-schema.js";
|
||||
import type { ChannelPlugin } from "../../../src/channels/plugins/types.plugin.js";
|
||||
import { getChatChannelMeta } from "../../../src/channels/registry.js";
|
||||
import { SignalConfigSchema } from "../../../src/config/zod-schema.providers-core.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "../../../src/routing/session-key.js";
|
||||
import { normalizeE164 } from "../../../src/utils.js";
|
||||
SignalConfigSchema,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/signal";
|
||||
import {
|
||||
listSignalAccountIds,
|
||||
resolveDefaultSignalAccountId,
|
||||
|
||||
@ -22,11 +22,11 @@ import {
|
||||
resolveConfiguredFromRequiredCredentialStatuses,
|
||||
resolveSlackGroupRequireMention,
|
||||
resolveSlackGroupToolPolicy,
|
||||
createSlackActions,
|
||||
type ChannelPlugin,
|
||||
type OpenClawConfig,
|
||||
type SlackActionContext,
|
||||
} from "openclaw/plugin-sdk/slack";
|
||||
import type { SlackActionContext } from "../../../src/agents/tools/slack-actions.js";
|
||||
import { createSlackActions } from "../../../src/channels/plugins/slack.actions.js";
|
||||
import { buildPassiveProbedChannelStatusSummary } from "../../shared/channel-status-summary.js";
|
||||
import {
|
||||
listEnabledSlackAccounts,
|
||||
|
||||
@ -4,7 +4,10 @@ import * as mediaFetch from "../../../../src/media/fetch.js";
|
||||
import type { SavedMedia } from "../../../../src/media/store.js";
|
||||
import * as mediaStore from "../../../../src/media/store.js";
|
||||
import { mockPinnedHostnameResolution } from "../../../../src/test-helpers/ssrf.js";
|
||||
import { type FetchMock, withFetchPreconnect } from "../../../test-utils/fetch-mock.js";
|
||||
import {
|
||||
type FetchMock,
|
||||
withFetchPreconnect,
|
||||
} from "../../../../test/helpers/extensions/fetch-mock.js";
|
||||
import {
|
||||
fetchWithSlackAuth,
|
||||
resolveSlackAttachmentContent,
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
createAllowlistSetupWizardProxy,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
createEnvPatchedAccountSetupAdapter,
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
type OpenClawConfig,
|
||||
noteChannelLookupFailure,
|
||||
@ -18,7 +19,6 @@ import {
|
||||
type ChannelSetupWizard,
|
||||
type ChannelSetupWizardAllowFromEntry,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import { inspectSlackAccount } from "./account-inspect.js";
|
||||
import { listSlackAccountIds, resolveSlackAccount, type ResolvedSlackAccount } from "./accounts.js";
|
||||
import {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {
|
||||
formatDocsLink,
|
||||
noteChannelLookupFailure,
|
||||
noteChannelLookupSummary,
|
||||
type OpenClawConfig,
|
||||
@ -11,7 +12,6 @@ import type {
|
||||
ChannelSetupWizard,
|
||||
ChannelSetupWizardAllowFromEntry,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import { resolveDefaultSlackAccountId, resolveSlackAccount } from "./accounts.js";
|
||||
import { resolveSlackChannelAllowlist } from "./resolve-channels.js";
|
||||
import { resolveSlackUserAllowlist } from "./resolve-users.js";
|
||||
|
||||
@ -3,14 +3,18 @@ import {
|
||||
createScopedAccountConfigAccessors,
|
||||
createScopedChannelConfigBase,
|
||||
} from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { buildChannelConfigSchema } from "../../../src/channels/plugins/config-schema.js";
|
||||
import { patchChannelConfigForAccount } from "../../../src/channels/plugins/setup-wizard-helpers.js";
|
||||
import type { ChannelPlugin } from "../../../src/channels/plugins/types.plugin.js";
|
||||
import { getChatChannelMeta } from "../../../src/channels/registry.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { hasConfiguredSecretInput } from "../../../src/config/types.secrets.js";
|
||||
import { SlackConfigSchema } from "../../../src/config/zod-schema.providers-core.js";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import {
|
||||
formatDocsLink,
|
||||
hasConfiguredSecretInput,
|
||||
patchChannelConfigForAccount,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
getChatChannelMeta,
|
||||
SlackConfigSchema,
|
||||
type ChannelPlugin,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/slack";
|
||||
import { inspectSlackAccount } from "./account-inspect.js";
|
||||
import {
|
||||
listSlackAccountIds,
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { buildChannelSetupWizardAdapterFromSetupWizard } from "../../../src/channels/plugins/setup-wizard.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createTestWizardPrompter, type WizardPrompter } from "../../test-utils/setup-wizard.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import {
|
||||
createTestWizardPrompter,
|
||||
type WizardPrompter,
|
||||
} from "../../../test/helpers/extensions/setup-wizard.js";
|
||||
import { synologyChatPlugin } from "./channel.js";
|
||||
import { synologyChatSetupWizard } from "./setup-surface.js";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawPluginCommandDefinition } from "../test-utils/plugin-command.js";
|
||||
import { createPluginRuntimeMock } from "../test-utils/plugin-runtime-mock.js";
|
||||
import type { OpenClawPluginCommandDefinition } from "../../test/helpers/extensions/plugin-command.js";
|
||||
import { createPluginRuntimeMock } from "../../test/helpers/extensions/plugin-runtime-mock.js";
|
||||
import register from "./index.js";
|
||||
|
||||
function createHarness(config: Record<string, unknown>) {
|
||||
|
||||
@ -3,7 +3,7 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { withEnv } from "../../test-utils/env.js";
|
||||
import { withEnv } from "../../../test/helpers/extensions/env.js";
|
||||
import { inspectTelegramAccount } from "./account-inspect.js";
|
||||
|
||||
describe("inspectTelegramAccount SecretRef resolution", () => {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import * as subsystemModule from "../../../src/logging/subsystem.js";
|
||||
import { withEnv } from "../../test-utils/env.js";
|
||||
import { withEnv } from "../../../test/helpers/extensions/env.js";
|
||||
import {
|
||||
listTelegramAccountIds,
|
||||
resetMissingDefaultWarnFlag,
|
||||
|
||||
@ -2,7 +2,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { ChannelGroupPolicy } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { TelegramAccountConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { vi } from "vitest";
|
||||
import {
|
||||
createNativeCommandTestParams,
|
||||
|
||||
@ -2,7 +2,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resetInboundDedupe } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { MsgContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { GetReplyOptions, ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { beforeEach, vi } from "vitest";
|
||||
|
||||
type AnyMock = MockFn<(...args: unknown[]) => unknown>;
|
||||
|
||||
@ -3,8 +3,8 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { escapeRegExp, formatEnvelopeTimestamp } from "../../../test/helpers/envelope-timestamp.js";
|
||||
import { withEnvAsync } from "../../test-utils/env.js";
|
||||
import { useFrozenTime, useRealTime } from "../../test-utils/frozen-time.js";
|
||||
import { withEnvAsync } from "../../../test/helpers/extensions/env.js";
|
||||
import { useFrozenTime, useRealTime } from "../../../test/helpers/extensions/frozen-time.js";
|
||||
import {
|
||||
answerCallbackQuerySpy,
|
||||
botCtorSpy,
|
||||
|
||||
@ -5,7 +5,7 @@ import type {
|
||||
PluginRuntime,
|
||||
} from "openclaw/plugin-sdk/telegram";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { createRuntimeEnv } from "../../test-utils/runtime-env.js";
|
||||
import { createRuntimeEnv } from "../../../test/helpers/extensions/runtime-env.js";
|
||||
import type { ResolvedTelegramAccount } from "./accounts.js";
|
||||
import * as auditModule from "./audit.js";
|
||||
import { telegramPlugin } from "./channel.js";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { afterEach, type Mock, describe, expect, it, vi } from "vitest";
|
||||
import { withFetchPreconnect } from "../../test-utils/fetch-mock.js";
|
||||
import { withFetchPreconnect } from "../../../test/helpers/extensions/fetch-mock.js";
|
||||
import { probeTelegram, resetTelegramProbeFetcherCacheForTests } from "./probe.js";
|
||||
|
||||
const resolveTelegramFetch = vi.hoisted(() => vi.fn());
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import type { MockFn } from "openclaw/plugin-sdk/testing";
|
||||
import { beforeEach, vi } from "vitest";
|
||||
|
||||
const { botApi, botCtorSpy } = vi.hoisted(() => ({
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import {
|
||||
createEnvPatchedAccountSetupAdapter,
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatCliCommand,
|
||||
formatDocsLink,
|
||||
patchChannelConfigForAccount,
|
||||
promptResolvedAllowFrom,
|
||||
splitSetupEntries,
|
||||
@ -8,8 +10,6 @@ import {
|
||||
type WizardPrompter,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import type { ChannelSetupAdapter, ChannelSetupDmPolicy } from "openclaw/plugin-sdk/setup";
|
||||
import { formatCliCommand } from "../../../src/cli/command-format.js";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import { resolveDefaultTelegramAccountId, resolveTelegramAccount } from "./accounts.js";
|
||||
import { fetchTelegramChatId } from "./api-fetch.js";
|
||||
|
||||
|
||||
@ -3,12 +3,14 @@ import {
|
||||
createScopedAccountConfigAccessors,
|
||||
createScopedChannelConfigBase,
|
||||
} from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { buildChannelConfigSchema } from "../../../src/channels/plugins/config-schema.js";
|
||||
import type { ChannelPlugin } from "../../../src/channels/plugins/types.plugin.js";
|
||||
import { getChatChannelMeta } from "../../../src/channels/registry.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { TelegramConfigSchema } from "../../../src/config/zod-schema.providers-core.js";
|
||||
import { normalizeAccountId } from "../../../src/routing/session-key.js";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
getChatChannelMeta,
|
||||
normalizeAccountId,
|
||||
TelegramConfigSchema,
|
||||
type ChannelPlugin,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/telegram";
|
||||
import { inspectTelegramAccount } from "./account-inspect.js";
|
||||
import {
|
||||
listTelegramAccountIds,
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export { countLines, hasBalancedFences } from "../../src/test-utils/chunk-test-helpers.js";
|
||||
@ -1 +0,0 @@
|
||||
export { captureEnv, withEnv, withEnvAsync } from "../../src/test-utils/env.js";
|
||||
@ -1 +0,0 @@
|
||||
export { withFetchPreconnect, type FetchMock } from "../../src/test-utils/fetch-mock.js";
|
||||
@ -1 +0,0 @@
|
||||
export { useFrozenTime, useRealTime } from "../../src/test-utils/frozen-time.js";
|
||||
@ -1 +0,0 @@
|
||||
export { createMockServerResponse } from "../../src/test-utils/mock-http-response.js";
|
||||
@ -1 +0,0 @@
|
||||
export { registerSingleProviderPlugin } from "../../src/test-utils/plugin-registration.js";
|
||||
@ -1,4 +0,0 @@
|
||||
export {
|
||||
createProviderUsageFetch,
|
||||
makeResponse,
|
||||
} from "../../src/test-utils/provider-usage-fetch.js";
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user