pkgxray 0.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.
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ const DEFAULT_MODEL = "claude-opus-4-7";
4
+ const ENV_KEY = "ANTHROPIC_API_KEY";
5
+
6
+ function detect(modelId) {
7
+ return typeof modelId === "string" && modelId.startsWith("claude-");
8
+ }
9
+
10
+ function loadSdk() {
11
+ try {
12
+ const mod = require("@anthropic-ai/sdk");
13
+ return mod.default || mod;
14
+ } catch (error) {
15
+ if (error && error.code === "MODULE_NOT_FOUND") {
16
+ const hint = new Error(
17
+ "Anthropic provider needs @anthropic-ai/sdk. Install with: npm install @anthropic-ai/sdk"
18
+ );
19
+ hint.code = "REASONER_SDK_MISSING";
20
+ throw hint;
21
+ }
22
+ throw error;
23
+ }
24
+ }
25
+
26
+ async function call({ systemPrompt, userMessage, schema, model, apiKey, maxTokens, effort }) {
27
+ const Anthropic = loadSdk();
28
+ const client = new Anthropic({ apiKey });
29
+ const chosenModel = model || DEFAULT_MODEL;
30
+ const start = Date.now();
31
+ const response = await client.messages.create({
32
+ model: chosenModel,
33
+ max_tokens: maxTokens || 16000,
34
+ thinking: { type: "adaptive" },
35
+ output_config: {
36
+ effort: effort || "high",
37
+ format: { type: "json_schema", schema }
38
+ },
39
+ system: [
40
+ {
41
+ type: "text",
42
+ text: systemPrompt,
43
+ cache_control: { type: "ephemeral" }
44
+ }
45
+ ],
46
+ messages: [{ role: "user", content: userMessage }]
47
+ });
48
+ const latencyMs = Date.now() - start;
49
+ const textBlock = response.content.find((block) => block.type === "text");
50
+ if (!textBlock) {
51
+ const error = new Error("Anthropic response had no text content");
52
+ error.code = "REASONER_NO_TEXT";
53
+ throw error;
54
+ }
55
+ return {
56
+ text: textBlock.text,
57
+ usage: response.usage || null,
58
+ model: chosenModel,
59
+ latencyMs,
60
+ stopReason: response.stop_reason || null
61
+ };
62
+ }
63
+
64
+ module.exports = { name: "anthropic", defaultModel: DEFAULT_MODEL, envKey: ENV_KEY, detect, call };
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+
3
+ const DEFAULT_MODEL = "gemini-2.5-pro";
4
+ const ENV_KEY = "GEMINI_API_KEY";
5
+
6
+ function detect(modelId) {
7
+ return typeof modelId === "string" && /^gemini-/i.test(modelId);
8
+ }
9
+
10
+ function loadSdk() {
11
+ try {
12
+ return require("@google/generative-ai");
13
+ } catch (error) {
14
+ if (error && error.code === "MODULE_NOT_FOUND") {
15
+ const hint = new Error(
16
+ "Gemini provider needs @google/generative-ai. Install with: npm install @google/generative-ai"
17
+ );
18
+ hint.code = "REASONER_SDK_MISSING";
19
+ throw hint;
20
+ }
21
+ throw error;
22
+ }
23
+ }
24
+
25
+ async function call({ systemPrompt, userMessage, schema, model, apiKey, maxTokens }) {
26
+ const { GoogleGenerativeAI } = loadSdk();
27
+ const genAI = new GoogleGenerativeAI(apiKey || process.env[ENV_KEY] || process.env.GOOGLE_API_KEY);
28
+ const chosenModel = model || DEFAULT_MODEL;
29
+ const generative = genAI.getGenerativeModel({
30
+ model: chosenModel,
31
+ systemInstruction: systemPrompt,
32
+ generationConfig: {
33
+ responseMimeType: "application/json",
34
+ maxOutputTokens: maxTokens || 16000
35
+ }
36
+ });
37
+ const start = Date.now();
38
+ const result = await generative.generateContent(userMessage);
39
+ const latencyMs = Date.now() - start;
40
+ const response = result.response;
41
+ const text = typeof response.text === "function" ? response.text() : "";
42
+ if (!text) {
43
+ const error = new Error("Gemini response had no text content");
44
+ error.code = "REASONER_NO_TEXT";
45
+ throw error;
46
+ }
47
+ const meta = response.usageMetadata || {};
48
+ const usage = {
49
+ input_tokens: meta.promptTokenCount || 0,
50
+ output_tokens: meta.candidatesTokenCount || 0,
51
+ cache_read_input_tokens: meta.cachedContentTokenCount || 0,
52
+ cache_creation_input_tokens: 0
53
+ };
54
+ const finishReason =
55
+ response.candidates && response.candidates[0] && response.candidates[0].finishReason;
56
+ return {
57
+ text,
58
+ usage,
59
+ model: chosenModel,
60
+ latencyMs,
61
+ stopReason: finishReason || null,
62
+ schemaHint: schema ? "schema enforced via prompt only on Gemini" : null
63
+ };
64
+ }
65
+
66
+ module.exports = { name: "gemini", defaultModel: DEFAULT_MODEL, envKey: ENV_KEY, detect, call };
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ const anthropic = require("./anthropic");
4
+ const openai = require("./openai");
5
+ const gemini = require("./gemini");
6
+
7
+ const PROVIDERS = { anthropic, openai, gemini };
8
+
9
+ function listProviders() {
10
+ return Object.keys(PROVIDERS);
11
+ }
12
+
13
+ function getProvider(name) {
14
+ const provider = PROVIDERS[name];
15
+ if (!provider) {
16
+ const error = new Error(`Unknown provider: ${name}. Available: ${listProviders().join(", ")}`);
17
+ error.code = "REASONER_UNKNOWN_PROVIDER";
18
+ throw error;
19
+ }
20
+ return provider;
21
+ }
22
+
23
+ function detectProvider(modelId) {
24
+ if (!modelId) return null;
25
+ for (const provider of Object.values(PROVIDERS)) {
26
+ if (provider.detect(modelId)) return provider;
27
+ }
28
+ return null;
29
+ }
30
+
31
+ function resolveProvider({ provider, model } = {}) {
32
+ if (provider) return getProvider(provider);
33
+ if (model) {
34
+ const detected = detectProvider(model);
35
+ if (detected) return detected;
36
+ }
37
+ return anthropic;
38
+ }
39
+
40
+ module.exports = { PROVIDERS, listProviders, getProvider, detectProvider, resolveProvider };
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ const DEFAULT_MODEL = "gpt-5";
4
+ const ENV_KEY = "OPENAI_API_KEY";
5
+
6
+ function detect(modelId) {
7
+ if (typeof modelId !== "string") return false;
8
+ return /^(gpt-|o\d|chatgpt-)/i.test(modelId);
9
+ }
10
+
11
+ function loadSdk() {
12
+ try {
13
+ const mod = require("openai");
14
+ return mod.default || mod.OpenAI || mod;
15
+ } catch (error) {
16
+ if (error && error.code === "MODULE_NOT_FOUND") {
17
+ const hint = new Error(
18
+ "OpenAI provider needs the openai package. Install with: npm install openai"
19
+ );
20
+ hint.code = "REASONER_SDK_MISSING";
21
+ throw hint;
22
+ }
23
+ throw error;
24
+ }
25
+ }
26
+
27
+ async function call({ systemPrompt, userMessage, schema, model, apiKey, maxTokens }) {
28
+ const OpenAI = loadSdk();
29
+ const client = new OpenAI({ apiKey });
30
+ const chosenModel = model || DEFAULT_MODEL;
31
+ const start = Date.now();
32
+ const completion = await client.chat.completions.create({
33
+ model: chosenModel,
34
+ messages: [
35
+ { role: "system", content: systemPrompt },
36
+ { role: "user", content: userMessage }
37
+ ],
38
+ response_format: {
39
+ type: "json_schema",
40
+ json_schema: {
41
+ name: "supply_chain_verdict",
42
+ strict: true,
43
+ schema
44
+ }
45
+ },
46
+ max_completion_tokens: maxTokens || 16000
47
+ });
48
+ const latencyMs = Date.now() - start;
49
+ const choice = completion.choices && completion.choices[0];
50
+ if (!choice || !choice.message || typeof choice.message.content !== "string") {
51
+ const error = new Error("OpenAI response had no message content");
52
+ error.code = "REASONER_NO_TEXT";
53
+ throw error;
54
+ }
55
+ const usage = completion.usage
56
+ ? {
57
+ input_tokens: completion.usage.prompt_tokens,
58
+ output_tokens: completion.usage.completion_tokens,
59
+ cache_read_input_tokens:
60
+ (completion.usage.prompt_tokens_details &&
61
+ completion.usage.prompt_tokens_details.cached_tokens) ||
62
+ 0,
63
+ cache_creation_input_tokens: 0
64
+ }
65
+ : null;
66
+ return {
67
+ text: choice.message.content,
68
+ usage,
69
+ model: chosenModel,
70
+ latencyMs,
71
+ stopReason: choice.finish_reason || null
72
+ };
73
+ }
74
+
75
+ module.exports = { name: "openai", defaultModel: DEFAULT_MODEL, envKey: ENV_KEY, detect, call };