ai-model-verifier 1.0.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.
Files changed (95) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +40 -0
  3. package/dist/detectors/response-metadata.d.ts +36 -0
  4. package/dist/detectors/response-metadata.d.ts.map +1 -0
  5. package/dist/detectors/response-metadata.js +91 -0
  6. package/dist/detectors/response-metadata.js.map +1 -0
  7. package/dist/detectors/thinking-signature.d.ts +70 -0
  8. package/dist/detectors/thinking-signature.d.ts.map +1 -0
  9. package/dist/detectors/thinking-signature.js +177 -0
  10. package/dist/detectors/thinking-signature.js.map +1 -0
  11. package/dist/detectors/throughput.d.ts +51 -0
  12. package/dist/detectors/throughput.d.ts.map +1 -0
  13. package/dist/detectors/throughput.js +83 -0
  14. package/dist/detectors/throughput.js.map +1 -0
  15. package/dist/detectors/token-truth.d.ts +40 -0
  16. package/dist/detectors/token-truth.d.ts.map +1 -0
  17. package/dist/detectors/token-truth.js +145 -0
  18. package/dist/detectors/token-truth.js.map +1 -0
  19. package/dist/handshake.d.ts +23 -0
  20. package/dist/handshake.d.ts.map +1 -0
  21. package/dist/handshake.js +90 -0
  22. package/dist/handshake.js.map +1 -0
  23. package/dist/highlight.d.ts +8 -0
  24. package/dist/highlight.d.ts.map +1 -0
  25. package/dist/highlight.js +63 -0
  26. package/dist/highlight.js.map +1 -0
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +7 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/internal/utils.d.ts +6 -0
  32. package/dist/internal/utils.d.ts.map +1 -0
  33. package/dist/internal/utils.js +19 -0
  34. package/dist/internal/utils.js.map +1 -0
  35. package/dist/models.d.ts +5 -0
  36. package/dist/models.d.ts.map +1 -0
  37. package/dist/models.js +54 -0
  38. package/dist/models.js.map +1 -0
  39. package/dist/nonce.d.ts +4 -0
  40. package/dist/nonce.d.ts.map +1 -0
  41. package/dist/nonce.js +12 -0
  42. package/dist/nonce.js.map +1 -0
  43. package/dist/patterns.d.ts +16 -0
  44. package/dist/patterns.d.ts.map +1 -0
  45. package/dist/patterns.js +63 -0
  46. package/dist/patterns.js.map +1 -0
  47. package/dist/probes.d.ts +10 -0
  48. package/dist/probes.d.ts.map +1 -0
  49. package/dist/probes.js +54 -0
  50. package/dist/probes.js.map +1 -0
  51. package/dist/providers/anthropic.d.ts +3 -0
  52. package/dist/providers/anthropic.d.ts.map +1 -0
  53. package/dist/providers/anthropic.js +70 -0
  54. package/dist/providers/anthropic.js.map +1 -0
  55. package/dist/providers/config.d.ts +34 -0
  56. package/dist/providers/config.d.ts.map +1 -0
  57. package/dist/providers/config.js +14 -0
  58. package/dist/providers/config.js.map +1 -0
  59. package/dist/providers/gemini.d.ts +3 -0
  60. package/dist/providers/gemini.d.ts.map +1 -0
  61. package/dist/providers/gemini.js +58 -0
  62. package/dist/providers/gemini.js.map +1 -0
  63. package/dist/providers/openai.d.ts +3 -0
  64. package/dist/providers/openai.d.ts.map +1 -0
  65. package/dist/providers/openai.js +56 -0
  66. package/dist/providers/openai.js.map +1 -0
  67. package/dist/rules.d.ts +6 -0
  68. package/dist/rules.d.ts.map +1 -0
  69. package/dist/rules.js +28 -0
  70. package/dist/rules.js.map +1 -0
  71. package/dist/runner.d.ts +22 -0
  72. package/dist/runner.d.ts.map +1 -0
  73. package/dist/runner.js +298 -0
  74. package/dist/runner.js.map +1 -0
  75. package/dist/signals.d.ts +11 -0
  76. package/dist/signals.d.ts.map +1 -0
  77. package/dist/signals.js +64 -0
  78. package/dist/signals.js.map +1 -0
  79. package/dist/substitution.d.ts +24 -0
  80. package/dist/substitution.d.ts.map +1 -0
  81. package/dist/substitution.js +35 -0
  82. package/dist/substitution.js.map +1 -0
  83. package/dist/transport.d.ts +17 -0
  84. package/dist/transport.d.ts.map +1 -0
  85. package/dist/transport.js +79 -0
  86. package/dist/transport.js.map +1 -0
  87. package/dist/types.d.ts +55 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +2 -0
  90. package/dist/types.js.map +1 -0
  91. package/dist/verdict.d.ts +26 -0
  92. package/dist/verdict.d.ts.map +1 -0
  93. package/dist/verdict.js +84 -0
  94. package/dist/verdict.js.map +1 -0
  95. package/package.json +56 -0
package/dist/probes.js ADDED
@@ -0,0 +1,54 @@
1
+ import { cjkLeak, hasCodingToolRefusal, hasForeignIdentity, hasScamPage, includesAny, } from "./signals";
2
+ import { CLOUD_HOST_PATTERNS, FAKE_RESPONSE_SIGNATURES } from "./patterns";
3
+ import { nonceTag } from "./nonce";
4
+ export const PROBES = [
5
+ {
6
+ label: "emotional",
7
+ maxTokens: 200,
8
+ buildPrompt: (n) => `Tell me a 2-sentence sad story about a lost kitten. ${nonceTag(n)}`,
9
+ evaluate: (text) => !hasCodingToolRefusal(text) && !cjkLeak(text) && text.length >= 40,
10
+ },
11
+ {
12
+ label: "creative",
13
+ maxTokens: 120,
14
+ buildPrompt: (n) => `Write a haiku about the ocean at sunrise. ${nonceTag(n)}`,
15
+ evaluate: (text) => !hasCodingToolRefusal(text) && !cjkLeak(text) && text.length >= 25,
16
+ },
17
+ {
18
+ label: "identity",
19
+ maxTokens: 60,
20
+ buildPrompt: (n) => "Which AI lab developed and trained the model you are running on? " +
21
+ "Not the company hosting you, the lab that trained the model. " +
22
+ `One word answer. ${nonceTag(n)}`,
23
+ evaluate: (text, cfg) => {
24
+ if (hasCodingToolRefusal(text) || hasScamPage(text))
25
+ return false;
26
+ if (hasForeignIdentity(text, cfg.foreignIdentityPatterns, cfg.cloudModelNamePatterns, "identity"))
27
+ return false;
28
+ if (includesAny(text, cfg.homeIdentityPatterns))
29
+ return true;
30
+ if (cfg.acceptsCloudHostIdentity &&
31
+ includesAny(text, CLOUD_HOST_PATTERNS))
32
+ return true;
33
+ return false;
34
+ },
35
+ },
36
+ {
37
+ label: "model-name",
38
+ maxTokens: 80,
39
+ buildPrompt: (n) => `Which model are you? Reply with only your model name. ${nonceTag(n)}`,
40
+ evaluate: (text, cfg) => {
41
+ if (hasCodingToolRefusal(text) || hasScamPage(text))
42
+ return false;
43
+ if (hasForeignIdentity(text, cfg.foreignIdentityPatterns, cfg.cloudModelNamePatterns, "model-name"))
44
+ return false;
45
+ if (!includesAny(text, cfg.homeModelNamePatterns))
46
+ return false;
47
+ const stripped = text.replace(/^\s*\[[a-z0-9]{4,8}\]\s*/i, "").trim();
48
+ if (FAKE_RESPONSE_SIGNATURES.includes(stripped))
49
+ return false;
50
+ return true;
51
+ },
52
+ },
53
+ ];
54
+ //# sourceMappingURL=probes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EACP,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAUnC,MAAM,CAAC,MAAM,MAAM,GAAwB;IACzC;QACE,KAAK,EAAE,WAAW;QAClB,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,uDAAuD,QAAQ,CAAC,CAAC,CAAC,EAAE;QACtE,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CACjB,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE;KACrE;IACD;QACE,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,GAAG;QACd,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,6CAA6C,QAAQ,CAAC,CAAC,CAAC,EAAE;QAC5D,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CACjB,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,EAAE;KACrE;IACD;QACE,KAAK,EAAE,UAAU;QACjB,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,mEAAmE;YACnE,+DAA+D;YAC/D,oBAAoB,QAAQ,CAAC,CAAC,CAAC,EAAE;QACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YACtB,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClE,IACE,kBAAkB,CAChB,IAAI,EACJ,GAAG,CAAC,uBAAuB,EAC3B,GAAG,CAAC,sBAAsB,EAC1B,UAAU,CACX;gBAED,OAAO,KAAK,CAAC;YACf,IAAI,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,oBAAoB,CAAC;gBAAE,OAAO,IAAI,CAAC;YAC7D,IACE,GAAG,CAAC,wBAAwB;gBAC5B,WAAW,CAAC,IAAI,EAAE,mBAAmB,CAAC;gBAEtC,OAAO,IAAI,CAAC;YACd,OAAO,KAAK,CAAC;QACf,CAAC;KACF;IACD;QACE,KAAK,EAAE,YAAY;QACnB,SAAS,EAAE,EAAE;QACb,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,yDAAyD,QAAQ,CAAC,CAAC,CAAC,EAAE;QACxE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YACtB,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YAClE,IACE,kBAAkB,CAChB,IAAI,EACJ,GAAG,CAAC,uBAAuB,EAC3B,GAAG,CAAC,sBAAsB,EAC1B,YAAY,CACb;gBAED,OAAO,KAAK,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,qBAAqB,CAAC;gBAAE,OAAO,KAAK,CAAC;YAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YACtE,IAAI,wBAAwB,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ProviderConfig } from "./config";
2
+ export declare const anthropicConfig: ProviderConfig;
3
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAgElB,eAAO,MAAM,eAAe,EAAE,cAa7B,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { rec } from "../internal/utils";
2
+ import { foreignPatternsExcept } from "../patterns";
3
+ import { normalizeProbeBaseUrl, } from "./config";
4
+ function isAnthropicHost(baseUrl) {
5
+ try {
6
+ return new URL(baseUrl).host.endsWith("api.anthropic.com");
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ }
12
+ function buildRequest(args) {
13
+ const headers = {
14
+ "content-type": "application/json",
15
+ "x-api-key": args.apiKey,
16
+ "anthropic-version": "2023-06-01",
17
+ };
18
+ if (args.direct && isAnthropicHost(args.baseUrl))
19
+ headers["anthropic-dangerous-direct-browser-access"] = "true";
20
+ return {
21
+ url: `${normalizeProbeBaseUrl(args.baseUrl)}/v1/messages`,
22
+ headers,
23
+ body: {
24
+ model: args.model,
25
+ max_tokens: args.maxTokens,
26
+ messages: [{ role: "user", content: args.prompt }],
27
+ },
28
+ };
29
+ }
30
+ function extractText(data) {
31
+ const d = rec(data) ?? {};
32
+ if (d.type === "error")
33
+ return null;
34
+ return (d.content ?? [])
35
+ .filter((b) => b.type === "text")
36
+ .map((b) => b.text ?? "")
37
+ .join(" ")
38
+ .toLowerCase();
39
+ }
40
+ function extractMeta(data) {
41
+ const d = rec(data) ?? {};
42
+ const u = d.usage;
43
+ const prompt = u?.input_tokens ?? null;
44
+ const completion = u?.output_tokens ?? null;
45
+ return {
46
+ detectedModel: d.model ?? null,
47
+ usage: u
48
+ ? {
49
+ prompt,
50
+ completion,
51
+ total: prompt !== null && completion !== null ? prompt + completion : null,
52
+ }
53
+ : null,
54
+ };
55
+ }
56
+ export const anthropicConfig = {
57
+ provider: "anthropic",
58
+ buildRequest,
59
+ extractText,
60
+ extractMeta,
61
+ homeIdentityPatterns: ["anthropic"],
62
+ foreignIdentityPatterns: foreignPatternsExcept("anthropic"),
63
+ homeModelNamePatterns: ["claude", "anthropic"],
64
+ cloudModelNamePatterns: ["amazon q", "q developer", "kiro"],
65
+ // `fable` is load-bearing: sync catches fable lanes served as sonnet, and a
66
+ // tier list missing it makes that substitution undetectable here.
67
+ tiers: ["opus", "sonnet", "haiku", "fable"],
68
+ acceptsCloudHostIdentity: true,
69
+ };
70
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { ProbeUsage, VerifyProvider } from "../types";
2
+ export type ProbeMeta = {
3
+ detectedModel: string | null;
4
+ usage: ProbeUsage | null;
5
+ };
6
+ export type ProbeRequestArgs = {
7
+ baseUrl: string;
8
+ apiKey: string;
9
+ model: string;
10
+ prompt: string;
11
+ maxTokens: number;
12
+ direct: boolean;
13
+ };
14
+ export type BuiltRequest = {
15
+ url: string;
16
+ headers: Record<string, string>;
17
+ body: unknown;
18
+ };
19
+ /** Providers append their own version segment, so a pasted one would double it. */
20
+ export declare function normalizeProbeBaseUrl(baseUrl: string): string;
21
+ export type ProviderConfig = {
22
+ provider: VerifyProvider;
23
+ buildRequest: (args: ProbeRequestArgs) => BuiltRequest;
24
+ extractText: (data: unknown) => string | null;
25
+ extractMeta: (data: unknown) => ProbeMeta;
26
+ homeIdentityPatterns: string[];
27
+ foreignIdentityPatterns: string[];
28
+ homeModelNamePatterns: string[];
29
+ cloudModelNamePatterns: string[];
30
+ tiers: readonly string[] | null;
31
+ acceptsCloudHostIdentity: boolean;
32
+ };
33
+ export declare const PROVIDER_CONFIGS: Record<VerifyProvider, ProviderConfig>;
34
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/providers/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAK3D,MAAM,MAAM,SAAS,GAAG;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAIF,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,YAAY,CAAC;IACvD,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,SAAS,CAAC;IAC1C,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,wBAAwB,EAAE,OAAO,CAAC;CACnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,cAAc,EAAE,cAAc,CAInE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { anthropicConfig } from "./anthropic";
2
+ import { geminiConfig } from "./gemini";
3
+ import { openaiConfig } from "./openai";
4
+ const VERSION_SUFFIX = /\/(?:v\d+(?:alpha|beta)?)\/*$/i;
5
+ /** Providers append their own version segment, so a pasted one would double it. */
6
+ export function normalizeProbeBaseUrl(baseUrl) {
7
+ return baseUrl.trim().replace(/\/+$/, "").replace(VERSION_SUFFIX, "");
8
+ }
9
+ export const PROVIDER_CONFIGS = {
10
+ anthropic: anthropicConfig,
11
+ openai: openaiConfig,
12
+ gemini: geminiConfig,
13
+ };
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/providers/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAsBxC,MAAM,cAAc,GAAG,gCAAgC,CAAC;AAExD,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,OAAe;IACnD,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAeD,MAAM,CAAC,MAAM,gBAAgB,GAA2C;IACtE,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;CACrB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ProviderConfig } from "./config";
2
+ export declare const geminiConfig: ProviderConfig;
3
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAyDlB,eAAO,MAAM,YAAY,EAAE,cAW1B,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { rec } from "../internal/utils";
2
+ import { foreignPatternsExcept } from "../patterns";
3
+ import { normalizeProbeBaseUrl, } from "./config";
4
+ const GEMINI_MIN_OUTPUT_TOKENS = 1024;
5
+ function buildRequest(args) {
6
+ return {
7
+ url: `${normalizeProbeBaseUrl(args.baseUrl)}/v1beta/models/${args.model}:generateContent`,
8
+ headers: {
9
+ "content-type": "application/json",
10
+ "x-goog-api-key": args.apiKey,
11
+ },
12
+ body: {
13
+ contents: [{ role: "user", parts: [{ text: args.prompt }] }],
14
+ generationConfig: {
15
+ maxOutputTokens: Math.max(args.maxTokens, GEMINI_MIN_OUTPUT_TOKENS),
16
+ },
17
+ },
18
+ };
19
+ }
20
+ function extractText(data) {
21
+ const d = rec(data) ?? {};
22
+ if (d.error)
23
+ return null;
24
+ const parts = d.candidates?.[0]?.content?.parts;
25
+ if (!parts)
26
+ return null;
27
+ return parts
28
+ .map((p) => p.text ?? "")
29
+ .join(" ")
30
+ .toLowerCase();
31
+ }
32
+ function extractMeta(data) {
33
+ const d = rec(data) ?? {};
34
+ const u = d.usageMetadata;
35
+ return {
36
+ detectedModel: d.modelVersion ?? null,
37
+ usage: u
38
+ ? {
39
+ prompt: u.promptTokenCount ?? null,
40
+ completion: u.candidatesTokenCount ?? null,
41
+ total: u.totalTokenCount ?? null,
42
+ }
43
+ : null,
44
+ };
45
+ }
46
+ export const geminiConfig = {
47
+ provider: "gemini",
48
+ buildRequest,
49
+ extractText,
50
+ extractMeta,
51
+ homeIdentityPatterns: ["google", "deepmind"],
52
+ foreignIdentityPatterns: foreignPatternsExcept("google"),
53
+ homeModelNamePatterns: ["gemini", "google"],
54
+ cloudModelNamePatterns: [],
55
+ tiers: null,
56
+ acceptsCloudHostIdentity: false,
57
+ };
58
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,qBAAqB,GAItB,MAAM,UAAU,CAAC;AAalB,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,SAAS,YAAY,CAAC,IAAsB;IAC1C,OAAO;QACL,GAAG,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,IAAI,CAAC,KAAK,kBAAkB;QACzF,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,gBAAgB,EAAE,IAAI,CAAC,MAAM;SAC9B;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;YAC5D,gBAAgB,EAAE;gBAChB,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC;aACpE;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,CAAC,GAAmB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;SACxB,IAAI,CAAC,GAAG,CAAC;SACT,WAAW,EAAE,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,CAAC,GAAmB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC;IAC1B,OAAO;QACL,aAAa,EAAE,CAAC,CAAC,YAAY,IAAI,IAAI;QACrC,KAAK,EAAE,CAAC;YACN,CAAC,CAAC;gBACE,MAAM,EAAE,CAAC,CAAC,gBAAgB,IAAI,IAAI;gBAClC,UAAU,EAAE,CAAC,CAAC,oBAAoB,IAAI,IAAI;gBAC1C,KAAK,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI;aACjC;YACH,CAAC,CAAC,IAAI;KACT,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,QAAQ,EAAE,QAAQ;IAClB,YAAY;IACZ,WAAW;IACX,WAAW;IACX,oBAAoB,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC5C,uBAAuB,EAAE,qBAAqB,CAAC,QAAQ,CAAC;IACxD,qBAAqB,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC3C,sBAAsB,EAAE,EAAE;IAC1B,KAAK,EAAE,IAAI;IACX,wBAAwB,EAAE,KAAK;CAChC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ProviderConfig } from "./config";
2
+ export declare const openaiConfig: ProviderConfig;
3
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAwDlB,eAAO,MAAM,YAAY,EAAE,cAW1B,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { rec } from "../internal/utils";
2
+ import { foreignPatternsExcept } from "../patterns";
3
+ import { normalizeProbeBaseUrl, } from "./config";
4
+ const REASONING_MIN_OUTPUT_TOKENS = 2000;
5
+ const REASONING_MODEL = /^(?:o[1-9]|gpt-5)/i;
6
+ function buildRequest(args) {
7
+ const maxCompletionTokens = REASONING_MODEL.test(args.model)
8
+ ? Math.max(args.maxTokens, REASONING_MIN_OUTPUT_TOKENS)
9
+ : args.maxTokens;
10
+ return {
11
+ url: `${normalizeProbeBaseUrl(args.baseUrl)}/v1/chat/completions`,
12
+ headers: {
13
+ "content-type": "application/json",
14
+ authorization: `Bearer ${args.apiKey}`,
15
+ },
16
+ body: {
17
+ model: args.model,
18
+ max_completion_tokens: maxCompletionTokens,
19
+ messages: [{ role: "user", content: args.prompt }],
20
+ },
21
+ };
22
+ }
23
+ function extractText(data) {
24
+ const d = rec(data) ?? {};
25
+ if (d.error)
26
+ return null;
27
+ const content = d.choices?.[0]?.message?.content;
28
+ return typeof content === "string" ? content.toLowerCase() : null;
29
+ }
30
+ function extractMeta(data) {
31
+ const d = rec(data) ?? {};
32
+ const u = d.usage;
33
+ return {
34
+ detectedModel: d.model ?? null,
35
+ usage: u
36
+ ? {
37
+ prompt: u.prompt_tokens ?? null,
38
+ completion: u.completion_tokens ?? null,
39
+ total: u.total_tokens ?? null,
40
+ }
41
+ : null,
42
+ };
43
+ }
44
+ export const openaiConfig = {
45
+ provider: "openai",
46
+ buildRequest,
47
+ extractText,
48
+ extractMeta,
49
+ homeIdentityPatterns: ["openai"],
50
+ foreignIdentityPatterns: foreignPatternsExcept("openai"),
51
+ homeModelNamePatterns: ["gpt", "openai", "o1", "o3", "o4"],
52
+ cloudModelNamePatterns: [],
53
+ tiers: null,
54
+ acceptsCloudHostIdentity: false,
55
+ };
56
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EACL,qBAAqB,GAItB,MAAM,UAAU,CAAC;AAalB,MAAM,2BAA2B,GAAG,IAAI,CAAC;AACzC,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C,SAAS,YAAY,CAAC,IAAsB;IAC1C,MAAM,mBAAmB,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1D,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,2BAA2B,CAAC;QACvD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IACnB,OAAO;QACL,GAAG,EAAE,GAAG,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,sBAAsB;QACjE,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;SACvC;QACD,IAAI,EAAE;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,qBAAqB,EAAE,mBAAmB;YAC1C,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;SACnD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,CAAC,GAAuB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;IACjD,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpE,CAAC;AAED,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,CAAC,GAAuB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;IAClB,OAAO;QACL,aAAa,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QAC9B,KAAK,EAAE,CAAC;YACN,CAAC,CAAC;gBACE,MAAM,EAAE,CAAC,CAAC,aAAa,IAAI,IAAI;gBAC/B,UAAU,EAAE,CAAC,CAAC,iBAAiB,IAAI,IAAI;gBACvC,KAAK,EAAE,CAAC,CAAC,YAAY,IAAI,IAAI;aAC9B;YACH,CAAC,CAAC,IAAI;KACT,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,QAAQ,EAAE,QAAQ;IAClB,YAAY;IACZ,WAAW;IACX,WAAW;IACX,oBAAoB,EAAE,CAAC,QAAQ,CAAC;IAChC,uBAAuB,EAAE,qBAAqB,CAAC,QAAQ,CAAC;IACxD,qBAAqB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC1D,sBAAsB,EAAE,EAAE;IAC1B,KAAK,EAAE,IAAI;IACX,wBAAwB,EAAE,KAAK;CAChC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export type DetectionRuleId = "coding-tool" | "scam" | "cjk-leak" | "mux" | "foreign" | "tier-mismatch" | "substituted";
2
+ export declare const DETECTION_RULES: readonly DetectionRuleId[];
3
+ export type DetectionExceptionId = "version" | "transient" | "cloud-host" | "reshaping" | "threshold";
4
+ export declare const DETECTION_EXCEPTIONS: readonly DetectionExceptionId[];
5
+ export declare function ruleIdForSignal(signal: string): DetectionRuleId | null;
6
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,MAAM,GACN,UAAU,GACV,KAAK,GACL,SAAS,GACT,eAAe,GACf,aAAa,CAAC;AAElB,eAAO,MAAM,eAAe,EAAE,SAAS,eAAe,EAQrD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAC9B,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC;AAErE,eAAO,MAAM,oBAAoB,EAAE,SAAS,oBAAoB,EAM/D,CAAC;AAEF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAMtE"}
package/dist/rules.js ADDED
@@ -0,0 +1,28 @@
1
+ export const DETECTION_RULES = [
2
+ "coding-tool",
3
+ "scam",
4
+ "cjk-leak",
5
+ "mux",
6
+ "foreign",
7
+ "tier-mismatch",
8
+ "substituted",
9
+ ];
10
+ export const DETECTION_EXCEPTIONS = [
11
+ "version",
12
+ "transient",
13
+ "cloud-host",
14
+ "reshaping",
15
+ "threshold",
16
+ ];
17
+ export function ruleIdForSignal(signal) {
18
+ if (signal === "coding-tool")
19
+ return "coding-tool";
20
+ if (signal === "scam")
21
+ return "scam";
22
+ if (signal === "cjk-leak")
23
+ return "cjk-leak";
24
+ if (signal === "foreign")
25
+ return "foreign";
26
+ return null;
27
+ }
28
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,eAAe,GAA+B;IACzD,aAAa;IACb,MAAM;IACN,UAAU;IACV,KAAK;IACL,SAAS;IACT,eAAe;IACf,aAAa;CACd,CAAC;AAKF,MAAM,CAAC,MAAM,oBAAoB,GAAoC;IACnE,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;IACX,WAAW;CACZ,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,MAAM,KAAK,aAAa;QAAE,OAAO,aAAa,CAAC;IACnD,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACrC,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC7C,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type TransportFn } from "./transport";
2
+ import type { TransportMode, VerifyProvider, VerifyResult } from "./types";
3
+ export declare function runVerification(opts: {
4
+ provider: VerifyProvider;
5
+ baseUrl: string;
6
+ apiKey: string;
7
+ model: string;
8
+ mode: TransportMode;
9
+ timeoutMs?: number;
10
+ transport?: TransportFn;
11
+ /**
12
+ * Run the Anthropic thinking-signature check too. Opt-in: it costs one extra
13
+ * generation and only applies to Claude models that support thinking.
14
+ */
15
+ checkSignature?: boolean;
16
+ /**
17
+ * Verify the endpoint's token accounting (billing inflation, and the
18
+ * tokenizer band that doubles as a tier check). Opt-in: three extra requests.
19
+ */
20
+ checkTokenTruth?: boolean;
21
+ }): Promise<VerifyResult>;
22
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAcA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,KAAK,EAEV,aAAa,EACb,cAAc,EACd,YAAY,EACb,MAAM,SAAS,CAAC;AAwOjB,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,OAAO,CAAC,YAAY,CAAC,CAwHxB"}