@mrciphersmith/keryx 0.2.28 → 0.2.31

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 (2) hide show
  1. package/dist/cli.js +54 -159
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -41118,7 +41118,7 @@ var AGENT_SLASH_COMMANDS = [
41118
41118
  description: "Switch provider / API key",
41119
41119
  modes: BOTH,
41120
41120
  modeDescriptions: {
41121
- agent: "Switch connected provider (interactive picker)",
41121
+ agent: "Connect to an already configured provider (interactive picker)",
41122
41122
  chat: "Show how to set a provider API key in the environment"
41123
41123
  }
41124
41124
  },
@@ -41130,16 +41130,6 @@ var AGENT_SLASH_COMMANDS = [
41130
41130
  agent: "Add or configure a provider (interactive picker)"
41131
41131
  }
41132
41132
  },
41133
- {
41134
- name: "/search-provider",
41135
- description: "Configure or edit a web search provider",
41136
- modes: AGENT_ONLY
41137
- },
41138
- {
41139
- name: "/search-connect",
41140
- description: "Select an active tested web search provider",
41141
- modes: AGENT_ONLY
41142
- },
41143
41133
  { name: "/think", description: "Expand the last reasoning block", modes: AGENT_ONLY },
41144
41134
  { name: "/expand", description: "Expand the last tool output block", modes: AGENT_ONLY },
41145
41135
  {
@@ -44063,6 +44053,42 @@ function resolveSidebarMetadata(cwd) {
44063
44053
  } catch {}
44064
44054
  return { branch };
44065
44055
  }
44056
+ async function filterConnectedDetectedProviders(detected, options = {}) {
44057
+ const fetchFn = options.fetch ?? globalThis.fetch;
44058
+ const env = options.env ?? process.env;
44059
+ const connected = [];
44060
+ for (const prov of detected) {
44061
+ const registry = providerByName(prov.name);
44062
+ if (registry === undefined) {
44063
+ connected.push(prov);
44064
+ continue;
44065
+ }
44066
+ const requiresApiKey = registry.requiresApiKey ?? true;
44067
+ const envKey = prov.envKey ?? registry.envKey;
44068
+ if (!requiresApiKey || envKey === undefined) {
44069
+ connected.push(prov);
44070
+ continue;
44071
+ }
44072
+ const raw = env[envKey];
44073
+ if (raw === undefined || raw.length === 0) {
44074
+ continue;
44075
+ }
44076
+ const compat = {
44077
+ ...registry,
44078
+ ...prov.baseUrl !== undefined ? { baseUrl: prov.baseUrl } : {},
44079
+ ...prov.chatPath !== undefined ? { chatPath: prov.chatPath } : {},
44080
+ ...prov.modelsPath !== undefined ? { modelsPath: prov.modelsPath } : {}
44081
+ };
44082
+ const result = await fetchOpenAiCompatModelsDetailed(fetchFn, compat, raw, {
44083
+ timeoutMs: MODELS_FETCH_TIMEOUT_MS
44084
+ });
44085
+ if (result.source !== "live" || result.models.length === 0) {
44086
+ continue;
44087
+ }
44088
+ connected.push(prov);
44089
+ }
44090
+ return connected;
44091
+ }
44066
44092
  function createTuiAgentIo(otui, renderer, transcript) {
44067
44093
  let seq = 0;
44068
44094
  const append = (content) => {
@@ -44315,34 +44341,6 @@ function onKeypress3(r, handler) {
44315
44341
  r._internalKeyInput.onInternal("keypress", handler);
44316
44342
  return () => r._internalKeyInput.offInternal("keypress", handler);
44317
44343
  }
44318
- function promptTextStep(otui, r, opts) {
44319
- return new Promise((resolve3) => {
44320
- const box = overlayBox(otui, r, "search-field-picker");
44321
- r.root.add(box);
44322
- box.add(new otui.TextRenderable(r, { id: "sf-title", content: otui.t`${otui.bold(opts.title)} ${otui.dim("(Enter \xB7 Esc to cancel)")}` }));
44323
- box.add(new otui.TextRenderable(r, { id: "sf-note", content: otui.t`${otui.dim(opts.note)}`, marginTop: 1 }));
44324
- const field3 = new otui.InputRenderable(r, { id: "sf-input", value: opts.value, marginTop: 1 });
44325
- box.add(field3);
44326
- field3.focus();
44327
- const cleanup = () => {
44328
- unsub();
44329
- r.root.remove(box);
44330
- };
44331
- const unsub = onKeypress3(r, (key) => {
44332
- if (key.name === "escape") {
44333
- cleanup();
44334
- resolve3(undefined);
44335
- key.preventDefault();
44336
- key.stopPropagation();
44337
- }
44338
- });
44339
- field3.on(otui.InputRenderableEvents.ENTER, () => {
44340
- const value = field3.value.trim();
44341
- cleanup();
44342
- resolve3(value.length > 0 ? value : undefined);
44343
- });
44344
- });
44345
- }
44346
44344
  function promptBaseUrlStep(otui, r, label, baseUrl2) {
44347
44345
  return new Promise((resolve3) => {
44348
44346
  const box = overlayBox(otui, r, "base-url-picker");
@@ -44444,15 +44442,24 @@ function pickProviderStep(otui, r, detected) {
44444
44442
  });
44445
44443
  });
44446
44444
  }
44447
- function selectProviderModelInTui(otui, r, detected) {
44445
+ function selectProviderModelInTui(otui, r, detected, options = {}) {
44448
44446
  return new Promise((resolve3) => {
44449
44447
  if (detected.length === 0) {
44450
44448
  resolve3(undefined);
44451
44449
  return;
44452
44450
  }
44451
+ const candidatesPromise = options.onlyConnected ? filterConnectedDetectedProviders(detected, {
44452
+ ...options.fetch !== undefined ? { fetch: options.fetch } : {},
44453
+ ...options.env !== undefined ? { env: options.env } : {}
44454
+ }) : Promise.resolve(detected);
44453
44455
  (async () => {
44456
+ const candidates = await candidatesPromise;
44457
+ if (candidates.length === 0) {
44458
+ resolve3(undefined);
44459
+ return;
44460
+ }
44454
44461
  while (true) {
44455
- const prov = await pickProviderStep(otui, r, detected);
44462
+ const prov = await pickProviderStep(otui, r, candidates);
44456
44463
  if (prov === undefined) {
44457
44464
  resolve3(undefined);
44458
44465
  return;
@@ -44465,7 +44472,7 @@ function selectProviderModelInTui(otui, r, detected) {
44465
44472
  saveProviderBaseUrl(prov.name, selectedBaseUrl);
44466
44473
  const selectedProvider = selectedBaseUrl === undefined ? prov : { ...prov, baseUrl: selectedBaseUrl };
44467
44474
  const envKey = prov.envKey;
44468
- if (envKey !== undefined) {
44475
+ if (!options.onlyConnected && envKey !== undefined) {
44469
44476
  const existingKey = process.env[envKey];
44470
44477
  if (existingKey === undefined || existingKey.length === 0) {
44471
44478
  const kr = await promptApiKeyStep(otui, r, { label: prov.label ?? prov.name, envKey });
@@ -45501,103 +45508,6 @@ Staying in the current session.
45501
45508
  }
45502
45509
  return;
45503
45510
  }
45504
- if (command.name === "/search-provider") {
45505
- if (opts.searchController === undefined) {
45506
- io.onSystem?.(`Web search configuration is unavailable in this shell.
45507
- `);
45508
- return;
45509
- }
45510
- (async () => {
45511
- const descriptors = opts.searchController.configurable();
45512
- const selected = await showComposerChoice(otui, r, chrome.dock, {
45513
- title: "Configure web search provider",
45514
- subtitle: "All supported providers are shown; only a successful test makes one selectable.",
45515
- options: descriptors.map((descriptor2) => ({
45516
- id: descriptor2.id,
45517
- label: descriptor2.displayName,
45518
- description: descriptor2.kind === "local" ? "Local loopback only" : "Remote HTTPS API",
45519
- recommended: descriptor2.id === "searxng"
45520
- })),
45521
- cancelId: "cancel"
45522
- });
45523
- if (selected === "cancel") {
45524
- input2.focus();
45525
- return;
45526
- }
45527
- const descriptor = descriptors.find((item) => item.id === selected);
45528
- if (descriptor === undefined) {
45529
- input2.focus();
45530
- return;
45531
- }
45532
- const fields = { ...descriptor.defaults };
45533
- if (descriptor.id === "searxng") {
45534
- const baseUrl2 = await promptTextStep(otui, r, {
45535
- title: "SearXNG URL",
45536
- note: "Default is local; only localhost, 127.0.0.1, or ::1 is permitted.",
45537
- value: fields.baseUrl ?? "http://localhost"
45538
- });
45539
- if (baseUrl2 === undefined) {
45540
- input2.focus();
45541
- return;
45542
- }
45543
- const port = await promptTextStep(otui, r, {
45544
- title: "SearXNG port",
45545
- note: "Default: 8080. Edit it when your local server uses another port.",
45546
- value: fields.port ?? "8080"
45547
- });
45548
- if (port === undefined) {
45549
- input2.focus();
45550
- return;
45551
- }
45552
- fields.baseUrl = baseUrl2;
45553
- fields.port = port;
45554
- opts.searchController.configure(descriptor.id, fields);
45555
- } else {
45556
- const key = await promptApiKeyStep(otui, r, { label: descriptor.displayName, envKey: "stored privately" });
45557
- if (key.kind !== "key") {
45558
- input2.focus();
45559
- return;
45560
- }
45561
- opts.searchController.configure(descriptor.id, fields, key.value);
45562
- }
45563
- const result = await opts.searchController.test(descriptor.id);
45564
- io.onSystem?.(result.ok ? `${descriptor.displayName} connected. Use /search-connect to make it active.
45565
- ` : `${descriptor.displayName} could not be connected (${result.reason ?? "unknown error"}).
45566
- `);
45567
- input2.focus();
45568
- })();
45569
- return;
45570
- }
45571
- if (command.name === "/search-connect") {
45572
- if (opts.searchController === undefined) {
45573
- io.onSystem?.(`Web search configuration is unavailable in this shell.
45574
- `);
45575
- return;
45576
- }
45577
- (async () => {
45578
- const connected = opts.searchController.selectable();
45579
- if (connected.length === 0) {
45580
- io.onSystem?.(`No tested search providers. Configure one with /search-provider first.
45581
- `);
45582
- input2.focus();
45583
- return;
45584
- }
45585
- const selected = await showComposerChoice(otui, r, chrome.dock, {
45586
- title: "Select web search provider",
45587
- subtitle: "Only successfully tested providers are available.",
45588
- options: connected.map((descriptor) => ({ id: descriptor.id, label: descriptor.displayName, description: descriptor.kind })),
45589
- cancelId: "cancel"
45590
- });
45591
- if (selected !== "cancel") {
45592
- const result = await opts.searchController.select(selected);
45593
- io.onSystem?.(result.ok ? `Web search provider selected.
45594
- ` : `Provider is no longer connected; test it again.
45595
- `);
45596
- }
45597
- input2.focus();
45598
- })();
45599
- return;
45600
- }
45601
45511
  if (command.name === "/model") {
45602
45512
  (async () => {
45603
45513
  const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
@@ -45620,27 +45530,13 @@ Staying in the current session.
45620
45530
  if (command.name === "/connect" || command.name === "/provider") {
45621
45531
  (async () => {
45622
45532
  const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
45623
- const candidates = command.name === "/provider" ? detected : (await Promise.all(detected.map(async (provider) => {
45624
- if (provider.name === "fake")
45625
- return;
45626
- if (provider.name === "rapid-mlx") {
45627
- return (await modelsForPicker(provider)).length > 0 ? provider : undefined;
45628
- }
45629
- if (provider.envKey !== undefined) {
45630
- return process.env[provider.envKey]?.length ? provider : undefined;
45631
- }
45632
- return provider;
45633
- }))).filter((provider) => provider !== undefined);
45634
- if (candidates.length === 0) {
45635
- io.onSystem?.(`No connected providers found. Use /provider to add or configure one.
45636
- `);
45637
- input2.focus();
45638
- return;
45639
- }
45640
- const ns = await chrome.withOverlay(() => selectProviderModelInTui(otui, r, candidates));
45533
+ const ns = await chrome.withOverlay(() => command.name === "/connect" ? selectProviderModelInTui(otui, r, detected, { onlyConnected: true, env: process.env }) : selectProviderModelInTui(otui, r, detected));
45641
45534
  if (ns !== undefined) {
45642
45535
  await switchTo(ns);
45643
45536
  } else {
45537
+ if (command.name === "/connect") {
45538
+ chrome.showToast("No connected providers found. Run /provider to configure one first.");
45539
+ }
45644
45540
  input2.focus();
45645
45541
  }
45646
45542
  })();
@@ -46155,7 +46051,7 @@ init_shell_config();
46155
46051
  // package.json
46156
46052
  var package_default = {
46157
46053
  name: "@mrciphersmith/keryx",
46158
- version: "0.2.28",
46054
+ version: "0.2.31",
46159
46055
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
46160
46056
  private: false,
46161
46057
  publishConfig: {
@@ -47433,7 +47329,6 @@ async function shellCommand(args2, runtime = {}) {
47433
47329
  } else if (await (runtime.launchAgent ?? launchTuiAgentShell)({
47434
47330
  detected: tuiDetected,
47435
47331
  makeAgentDeps,
47436
- searchController: searchProviderController,
47437
47332
  redetect,
47438
47333
  ...tuiInitial !== undefined ? { initial: tuiInitial } : {},
47439
47334
  session: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.2.28",
3
+ "version": "0.2.31",
4
4
  "description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
5
5
  "private": false,
6
6
  "publishConfig": {