@cmmd-center/forge 0.9.16 → 0.9.17

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/bin.mjs CHANGED
@@ -22,7 +22,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, createPublicK
22
22
  import * as FS$1 from "node:fs";
23
23
  import fs, { accessSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, mkdtempSync, promises, readFile, readFileSync, readdir, readdirSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
24
24
  import * as NodeOS from "node:os";
25
- import $U, { homedir, networkInterfaces, tmpdir } from "node:os";
25
+ import os, { homedir, networkInterfaces, tmpdir } from "node:os";
26
26
  import * as Path$1 from "node:path";
27
27
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
28
28
  import { pathToFileURL } from "node:url";
@@ -22164,6 +22164,40 @@ const ServerProviderAuth = Struct({
22164
22164
  accountEmail: optional$4(TrimmedNonEmptyString),
22165
22165
  provenance: optional$4(ProviderAuthProvenance)
22166
22166
  });
22167
+ /**
22168
+ * Whether this Environment will let a person select the provider.
22169
+ *
22170
+ * Published for every provider the build knows about. A provider is never
22171
+ * dropped from the list: absence is not a state, and four different reasons
22172
+ * once collapsed into one "Coming soon." string because the Shell had to infer
22173
+ * meaning from what was missing. See
22174
+ * `docs/adr/withheld-providers-carry-their-reason.md`.
22175
+ */
22176
+ const ProviderAvailability = Literals(["available", "unavailable"]);
22177
+ /**
22178
+ * Why a Withheld Provider is withheld. The four members are the glossary's,
22179
+ * in `CONTEXT.md` section "Provider availability": Unbuilt, Not Offered, Not
22180
+ * Usable, Not on this Environment. Only Unbuilt may read "Coming soon."
22181
+ *
22182
+ * An Environment can only ever report Unbuilt, Not Usable, or Not on this
22183
+ * Environment. Not Offered is a CMMD fact about the organization's Provider
22184
+ * Offer, which the Shell adds when it joins.
22185
+ */
22186
+ const ProviderUnavailableReason = Literals([
22187
+ "unbuilt",
22188
+ "not-offered",
22189
+ "not-usable",
22190
+ "not-on-this-environment"
22191
+ ]);
22192
+ /**
22193
+ * The Not Usable sub-case. It picks a second line of copy, not a fifth state,
22194
+ * which is why it is a separate field rather than three more reasons.
22195
+ */
22196
+ const ProviderUnavailableDetail = Literals([
22197
+ "no-connection",
22198
+ "delivery-pending",
22199
+ "reconnect-required"
22200
+ ]);
22167
22201
  const ServerProviderModel = Struct({
22168
22202
  slug: TrimmedNonEmptyString,
22169
22203
  name: TrimmedNonEmptyString,
@@ -22195,6 +22229,9 @@ const ServerProvider = Struct({
22195
22229
  checkedAt: IsoDateTime,
22196
22230
  message: optional$4(TrimmedNonEmptyString),
22197
22231
  models: ArraySchema(ServerProviderModel),
22232
+ availability: optional$4(ProviderAvailability),
22233
+ unavailableReason: optional$4(ProviderUnavailableReason),
22234
+ unavailableDetail: optional$4(ProviderUnavailableDetail),
22198
22235
  slashCommands: ArraySchema(ServerProviderSlashCommand).pipe(withDecodingDefault(succeed([]))),
22199
22236
  skills: ArraySchema(ServerProviderSkill).pipe(withDecodingDefault(succeed([])))
22200
22237
  });
@@ -49482,7 +49519,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
49482
49519
  const min = forceColor || 0;
49483
49520
  if (env.TERM === "dumb") return min;
49484
49521
  if (process$1.platform === "win32") {
49485
- const osRelease = $U.release().split(".");
49522
+ const osRelease = os.release().split(".");
49486
49523
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
49487
49524
  return 1;
49488
49525
  }
@@ -51925,7 +51962,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
51925
51962
  exports.processDetector = void 0;
51926
51963
  const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
51927
51964
  const semconv_1 = require_semconv$1();
51928
- const os$3 = __require("os");
51965
+ const os$4 = __require("os");
51929
51966
  /**
51930
51967
  * ProcessDetector will be used to detect the resources related current process running
51931
51968
  * and being instrumented from the NodeJS Process module.
@@ -51947,7 +51984,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
51947
51984
  };
51948
51985
  if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
51949
51986
  try {
51950
- const userInfo = os$3.userInfo();
51987
+ const userInfo = os$4.userInfo();
51951
51988
  attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
51952
51989
  } catch (e) {
51953
51990
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -64870,7 +64907,7 @@ function normalizeNumberish(value) {
64870
64907
  }
64871
64908
  //#endregion
64872
64909
  //#region package.json
64873
- var version$1 = "0.9.16";
64910
+ var version$1 = "0.9.17";
64874
64911
  //#endregion
64875
64912
  //#region src/sentry.ts
64876
64913
  const SERVER_APP_NAME = "forge-server";
@@ -73500,7 +73537,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
73500
73537
  var fs$6 = __require("fs");
73501
73538
  var path$5 = __require("path");
73502
73539
  var url$1 = __require("url");
73503
- var os$2 = __require("os");
73540
+ var os$3 = __require("os");
73504
73541
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
73505
73542
  var vars = process.config && process.config.variables || {};
73506
73543
  var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
@@ -73508,8 +73545,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
73508
73545
  var abi = versions.modules;
73509
73546
  if (versions.deno || process.isBun) abi = "unsupported";
73510
73547
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
73511
- var arch = process.env.npm_config_arch || os$2.arch();
73512
- var platform = process.env.npm_config_platform || os$2.platform();
73548
+ var arch = process.env.npm_config_arch || os$3.arch();
73549
+ var platform = process.env.npm_config_platform || os$3.platform();
73513
73550
  var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
73514
73551
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
73515
73552
  var uv = (versions.uv || "").split(".")[0];
@@ -91167,7 +91204,7 @@ const launchDetached = (launch) => gen(function* () {
91167
91204
  });
91168
91205
  const OpenLive = effect(Open, gen(function* () {
91169
91206
  const open = yield* tryPromise({
91170
- try: () => import("./open-D8mGyWmt.mjs"),
91207
+ try: () => import("./open-FIgTDosf.mjs"),
91171
91208
  catch: (cause) => new OpenError$1({
91172
91209
  message: "failed to load browser opener",
91173
91210
  cause
@@ -184380,7 +184417,7 @@ var Vce = {
184380
184417
  function Ve() {
184381
184418
  return Vce;
184382
184419
  }
184383
- var Us = $U.homedir(), lk = $U.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
184420
+ var Us = os.homedir(), lk = os.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
184384
184421
  let t = path.join(Us, "Library");
184385
184422
  return {
184386
184423
  data: path.join(t, "Application Support", e),
@@ -194580,12 +194617,12 @@ function qZ(e, t) {
194580
194617
  }
194581
194618
  return n;
194582
194619
  }
194583
- var os$1 = "https://code.claude.com/docs/en", kKe = [
194620
+ var os$2 = "https://code.claude.com/docs/en", kKe = [
194584
194621
  {
194585
194622
  matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
194586
194623
  tip: {
194587
194624
  suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
194588
- docLink: `${os$1}/iam#permission-modes`
194625
+ docLink: `${os$2}/iam#permission-modes`
194589
194626
  }
194590
194627
  },
194591
194628
  {
@@ -194600,7 +194637,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
194600
194637
  matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
194601
194638
  tip: {
194602
194639
  suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
194603
- docLink: `${os$1}/settings#environment-variables`
194640
+ docLink: `${os$2}/settings#environment-variables`
194604
194641
  }
194605
194642
  },
194606
194643
  {
@@ -194611,14 +194648,14 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
194611
194648
  matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
194612
194649
  tip: {
194613
194650
  suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
194614
- docLink: `${os$1}/hooks`
194651
+ docLink: `${os$2}/hooks`
194615
194652
  }
194616
194653
  },
194617
194654
  {
194618
194655
  matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
194619
194656
  tip: {
194620
194657
  suggestion: "Command hooks require `command`. For exec form (no shell), set `command` to the executable and `args` to its arguments: {\"type\": \"command\", \"command\": \"echo\", \"args\": [\"hi\"]}. For shell form, set `command` to the full shell string: {\"type\": \"command\", \"command\": \"echo hi\"}.",
194621
- docLink: `${os$1}/hooks#exec-form-and-shell-form`
194658
+ docLink: `${os$2}/hooks#exec-form-and-shell-form`
194622
194659
  }
194623
194660
  },
194624
194661
  {
@@ -194633,7 +194670,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
194633
194670
  matches: (e) => e.code === "unrecognized_keys",
194634
194671
  tip: {
194635
194672
  suggestion: "Check for typos or refer to the documentation for valid fields",
194636
- docLink: `${os$1}/settings`
194673
+ docLink: `${os$2}/settings`
194637
194674
  }
194638
194675
  },
194639
194676
  {
@@ -194648,13 +194685,13 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
194648
194685
  matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
194649
194686
  tip: {
194650
194687
  suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
194651
- docLink: `${os$1}/iam#working-directories`
194688
+ docLink: `${os$2}/iam#working-directories`
194652
194689
  }
194653
194690
  }
194654
194691
  ], AKe = {
194655
- permissions: `${os$1}/iam#configuring-permissions`,
194656
- env: `${os$1}/settings#environment-variables`,
194657
- hooks: `${os$1}/hooks`
194692
+ permissions: `${os$2}/iam#configuring-permissions`,
194693
+ env: `${os$2}/settings#environment-variables`,
194694
+ hooks: `${os$2}/hooks`
194658
194695
  };
194659
194696
  function GZ(e) {
194660
194697
  let t = kKe.find((r) => r.matches(e));
@@ -258907,7 +258944,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
258907
258944
  var dgram = __require("dgram");
258908
258945
  var thunky = require_thunky();
258909
258946
  var events = __require("events");
258910
- var os = __require("os");
258947
+ var os$1 = __require("os");
258911
258948
  var noop = function() {};
258912
258949
  module.exports = function(opts) {
258913
258950
  if (!opts) opts = {};
@@ -259038,14 +259075,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
259038
259075
  return that;
259039
259076
  };
259040
259077
  function defaultInterface() {
259041
- var networks = os.networkInterfaces();
259078
+ var networks = os$1.networkInterfaces();
259042
259079
  var names = Object.keys(networks);
259043
259080
  for (var i = 0; i < names.length; i++) {
259044
259081
  var net = networks[names[i]];
259045
259082
  for (var j = 0; j < net.length; j++) {
259046
259083
  var iface = net[j];
259047
259084
  if (isIPv4(iface.family) && !iface.internal) {
259048
- if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
259085
+ if (os$1.platform() === "darwin" && names[i] === "en0") return iface.address;
259049
259086
  return "0.0.0.0";
259050
259087
  }
259051
259088
  }
@@ -259053,7 +259090,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
259053
259090
  return "127.0.0.1";
259054
259091
  }
259055
259092
  function allInterfaces() {
259056
- var networks = os.networkInterfaces();
259093
+ var networks = os$1.networkInterfaces();
259057
259094
  var names = Object.keys(networks);
259058
259095
  var res = [];
259059
259096
  for (var i = 0; i < names.length; i++) {
@@ -284577,14 +284614,87 @@ const writeProviderStatusCache = (input) => {
284577
284614
  })));
284578
284615
  };
284579
284616
  //#endregion
284580
- //#region src/provider/Layers/ProviderRegistry.ts
284617
+ //#region ../../packages/shared/src/providerExecution.ts
284618
+ /**
284619
+ * Canonical provider-readiness gate for starting work.
284620
+ *
284621
+ * Cloud user VMs can execute through Forge's scoped provider proxy without a
284622
+ * provider-local login. In that case the provider reports unauthenticated but
284623
+ * its credential provenance is explicitly `proxied`.
284624
+ */
284625
+ function isServerProviderExecutable(provider) {
284626
+ const hasExecutionAuthority = provider.auth.status !== "unauthenticated" || provider.auth.provenance?.credentialScope === "proxied";
284627
+ return provider.enabled && provider.installed && provider.status === "ready" && hasExecutionAuthority && provider.models.length > 0;
284628
+ }
284629
+ //#endregion
284630
+ //#region src/provider/providerAvailability.ts
284581
284631
  /**
284582
- * Providers surfaced in the UI but lacking a dedicated detection Layer.
284583
- * Every provider now has a real Layer; this array stays as a (currently
284584
- * empty) hook for any future provider that ships in the UI before its
284585
- * server-side detection lands.
284632
+ * Derive what this Environment knows about a provider's availability.
284633
+ *
284634
+ * WHY THIS EXISTS
284635
+ *
284636
+ * Four different states (Unbuilt, Not Offered, Not Usable, Not on this
284637
+ * Environment) used to render as one "Coming soon." string, because consumers
284638
+ * were handed a filtered list and had to infer meaning from what was missing.
284639
+ * Every provider is now published with an explicit availability and, when
284640
+ * withheld, its reason. See `docs/adr/withheld-providers-carry-their-reason.md`
284641
+ * and the glossary in `CONTEXT.md` section "Provider availability".
284642
+ *
284643
+ * WHAT AN ENVIRONMENT MAY SAY
284644
+ *
284645
+ * Three of the four reasons only. Not Offered is a fact about the CMMD
284646
+ * organization's Provider Offer, and delivery-pending is a fact about a
284647
+ * credential in flight; neither is visible from inside an Environment, so the
284648
+ * Shell adds them when it joins. Nothing here may invent them.
284649
+ *
284650
+ * This reads the snapshot a provider Layer already produced. It runs no probe
284651
+ * and changes no probe: `isServerProviderExecutable` stays the single gate on
284652
+ * whether a turn can be dispatched, and this restates its answer in the
284653
+ * vocabulary a person sees.
284586
284654
  */
284587
- const STUB_PROVIDERS = [];
284655
+ /**
284656
+ * Providers Forge ships in the UI but cannot execute, published as Unbuilt.
284657
+ *
284658
+ * Empty in this build: codex, claudeAgent, ollama, cmmd, apex, cursor and
284659
+ * opencode all have a real detection Layer and a registered adapter. The list
284660
+ * stays as the one place a provider that ships ahead of its server-side
284661
+ * implementation is named, so "Coming soon." is a deliberate entry rather than
284662
+ * a fallback something fell into.
284663
+ */
284664
+ const UNBUILT_PROVIDERS = [];
284665
+ function deriveProviderAvailability(provider, unbuiltProviders = UNBUILT_PROVIDERS) {
284666
+ if (unbuiltProviders.includes(provider.provider)) return {
284667
+ availability: "unavailable",
284668
+ unavailableReason: "unbuilt"
284669
+ };
284670
+ if (isServerProviderExecutable(provider)) return { availability: "available" };
284671
+ const hasProxiedCredential = provider.auth.provenance?.credentialScope === "proxied";
284672
+ if (provider.installed && provider.auth.status === "unauthenticated" && !hasProxiedCredential) return {
284673
+ availability: "unavailable",
284674
+ unavailableReason: "not-usable",
284675
+ unavailableDetail: "no-connection"
284676
+ };
284677
+ return {
284678
+ availability: "unavailable",
284679
+ unavailableReason: "not-on-this-environment"
284680
+ };
284681
+ }
284682
+ /**
284683
+ * Stamp a snapshot with its derived availability.
284684
+ *
284685
+ * The previous fields are dropped before the new ones are applied. Merging
284686
+ * would leave a provider that just connected reporting `available` while still
284687
+ * carrying the reason it was withheld for.
284688
+ */
284689
+ function withProviderAvailability(provider, unbuiltProviders = UNBUILT_PROVIDERS) {
284690
+ const { availability: _availability, unavailableReason: _unavailableReason, unavailableDetail: _unavailableDetail, ...rest } = provider;
284691
+ return {
284692
+ ...rest,
284693
+ ...deriveProviderAvailability(provider, unbuiltProviders)
284694
+ };
284695
+ }
284696
+ //#endregion
284697
+ //#region src/provider/Layers/ProviderRegistry.ts
284588
284698
  const loadProviders = (codexProvider, claudeProvider, ollamaProvider, cmmdProvider, apexProvider, cursorProvider, opencodeProvider) => all([
284589
284699
  codexProvider.getSnapshot,
284590
284700
  claudeProvider.getSnapshot,
@@ -284621,9 +284731,9 @@ const ProviderRegistryLive = effect(ProviderRegistry, gen(function* () {
284621
284731
  cachedProvider,
284622
284732
  fallbackProvider
284623
284733
  });
284624
- return STUB_PROVIDERS.includes(provider) ? fallbackProvider : void 0;
284734
+ return UNBUILT_PROVIDERS.includes(provider) ? fallbackProvider : void 0;
284625
284735
  }));
284626
- }, { concurrency: "unbounded" }).pipe(map$3((providers) => orderProviderSnapshots(providers.filter((provider) => provider !== void 0)))));
284736
+ }, { concurrency: "unbounded" }).pipe(map$3((providers) => orderProviderSnapshots(providers.filter((provider) => provider !== void 0).map((provider) => withProviderAvailability(provider))))));
284627
284737
  const persistProvider = (provider) => writeProviderStatusCache({
284628
284738
  filePath: cachePathByProvider.get(provider.provider),
284629
284739
  provider
@@ -284631,7 +284741,8 @@ const ProviderRegistryLive = effect(ProviderRegistry, gen(function* () {
284631
284741
  provider: provider.provider,
284632
284742
  error
284633
284743
  })), ignore);
284634
- const upsertProviders = fn$1("upsertProviders")(function* (nextProviders, options) {
284744
+ const upsertProviders = fn$1("upsertProviders")(function* (incomingProviders, options) {
284745
+ const nextProviders = incomingProviders.map((provider) => withProviderAvailability(provider));
284635
284746
  const [previousProviders, providers] = yield* modify$3(providersRef, (previousProviders) => {
284636
284747
  const mergedProviders = new Map(previousProviders.map((provider) => [provider.provider, provider]));
284637
284748
  for (const provider of nextProviders) mergedProviders.set(provider.provider, provider);
@@ -287392,7 +287503,7 @@ function resolveBuildCommitFromEnv(env) {
287392
287503
  * environment descriptor down instead of reporting an honest "unknown".
287393
287504
  */
287394
287505
  function readBakedBuildCommit() {
287395
- return "e65edd4d1b8a361863a52b171b5e73295d691e11";
287506
+ return "86c71b55bb7a5dfbbad063d6e4c082570759f006";
287396
287507
  }
287397
287508
  async function resolveServerBuildCommit(input) {
287398
287509
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -300054,21 +300165,24 @@ function processRuntimeReplicationOutboxItem(item, dependencies) {
300054
300165
  //#endregion
300055
300166
  //#region src/runtimeReplication/Services/ActiveHourMeter.ts
300056
300167
  var ActiveHourMeter = class extends Service$1()("forge/runtimeReplication/Services/ActiveHourMeter") {};
300057
- //#endregion
300058
- //#region ../../packages/shared/src/providerExecution.ts
300168
+ /** `slug` and `name` are `.min(1).max(512)` on the receiving schema. */
300169
+ const FIELD_MAX_LENGTH = 512;
300170
+ /** `version` is `.max(128)` on the receiving schema, with no length floor. */
300171
+ const VERSION_MAX_LENGTH = 128;
300172
+ /** `binaryPath` is `.max(2048)` on the receiving schema, with no length floor. */
300173
+ const BINARY_PATH_MAX_LENGTH = 2048;
300059
300174
  /**
300060
- * Canonical provider-readiness gate for starting work.
300175
+ * Trim to the receiving schema's maximum, or null.
300061
300176
  *
300062
- * Cloud user VMs can execute through Forge's scoped provider proxy without a
300063
- * provider-local login. In that case the provider reports unauthenticated but
300064
- * its credential provenance is explicitly `proxied`.
300177
+ * Neither field has a length floor, so an empty string would be legal — but it
300178
+ * is not an answer. A version nobody resolved and a binary nobody found are
300179
+ * both null, which is what the control plane stores and what a reader can tell
300180
+ * apart from a real value.
300065
300181
  */
300066
- function isServerProviderExecutable(provider) {
300067
- const hasExecutionAuthority = provider.auth.status !== "unauthenticated" || provider.auth.provenance?.credentialScope === "proxied";
300068
- return provider.enabled && provider.installed && provider.status === "ready" && hasExecutionAuthority && provider.models.length > 0;
300182
+ function cappedText(value, max) {
300183
+ const normalized = value?.trim().slice(0, max);
300184
+ return normalized ? normalized : null;
300069
300185
  }
300070
- /** `slug` and `name` are `.min(1).max(512)` on the receiving schema. */
300071
- const FIELD_MAX_LENGTH = 512;
300072
300186
  function serializeModel(model) {
300073
300187
  const slug = model.slug.trim().slice(0, FIELD_MAX_LENGTH);
300074
300188
  const name = model.name.trim().slice(0, FIELD_MAX_LENGTH);
@@ -300082,20 +300196,48 @@ function serializeModel(model) {
300082
300196
  name
300083
300197
  };
300084
300198
  }
300199
+ /**
300200
+ * The availability to publish for one provider.
300201
+ *
300202
+ * The registry stamps every snapshot before it leaves, so this normally copies.
300203
+ * Deriving over a stamped snapshot would lose the one fact only the registry
300204
+ * holds — which providers this build cannot run at all — and republish every
300205
+ * Unbuilt provider as Not on this Environment. The fallback covers a snapshot
300206
+ * that reached the outbox from some other path.
300207
+ *
300208
+ * Built by spread so a key with no value is ABSENT rather than `undefined`: the
300209
+ * receiving object is `.strict()`, `undefined` is not a legal enum member, and
300210
+ * the outbox retries the resulting 400 forever.
300211
+ */
300212
+ function publishedAvailability(provider) {
300213
+ if (provider.availability === void 0) return deriveProviderAvailability(provider);
300214
+ const reason = provider.unavailableReason;
300215
+ const detail = provider.unavailableDetail;
300216
+ return {
300217
+ availability: provider.availability,
300218
+ ...reason === void 0 ? {} : { unavailableReason: reason },
300219
+ ...detail === void 0 ? {} : { unavailableDetail: detail }
300220
+ };
300221
+ }
300222
+ function serializeProvider(provider) {
300223
+ const models = [];
300224
+ for (const model of provider.models) {
300225
+ if (models.length >= 256) break;
300226
+ const serialized = serializeModel(model);
300227
+ if (serialized) models.push(serialized);
300228
+ }
300229
+ return {
300230
+ provider: provider.provider,
300231
+ models,
300232
+ ...publishedAvailability(provider),
300233
+ version: cappedText(provider.version, VERSION_MAX_LENGTH),
300234
+ binaryPath: cappedText(provider.auth.provenance?.binaryPath, BINARY_PATH_MAX_LENGTH)
300235
+ };
300236
+ }
300085
300237
  function serializeProviderCatalog(providers) {
300086
300238
  const catalog = [];
300087
300239
  for (const provider of providers) {
300088
- if (!isServerProviderExecutable(provider)) continue;
300089
- const models = [];
300090
- for (const model of provider.models) {
300091
- if (models.length >= 256) break;
300092
- const serialized = serializeModel(model);
300093
- if (serialized) models.push(serialized);
300094
- }
300095
- catalog.push({
300096
- provider: provider.provider,
300097
- models
300098
- });
300240
+ catalog.push(serializeProvider(provider));
300099
300241
  if (catalog.length >= 16) break;
300100
300242
  }
300101
300243
  return catalog;
@@ -310543,7 +310685,7 @@ const connectLoginCommand = make$32("login", {
310543
310685
  })).json();
310544
310686
  },
310545
310687
  openBrowser: async (url) => {
310546
- const open = (await import("./open-D8mGyWmt.mjs")).default;
310688
+ const open = (await import("./open-FIgTDosf.mjs")).default;
310547
310689
  await open(url);
310548
310690
  return true;
310549
310691
  },