@cmmd-center/forge 0.13.49 → 0.13.50

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.cjs CHANGED
@@ -66257,7 +66257,7 @@ function normalizeNumberish(value) {
66257
66257
  }
66258
66258
  //#endregion
66259
66259
  //#region package.json
66260
- var version$1 = "0.13.49";
66260
+ var version$1 = "0.13.50";
66261
66261
  //#endregion
66262
66262
  //#region src/sentry.ts
66263
66263
  const SERVER_APP_NAME = "forge-server";
@@ -89213,6 +89213,13 @@ function errorFromBody(body, fallback) {
89213
89213
  }
89214
89214
  return fallback;
89215
89215
  }
89216
+ function codeFromBody(body) {
89217
+ if (body && typeof body === "object") {
89218
+ const code = body["code"];
89219
+ if (typeof code === "string") return code;
89220
+ }
89221
+ return null;
89222
+ }
89216
89223
  function shouldRefreshCmmdBrokerJwt(status) {
89217
89224
  return status === 401 || status === 403;
89218
89225
  }
@@ -89335,9 +89342,10 @@ var GitHubBroker = class {
89335
89342
  } : auth);
89336
89343
  }
89337
89344
  async status(auth) {
89338
- const grant = this.resolveRuntimeGrant();
89339
- if (grant) return this.cmmdRuntimeJson(grant, "status");
89340
- return this.cmmdJson(auth, "/api/github-oauth/status");
89345
+ return this.cmmdRequest(auth, {
89346
+ jwtPath: "/api/github-oauth/status",
89347
+ runtimeResource: "status"
89348
+ });
89341
89349
  }
89342
89350
  async workspaceStatus(input) {
89343
89351
  const cwdValidation = validateCwd(input.cwd);
@@ -89526,12 +89534,16 @@ var GitHubBroker = class {
89526
89534
  async listRepositories(auth, input = {}) {
89527
89535
  const search = new URLSearchParams();
89528
89536
  if (input.search?.trim()) search.set("search", input.search.trim());
89529
- const grant = this.resolveRuntimeGrant();
89530
- if (grant) return this.cmmdRuntimeJson(grant, "repos", { search: search.size > 0 ? search : void 0 });
89531
- return this.cmmdJson(auth, "/api/forge/github/repos", { search: search.size > 0 ? search : void 0 });
89537
+ return this.cmmdRequest(auth, {
89538
+ jwtPath: "/api/forge/github/repos",
89539
+ runtimeResource: "repos",
89540
+ search: search.size > 0 ? search : void 0
89541
+ });
89532
89542
  }
89533
89543
  async createRepository(auth, input) {
89534
- return this.cmmdJson(auth, "/api/forge/github/repos", {
89544
+ return this.cmmdRequest(auth, {
89545
+ jwtPath: "/api/forge/github/repos",
89546
+ runtimeResource: "repos",
89535
89547
  method: "POST",
89536
89548
  body: {
89537
89549
  owner: input.owner,
@@ -90191,6 +90203,21 @@ var GitHubBroker = class {
90191
90203
  }
90192
90204
  };
90193
90205
  }
90206
+ /**
90207
+ * The only way this broker calls CMMD as the person. Every operation names
90208
+ * both routes, because a managed runtime acts on its runtime grant and never
90209
+ * on a user JWT (CMMD ADR-015): it holds no refreshable JWT, so the JWT path
90210
+ * there reports a session expiry that signing in cannot fix. A cloud runtime
90211
+ * with no usable grant fails closed. Desktop and local keep the JWT path.
90212
+ */
90213
+ async cmmdRequest(auth, operation) {
90214
+ const { jwtPath, runtimeResource, ...options } = operation;
90215
+ const grant = this.resolveRuntimeGrant();
90216
+ if (grant) return this.cmmdRuntimeJson(grant, runtimeResource, options);
90217
+ const missingGrantFailure = this.missingRuntimeGrantFailure();
90218
+ if (missingGrantFailure) return missingGrantFailure;
90219
+ return this.cmmdJson(auth, jwtPath, options);
90220
+ }
90194
90221
  async cmmdJson(auth, path, options = {}) {
90195
90222
  const jwt = await this.resolveJwt(auth);
90196
90223
  if (!jwt) return {
@@ -90275,6 +90302,22 @@ var GitHubBroker = class {
90275
90302
  token: token.trim()
90276
90303
  };
90277
90304
  }
90305
+ /**
90306
+ * A cloud runtime with no usable grant must not fall back to the person's JWT.
90307
+ * `githubWriteIdentity: "my-account"` is the deliberate opposite choice for git
90308
+ * credentials, so those paths pass `allowMyAccount`.
90309
+ */
90310
+ missingRuntimeGrantFailure(options = {}) {
90311
+ if (options.allowMyAccount && this.githubWriteIdentity === "my-account") return null;
90312
+ const failure = classifyMissingRuntimeGrant({
90313
+ isCmmdCloudRuntimeMode: this.isCmmdCloudRuntimeMode,
90314
+ hasRuntimeGrant: false
90315
+ });
90316
+ return failure ? {
90317
+ ok: false,
90318
+ ...failure
90319
+ } : null;
90320
+ }
90278
90321
  async resolveInstallationToken(auth, repoFullName) {
90279
90322
  const runtimeGrant = this.resolveRuntimeGrant("github");
90280
90323
  if (runtimeGrant) {
@@ -90282,6 +90325,8 @@ var GitHubBroker = class {
90282
90325
  if (!token.ok) return token;
90283
90326
  return token.token ?? invalidInstallationTokenResult();
90284
90327
  }
90328
+ const missingGrantFailure = this.missingRuntimeGrantFailure({ allowMyAccount: true });
90329
+ if (missingGrantFailure) return missingGrantFailure;
90285
90330
  const jwt = await this.resolveJwt(auth);
90286
90331
  if (!jwt) return cmmdReauthRequiredResult();
90287
90332
  let token = await this.fetchInstallationToken(jwt, repoFullName);
@@ -90636,16 +90681,8 @@ var GitHubBroker = class {
90636
90681
  repoFullName
90637
90682
  };
90638
90683
  }
90639
- const missingGrantFailure = this.githubWriteIdentity === "my-account" ? null : classifyMissingRuntimeGrant({
90640
- isCmmdCloudRuntimeMode: this.isCmmdCloudRuntimeMode,
90641
- hasRuntimeGrant: runtimeGrant !== null
90642
- });
90643
- if (missingGrantFailure) return {
90644
- ok: false,
90645
- code: missingGrantFailure.code,
90646
- userActionRequired: missingGrantFailure.userActionRequired,
90647
- error: missingGrantFailure.error
90648
- };
90684
+ const missingGrantFailure = this.missingRuntimeGrantFailure({ allowMyAccount: true });
90685
+ if (missingGrantFailure) return missingGrantFailure;
90649
90686
  const jwt = await this.resolveJwt(auth);
90650
90687
  if (!jwt) return cmmdReauthRequiredResult();
90651
90688
  let token = await this.fetchInstallationToken(jwt, repoFullName);
@@ -90710,7 +90747,7 @@ var GitHubBroker = class {
90710
90747
  };
90711
90748
  }
90712
90749
  /**
90713
- * GET a grant-authenticated GitHub read endpoint from inside a managed runtime. The
90750
+ * Call a grant-authenticated GitHub endpoint from inside a managed runtime. The
90714
90751
  * runtime grant token (scope `github`) stands in for the user JWT — CMMD
90715
90752
  * resolves identity server-side and returns the same body as the JWT routes,
90716
90753
  * so callers get an identical `GitHubBrokerResult`. `resource` is the trailing
@@ -90719,18 +90756,21 @@ var GitHubBroker = class {
90719
90756
  */
90720
90757
  async cmmdRuntimeJson(grant, resource, options = {}) {
90721
90758
  const response = await this.fetchImpl(makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/github/${resource}`, options.search), {
90722
- method: "GET",
90723
- headers: { Authorization: `Bearer ${grant.token}` }
90724
- });
90725
- const body = await parseResponseBody(response);
90726
- if (!response.ok) return {
90759
+ method: options.method ?? "GET",
90760
+ headers: {
90761
+ Authorization: `Bearer ${grant.token}`,
90762
+ ...options.body !== void 0 ? { "Content-Type": "application/json" } : {}
90763
+ },
90764
+ ...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {},
90765
+ signal: AbortSignal.timeout(GITHUB_BROKER_REQUEST_TIMEOUT_MS)
90766
+ }).catch(() => null);
90767
+ if (response === null) return {
90727
90768
  ok: false,
90728
- status: response.status,
90729
- code: response.status === 401 ? "GITHUB_AUTH_REQUIRED" : "GITHUB_BROKER_REQUEST_FAILED",
90730
- ...response.status === 401 ? { userActionRequired: "connect_github" } : {},
90731
- error: errorFromBody(body, `GitHub runtime request failed with status ${response.status}.`),
90732
- data: body
90769
+ code: "GITHUB_BROKER_REQUEST_FAILED",
90770
+ error: "CMMD could not be reached for this GitHub request. Retry in a moment."
90733
90771
  };
90772
+ const body = await parseResponseBody(response);
90773
+ if (!response.ok) return runtimeGrantRequestFailure(response.status, body);
90734
90774
  return {
90735
90775
  ok: true,
90736
90776
  status: response.status,
@@ -90857,6 +90897,34 @@ function parseWorkspaceStatus(stdout) {
90857
90897
  function isGitHubCliCredential(value) {
90858
90898
  return "token" in value && "repoFullName" in value;
90859
90899
  }
90900
+ function runtimeGrantRequestFailure(status, body) {
90901
+ const cmmdCode = codeFromBody(body);
90902
+ const grantFailure = cmmdCode?.startsWith("RUNTIME_GRANT_") ? classifyMissingRuntimeGrant({
90903
+ isCmmdCloudRuntimeMode: true,
90904
+ hasRuntimeGrant: false
90905
+ }) : null;
90906
+ if (grantFailure) return {
90907
+ ok: false,
90908
+ status,
90909
+ ...grantFailure,
90910
+ data: body
90911
+ };
90912
+ if (status === 401) return {
90913
+ ok: false,
90914
+ status,
90915
+ code: "GITHUB_AUTH_REQUIRED",
90916
+ userActionRequired: "connect_github",
90917
+ error: errorFromBody(body, `GitHub runtime request failed with status ${status}.`),
90918
+ data: body
90919
+ };
90920
+ return {
90921
+ ok: false,
90922
+ status,
90923
+ code: cmmdCode ?? "GITHUB_BROKER_REQUEST_FAILED",
90924
+ error: errorFromBody(body, `GitHub runtime request failed with status ${status}.`),
90925
+ data: body
90926
+ };
90927
+ }
90860
90928
  function cmmdReauthRequiredResult() {
90861
90929
  return {
90862
90930
  ok: false,
@@ -298065,7 +298133,7 @@ function resolveBuildCommitFromEnv(env) {
298065
298133
  * environment descriptor down instead of reporting an honest "unknown".
298066
298134
  */
298067
298135
  function readBakedBuildCommit() {
298068
- return "efe4f61b3d4a7de342d1d80983113ff48dd26235";
298136
+ return "64478cf3c507c24bc59b83783ca2eb2ddd93de2c";
298069
298137
  }
298070
298138
  async function resolveServerBuildCommit(input) {
298071
298139
  if (isFullCommitSha(input.baked)) return input.baked;
package/dist/bin.mjs CHANGED
@@ -23,7 +23,7 @@ import { createCipheriv, createDecipheriv, createHash, createHmac, createPublicK
23
23
  import * as FS$1 from "node:fs";
24
24
  import fs, { accessSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, mkdtempSync, promises, readFile, readFileSync, readdir, readdirSync, realpathSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
25
25
  import * as NodeOS from "node:os";
26
- import $U, { homedir, networkInterfaces, tmpdir } from "node:os";
26
+ import os, { homedir, networkInterfaces, tmpdir } from "node:os";
27
27
  import * as Path$1 from "node:path";
28
28
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
29
29
  import { pathToFileURL } from "node:url";
@@ -50573,7 +50573,7 @@ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
50573
50573
  const min = forceColor || 0;
50574
50574
  if (env.TERM === "dumb") return min;
50575
50575
  if (process$1.platform === "win32") {
50576
- const osRelease = $U.release().split(".");
50576
+ const osRelease = os.release().split(".");
50577
50577
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
50578
50578
  return 1;
50579
50579
  }
@@ -53016,7 +53016,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
53016
53016
  exports.processDetector = void 0;
53017
53017
  const api_1 = (init_esm$1(), __toCommonJS(esm_exports$1));
53018
53018
  const semconv_1 = require_semconv$1();
53019
- const os$3 = __require("os");
53019
+ const os$4 = __require("os");
53020
53020
  /**
53021
53021
  * ProcessDetector will be used to detect the resources related current process running
53022
53022
  * and being instrumented from the NodeJS Process module.
@@ -53038,7 +53038,7 @@ var require_ProcessDetector = /* @__PURE__ */ __commonJSMin(((exports) => {
53038
53038
  };
53039
53039
  if (process.argv.length > 1) attributes[semconv_1.ATTR_PROCESS_COMMAND] = process.argv[1];
53040
53040
  try {
53041
- const userInfo = os$3.userInfo();
53041
+ const userInfo = os$4.userInfo();
53042
53042
  attributes[semconv_1.ATTR_PROCESS_OWNER] = userInfo.username;
53043
53043
  } catch (e) {
53044
53044
  api_1.diag.debug(`error obtaining process owner: ${e}`);
@@ -65961,7 +65961,7 @@ function normalizeNumberish(value) {
65961
65961
  }
65962
65962
  //#endregion
65963
65963
  //#region package.json
65964
- var version$1 = "0.13.49";
65964
+ var version$1 = "0.13.50";
65965
65965
  //#endregion
65966
65966
  //#region src/sentry.ts
65967
65967
  const SERVER_APP_NAME = "forge-server";
@@ -75844,7 +75844,7 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
75844
75844
  var fs$6 = __require("fs");
75845
75845
  var path$5 = __require("path");
75846
75846
  var url$1 = __require("url");
75847
- var os$2 = __require("os");
75847
+ var os$3 = __require("os");
75848
75848
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : __require;
75849
75849
  var vars = process.config && process.config.variables || {};
75850
75850
  var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
@@ -75852,8 +75852,8 @@ var require_node_gyp_build = /* @__PURE__ */ __commonJSMin(((exports, module) =>
75852
75852
  var abi = versions.modules;
75853
75853
  if (versions.deno || process.isBun) abi = "unsupported";
75854
75854
  var runtime = isElectron() ? "electron" : isNwjs() ? "node-webkit" : "node";
75855
- var arch = process.env.npm_config_arch || os$2.arch();
75856
- var platform = process.env.npm_config_platform || os$2.platform();
75855
+ var arch = process.env.npm_config_arch || os$3.arch();
75856
+ var platform = process.env.npm_config_platform || os$3.platform();
75857
75857
  var libc = process.env.LIBC || (isMusl(platform) ? "musl" : "glibc");
75858
75858
  var armv = process.env.ARM_VERSION || (arch === "arm64" ? "8" : vars.arm_version) || "";
75859
75859
  var uv = (versions.uv || "").split(".")[0];
@@ -88857,6 +88857,13 @@ function errorFromBody(body, fallback) {
88857
88857
  }
88858
88858
  return fallback;
88859
88859
  }
88860
+ function codeFromBody(body) {
88861
+ if (body && typeof body === "object") {
88862
+ const code = body["code"];
88863
+ if (typeof code === "string") return code;
88864
+ }
88865
+ return null;
88866
+ }
88860
88867
  function shouldRefreshCmmdBrokerJwt(status) {
88861
88868
  return status === 401 || status === 403;
88862
88869
  }
@@ -88979,9 +88986,10 @@ var GitHubBroker = class {
88979
88986
  } : auth);
88980
88987
  }
88981
88988
  async status(auth) {
88982
- const grant = this.resolveRuntimeGrant();
88983
- if (grant) return this.cmmdRuntimeJson(grant, "status");
88984
- return this.cmmdJson(auth, "/api/github-oauth/status");
88989
+ return this.cmmdRequest(auth, {
88990
+ jwtPath: "/api/github-oauth/status",
88991
+ runtimeResource: "status"
88992
+ });
88985
88993
  }
88986
88994
  async workspaceStatus(input) {
88987
88995
  const cwdValidation = validateCwd(input.cwd);
@@ -89170,12 +89178,16 @@ var GitHubBroker = class {
89170
89178
  async listRepositories(auth, input = {}) {
89171
89179
  const search = new URLSearchParams();
89172
89180
  if (input.search?.trim()) search.set("search", input.search.trim());
89173
- const grant = this.resolveRuntimeGrant();
89174
- if (grant) return this.cmmdRuntimeJson(grant, "repos", { search: search.size > 0 ? search : void 0 });
89175
- return this.cmmdJson(auth, "/api/forge/github/repos", { search: search.size > 0 ? search : void 0 });
89181
+ return this.cmmdRequest(auth, {
89182
+ jwtPath: "/api/forge/github/repos",
89183
+ runtimeResource: "repos",
89184
+ search: search.size > 0 ? search : void 0
89185
+ });
89176
89186
  }
89177
89187
  async createRepository(auth, input) {
89178
- return this.cmmdJson(auth, "/api/forge/github/repos", {
89188
+ return this.cmmdRequest(auth, {
89189
+ jwtPath: "/api/forge/github/repos",
89190
+ runtimeResource: "repos",
89179
89191
  method: "POST",
89180
89192
  body: {
89181
89193
  owner: input.owner,
@@ -89835,6 +89847,21 @@ var GitHubBroker = class {
89835
89847
  }
89836
89848
  };
89837
89849
  }
89850
+ /**
89851
+ * The only way this broker calls CMMD as the person. Every operation names
89852
+ * both routes, because a managed runtime acts on its runtime grant and never
89853
+ * on a user JWT (CMMD ADR-015): it holds no refreshable JWT, so the JWT path
89854
+ * there reports a session expiry that signing in cannot fix. A cloud runtime
89855
+ * with no usable grant fails closed. Desktop and local keep the JWT path.
89856
+ */
89857
+ async cmmdRequest(auth, operation) {
89858
+ const { jwtPath, runtimeResource, ...options } = operation;
89859
+ const grant = this.resolveRuntimeGrant();
89860
+ if (grant) return this.cmmdRuntimeJson(grant, runtimeResource, options);
89861
+ const missingGrantFailure = this.missingRuntimeGrantFailure();
89862
+ if (missingGrantFailure) return missingGrantFailure;
89863
+ return this.cmmdJson(auth, jwtPath, options);
89864
+ }
89838
89865
  async cmmdJson(auth, path, options = {}) {
89839
89866
  const jwt = await this.resolveJwt(auth);
89840
89867
  if (!jwt) return {
@@ -89919,6 +89946,22 @@ var GitHubBroker = class {
89919
89946
  token: token.trim()
89920
89947
  };
89921
89948
  }
89949
+ /**
89950
+ * A cloud runtime with no usable grant must not fall back to the person's JWT.
89951
+ * `githubWriteIdentity: "my-account"` is the deliberate opposite choice for git
89952
+ * credentials, so those paths pass `allowMyAccount`.
89953
+ */
89954
+ missingRuntimeGrantFailure(options = {}) {
89955
+ if (options.allowMyAccount && this.githubWriteIdentity === "my-account") return null;
89956
+ const failure = classifyMissingRuntimeGrant({
89957
+ isCmmdCloudRuntimeMode: this.isCmmdCloudRuntimeMode,
89958
+ hasRuntimeGrant: false
89959
+ });
89960
+ return failure ? {
89961
+ ok: false,
89962
+ ...failure
89963
+ } : null;
89964
+ }
89922
89965
  async resolveInstallationToken(auth, repoFullName) {
89923
89966
  const runtimeGrant = this.resolveRuntimeGrant("github");
89924
89967
  if (runtimeGrant) {
@@ -89926,6 +89969,8 @@ var GitHubBroker = class {
89926
89969
  if (!token.ok) return token;
89927
89970
  return token.token ?? invalidInstallationTokenResult();
89928
89971
  }
89972
+ const missingGrantFailure = this.missingRuntimeGrantFailure({ allowMyAccount: true });
89973
+ if (missingGrantFailure) return missingGrantFailure;
89929
89974
  const jwt = await this.resolveJwt(auth);
89930
89975
  if (!jwt) return cmmdReauthRequiredResult();
89931
89976
  let token = await this.fetchInstallationToken(jwt, repoFullName);
@@ -90280,16 +90325,8 @@ var GitHubBroker = class {
90280
90325
  repoFullName
90281
90326
  };
90282
90327
  }
90283
- const missingGrantFailure = this.githubWriteIdentity === "my-account" ? null : classifyMissingRuntimeGrant({
90284
- isCmmdCloudRuntimeMode: this.isCmmdCloudRuntimeMode,
90285
- hasRuntimeGrant: runtimeGrant !== null
90286
- });
90287
- if (missingGrantFailure) return {
90288
- ok: false,
90289
- code: missingGrantFailure.code,
90290
- userActionRequired: missingGrantFailure.userActionRequired,
90291
- error: missingGrantFailure.error
90292
- };
90328
+ const missingGrantFailure = this.missingRuntimeGrantFailure({ allowMyAccount: true });
90329
+ if (missingGrantFailure) return missingGrantFailure;
90293
90330
  const jwt = await this.resolveJwt(auth);
90294
90331
  if (!jwt) return cmmdReauthRequiredResult();
90295
90332
  let token = await this.fetchInstallationToken(jwt, repoFullName);
@@ -90354,7 +90391,7 @@ var GitHubBroker = class {
90354
90391
  };
90355
90392
  }
90356
90393
  /**
90357
- * GET a grant-authenticated GitHub read endpoint from inside a managed runtime. The
90394
+ * Call a grant-authenticated GitHub endpoint from inside a managed runtime. The
90358
90395
  * runtime grant token (scope `github`) stands in for the user JWT — CMMD
90359
90396
  * resolves identity server-side and returns the same body as the JWT routes,
90360
90397
  * so callers get an identical `GitHubBrokerResult`. `resource` is the trailing
@@ -90363,18 +90400,21 @@ var GitHubBroker = class {
90363
90400
  */
90364
90401
  async cmmdRuntimeJson(grant, resource, options = {}) {
90365
90402
  const response = await this.fetchImpl(makeUrl(this.commandAppUrl, `/api/forge/runtimes/${encodeURIComponent(grant.runtimeId)}/github/${resource}`, options.search), {
90366
- method: "GET",
90367
- headers: { Authorization: `Bearer ${grant.token}` }
90368
- });
90369
- const body = await parseResponseBody(response);
90370
- if (!response.ok) return {
90403
+ method: options.method ?? "GET",
90404
+ headers: {
90405
+ Authorization: `Bearer ${grant.token}`,
90406
+ ...options.body !== void 0 ? { "Content-Type": "application/json" } : {}
90407
+ },
90408
+ ...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {},
90409
+ signal: AbortSignal.timeout(GITHUB_BROKER_REQUEST_TIMEOUT_MS)
90410
+ }).catch(() => null);
90411
+ if (response === null) return {
90371
90412
  ok: false,
90372
- status: response.status,
90373
- code: response.status === 401 ? "GITHUB_AUTH_REQUIRED" : "GITHUB_BROKER_REQUEST_FAILED",
90374
- ...response.status === 401 ? { userActionRequired: "connect_github" } : {},
90375
- error: errorFromBody(body, `GitHub runtime request failed with status ${response.status}.`),
90376
- data: body
90413
+ code: "GITHUB_BROKER_REQUEST_FAILED",
90414
+ error: "CMMD could not be reached for this GitHub request. Retry in a moment."
90377
90415
  };
90416
+ const body = await parseResponseBody(response);
90417
+ if (!response.ok) return runtimeGrantRequestFailure(response.status, body);
90378
90418
  return {
90379
90419
  ok: true,
90380
90420
  status: response.status,
@@ -90501,6 +90541,34 @@ function parseWorkspaceStatus(stdout) {
90501
90541
  function isGitHubCliCredential(value) {
90502
90542
  return "token" in value && "repoFullName" in value;
90503
90543
  }
90544
+ function runtimeGrantRequestFailure(status, body) {
90545
+ const cmmdCode = codeFromBody(body);
90546
+ const grantFailure = cmmdCode?.startsWith("RUNTIME_GRANT_") ? classifyMissingRuntimeGrant({
90547
+ isCmmdCloudRuntimeMode: true,
90548
+ hasRuntimeGrant: false
90549
+ }) : null;
90550
+ if (grantFailure) return {
90551
+ ok: false,
90552
+ status,
90553
+ ...grantFailure,
90554
+ data: body
90555
+ };
90556
+ if (status === 401) return {
90557
+ ok: false,
90558
+ status,
90559
+ code: "GITHUB_AUTH_REQUIRED",
90560
+ userActionRequired: "connect_github",
90561
+ error: errorFromBody(body, `GitHub runtime request failed with status ${status}.`),
90562
+ data: body
90563
+ };
90564
+ return {
90565
+ ok: false,
90566
+ status,
90567
+ code: cmmdCode ?? "GITHUB_BROKER_REQUEST_FAILED",
90568
+ error: errorFromBody(body, `GitHub runtime request failed with status ${status}.`),
90569
+ data: body
90570
+ };
90571
+ }
90504
90572
  function cmmdReauthRequiredResult() {
90505
90573
  return {
90506
90574
  ok: false,
@@ -93541,7 +93609,7 @@ const launchDetached = (launch) => gen(function* () {
93541
93609
  });
93542
93610
  const OpenLive = effect(Open, gen(function* () {
93543
93611
  const open = yield* tryPromise({
93544
- try: () => import("./open-2-reBrpv.mjs"),
93612
+ try: () => import("./open-yHTUkd2Y.mjs"),
93545
93613
  catch: (cause) => new OpenError$1({
93546
93614
  message: "failed to load browser opener",
93547
93615
  cause
@@ -191059,7 +191127,7 @@ var Vce = {
191059
191127
  function Ve() {
191060
191128
  return Vce;
191061
191129
  }
191062
- var Us = $U.homedir(), lk = $U.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
191130
+ var Us = os.homedir(), lk = os.tmpdir(), { env: Vc } = process$1, Yce = (e) => {
191063
191131
  let t = path.join(Us, "Library");
191064
191132
  return {
191065
191133
  data: path.join(t, "Application Support", e),
@@ -201259,12 +201327,12 @@ function qZ(e, t) {
201259
201327
  }
201260
201328
  return n;
201261
201329
  }
201262
- var os$1 = "https://code.claude.com/docs/en", kKe = [
201330
+ var os$2 = "https://code.claude.com/docs/en", kKe = [
201263
201331
  {
201264
201332
  matches: (e) => e.path === "permissions.defaultMode" && e.code === "invalid_value",
201265
201333
  tip: {
201266
201334
  suggestion: "Valid modes: \"acceptEdits\" (ask before file changes), \"plan\" (analysis only), \"bypassPermissions\" (auto-accept all), or \"default\" (standard behavior)",
201267
- docLink: `${os$1}/iam#permission-modes`
201335
+ docLink: `${os$2}/iam#permission-modes`
201268
201336
  }
201269
201337
  },
201270
201338
  {
@@ -201279,7 +201347,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
201279
201347
  matches: (e) => e.path.startsWith("env.") && e.code === "invalid_type",
201280
201348
  tip: {
201281
201349
  suggestion: "Environment variables must be strings. Wrap numbers and booleans in quotes. Example: \"DEBUG\": \"true\", \"PORT\": \"3000\"",
201282
- docLink: `${os$1}/settings#environment-variables`
201350
+ docLink: `${os$2}/settings#environment-variables`
201283
201351
  }
201284
201352
  },
201285
201353
  {
@@ -201290,14 +201358,14 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
201290
201358
  matches: (e) => e.path.startsWith("hooks.") && e.code === "invalid_key",
201291
201359
  tip: {
201292
201360
  suggestion: "Not a recognized hook event. Common events: PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd, Stop. Check spelling and capitalization.",
201293
- docLink: `${os$1}/hooks`
201361
+ docLink: `${os$2}/hooks`
201294
201362
  }
201295
201363
  },
201296
201364
  {
201297
201365
  matches: (e) => /\.hooks\.\d+\.command$/.test(e.path) && e.code === "invalid_type" && e.received === "undefined",
201298
201366
  tip: {
201299
201367
  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\"}.",
201300
- docLink: `${os$1}/hooks#exec-form-and-shell-form`
201368
+ docLink: `${os$2}/hooks#exec-form-and-shell-form`
201301
201369
  }
201302
201370
  },
201303
201371
  {
@@ -201312,7 +201380,7 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
201312
201380
  matches: (e) => e.code === "unrecognized_keys",
201313
201381
  tip: {
201314
201382
  suggestion: "Check for typos or refer to the documentation for valid fields",
201315
- docLink: `${os$1}/settings`
201383
+ docLink: `${os$2}/settings`
201316
201384
  }
201317
201385
  },
201318
201386
  {
@@ -201327,13 +201395,13 @@ var os$1 = "https://code.claude.com/docs/en", kKe = [
201327
201395
  matches: (e) => e.path === "permissions.additionalDirectories" && e.code === "invalid_type",
201328
201396
  tip: {
201329
201397
  suggestion: "Must be an array of directory paths. Example: [\"~/projects\", \"/tmp/workspace\"]. You can also use --add-dir flag or /add-dir command",
201330
- docLink: `${os$1}/iam#working-directories`
201398
+ docLink: `${os$2}/iam#working-directories`
201331
201399
  }
201332
201400
  }
201333
201401
  ], AKe = {
201334
- permissions: `${os$1}/iam#configuring-permissions`,
201335
- env: `${os$1}/settings#environment-variables`,
201336
- hooks: `${os$1}/hooks`
201402
+ permissions: `${os$2}/iam#configuring-permissions`,
201403
+ env: `${os$2}/settings#environment-variables`,
201404
+ hooks: `${os$2}/hooks`
201337
201405
  };
201338
201406
  function GZ(e) {
201339
201407
  let t = kKe.find((r) => r.matches(e));
@@ -269460,7 +269528,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
269460
269528
  var dgram = __require("dgram");
269461
269529
  var thunky = require_thunky();
269462
269530
  var events = __require("events");
269463
- var os = __require("os");
269531
+ var os$1 = __require("os");
269464
269532
  var noop = function() {};
269465
269533
  module.exports = function(opts) {
269466
269534
  if (!opts) opts = {};
@@ -269591,14 +269659,14 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
269591
269659
  return that;
269592
269660
  };
269593
269661
  function defaultInterface() {
269594
- var networks = os.networkInterfaces();
269662
+ var networks = os$1.networkInterfaces();
269595
269663
  var names = Object.keys(networks);
269596
269664
  for (var i = 0; i < names.length; i++) {
269597
269665
  var net = networks[names[i]];
269598
269666
  for (var j = 0; j < net.length; j++) {
269599
269667
  var iface = net[j];
269600
269668
  if (isIPv4(iface.family) && !iface.internal) {
269601
- if (os.platform() === "darwin" && names[i] === "en0") return iface.address;
269669
+ if (os$1.platform() === "darwin" && names[i] === "en0") return iface.address;
269602
269670
  return "0.0.0.0";
269603
269671
  }
269604
269672
  }
@@ -269606,7 +269674,7 @@ var import_multicast_dns = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMi
269606
269674
  return "127.0.0.1";
269607
269675
  }
269608
269676
  function allInterfaces() {
269609
- var networks = os.networkInterfaces();
269677
+ var networks = os$1.networkInterfaces();
269610
269678
  var names = Object.keys(networks);
269611
269679
  var res = [];
269612
269680
  for (var i = 0; i < names.length; i++) {
@@ -297510,7 +297578,7 @@ function resolveBuildCommitFromEnv(env) {
297510
297578
  * environment descriptor down instead of reporting an honest "unknown".
297511
297579
  */
297512
297580
  function readBakedBuildCommit() {
297513
- return "efe4f61b3d4a7de342d1d80983113ff48dd26235";
297581
+ return "64478cf3c507c24bc59b83783ca2eb2ddd93de2c";
297514
297582
  }
297515
297583
  async function resolveServerBuildCommit(input) {
297516
297584
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -322113,7 +322181,7 @@ const connectLoginCommand = make$34("login", {
322113
322181
  })).json();
322114
322182
  },
322115
322183
  openBrowser: async (url) => {
322116
- const open = (await import("./open-2-reBrpv.mjs")).default;
322184
+ const open = (await import("./open-yHTUkd2Y.mjs")).default;
322117
322185
  await open(url);
322118
322186
  return true;
322119
322187
  },