@cmmd-center/forge 0.14.1 → 0.14.2

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 (71) hide show
  1. package/dist/bin.cjs +487 -41
  2. package/dist/bin.mjs +511 -65
  3. package/dist/client/assets/{CanvasPanel-BeSvnc85.js → CanvasPanel-Bk1rL0LG.js} +3 -3
  4. package/dist/client/assets/CompositeItem-D1GrQhpu.js +2 -0
  5. package/dist/client/assets/CompositeList-CEBk8sf_.js +2 -0
  6. package/dist/client/assets/DiffPanel-jC25MVg8.js +64 -0
  7. package/dist/client/assets/{DiffPanel.logic-CAb-hngG.js → DiffPanel.logic-DHo4jHZM.js} +6 -6
  8. package/dist/client/assets/{DiffWorkerPoolProvider-BbyQb-ye.js → DiffWorkerPoolProvider-r1DUfA1d.js} +10 -10
  9. package/dist/client/assets/Effect-CyyMOw4X.js +15 -0
  10. package/dist/client/assets/PullRequestCodePanel-BWuWxI6X.js +5 -0
  11. package/dist/client/assets/Schema-8EGdYSms.js +3 -0
  12. package/dist/client/assets/Stream-Bvl2Z6qI.js +2 -0
  13. package/dist/client/assets/ThemeEditorPanel-BOkxNR3t.js +2 -0
  14. package/dist/client/assets/Virtualizer-DOL71mrP.js +2 -0
  15. package/dist/client/assets/WorkerPoolContext-gI2-7Koc.js +2538 -0
  16. package/dist/client/assets/activeOrganizationId-CySrJzMX.js +2 -0
  17. package/dist/client/assets/atomRegistry-CzI2zp7d.js +3 -0
  18. package/dist/client/assets/{canvasStateStore-DYt9MgFu.js → canvasStateStore-dUmp5NFj.js} +2 -2
  19. package/dist/client/assets/chevron-left-BXpfeqsT.js +2 -0
  20. package/dist/client/assets/chevron-right-B103tjaJ.js +2 -0
  21. package/dist/client/assets/cmmdAuthRedirect-CHlAAdAc.js +3 -0
  22. package/dist/client/assets/cmmdEmbedMode-DhVvltxi.js +2 -0
  23. package/dist/client/assets/currentForgeWorkspaceStore-eKCBxKgv.js +2 -0
  24. package/dist/client/assets/dialog-BfhVD7Kq.js +2 -0
  25. package/dist/client/assets/getPseudoElementBounds-DBf0dPO9.js +2 -0
  26. package/dist/client/assets/index-BS4FABiE.js +301 -0
  27. package/dist/client/assets/minus-CbEeUDFT.js +2 -0
  28. package/dist/client/assets/popover-D8qvi5AD.js +2 -0
  29. package/dist/client/assets/{react-D4GEJ3ir.js → react-A0DLYjwn.js} +2 -2
  30. package/dist/client/assets/scroll-area-BDuz0PnB.js +2 -0
  31. package/dist/client/assets/sidebarV2CustomSnoozeDialog-pxOuwuY2.js +2 -0
  32. package/dist/client/assets/src-7C4X1Oy2.js +2 -0
  33. package/dist/client/assets/switch-BeaQwtm7.js +2 -0
  34. package/dist/client/assets/{themePalette-BWvBK22X.js → themePalette-D4rx0k29.js} +2 -2
  35. package/dist/client/assets/toggle--uJ9LmDV.js +2 -0
  36. package/dist/client/assets/toggle-group-6UcL78FY.js +2 -0
  37. package/dist/client/assets/tooltip-C_eHCky0.js +2 -0
  38. package/dist/client/assets/useOpenInteractionType-BFjAYgzR.js +2 -0
  39. package/dist/client/assets/{workspaceReadinessAtom-D6bgTvKb.js → workspaceReadinessAtom-BIm13kLJ.js} +2 -2
  40. package/dist/client/index.html +33 -31
  41. package/dist/forge-build.json +1 -1
  42. package/dist/{open-yHTUkd2Y.mjs → open-2-reBrpv.mjs} +3 -3
  43. package/package.json +1 -1
  44. package/dist/client/assets/CompositeItem-DTyKsv13.js +0 -2
  45. package/dist/client/assets/CompositeList-Bc8TYCyy.js +0 -2
  46. package/dist/client/assets/DiffPanel-3EEekk0W.js +0 -64
  47. package/dist/client/assets/PullRequestCodePanel--fricLiS.js +0 -5
  48. package/dist/client/assets/Stream-mUTFnSY9.js +0 -15
  49. package/dist/client/assets/ThemeEditorPanel-BCJuZ6ai.js +0 -2
  50. package/dist/client/assets/Virtualizer-DX75f7Mw.js +0 -2
  51. package/dist/client/assets/WorkerPoolContext-D_2lN-9Y.js +0 -1533
  52. package/dist/client/assets/atomRegistry-C1yW8tyM.js +0 -3
  53. package/dist/client/assets/chevron-left-1XbEOuXj.js +0 -2
  54. package/dist/client/assets/chevron-right-DAF000Jz.js +0 -2
  55. package/dist/client/assets/cmmdAuthRedirect-DRkKjx0G.js +0 -3
  56. package/dist/client/assets/cmmdForgeRuntimeListResource-Df9wlF4U.js +0 -1008
  57. package/dist/client/assets/currentForgeWorkspaceStore-CiCPSq18.js +0 -2
  58. package/dist/client/assets/dialog-C0bK23D8.js +0 -2
  59. package/dist/client/assets/getPseudoElementBounds-DJTX-eyW.js +0 -2
  60. package/dist/client/assets/index-BHReJBiJ.js +0 -301
  61. package/dist/client/assets/minus-_j91i8bf.js +0 -2
  62. package/dist/client/assets/popover-ClRgm7hB.js +0 -2
  63. package/dist/client/assets/scroll-area-BHqISEYq.js +0 -2
  64. package/dist/client/assets/sidebarV2CustomSnoozeDialog-lbAJoff_.js +0 -2
  65. package/dist/client/assets/src-B_wrKHuq.js +0 -3
  66. package/dist/client/assets/switch-BWQHMJkU.js +0 -2
  67. package/dist/client/assets/toggle-CORC1vE9.js +0 -2
  68. package/dist/client/assets/toggle-group-C9nAr6VB.js +0 -2
  69. package/dist/client/assets/tooltip-CrS-TEbN.js +0 -2
  70. package/dist/client/assets/useOpenInteractionType-KsRrk6uH.js +0 -2
  71. package/dist/client/assets/utils-xQJ3ak-X.js +0 -2
package/dist/bin.cjs CHANGED
@@ -27136,14 +27136,15 @@ function nonEmptyString$3(value) {
27136
27136
  }
27137
27137
  /**
27138
27138
  * Resolve the operational Sprite name for provision / connect / readiness gates.
27139
+ * Only the authoritative `spriteName` counts: missing, empty, and explicit-null
27140
+ * values all resolve to null.
27139
27141
  *
27140
- * @see CmmdRuntimeSpriteIdentitySource for the dual-contract rules.
27142
+ * @see CmmdRuntimeSpriteIdentitySource for the identity rules.
27141
27143
  */
27142
27144
  function resolveCmmdRuntimeSpriteName(runtime) {
27143
- if (Object.hasOwn(runtime, "spriteName")) return nonEmptyString$3(runtime.spriteName);
27144
- return nonEmptyString$3(runtime.flyMachineId);
27145
+ return nonEmptyString$3(runtime.spriteName);
27145
27146
  }
27146
- /** True when the payload carries an operational Sprite name after dual-read. */
27147
+ /** True when the payload carries an authoritative Sprite name. */
27147
27148
  function hasCmmdRuntimeSpriteIdentity(runtime) {
27148
27149
  return resolveCmmdRuntimeSpriteName(runtime) !== null;
27149
27150
  }
@@ -27218,7 +27219,8 @@ const WORKTREE_LAUNCH_ACTIVITY_KINDS = new Set([
27218
27219
  "setup-script.skipped",
27219
27220
  "setup-script.failed",
27220
27221
  "launch.agent-starting",
27221
- "launch.cancelled"
27222
+ "launch.cancelled",
27223
+ "checkout-launch"
27222
27224
  ]);
27223
27225
  function encodeCmmdRuntimeWorktreeLaunchActivityPayload(kind, payload) {
27224
27226
  return {
@@ -27272,6 +27274,258 @@ function decodeCmmdRuntimePlanActivity(payload) {
27272
27274
  };
27273
27275
  }
27274
27276
  //#endregion
27277
+ //#region ../../packages/contracts/src/checkoutLaunch.ts
27278
+ /**
27279
+ * One Checkout launch snapshot for a thread.
27280
+ *
27281
+ * Upstream (`pingdotgg/t3code`, WorktreeSetupTracker) owns this shape: one
27282
+ * snapshot, fixed activity id, handoff when the agent stage is done and the
27283
+ * turn has started. Forge keeps its own stage names. The admission wait is
27284
+ * the first stage of this same snapshot, because a shared Environment can be
27285
+ * busy before any Checkout activity exists.
27286
+ */
27287
+ const CHECKOUT_LAUNCH_ACTIVITY_KIND = "checkout-launch";
27288
+ const PREPARATION_STAGES = [
27289
+ {
27290
+ id: "resolve",
27291
+ label: "Resolve base branch"
27292
+ },
27293
+ {
27294
+ id: "checkout",
27295
+ label: "Check out files"
27296
+ },
27297
+ {
27298
+ id: "dependencies",
27299
+ label: "Prepare dependencies"
27300
+ },
27301
+ {
27302
+ id: "setup",
27303
+ label: "Start setup script"
27304
+ },
27305
+ {
27306
+ id: "agent",
27307
+ label: "Start agent"
27308
+ }
27309
+ ];
27310
+ function checkoutLaunchActivityId(threadId) {
27311
+ return `checkout-launch:${threadId}`;
27312
+ }
27313
+ function preparationStages(statusFor, detailFor = () => null) {
27314
+ return PREPARATION_STAGES.map((stage) => ({
27315
+ id: stage.id,
27316
+ label: stage.label,
27317
+ status: statusFor(stage.id),
27318
+ detail: detailFor(stage.id)
27319
+ }));
27320
+ }
27321
+ function beginPreparationCheckoutLaunch(input) {
27322
+ return {
27323
+ phase: "running",
27324
+ stages: preparationStages((id) => id === "resolve" ? "running" : "pending"),
27325
+ startedAt: input.startedAt,
27326
+ completedAt: null,
27327
+ error: null,
27328
+ cancellable: true,
27329
+ worktreePath: input.worktreePath ?? null,
27330
+ turnStartedAt: null
27331
+ };
27332
+ }
27333
+ function replaceStage(snapshot, id, patch) {
27334
+ return {
27335
+ ...snapshot,
27336
+ stages: snapshot.stages.map((stage) => stage.id === id ? {
27337
+ ...stage,
27338
+ ...patch
27339
+ } : stage)
27340
+ };
27341
+ }
27342
+ function ensurePreparation(snapshot, startedAt) {
27343
+ if (snapshot && snapshot.stages.some((stage) => stage.id === "resolve")) return snapshot;
27344
+ return beginPreparationCheckoutLaunch({
27345
+ startedAt: snapshot?.startedAt ?? startedAt,
27346
+ worktreePath: snapshot?.worktreePath ?? null
27347
+ });
27348
+ }
27349
+ function settlePhase(snapshot) {
27350
+ if (snapshot.phase === "failed" || snapshot.phase === "cancelled") return snapshot;
27351
+ const agent = snapshot.stages.find((stage) => stage.id === "agent");
27352
+ const setup = snapshot.stages.find((stage) => stage.id === "setup");
27353
+ const agentDone = agent?.status === "done" && snapshot.turnStartedAt !== null;
27354
+ const setupStillRunning = setup?.status === "running";
27355
+ if (!agentDone || setupStillRunning) return snapshot;
27356
+ return {
27357
+ ...snapshot,
27358
+ phase: "done",
27359
+ completedAt: snapshot.completedAt ?? snapshot.turnStartedAt,
27360
+ cancellable: false
27361
+ };
27362
+ }
27363
+ function payloadString(payload, key) {
27364
+ const value = payload?.[key];
27365
+ return typeof value === "string" && value.length > 0 ? value : null;
27366
+ }
27367
+ function payloadNumber(payload, key) {
27368
+ const value = payload?.[key];
27369
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
27370
+ }
27371
+ const STAGE_IDS = new Set([
27372
+ "resolve",
27373
+ "checkout",
27374
+ "dependencies",
27375
+ "setup",
27376
+ "agent"
27377
+ ]);
27378
+ const STAGE_STATUSES = new Set([
27379
+ "done",
27380
+ "failed",
27381
+ "skipped",
27382
+ "running"
27383
+ ]);
27384
+ const LAUNCH_FAILING_STAGES = new Set([
27385
+ "resolve",
27386
+ "checkout",
27387
+ "dependencies"
27388
+ ]);
27389
+ function stageIdFromPayload(payload) {
27390
+ const id = payloadString(payload, "id") ?? payloadString(payload, "stage");
27391
+ return id !== null && STAGE_IDS.has(id) ? id : null;
27392
+ }
27393
+ function stageStatus(status) {
27394
+ return status !== null && STAGE_STATUSES.has(status) ? status : "running";
27395
+ }
27396
+ function applyStage(snapshot, event) {
27397
+ const id = stageIdFromPayload(event.payload);
27398
+ if (!id) return snapshot;
27399
+ snapshot = ensurePreparation(snapshot, event.createdAt);
27400
+ const nextStatus = stageStatus(payloadString(event.payload, "status"));
27401
+ const percent = payloadNumber(event.payload, "percent");
27402
+ const detail = percent !== null ? `${Math.round(percent)}%` : payloadString(event.payload, "detail");
27403
+ const next = replaceStage(snapshot, id, {
27404
+ status: nextStatus,
27405
+ detail
27406
+ });
27407
+ if (nextStatus !== "failed" || !LAUNCH_FAILING_STAGES.has(id)) return next;
27408
+ return {
27409
+ ...next,
27410
+ phase: "failed",
27411
+ error: event.summary ?? next.error,
27412
+ completedAt: event.createdAt,
27413
+ cancellable: false
27414
+ };
27415
+ }
27416
+ /**
27417
+ * Fold one launch activity into the snapshot. A recorded `checkout-launch`
27418
+ * payload replaces the snapshot. Older per-step activities still fold so a
27419
+ * thread that never received the snapshot does not go blank.
27420
+ */
27421
+ function reduceCheckoutLaunch(snapshot, event) {
27422
+ if (event.kind === "checkout-launch") return readCheckoutLaunchSnapshot(event) ?? snapshot;
27423
+ if (event.kind === "worktree.requested") return beginPreparationCheckoutLaunch({
27424
+ startedAt: snapshot?.startedAt ?? event.createdAt,
27425
+ worktreePath: payloadString(event.payload, "worktreePath") ?? snapshot?.worktreePath ?? null
27426
+ });
27427
+ if (!snapshot && event.kind !== "worktree.stage" && event.kind !== "worktree.failed") snapshot = beginPreparationCheckoutLaunch({ startedAt: event.createdAt });
27428
+ if (!snapshot) return snapshot;
27429
+ return CHECKOUT_LAUNCH_EVENT_HANDLERS[event.kind]?.(snapshot, event) ?? snapshot;
27430
+ }
27431
+ function setSetup(snapshot, event, status, detail) {
27432
+ return replaceStage(ensurePreparation(snapshot, event.createdAt), "setup", {
27433
+ status,
27434
+ detail
27435
+ });
27436
+ }
27437
+ function applyCreated(snapshot, event) {
27438
+ return {
27439
+ ...snapshot,
27440
+ worktreePath: payloadString(event.payload, "worktreePath") ?? snapshot.worktreePath
27441
+ };
27442
+ }
27443
+ function applyOutput(snapshot, event) {
27444
+ const detail = payloadString(event.payload, "detail") ?? event.summary ?? null;
27445
+ const match = detail ? /Updating files:\s+(\d+)%/.exec(detail) : null;
27446
+ if (!match) return snapshot;
27447
+ return replaceStage(ensurePreparation(snapshot, event.createdAt), "checkout", {
27448
+ status: "running",
27449
+ detail: `${match[1]}%`
27450
+ });
27451
+ }
27452
+ function applyAgentStarting(snapshot, event) {
27453
+ const prepared = ensurePreparation(snapshot, event.createdAt);
27454
+ return {
27455
+ ...replaceStage(event.payload?.setupRequested === false ? setSetup(prepared, event, "skipped", "Not requested") : prepared, "agent", {
27456
+ status: "running",
27457
+ detail: event.summary ?? "Starting agent"
27458
+ }),
27459
+ cancellable: false
27460
+ };
27461
+ }
27462
+ function applyFailed(snapshot, event) {
27463
+ snapshot = ensurePreparation(snapshot, event.createdAt);
27464
+ const detail = payloadString(event.payload, "detail") ?? event.summary ?? snapshot.error;
27465
+ const running = snapshot.stages.find((stage) => stage.status === "running");
27466
+ return {
27467
+ ...running ? replaceStage(snapshot, running.id, {
27468
+ status: "failed",
27469
+ detail
27470
+ }) : snapshot,
27471
+ phase: "failed",
27472
+ error: detail ?? "Checkout launch failed",
27473
+ completedAt: event.createdAt,
27474
+ cancellable: false
27475
+ };
27476
+ }
27477
+ function applyCancelled(snapshot, event) {
27478
+ return {
27479
+ ...snapshot,
27480
+ phase: "cancelled",
27481
+ error: event.summary ?? "Launch cancelled",
27482
+ completedAt: event.createdAt,
27483
+ cancellable: false
27484
+ };
27485
+ }
27486
+ const CHECKOUT_LAUNCH_EVENT_HANDLERS = {
27487
+ "worktree.stage": applyStage,
27488
+ "worktree.created": applyCreated,
27489
+ "worktree.output": applyOutput,
27490
+ "setup-script.skipped": (snapshot, event) => setSetup(snapshot, event, "skipped", event.summary ?? "No setup script configured"),
27491
+ "setup-script.running": (snapshot, event) => setSetup(snapshot, event, "running", event.summary ?? null),
27492
+ "setup-script.started": (snapshot, event) => setSetup(snapshot, event, "done", event.summary ?? "Running in terminal"),
27493
+ "setup-script.completed": (snapshot, event) => setSetup(snapshot, event, "done", event.summary ?? null),
27494
+ "setup-script.failed": (snapshot, event) => setSetup(snapshot, event, "failed", event.summary ?? "Setup script failed"),
27495
+ "launch.agent-starting": applyAgentStarting,
27496
+ "worktree.failed": applyFailed,
27497
+ "launch.cancelled": applyCancelled
27498
+ };
27499
+ function withCheckoutLaunchTurnStarted(snapshot, turnStartedAt) {
27500
+ if (!turnStartedAt) return snapshot;
27501
+ const agent = snapshot.stages.find((stage) => stage.id === "agent");
27502
+ return settlePhase({
27503
+ ...agent && (agent.status === "running" || agent.status === "done") ? replaceStage(snapshot, "agent", {
27504
+ status: "done",
27505
+ detail: agent.detail
27506
+ }) : snapshot,
27507
+ turnStartedAt
27508
+ });
27509
+ }
27510
+ function readCheckoutLaunchSnapshot(activity) {
27511
+ if (activity.kind !== "checkout-launch") return null;
27512
+ const payload = activity.payload;
27513
+ if (!payload || typeof payload !== "object") return null;
27514
+ const record = payload;
27515
+ if (record.phase !== "running" && record.phase !== "done" && record.phase !== "failed" && record.phase !== "cancelled") return null;
27516
+ if (!Array.isArray(record.stages) || typeof record.startedAt !== "string") return null;
27517
+ return {
27518
+ phase: record.phase,
27519
+ stages: record.stages,
27520
+ startedAt: record.startedAt,
27521
+ completedAt: record.completedAt ?? null,
27522
+ error: record.error ?? null,
27523
+ cancellable: record.cancellable === true,
27524
+ worktreePath: record.worktreePath ?? null,
27525
+ turnStartedAt: record.turnStartedAt ?? null
27526
+ };
27527
+ }
27528
+ //#endregion
27275
27529
  //#region ../../packages/contracts/src/cmmdProjectPatch.ts
27276
27530
  const CMMD_PROJECT_PATCH_FIELDS = {
27277
27531
  title: "requiredText",
@@ -66433,7 +66687,7 @@ function normalizeNumberish(value) {
66433
66687
  }
66434
66688
  //#endregion
66435
66689
  //#region package.json
66436
- var version$1 = "0.14.1";
66690
+ var version$1 = "0.14.2";
66437
66691
  //#endregion
66438
66692
  //#region src/sentry.ts
66439
66693
  const SERVER_APP_NAME = "forge-server";
@@ -66719,6 +66973,12 @@ function deriveAuthClientMetadata(input) {
66719
66973
  * Hosts a PaaS assigns automatically. They are reachable, but they are not the
66720
66974
  * domain the product is registered under, so they must never end up in an OAuth
66721
66975
  * `redirect_uri`.
66976
+ *
66977
+ * The hosted web channels (forge#3557) are the deliberate exception: their
66978
+ * `.up.railway.app` hosts ARE product surfaces, the operator enumerates them in
66979
+ * `FORGE_WEB_CHANNEL_ORIGINS`, and CMMD's `cmmd-forge-web` OAuth client lists
66980
+ * their callback URIs as registered redirect URIs. Every other platform host
66981
+ * stays excluded.
66722
66982
  */
66723
66983
  const PLATFORM_DEFAULT_HOST_SUFFIXES = [".up.railway.app"];
66724
66984
  function isPlatformDefaultHost(hostname) {
@@ -66757,6 +67017,41 @@ function resolveForgePublicUrl(env = process.env) {
66757
67017
  if (canonicalDomain.toLowerCase() === configuredHost.toLowerCase()) return configured;
66758
67018
  return `https://${canonicalDomain}`.replace(/\/$/, "");
66759
67019
  }
67020
+ /**
67021
+ * Hosted web channel origins (forge#3557) allowed to complete OAuth against
67022
+ * this server, from `FORGE_WEB_CHANNEL_ORIGINS`.
67023
+ *
67024
+ * The channels serve the web bundle from their own domains and forward `/api`
67025
+ * here with `x-forwarded-host` set to the channel host. Login must build its
67026
+ * `redirect_uri` from that host, or CMMD's authorize round-trip returns the
67027
+ * browser to `FORGE_PUBLIC_URL` — an origin where the login's state and PKCE
67028
+ * cookies do not exist. Because anything on the internet can also send this
67029
+ * server an `x-forwarded-host` header, the accepted hosts are never inferred
67030
+ * from the request: the operator enumerates the exact channel origins, and
67031
+ * only those count.
67032
+ *
67033
+ * Entries are comma-separated origins (`https://host[:port]`); a bare hostname
67034
+ * assumes https. Every entry normalizes to its URL origin, so stray path,
67035
+ * query, or userinfo components never reach a redirect URI. Whitespace,
67036
+ * trailing slashes, and unparseable entries are dropped.
67037
+ */
67038
+ function resolveForgeWebChannelOrigins(env = process.env) {
67039
+ return (env.FORGE_WEB_CHANNEL_ORIGINS ?? "").split(",").map((entry) => entry.trim().replace(/\/+$/, "")).filter((entry) => entry.length > 0).map((entry) => entry.includes("://") ? entry : `https://${entry}`).filter((entry) => URL.canParse(entry)).map((entry) => new URL(entry).origin).filter((origin) => origin !== "null");
67040
+ }
67041
+ /**
67042
+ * The allowlisted channel origin for a forwarded host, or null when the host
67043
+ * is not one. Matching is on the URL host — hostname plus explicit port — so
67044
+ * an entry with a port only matches that exact host:port, and a lookalike or
67045
+ * suffix host never matches. The returned origin is the operator's registered
67046
+ * form, scheme included, so it is exactly the redirect URI CMMD's client
67047
+ * registry holds.
67048
+ */
67049
+ function matchForgeWebChannelOrigin(forwardedHost, env = process.env) {
67050
+ const candidate = forwardedHost.trim().toLowerCase();
67051
+ if (!candidate) return null;
67052
+ for (const origin of resolveForgeWebChannelOrigins(env)) if (new URL(origin).host.toLowerCase() === candidate) return origin;
67053
+ return null;
67054
+ }
66760
67055
  function forgeConfiguredPublicUrl() {
66761
67056
  return resolveForgePublicUrl();
66762
67057
  }
@@ -66798,7 +67093,11 @@ function forgePublicUrlForRequest(request) {
66798
67093
  const forwardedHost = normalizeForwardedHeaderValue(request.headers["x-forwarded-host"]);
66799
67094
  const forwardedProto = normalizeForwardedHeaderValue(request.headers["x-forwarded-proto"]) ?? "https";
66800
67095
  if (forwardedHost && (isLoopbackOAuthHost(forwardedHost) || isPrivateDevOAuthHost(forwardedHost))) return `${forwardedProto === "https" ? "https" : "http"}://${forwardedHost}`.replace(/\/$/, "");
66801
- if (forwardedHost) return forgeConfiguredPublicUrl();
67096
+ if (forwardedHost) {
67097
+ const channelOrigin = matchForgeWebChannelOrigin(forwardedHost);
67098
+ if (channelOrigin) return channelOrigin;
67099
+ return forgeConfiguredPublicUrl();
67100
+ }
66802
67101
  const directHost = normalizeForwardedHeaderValue(request.headers["host"]);
66803
67102
  if (directHost && (isLoopbackOAuthHost(directHost) || isPrivateDevOAuthHost(directHost))) return `http://${directHost}`.replace(/\/$/, "");
66804
67103
  return forgeConfiguredPublicUrl();
@@ -70750,6 +71049,19 @@ function createCloudflareTurnIceServerResolver(options) {
70750
71049
  }
70751
71050
  //#endregion
70752
71051
  //#region src/http.ts
71052
+ /**
71053
+ * What the catch-all does with a non-API GET. A managed cloud surface is
71054
+ * runtime-only no matter what files exist on disk — the web client's single
71055
+ * home is the static channels (forge#3567) — while a local server either
71056
+ * serves its bundle or reports itself unconfigured.
71057
+ */
71058
+ function resolveWebServingOutcome(input) {
71059
+ if (input.managedCloudSurface) return { kind: "runtime-only" };
71060
+ return input.staticDir ? {
71061
+ kind: "serve",
71062
+ staticDir: input.staticDir
71063
+ } : { kind: "unconfigured" };
71064
+ }
70753
71065
  const PROJECT_FAVICON_CACHE_CONTROL = "public, max-age=3600";
70754
71066
  const PROJECT_FAVICON_MISS_CACHE_CONTROL = "public, max-age=300";
70755
71067
  /**
@@ -71012,8 +71324,16 @@ const staticAndDevRouteLayer = add$1("GET", "*", require_Schema$1.gen(function*
71012
71324
  }, { status: 404 });
71013
71325
  const config = yield* ServerConfig;
71014
71326
  if (config.devUrl && isLoopbackHostname(url.value.hostname)) return require_HttpServer.redirect(resolveDevRedirectUrl(config.devUrl, url.value), { status: 302 });
71015
- const staticDir = config.staticDir ?? (config.devUrl ? yield* resolveStaticDir() : void 0);
71016
- if (!staticDir) return require_HttpServer.text("No static directory configured and no dev URL set.", { status: 503 });
71327
+ const outcome = resolveWebServingOutcome({
71328
+ staticDir: config.staticDir ?? (config.devUrl ? yield* resolveStaticDir() : void 0),
71329
+ managedCloudSurface: (config.forgeCloudShellMode ?? false) || (config.forgeCmmdRuntimeMode ?? false)
71330
+ });
71331
+ if (outcome.kind === "runtime-only") return require_HttpServer.jsonUnsafe({
71332
+ error: "not_found",
71333
+ message: "This server does not serve the web client."
71334
+ }, { status: 404 });
71335
+ if (outcome.kind === "unconfigured") return require_HttpServer.text("No static directory configured and no dev URL set.", { status: 503 });
71336
+ const staticDir = outcome.staticDir;
71017
71337
  const fileSystem = yield* require_Path.FileSystem;
71018
71338
  const path = yield* require_Path.Path;
71019
71339
  const staticRoot = path.resolve(staticDir);
@@ -88846,7 +89166,7 @@ function refreshForgeManagedGitHubRemoteCredentials(input, dependencies = {
88846
89166
  }));
88847
89167
  isCacheManaged = helper.code === 0 && helper.stdout.includes("cache");
88848
89168
  }
88849
- if (!isEmbedded && !isCacheManaged) return {
89169
+ if (!isEmbedded && !isCacheManaged && !input.allowUnmanagedRemote) return {
88850
89170
  status: 200,
88851
89171
  body: {
88852
89172
  refreshed: false,
@@ -94548,6 +94868,37 @@ const toBootstrapDispatchCommandCauseError = (cause) => {
94548
94868
  });
94549
94869
  };
94550
94870
  const bootstrapCommandId = (command, stage) => CommandId.make(`server:${stage}:${command.commandId}`);
94871
+ const publishCheckoutLaunchSnapshot = (input) => input.orchestrationEngine.dispatch({
94872
+ type: "thread.activity.append",
94873
+ commandId: CommandId.make(`server:checkout-launch:${crypto.randomUUID()}`),
94874
+ threadId: input.threadId,
94875
+ activity: {
94876
+ id: EventId.make(checkoutLaunchActivityId(input.threadId)),
94877
+ tone: input.snapshot.phase === "failed" ? "error" : "info",
94878
+ kind: CHECKOUT_LAUNCH_ACTIVITY_KIND,
94879
+ summary: "Checkout launch",
94880
+ payload: input.snapshot,
94881
+ turnId: null,
94882
+ createdAt: input.createdAt
94883
+ },
94884
+ createdAt: input.createdAt
94885
+ });
94886
+ const recordCheckoutLaunchEvent = (input) => {
94887
+ const next = reduceCheckoutLaunch(input.launch.snapshot, {
94888
+ kind: input.kind,
94889
+ createdAt: input.createdAt,
94890
+ summary: input.summary,
94891
+ payload: input.payload
94892
+ });
94893
+ input.launch.snapshot = next;
94894
+ if (!next) return require_Schema$1.void_;
94895
+ return publishCheckoutLaunchSnapshot({
94896
+ orchestrationEngine: input.orchestrationEngine,
94897
+ threadId: input.threadId,
94898
+ snapshot: next,
94899
+ createdAt: input.createdAt
94900
+ });
94901
+ };
94551
94902
  const appendSetupScriptActivity = (input) => input.orchestrationEngine.dispatch({
94552
94903
  type: "thread.activity.append",
94553
94904
  commandId: input.commandId,
@@ -94562,7 +94913,15 @@ const appendSetupScriptActivity = (input) => input.orchestrationEngine.dispatch(
94562
94913
  createdAt: input.createdAt
94563
94914
  },
94564
94915
  createdAt: input.createdAt
94565
- });
94916
+ }).pipe(require_Schema$1.andThen(() => recordCheckoutLaunchEvent({
94917
+ orchestrationEngine: input.orchestrationEngine,
94918
+ threadId: input.threadId,
94919
+ launch: input.launch,
94920
+ kind: input.kind,
94921
+ summary: input.summary,
94922
+ createdAt: input.createdAt,
94923
+ payload: input.payload
94924
+ })));
94566
94925
  const appendWorktreeActivity = (input) => input.orchestrationEngine.dispatch({
94567
94926
  type: "thread.activity.append",
94568
94927
  commandId: input.commandId,
@@ -94577,7 +94936,15 @@ const appendWorktreeActivity = (input) => input.orchestrationEngine.dispatch({
94577
94936
  createdAt: input.createdAt
94578
94937
  },
94579
94938
  createdAt: input.createdAt
94580
- });
94939
+ }).pipe(require_Schema$1.andThen(() => recordCheckoutLaunchEvent({
94940
+ orchestrationEngine: input.orchestrationEngine,
94941
+ threadId: input.threadId,
94942
+ launch: input.launch,
94943
+ kind: input.kind,
94944
+ summary: input.summary,
94945
+ createdAt: input.createdAt,
94946
+ payload: input.payload
94947
+ })));
94581
94948
  const truncateBootstrapOutputLine = (line) => {
94582
94949
  const trimmed = line.trim();
94583
94950
  if (trimmed.length <= MAX_BOOTSTRAP_OUTPUT_LINE_LENGTH) return trimmed;
@@ -94687,9 +95054,11 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94687
95054
  summary: "Creating worktree",
94688
95055
  createdAt: requestedAt,
94689
95056
  payload: requestedPayload,
94690
- tone: "info"
95057
+ tone: "info",
95058
+ launch: input.launch
94691
95059
  });
94692
95060
  if (bootstrapWorktree.startFromOrigin) {
95061
+ if (input.refreshSourceControlCredentials) yield* input.refreshSourceControlCredentials(projectCwd);
94693
95062
  if (!input.git.fetch) return yield* require_Schema$1.fail(/* @__PURE__ */ new Error("Git fetch is unavailable for origin worktree preparation."));
94694
95063
  yield* input.git.fetch({
94695
95064
  cwd: projectCwd,
@@ -94711,7 +95080,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94711
95080
  detail,
94712
95081
  stage: "fetch"
94713
95082
  },
94714
- tone: "error"
95083
+ tone: "error",
95084
+ launch: input.launch
94715
95085
  }).pipe(require_Schema$1.andThen(require_Schema$1.failCause(cause)));
94716
95086
  }));
94717
95087
  }
@@ -94729,7 +95099,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94729
95099
  summary: "Preparing worktree",
94730
95100
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
94731
95101
  payload: update,
94732
- tone: "info"
95102
+ tone: "info",
95103
+ launch: input.launch
94733
95104
  }).pipe(require_Schema$1.asVoid, require_Schema$1.ignore),
94734
95105
  progress: {
94735
95106
  onStdoutLine: (line) => {
@@ -94747,7 +95118,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94747
95118
  stream: "stdout",
94748
95119
  detail
94749
95120
  },
94750
- tone: "info"
95121
+ tone: "info",
95122
+ launch: input.launch
94751
95123
  }).pipe(require_Schema$1.asVoid, require_Schema$1.ignore);
94752
95124
  },
94753
95125
  onStderrLine: (line) => {
@@ -94765,7 +95137,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94765
95137
  stream: "stderr",
94766
95138
  detail
94767
95139
  },
94768
- tone: "info"
95140
+ tone: "info",
95141
+ launch: input.launch
94769
95142
  }).pipe(require_Schema$1.asVoid, require_Schema$1.ignore);
94770
95143
  }
94771
95144
  }
@@ -94784,7 +95157,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94784
95157
  ...requestedPayload,
94785
95158
  detail
94786
95159
  },
94787
- tone: "error"
95160
+ tone: "error",
95161
+ launch: input.launch
94788
95162
  }).pipe(require_Schema$1.andThen(require_Schema$1.failCause(cause)));
94789
95163
  }));
94790
95164
  const worktreePath = worktree.worktree.path;
@@ -94808,7 +95182,8 @@ const prepareBootstrapWorktree = (input) => require_Schema$1.gen(function* () {
94808
95182
  worktreePath,
94809
95183
  checkedOutBranch: worktree.worktree.branch
94810
95184
  },
94811
- tone: "info"
95185
+ tone: "info",
95186
+ launch: input.launch
94812
95187
  });
94813
95188
  return {
94814
95189
  worktreePath,
@@ -94824,6 +95199,7 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94824
95199
  let targetProjectCwd = bootstrap?.prepareWorktree?.projectCwd;
94825
95200
  let targetWorktreePath = bootstrap?.createThread?.worktreePath ?? null;
94826
95201
  let worktreeFailureReported = false;
95202
+ const launch = { snapshot: null };
94827
95203
  const cleanupCreatedThread = () => createdThread && !worktreeFailureReported ? orchestrationEngine.dispatch({
94828
95204
  type: "thread.delete",
94829
95205
  commandId: bootstrapCommandId(command, "bootstrap-thread-delete"),
@@ -94842,7 +95218,8 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94842
95218
  detail,
94843
95219
  worktreePath: record.worktreePath
94844
95220
  },
94845
- tone: "error"
95221
+ tone: "error",
95222
+ launch
94846
95223
  }).pipe(require_Schema$1.ignoreCause({ log: false }), require_Schema$1.flatMap(() => require_Schema$1.logWarning("bootstrap turn start failed to launch setup script", {
94847
95224
  threadId: command.threadId,
94848
95225
  worktreePath: record.worktreePath,
@@ -94864,7 +95241,8 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94864
95241
  summary: "Starting setup script",
94865
95242
  createdAt: record.requestedAt,
94866
95243
  payload,
94867
- tone: "info"
95244
+ tone: "info",
95245
+ launch
94868
95246
  }), appendSetupScriptActivity({
94869
95247
  orchestrationEngine,
94870
95248
  threadId: command.threadId,
@@ -94873,7 +95251,8 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94873
95251
  summary: "Setup script started",
94874
95252
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
94875
95253
  payload,
94876
- tone: "info"
95254
+ tone: "info",
95255
+ launch
94877
95256
  })]).pipe(require_Schema$1.asVoid, require_Schema$1.catch_((error) => require_Schema$1.logWarning("bootstrap turn start launched setup script but failed to record setup activity", {
94878
95257
  threadId: command.threadId,
94879
95258
  worktreePath: record.worktreePath,
@@ -94905,7 +95284,8 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94905
95284
  summary: "No setup script configured",
94906
95285
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
94907
95286
  payload: {},
94908
- tone: "info"
95287
+ tone: "info",
95288
+ launch
94909
95289
  }).pipe(require_Schema$1.asVoid, require_Schema$1.ignore);
94910
95290
  return recordSetupScriptStarted({
94911
95291
  requestedAt,
@@ -94926,7 +95306,9 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94926
95306
  orchestrationEngine,
94927
95307
  git,
94928
95308
  gitStatusBroadcaster,
94929
- command
95309
+ ...input.refreshSourceControlCredentials ? { refreshSourceControlCredentials: input.refreshSourceControlCredentials } : {},
95310
+ command,
95311
+ launch
94930
95312
  }).pipe(require_Schema$1.catchCause((cause) => {
94931
95313
  if (!require_Schema$1.hasInterruptsOnly(cause)) worktreeFailureReported = true;
94932
95314
  return require_Schema$1.failCause(cause);
@@ -94944,10 +95326,22 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94944
95326
  summary: "Starting agent",
94945
95327
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
94946
95328
  payload: { setupRequested: bootstrap.runSetupScript === true },
94947
- tone: "info"
95329
+ tone: "info",
95330
+ launch
94948
95331
  }).pipe(require_Schema$1.ignore);
94949
95332
  sealBootstrapCommand(orchestrationEngine, command.commandId);
94950
- return yield* orchestrationEngine.dispatch(finalTurnStartCommand);
95333
+ const started = yield* orchestrationEngine.dispatch(finalTurnStartCommand);
95334
+ if (launch.snapshot && bootstrap?.prepareWorktree) {
95335
+ const settledAt = (/* @__PURE__ */ new Date()).toISOString();
95336
+ launch.snapshot = withCheckoutLaunchTurnStarted(launch.snapshot, settledAt);
95337
+ yield* publishCheckoutLaunchSnapshot({
95338
+ orchestrationEngine,
95339
+ threadId: command.threadId,
95340
+ snapshot: launch.snapshot,
95341
+ createdAt: settledAt
95342
+ }).pipe(require_Schema$1.ignore);
95343
+ }
95344
+ return started;
94951
95345
  });
94952
95346
  return yield* runBootstrapCommand(orchestrationEngine, command.commandId, bootstrapProgram.pipe(require_Schema$1.onInterrupt(() => appendWorktreeActivity({
94953
95347
  orchestrationEngine,
@@ -94957,7 +95351,8 @@ const dispatchBootstrapTurnStart$1 = (input, command) => require_Schema$1.gen(fu
94957
95351
  summary: "Launch cancelled",
94958
95352
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
94959
95353
  payload: {},
94960
- tone: "info"
95354
+ tone: "info",
95355
+ launch
94961
95356
  }).pipe(require_Schema$1.ignore)), require_Schema$1.catchCause((cause) => {
94962
95357
  const dispatchError = toBootstrapDispatchCommandCauseError(cause);
94963
95358
  if (require_Schema$1.hasInterruptsOnly(cause)) return require_Schema$1.fail(dispatchError);
@@ -291634,6 +292029,21 @@ function readProviderAccountId(selection) {
291634
292029
  return "providerAccountId" in selection ? selection.providerAccountId : void 0;
291635
292030
  }
291636
292031
  //#endregion
292032
+ //#region src/orchestration/expiredProviderEgressToken.ts
292033
+ const EXPIRED_PROVIDER_EGRESS_TOKEN = "Provider egress token is invalid or expired";
292034
+ /**
292035
+ * The CMMD egress authorizer uses this sentence for a token it will not
292036
+ * accept. A workspace reconnect 401 is a different failure and must not
292037
+ * take this path.
292038
+ *
292039
+ * The token lives in the provider process environment. Stopping that process
292040
+ * lets the next session start mint a new one. A later send of this same turn
292041
+ * delivers the user message a second time, so the recovery stops at the session.
292042
+ */
292043
+ function isExpiredProviderEgressTokenError(message) {
292044
+ return typeof message === "string" && message.includes(EXPIRED_PROVIDER_EGRESS_TOKEN);
292045
+ }
292046
+ //#endregion
291637
292047
  //#region src/persistence/Layers/ProjectionTurns.ts
291638
292048
  const ProjectionTurnDbRowSchema = ProjectionTurn.mapFields(require_Schema$1.assign({
291639
292049
  checkpointFiles: require_Schema$1.fromJsonString(require_Schema$1.ArraySchema(OrchestrationCheckpointFile)),
@@ -293528,6 +293938,7 @@ const make$8 = require_Schema$1.fn("make")(function* () {
293528
293938
  const handleRuntimeError = require_Schema$1.fn("handleRuntimeError")(function* (event, thread, eventTurnId, activeTurnId) {
293529
293939
  if (event.type !== "runtime.error") return;
293530
293940
  if (!shouldApplyRuntimeErrorEvent(activeTurnId, eventTurnId)) return;
293941
+ if (isExpiredProviderEgressTokenError(event.payload.message)) yield* providerService.stopSession({ threadId: thread.id }).pipe(require_Schema$1.catchCause(() => require_Schema$1.void_));
293531
293942
  yield* orchestrationEngine.dispatch({
293532
293943
  type: "thread.session.set",
293533
293944
  commandId: providerCommandId(event, "runtime-error-session-set"),
@@ -301215,7 +301626,7 @@ function resolveBuildCommitFromEnv(env) {
301215
301626
  * environment descriptor down instead of reporting an honest "unknown".
301216
301627
  */
301217
301628
  function readBakedBuildCommit() {
301218
- return "c541d41e992712a7ab25a9ae28ee5e3815e77426";
301629
+ return "a00cf0b653c5ad41933b286a3f108c74a8b61780";
301219
301630
  }
301220
301631
  async function resolveServerBuildCommit(input) {
301221
301632
  if (isFullCommitSha(input.baked)) return input.baked;
@@ -310454,6 +310865,26 @@ function readNonEmptyString(value) {
310454
310865
  //#region src/orchestration/http.ts
310455
310866
  const DISPATCH_CAUSE_DETAIL_LIMIT = 500;
310456
310867
  const DISPATCH_CAUSE_MAX_DEPTH = 8;
310868
+ const resolveBootstrapGithubAuth = (input) => {
310869
+ const runtimeGrantAuth = resolveRuntimeGitHubGrantAuth(input.config, input.headers);
310870
+ return runtimeGrantAuth ? require_Schema$1.succeed(runtimeGrantAuth) : resolveCmmdJwtForSession({
310871
+ sessionId: input.session.sessionId,
310872
+ subject: input.session.subject,
310873
+ logPrefix: "bootstrap-github"
310874
+ });
310875
+ };
310876
+ const refreshBootstrapSourceControlCredentials = (input) => require_Schema$1.gen(function* () {
310877
+ if (!input.auth) return yield* require_Schema$1.fail(/* @__PURE__ */ new Error("CMMD GitHub authorization is unavailable for Work Session bootstrap."));
310878
+ const result = yield* refreshForgeManagedGitHubRemoteCredentials({
310879
+ cwd: input.cwd,
310880
+ auth: typeof input.auth === "object" ? input.auth : {
310881
+ kind: "cmmd-jwt",
310882
+ jwt: input.auth
310883
+ },
310884
+ allowUnmanagedRemote: true
310885
+ }, void 0, input.forgeGitCredentialCache ? "cache" : "embed");
310886
+ if (result.status >= 400) return yield* require_Schema$1.fail(new Error(typeof result.body.error === "string" ? result.body.error : "CMMD GitHub authorization failed for Work Session bootstrap."));
310887
+ });
310457
310888
  /**
310458
310889
  * Render the underlying failure of a dispatch refusal as a single line.
310459
310890
  *
@@ -310894,7 +311325,9 @@ const orchestrationSnapshotRouteLayer = add$1("GET", "/api/orchestration/snapsho
310894
311325
  return require_HttpServer.jsonUnsafe(snapshot, { status: 200 });
310895
311326
  }).pipe(require_Schema$1.catchTag("AuthError", respondToOrchestrationAuthError), require_Schema$1.catchTag("OrchestrationGetSnapshotError", respondToOrchestrationHttpError)));
310896
311327
  const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispatch", require_Schema$1.gen(function* () {
311328
+ const request = yield* require_HttpServer.HttpServerRequest;
310897
311329
  const session = yield* authenticateOwnerSession$1;
311330
+ const config = yield* ServerConfig;
310898
311331
  const orchestrationEngine = yield* OrchestrationEngineService;
310899
311332
  const startup = yield* ServerRuntimeStartup;
310900
311333
  const { result } = yield* admitNormalizedDispatchCommand(yield* require_HttpServer.schemaBodyJson(ClientOrchestrationCommand).pipe(require_Schema$1.mapError((cause) => new OrchestrationDispatchCommandError({
@@ -310912,6 +311345,11 @@ const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispat
310912
311345
  });
310913
311346
  if (admissionRefusal !== null) return yield* new OrchestrationDispatchCommandError({ message: admissionRefusal });
310914
311347
  if (normalizedCommand.type === "thread.turn.start") recordThreadSession(normalizedCommand.threadId, session.sessionId);
311348
+ const bootstrapGithubAuth = normalizedCommand.type === "thread.turn.start" && normalizedCommand.bootstrap ? yield* resolveBootstrapGithubAuth({
311349
+ config,
311350
+ headers: request.headers,
311351
+ session
311352
+ }) : null;
310915
311353
  const dispatchEffect = normalizedCommand.type === "thread.turn.start" && normalizedCommand.bootstrap ? require_Schema$1.gen(function* () {
310916
311354
  const git = yield* require_Schema$1.serviceOption(GitCore);
310917
311355
  const gitStatusBroadcaster = yield* require_Schema$1.serviceOption(GitStatusBroadcaster);
@@ -310921,7 +311359,12 @@ const orchestrationDispatchRouteLayer = add$1("POST", "/api/orchestration/dispat
310921
311359
  orchestrationEngine,
310922
311360
  git: git.value,
310923
311361
  gitStatusBroadcaster: gitStatusBroadcaster.value,
310924
- projectSetupScriptRunner: projectSetupScriptRunner.value
311362
+ projectSetupScriptRunner: projectSetupScriptRunner.value,
311363
+ refreshSourceControlCredentials: (cwd) => refreshBootstrapSourceControlCredentials({
311364
+ forgeGitCredentialCache: config.forgeGitCredentialCache,
311365
+ auth: bootstrapGithubAuth,
311366
+ cwd
311367
+ })
310925
311368
  }, normalizedCommand);
310926
311369
  }).pipe(require_Schema$1.mapError((cause) => new OrchestrationDispatchCommandError({
310927
311370
  message: "Failed to dispatch orchestration command.",
@@ -314090,12 +314533,15 @@ registerProxyRoute({
314090
314533
  orgIdSource: "none"
314091
314534
  });
314092
314535
  const cmmdForgeCloudProjectsListRouteLayer = add$1("GET", "/api/cmmd/forge-cloud-projects", require_Schema$1.gen(function* () {
314536
+ const request = yield* require_HttpServer.HttpServerRequest;
314537
+ const organizationId = normalizeOrgIdQueryParam(new URL(request.url, "http://localhost").searchParams.get("orgId"));
314093
314538
  const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect("forge-cloud-projects");
314094
314539
  if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
314095
314540
  const upstreamUrl = `${resolveCommandAppUrl()}${CMMD_CLOUD_PROJECTS_PATH}`;
314096
314541
  const upstreamOrError = yield* fetchCmmdUpstreamWithRetry(() => fetch(upstreamUrl, { headers: {
314097
314542
  Authorization: `Bearer ${accessToken}`,
314098
- Accept: "application/json"
314543
+ Accept: "application/json",
314544
+ ...organizationId !== void 0 ? { "X-Organization-ID": organizationId } : {}
314099
314545
  } }), "idempotent");
314100
314546
  if (!upstreamOrError.ok) return require_HttpServer.jsonUnsafe({
314101
314547
  error: "CMMD is unreachable. Check your connection.",
@@ -314199,10 +314645,11 @@ const FORGE_RUNTIMES_KICKOFF_FRAME = new TextEncoder().encode(": ok\n\n");
314199
314645
  * is the designed failure mode. Retrying here would stack a second backoff
314200
314646
  * inside the first and delay the frame the client is waiting on.
314201
314647
  */
314202
- function makeFetchForgeCatalogFrameEffect(proxy, upstreamUrl, accessToken) {
314648
+ function makeFetchForgeCatalogFrameEffect(proxy, upstreamUrl, accessToken, organizationId) {
314203
314649
  return require_Schema$1.tryPromise(() => fetch(upstreamUrl, { headers: {
314204
314650
  Authorization: `Bearer ${accessToken}`,
314205
- Accept: "application/json"
314651
+ Accept: "application/json",
314652
+ ...organizationId !== void 0 ? { "X-Organization-ID": organizationId } : {}
314206
314653
  } }).then(async (res) => {
314207
314654
  if (res.status === 401 || res.status === 403) {
314208
314655
  console.warn(`[${proxy.logTag}] upstream auth failure: ${res.status}`);
@@ -314227,9 +314674,11 @@ function makeFetchForgeCatalogFrameEffect(proxy, upstreamUrl, accessToken) {
314227
314674
  */
314228
314675
  function makeForgeCatalogEventsHandler(proxy, upstreamUrl) {
314229
314676
  return require_Schema$1.gen(function* () {
314677
+ const request = yield* require_HttpServer.HttpServerRequest;
314678
+ const organizationId = normalizeOrgIdQueryParam(new URL(request.url, "http://localhost").searchParams.get("orgId"));
314230
314679
  const { session, jwt: accessToken } = yield* makeCmmdProxyAccessTokenEffect(proxy.logTag);
314231
314680
  if (!accessToken) return yield* respondCmmdConnectionRequired(session.sessionId);
314232
- const fetchFrame = makeFetchForgeCatalogFrameEffect(proxy, upstreamUrl, accessToken);
314681
+ const fetchFrame = makeFetchForgeCatalogFrameEffect(proxy, upstreamUrl, accessToken, organizationId);
314233
314682
  const dataStream = require_Path.concat(require_Path.fromEffect(fetchFrame), require_Path.tick(FORGE_RUNTIMES_POLL_INTERVAL).pipe(require_Path.mapEffect(() => fetchFrame))).pipe(require_Path.filter((frame) => frame !== null));
314234
314683
  const keepaliveStream = require_Path.tick(FORGE_RUNTIMES_KEEPALIVE_INTERVAL).pipe(require_Path.map(() => FORGE_RUNTIMES_KEEPALIVE_FRAME));
314235
314684
  const frames = require_Path.concat(require_Path.succeed(FORGE_RUNTIMES_KICKOFF_FRAME), require_Path.merge(dataStream, keepaliveStream)).pipe(require_Path.ensuring(require_Schema$1.sync(() => {
@@ -314720,10 +315169,7 @@ function isLegacyRuntimeConnection(value, expectedRuntimeId) {
314720
315169
  return [
314721
315170
  runtime.runtimeId === expectedRuntimeId,
314722
315171
  runtime.runtimeCapabilityMode === "legacy_env",
314723
- hasCmmdRuntimeSpriteIdentity({
314724
- ...Object.hasOwn(runtime, "spriteName") ? { spriteName: typeof runtime.spriteName === "string" ? runtime.spriteName : null } : {},
314725
- ...Object.hasOwn(runtime, "flyMachineId") ? { flyMachineId: typeof runtime.flyMachineId === "string" ? runtime.flyMachineId : null } : {}
314726
- }),
315172
+ hasCmmdRuntimeSpriteIdentity({ spriteName: typeof runtime.spriteName === "string" ? runtime.spriteName : null }),
314727
315173
  !Object.hasOwn(runtime, "brokerAuthorityAttestedForgeGitCommit"),
314728
315174
  runtime.brokerAuthorityAttestedImageRef === null,
314729
315175
  runtime.brokerAuthorityAttestedImageVersion === null,
@@ -327262,7 +327708,7 @@ const resolveServerConfig = (flags, cliLogLevel, options) => require_Schema$1.ge
327262
327708
  const isManagedCloudSurface = (env.forgeCmmdRuntimeMode ?? false) || (env.forgeCloudShellMode ?? false);
327263
327709
  const autoBootstrapProjectFromCwd = require_Schema$1.getOrElse(resolveOptionPrecedence(require_Schema$1.fromUndefinedOr(options?.forceAutoBootstrapProjectFromCwd), isHeadlessStartup ? require_Schema$1.some(false) : require_Schema$1.none(), normalizedFlags.autoBootstrapProjectFromCwd, require_Schema$1.fromUndefinedOr(env.autoBootstrapProjectFromCwd), require_Schema$1.fromUndefinedOr(bootstrap?.autoBootstrapProjectFromCwd)), () => mode === "web" && !isManagedCloudSurface);
327264
327710
  const logWebSocketEvents = require_Schema$1.getOrElse(resolveOptionPrecedence(normalizedFlags.logWebSocketEvents, require_Schema$1.fromUndefinedOr(env.logWebSocketEvents), require_Schema$1.fromUndefinedOr(bootstrap?.logWebSocketEvents)), () => Boolean(devUrl));
327265
- const staticDir = devUrl ? void 0 : yield* resolveStaticDir();
327711
+ const staticDir = devUrl || isManagedCloudSurface ? void 0 : yield* resolveStaticDir();
327266
327712
  const host = require_Schema$1.getOrElse(resolveOptionPrecedence(normalizedFlags.host, require_Schema$1.fromUndefinedOr(env.host), require_Schema$1.fromUndefinedOr(bootstrap?.host)), () => mode === "desktop" ? "127.0.0.1" : void 0);
327267
327713
  const logLevel = require_Schema$1.getOrElse(cliLogLevel, () => env.logLevel);
327268
327714
  const browserWebRtcIceServers = parseBrowserWebRtcIceServers(env.browserWebRtcIceServers);
@@ -327446,16 +327892,16 @@ const findActiveProjectTarget = require_Schema$1.fn("findActiveProjectTarget")(f
327446
327892
  workspaceRoot: resolved.workspaceRoot
327447
327893
  };
327448
327894
  });
327449
- const fetchLiveOrchestrationSnapshot = (origin, bearerToken$2) => runLiveServerRequest(require_HttpServer.get(`${origin}/api/orchestration/snapshot`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$2)), require_HttpServer.matchStatus({
327895
+ const fetchLiveOrchestrationSnapshot = (origin, bearerToken$3) => runLiveServerRequest(require_HttpServer.get(`${origin}/api/orchestration/snapshot`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$3)), require_HttpServer.matchStatus({
327450
327896
  "2xx": decodeOrchestrationReadModelResponse,
327451
327897
  orElse: (response) => readErrorMessageFromResponse(response).pipe(require_Schema$1.flatMap((message) => require_Schema$1.fail(new Error(message))))
327452
327898
  }));
327453
327899
  const ProjectLeadExplanationEnvelope = require_Schema$1.Struct({ data: ProjectLeadExplanationSchema });
327454
- const fetchLiveProjectLeadExplanation = (origin, bearerToken$1, projectId) => runLiveServerRequest(require_HttpServer.get(`${origin}/api/cmmd/projects/${projectId}/project-lead/explain`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$1)), require_HttpServer.matchStatus({
327900
+ const fetchLiveProjectLeadExplanation = (origin, bearerToken$2, projectId) => runLiveServerRequest(require_HttpServer.get(`${origin}/api/cmmd/projects/${projectId}/project-lead/explain`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$2)), require_HttpServer.matchStatus({
327455
327901
  "2xx": (response) => require_HttpServer.schemaBodyJson$1(ProjectLeadExplanationEnvelope)(response).pipe(require_Schema$1.map((body) => body.data)),
327456
327902
  orElse: (response) => readErrorMessageFromResponse(response).pipe(require_Schema$1.flatMap((message) => require_Schema$1.fail(new Error(message))))
327457
327903
  }));
327458
- const dispatchLiveOrchestrationCommand = (origin, bearerToken$3, command) => require_HttpServer.post(`${origin}/api/orchestration/dispatch`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$3), require_HttpServer.bodyJson(command), require_Schema$1.flatMap((request) => runLiveServerRequest(request, require_HttpServer.matchStatus({
327904
+ const dispatchLiveOrchestrationCommand = (origin, bearerToken$1, command) => require_HttpServer.post(`${origin}/api/orchestration/dispatch`).pipe(require_HttpServer.acceptJson, require_HttpServer.bearerToken(bearerToken$1), require_HttpServer.bodyJson(command), require_Schema$1.flatMap((request) => runLiveServerRequest(request, require_HttpServer.matchStatus({
327459
327905
  "2xx": () => require_Schema$1.void_,
327460
327906
  orElse: (response) => readErrorMessageFromResponse(response).pipe(require_Schema$1.flatMap((message) => require_Schema$1.fail(new Error(message))))
327461
327907
  }))));