@juspay/neurolink 11.23.1 → 11.23.3

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.
@@ -12,6 +12,7 @@ import { assertSafeUrl } from "../../utils/ssrfGuard.js";
12
12
  import { createTimeoutController } from "../../utils/timeout.js";
13
13
  import { stripTrailingSlash } from "../openaiChatCompletionsClient.js";
14
14
  import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
15
+ import { isOpenAIQuotaExhaustedError } from "../../utils/providerRetry.js";
15
16
  const OPENAI_DEFAULT_BASE_URL = "https://api.openai.com/v1";
16
17
  /**
17
18
  * Resolve the effective OpenAI base URL from optional credential / env
@@ -113,6 +114,23 @@ export class OpenAIProvider extends OpenAIChatCompletionsProvider {
113
114
  ? ctx.message
114
115
  : "Invalid OpenAI API key. Please check your OPENAI_API_KEY environment variable.",
115
116
  },
117
+ // MUST precede the 429 rule below. OpenAI returns 429 for two
118
+ // unrelated conditions: transient throttling, and a permanently
119
+ // exhausted quota (out of credit, or a spend cap reached). Matching on
120
+ // the status code alone collapses them, and the resulting advice —
121
+ // "try again later" — is the one thing that can never resolve the
122
+ // second. The signal is the error TYPE, not the wording.
123
+ {
124
+ // One definition of "permanent billing state", in the helper. The
125
+ // earlier cut also tested `errorType === "insufficient_quota"` here,
126
+ // which is precisely the helper's own first branch — two places to
127
+ // keep in step for no benefit.
128
+ match: (ctx) => isOpenAIQuotaExhaustedError(ctx.error),
129
+ errorClass: ProviderError,
130
+ message: "OpenAI quota exhausted — this will not resolve by retrying. " +
131
+ "Check your plan and billing details at " +
132
+ "https://platform.openai.com/account/billing",
133
+ },
116
134
  {
117
135
  match: (ctx) => ctx.statusCode === 429 ||
118
136
  errorType === "rate_limit_error" ||
@@ -52,6 +52,24 @@ export declare function duckTypedStatusCode(error: unknown): number | undefined;
52
52
  * hand-rolled OpenAI-compatible client's record). Shared with baseProvider.
53
53
  */
54
54
  export declare function extractRetryAfterMsFromError(error: unknown): number | undefined;
55
+ /**
56
+ * An OpenAI-wire `insufficient_quota` error: the account is out of credit or
57
+ * has hit a spend cap.
58
+ *
59
+ * Exported and shared with the OpenAI error table so the retry predicate and
60
+ * the message a caller sees cannot disagree about what a permanent billing
61
+ * state looks like. The type is NOT a field on the error — OpenAI puts it
62
+ * inside the JSON response body, which the SDK keeps as a string — so any
63
+ * caller that needs it has to parse, and none should do so on its own.
64
+ *
65
+ * Deliberately keyed on the error TYPE, never on the word "quota". OpenAI and
66
+ * xAI send 429 + `type: "insufficient_quota"` for a permanent billing state,
67
+ * but other providers use "quota" for ordinary throttling — Google's 429 reads
68
+ * "Quota exceeded for quota metric ...", which IS retryable and must stay that
69
+ * way. Matching free text here would make Gemini throttling non-retryable and
70
+ * quietly remove a layer of resilience.
71
+ */
72
+ export declare function isOpenAIQuotaExhaustedError(error: unknown): boolean;
55
73
  export declare function isRetryableProviderError(error: unknown): boolean;
56
74
  /**
57
75
  * Extract the HTTP status code from an AI SDK error, if available.
@@ -105,7 +105,53 @@ export function extractRetryAfterMsFromError(error) {
105
105
  }
106
106
  return undefined;
107
107
  }
108
+ /**
109
+ * An OpenAI-wire `insufficient_quota` error: the account is out of credit or
110
+ * has hit a spend cap.
111
+ *
112
+ * Exported and shared with the OpenAI error table so the retry predicate and
113
+ * the message a caller sees cannot disagree about what a permanent billing
114
+ * state looks like. The type is NOT a field on the error — OpenAI puts it
115
+ * inside the JSON response body, which the SDK keeps as a string — so any
116
+ * caller that needs it has to parse, and none should do so on its own.
117
+ *
118
+ * Deliberately keyed on the error TYPE, never on the word "quota". OpenAI and
119
+ * xAI send 429 + `type: "insufficient_quota"` for a permanent billing state,
120
+ * but other providers use "quota" for ordinary throttling — Google's 429 reads
121
+ * "Quota exceeded for quota metric ...", which IS retryable and must stay that
122
+ * way. Matching free text here would make Gemini throttling non-retryable and
123
+ * quietly remove a layer of resilience.
124
+ */
125
+ export function isOpenAIQuotaExhaustedError(error) {
126
+ if (typeof error !== "object" || error === null) {
127
+ return false;
128
+ }
129
+ const err = error;
130
+ if (err.type === "insufficient_quota") {
131
+ return true;
132
+ }
133
+ // The SDK keeps the raw payload as a string; the type lives inside it.
134
+ if (typeof err.responseBody === "string") {
135
+ try {
136
+ const parsed = JSON.parse(err.responseBody);
137
+ const inner = parsed?.error;
138
+ return inner?.type === "insufficient_quota";
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ return false;
145
+ }
108
146
  export function isRetryableProviderError(error) {
147
+ // Before every other branch, including the SDK's own flag: a 429 carrying
148
+ // `insufficient_quota` is marked retryable by the AI SDK because it only
149
+ // looks at the status code. Retrying it burns the full ladder — 3 attempts
150
+ // and ~20s of backoff, since no Retry-After accompanies these — on a state
151
+ // that cannot change until someone tops up the account.
152
+ if (isOpenAIQuotaExhaustedError(error)) {
153
+ return false;
154
+ }
109
155
  // Preferred path: use the AI SDK's own branded type check + isRetryable flag
110
156
  if (APICallError.isInstance(error)) {
111
157
  return error.isRetryable;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "11.23.1",
3
+ "version": "11.23.3",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
6
6
  "author": {
@@ -38,7 +38,7 @@
38
38
  "preview": "vite preview",
39
39
  "prepare": "git rev-parse --git-dir > /dev/null 2>&1 && husky install || echo 'Skipping husky in non-git environment'",
40
40
  "prepack": "svelte-kit sync && svelte-package && pnpm run build:react-hooks && pnpm run build:cli && pnpm run build:browser && publint",
41
- "build:react-hooks": "npx tsc --jsx react-jsx --module nodenext --moduleResolution nodenext --target esnext --esModuleInterop --skipLibCheck --outDir dist --declaration false src/lib/client/reactHooks.tsx",
41
+ "build:react-hooks": "pnpm exec tsc --jsx react-jsx --module nodenext --moduleResolution nodenext --target esnext --esModuleInterop --skipLibCheck --outDir dist --declaration false src/lib/client/reactHooks.tsx",
42
42
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit --strict",
43
43
  "check:ci-scripts": "svelte-kit sync && tsc -p tsconfig.ci-scripts.json",
44
44
  "check:test-parse": "node scripts/parse-check-tests.mjs",
@@ -68,80 +68,80 @@
68
68
  "convert:shell-scripts": "tsx tools/automation/shellConverter.ts",
69
69
  "convert:specific": "tsx tools/automation/shellConverter.ts --specific",
70
70
  "// Testing (Continuous Test Suites)": "",
71
- "test": "npx tsx test/continuous-test-suite.ts",
72
- "test:client": "npx tsx test/continuous-test-suite-client.ts",
73
- "test:context": "npx tsx test/continuous-test-suite-context.ts",
74
- "test:evaluation": "npx tsx test/continuous-test-suite-evaluation.ts",
75
- "test:handler-registry": "npx tsx test/continuous-test-suite-handler-registry.ts",
76
- "test:mcp": "npx tsx test/continuous-test-suite-mcp-infra.ts",
77
- "test:tool-resolution": "npx tsx test/continuous-test-suite-tool-resolution.ts",
78
- "test:mcp:http": "npx tsx test/continuous-test-suite-mcp-http.ts",
79
- "test:mcp:sdk": "npx tsx test/continuous-test-suite-mcp-sdk.ts",
80
- "test:mcp:cli": "npx tsx test/continuous-test-suite-mcp-cli.ts",
71
+ "test": "pnpm exec tsx test/continuous-test-suite.ts",
72
+ "test:client": "pnpm exec tsx test/continuous-test-suite-client.ts",
73
+ "test:context": "pnpm exec tsx test/continuous-test-suite-context.ts",
74
+ "test:evaluation": "pnpm exec tsx test/continuous-test-suite-evaluation.ts",
75
+ "test:handler-registry": "pnpm exec tsx test/continuous-test-suite-handler-registry.ts",
76
+ "test:mcp": "pnpm exec tsx test/continuous-test-suite-mcp-infra.ts",
77
+ "test:tool-resolution": "pnpm exec tsx test/continuous-test-suite-tool-resolution.ts",
78
+ "test:mcp:http": "pnpm exec tsx test/continuous-test-suite-mcp-http.ts",
79
+ "test:mcp:sdk": "pnpm exec tsx test/continuous-test-suite-mcp-sdk.ts",
80
+ "test:mcp:cli": "pnpm exec tsx test/continuous-test-suite-mcp-cli.ts",
81
81
  "test:mcp:full": "pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:mcp:http",
82
- "test:media": "npx tsx test/continuous-test-suite-media-gen.ts",
83
- "test:memory": "npx tsx test/continuous-test-suite-memory.ts",
84
- "test:openai-compat-streaming-retry": "npx tsx test/continuous-test-suite-openai-compat-streaming-retry.ts",
85
- "test:anthropic-streaming-retry": "npx tsx test/continuous-test-suite-anthropic-streaming-retry.ts",
86
- "test:adjust-body-after-400": "npx tsx test/continuous-test-suite-adjust-body-after-400.ts",
87
- "test:error-classification-e2e": "npx tsx test/continuous-test-suite-error-classification-e2e.ts",
88
- "test:error-classifier-contract": "npx tsx test/continuous-test-suite-error-classifier-contract.ts",
89
- "test:bedrock-inference-profile": "npx tsx test/continuous-test-suite-bedrock-inference-profile.ts",
90
- "test:loop-engine": "npx tsx test/continuous-test-suite-loop-engine.ts",
91
- "test:middleware": "npx tsx test/continuous-test-suite-middleware.ts",
92
- "test:observability": "npx tsx test/continuous-test-suite-observability.ts",
93
- "test:ppt": "npx tsx test/continuous-test-suite-ppt.ts",
82
+ "test:media": "pnpm exec tsx test/continuous-test-suite-media-gen.ts",
83
+ "test:memory": "pnpm exec tsx test/continuous-test-suite-memory.ts",
84
+ "test:openai-compat-streaming-retry": "pnpm exec tsx test/continuous-test-suite-openai-compat-streaming-retry.ts",
85
+ "test:anthropic-streaming-retry": "pnpm exec tsx test/continuous-test-suite-anthropic-streaming-retry.ts",
86
+ "test:adjust-body-after-400": "pnpm exec tsx test/continuous-test-suite-adjust-body-after-400.ts",
87
+ "test:error-classification-e2e": "pnpm exec tsx test/continuous-test-suite-error-classification-e2e.ts",
88
+ "test:error-classifier-contract": "pnpm exec tsx test/continuous-test-suite-error-classifier-contract.ts",
89
+ "test:bedrock-inference-profile": "pnpm exec tsx test/continuous-test-suite-bedrock-inference-profile.ts",
90
+ "test:loop-engine": "pnpm exec tsx test/continuous-test-suite-loop-engine.ts",
91
+ "test:middleware": "pnpm exec tsx test/continuous-test-suite-middleware.ts",
92
+ "test:observability": "pnpm exec tsx test/continuous-test-suite-observability.ts",
93
+ "test:ppt": "pnpm exec tsx test/continuous-test-suite-ppt.ts",
94
94
  "test:vertex-loop-characterization": "tsx test/continuous-test-suite-vertex-loop-characterization.ts",
95
- "test:providers": "npx tsx test/continuous-test-suite-providers.ts",
96
- "test:new-providers": "npx tsx test/continuous-test-suite-new-providers.ts",
97
- "test:matrix": "npx tsx test/continuous-test-suite-provider-matrix.ts",
98
- "test:matrix:cli": "npx tsx test/continuous-test-suite-provider-matrix-cli.ts",
99
- "test:mcp:spans": "npx tsx test/continuous-test-suite-mcp-spans.ts",
100
- "test:mcp:infra": "npx tsx test/continuous-test-suite-mcp-infra.ts",
101
- "test:providers-mocked": "npx tsx test/continuous-test-suite-providers-mocked.ts",
102
- "scaffold:provider": "npx tsx tools/scaffold-provider.ts",
103
- "verify:provider-onboarding": "npx tsx tools/verify-provider-onboarding.ts",
104
- "test:openai-compat-catalog": "npx tsx test/continuous-test-suite-openai-compat-catalog.ts",
105
- "test:provider-descriptors": "npx tsx test/continuous-test-suite-provider-descriptors.ts",
106
- "test:provider-structure": "npx tsx test/continuous-test-suite-provider-structure.ts",
107
- "test:model-manifests": "npx tsx test/continuous-test-suite-model-manifests.ts",
108
- "test:provider-fallback": "npx tsx test/continuous-test-suite-provider-fallback.ts",
109
- "test:provider-fallback-latency": "npx tsx test/continuous-test-suite-provider-fallback-latency.ts",
110
- "test:provider-wiring": "npx tsx test/continuous-test-suite-provider-wiring.ts",
111
- "test:rag": "npx tsx test/continuous-test-suite-rag.ts",
112
- "test:skills": "npx tsx test/continuous-test-suite-skills.ts",
113
- "test:servers": "npx tsx test/continuous-test-suite-servers.ts",
114
- "test:tool-reliability": "npx tsx test/continuous-test-suite-tool-reliability.ts",
115
- "test:tts": "npx tsx test/continuous-test-suite-tts.ts",
116
- "test:tts:unit": "npx tsx test/continuous-test-suite-tts-unit.ts",
117
- "test:stt:unit": "npx tsx test/continuous-test-suite-stt-unit.ts",
118
- "test:realtime:unit": "npx tsx test/continuous-test-suite-realtime-unit.ts",
119
- "test:video:unit": "npx tsx test/continuous-test-suite-video-generation-unit.ts",
120
- "test:voice": "npx tsx test/continuous-test-suite-voice.ts",
121
- "test:avatar": "npx tsx test/continuous-test-suite-avatar.ts",
122
- "test:avatar:unit": "npx tsx test/continuous-test-suite-avatar-unit.ts",
123
- "test:music": "npx tsx test/continuous-test-suite-music.ts",
124
- "test:music:unit": "npx tsx test/continuous-test-suite-music-unit.ts",
125
- "test:image-gen": "npx tsx test/continuous-test-suite-image-gen-extras.ts",
126
- "test:credentials": "npx tsx test/continuous-test-suite-credentials.ts",
127
- "test:local-usage": "npx tsx test/continuous-test-suite-local-usage.ts",
128
- "test:dynamic": "npx tsx test/continuous-test-suite-dynamic.ts",
129
- "test:proxy": "npx tsx test/continuous-test-suite-proxy.ts",
130
- "test:codex": "npx tsx test/continuous-test-suite-codex.ts",
131
- "test:bugfixes": "npx tsx test/continuous-test-suite-bugfixes.ts",
132
- "test:json-e2e": "npx tsx test/continuous-test-suite-json-e2e.ts",
133
- "test:workflow": "npx tsx test/continuous-test-suite-workflow.ts",
134
- "test:hitl": "npx tsx test/continuous-test-suite-hitl.ts",
135
- "test:tasks": "npx tsx test/continuous-test-suite-tasks.ts",
136
- "test:auth": "npx tsx test/continuous-test-suite-auth.ts",
137
- "test:autoresearch": "npx tsx test/continuous-test-suite-autoresearch.ts",
138
- "test:tool-routing-cli": "npx tsx test/continuous-test-suite-tool-routing-cli.ts",
139
- "test:tool-dedup": "npx tsx test/continuous-test-suite-tool-dedup.ts",
140
- "test:model-not-found-retryable": "npx tsx test/continuous-test-suite-model-not-found-retryable.ts",
95
+ "test:providers": "pnpm exec tsx test/continuous-test-suite-providers.ts",
96
+ "test:new-providers": "pnpm exec tsx test/continuous-test-suite-new-providers.ts",
97
+ "test:matrix": "pnpm exec tsx test/continuous-test-suite-provider-matrix.ts",
98
+ "test:matrix:cli": "pnpm exec tsx test/continuous-test-suite-provider-matrix-cli.ts",
99
+ "test:mcp:spans": "pnpm exec tsx test/continuous-test-suite-mcp-spans.ts",
100
+ "test:mcp:infra": "pnpm exec tsx test/continuous-test-suite-mcp-infra.ts",
101
+ "test:providers-mocked": "pnpm exec tsx test/continuous-test-suite-providers-mocked.ts",
102
+ "scaffold:provider": "pnpm exec tsx tools/scaffold-provider.ts",
103
+ "verify:provider-onboarding": "pnpm exec tsx tools/verify-provider-onboarding.ts",
104
+ "test:openai-compat-catalog": "pnpm exec tsx test/continuous-test-suite-openai-compat-catalog.ts",
105
+ "test:provider-descriptors": "pnpm exec tsx test/continuous-test-suite-provider-descriptors.ts",
106
+ "test:provider-structure": "pnpm exec tsx test/continuous-test-suite-provider-structure.ts",
107
+ "test:model-manifests": "pnpm exec tsx test/continuous-test-suite-model-manifests.ts",
108
+ "test:provider-fallback": "pnpm exec tsx test/continuous-test-suite-provider-fallback.ts",
109
+ "test:provider-fallback-latency": "pnpm exec tsx test/continuous-test-suite-provider-fallback-latency.ts",
110
+ "test:provider-wiring": "pnpm exec tsx test/continuous-test-suite-provider-wiring.ts",
111
+ "test:rag": "pnpm exec tsx test/continuous-test-suite-rag.ts",
112
+ "test:skills": "pnpm exec tsx test/continuous-test-suite-skills.ts",
113
+ "test:servers": "pnpm exec tsx test/continuous-test-suite-servers.ts",
114
+ "test:tool-reliability": "pnpm exec tsx test/continuous-test-suite-tool-reliability.ts",
115
+ "test:tts": "pnpm exec tsx test/continuous-test-suite-tts.ts",
116
+ "test:tts:unit": "pnpm exec tsx test/continuous-test-suite-tts-unit.ts",
117
+ "test:stt:unit": "pnpm exec tsx test/continuous-test-suite-stt-unit.ts",
118
+ "test:realtime:unit": "pnpm exec tsx test/continuous-test-suite-realtime-unit.ts",
119
+ "test:video:unit": "pnpm exec tsx test/continuous-test-suite-video-generation-unit.ts",
120
+ "test:voice": "pnpm exec tsx test/continuous-test-suite-voice.ts",
121
+ "test:avatar": "pnpm exec tsx test/continuous-test-suite-avatar.ts",
122
+ "test:avatar:unit": "pnpm exec tsx test/continuous-test-suite-avatar-unit.ts",
123
+ "test:music": "pnpm exec tsx test/continuous-test-suite-music.ts",
124
+ "test:music:unit": "pnpm exec tsx test/continuous-test-suite-music-unit.ts",
125
+ "test:image-gen": "pnpm exec tsx test/continuous-test-suite-image-gen-extras.ts",
126
+ "test:credentials": "pnpm exec tsx test/continuous-test-suite-credentials.ts",
127
+ "test:local-usage": "pnpm exec tsx test/continuous-test-suite-local-usage.ts",
128
+ "test:dynamic": "pnpm exec tsx test/continuous-test-suite-dynamic.ts",
129
+ "test:proxy": "pnpm exec tsx test/continuous-test-suite-proxy.ts",
130
+ "test:codex": "pnpm exec tsx test/continuous-test-suite-codex.ts",
131
+ "test:bugfixes": "pnpm exec tsx test/continuous-test-suite-bugfixes.ts",
132
+ "test:json-e2e": "pnpm exec tsx test/continuous-test-suite-json-e2e.ts",
133
+ "test:workflow": "pnpm exec tsx test/continuous-test-suite-workflow.ts",
134
+ "test:hitl": "pnpm exec tsx test/continuous-test-suite-hitl.ts",
135
+ "test:tasks": "pnpm exec tsx test/continuous-test-suite-tasks.ts",
136
+ "test:auth": "pnpm exec tsx test/continuous-test-suite-auth.ts",
137
+ "test:autoresearch": "pnpm exec tsx test/continuous-test-suite-autoresearch.ts",
138
+ "test:tool-routing-cli": "pnpm exec tsx test/continuous-test-suite-tool-routing-cli.ts",
139
+ "test:tool-dedup": "pnpm exec tsx test/continuous-test-suite-tool-dedup.ts",
140
+ "test:model-not-found-retryable": "pnpm exec tsx test/continuous-test-suite-model-not-found-retryable.ts",
141
141
  "test:ci": "pnpm run test && pnpm run test:client && pnpm run test:hitl",
142
142
  "// CI tier — fast, no live AI calls, safe for every commit (test:unit; also see the separate provider-safety-net CI job, which runs build + test:providers-mocked + test:provider-structure + test:error-classifier-contract on every PR)": "",
143
- "test:tool-routing": "npx tsx test/continuous-test-suite-tool-routing.ts",
144
- "test:tool-routing-semantic": "npx tsx test/continuous-test-suite-tool-routing-semantic.ts",
143
+ "test:tool-routing": "pnpm exec tsx test/continuous-test-suite-tool-routing.ts",
144
+ "test:tool-routing-semantic": "pnpm exec tsx test/continuous-test-suite-tool-routing-semantic.ts",
145
145
  "test:unit": "pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:tool-routing-semantic && pnpm run test:mcp-result-cache && pnpm run test:model-not-found-retryable && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:vector-chroma && pnpm run test:vector-pgvector && pnpm run test:vector-pinecone && pnpm run test:provider-wiring && pnpm run test:docs-mcp",
146
146
  "// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit; test:matrix, a different suite covering the full provider capability matrix, runs nightly via .github/workflows/live-matrix.yml — test:providers itself is still only wired into test:live, not any GitHub Actions workflow)": "",
147
147
  "test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic",
@@ -189,7 +189,7 @@
189
189
  "// Release & Publishing": "",
190
190
  "release": "pnpm run build:complete && pnpm run test:ci && changeset publish",
191
191
  "test:semantic-release": "node scripts/test-semantic-release.js",
192
- "release:dry-run": "npx semantic-release --dry-run",
192
+ "release:dry-run": "pnpm exec semantic-release --dry-run",
193
193
  "// Build Rule Enforcement Scripts": "",
194
194
  "validate": "tsx scripts/build-validations.ts",
195
195
  "validate:env": "tsx scripts/env-validation.ts",
@@ -200,21 +200,21 @@
200
200
  "quality:report": "pnpm run quality:metrics && echo 'Quality metrics saved to quality-metrics.json'",
201
201
  "pre-push": "pnpm run check:deps && pnpm run build && pnpm run test:providers-mocked && pnpm run test:provider-structure && pnpm run test:model-manifests",
202
202
  "check:all": "pnpm run lint && pnpm run format --check && pnpm run validate && pnpm run validate:commit",
203
- "test:file-formats": "npx tsx test/continuous-test-suite-file-formats.ts",
203
+ "test:file-formats": "pnpm exec tsx test/continuous-test-suite-file-formats.ts",
204
204
  "test:multimodal": "pnpm run test:file-formats && pnpm run test:multimodal:sdk",
205
- "test:multimodal:sdk": "npx tsx test/continuous-test-suite-multimodal-sdk.ts",
206
- "test:mcp-result-cache": "npx tsx test/continuous-test-suite-mcp-result-cache.ts",
207
- "test:archive:security": "npx tsx test/continuous-test-suite-archive-security.ts",
208
- "test:office:security": "npx tsx test/continuous-test-suite-office-security.ts",
209
- "test:model-pool": "npx tsx test/continuous-test-suite-model-pool.ts",
210
- "test:vector-chroma": "npx tsx test/continuous-test-suite-vector-chroma.ts",
211
- "test:vector-pgvector": "npx tsx test/continuous-test-suite-vector-pgvector.ts",
212
- "test:vector-pinecone": "npx tsx test/continuous-test-suite-vector-pinecone.ts",
205
+ "test:multimodal:sdk": "pnpm exec tsx test/continuous-test-suite-multimodal-sdk.ts",
206
+ "test:mcp-result-cache": "pnpm exec tsx test/continuous-test-suite-mcp-result-cache.ts",
207
+ "test:archive:security": "pnpm exec tsx test/continuous-test-suite-archive-security.ts",
208
+ "test:office:security": "pnpm exec tsx test/continuous-test-suite-office-security.ts",
209
+ "test:model-pool": "pnpm exec tsx test/continuous-test-suite-model-pool.ts",
210
+ "test:vector-chroma": "pnpm exec tsx test/continuous-test-suite-vector-chroma.ts",
211
+ "test:vector-pgvector": "pnpm exec tsx test/continuous-test-suite-vector-pgvector.ts",
212
+ "test:vector-pinecone": "pnpm exec tsx test/continuous-test-suite-vector-pinecone.ts",
213
213
  "test:bedrock-loop-characterization": "tsx test/continuous-test-suite-bedrock-loop-characterization.ts",
214
214
  "test:sagemaker-streaming": "tsx test/continuous-test-suite-sagemaker-streaming.ts",
215
215
  "test:anthropic-loop-characterization": "tsx test/continuous-test-suite-anthropic-loop-characterization.ts",
216
216
  "test:aistudio-loop-characterization": "tsx test/continuous-test-suite-aistudio-loop-characterization.ts",
217
- "test:docs-mcp": "npx tsx test/continuous-test-suite-docs-mcp.ts",
217
+ "test:docs-mcp": "pnpm exec tsx test/continuous-test-suite-docs-mcp.ts",
218
218
  "test:vertex-claude-characterization": "tsx test/continuous-test-suite-vertex-claude-characterization.ts"
219
219
  },
220
220
  "files": [