@spotpatch/vite 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -12
- package/dist/index.cjs +179 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -5
- package/dist/index.d.ts +16 -5
- package/dist/index.js +179 -33
- package/dist/index.js.map +1 -1
- package/dist/runtime-client.js +8 -8
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import { ContextBudget, SpotPatchLocalePreference, ResolvedAiOptions, AiOptions } from '@spotpatch/shared';
|
|
3
|
-
export { AgentApplyMode, AgentCheckDefinition, AgentLimits, AiExecutionOptions, AiModelProfile, AiOptions, AiProviderProtocol, ContextBudget, DEFAULT_AGENT_LIMITS, OpenAICompatibleProviderOptions } from '@spotpatch/shared';
|
|
2
|
+
import { ContextBudget, SpotPatchLocalePreference, ResolvedAiOptions, AiProviderProtocol, AiProviderAuthentication, AiExecutionOptions, AiOptions } from '@spotpatch/shared';
|
|
3
|
+
export { AgentApplyMode, AgentCheckDefinition, AgentLimits, AiExecutionOptions, AiModelProfile, AiOptions, AiProviderAuthentication, AiProviderProtocol, ContextBudget, DEFAULT_AGENT_LIMITS, OpenAICompatibleProviderOptions } from '@spotpatch/shared';
|
|
4
4
|
|
|
5
5
|
type FilterEntry = string | RegExp;
|
|
6
|
+
interface SimpleAiOptions {
|
|
7
|
+
readonly baseURL: string;
|
|
8
|
+
readonly model: string;
|
|
9
|
+
readonly apiKeyEnv?: string;
|
|
10
|
+
readonly protocol?: AiProviderProtocol;
|
|
11
|
+
readonly authentication?: AiProviderAuthentication;
|
|
12
|
+
readonly providerLabel?: string;
|
|
13
|
+
readonly modelLabel?: string;
|
|
14
|
+
readonly execution?: AiExecutionOptions;
|
|
15
|
+
}
|
|
16
|
+
type SpotPatchAiOptions = false | SimpleAiOptions | AiOptions;
|
|
6
17
|
interface SpotPatchOptions {
|
|
7
18
|
readonly enabled?: boolean;
|
|
8
19
|
readonly include?: readonly FilterEntry[];
|
|
@@ -15,7 +26,7 @@ interface SpotPatchOptions {
|
|
|
15
26
|
readonly debug?: boolean;
|
|
16
27
|
readonly locale?: SpotPatchLocalePreference;
|
|
17
28
|
readonly maxTargets?: number;
|
|
18
|
-
readonly ai?:
|
|
29
|
+
readonly ai?: SpotPatchAiOptions;
|
|
19
30
|
}
|
|
20
31
|
interface ResolvedSpotPatchOptions {
|
|
21
32
|
readonly enabled: boolean;
|
|
@@ -52,8 +63,8 @@ declare const DEFAULT_OPTIONS: Readonly<{
|
|
|
52
63
|
maxTargets: number;
|
|
53
64
|
ai: false;
|
|
54
65
|
}>;
|
|
55
|
-
declare function resolveOptions(options?: SpotPatchOptions): ResolvedSpotPatchOptions;
|
|
66
|
+
declare function resolveOptions(options?: SpotPatchOptions, environmentAi?: false | SimpleAiOptions): ResolvedSpotPatchOptions;
|
|
56
67
|
|
|
57
68
|
declare function spotPatch(userOptions?: SpotPatchOptions): Plugin[];
|
|
58
69
|
|
|
59
|
-
export { DEFAULT_OPTIONS, type ResolvedSpotPatchOptions, type SpotPatchOptions, resolveOptions, spotPatch };
|
|
70
|
+
export { DEFAULT_OPTIONS, type ResolvedSpotPatchOptions, type SimpleAiOptions, type SpotPatchAiOptions, type SpotPatchOptions, resolveOptions, spotPatch };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
|
-
import { ContextBudget, SpotPatchLocalePreference, ResolvedAiOptions, AiOptions } from '@spotpatch/shared';
|
|
3
|
-
export { AgentApplyMode, AgentCheckDefinition, AgentLimits, AiExecutionOptions, AiModelProfile, AiOptions, AiProviderProtocol, ContextBudget, DEFAULT_AGENT_LIMITS, OpenAICompatibleProviderOptions } from '@spotpatch/shared';
|
|
2
|
+
import { ContextBudget, SpotPatchLocalePreference, ResolvedAiOptions, AiProviderProtocol, AiProviderAuthentication, AiExecutionOptions, AiOptions } from '@spotpatch/shared';
|
|
3
|
+
export { AgentApplyMode, AgentCheckDefinition, AgentLimits, AiExecutionOptions, AiModelProfile, AiOptions, AiProviderAuthentication, AiProviderProtocol, ContextBudget, DEFAULT_AGENT_LIMITS, OpenAICompatibleProviderOptions } from '@spotpatch/shared';
|
|
4
4
|
|
|
5
5
|
type FilterEntry = string | RegExp;
|
|
6
|
+
interface SimpleAiOptions {
|
|
7
|
+
readonly baseURL: string;
|
|
8
|
+
readonly model: string;
|
|
9
|
+
readonly apiKeyEnv?: string;
|
|
10
|
+
readonly protocol?: AiProviderProtocol;
|
|
11
|
+
readonly authentication?: AiProviderAuthentication;
|
|
12
|
+
readonly providerLabel?: string;
|
|
13
|
+
readonly modelLabel?: string;
|
|
14
|
+
readonly execution?: AiExecutionOptions;
|
|
15
|
+
}
|
|
16
|
+
type SpotPatchAiOptions = false | SimpleAiOptions | AiOptions;
|
|
6
17
|
interface SpotPatchOptions {
|
|
7
18
|
readonly enabled?: boolean;
|
|
8
19
|
readonly include?: readonly FilterEntry[];
|
|
@@ -15,7 +26,7 @@ interface SpotPatchOptions {
|
|
|
15
26
|
readonly debug?: boolean;
|
|
16
27
|
readonly locale?: SpotPatchLocalePreference;
|
|
17
28
|
readonly maxTargets?: number;
|
|
18
|
-
readonly ai?:
|
|
29
|
+
readonly ai?: SpotPatchAiOptions;
|
|
19
30
|
}
|
|
20
31
|
interface ResolvedSpotPatchOptions {
|
|
21
32
|
readonly enabled: boolean;
|
|
@@ -52,8 +63,8 @@ declare const DEFAULT_OPTIONS: Readonly<{
|
|
|
52
63
|
maxTargets: number;
|
|
53
64
|
ai: false;
|
|
54
65
|
}>;
|
|
55
|
-
declare function resolveOptions(options?: SpotPatchOptions): ResolvedSpotPatchOptions;
|
|
66
|
+
declare function resolveOptions(options?: SpotPatchOptions, environmentAi?: false | SimpleAiOptions): ResolvedSpotPatchOptions;
|
|
56
67
|
|
|
57
68
|
declare function spotPatch(userOptions?: SpotPatchOptions): Plugin[];
|
|
58
69
|
|
|
59
|
-
export { DEFAULT_OPTIONS, type ResolvedSpotPatchOptions, type SpotPatchOptions, resolveOptions, spotPatch };
|
|
70
|
+
export { DEFAULT_OPTIONS, type ResolvedSpotPatchOptions, type SimpleAiOptions, type SpotPatchAiOptions, type SpotPatchOptions, resolveOptions, spotPatch };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
+
// src/plugin.ts
|
|
2
|
+
import path10 from "path";
|
|
3
|
+
import { loadEnv } from "vite";
|
|
4
|
+
|
|
5
|
+
// src/environment-ai.ts
|
|
6
|
+
var AI_ENVIRONMENT_NAMES = Object.freeze({
|
|
7
|
+
authentication: "SPOTPATCH_AI_AUTHENTICATION",
|
|
8
|
+
baseURL: "SPOTPATCH_AI_BASE_URL",
|
|
9
|
+
credential: "SPOTPATCH_AI_API_KEY",
|
|
10
|
+
model: "SPOTPATCH_AI_MODEL",
|
|
11
|
+
protocol: "SPOTPATCH_AI_PROTOCOL"
|
|
12
|
+
});
|
|
13
|
+
function normalizedValue(environment, name) {
|
|
14
|
+
const value = environment[name];
|
|
15
|
+
if (value === void 0 || value.trim().length === 0) {
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
return value.trim();
|
|
19
|
+
}
|
|
20
|
+
function resolveEnvironmentAiConfiguration(environment) {
|
|
21
|
+
const baseURL = normalizedValue(environment, AI_ENVIRONMENT_NAMES.baseURL);
|
|
22
|
+
const model = normalizedValue(environment, AI_ENVIRONMENT_NAMES.model);
|
|
23
|
+
const credential = normalizedValue(environment, AI_ENVIRONMENT_NAMES.credential);
|
|
24
|
+
const protocol = normalizedValue(environment, AI_ENVIRONMENT_NAMES.protocol);
|
|
25
|
+
const authentication = normalizedValue(
|
|
26
|
+
environment,
|
|
27
|
+
AI_ENVIRONMENT_NAMES.authentication
|
|
28
|
+
);
|
|
29
|
+
const configuredValues = [baseURL, model, credential, protocol, authentication];
|
|
30
|
+
if (configuredValues.every((value) => value === void 0)) {
|
|
31
|
+
return Object.freeze({ ai: false });
|
|
32
|
+
}
|
|
33
|
+
const missing = [
|
|
34
|
+
[AI_ENVIRONMENT_NAMES.baseURL, baseURL],
|
|
35
|
+
[AI_ENVIRONMENT_NAMES.model, model],
|
|
36
|
+
[AI_ENVIRONMENT_NAMES.credential, credential]
|
|
37
|
+
].filter((entry) => entry[1] === void 0).map(([name]) => name);
|
|
38
|
+
if (missing.length > 0) {
|
|
39
|
+
throw new RangeError(
|
|
40
|
+
`SpotPatch AI environment configuration is incomplete; missing ${missing.join(", ")}.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (baseURL === void 0 || model === void 0 || credential === void 0) {
|
|
44
|
+
throw new RangeError("SpotPatch AI environment configuration is incomplete.");
|
|
45
|
+
}
|
|
46
|
+
if (protocol !== void 0 && protocol !== "responses" && protocol !== "chat-completions") {
|
|
47
|
+
throw new RangeError(
|
|
48
|
+
"SpotPatch SPOTPATCH_AI_PROTOCOL must be responses or chat-completions."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
if (authentication !== void 0 && authentication !== "bearer" && authentication !== "x-api-key") {
|
|
52
|
+
throw new RangeError(
|
|
53
|
+
"SpotPatch SPOTPATCH_AI_AUTHENTICATION must be bearer or x-api-key."
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return Object.freeze({
|
|
57
|
+
ai: Object.freeze({
|
|
58
|
+
baseURL,
|
|
59
|
+
model,
|
|
60
|
+
...protocol === void 0 ? {} : { protocol },
|
|
61
|
+
...authentication === void 0 ? {} : { authentication }
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
1
66
|
// src/options.ts
|
|
2
67
|
import {
|
|
3
68
|
DEFAULT_AGENT_LIMITS,
|
|
@@ -66,6 +131,7 @@ var aiOptionsSchema = z.strictObject({
|
|
|
66
131
|
type: z.literal("openai-compatible"),
|
|
67
132
|
label: z.string(),
|
|
68
133
|
protocol: z.enum(["responses", "chat-completions"]),
|
|
134
|
+
authentication: z.enum(["bearer", "x-api-key"]).optional(),
|
|
69
135
|
baseURL: z.string(),
|
|
70
136
|
apiKeyEnv: z.string(),
|
|
71
137
|
models: z.record(
|
|
@@ -83,6 +149,16 @@ var aiOptionsSchema = z.strictObject({
|
|
|
83
149
|
limits: agentLimitsSchema
|
|
84
150
|
}).optional()
|
|
85
151
|
});
|
|
152
|
+
var simpleAiOptionsSchema = z.strictObject({
|
|
153
|
+
baseURL: z.string(),
|
|
154
|
+
model: z.string(),
|
|
155
|
+
apiKeyEnv: z.string().optional(),
|
|
156
|
+
protocol: z.enum(["responses", "chat-completions"]).optional(),
|
|
157
|
+
authentication: z.enum(["bearer", "x-api-key"]).optional(),
|
|
158
|
+
providerLabel: z.string().optional(),
|
|
159
|
+
modelLabel: z.string().optional(),
|
|
160
|
+
execution: aiOptionsSchema.shape.execution
|
|
161
|
+
});
|
|
86
162
|
function assertIdentifier(value, label) {
|
|
87
163
|
if (!PROFILE_ID_PATTERN.test(value)) {
|
|
88
164
|
throw new RangeError(
|
|
@@ -182,6 +258,7 @@ function resolveProviders(providers) {
|
|
|
182
258
|
type: provider.type,
|
|
183
259
|
label: nonEmpty(provider.label, "provider label", 100),
|
|
184
260
|
protocol: provider.protocol,
|
|
261
|
+
authentication: provider.authentication ?? "bearer",
|
|
185
262
|
baseURL: normalizeProviderBaseURL(provider.baseURL),
|
|
186
263
|
apiKeyEnv: provider.apiKeyEnv,
|
|
187
264
|
models,
|
|
@@ -225,7 +302,36 @@ function resolveAiOptions(options) {
|
|
|
225
302
|
if (options === void 0 || options === false) {
|
|
226
303
|
return false;
|
|
227
304
|
}
|
|
228
|
-
const
|
|
305
|
+
const expanded = "providers" in options ? options : (() => {
|
|
306
|
+
const simple = simpleAiOptionsSchema.safeParse(options);
|
|
307
|
+
if (!simple.success) {
|
|
308
|
+
throw new RangeError("SpotPatch AI configuration is invalid.");
|
|
309
|
+
}
|
|
310
|
+
const providerId = "default";
|
|
311
|
+
const modelId = "default";
|
|
312
|
+
return {
|
|
313
|
+
providers: {
|
|
314
|
+
[providerId]: {
|
|
315
|
+
type: "openai-compatible",
|
|
316
|
+
label: simple.data.providerLabel ?? "AI provider",
|
|
317
|
+
protocol: simple.data.protocol ?? "chat-completions",
|
|
318
|
+
authentication: simple.data.authentication ?? "bearer",
|
|
319
|
+
baseURL: simple.data.baseURL,
|
|
320
|
+
apiKeyEnv: simple.data.apiKeyEnv ?? "SPOTPATCH_AI_API_KEY",
|
|
321
|
+
models: {
|
|
322
|
+
[modelId]: {
|
|
323
|
+
label: simple.data.modelLabel ?? "AI model",
|
|
324
|
+
model: simple.data.model
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
defaultModel: modelId
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
defaultProvider: providerId,
|
|
331
|
+
...simple.data.execution === void 0 ? {} : { execution: simple.data.execution }
|
|
332
|
+
};
|
|
333
|
+
})();
|
|
334
|
+
const parsed = aiOptionsSchema.safeParse(expanded);
|
|
229
335
|
if (!parsed.success) {
|
|
230
336
|
throw new RangeError("SpotPatch AI configuration is invalid.");
|
|
231
337
|
}
|
|
@@ -285,7 +391,7 @@ function assertPositiveBudget(budget) {
|
|
|
285
391
|
}
|
|
286
392
|
}
|
|
287
393
|
}
|
|
288
|
-
function resolveOptions(options = {}) {
|
|
394
|
+
function resolveOptions(options = {}, environmentAi) {
|
|
289
395
|
const budget = Object.freeze({
|
|
290
396
|
...DEFAULT_OPTIONS.budget,
|
|
291
397
|
...options.budget
|
|
@@ -313,7 +419,7 @@ function resolveOptions(options = {}) {
|
|
|
313
419
|
debug: options.debug ?? DEFAULT_OPTIONS.debug,
|
|
314
420
|
locale,
|
|
315
421
|
maxTargets,
|
|
316
|
-
ai: resolveAiOptions(options.ai)
|
|
422
|
+
ai: resolveAiOptions(options.ai ?? environmentAi)
|
|
317
423
|
};
|
|
318
424
|
if (resolved.shortcut.trim().length === 0) {
|
|
319
425
|
throw new RangeError("SpotPatch shortcut cannot be empty.");
|
|
@@ -370,7 +476,7 @@ import path2 from "path";
|
|
|
370
476
|
// package.json
|
|
371
477
|
var package_default = {
|
|
372
478
|
name: "@spotpatch/vite",
|
|
373
|
-
version: "1.
|
|
479
|
+
version: "1.1.0",
|
|
374
480
|
description: "Vite development plugin for SpotPatch.",
|
|
375
481
|
license: "MIT",
|
|
376
482
|
repository: {
|
|
@@ -462,15 +568,16 @@ function readConsumerViteVersion(root) {
|
|
|
462
568
|
return VITE_VERSION;
|
|
463
569
|
}
|
|
464
570
|
function createClientModule(input, clientBundle, viteVersion) {
|
|
571
|
+
const options = input.context.getOptions();
|
|
465
572
|
const runtimeConfig = {
|
|
466
|
-
ai: createRuntimeAiConfig(
|
|
467
|
-
budget:
|
|
468
|
-
debug:
|
|
469
|
-
locale:
|
|
470
|
-
maxTargets:
|
|
471
|
-
redact:
|
|
573
|
+
ai: createRuntimeAiConfig(options.ai),
|
|
574
|
+
budget: options.budget,
|
|
575
|
+
debug: options.debug,
|
|
576
|
+
locale: options.locale,
|
|
577
|
+
maxTargets: options.maxTargets,
|
|
578
|
+
redact: options.redact,
|
|
472
579
|
sessionToken: input.session.token,
|
|
473
|
-
shortcut:
|
|
580
|
+
shortcut: options.shortcut,
|
|
474
581
|
spotPatchVersion: package_default.version,
|
|
475
582
|
viteVersion
|
|
476
583
|
};
|
|
@@ -602,7 +709,7 @@ function snapshot(job) {
|
|
|
602
709
|
);
|
|
603
710
|
}
|
|
604
711
|
function capabilityCacheKey(provider, model) {
|
|
605
|
-
const configurationDigest = createHash("sha256").update(provider.baseURL).update("\0").update(provider.protocol).digest("hex");
|
|
712
|
+
const configurationDigest = createHash("sha256").update(provider.baseURL).update("\0").update(provider.protocol).update("\0").update(provider.authentication).digest("hex");
|
|
606
713
|
return `${provider.id}:${model.id}:${configurationDigest}`;
|
|
607
714
|
}
|
|
608
715
|
function freezeEvent(event) {
|
|
@@ -1550,18 +1657,18 @@ var EVENT_STREAM_END_STATUSES = /* @__PURE__ */ new Set([
|
|
|
1550
1657
|
"reverted",
|
|
1551
1658
|
"failed"
|
|
1552
1659
|
]);
|
|
1553
|
-
function matchAgentRequestPath(
|
|
1554
|
-
if (
|
|
1660
|
+
function matchAgentRequestPath(path11) {
|
|
1661
|
+
if (path11 === SPOTPATCH_ENDPOINTS.agentCapability) {
|
|
1555
1662
|
return Object.freeze({ kind: "capability" });
|
|
1556
1663
|
}
|
|
1557
|
-
if (
|
|
1664
|
+
if (path11 === SPOTPATCH_ENDPOINTS.agentJobs) {
|
|
1558
1665
|
return Object.freeze({ kind: "create-job" });
|
|
1559
1666
|
}
|
|
1560
1667
|
const prefix = `${SPOTPATCH_ENDPOINTS.agentJobs}/`;
|
|
1561
|
-
if (!
|
|
1668
|
+
if (!path11.startsWith(prefix)) {
|
|
1562
1669
|
return void 0;
|
|
1563
1670
|
}
|
|
1564
|
-
const segments =
|
|
1671
|
+
const segments = path11.slice(prefix.length).split("/");
|
|
1565
1672
|
const jobId = segments[0];
|
|
1566
1673
|
const action = segments[1];
|
|
1567
1674
|
if (segments.length !== 2 || jobId === void 0 || !AGENT_JOB_ID_PATTERN.test(jobId) || action === void 0 || !AGENT_JOB_ACTIONS.has(action)) {
|
|
@@ -1903,9 +2010,9 @@ async function handleOpenEditor(request, options) {
|
|
|
1903
2010
|
}
|
|
1904
2011
|
function createSpotPatchMiddleware(options) {
|
|
1905
2012
|
return (request, response, next) => {
|
|
1906
|
-
const
|
|
1907
|
-
const agentRoute = matchAgentRequestPath(
|
|
1908
|
-
if (
|
|
2013
|
+
const path11 = requestPath(request);
|
|
2014
|
+
const agentRoute = matchAgentRequestPath(path11);
|
|
2015
|
+
if (path11 !== SPOTPATCH_ENDPOINTS2.sourceContext && path11 !== SPOTPATCH_ENDPOINTS2.openEditor && agentRoute === void 0 && !path11.startsWith(`${SPOTPATCH_API_BASE}/`)) {
|
|
1909
2016
|
next();
|
|
1910
2017
|
return;
|
|
1911
2018
|
}
|
|
@@ -1914,7 +2021,7 @@ function createSpotPatchMiddleware(options) {
|
|
|
1914
2021
|
allowLan: options.options.allowLan,
|
|
1915
2022
|
sessionToken: options.session.token
|
|
1916
2023
|
});
|
|
1917
|
-
if (
|
|
2024
|
+
if (path11 === SPOTPATCH_ENDPOINTS2.sourceContext) {
|
|
1918
2025
|
if (request.method !== "POST") {
|
|
1919
2026
|
throw new SpotPatchError8(ERROR_CODES8.INVALID_REQUEST);
|
|
1920
2027
|
}
|
|
@@ -1922,7 +2029,7 @@ function createSpotPatchMiddleware(options) {
|
|
|
1922
2029
|
writeJson(response, 200, { ok: true, data });
|
|
1923
2030
|
return;
|
|
1924
2031
|
}
|
|
1925
|
-
if (
|
|
2032
|
+
if (path11 === SPOTPATCH_ENDPOINTS2.openEditor) {
|
|
1926
2033
|
if (request.method !== "POST") {
|
|
1927
2034
|
throw new SpotPatchError8(ERROR_CODES8.INVALID_REQUEST);
|
|
1928
2035
|
}
|
|
@@ -1970,11 +2077,16 @@ function createServerPlugin(input) {
|
|
|
1970
2077
|
throw new Error("SpotPatch server initialized before Vite config resolution.");
|
|
1971
2078
|
}
|
|
1972
2079
|
const root = path6.resolve(config.root);
|
|
1973
|
-
|
|
2080
|
+
const options = input.context.getOptions();
|
|
2081
|
+
agentManager = options.ai === false ? void 0 : createAgentJobManager({
|
|
2082
|
+
ai: options.ai,
|
|
2083
|
+
environment: input.context.getCredentialEnvironment(),
|
|
2084
|
+
root
|
|
2085
|
+
});
|
|
1974
2086
|
server.middlewares.use(
|
|
1975
2087
|
createSpotPatchMiddleware({
|
|
1976
2088
|
...agentManager === void 0 ? {} : { agentManager },
|
|
1977
|
-
options
|
|
2089
|
+
options,
|
|
1978
2090
|
registry: input.registry,
|
|
1979
2091
|
root,
|
|
1980
2092
|
session: input.session,
|
|
@@ -1985,7 +2097,7 @@ function createServerPlugin(input) {
|
|
|
1985
2097
|
void closeResources();
|
|
1986
2098
|
});
|
|
1987
2099
|
config.logger.info(
|
|
1988
|
-
`[spotpatch:vite] Ready. Toggle picker with ${
|
|
2100
|
+
`[spotpatch:vite] Ready. Toggle picker with ${options.shortcut}.`
|
|
1989
2101
|
);
|
|
1990
2102
|
},
|
|
1991
2103
|
async closeBundle() {
|
|
@@ -2180,7 +2292,7 @@ function getDisplayPath(root, id) {
|
|
|
2180
2292
|
}
|
|
2181
2293
|
function createTransformPlugin(input) {
|
|
2182
2294
|
let root = process.cwd();
|
|
2183
|
-
let filter = createTransformFilter(root, input.
|
|
2295
|
+
let filter = createTransformFilter(root, input.context.getOptions());
|
|
2184
2296
|
let logger;
|
|
2185
2297
|
const warnedFiles = /* @__PURE__ */ new Set();
|
|
2186
2298
|
const cache = /* @__PURE__ */ new Map();
|
|
@@ -2188,9 +2300,12 @@ function createTransformPlugin(input) {
|
|
|
2188
2300
|
name: "spotpatch:transform",
|
|
2189
2301
|
apply: "serve",
|
|
2190
2302
|
enforce: "pre",
|
|
2303
|
+
config(config, environment) {
|
|
2304
|
+
input.configure?.(config, environment);
|
|
2305
|
+
},
|
|
2191
2306
|
configResolved(config) {
|
|
2192
2307
|
root = path9.resolve(config.root);
|
|
2193
|
-
filter = createTransformFilter(root, input.
|
|
2308
|
+
filter = createTransformFilter(root, input.context.getOptions());
|
|
2194
2309
|
logger = config.logger;
|
|
2195
2310
|
},
|
|
2196
2311
|
transform(code, id) {
|
|
@@ -2203,6 +2318,7 @@ function createTransformPlugin(input) {
|
|
|
2203
2318
|
return cache.get(cacheKey) ?? null;
|
|
2204
2319
|
}
|
|
2205
2320
|
const startedAt = performance.now();
|
|
2321
|
+
const options = input.context.getOptions();
|
|
2206
2322
|
try {
|
|
2207
2323
|
const result = injectSourceMarkers({
|
|
2208
2324
|
code,
|
|
@@ -2220,7 +2336,7 @@ function createTransformPlugin(input) {
|
|
|
2220
2336
|
map: result.map.toString()
|
|
2221
2337
|
});
|
|
2222
2338
|
cache.set(cacheKey, output);
|
|
2223
|
-
if (
|
|
2339
|
+
if (options.debug) {
|
|
2224
2340
|
const elapsed = performance.now() - startedAt;
|
|
2225
2341
|
logger?.info(
|
|
2226
2342
|
`[spotpatch:transform] ${getDisplayPath(root, id)} ${elapsed.toFixed(2)}ms`
|
|
@@ -2230,7 +2346,7 @@ function createTransformPlugin(input) {
|
|
|
2230
2346
|
} catch (error) {
|
|
2231
2347
|
if (!warnedFiles.has(cleanId)) {
|
|
2232
2348
|
warnedFiles.add(cleanId);
|
|
2233
|
-
const detail =
|
|
2349
|
+
const detail = options.debug && error instanceof Error ? `: ${error.message}` : "";
|
|
2234
2350
|
logger?.warn(
|
|
2235
2351
|
`[spotpatch:transform] Failed to transform ${getDisplayPath(root, id)}; using original module${detail}`
|
|
2236
2352
|
);
|
|
@@ -2243,16 +2359,46 @@ function createTransformPlugin(input) {
|
|
|
2243
2359
|
|
|
2244
2360
|
// src/plugin.ts
|
|
2245
2361
|
function spotPatch(userOptions = {}) {
|
|
2246
|
-
|
|
2362
|
+
let options = resolveOptions(userOptions);
|
|
2363
|
+
let credentialEnvironment = Object.freeze({});
|
|
2247
2364
|
if (!options.enabled) {
|
|
2248
2365
|
return [];
|
|
2249
2366
|
}
|
|
2250
2367
|
const registry = createSourceRegistry();
|
|
2251
2368
|
const session = createSession();
|
|
2369
|
+
const context = Object.freeze({
|
|
2370
|
+
getCredentialEnvironment: () => credentialEnvironment,
|
|
2371
|
+
getOptions: () => options
|
|
2372
|
+
});
|
|
2373
|
+
const configure = (config, environment) => {
|
|
2374
|
+
const root = path10.resolve(process.cwd(), config.root ?? ".");
|
|
2375
|
+
const loadedEnvironment = config.envDir === false ? process.env : loadEnv(environment.mode, path10.resolve(root, config.envDir ?? "."), "");
|
|
2376
|
+
const environmentAi = userOptions.ai === void 0 ? resolveEnvironmentAiConfiguration(loadedEnvironment).ai : false;
|
|
2377
|
+
options = resolveOptions(userOptions, environmentAi);
|
|
2378
|
+
if (options.ai === false) {
|
|
2379
|
+
credentialEnvironment = Object.freeze({});
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
const names = new Set(
|
|
2383
|
+
Object.values(options.ai.providers).map((provider) => provider.apiKeyEnv)
|
|
2384
|
+
);
|
|
2385
|
+
const missing = [...names].filter((name) => {
|
|
2386
|
+
const value = loadedEnvironment[name];
|
|
2387
|
+
return value === void 0 || value.trim().length === 0;
|
|
2388
|
+
});
|
|
2389
|
+
if (missing.length > 0) {
|
|
2390
|
+
throw new RangeError(
|
|
2391
|
+
`SpotPatch AI credential environment is missing ${missing.join(", ")}.`
|
|
2392
|
+
);
|
|
2393
|
+
}
|
|
2394
|
+
credentialEnvironment = Object.freeze(
|
|
2395
|
+
Object.fromEntries([...names].map((name) => [name, loadedEnvironment[name]]))
|
|
2396
|
+
);
|
|
2397
|
+
};
|
|
2252
2398
|
return [
|
|
2253
|
-
createTransformPlugin({
|
|
2254
|
-
createRuntimeInjectionPlugin({
|
|
2255
|
-
createServerPlugin({
|
|
2399
|
+
createTransformPlugin({ configure, context, registry }),
|
|
2400
|
+
createRuntimeInjectionPlugin({ context, session }),
|
|
2401
|
+
createServerPlugin({ context, registry, session })
|
|
2256
2402
|
];
|
|
2257
2403
|
}
|
|
2258
2404
|
|