agentful 0.4.3 → 0.4.4

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/index.cjs +78 -8
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -3044,7 +3044,7 @@ var VERSION, brand, useColor, wrap, paint, tuiDesign, sym, ui;
3044
3044
  var init_branding = __esm({
3045
3045
  "src/branding.ts"() {
3046
3046
  "use strict";
3047
- VERSION = "0.4.3" ? "0.4.3" : null.version;
3047
+ VERSION = "0.4.4" ? "0.4.4" : null.version;
3048
3048
  brand = {
3049
3049
  name: "agentful",
3050
3050
  // the command users type
@@ -7416,6 +7416,21 @@ function skillsInstructionFor(framework, rootDir) {
7416
7416
  }
7417
7417
 
7418
7418
  // src/lib/models.ts
7419
+ var OAUTH_BYOK_PROVIDER = "github-copilot";
7420
+ async function fetchCopilotAccountModels(auth) {
7421
+ try {
7422
+ const res = await request(
7423
+ `${PB_URL}/api/llm/copilot/models`,
7424
+ { token: auth.pb_token, timeoutMs: 15e3 }
7425
+ );
7426
+ return (res.models || []).map((m) => m?.id).filter((id) => !!id);
7427
+ } catch {
7428
+ return null;
7429
+ }
7430
+ }
7431
+ function supportsHostedModelInLocalEngine(id) {
7432
+ return !/^gemini-3(?:[.-]|$)/i.test(id.trim());
7433
+ }
7419
7434
  async function fetchModelCatalog(auth, fallback) {
7420
7435
  const regionDefaultsToBedrock = fallback.ai_region === "eu" || fallback.ai_region === "de";
7421
7436
  const isAgenticCapable = (id) => id !== "auto" && !id.includes("bedrock");
@@ -7429,8 +7444,8 @@ async function fetchModelCatalog(auth, fallback) {
7429
7444
  }
7430
7445
  if (!catalog?.models?.length) {
7431
7446
  return {
7432
- models: fallback.models.map((id) => ({ id, name: id })),
7433
- defaultModel: fallback.default_model,
7447
+ models: fallback.models.filter(supportsHostedModelInLocalEngine).map((id) => ({ id, name: id })),
7448
+ defaultModel: supportsHostedModelInLocalEngine(fallback.default_model) ? fallback.default_model : fallback.models.find(supportsHostedModelInLocalEngine) || "auto",
7434
7449
  byokProviders: [],
7435
7450
  canSelectModel: true,
7436
7451
  inactiveByok: []
@@ -7440,6 +7455,7 @@ async function fetchModelCatalog(auth, fallback) {
7440
7455
  let hasGenericByok = false;
7441
7456
  for (const m of catalog.models) {
7442
7457
  if (!m?.id) continue;
7458
+ if (!supportsHostedModelInLocalEngine(m.id)) continue;
7443
7459
  if (m.id === "byok") {
7444
7460
  if (m.has_active_keys) hasGenericByok = true;
7445
7461
  continue;
@@ -7448,6 +7464,7 @@ async function fetchModelCatalog(auth, fallback) {
7448
7464
  }
7449
7465
  const byokProviders = [];
7450
7466
  const inactiveByok = [];
7467
+ let byokNotice;
7451
7468
  if (catalog.byok_enabled && catalog.has_byok_keys) {
7452
7469
  try {
7453
7470
  const res = await request(`${PB_URL}/api/llm/byok`, {
@@ -7460,8 +7477,23 @@ async function fetchModelCatalog(auth, fallback) {
7460
7477
  inactiveByok.push({ provider: key.provider_type, models: key.models || [] });
7461
7478
  continue;
7462
7479
  }
7463
- byokProviders.push(key.provider_type);
7464
- for (const model of key.models || []) {
7480
+ const selection = key.models || [];
7481
+ let models = selection;
7482
+ if (key.provider_type === OAUTH_BYOK_PROVIDER) {
7483
+ const live = await fetchCopilotAccountModels(auth);
7484
+ if (live === null) {
7485
+ byokNotice = selection.length ? `${key.provider_type}: account model list unavailable \u2014 showing your stored selection.` : `${key.provider_type}: account model list unavailable \u2014 no own-key model in this session.`;
7486
+ } else if (!selection.length) {
7487
+ models = live;
7488
+ } else {
7489
+ models = selection.filter((m) => live.includes(m));
7490
+ if (!models.length) {
7491
+ byokNotice = `${key.provider_type}: none of your selected models is served by the account right now \u2014 re-select them in Settings \u2192 BYOK.`;
7492
+ }
7493
+ }
7494
+ }
7495
+ if (models.length) byokProviders.push(key.provider_type);
7496
+ for (const model of models) {
7465
7497
  entries.push({
7466
7498
  id: `byok/${key.provider_type}/${model}`,
7467
7499
  name: `${model} \xB7 your key (${key.provider_type})`,
@@ -7486,7 +7518,8 @@ async function fetchModelCatalog(auth, fallback) {
7486
7518
  defaultModel,
7487
7519
  byokProviders,
7488
7520
  canSelectModel: catalog.can_select_model !== false,
7489
- inactiveByok
7521
+ inactiveByok,
7522
+ byokNotice
7490
7523
  };
7491
7524
  }
7492
7525
 
@@ -7805,6 +7838,20 @@ async function listEngineModels(binPath, xdg, provider) {
7805
7838
  });
7806
7839
  return parseEngineModelsOutput(stdout);
7807
7840
  }
7841
+ async function refreshEngineModelCache(binPath, xdg) {
7842
+ await execFileAsync(binPath, ["models", "--refresh"], {
7843
+ env: {
7844
+ ...process.env,
7845
+ XDG_CONFIG_HOME: xdg.configHome,
7846
+ XDG_DATA_HOME: xdg.dataHome,
7847
+ XDG_STATE_HOME: xdg.stateHome,
7848
+ OPENCODE_DISABLE_AUTOUPDATE: "true"
7849
+ },
7850
+ encoding: "utf8",
7851
+ maxBuffer: 8 * 1024 * 1024,
7852
+ timeout: 6e4
7853
+ });
7854
+ }
7808
7855
  async function assertEngineModelAvailable(binPath, xdg, model, listModels = listEngineModels) {
7809
7856
  const provider = modelProvider(model);
7810
7857
  const models = await listModels(binPath, xdg, provider);
@@ -8199,6 +8246,9 @@ async function tuiCommand(opts = {}) {
8199
8246
  "Resume model metadata is not readable locally; the engine keeps the session model unchanged."
8200
8247
  ));
8201
8248
  }
8249
+ if (catalog.byokNotice) {
8250
+ ui.warn(catalog.byokNotice);
8251
+ }
8202
8252
  if (catalog.byokProviders.length) {
8203
8253
  ui.info(paint.dim(
8204
8254
  `Includes your own keys (${catalog.byokProviders.join(", ")}): billed by that provider` + (session.ai_region && session.ai_region !== "all" ? `, outside your "${session.ai_region}" region setting.` : ".")
@@ -8475,6 +8525,10 @@ async function licensesCommand() {
8475
8525
 
8476
8526
  // src/commands/models.ts
8477
8527
  init_branding();
8528
+ function describeInactiveModels(key) {
8529
+ if (key.models.length) return key.models.join(", ");
8530
+ return key.provider === OAUTH_BYOK_PROVIDER ? "all account models" : "(no model)";
8531
+ }
8478
8532
  async function modelsCommand(opts) {
8479
8533
  console.log(banner());
8480
8534
  const auth = await ensureAuth();
@@ -8492,18 +8546,30 @@ async function modelsCommand(opts) {
8492
8546
  const decision = decideLocalProviders(policy);
8493
8547
  const resolved = resolveLocalProviders(policy);
8494
8548
  const configured = Object.keys(readLocalProviders());
8549
+ if (catalog.byokNotice) {
8550
+ console.log("");
8551
+ ui.warn(catalog.byokNotice);
8552
+ }
8495
8553
  if (catalog.inactiveByok.length) {
8496
8554
  console.log("");
8497
8555
  console.log(paint.dim(" Configured but inactive (one own key can be active at a time \u2014"));
8498
8556
  console.log(paint.dim(" switch it in Settings \u2192 BYOK to use another):"));
8499
8557
  for (const k of catalog.inactiveByok) {
8500
- console.log(paint.dim(` \u25CB ${k.models.join(", ") || "(no model)"} \xB7 ${k.provider}`));
8558
+ console.log(paint.dim(` \u25CB ${describeInactiveModels(k)} \xB7 ${k.provider}`));
8501
8559
  }
8502
8560
  }
8503
8561
  const xdg = engineXdg();
8504
8562
  const connectedProviders = readConnectedEngineProviders(xdg);
8505
8563
  if (connectedProviders.length) {
8506
8564
  const binPath = await ensureEngine();
8565
+ if (opts.refresh) {
8566
+ try {
8567
+ await refreshEngineModelCache(binPath, xdg);
8568
+ ui.step("Refreshed the engine model cache from models.dev.");
8569
+ } catch {
8570
+ ui.warn("Engine model cache could not be refreshed \u2014 listing the cached catalog.");
8571
+ }
8572
+ }
8507
8573
  console.log("");
8508
8574
  console.log(paint.bold("Direct TUI connections") + paint.dim(" (provider billing/terms; outside Agentful credits and region controls)"));
8509
8575
  for (const provider of connectedProviders) {
@@ -8518,6 +8584,10 @@ async function modelsCommand(opts) {
8518
8584
  console.log(` ${paint.warn("!")} ${provider} ${paint.dim("\u2014 catalog could not be read")}`);
8519
8585
  }
8520
8586
  }
8587
+ } else if (opts.refresh) {
8588
+ console.log("");
8589
+ ui.info("No provider is connected directly in the TUI, so nothing is cached \u2014");
8590
+ ui.info("the Agentful catalog and your own keys are read live on every run.");
8521
8591
  }
8522
8592
  console.log("");
8523
8593
  console.log(paint.bold("Local providers") + paint.dim(" (your key, direct to the provider)"));
@@ -8635,7 +8705,7 @@ program2.command("tui").description("Start the Agentful coding TUI with your Age
8635
8705
  program2.command("publish <subdomain>").description("Publish the built project at https://<subdomain>.agentful.dev").action(run(publishCommand));
8636
8706
  program2.command("share").description("Make the live preview public (anyone with the link)").option("--private", "make the preview owner-only again").action(run((opts) => shareCommand(opts)));
8637
8707
  program2.command("pull").description("Download the cloud workspace into this directory").option("--force", "overwrite files in a non-empty directory").action(run((opts) => pullCommand(opts)));
8638
- program2.command("models").description("List available models and manage local providers with your own key").option("--add-local", "create/show the local provider file to edit").action(run((opts) => modelsCommand(opts)));
8708
+ program2.command("models").description("List available models and manage local providers with your own key").option("--add-local", "create/show the local provider file to edit").option("--refresh", "refresh the engine model cache from models.dev").action(run((opts) => modelsCommand(opts)));
8639
8709
  program2.command("upgrade").description("Update the CLI to the latest version").action(run(upgradeCommand));
8640
8710
  program2.command("licenses").description("Show licenses of the software distributed with this CLI").action(run(licensesCommand));
8641
8711
  program2.parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentful",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Agentful in your terminal — local development with push-to-cloud previews",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://agentful.dev",