@theokit/sdk 4.15.0 → 4.15.2

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/dist/index.cjs CHANGED
@@ -11522,14 +11522,14 @@ var PluginsManager = class {
11522
11522
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: MD-first + JSON fallback + both-present detection per plugin folder — branch table is clearer inlined.
11523
11523
  async refresh() {
11524
11524
  this.plugins = [];
11525
- const pluginsRoot = path.join(this.cwd, ".theokit", "plugins");
11526
- const entries = await readWorkspaceDir(pluginsRoot, "plugins_read_error", "plugins directory");
11525
+ const pluginsRoot2 = path.join(this.cwd, ".theokit", "plugins");
11526
+ const entries = await readWorkspaceDir(pluginsRoot2, "plugins_read_error", "plugins directory");
11527
11527
  for (const entry of entries) {
11528
11528
  if (!entry.isDirectory()) continue;
11529
11529
  const folderName = entry.name;
11530
- const mdPath = path.join(pluginsRoot, folderName, "PLUGIN.md");
11531
- const jsonPath = path.join(pluginsRoot, folderName, "plugin.json");
11532
- const metadata = fs.existsSync(mdPath) ? await loadPluginManifestFromMarkdown(pluginsRoot, folderName) : await loadPluginManifestFromJson(jsonPath, folderName);
11530
+ const mdPath = path.join(pluginsRoot2, folderName, "PLUGIN.md");
11531
+ const jsonPath = path.join(pluginsRoot2, folderName, "plugin.json");
11532
+ const metadata = fs.existsSync(mdPath) ? await loadPluginManifestFromMarkdown(pluginsRoot2, folderName) : await loadPluginManifestFromJson(jsonPath, folderName);
11533
11533
  if (fs.existsSync(mdPath) && fs.existsSync(jsonPath)) {
11534
11534
  warnOnce(
11535
11535
  `plugin-${folderName}-both`,
@@ -11608,8 +11608,8 @@ async function loadPluginManifestFromJson(manifestPath, folderName) {
11608
11608
  if (typeof record.entry === "string") metadata.entry = record.entry;
11609
11609
  return metadata;
11610
11610
  }
11611
- async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
11612
- const mdPath = path.join(pluginsRoot, folderName, "PLUGIN.md");
11611
+ async function loadPluginManifestFromMarkdown(pluginsRoot2, folderName) {
11612
+ const mdPath = path.join(pluginsRoot2, folderName, "PLUGIN.md");
11613
11613
  let raw;
11614
11614
  try {
11615
11615
  raw = await promises.readFile(mdPath, "utf8");
@@ -11619,7 +11619,7 @@ async function loadPluginManifestFromMarkdown(pluginsRoot, folderName) {
11619
11619
  cause
11620
11620
  });
11621
11621
  }
11622
- const fakeDir = path.join(pluginsRoot, folderName);
11622
+ const fakeDir = path.join(pluginsRoot2, folderName);
11623
11623
  const entities = await loadMarkdownEntities({
11624
11624
  dir: fakeDir,
11625
11625
  schema: PluginFrontmatterSchema,
@@ -14635,6 +14635,103 @@ function registerBuiltins() {
14635
14635
  registerProvider(CEREBRAS);
14636
14636
  registerCatalogProviders();
14637
14637
  }
14638
+ function globalSingleton3(key2, create) {
14639
+ const g = globalThis;
14640
+ const sym = Symbol.for(key2);
14641
+ if (g[sym] === void 0) g[sym] = create();
14642
+ return g[sym];
14643
+ }
14644
+ var discoveryState = globalSingleton3("theokit-sdk.providers.discovered", () => ({
14645
+ done: false
14646
+ }));
14647
+ function pluginsRoot() {
14648
+ return path.join(os.homedir(), ".theokit", "plugins", "model-providers");
14649
+ }
14650
+ function trustFilePath() {
14651
+ return path.join(os.homedir(), ".theokit", "plugins", "trusted-providers.json");
14652
+ }
14653
+ function loadTrustedNames() {
14654
+ const trusted = /* @__PURE__ */ new Set();
14655
+ const path = trustFilePath();
14656
+ if (fs.existsSync(path)) {
14657
+ try {
14658
+ const parsed = JSON.parse(fs.readFileSync(path, "utf-8"));
14659
+ if (Array.isArray(parsed)) {
14660
+ let discarded = 0;
14661
+ for (const name of parsed) {
14662
+ if (typeof name === "string" && name.length > 0) trusted.add(name);
14663
+ else discarded += 1;
14664
+ }
14665
+ if (discarded > 0) {
14666
+ process.stderr.write(
14667
+ `[theokit-sdk] WARN: ${path} contains ${discarded} non-string entr${discarded === 1 ? "y" : "ies"} \u2014 discarded (entries must be plugin-name strings)
14668
+ `
14669
+ );
14670
+ }
14671
+ } else {
14672
+ process.stderr.write(
14673
+ `[theokit-sdk] WARN: ${path} is not a JSON array \u2014 trusting NO provider plugins (fail-closed)
14674
+ `
14675
+ );
14676
+ }
14677
+ } catch {
14678
+ process.stderr.write(
14679
+ `[theokit-sdk] WARN: ${path} is not valid JSON \u2014 trusting NO provider plugins (fail-closed)
14680
+ `
14681
+ );
14682
+ }
14683
+ }
14684
+ for (const name of (process.env.THEOKIT_TRUSTED_PROVIDERS ?? "").split(",")) {
14685
+ const trimmed = name.trim();
14686
+ if (trimmed.length > 0) trusted.add(trimmed);
14687
+ }
14688
+ return trusted;
14689
+ }
14690
+ async function discoverProviderPlugins() {
14691
+ if (discoveryState.done) return;
14692
+ discoveryState.done = true;
14693
+ const root = pluginsRoot();
14694
+ if (!fs.existsSync(root)) return;
14695
+ let entries;
14696
+ try {
14697
+ entries = await promises.readdir(root);
14698
+ } catch {
14699
+ return;
14700
+ }
14701
+ const trusted = loadTrustedNames();
14702
+ for (const entry of entries) {
14703
+ if (!trusted.has(entry)) {
14704
+ process.stderr.write(
14705
+ `[theokit-sdk] WARN: provider plugin "${entry}" is present but NOT trusted \u2014 skipped. To trust it, add "${entry}" to ${trustFilePath()} (JSON array of names) or THEOKIT_TRUSTED_PROVIDERS (comma-separated), then restart the process.
14706
+ `
14707
+ );
14708
+ continue;
14709
+ }
14710
+ await loadOne(path.join(root, entry), entry);
14711
+ }
14712
+ }
14713
+ async function loadOne(dir, entryName) {
14714
+ for (const ext of ["index.mjs", "index.js"]) {
14715
+ const indexPath = path.join(dir, ext);
14716
+ if (!fs.existsSync(indexPath)) continue;
14717
+ try {
14718
+ const mod = await import(url.pathToFileURL(indexPath).href);
14719
+ const plugin = mod.default ?? mod[entryName] ?? mod;
14720
+ if (plugin !== null && typeof plugin === "object" && plugin.kind === "model-provider") {
14721
+ const profile = plugin.profile;
14722
+ if (profile !== void 0 && typeof profile === "object") {
14723
+ registerProvider(profile);
14724
+ }
14725
+ }
14726
+ return;
14727
+ } catch (err) {
14728
+ const msg = err instanceof Error ? err.message : String(err);
14729
+ process.stderr.write(`[theokit-sdk] failed to load provider plugin "${entryName}": ${msg}
14730
+ `);
14731
+ return;
14732
+ }
14733
+ }
14734
+ }
14638
14735
 
14639
14736
  // src/internal/llm/anthropic.ts
14640
14737
  init_errors();
@@ -20237,6 +20334,7 @@ function resolveAgentPersistenceCwd(options) {
20237
20334
  return process.cwd();
20238
20335
  }
20239
20336
  async function rehydrateExistingAgent(agentId, existing, options) {
20337
+ await discoverProviderPlugins();
20240
20338
  await validateRehydratedAgent(agentId, existing);
20241
20339
  const mergedLocal = options.local !== void 0 && existing.options.local !== void 0 ? { ...existing.options.local, ...options.local } : options.local ?? existing.options.local;
20242
20340
  const mergedOptions = {
@@ -20366,6 +20464,7 @@ var Agent = class _Agent {
20366
20464
  pluginCount: enabledPluginNames(options.plugins).length
20367
20465
  });
20368
20466
  try {
20467
+ await discoverProviderPlugins();
20369
20468
  const agent = await runCreateUnderSpan(options, span);
20370
20469
  return agent;
20371
20470
  } catch (err) {
@@ -23314,6 +23413,7 @@ var Theokit = class {
23314
23413
  };
23315
23414
  async function maybeListLocalModels(providerName) {
23316
23415
  registerBuiltins();
23416
+ await discoverProviderPlugins();
23317
23417
  const profile = getProviderProfile(providerName);
23318
23418
  if (profile === void 0) return void 0;
23319
23419
  if (profile.authType !== "none") return void 0;