test(plugins): parse boundary import syntax

This commit is contained in:
Peter Steinberger
2026-04-28 00:34:56 +01:00
parent a412603bad
commit 3f94f25a3c
2 changed files with 42 additions and 9 deletions

View File

@@ -27,7 +27,7 @@ Docs: https://docs.openclaw.ai
- Providers/Codex: pass agent and workspace directories into provider stream wrappers so Codex native `web_search` activation can evaluate the correct auth context, and smoke-test the built status-message runtime by resolving the emitted bundle name. Carries forward #67843; refs #65909. Thanks @neilofneils404.
- Cron/models: keep `payload.model` as a per-job primary that can use configured fallbacks, while still letting `payload.fallbacks: []` make cron runs strict and avoid hidden agent-primary retries. Refs #73023. Thanks @pavelyortho-cyber.
- Models/fallbacks: treat user-selected session models as exact choices, so `/model ollama/...` and model-picker switches fail visibly when the selected provider is unreachable instead of answering from an unrelated configured fallback. Fixes #73023. Thanks @pavelyortho-cyber.
- Codex harness: keep ChatGPT subscription app-server runs from inheriting `CODEX_API_KEY` or `OPENAI_API_KEY`, and fall back to `CODEX_API_KEY` / `OPENAI_API_KEY` app-server login only when no Codex account is available. Fixes #73057. Thanks @holgergruenhagen.
- Codex harness: keep ChatGPT subscription app-server runs from inheriting `CODEX_API_KEY` or `OPENAI_API_KEY`, and fall back to `CODEX_API_KEY` / `OPENAI_API_KEY` app-server login only when no Codex account is available. Fixes #73057. Thanks @holgergruenhagen and @pashpashpash.
- CLI/model probes: fail local `infer model run` probes when the provider returns no text output, so unreachable local providers and empty completions no longer look like successful smoke tests. Refs #73023. Thanks @pavelyortho-cyber.
- CLI/Ollama: run local `infer model run` through the lean provider completion path and skip global model discovery for one-shot local probes, so Ollama smoke tests no longer pay full chat-agent/tool startup cost or hang before the native `/api/chat` request. Fixes #72851. Thanks @TotalRes2020.
- Doctor/gateway services: ignore launchd/systemd companion services that only reference the gateway as a dependency, suppress inactive Linux extra-service warnings, and avoid rewriting a running systemd gateway command/entrypoint during doctor repair. Carries forward #39118. Thanks @therk.

View File

@@ -1,6 +1,7 @@
import { readFileSync, readdirSync } from "node:fs";
import { dirname, relative, resolve, sep } from "node:path";
import { fileURLToPath } from "node:url";
import ts from "typescript";
import { describe, expect, it } from "vitest";
const SRC_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
@@ -165,14 +166,46 @@ function isAllowedBundledExtensionImport(specifier: string): boolean {
}
function collectBundledExtensionImports(source: string): string[] {
const matches = [
...source.matchAll(/from\s+["']([^"']*extensions\/[^"']+)["']/gu),
...source.matchAll(/vi\.(?:mock|doMock)\(\s*["']([^"']*extensions\/[^"']+)["']/gu),
...source.matchAll(/importActual(?:<[^>]*>)?\(\s*["']([^"']*extensions\/[^"']+)["']/gu),
];
return matches
.map((match) => match[1])
.filter((specifier): specifier is string => typeof specifier === "string");
const sourceFile = ts.createSourceFile(
"boundary-invariants-input.ts",
source,
ts.ScriptTarget.Latest,
true,
ts.ScriptKind.TS,
);
const specifiers: string[] = [];
function visit(node: ts.Node): void {
if (
(ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&
node.moduleSpecifier &&
ts.isStringLiteralLike(node.moduleSpecifier)
) {
specifiers.push(node.moduleSpecifier.text);
}
if (ts.isCallExpression(node) && isBundledExtensionImportHelperCall(node.expression)) {
const firstArgument = node.arguments[0];
if (firstArgument && ts.isStringLiteralLike(firstArgument)) {
specifiers.push(firstArgument.text);
}
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
return specifiers.filter((specifier) => specifier.includes("extensions/"));
}
function isBundledExtensionImportHelperCall(expression: ts.Expression): boolean {
if (ts.isPropertyAccessExpression(expression)) {
return (
((expression.name.text === "mock" || expression.name.text === "doMock") &&
ts.isIdentifier(expression.expression) &&
expression.expression.text === "vi") ||
expression.name.text === "importActual"
);
}
return ts.isIdentifier(expression) && expression.text === "importActual";
}
function collectTypedHookNames(source: string): string[] {