@mrciphersmith/keryx 0.2.27 → 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 +58 -161
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -38944,7 +38944,8 @@ import { homedir as homedir5 } from "os";
38944
38944
  var WORKER_TIMEOUT_MS = 1e4;
38945
38945
  var MAX_WORKER_OUTPUT_BYTES = 192000;
38946
38946
  var WORKER_SOURCE = String.raw`
38947
- const { request } = await import("node:https");
38947
+ const { request: httpsRequest } = await import("node:https");
38948
+ const { request: httpRequest } = await import("node:http");
38948
38949
  const { isIP } = await import("node:net");
38949
38950
  const input = JSON.parse(await Bun.stdin.text());
38950
38951
  const fail = () => process.stdout.write(JSON.stringify({ ok: false, reason: "request failed or timed out" }));
@@ -38959,6 +38960,7 @@ try {
38959
38960
  }
38960
38961
  const encoded = payload ? JSON.stringify(payload) : undefined;
38961
38962
  if (encoded) { headers["content-type"] = "application/json"; headers["content-length"] = String(Buffer.byteLength(encoded)); }
38963
+ const request = input.url.startsWith("http:") ? httpRequest : httpsRequest;
38962
38964
  const req = request(input.url, {
38963
38965
  method: input.method,
38964
38966
  lookup: (_host, options, callback) => {
@@ -38969,7 +38971,7 @@ try {
38969
38971
  if (options && options.all) callback(null, [record]);
38970
38972
  else callback(null, record.address, record.family);
38971
38973
  },
38972
- servername: input.hostname,
38974
+ ...(input.url.startsWith("https:") ? { servername: input.hostname } : {}),
38973
38975
  headers,
38974
38976
  }, (res) => {
38975
38977
  const chunks = []; let size = 0;
@@ -41116,7 +41118,7 @@ var AGENT_SLASH_COMMANDS = [
41116
41118
  description: "Switch provider / API key",
41117
41119
  modes: BOTH,
41118
41120
  modeDescriptions: {
41119
- agent: "Switch connected provider (interactive picker)",
41121
+ agent: "Connect to an already configured provider (interactive picker)",
41120
41122
  chat: "Show how to set a provider API key in the environment"
41121
41123
  }
41122
41124
  },
@@ -41128,16 +41130,6 @@ var AGENT_SLASH_COMMANDS = [
41128
41130
  agent: "Add or configure a provider (interactive picker)"
41129
41131
  }
41130
41132
  },
41131
- {
41132
- name: "/search-provider",
41133
- description: "Configure or edit a web search provider",
41134
- modes: AGENT_ONLY
41135
- },
41136
- {
41137
- name: "/search-connect",
41138
- description: "Select an active tested web search provider",
41139
- modes: AGENT_ONLY
41140
- },
41141
41133
  { name: "/think", description: "Expand the last reasoning block", modes: AGENT_ONLY },
41142
41134
  { name: "/expand", description: "Expand the last tool output block", modes: AGENT_ONLY },
41143
41135
  {
@@ -44061,6 +44053,42 @@ function resolveSidebarMetadata(cwd) {
44061
44053
  } catch {}
44062
44054
  return { branch };
44063
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
+ }
44064
44092
  function createTuiAgentIo(otui, renderer, transcript) {
44065
44093
  let seq = 0;
44066
44094
  const append = (content) => {
@@ -44313,34 +44341,6 @@ function onKeypress3(r, handler) {
44313
44341
  r._internalKeyInput.onInternal("keypress", handler);
44314
44342
  return () => r._internalKeyInput.offInternal("keypress", handler);
44315
44343
  }
44316
- function promptTextStep(otui, r, opts) {
44317
- return new Promise((resolve3) => {
44318
- const box = overlayBox(otui, r, "search-field-picker");
44319
- r.root.add(box);
44320
- box.add(new otui.TextRenderable(r, { id: "sf-title", content: otui.t`${otui.bold(opts.title)} ${otui.dim("(Enter \xB7 Esc to cancel)")}` }));
44321
- box.add(new otui.TextRenderable(r, { id: "sf-note", content: otui.t`${otui.dim(opts.note)}`, marginTop: 1 }));
44322
- const field3 = new otui.InputRenderable(r, { id: "sf-input", value: opts.value, marginTop: 1 });
44323
- box.add(field3);
44324
- field3.focus();
44325
- const cleanup = () => {
44326
- unsub();
44327
- r.root.remove(box);
44328
- };
44329
- const unsub = onKeypress3(r, (key) => {
44330
- if (key.name === "escape") {
44331
- cleanup();
44332
- resolve3(undefined);
44333
- key.preventDefault();
44334
- key.stopPropagation();
44335
- }
44336
- });
44337
- field3.on(otui.InputRenderableEvents.ENTER, () => {
44338
- const value = field3.value.trim();
44339
- cleanup();
44340
- resolve3(value.length > 0 ? value : undefined);
44341
- });
44342
- });
44343
- }
44344
44344
  function promptBaseUrlStep(otui, r, label, baseUrl2) {
44345
44345
  return new Promise((resolve3) => {
44346
44346
  const box = overlayBox(otui, r, "base-url-picker");
@@ -44442,15 +44442,24 @@ function pickProviderStep(otui, r, detected) {
44442
44442
  });
44443
44443
  });
44444
44444
  }
44445
- function selectProviderModelInTui(otui, r, detected) {
44445
+ function selectProviderModelInTui(otui, r, detected, options = {}) {
44446
44446
  return new Promise((resolve3) => {
44447
44447
  if (detected.length === 0) {
44448
44448
  resolve3(undefined);
44449
44449
  return;
44450
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);
44451
44455
  (async () => {
44456
+ const candidates = await candidatesPromise;
44457
+ if (candidates.length === 0) {
44458
+ resolve3(undefined);
44459
+ return;
44460
+ }
44452
44461
  while (true) {
44453
- const prov = await pickProviderStep(otui, r, detected);
44462
+ const prov = await pickProviderStep(otui, r, candidates);
44454
44463
  if (prov === undefined) {
44455
44464
  resolve3(undefined);
44456
44465
  return;
@@ -44463,7 +44472,7 @@ function selectProviderModelInTui(otui, r, detected) {
44463
44472
  saveProviderBaseUrl(prov.name, selectedBaseUrl);
44464
44473
  const selectedProvider = selectedBaseUrl === undefined ? prov : { ...prov, baseUrl: selectedBaseUrl };
44465
44474
  const envKey = prov.envKey;
44466
- if (envKey !== undefined) {
44475
+ if (!options.onlyConnected && envKey !== undefined) {
44467
44476
  const existingKey = process.env[envKey];
44468
44477
  if (existingKey === undefined || existingKey.length === 0) {
44469
44478
  const kr = await promptApiKeyStep(otui, r, { label: prov.label ?? prov.name, envKey });
@@ -45499,103 +45508,6 @@ Staying in the current session.
45499
45508
  }
45500
45509
  return;
45501
45510
  }
45502
- if (command.name === "/search-provider") {
45503
- if (opts.searchController === undefined) {
45504
- io.onSystem?.(`Web search configuration is unavailable in this shell.
45505
- `);
45506
- return;
45507
- }
45508
- (async () => {
45509
- const descriptors = opts.searchController.configurable();
45510
- const selected = await showComposerChoice(otui, r, chrome.dock, {
45511
- title: "Configure web search provider",
45512
- subtitle: "All supported providers are shown; only a successful test makes one selectable.",
45513
- options: descriptors.map((descriptor2) => ({
45514
- id: descriptor2.id,
45515
- label: descriptor2.displayName,
45516
- description: descriptor2.kind === "local" ? "Local loopback only" : "Remote HTTPS API",
45517
- recommended: descriptor2.id === "searxng"
45518
- })),
45519
- cancelId: "cancel"
45520
- });
45521
- if (selected === "cancel") {
45522
- input2.focus();
45523
- return;
45524
- }
45525
- const descriptor = descriptors.find((item) => item.id === selected);
45526
- if (descriptor === undefined) {
45527
- input2.focus();
45528
- return;
45529
- }
45530
- const fields = { ...descriptor.defaults };
45531
- if (descriptor.id === "searxng") {
45532
- const baseUrl2 = await promptTextStep(otui, r, {
45533
- title: "SearXNG URL",
45534
- note: "Default is local; only localhost, 127.0.0.1, or ::1 is permitted.",
45535
- value: fields.baseUrl ?? "http://localhost"
45536
- });
45537
- if (baseUrl2 === undefined) {
45538
- input2.focus();
45539
- return;
45540
- }
45541
- const port = await promptTextStep(otui, r, {
45542
- title: "SearXNG port",
45543
- note: "Default: 8080. Edit it when your local server uses another port.",
45544
- value: fields.port ?? "8080"
45545
- });
45546
- if (port === undefined) {
45547
- input2.focus();
45548
- return;
45549
- }
45550
- fields.baseUrl = baseUrl2;
45551
- fields.port = port;
45552
- opts.searchController.configure(descriptor.id, fields);
45553
- } else {
45554
- const key = await promptApiKeyStep(otui, r, { label: descriptor.displayName, envKey: "stored privately" });
45555
- if (key.kind !== "key") {
45556
- input2.focus();
45557
- return;
45558
- }
45559
- opts.searchController.configure(descriptor.id, fields, key.value);
45560
- }
45561
- const result = await opts.searchController.test(descriptor.id);
45562
- io.onSystem?.(result.ok ? `${descriptor.displayName} connected. Use /search-connect to make it active.
45563
- ` : `${descriptor.displayName} could not be connected (${result.reason ?? "unknown error"}).
45564
- `);
45565
- input2.focus();
45566
- })();
45567
- return;
45568
- }
45569
- if (command.name === "/search-connect") {
45570
- if (opts.searchController === undefined) {
45571
- io.onSystem?.(`Web search configuration is unavailable in this shell.
45572
- `);
45573
- return;
45574
- }
45575
- (async () => {
45576
- const connected = opts.searchController.selectable();
45577
- if (connected.length === 0) {
45578
- io.onSystem?.(`No tested search providers. Configure one with /search-provider first.
45579
- `);
45580
- input2.focus();
45581
- return;
45582
- }
45583
- const selected = await showComposerChoice(otui, r, chrome.dock, {
45584
- title: "Select web search provider",
45585
- subtitle: "Only successfully tested providers are available.",
45586
- options: connected.map((descriptor) => ({ id: descriptor.id, label: descriptor.displayName, description: descriptor.kind })),
45587
- cancelId: "cancel"
45588
- });
45589
- if (selected !== "cancel") {
45590
- const result = await opts.searchController.select(selected);
45591
- io.onSystem?.(result.ok ? `Web search provider selected.
45592
- ` : `Provider is no longer connected; test it again.
45593
- `);
45594
- }
45595
- input2.focus();
45596
- })();
45597
- return;
45598
- }
45599
45511
  if (command.name === "/model") {
45600
45512
  (async () => {
45601
45513
  const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
@@ -45618,27 +45530,13 @@ Staying in the current session.
45618
45530
  if (command.name === "/connect" || command.name === "/provider") {
45619
45531
  (async () => {
45620
45532
  const detected = opts.redetect !== undefined ? await opts.redetect() : opts.detected;
45621
- const candidates = command.name === "/provider" ? detected : (await Promise.all(detected.map(async (provider) => {
45622
- if (provider.name === "fake")
45623
- return;
45624
- if (provider.name === "rapid-mlx") {
45625
- return (await modelsForPicker(provider)).length > 0 ? provider : undefined;
45626
- }
45627
- if (provider.envKey !== undefined) {
45628
- return process.env[provider.envKey]?.length ? provider : undefined;
45629
- }
45630
- return provider;
45631
- }))).filter((provider) => provider !== undefined);
45632
- if (candidates.length === 0) {
45633
- io.onSystem?.(`No connected providers found. Use /provider to add or configure one.
45634
- `);
45635
- input2.focus();
45636
- return;
45637
- }
45638
- 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));
45639
45534
  if (ns !== undefined) {
45640
45535
  await switchTo(ns);
45641
45536
  } else {
45537
+ if (command.name === "/connect") {
45538
+ chrome.showToast("No connected providers found. Run /provider to configure one first.");
45539
+ }
45642
45540
  input2.focus();
45643
45541
  }
45644
45542
  })();
@@ -46153,7 +46051,7 @@ init_shell_config();
46153
46051
  // package.json
46154
46052
  var package_default = {
46155
46053
  name: "@mrciphersmith/keryx",
46156
- version: "0.2.27",
46054
+ version: "0.2.31",
46157
46055
  description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
46158
46056
  private: false,
46159
46057
  publishConfig: {
@@ -47431,7 +47329,6 @@ async function shellCommand(args2, runtime = {}) {
47431
47329
  } else if (await (runtime.launchAgent ?? launchTuiAgentShell)({
47432
47330
  detected: tuiDetected,
47433
47331
  makeAgentDeps,
47434
- searchController: searchProviderController,
47435
47332
  redetect,
47436
47333
  ...tuiInitial !== undefined ? { initial: tuiInitial } : {},
47437
47334
  session: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrciphersmith/keryx",
3
- "version": "0.2.27",
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": {