@theokit/sdk 4.14.0 → 4.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Dynamic provider-plugin trust gate (agent-builder M47): the out-of-tree loader (`~/.theokit/plugins/model-providers/<name>/index.{js,mjs}` — the documented extension path for shipping a provider as a package) now requires EXPLICIT human trust before any dynamic import. A plugin's code executes at import time (an arbitrary-code-execution surface), so nothing is evaluated unless the plugin name is listed in `~/.theokit/plugins/trusted-providers.json` (a JSON string array — the auditable primary) or the additive `THEOKIT_TRUSTED_PROVIDERS` env (comma-separated). Fail-closed: a missing or malformed trust file trusts NOTHING (malformed WARNs); an untrusted plugin is skipped with an actionable WARN naming the file to edit — its code is NEVER evaluated (proven by an import-side-effect fixture test). **BREAKING (deliberate security fix):** previously ANY package dropped into the plugins dir executed unguarded; existing plugin users must add their plugin names to the trust file (the WARN says exactly how).
8
+
9
+ ## 4.14.1
10
+
11
+ ### Patch Changes
12
+
13
+ - M45 adversarial-review fixes: (H1) a malformed `baseUrl` (scheme-less host, empty env var) no longer throws an untyped `TypeError` from the OpenAIClient CONSTRUCTOR — poisoning the whole provider chain at `resolveProviderChain` time even when only a fallback was misconfigured; the URL parse now degrades to the legacy `/v1/chat/completions` path (byte-identical to pre-M45) and fails typed at fetch time. (M2) re-running `registerBuiltins()` across bundle copies (`@theokit/sdk` + `@theokit/sdk/models`) no longer emits 19 bogus `overridden by user plugin` WARNs — the guard lives on `globalThis` like the registry itself. (M3) a trailing-slash versioned baseUrl (`…/v1/`) now joins cleanly (no `/v1//chat/completions`). (L1) the `google` builtin also honors `GOOGLE_GENERATIVE_AI_API_KEY` (the ai-sdk convention). (L4) `getCatalogCapabilities` resolves entry aliases (e.g. `google`). NOTICE extended for the M45 adaptations. **Migration note (M1):** the chat-completions URL-join now detects version segments ANYWHERE in the baseUrl path — a gateway mounting an OpenAI-compat surface under a versioned prefix (e.g. `https://gw.corp/v2/tenants/x`) that previously got `/v1/chat/completions` appended now gets `/chat/completions`; declare `chatCompletionsPath` on the profile to pin an exact path.
14
+
3
15
  ## 4.14.0
4
16
 
5
17
  ### Minor Changes
package/dist/cron.cjs CHANGED
@@ -752,13 +752,13 @@ function setAgentFacade(facade) {
752
752
  globalThis[FACADE_KEY] = facade;
753
753
  }
754
754
  function getAgentFacade() {
755
- const registered3 = globalThis[FACADE_KEY];
756
- if (registered3 === void 0) {
755
+ const registered2 = globalThis[FACADE_KEY];
756
+ if (registered2 === void 0) {
757
757
  throw new Error(
758
758
  "internal: Agent facade not registered. The `agent.ts` module must be loaded before internal subsystems (LocalAgent.runUntil/fork, eval, scorers, cron) invoke it."
759
759
  );
760
760
  }
761
- return registered3;
761
+ return registered2;
762
762
  }
763
763
  var FACADE_KEY;
764
764
  var init_agent_factory_registry = __esm({
@@ -11486,11 +11486,22 @@ var DEEPINFRA = openAiCompatibleProfile({
11486
11486
  hostname: "api.deepinfra.com"
11487
11487
  });
11488
11488
 
11489
+ // src/internal/providers/builtin/gemini.ts
11490
+ var GEMINI = {
11491
+ name: "gemini",
11492
+ apiMode: "chat_completions",
11493
+ envVars: ["OPENROUTER_API_KEY"],
11494
+ authType: "api_key",
11495
+ baseUrl: "https://openrouter.ai/api",
11496
+ hostname: "openrouter.ai",
11497
+ fallbackModels: ["google/gemini-2.0-flash-001"]
11498
+ };
11499
+
11489
11500
  // src/internal/providers/builtin/google.ts
11490
11501
  var GOOGLE = openAiCompatibleProfile({
11491
11502
  name: "google",
11492
11503
  baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
11493
- envVars: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
11504
+ envVars: ["GOOGLE_API_KEY", "GEMINI_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
11494
11505
  fallbackModels: ["gemini-2.5-pro", "gemini-2.5-flash"],
11495
11506
  hostname: "generativelanguage.googleapis.com"
11496
11507
  });
@@ -11504,56 +11515,6 @@ var GROQ = openAiCompatibleProfile({
11504
11515
  hostname: "api.groq.com"
11505
11516
  });
11506
11517
 
11507
- // src/internal/providers/builtin/mistral.ts
11508
- var MISTRAL = openAiCompatibleProfile({
11509
- name: "mistral",
11510
- baseUrl: "https://api.mistral.ai/v1",
11511
- envVars: ["MISTRAL_API_KEY"],
11512
- fallbackModels: ["mistral-large-latest", "codestral-latest"],
11513
- hostname: "api.mistral.ai"
11514
- });
11515
-
11516
- // src/internal/providers/builtin/perplexity.ts
11517
- var PERPLEXITY = openAiCompatibleProfile({
11518
- name: "perplexity",
11519
- baseUrl: "https://api.perplexity.ai",
11520
- chatCompletionsPath: "/chat/completions",
11521
- envVars: ["PERPLEXITY_API_KEY"],
11522
- fallbackModels: ["sonar-pro", "sonar"],
11523
- hostname: "api.perplexity.ai"
11524
- });
11525
-
11526
- // src/internal/providers/builtin/together.ts
11527
- var TOGETHER = openAiCompatibleProfile({
11528
- name: "together",
11529
- aliases: ["togetherai"],
11530
- baseUrl: "https://api.together.xyz/v1",
11531
- envVars: ["TOGETHER_API_KEY"],
11532
- fallbackModels: ["Qwen/Qwen2.5-7B-Instruct-Turbo"],
11533
- hostname: "api.together.xyz"
11534
- });
11535
-
11536
- // src/internal/providers/builtin/xai.ts
11537
- var XAI = openAiCompatibleProfile({
11538
- name: "xai",
11539
- aliases: ["grok"],
11540
- baseUrl: "https://api.x.ai/v1",
11541
- envVars: ["XAI_API_KEY"],
11542
- fallbackModels: ["grok-4.5", "grok-4.3"],
11543
- hostname: "api.x.ai"
11544
- });
11545
-
11546
- // src/internal/providers/builtin/gemini.ts
11547
- var GEMINI = {
11548
- name: "gemini",
11549
- apiMode: "chat_completions",
11550
- envVars: ["OPENROUTER_API_KEY"],
11551
- authType: "api_key",
11552
- baseUrl: "https://openrouter.ai/api",
11553
- hostname: "openrouter.ai",
11554
- fallbackModels: ["google/gemini-2.0-flash-001"]
11555
- };
11556
-
11557
11518
  // src/internal/providers/builtin/llamacpp.ts
11558
11519
  var LLAMACPP = {
11559
11520
  name: "llamacpp",
@@ -11580,6 +11541,15 @@ var LMSTUDIO = {
11580
11541
  fallbackModels: ["loaded-model"]
11581
11542
  };
11582
11543
 
11544
+ // src/internal/providers/builtin/mistral.ts
11545
+ var MISTRAL = openAiCompatibleProfile({
11546
+ name: "mistral",
11547
+ baseUrl: "https://api.mistral.ai/v1",
11548
+ envVars: ["MISTRAL_API_KEY"],
11549
+ fallbackModels: ["mistral-large-latest", "codestral-latest"],
11550
+ hostname: "api.mistral.ai"
11551
+ });
11552
+
11583
11553
  // src/internal/providers/builtin/ollama.ts
11584
11554
  var OLLAMA = {
11585
11555
  name: "ollama",
@@ -11974,6 +11944,26 @@ var OPENROUTER = {
11974
11944
  extraHeaders: { "HTTP-Referer": "https://usetheo.dev", "X-Title": "theokit" }
11975
11945
  };
11976
11946
 
11947
+ // src/internal/providers/builtin/perplexity.ts
11948
+ var PERPLEXITY = openAiCompatibleProfile({
11949
+ name: "perplexity",
11950
+ baseUrl: "https://api.perplexity.ai",
11951
+ chatCompletionsPath: "/chat/completions",
11952
+ envVars: ["PERPLEXITY_API_KEY"],
11953
+ fallbackModels: ["sonar-pro", "sonar"],
11954
+ hostname: "api.perplexity.ai"
11955
+ });
11956
+
11957
+ // src/internal/providers/builtin/together.ts
11958
+ var TOGETHER = openAiCompatibleProfile({
11959
+ name: "together",
11960
+ aliases: ["togetherai"],
11961
+ baseUrl: "https://api.together.xyz/v1",
11962
+ envVars: ["TOGETHER_API_KEY"],
11963
+ fallbackModels: ["Qwen/Qwen2.5-7B-Instruct-Turbo"],
11964
+ hostname: "api.together.xyz"
11965
+ });
11966
+
11977
11967
  // src/internal/providers/builtin/vertex.ts
11978
11968
  var VERTEX = {
11979
11969
  name: "vertex",
@@ -12005,11 +11995,26 @@ function stripVertexPrefix(modelId) {
12005
11995
  return modelId.replace(/^vertex\/(anthropic|google)\//, "");
12006
11996
  }
12007
11997
 
11998
+ // src/internal/providers/builtin/xai.ts
11999
+ var XAI = openAiCompatibleProfile({
12000
+ name: "xai",
12001
+ aliases: ["grok"],
12002
+ baseUrl: "https://api.x.ai/v1",
12003
+ envVars: ["XAI_API_KEY"],
12004
+ fallbackModels: ["grok-4.5", "grok-4.3"],
12005
+ hostname: "api.x.ai"
12006
+ });
12007
+
12008
12008
  // src/internal/providers/builtin/index.ts
12009
- var registered2 = false;
12009
+ var _registeredState = (() => {
12010
+ const g = globalThis;
12011
+ const sym = /* @__PURE__ */ Symbol.for("theokit-sdk.providers.builtins-registered");
12012
+ if (g[sym] === void 0) g[sym] = { done: false };
12013
+ return g[sym];
12014
+ })();
12010
12015
  function registerBuiltins() {
12011
- if (registered2) return;
12012
- registered2 = true;
12016
+ if (_registeredState.done) return;
12017
+ _registeredState.done = true;
12013
12018
  registerProvider(ANTHROPIC);
12014
12019
  registerProvider(OPENAI);
12015
12020
  registerProvider(OPENAI_CHATGPT);
@@ -13178,11 +13183,18 @@ var StreamSuppressionBuffer = class {
13178
13183
  };
13179
13184
 
13180
13185
  // src/internal/llm/openai.ts
13186
+ function deriveChatPath(baseUrl) {
13187
+ try {
13188
+ return /\/v\d+[a-z]*(\/|$)/.test(new URL(baseUrl).pathname) ? "/chat/completions" : "/v1/chat/completions";
13189
+ } catch {
13190
+ return "/v1/chat/completions";
13191
+ }
13192
+ }
13181
13193
  var OpenAIClient = class {
13182
13194
  constructor(options) {
13183
13195
  this.options = options;
13184
- this.baseUrl = options.baseUrl ?? "https://api.openai.com";
13185
- this.chatPath = options.chatCompletionsPath ?? (/\/v\d+[a-z]*(\/|$)/.test(new URL(this.baseUrl).pathname) ? "/chat/completions" : "/v1/chat/completions");
13196
+ this.baseUrl = (options.baseUrl ?? "https://api.openai.com").replace(/\/+$/, "");
13197
+ this.chatPath = options.chatCompletionsPath ?? deriveChatPath(this.baseUrl);
13186
13198
  this.fetchImpl = options.fetch ?? fetch;
13187
13199
  }
13188
13200
  options;
@@ -14652,12 +14664,12 @@ function resolveMcpCwd(configCwd) {
14652
14664
 
14653
14665
  // src/internal/providers/register-plugin-providers.ts
14654
14666
  function registerPluginProviderProfiles(entries) {
14655
- let registered3 = 0;
14667
+ let registered2 = 0;
14656
14668
  for (const entry of entries) {
14657
14669
  registerProvider(entry.profile);
14658
- registered3 += 1;
14670
+ registered2 += 1;
14659
14671
  }
14660
- return registered3;
14672
+ return registered2;
14661
14673
  }
14662
14674
 
14663
14675
  // src/internal/local-agent/real-local-run.ts
@@ -14982,12 +14994,12 @@ var pluginProvidersAnnounced = false;
14982
14994
  function resolveRunProvider(options) {
14983
14995
  registerBuiltins();
14984
14996
  const profiles = options.pluginManager?.aggregated.providerProfiles ?? [];
14985
- const registered3 = registerPluginProviderProfiles(profiles);
14986
- if (registered3 > 0 && !pluginProvidersAnnounced) {
14997
+ const registered2 = registerPluginProviderProfiles(profiles);
14998
+ if (registered2 > 0 && !pluginProvidersAnnounced) {
14987
14999
  pluginProvidersAnnounced = true;
14988
15000
  const names = profiles.map((e) => e.profile.name).join(", ");
14989
15001
  process.stderr.write(
14990
- `[theokit-sdk] registered ${registered3} plugin provider profile(s): ${names}
15002
+ `[theokit-sdk] registered ${registered2} plugin provider profile(s): ${names}
14991
15003
  `
14992
15004
  );
14993
15005
  }