mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(providers): publish Meta provider (#103070)
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# Meta provider
|
||||
|
||||
Bundled OpenClaw provider plugin for the **Meta API** — an OpenAI-compatible
|
||||
**Responses API** endpoint (`POST /v1/responses`).
|
||||
|
||||
- **Base URL:** `https://api.ai.meta.com/v1`
|
||||
- **Auth:** `Authorization: Bearer $MODEL_API_KEY`
|
||||
- **Model:** `muse-spark-1.1` (reasoning model; use `muse-spark` for smoke tests until 1.1 ships)
|
||||
- Context window: 1,048,576 tokens (input + output share the budget)
|
||||
- Reasoning effort: `minimal | low | medium | high | xhigh` (default: `high`)
|
||||
- Vision: image input in `user` messages
|
||||
- Tool calling + streaming
|
||||
- Stateless encrypted reasoning replay (`store: false`)
|
||||
|
||||
## Usage
|
||||
|
||||
Set the API key and select the model:
|
||||
|
||||
```bash
|
||||
export MODEL_API_KEY=<key>
|
||||
```
|
||||
|
||||
```json5
|
||||
// ~/.openclaw/openclaw.json
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "meta/muse-spark-1.1" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Or run onboarding and choose **Meta**.
|
||||
|
||||
## Thinking / reasoning
|
||||
|
||||
`--thinking <level>` and `/think <level>` map to Responses API `reasoning.effort`.
|
||||
Default thinking level is `high`. `off` maps to `minimal` because Muse Spark does
|
||||
not accept `none`.
|
||||
|
||||
## Docs
|
||||
|
||||
See `docs/providers/meta.md` for setup, onboarding, and smoke tests.
|
||||
|
||||
## Live test
|
||||
|
||||
```bash
|
||||
export MODEL_API_KEY=<key>
|
||||
export OPENCLAW_LIVE_TEST=1
|
||||
export META_LIVE_TEST=1
|
||||
pnpm test extensions/meta/meta.live.test.ts
|
||||
```
|
||||
|
||||
Live tests call `muse-spark` on `/v1/responses`.
|
||||
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Public Meta provider plugin API exports.
|
||||
*/
|
||||
export {
|
||||
buildMetaCatalogModels,
|
||||
buildMetaModelDefinition,
|
||||
META_BASE_URL,
|
||||
META_MODEL_CATALOG,
|
||||
} from "./models.js";
|
||||
export { buildMetaProvider } from "./provider-catalog.js";
|
||||
export { applyMetaConfig, META_DEFAULT_MODEL_REF } from "./onboard.js";
|
||||
@@ -0,0 +1,70 @@
|
||||
// Meta tests cover plugin registration and catalog shape.
|
||||
import { capturePluginRegistration } from "openclaw/plugin-sdk/plugin-test-runtime";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildMetaProvider } from "./api.js";
|
||||
import plugin from "./index.js";
|
||||
|
||||
function requireThinkingProfileResolver(
|
||||
provider: ReturnType<typeof capturePluginRegistration>["providers"][number],
|
||||
) {
|
||||
if (!provider.resolveThinkingProfile) {
|
||||
throw new Error("Expected resolveThinkingProfile on Meta provider");
|
||||
}
|
||||
return provider.resolveThinkingProfile;
|
||||
}
|
||||
|
||||
describe("meta provider", () => {
|
||||
it("registers the Meta provider with api-key auth", () => {
|
||||
const captured = capturePluginRegistration(plugin);
|
||||
const [provider] = captured.providers;
|
||||
if (!provider) {
|
||||
throw new Error("Expected Meta provider");
|
||||
}
|
||||
expect(provider).toMatchObject({
|
||||
id: "meta",
|
||||
label: "Meta",
|
||||
docsPath: "/providers/meta",
|
||||
});
|
||||
expect(provider.auth).toHaveLength(1);
|
||||
expect(provider.auth[0]).toMatchObject({
|
||||
id: "api-key",
|
||||
kind: "api_key",
|
||||
label: "Meta API key",
|
||||
});
|
||||
});
|
||||
|
||||
it("builds the muse-spark-1.1 catalog entry over openai-responses", () => {
|
||||
const providerConfig = buildMetaProvider();
|
||||
expect(providerConfig.baseUrl).toBe("https://api.ai.meta.com/v1");
|
||||
expect(providerConfig.api).toBe("openai-responses");
|
||||
const model = providerConfig.models.find((m) => m.id === "muse-spark-1.1");
|
||||
if (!model) {
|
||||
throw new Error("Expected muse-spark-1.1 model");
|
||||
}
|
||||
expect(model.contextWindow).toBe(1048576);
|
||||
expect(model.reasoning).toBe(true);
|
||||
expect(model.input).toContain("image");
|
||||
});
|
||||
|
||||
it("advertises a high default thinking profile for muse-spark models", () => {
|
||||
const captured = capturePluginRegistration(plugin);
|
||||
const [provider] = captured.providers;
|
||||
if (!provider) {
|
||||
throw new Error("Expected Meta provider");
|
||||
}
|
||||
const resolveThinkingProfile = requireThinkingProfileResolver(provider);
|
||||
const profile = resolveThinkingProfile({
|
||||
provider: "meta",
|
||||
modelId: "muse-spark-1.1",
|
||||
} as never);
|
||||
expect(profile?.defaultLevel).toBe("high");
|
||||
expect(profile?.levels.map((level) => level.id)).toEqual([
|
||||
"off",
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh",
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Meta provider plugin entrypoint.
|
||||
*/
|
||||
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
|
||||
import { OPENAI_COMPATIBLE_REPLAY_HOOKS } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import { applyMetaConfig, META_DEFAULT_MODEL_REF } from "./onboard.js";
|
||||
import { buildMetaProvider } from "./provider-catalog.js";
|
||||
import { wrapMetaProviderStream } from "./stream.js";
|
||||
import { resolveMetaThinkingProfile } from "./thinking.js";
|
||||
|
||||
const PROVIDER_ID = "meta";
|
||||
|
||||
export default defineSingleProviderPluginEntry({
|
||||
id: PROVIDER_ID,
|
||||
name: "Meta Provider",
|
||||
description: "Bundled Meta provider plugin",
|
||||
provider: {
|
||||
label: "Meta",
|
||||
docsPath: "/providers/meta",
|
||||
auth: [
|
||||
{
|
||||
methodId: "api-key",
|
||||
label: "Meta API key",
|
||||
hint: "Meta (Responses API)",
|
||||
optionKey: "metaApiKey",
|
||||
flagName: "--meta-api-key",
|
||||
envVar: "MODEL_API_KEY",
|
||||
promptMessage: "Enter Meta API key",
|
||||
defaultModel: META_DEFAULT_MODEL_REF,
|
||||
applyConfig: (cfg) => applyMetaConfig(cfg),
|
||||
noteMessage: ["Meta provides Responses API inference."].join("\n"),
|
||||
noteTitle: "Meta",
|
||||
wizard: {
|
||||
groupLabel: "Meta",
|
||||
groupHint: "Meta (Responses API)",
|
||||
},
|
||||
},
|
||||
],
|
||||
catalog: {
|
||||
buildProvider: buildMetaProvider,
|
||||
buildStaticProvider: buildMetaProvider,
|
||||
},
|
||||
...OPENAI_COMPATIBLE_REPLAY_HOOKS,
|
||||
wrapStreamFn: wrapMetaProviderStream,
|
||||
resolveThinkingProfile: ({ modelId }) => resolveMetaThinkingProfile(modelId),
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
// Meta live tests prove muse-spark auth and Responses API completion.
|
||||
import { streamSimple, type Model } from "openclaw/plugin-sdk/llm";
|
||||
import { extractNonEmptyAssistantText, isLiveTestEnabled } from "openclaw/plugin-sdk/test-env";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildMetaProvider } from "./provider-catalog.js";
|
||||
import { wrapMetaProviderStream } from "./stream.js";
|
||||
|
||||
const MODEL_API_KEY = process.env.MODEL_API_KEY?.trim() ?? "";
|
||||
const LIVE_MODEL_ID = "muse-spark";
|
||||
const LIVE =
|
||||
isLiveTestEnabled(["META_LIVE_TEST", "MODEL_API_LIVE_TEST"]) &&
|
||||
MODEL_API_KEY.length > 0;
|
||||
const describeLive = LIVE ? describe : describe.skip;
|
||||
|
||||
function resolveLiveModel(): Model<"openai-responses"> {
|
||||
const provider = buildMetaProvider();
|
||||
const catalogModel = provider.models?.find((entry) => entry.id === "muse-spark-1.1");
|
||||
if (!catalogModel) {
|
||||
throw new Error("Meta catalog does not include muse-spark-1.1");
|
||||
}
|
||||
return {
|
||||
provider: "meta",
|
||||
baseUrl: provider.baseUrl,
|
||||
...catalogModel,
|
||||
id: LIVE_MODEL_ID,
|
||||
api: "openai-responses",
|
||||
} as Model<"openai-responses">;
|
||||
}
|
||||
|
||||
function resolveLiveStreamFn() {
|
||||
const model = resolveLiveModel();
|
||||
return (
|
||||
wrapMetaProviderStream({
|
||||
provider: "meta",
|
||||
modelId: model.id,
|
||||
model,
|
||||
streamFn: streamSimple,
|
||||
}) ?? streamSimple
|
||||
);
|
||||
}
|
||||
|
||||
describeLive("meta plugin live", () => {
|
||||
it("lists muse-spark via the /models endpoint", async () => {
|
||||
const response = await fetch("https://api.ai.meta.com/v1/models", {
|
||||
headers: { Authorization: `Bearer ${MODEL_API_KEY}` },
|
||||
});
|
||||
expect(response.ok).toBe(true);
|
||||
const body = (await response.json()) as { data?: Array<{ id: string }> };
|
||||
const ids = (body.data ?? []).map((entry) => entry.id);
|
||||
expect(ids).toContain(LIVE_MODEL_ID);
|
||||
}, 30_000);
|
||||
|
||||
it("completes a muse-spark Responses API turn with high reasoning effort", async () => {
|
||||
const model = resolveLiveModel();
|
||||
let capturedPayload: Record<string, unknown> | undefined;
|
||||
const stream = await resolveLiveStreamFn()(
|
||||
model,
|
||||
{
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: "Reply with exactly: PATCH_OK",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
apiKey: MODEL_API_KEY,
|
||||
maxTokens: 4000, // fix: high reasoning needs ~300 tokens
|
||||
reasoning: "high",
|
||||
onPayload: (payload) => {
|
||||
capturedPayload = payload as Record<string, unknown>;
|
||||
},
|
||||
},
|
||||
);
|
||||
const result = await stream.result();
|
||||
|
||||
if (result.stopReason === "error") {
|
||||
throw new Error(result.errorMessage || "Meta returned an error");
|
||||
}
|
||||
|
||||
expect(capturedPayload?.store).toBe(false);
|
||||
expect(capturedPayload?.include).toEqual(
|
||||
expect.arrayContaining(["reasoning.encrypted_content"]),
|
||||
);
|
||||
const reasoning = capturedPayload?.reasoning as { effort?: string } | undefined;
|
||||
expect(reasoning?.effort).toBe("high");
|
||||
expect(extractNonEmptyAssistantText(result.content)).toMatch(/PATCH_OK/i);
|
||||
}, 120_000);
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Meta model catalog helpers derived from the plugin manifest.
|
||||
*/
|
||||
import { buildManifestModelProviderConfig } from "openclaw/plugin-sdk/provider-catalog-shared";
|
||||
import type { ModelDefinitionConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import manifest from "./openclaw.plugin.json" with { type: "json" };
|
||||
|
||||
const META_MANIFEST_CATALOG = manifest.modelCatalog.providers["meta"];
|
||||
|
||||
/** Base URL for Meta OpenAI-compatible inference. */
|
||||
export const META_BASE_URL = META_MANIFEST_CATALOG.baseUrl;
|
||||
/** Meta model catalog entries from the plugin manifest. */
|
||||
export const META_MODEL_CATALOG = META_MANIFEST_CATALOG.models;
|
||||
|
||||
/** Builds normalized Meta catalog model definitions. */
|
||||
export function buildMetaCatalogModels(): ModelDefinitionConfig[] {
|
||||
return buildManifestModelProviderConfig({
|
||||
providerId: "meta",
|
||||
catalog: META_MANIFEST_CATALOG,
|
||||
}).models;
|
||||
}
|
||||
|
||||
/** Builds one normalized Meta model definition from a manifest entry. */
|
||||
export function buildMetaModelDefinition(
|
||||
model: (typeof META_MODEL_CATALOG)[number],
|
||||
): ModelDefinitionConfig {
|
||||
const providerConfig = buildManifestModelProviderConfig({
|
||||
providerId: "meta",
|
||||
catalog: { ...META_MANIFEST_CATALOG, models: [model] },
|
||||
});
|
||||
return providerConfig.models[0];
|
||||
}
|
||||
Generated
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@openclaw/meta-provider",
|
||||
"version": "2026.6.11",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@openclaw/meta-provider",
|
||||
"version": "2026.6.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Meta onboarding config helpers.
|
||||
*/
|
||||
import {
|
||||
createModelCatalogPresetAppliers,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/provider-onboard";
|
||||
import {
|
||||
buildMetaModelDefinition,
|
||||
META_BASE_URL,
|
||||
META_MODEL_CATALOG,
|
||||
} from "./models.js";
|
||||
|
||||
/** Default Meta model reference used after onboarding. */
|
||||
export const META_DEFAULT_MODEL_REF = "meta/muse-spark-1.1";
|
||||
|
||||
const metaPresetAppliers = createModelCatalogPresetAppliers({
|
||||
primaryModelRef: META_DEFAULT_MODEL_REF,
|
||||
resolveParams: (_cfg: OpenClawConfig) => ({
|
||||
providerId: "meta",
|
||||
api: "openai-responses",
|
||||
baseUrl: META_BASE_URL,
|
||||
catalogModels: META_MODEL_CATALOG.map(buildMetaModelDefinition),
|
||||
aliases: [{ modelRef: META_DEFAULT_MODEL_REF, alias: "Muse Spark 1.1" }],
|
||||
}),
|
||||
});
|
||||
|
||||
/** Applies Meta provider/catalog config and default model aliases. */
|
||||
export function applyMetaConfig(cfg: OpenClawConfig): OpenClawConfig {
|
||||
return metaPresetAppliers.applyConfig(cfg);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"id": "meta",
|
||||
"activation": {
|
||||
"onStartup": false
|
||||
},
|
||||
"enabledByDefault": true,
|
||||
"providers": ["meta"],
|
||||
"providerEndpoints": [
|
||||
{
|
||||
"endpointClass": "meta-native",
|
||||
"hosts": ["api.ai.meta.com"]
|
||||
}
|
||||
],
|
||||
"providerRequest": {
|
||||
"providers": {
|
||||
"meta": {
|
||||
"family": "meta"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modelCatalog": {
|
||||
"providers": {
|
||||
"meta": {
|
||||
"baseUrl": "https://api.ai.meta.com/v1",
|
||||
"api": "openai-responses",
|
||||
"models": [
|
||||
{
|
||||
"id": "muse-spark-1.1",
|
||||
"name": "Muse Spark 1.1",
|
||||
"reasoning": true,
|
||||
"input": ["text", "image"],
|
||||
"contextWindow": 1048576,
|
||||
"maxTokens": 128000,
|
||||
"thinkingLevelMap": {
|
||||
"off": "minimal",
|
||||
"minimal": "minimal",
|
||||
"low": "low",
|
||||
"medium": "medium",
|
||||
"high": "high",
|
||||
"xhigh": "xhigh"
|
||||
},
|
||||
"compat": {
|
||||
"supportsTools": true,
|
||||
"supportsReasoningEffort": true,
|
||||
"supportedReasoningEfforts": [
|
||||
"minimal",
|
||||
"low",
|
||||
"medium",
|
||||
"high",
|
||||
"xhigh"
|
||||
]
|
||||
},
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"discovery": {
|
||||
"meta": "static"
|
||||
}
|
||||
},
|
||||
"setup": {
|
||||
"providers": [
|
||||
{
|
||||
"id": "meta",
|
||||
"authMethods": ["api-key"],
|
||||
"envVars": ["MODEL_API_KEY"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"providerAuthChoices": [
|
||||
{
|
||||
"provider": "meta",
|
||||
"method": "api-key",
|
||||
"choiceId": "meta-api-key",
|
||||
"appGuidedSecret": true,
|
||||
"choiceLabel": "Meta API key",
|
||||
"choiceHint": "Meta (Responses API)",
|
||||
"groupId": "meta",
|
||||
"groupLabel": "Meta",
|
||||
"groupHint": "Meta (Responses API)",
|
||||
"onboardingFeatured": true,
|
||||
"optionKey": "metaApiKey",
|
||||
"cliFlag": "--meta-api-key",
|
||||
"cliOption": "--meta-api-key <key>",
|
||||
"cliDescription": "Meta API key"
|
||||
}
|
||||
],
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@openclaw/meta-provider",
|
||||
"version": "2026.6.11",
|
||||
"description": "OpenClaw Meta provider plugin.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/openclaw/openclaw"
|
||||
},
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@openclaw/plugin-sdk": "workspace:*"
|
||||
},
|
||||
"openclaw": {
|
||||
"extensions": [
|
||||
"./index.ts"
|
||||
],
|
||||
"install": {
|
||||
"clawhubSpec": "clawhub:@openclaw/meta-provider",
|
||||
"npmSpec": "@openclaw/meta-provider",
|
||||
"defaultChoice": "npm",
|
||||
"minHostVersion": ">=2026.6.11"
|
||||
},
|
||||
"compat": {
|
||||
"pluginApi": ">=2026.6.11"
|
||||
},
|
||||
"build": {
|
||||
"openclawVersion": "2026.6.11",
|
||||
"bundledDist": true
|
||||
},
|
||||
"release": {
|
||||
"publishToClawHub": true,
|
||||
"publishToNpm": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Meta model provider builder.
|
||||
*/
|
||||
import type { ModelProviderConfig } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
import { buildMetaCatalogModels, META_BASE_URL } from "./models.js";
|
||||
|
||||
/** Builds the Meta OpenAI-compatible model provider config. */
|
||||
export function buildMetaProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: META_BASE_URL,
|
||||
api: "openai-responses",
|
||||
models: buildMetaCatalogModels(),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Meta plugin module implements stream behavior.
|
||||
import type { StreamFn } from "openclaw/plugin-sdk/agent-core";
|
||||
import { streamSimple } from "openclaw/plugin-sdk/llm";
|
||||
import type { ProviderWrapStreamFnContext } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { streamWithPayloadPatch } from "openclaw/plugin-sdk/provider-stream-shared";
|
||||
|
||||
const META_REASONING_ENCRYPTED_CONTENT_INCLUDE = "reasoning.encrypted_content";
|
||||
|
||||
function ensureMetaResponsesReplayFields(payloadObj: Record<string, unknown>): void {
|
||||
const existing = payloadObj.include;
|
||||
const include = Array.isArray(existing)
|
||||
? existing.filter((entry): entry is string => typeof entry === "string")
|
||||
: [];
|
||||
if (!include.includes(META_REASONING_ENCRYPTED_CONTENT_INCLUDE)) {
|
||||
include.push(META_REASONING_ENCRYPTED_CONTENT_INCLUDE);
|
||||
}
|
||||
payloadObj.include = include;
|
||||
payloadObj.store = false;
|
||||
}
|
||||
|
||||
export function createMetaResponsesWrapper(baseStreamFn: StreamFn | undefined): StreamFn {
|
||||
const underlying = baseStreamFn ?? streamSimple;
|
||||
return (model, context, options) =>
|
||||
streamWithPayloadPatch(underlying, model, context, options, (payloadObj) => {
|
||||
if (model.provider !== "meta" || model.api !== "openai-responses") {
|
||||
return;
|
||||
}
|
||||
if (!model.reasoning) {
|
||||
return;
|
||||
}
|
||||
ensureMetaResponsesReplayFields(payloadObj);
|
||||
});
|
||||
}
|
||||
|
||||
export function wrapMetaProviderStream(
|
||||
ctx: ProviderWrapStreamFnContext,
|
||||
): StreamFn | undefined {
|
||||
if (ctx.provider !== "meta" || ctx.model?.api !== "openai-responses") {
|
||||
return undefined;
|
||||
}
|
||||
return createMetaResponsesWrapper(ctx.streamFn);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Meta plugin module implements thinking behavior.
|
||||
import type { ProviderThinkingProfile } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
const META_REASONING_MODEL_IDS = new Set(["muse-spark", "muse-spark-1.1"]);
|
||||
|
||||
function isMetaReasoningModelId(modelId: string): boolean {
|
||||
return META_REASONING_MODEL_IDS.has(modelId.toLowerCase());
|
||||
}
|
||||
|
||||
const META_THINKING_LEVEL_IDS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const;
|
||||
|
||||
const META_THINKING_PROFILE = {
|
||||
levels: META_THINKING_LEVEL_IDS.map((id) => ({ id })),
|
||||
defaultLevel: "high",
|
||||
} satisfies ProviderThinkingProfile;
|
||||
|
||||
export function resolveMetaThinkingProfile(
|
||||
modelId: string,
|
||||
): ProviderThinkingProfile | undefined {
|
||||
return isMetaReasoningModelId(modelId) ? META_THINKING_PROFILE : undefined;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../tsconfig.package-boundary.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": ["./*.ts", "./src/**/*.ts"],
|
||||
"exclude": [
|
||||
"./**/*.test.ts",
|
||||
"./dist/**",
|
||||
"./node_modules/**",
|
||||
"./src/test-support/**",
|
||||
"./src/**/*test-helpers.ts",
|
||||
"./src/**/*test-harness.ts",
|
||||
"./src/**/*test-support.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user