test add extension plugin sdk boundary guards
This commit is contained in:
parent
a03f43d5bd
commit
5484225b2d
94
.github/workflows/ci.yml
vendored
94
.github/workflows/ci.yml
vendored
@ -398,6 +398,100 @@ jobs:
|
||||
echo "::error::Web search provider boundary grace period ended at ${WEB_SEARCH_PROVIDER_BOUNDARY_ENFORCE_AFTER}. ${fix_instructions}"
|
||||
exit "$status"
|
||||
|
||||
extension-src-outside-plugin-sdk-boundary:
|
||||
name: "extension-src-outside-plugin-sdk-boundary"
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
env:
|
||||
EXTENSION_PLUGIN_SDK_BOUNDARY_ENFORCE_AFTER: "2026-03-24T05:00:00Z"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Run extension src boundary guard with grace period
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
tmp_output="$(mktemp)"
|
||||
if pnpm run lint:extensions:no-src-outside-plugin-sdk >"$tmp_output" 2>&1; then
|
||||
cat "$tmp_output"
|
||||
rm -f "$tmp_output"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
status=$?
|
||||
cat "$tmp_output"
|
||||
rm -f "$tmp_output"
|
||||
|
||||
now_epoch="$(date -u +%s)"
|
||||
enforce_epoch="$(date -u -d "$EXTENSION_PLUGIN_SDK_BOUNDARY_ENFORCE_AFTER" +%s)"
|
||||
fix_instructions="If you are an LLM agent fixing this: run 'pnpm run lint:extensions:no-src-outside-plugin-sdk', move extension imports off core src paths and onto src/plugin-sdk/**, and if the remaining inventory is intentional for now update test/fixtures/extension-src-outside-plugin-sdk-inventory.json in the same PR."
|
||||
|
||||
if [ "$now_epoch" -lt "$enforce_epoch" ]; then
|
||||
echo "::warning::Extension src boundary violations are temporarily allowed until ${EXTENSION_PLUGIN_SDK_BOUNDARY_ENFORCE_AFTER}. This grace period ends in one week from the rollout date. After that timestamp this job will fail unless the inventory is reduced or the baseline is intentionally updated. ${fix_instructions}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::Extension src boundary grace period ended at ${EXTENSION_PLUGIN_SDK_BOUNDARY_ENFORCE_AFTER}. ${fix_instructions}"
|
||||
exit "$status"
|
||||
|
||||
extension-plugin-sdk-internal-boundary:
|
||||
name: "extension-plugin-sdk-internal-boundary"
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
env:
|
||||
EXTENSION_PLUGIN_SDK_INTERNAL_ENFORCE_AFTER: "2026-03-24T05:00:00Z"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Run extension plugin-sdk-internal guard with grace period
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
tmp_output="$(mktemp)"
|
||||
if pnpm run lint:extensions:no-plugin-sdk-internal >"$tmp_output" 2>&1; then
|
||||
cat "$tmp_output"
|
||||
rm -f "$tmp_output"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
status=$?
|
||||
cat "$tmp_output"
|
||||
rm -f "$tmp_output"
|
||||
|
||||
now_epoch="$(date -u +%s)"
|
||||
enforce_epoch="$(date -u -d "$EXTENSION_PLUGIN_SDK_INTERNAL_ENFORCE_AFTER" +%s)"
|
||||
fix_instructions="If you are an LLM agent fixing this: run 'pnpm run lint:extensions:no-plugin-sdk-internal', remove extension imports of src/plugin-sdk-internal/** in favor of src/plugin-sdk/**, and if the remaining inventory is intentional for now update test/fixtures/extension-plugin-sdk-internal-inventory.json in the same PR."
|
||||
|
||||
if [ "$now_epoch" -lt "$enforce_epoch" ]; then
|
||||
echo "::warning::Extension plugin-sdk-internal boundary violations are temporarily allowed until ${EXTENSION_PLUGIN_SDK_INTERNAL_ENFORCE_AFTER}. This grace period ends in one week from the rollout date. After that timestamp this job will fail unless the inventory is reduced or the baseline is intentionally updated. ${fix_instructions}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "::error::Extension plugin-sdk-internal boundary grace period ended at ${EXTENSION_PLUGIN_SDK_INTERNAL_ENFORCE_AFTER}. ${fix_instructions}"
|
||||
exit "$status"
|
||||
|
||||
build-smoke:
|
||||
name: "build-smoke"
|
||||
needs: [docs-scope, changed-scope]
|
||||
|
||||
@ -546,6 +546,8 @@
|
||||
"lint:auth:pairing-account-scope": "node scripts/check-pairing-account-scope.mjs",
|
||||
"lint:docs": "pnpm dlx markdownlint-cli2",
|
||||
"lint:docs:fix": "pnpm dlx markdownlint-cli2 --fix",
|
||||
"lint:extensions:no-plugin-sdk-internal": "node scripts/check-extension-plugin-sdk-boundary.mjs --mode=plugin-sdk-internal",
|
||||
"lint:extensions:no-src-outside-plugin-sdk": "node scripts/check-extension-plugin-sdk-boundary.mjs --mode=src-outside-plugin-sdk",
|
||||
"lint:fix": "oxlint --type-aware --fix && pnpm format",
|
||||
"lint:plugins:no-extension-imports": "node scripts/check-plugin-extension-import-boundary.mjs",
|
||||
"lint:plugins:no-extension-src-imports": "node --import tsx scripts/check-no-extension-src-imports.ts",
|
||||
|
||||
267
scripts/check-extension-plugin-sdk-boundary.mjs
Normal file
267
scripts/check-extension-plugin-sdk-boundary.mjs
Normal file
@ -0,0 +1,267 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { promises as fs } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import ts from "typescript";
|
||||
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const extensionsRoot = path.join(repoRoot, "extensions");
|
||||
|
||||
const MODES = new Set(["src-outside-plugin-sdk", "plugin-sdk-internal"]);
|
||||
|
||||
const baselinePathByMode = {
|
||||
"src-outside-plugin-sdk": path.join(
|
||||
repoRoot,
|
||||
"test",
|
||||
"fixtures",
|
||||
"extension-src-outside-plugin-sdk-inventory.json",
|
||||
),
|
||||
"plugin-sdk-internal": path.join(
|
||||
repoRoot,
|
||||
"test",
|
||||
"fixtures",
|
||||
"extension-plugin-sdk-internal-inventory.json",
|
||||
),
|
||||
};
|
||||
|
||||
const ruleTextByMode = {
|
||||
"src-outside-plugin-sdk":
|
||||
"Rule: production extensions/** must not import src/** outside src/plugin-sdk/**",
|
||||
"plugin-sdk-internal":
|
||||
"Rule: production extensions/** must not import src/plugin-sdk-internal/**",
|
||||
};
|
||||
|
||||
function normalizePath(filePath) {
|
||||
return path.relative(repoRoot, filePath).split(path.sep).join("/");
|
||||
}
|
||||
|
||||
function isCodeFile(fileName) {
|
||||
return /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(fileName);
|
||||
}
|
||||
|
||||
function isTestLikeFile(relativePath) {
|
||||
return (
|
||||
/(^|\/)(__tests__|fixtures)\//.test(relativePath) ||
|
||||
/\.(test|spec)\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(relativePath)
|
||||
);
|
||||
}
|
||||
|
||||
async function collectExtensionSourceFiles(rootDir) {
|
||||
const out = [];
|
||||
async function walk(dir) {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.name === "dist" || entry.name === "node_modules") {
|
||||
continue;
|
||||
}
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await walk(fullPath);
|
||||
continue;
|
||||
}
|
||||
if (!entry.isFile() || !isCodeFile(entry.name)) {
|
||||
continue;
|
||||
}
|
||||
const relativePath = normalizePath(fullPath);
|
||||
if (isTestLikeFile(relativePath)) {
|
||||
continue;
|
||||
}
|
||||
out.push(fullPath);
|
||||
}
|
||||
}
|
||||
await walk(rootDir);
|
||||
return out.toSorted((left, right) => normalizePath(left).localeCompare(normalizePath(right)));
|
||||
}
|
||||
|
||||
function toLine(sourceFile, node) {
|
||||
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
||||
}
|
||||
|
||||
function resolveSpecifier(specifier, importerFile) {
|
||||
if (specifier.startsWith(".")) {
|
||||
return normalizePath(path.resolve(path.dirname(importerFile), specifier));
|
||||
}
|
||||
if (specifier.startsWith("/")) {
|
||||
return normalizePath(specifier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function classifyReason(mode, kind, resolvedPath) {
|
||||
const verb =
|
||||
kind === "export"
|
||||
? "re-exports"
|
||||
: kind === "dynamic-import"
|
||||
? "dynamically imports"
|
||||
: "imports";
|
||||
if (mode === "plugin-sdk-internal") {
|
||||
return `${verb} src/plugin-sdk-internal from an extension`;
|
||||
}
|
||||
if (resolvedPath.startsWith("src/plugin-sdk/")) {
|
||||
return `${verb} allowed plugin-sdk path`;
|
||||
}
|
||||
return `${verb} core src path outside plugin-sdk from an extension`;
|
||||
}
|
||||
|
||||
function compareEntries(left, right) {
|
||||
return (
|
||||
left.file.localeCompare(right.file) ||
|
||||
left.line - right.line ||
|
||||
left.kind.localeCompare(right.kind) ||
|
||||
left.specifier.localeCompare(right.specifier) ||
|
||||
left.resolvedPath.localeCompare(right.resolvedPath) ||
|
||||
left.reason.localeCompare(right.reason)
|
||||
);
|
||||
}
|
||||
|
||||
function shouldReport(mode, resolvedPath) {
|
||||
if (!resolvedPath?.startsWith("src/")) {
|
||||
return false;
|
||||
}
|
||||
if (mode === "plugin-sdk-internal") {
|
||||
return resolvedPath.startsWith("src/plugin-sdk-internal/");
|
||||
}
|
||||
return !resolvedPath.startsWith("src/plugin-sdk/");
|
||||
}
|
||||
|
||||
function collectFromSourceFile(mode, sourceFile, filePath) {
|
||||
const entries = [];
|
||||
|
||||
function push(kind, specifierNode, specifier) {
|
||||
const resolvedPath = resolveSpecifier(specifier, filePath);
|
||||
if (!shouldReport(mode, resolvedPath)) {
|
||||
return;
|
||||
}
|
||||
entries.push({
|
||||
file: normalizePath(filePath),
|
||||
line: toLine(sourceFile, specifierNode),
|
||||
kind,
|
||||
specifier,
|
||||
resolvedPath,
|
||||
reason: classifyReason(mode, kind, resolvedPath),
|
||||
});
|
||||
}
|
||||
|
||||
function visit(node) {
|
||||
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
push("import", node.moduleSpecifier, node.moduleSpecifier.text);
|
||||
} else if (
|
||||
ts.isExportDeclaration(node) &&
|
||||
node.moduleSpecifier &&
|
||||
ts.isStringLiteral(node.moduleSpecifier)
|
||||
) {
|
||||
push("export", node.moduleSpecifier, node.moduleSpecifier.text);
|
||||
} else if (
|
||||
ts.isCallExpression(node) &&
|
||||
node.expression.kind === ts.SyntaxKind.ImportKeyword &&
|
||||
node.arguments.length === 1 &&
|
||||
ts.isStringLiteral(node.arguments[0])
|
||||
) {
|
||||
push("dynamic-import", node.arguments[0], node.arguments[0].text);
|
||||
}
|
||||
ts.forEachChild(node, visit);
|
||||
}
|
||||
|
||||
visit(sourceFile);
|
||||
return entries;
|
||||
}
|
||||
|
||||
export async function collectExtensionPluginSdkBoundaryInventory(mode) {
|
||||
if (!MODES.has(mode)) {
|
||||
throw new Error(`Unknown mode: ${mode}`);
|
||||
}
|
||||
const files = await collectExtensionSourceFiles(extensionsRoot);
|
||||
const inventory = [];
|
||||
for (const filePath of files) {
|
||||
const source = await fs.readFile(filePath, "utf8");
|
||||
const scriptKind =
|
||||
filePath.endsWith(".tsx") || filePath.endsWith(".jsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS;
|
||||
const sourceFile = ts.createSourceFile(
|
||||
filePath,
|
||||
source,
|
||||
ts.ScriptTarget.Latest,
|
||||
true,
|
||||
scriptKind,
|
||||
);
|
||||
inventory.push(...collectFromSourceFile(mode, sourceFile, filePath));
|
||||
}
|
||||
return inventory.toSorted(compareEntries);
|
||||
}
|
||||
|
||||
export async function readExpectedInventory(mode) {
|
||||
return JSON.parse(await fs.readFile(baselinePathByMode[mode], "utf8"));
|
||||
}
|
||||
|
||||
export function diffInventory(expected, actual) {
|
||||
const expectedKeys = new Set(expected.map((entry) => JSON.stringify(entry)));
|
||||
const actualKeys = new Set(actual.map((entry) => JSON.stringify(entry)));
|
||||
return {
|
||||
missing: expected
|
||||
.filter((entry) => !actualKeys.has(JSON.stringify(entry)))
|
||||
.toSorted(compareEntries),
|
||||
unexpected: actual
|
||||
.filter((entry) => !expectedKeys.has(JSON.stringify(entry)))
|
||||
.toSorted(compareEntries),
|
||||
};
|
||||
}
|
||||
|
||||
function formatInventoryHuman(mode, inventory) {
|
||||
const lines = [ruleTextByMode[mode]];
|
||||
if (inventory.length === 0) {
|
||||
lines.push("No extension plugin-sdk boundary violations found.");
|
||||
return lines.join("\n");
|
||||
}
|
||||
lines.push("Extension boundary inventory:");
|
||||
let activeFile = "";
|
||||
for (const entry of inventory) {
|
||||
if (entry.file !== activeFile) {
|
||||
activeFile = entry.file;
|
||||
lines.push(activeFile);
|
||||
}
|
||||
lines.push(` - line ${entry.line} [${entry.kind}] ${entry.reason}`);
|
||||
lines.push(` specifier: ${entry.specifier}`);
|
||||
lines.push(` resolved: ${entry.resolvedPath}`);
|
||||
}
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
export async function main(argv = process.argv.slice(2)) {
|
||||
const json = argv.includes("--json");
|
||||
const modeArg = argv.find((arg) => arg.startsWith("--mode="));
|
||||
const mode = modeArg?.slice("--mode=".length) ?? "src-outside-plugin-sdk";
|
||||
if (!MODES.has(mode)) {
|
||||
throw new Error(`Unknown mode: ${mode}`);
|
||||
}
|
||||
|
||||
const actual = await collectExtensionPluginSdkBoundaryInventory(mode);
|
||||
if (json) {
|
||||
process.stdout.write(`${JSON.stringify(actual, null, 2)}\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
const expected = await readExpectedInventory(mode);
|
||||
const diff = diffInventory(expected, actual);
|
||||
console.log(formatInventoryHuman(mode, actual));
|
||||
if (diff.missing.length === 0 && diff.unexpected.length === 0) {
|
||||
console.log(`Baseline matches (${actual.length} entries).`);
|
||||
return;
|
||||
}
|
||||
if (diff.missing.length > 0) {
|
||||
console.error(`Missing baseline entries (${diff.missing.length}):`);
|
||||
for (const entry of diff.missing) {
|
||||
console.error(` - ${entry.file}:${entry.line} ${entry.reason}`);
|
||||
}
|
||||
}
|
||||
if (diff.unexpected.length > 0) {
|
||||
console.error(`Unexpected inventory entries (${diff.unexpected.length}):`);
|
||||
for (const entry of diff.unexpected) {
|
||||
console.error(` - ${entry.file}:${entry.line} ${entry.reason}`);
|
||||
}
|
||||
}
|
||||
process.exitCode = 1;
|
||||
}
|
||||
|
||||
if (path.resolve(process.argv[1] ?? "") === fileURLToPath(import.meta.url)) {
|
||||
await main();
|
||||
}
|
||||
104
test/extension-plugin-sdk-boundary.test.ts
Normal file
104
test/extension-plugin-sdk-boundary.test.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
collectExtensionPluginSdkBoundaryInventory,
|
||||
diffInventory,
|
||||
} from "../scripts/check-extension-plugin-sdk-boundary.mjs";
|
||||
|
||||
const repoRoot = process.cwd();
|
||||
const scriptPath = path.join(repoRoot, "scripts", "check-extension-plugin-sdk-boundary.mjs");
|
||||
|
||||
function readBaseline(fileName: string) {
|
||||
return JSON.parse(readFileSync(path.join(repoRoot, "test", "fixtures", fileName), "utf8"));
|
||||
}
|
||||
|
||||
describe("extension src outside plugin-sdk boundary inventory", () => {
|
||||
it("produces stable sorted output", async () => {
|
||||
const first = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk");
|
||||
const second = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk");
|
||||
|
||||
expect(second).toEqual(first);
|
||||
expect(
|
||||
[...first].toSorted(
|
||||
(left, right) =>
|
||||
left.file.localeCompare(right.file) ||
|
||||
left.line - right.line ||
|
||||
left.kind.localeCompare(right.kind) ||
|
||||
left.specifier.localeCompare(right.specifier) ||
|
||||
left.resolvedPath.localeCompare(right.resolvedPath) ||
|
||||
left.reason.localeCompare(right.reason),
|
||||
),
|
||||
).toEqual(first);
|
||||
});
|
||||
|
||||
it("captures known current production violations", async () => {
|
||||
const inventory = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk");
|
||||
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
file: "extensions/brave/src/brave-web-search-provider.ts",
|
||||
resolvedPath: "src/agents/tools/common.js",
|
||||
}),
|
||||
);
|
||||
expect(inventory).toContainEqual(
|
||||
expect.objectContaining({
|
||||
file: "extensions/discord/src/runtime-api.ts",
|
||||
resolvedPath: "src/config/types.secrets.js",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("matches the checked-in baseline", async () => {
|
||||
const expected = readBaseline("extension-src-outside-plugin-sdk-inventory.json");
|
||||
const actual = await collectExtensionPluginSdkBoundaryInventory("src-outside-plugin-sdk");
|
||||
|
||||
expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] });
|
||||
});
|
||||
|
||||
it("script json output matches the baseline exactly", () => {
|
||||
const stdout = execFileSync(
|
||||
process.execPath,
|
||||
[scriptPath, "--mode=src-outside-plugin-sdk", "--json"],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
encoding: "utf8",
|
||||
},
|
||||
);
|
||||
|
||||
expect(JSON.parse(stdout)).toEqual(
|
||||
readBaseline("extension-src-outside-plugin-sdk-inventory.json"),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("extension plugin-sdk-internal boundary inventory", () => {
|
||||
it("is currently empty", async () => {
|
||||
const inventory = await collectExtensionPluginSdkBoundaryInventory("plugin-sdk-internal");
|
||||
|
||||
expect(inventory).toEqual([]);
|
||||
});
|
||||
|
||||
it("matches the checked-in empty baseline", async () => {
|
||||
const expected = readBaseline("extension-plugin-sdk-internal-inventory.json");
|
||||
const actual = await collectExtensionPluginSdkBoundaryInventory("plugin-sdk-internal");
|
||||
|
||||
expect(diffInventory(expected, actual)).toEqual({ missing: [], unexpected: [] });
|
||||
});
|
||||
|
||||
it("script json output matches the empty baseline exactly", () => {
|
||||
const stdout = execFileSync(
|
||||
process.execPath,
|
||||
[scriptPath, "--mode=plugin-sdk-internal", "--json"],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
encoding: "utf8",
|
||||
},
|
||||
);
|
||||
|
||||
expect(JSON.parse(stdout)).toEqual(
|
||||
readBaseline("extension-plugin-sdk-internal-inventory.json"),
|
||||
);
|
||||
});
|
||||
});
|
||||
1
test/fixtures/extension-plugin-sdk-internal-inventory.json
vendored
Normal file
1
test/fixtures/extension-plugin-sdk-internal-inventory.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
[]
|
||||
362
test/fixtures/extension-src-outside-plugin-sdk-inventory.json
vendored
Normal file
362
test/fixtures/extension-src-outside-plugin-sdk-inventory.json
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
[
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 2,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/common.js",
|
||||
"resolvedPath": "src/agents/tools/common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 3,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 19,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 23,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 24,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/cli/command-format.js",
|
||||
"resolvedPath": "src/cli/command-format.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 25,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/config/config.js",
|
||||
"resolvedPath": "src/config/config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 29,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/brave/src/brave-web-search-provider.ts",
|
||||
"line": 30,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/security/external-content.js",
|
||||
"resolvedPath": "src/security/external-content.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/discord/src/runtime-api.ts",
|
||||
"line": 38,
|
||||
"kind": "export",
|
||||
"specifier": "../../../src/agents/date-time.js",
|
||||
"resolvedPath": "src/agents/date-time.js",
|
||||
"reason": "re-exports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/discord/src/runtime-api.ts",
|
||||
"line": 39,
|
||||
"kind": "export",
|
||||
"specifier": "../../../src/agents/sandbox-paths.js",
|
||||
"resolvedPath": "src/agents/sandbox-paths.js",
|
||||
"reason": "re-exports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/discord/src/runtime-api.ts",
|
||||
"line": 41,
|
||||
"kind": "export",
|
||||
"specifier": "../../../src/polls.js",
|
||||
"resolvedPath": "src/polls.js",
|
||||
"reason": "re-exports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/discord/src/runtime-api.ts",
|
||||
"line": 42,
|
||||
"kind": "export",
|
||||
"specifier": "../../../src/config/types.js",
|
||||
"resolvedPath": "src/config/types.js",
|
||||
"reason": "re-exports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/discord/src/runtime-api.ts",
|
||||
"line": 47,
|
||||
"kind": "export",
|
||||
"specifier": "../../../src/config/types.secrets.js",
|
||||
"resolvedPath": "src/config/types.secrets.js",
|
||||
"reason": "re-exports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/firecrawl/src/firecrawl-search-provider.ts",
|
||||
"line": 5,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/firecrawl/src/firecrawl-search-provider.ts",
|
||||
"line": 6,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/enable.js",
|
||||
"resolvedPath": "src/plugins/enable.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/firecrawl/src/firecrawl-search-provider.ts",
|
||||
"line": 7,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 2,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/common.js",
|
||||
"resolvedPath": "src/agents/tools/common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 3,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-citation-redirect.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-citation-redirect.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 4,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 17,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 21,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 22,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/config/config.js",
|
||||
"resolvedPath": "src/config/config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 26,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/google/src/gemini-web-search-provider.ts",
|
||||
"line": 27,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/security/external-content.js",
|
||||
"resolvedPath": "src/security/external-content.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 2,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/common.js",
|
||||
"resolvedPath": "src/agents/tools/common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 3,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 16,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 20,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 21,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/config/config.js",
|
||||
"resolvedPath": "src/config/config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 25,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/moonshot/src/kimi-web-search-provider.ts",
|
||||
"line": 26,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/security/external-content.js",
|
||||
"resolvedPath": "src/security/external-content.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 6,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/common.js",
|
||||
"resolvedPath": "src/agents/tools/common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 7,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 25,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 29,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 30,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/config/config.js",
|
||||
"resolvedPath": "src/config/config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 35,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/perplexity/src/perplexity-web-search-provider.ts",
|
||||
"line": 36,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/security/external-content.js",
|
||||
"resolvedPath": "src/security/external-content.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 2,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/common.js",
|
||||
"resolvedPath": "src/agents/tools/common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 3,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 16,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-common.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-common.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 20,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/agents/tools/web-search-provider-config.js",
|
||||
"resolvedPath": "src/agents/tools/web-search-provider-config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 21,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/config/config.js",
|
||||
"resolvedPath": "src/config/config.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 25,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/plugins/types.js",
|
||||
"resolvedPath": "src/plugins/types.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
},
|
||||
{
|
||||
"file": "extensions/xai/src/grok-web-search-provider.ts",
|
||||
"line": 26,
|
||||
"kind": "import",
|
||||
"specifier": "../../../src/security/external-content.js",
|
||||
"resolvedPath": "src/security/external-content.js",
|
||||
"reason": "imports core src path outside plugin-sdk from an extension"
|
||||
}
|
||||
]
|
||||
Loading…
x
Reference in New Issue
Block a user