@remixhq/claude-plugin 0.1.12 → 0.1.15

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.
@@ -21513,7 +21513,7 @@ var RemixError = class extends Error {
21513
21513
  }
21514
21514
  };
21515
21515
 
21516
- // node_modules/@remixhq/core/dist/chunk-4276ARDF.js
21516
+ // node_modules/@remixhq/core/dist/chunk-B5S3PUIR.js
21517
21517
  async function readJsonSafe(res) {
21518
21518
  const ct = res.headers.get("content-type") ?? "";
21519
21519
  if (!ct.toLowerCase().includes("application/json")) return null;
@@ -21627,11 +21627,33 @@ function createApiClient(config2, opts) {
21627
21627
  const qs = new URLSearchParams();
21628
21628
  if (params?.projectId) qs.set("projectId", params.projectId);
21629
21629
  if (params?.organizationId) qs.set("organizationId", params.organizationId);
21630
+ if (params?.ownership) qs.set("ownership", params.ownership);
21631
+ if (params?.accessScope) qs.set("accessScope", params.accessScope);
21632
+ if (params?.createdBy) qs.set("createdBy", params.createdBy);
21630
21633
  if (params?.forked) qs.set("forked", params.forked);
21634
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21635
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21631
21636
  const suffix = qs.toString() ? `?${qs.toString()}` : "";
21632
21637
  return request(`/v1/apps${suffix}`, { method: "GET" });
21633
21638
  },
21634
21639
  getApp: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}`, { method: "GET" }),
21640
+ getAppContext: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/context`, { method: "GET" }),
21641
+ getAppOverview: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/overview`, { method: "GET" }),
21642
+ listAppTimeline: (appId, params) => {
21643
+ const qs = new URLSearchParams();
21644
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21645
+ if (params?.cursor) qs.set("cursor", params.cursor);
21646
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21647
+ return request(`/v1/apps/${encodeURIComponent(appId)}/timeline${suffix}`, { method: "GET" });
21648
+ },
21649
+ getAppTimelineEvent: (appId, eventId) => request(`/v1/apps/${encodeURIComponent(appId)}/timeline/${encodeURIComponent(eventId)}`, { method: "GET" }),
21650
+ listAppEditQueue: (appId, params) => {
21651
+ const qs = new URLSearchParams();
21652
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21653
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21654
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21655
+ return request(`/v1/apps/${encodeURIComponent(appId)}/edit-queue${suffix}`, { method: "GET" });
21656
+ },
21635
21657
  getMergeRequest: (mrId) => request(`/v1/merge-requests/${encodeURIComponent(mrId)}`, { method: "GET" }),
21636
21658
  presignImportUpload: (payload) => request("/v1/apps/import/upload/presign", { method: "POST", body: JSON.stringify(payload) }),
21637
21659
  importFromUpload: (payload) => request("/v1/apps/import/upload", { method: "POST", body: JSON.stringify(payload) }),
@@ -21713,6 +21735,8 @@ function createApiClient(config2, opts) {
21713
21735
  qs.set("status", params.status);
21714
21736
  }
21715
21737
  if (params?.kind) qs.set("kind", params.kind);
21738
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21739
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21716
21740
  const suffix = qs.toString() ? `?${qs.toString()}` : "";
21717
21741
  return request(`/v1/merge-requests${suffix}`, { method: "GET" });
21718
21742
  },
@@ -21731,24 +21755,60 @@ function createApiClient(config2, opts) {
21731
21755
  method: "POST",
21732
21756
  body: JSON.stringify(payload)
21733
21757
  }),
21734
- listOrganizationMembers: (orgId) => request(`/v1/organizations/${encodeURIComponent(orgId)}/members`, { method: "GET" }),
21758
+ listOrganizationMembers: (orgId, params) => {
21759
+ const qs = new URLSearchParams();
21760
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21761
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21762
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21763
+ return request(`/v1/organizations/${encodeURIComponent(orgId)}/members${suffix}`, { method: "GET" });
21764
+ },
21735
21765
  updateOrganizationMember: (orgId, userId, payload) => request(`/v1/organizations/${encodeURIComponent(orgId)}/members/${encodeURIComponent(userId)}`, {
21736
21766
  method: "PATCH",
21737
21767
  body: JSON.stringify(payload)
21738
21768
  }),
21739
- listProjectMembers: (projectId) => request(`/v1/projects/${encodeURIComponent(projectId)}/members`, { method: "GET" }),
21769
+ listProjectMembers: (projectId, params) => {
21770
+ const qs = new URLSearchParams();
21771
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21772
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21773
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21774
+ return request(`/v1/projects/${encodeURIComponent(projectId)}/members${suffix}`, { method: "GET" });
21775
+ },
21740
21776
  updateProjectMember: (projectId, userId, payload) => request(`/v1/projects/${encodeURIComponent(projectId)}/members/${encodeURIComponent(userId)}`, {
21741
21777
  method: "PATCH",
21742
21778
  body: JSON.stringify(payload)
21743
21779
  }),
21744
- listAppMembers: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/members`, { method: "GET" }),
21780
+ listAppMembers: (appId, params) => {
21781
+ const qs = new URLSearchParams();
21782
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21783
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21784
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21785
+ return request(`/v1/apps/${encodeURIComponent(appId)}/members${suffix}`, { method: "GET" });
21786
+ },
21745
21787
  updateAppMember: (appId, userId, payload) => request(`/v1/apps/${encodeURIComponent(appId)}/members/${encodeURIComponent(userId)}`, {
21746
21788
  method: "PATCH",
21747
21789
  body: JSON.stringify(payload)
21748
21790
  }),
21749
- listOrganizationInvites: (orgId) => request(`/v1/organizations/${encodeURIComponent(orgId)}/invitations`, { method: "GET" }),
21750
- listProjectInvites: (projectId) => request(`/v1/projects/${encodeURIComponent(projectId)}/invitations`, { method: "GET" }),
21751
- listAppInvites: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/invitations`, { method: "GET" }),
21791
+ listOrganizationInvites: (orgId, params) => {
21792
+ const qs = new URLSearchParams();
21793
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21794
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21795
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21796
+ return request(`/v1/organizations/${encodeURIComponent(orgId)}/invitations${suffix}`, { method: "GET" });
21797
+ },
21798
+ listProjectInvites: (projectId, params) => {
21799
+ const qs = new URLSearchParams();
21800
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21801
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21802
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21803
+ return request(`/v1/projects/${encodeURIComponent(projectId)}/invitations${suffix}`, { method: "GET" });
21804
+ },
21805
+ listAppInvites: (appId, params) => {
21806
+ const qs = new URLSearchParams();
21807
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21808
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21809
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21810
+ return request(`/v1/apps/${encodeURIComponent(appId)}/invitations${suffix}`, { method: "GET" });
21811
+ },
21752
21812
  resendOrganizationInvite: (orgId, inviteId, payload) => request(`/v1/organizations/${encodeURIComponent(orgId)}/invitations/${encodeURIComponent(inviteId)}/resend`, {
21753
21813
  method: "POST",
21754
21814
  body: JSON.stringify(payload ?? {})
@@ -21770,6 +21830,7 @@ function createApiClient(config2, opts) {
21770
21830
  revokeAppInvite: (appId, inviteId) => request(`/v1/apps/${encodeURIComponent(appId)}/invitations/${encodeURIComponent(inviteId)}`, {
21771
21831
  method: "DELETE"
21772
21832
  }),
21833
+ acceptInvitation: (payload) => request("/v1/invitations/accept", { method: "POST", body: JSON.stringify(payload) }),
21773
21834
  syncUpstreamApp: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/sync-upstream`, {
21774
21835
  method: "POST",
21775
21836
  body: JSON.stringify({})
@@ -21805,7 +21866,31 @@ function createApiClient(config2, opts) {
21805
21866
  `/v1/apps/${encodeURIComponent(appId)}/bundles/${encodeURIComponent(bundleId)}/assets/download?${qs.toString()}`,
21806
21867
  { method: "GET" }
21807
21868
  );
21808
- }
21869
+ },
21870
+ listAgentRuns: (appId, params) => {
21871
+ const qs = new URLSearchParams();
21872
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21873
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21874
+ if (params?.status) qs.set("status", params.status);
21875
+ if (params?.currentPhase) qs.set("currentPhase", params.currentPhase);
21876
+ if (params?.createdAfter) qs.set("createdAfter", params.createdAfter);
21877
+ if (params?.createdBefore) qs.set("createdBefore", params.createdBefore);
21878
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21879
+ return request(`/v1/apps/${encodeURIComponent(appId)}/agent-runs${suffix}`, { method: "GET" });
21880
+ },
21881
+ getAgentRun: (appId, runId) => request(`/v1/apps/${encodeURIComponent(appId)}/agent-runs/${encodeURIComponent(runId)}`, { method: "GET" }),
21882
+ listAgentRunEvents: (appId, runId, params) => {
21883
+ const qs = new URLSearchParams();
21884
+ if (typeof params?.limit === "number") qs.set("limit", String(params.limit));
21885
+ if (typeof params?.offset === "number") qs.set("offset", String(params.offset));
21886
+ if (params?.createdAfter) qs.set("createdAfter", params.createdAfter);
21887
+ if (params?.createdBefore) qs.set("createdBefore", params.createdBefore);
21888
+ const suffix = qs.toString() ? `?${qs.toString()}` : "";
21889
+ return request(`/v1/apps/${encodeURIComponent(appId)}/agent-runs/${encodeURIComponent(runId)}/events${suffix}`, {
21890
+ method: "GET"
21891
+ });
21892
+ },
21893
+ getSandboxStatus: (appId) => request(`/v1/apps/${encodeURIComponent(appId)}/sandbox/status`, { method: "GET" })
21809
21894
  };
21810
21895
  }
21811
21896
 
@@ -41707,7 +41792,7 @@ var REMIX_ERROR_CODES = {
41707
41792
  // node_modules/@remixhq/mcp/dist/index.js
41708
41793
  var import_path11 = __toESM(require("path"), 1);
41709
41794
 
41710
- // node_modules/@remixhq/core/dist/chunk-FAZUMWBS.js
41795
+ // node_modules/@remixhq/core/dist/chunk-GEHSFPCD.js
41711
41796
  var import_promises2 = __toESM(require("fs/promises"), 1);
41712
41797
  var import_path2 = __toESM(require("path"), 1);
41713
41798
  var import_promises3 = __toESM(require("fs/promises"), 1);
@@ -41785,7 +41870,7 @@ async function writeCollabBinding(repoRoot, binding) {
41785
41870
  return filePath;
41786
41871
  }
41787
41872
 
41788
- // node_modules/@remixhq/core/dist/chunk-RREREIGW.js
41873
+ // node_modules/@remixhq/core/dist/chunk-J3J4PBQ7.js
41789
41874
  var import_promises15 = __toESM(require("fs/promises"), 1);
41790
41875
  var import_crypto = require("crypto");
41791
41876
  var import_os2 = __toESM(require("os"), 1);
@@ -48566,7 +48651,7 @@ var {
48566
48651
  getCancelSignal: getCancelSignal2
48567
48652
  } = getIpcExport();
48568
48653
 
48569
- // node_modules/@remixhq/core/dist/chunk-RREREIGW.js
48654
+ // node_modules/@remixhq/core/dist/chunk-J3J4PBQ7.js
48570
48655
  var GIT_REMOTE_PROTOCOL_RE = /^(https?|ssh):\/\//i;
48571
48656
  var SCP_LIKE_GIT_REMOTE_RE = /^(?<user>[^@\s]+)@(?<host>[^:\s]+):(?<path>[^\\\s]+)$/;
48572
48657
  var CANONICAL_GIT_REMOTE_RE = /^(?<host>(?:localhost|[a-z0-9.-]+))\/(?<path>[^\\\s]+)$/i;
@@ -48813,6 +48898,13 @@ async function listUntrackedFiles(cwd) {
48813
48898
  return [];
48814
48899
  }
48815
48900
  }
48901
+ async function getWorkspaceDiff(cwd) {
48902
+ const snapshot = await getWorkspaceSnapshot(cwd);
48903
+ return {
48904
+ diff: snapshot.diff,
48905
+ includedUntrackedPaths: snapshot.includedUntrackedPaths
48906
+ };
48907
+ }
48816
48908
  async function getWorkspaceSnapshot(cwd) {
48817
48909
  const headCommitHash = await getHeadCommitHash(cwd);
48818
48910
  if (!headCommitHash) {
@@ -49252,6 +49344,26 @@ function unwrapResponseObject(resp, label) {
49252
49344
  }
49253
49345
  return obj;
49254
49346
  }
49347
+ var DEFAULT_PAGINATION_LIMIT = 25;
49348
+ var MAX_PAGINATION_LIMIT = 50;
49349
+ function normalizePagination(params) {
49350
+ const rawLimit = typeof params?.limit === "number" && Number.isFinite(params.limit) ? Math.trunc(params.limit) : DEFAULT_PAGINATION_LIMIT;
49351
+ const rawOffset = typeof params?.offset === "number" && Number.isFinite(params.offset) ? Math.trunc(params.offset) : 0;
49352
+ return {
49353
+ limit: Math.max(1, Math.min(MAX_PAGINATION_LIMIT, rawLimit)),
49354
+ offset: Math.max(0, rawOffset)
49355
+ };
49356
+ }
49357
+ function paginateOverfetchedItems(items, params) {
49358
+ const pagination = normalizePagination(params);
49359
+ return {
49360
+ items: items.slice(0, pagination.limit),
49361
+ pagination: {
49362
+ ...pagination,
49363
+ hasMore: items.length > pagination.limit
49364
+ }
49365
+ };
49366
+ }
49255
49367
  function unwrapMergeRequest(resp) {
49256
49368
  return unwrapResponseObject(resp, "merge request");
49257
49369
  }
@@ -50201,6 +50313,7 @@ async function collabAdd(params) {
50201
50313
  }
50202
50314
  const { backupPath } = await writeTempUnifiedDiffBackup(diff, "remix-add");
50203
50315
  try {
50316
+ await pollAppReady(params.api, binding.currentAppId);
50204
50317
  if (submissionSnapshot) {
50205
50318
  await assertRepoSnapshotUnchanged(repoRoot, submissionSnapshot, {
50206
50319
  operation: "`remix collab add` auto-sync",
@@ -50345,6 +50458,105 @@ async function collabRecordTurn(params) {
50345
50458
  });
50346
50459
  return unwrapResponseObject(resp, "collab turn");
50347
50460
  }
50461
+ function collectWarnings(value) {
50462
+ if (!Array.isArray(value)) return [];
50463
+ return value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
50464
+ }
50465
+ async function collabFinalizeTurn(params) {
50466
+ const repoRoot = await findGitRoot(params.cwd);
50467
+ const binding = await readCollabBinding(repoRoot);
50468
+ if (!binding) {
50469
+ throw new RemixError("Repository is not bound to Remix.", {
50470
+ exitCode: 2,
50471
+ hint: "Run `remix collab init` first."
50472
+ });
50473
+ }
50474
+ const prompt = params.prompt.trim();
50475
+ const assistantResponse = params.assistantResponse.trim();
50476
+ if (!prompt) throw new RemixError("Prompt is required.", { exitCode: 2 });
50477
+ if (!assistantResponse) throw new RemixError("Assistant response is required.", { exitCode: 2 });
50478
+ const diffSource = params.diffSource ?? (params.diff ? "external" : "worktree");
50479
+ const externalDiff = params.diff?.trim() ?? "";
50480
+ const workspaceDiff = diffSource === "worktree" ? await getWorkspaceDiff(repoRoot) : null;
50481
+ const hasChangedTurn = diffSource === "external" ? externalDiff.length > 0 : Boolean(workspaceDiff?.diff.trim());
50482
+ const currentHeadCommitHash = await getHeadCommitHash(repoRoot);
50483
+ const idempotencyKey = params.idempotencyKey?.trim() || buildDeterministicIdempotencyKey({
50484
+ kind: "collab_finalize_turn_v1",
50485
+ appId: binding.currentAppId,
50486
+ upstreamAppId: binding.upstreamAppId,
50487
+ headCommitHash: currentHeadCommitHash,
50488
+ modeHint: hasChangedTurn ? "changed_turn" : "no_diff_turn",
50489
+ prompt,
50490
+ assistantResponse,
50491
+ externalDiff: diffSource === "external" ? externalDiff : null
50492
+ });
50493
+ if (diffSource === "external" && !hasChangedTurn) {
50494
+ throw new RemixError("External diff is empty.", {
50495
+ exitCode: 2,
50496
+ hint: "Pass a non-empty diff when using external diff submission, or omit the external diff so finalize-turn can inspect the live worktree."
50497
+ });
50498
+ }
50499
+ if (hasChangedTurn) {
50500
+ const localHeadBefore = currentHeadCommitHash;
50501
+ const capturedUntrackedPathsCandidate = diffSource === "worktree" ? await listUntrackedFiles(repoRoot) : [];
50502
+ const changeStep = await collabAdd({
50503
+ api: params.api,
50504
+ cwd: repoRoot,
50505
+ prompt,
50506
+ assistantResponse,
50507
+ diff: diffSource === "external" ? externalDiff : null,
50508
+ diffSource,
50509
+ sync: params.sync,
50510
+ allowBranchMismatch: params.allowBranchMismatch,
50511
+ idempotencyKey,
50512
+ actor: params.actor
50513
+ });
50514
+ const localHeadAfter = await getHeadCommitHash(repoRoot);
50515
+ const warnings = [
50516
+ ...collectWarnings(changeStep.warnings),
50517
+ ...diffSource === "external" && params.sync !== false ? [
50518
+ "Automatic local discard+sync was skipped because the diff came from an external source and may not match the current worktree."
50519
+ ] : []
50520
+ ];
50521
+ const autoSyncRequested = params.sync !== false;
50522
+ const autoSyncEligible = diffSource === "worktree";
50523
+ return {
50524
+ mode: "changed_turn",
50525
+ idempotencyKey,
50526
+ changeStep,
50527
+ collabTurn: null,
50528
+ autoSync: {
50529
+ requested: autoSyncRequested,
50530
+ eligible: autoSyncEligible,
50531
+ attempted: autoSyncRequested && autoSyncEligible,
50532
+ applied: autoSyncRequested && autoSyncEligible,
50533
+ trackedChangesDiscarded: autoSyncRequested && autoSyncEligible,
50534
+ capturedUntrackedPathsCandidate,
50535
+ localHeadBefore,
50536
+ localHeadAfter,
50537
+ localRepoMutated: autoSyncRequested && autoSyncEligible && localHeadBefore !== localHeadAfter
50538
+ },
50539
+ warnings
50540
+ };
50541
+ }
50542
+ const collabTurn = await collabRecordTurn({
50543
+ api: params.api,
50544
+ cwd: repoRoot,
50545
+ prompt,
50546
+ assistantResponse,
50547
+ allowBranchMismatch: params.allowBranchMismatch,
50548
+ idempotencyKey,
50549
+ actor: params.actor
50550
+ });
50551
+ return {
50552
+ mode: "no_diff_turn",
50553
+ idempotencyKey,
50554
+ changeStep: null,
50555
+ collabTurn,
50556
+ autoSync: null,
50557
+ warnings: []
50558
+ };
50559
+ }
50348
50560
  async function collabApprove(params) {
50349
50561
  if (params.mode === "sync-target-repo") {
50350
50562
  if (!params.cwd?.trim()) {
@@ -50602,17 +50814,22 @@ async function collabListMergeRequests(params) {
50602
50814
  appId: params.appId,
50603
50815
  queue: params.queue
50604
50816
  });
50817
+ const pageRequest = normalizePagination(params);
50605
50818
  const resp = await params.api.listMergeRequests({
50606
50819
  queue: params.queue,
50607
50820
  appId,
50608
50821
  status: params.status,
50609
- kind: params.kind ?? "merge"
50822
+ kind: params.kind ?? "merge",
50823
+ limit: pageRequest.limit + 1,
50824
+ offset: pageRequest.offset
50610
50825
  });
50611
50826
  const mergeRequests = unwrapResponseObject(resp, "merge requests");
50827
+ const page = paginateOverfetchedItems(mergeRequests, params);
50612
50828
  return {
50613
50829
  queue: params.queue,
50614
50830
  appId: appId ?? null,
50615
- mergeRequests
50831
+ mergeRequests: page.items,
50832
+ pagination: page.pagination
50616
50833
  };
50617
50834
  }
50618
50835
  async function resolveScopeTarget(params) {
@@ -50651,12 +50868,24 @@ async function collabListMembers(params) {
50651
50868
  scope: params.scope,
50652
50869
  targetId: params.targetId
50653
50870
  });
50654
- const resp = params.scope === "organization" ? await params.api.listOrganizationMembers(targetId) : params.scope === "project" ? await params.api.listProjectMembers(targetId) : await params.api.listAppMembers(targetId);
50871
+ const pageRequest = normalizePagination(params);
50872
+ const resp = params.scope === "organization" ? await params.api.listOrganizationMembers(targetId, {
50873
+ limit: pageRequest.limit + 1,
50874
+ offset: pageRequest.offset
50875
+ }) : params.scope === "project" ? await params.api.listProjectMembers(targetId, {
50876
+ limit: pageRequest.limit + 1,
50877
+ offset: pageRequest.offset
50878
+ }) : await params.api.listAppMembers(targetId, {
50879
+ limit: pageRequest.limit + 1,
50880
+ offset: pageRequest.offset
50881
+ });
50655
50882
  const members = params.scope === "organization" ? unwrapResponseObject(resp, "members") : params.scope === "project" ? unwrapResponseObject(resp, "members") : unwrapResponseObject(resp, "members");
50883
+ const page = paginateOverfetchedItems(members, params);
50656
50884
  return {
50657
50885
  scopeType: params.scope,
50658
50886
  targetId,
50659
- members
50887
+ members: page.items,
50888
+ pagination: page.pagination
50660
50889
  };
50661
50890
  }
50662
50891
  async function collabUpdateMemberRole(params) {
@@ -50850,6 +51079,23 @@ async function collabInvite(params) {
50850
51079
  targetId
50851
51080
  };
50852
51081
  }
51082
+ async function collabList(params) {
51083
+ const pageRequest = normalizePagination(params);
51084
+ const resp = await params.api.listApps({
51085
+ ownership: params.ownership ?? "all",
51086
+ accessScope: params.accessScope ?? "explicit_member",
51087
+ createdBy: params.createdBy,
51088
+ forked: params.forked ?? "all",
51089
+ limit: pageRequest.limit + 1,
51090
+ offset: pageRequest.offset
51091
+ });
51092
+ const apps = unwrapResponseObject(resp, "apps");
51093
+ const page = paginateOverfetchedItems(apps, params);
51094
+ return {
51095
+ apps: page.items,
51096
+ pagination: page.pagination
51097
+ };
51098
+ }
50853
51099
  async function collabReconcile(params) {
50854
51100
  const repoRoot = await findGitRoot(params.cwd);
50855
51101
  const binding = await readCollabBinding(repoRoot);
@@ -51465,6 +51711,8 @@ var ERROR_CODES = {
51465
51711
  METADATA_CONFLICT: "METADATA_CONFLICT",
51466
51712
  DESTRUCTIVE_OPERATION_BLOCKED: "DESTRUCTIVE_OPERATION_BLOCKED",
51467
51713
  CONFIG_INVALID: "CONFIG_INVALID",
51714
+ ACCESS_DENIED: "ACCESS_DENIED",
51715
+ RESOURCE_NOT_FOUND: "RESOURCE_NOT_FOUND",
51468
51716
  INTERNAL_ERROR: "INTERNAL_ERROR"
51469
51717
  };
51470
51718
  var RemixMcpError = class extends Error {
@@ -51480,6 +51728,15 @@ function toStringOrNull(value) {
51480
51728
  const trimmed = value.trim();
51481
51729
  return trimmed.length > 0 ? trimmed : null;
51482
51730
  }
51731
+ function parseJsonObject(value) {
51732
+ if (!value) return null;
51733
+ try {
51734
+ const parsed = JSON.parse(value);
51735
+ return parsed && typeof parsed === "object" ? parsed : null;
51736
+ } catch {
51737
+ return null;
51738
+ }
51739
+ }
51483
51740
  function makeNormalized(params) {
51484
51741
  return {
51485
51742
  code: params.code,
@@ -51493,6 +51750,8 @@ function normalizeByMessage(err) {
51493
51750
  const code = toStringOrNull(err.code);
51494
51751
  const message = toStringOrNull(err.message) ?? "Unexpected error.";
51495
51752
  const hint = toStringOrNull(err.hint);
51753
+ const hintBody = parseJsonObject(hint);
51754
+ const statusCode = typeof hintBody?.statusCode === "number" ? hintBody.statusCode : typeof hintBody?.statusCode === "string" ? Number(hintBody.statusCode) : null;
51496
51755
  if (code === ERROR_CODES.REPO_LOCK_HELD) {
51497
51756
  return makeNormalized({
51498
51757
  code: ERROR_CODES.REPO_LOCK_HELD,
@@ -51593,6 +51852,22 @@ function normalizeByMessage(err) {
51593
51852
  category: "remote_state"
51594
51853
  });
51595
51854
  }
51855
+ if (statusCode === 403) {
51856
+ return makeNormalized({
51857
+ code: ERROR_CODES.ACCESS_DENIED,
51858
+ message,
51859
+ hint,
51860
+ category: "remote_state"
51861
+ });
51862
+ }
51863
+ if (statusCode === 404) {
51864
+ return makeNormalized({
51865
+ code: ERROR_CODES.RESOURCE_NOT_FOUND,
51866
+ message,
51867
+ hint,
51868
+ category: "remote_state"
51869
+ });
51870
+ }
51596
51871
  if (message.includes("Timed out") || message.includes("failed") || message.includes("error state")) {
51597
51872
  return makeNormalized({
51598
51873
  code: ERROR_CODES.REMOTE_ERROR,
@@ -51770,6 +52045,11 @@ function makeErrorResult(envelope) {
51770
52045
  }
51771
52046
  var genericRecordSchema = external_exports.record(external_exports.string(), external_exports.unknown());
51772
52047
  var genericArraySchema = external_exports.array(genericRecordSchema);
52048
+ var paginationSchema = external_exports.object({
52049
+ limit: external_exports.number().int().positive(),
52050
+ offset: external_exports.number().int().nonnegative(),
52051
+ hasMore: external_exports.boolean()
52052
+ });
51773
52053
  var mergeRequestQueueSchema = external_exports.enum([
51774
52054
  "reviewable",
51775
52055
  "created_by_me",
@@ -51791,7 +52071,12 @@ var initInputSchema = {
51791
52071
  var listInputSchema = {
51792
52072
  requestId: external_exports.string().trim().min(1).optional(),
51793
52073
  outputMode: external_exports.enum(["summary", "full"]).optional(),
51794
- forked: external_exports.enum(["only", "exclude", "all"]).optional()
52074
+ ownership: external_exports.enum(["mine", "shared", "all"]).optional(),
52075
+ accessScope: external_exports.enum(["all_readable", "explicit_member"]).optional(),
52076
+ createdBy: external_exports.string().trim().min(1).optional(),
52077
+ forked: external_exports.enum(["only", "exclude", "all"]).optional(),
52078
+ limit: external_exports.number().int().positive().max(50).optional(),
52079
+ offset: external_exports.number().int().nonnegative().optional()
51795
52080
  };
51796
52081
  var remixInputSchema = {
51797
52082
  ...commonRequestFieldsSchema,
@@ -51820,6 +52105,16 @@ var recordTurnInputSchema = {
51820
52105
  allowBranchMismatch: external_exports.boolean().optional(),
51821
52106
  idempotencyKey: external_exports.string().trim().min(1).optional()
51822
52107
  };
52108
+ var finalizeTurnInputSchema = {
52109
+ ...commonRequestFieldsSchema,
52110
+ prompt: external_exports.string().trim().min(1),
52111
+ assistantResponse: external_exports.string().trim().min(1),
52112
+ diffSource: external_exports.enum(["worktree", "external"]).optional(),
52113
+ externalDiff: external_exports.string().optional(),
52114
+ sync: external_exports.boolean().optional(),
52115
+ allowBranchMismatch: external_exports.boolean().optional(),
52116
+ idempotencyKey: external_exports.string().trim().min(1).optional()
52117
+ };
51823
52118
  var previewInputSchema = {
51824
52119
  ...commonRequestFieldsSchema
51825
52120
  };
@@ -51835,20 +52130,26 @@ var reviewQueueInputSchema = {
51835
52130
  requestId: external_exports.string().trim().min(1).optional(),
51836
52131
  outputMode: external_exports.enum(["summary", "full"]).optional(),
51837
52132
  status: external_exports.string().trim().min(1).optional(),
51838
- kind: external_exports.enum(["merge", "sync", "all"]).optional()
52133
+ kind: external_exports.enum(["merge", "sync", "all"]).optional(),
52134
+ limit: external_exports.number().int().positive().max(50).optional(),
52135
+ offset: external_exports.number().int().nonnegative().optional()
51839
52136
  };
51840
52137
  var myMergeRequestsInputSchema = {
51841
52138
  requestId: external_exports.string().trim().min(1).optional(),
51842
52139
  outputMode: external_exports.enum(["summary", "full"]).optional(),
51843
52140
  status: external_exports.string().trim().min(1).optional(),
51844
- kind: external_exports.enum(["merge", "sync", "all"]).optional()
52141
+ kind: external_exports.enum(["merge", "sync", "all"]).optional(),
52142
+ limit: external_exports.number().int().positive().max(50).optional(),
52143
+ offset: external_exports.number().int().nonnegative().optional()
51845
52144
  };
51846
52145
  var appMergeRequestsInputSchema = {
51847
52146
  ...commonRequestFieldsSchema,
51848
52147
  queue: appScopedMergeRequestQueueSchema,
51849
52148
  appId: external_exports.string().trim().min(1).optional(),
51850
52149
  status: external_exports.string().trim().min(1).optional(),
51851
- kind: external_exports.enum(["merge", "sync", "all"]).optional()
52150
+ kind: external_exports.enum(["merge", "sync", "all"]).optional(),
52151
+ limit: external_exports.number().int().positive().max(50).optional(),
52152
+ offset: external_exports.number().int().nonnegative().optional()
51852
52153
  };
51853
52154
  var viewMergeRequestInputSchema = {
51854
52155
  requestId: external_exports.string().trim().min(1).optional(),
@@ -51879,6 +52180,38 @@ var inviteInputSchema = {
51879
52180
  var listMembersInputSchema = {
51880
52181
  ...commonRequestFieldsSchema,
51881
52182
  scope: memberScopeSchema,
52183
+ targetId: external_exports.string().trim().min(1).optional(),
52184
+ limit: external_exports.number().int().positive().max(50).optional(),
52185
+ offset: external_exports.number().int().nonnegative().optional()
52186
+ };
52187
+ var listInvitesInputSchema = {
52188
+ ...commonRequestFieldsSchema,
52189
+ scope: memberScopeSchema.optional(),
52190
+ targetId: external_exports.string().trim().min(1).optional(),
52191
+ limit: external_exports.number().int().positive().max(50).optional(),
52192
+ offset: external_exports.number().int().nonnegative().optional()
52193
+ };
52194
+ var resendInviteInputSchema = {
52195
+ ...commonRequestFieldsSchema,
52196
+ scope: memberScopeSchema.optional(),
52197
+ targetId: external_exports.string().trim().min(1).optional(),
52198
+ inviteId: external_exports.string().trim().min(1),
52199
+ ttlDays: external_exports.number().int().positive().max(30).optional()
52200
+ };
52201
+ var revokeInviteInputSchema = {
52202
+ ...commonRequestFieldsSchema,
52203
+ scope: memberScopeSchema.optional(),
52204
+ targetId: external_exports.string().trim().min(1).optional(),
52205
+ inviteId: external_exports.string().trim().min(1),
52206
+ confirm: external_exports.boolean()
52207
+ };
52208
+ var acceptInvitationInputSchema = {
52209
+ requestId: external_exports.string().trim().min(1).optional(),
52210
+ token: external_exports.string().trim().min(20)
52211
+ };
52212
+ var accessDebugInputSchema = {
52213
+ ...commonRequestFieldsSchema,
52214
+ scope: memberScopeSchema.optional(),
51882
52215
  targetId: external_exports.string().trim().min(1).optional()
51883
52216
  };
51884
52217
  var updateMemberRoleInputSchema = {
@@ -51902,7 +52235,8 @@ var initDataSchema = external_exports.object({
51902
52235
  repoRoot: external_exports.string()
51903
52236
  });
51904
52237
  var listDataSchema = external_exports.object({
51905
- apps: genericArraySchema
52238
+ apps: genericArraySchema,
52239
+ pagination: paginationSchema
51906
52240
  });
51907
52241
  var remixDataSchema = external_exports.object({
51908
52242
  appId: external_exports.string(),
@@ -51925,12 +52259,21 @@ var addDataSchema = external_exports.object({
51925
52259
  autoSync: genericRecordSchema
51926
52260
  });
51927
52261
  var recordTurnDataSchema = genericRecordSchema;
52262
+ var finalizeTurnDataSchema = external_exports.object({
52263
+ mode: external_exports.enum(["changed_turn", "no_diff_turn"]),
52264
+ idempotencyKey: external_exports.string().min(1),
52265
+ changeStep: genericRecordSchema.nullable(),
52266
+ collabTurn: genericRecordSchema.nullable(),
52267
+ autoSync: genericRecordSchema.nullable(),
52268
+ warnings: external_exports.array(external_exports.string())
52269
+ });
51928
52270
  var syncDataSchema = genericRecordSchema;
51929
52271
  var requestMergeDataSchema = genericRecordSchema;
51930
52272
  var mergeRequestQueueDataSchema = external_exports.object({
51931
52273
  queue: mergeRequestQueueSchema,
51932
52274
  appId: external_exports.string().nullable(),
51933
- mergeRequests: external_exports.array(genericRecordSchema)
52275
+ mergeRequests: external_exports.array(genericRecordSchema),
52276
+ pagination: paginationSchema
51934
52277
  });
51935
52278
  var viewMergeRequestDataSchema = genericRecordSchema;
51936
52279
  var approveDataSchema = genericRecordSchema;
@@ -51942,7 +52285,49 @@ var memberRecordSchema = genericRecordSchema;
51942
52285
  var listMembersDataSchema = external_exports.object({
51943
52286
  scopeType: memberScopeSchema,
51944
52287
  targetId: external_exports.string(),
51945
- members: external_exports.array(memberRecordSchema)
52288
+ members: external_exports.array(memberRecordSchema),
52289
+ pagination: paginationSchema
52290
+ });
52291
+ var listInvitesDataSchema = external_exports.object({
52292
+ scopeType: memberScopeSchema,
52293
+ targetId: external_exports.string(),
52294
+ invites: external_exports.array(genericRecordSchema),
52295
+ pagination: paginationSchema
52296
+ });
52297
+ var resendInviteDataSchema = genericRecordSchema;
52298
+ var revokeInviteDataSchema = external_exports.object({
52299
+ scopeType: memberScopeSchema,
52300
+ targetId: external_exports.string(),
52301
+ inviteId: external_exports.string(),
52302
+ revoked: external_exports.boolean()
52303
+ });
52304
+ var acceptInvitationDataSchema = genericRecordSchema;
52305
+ var accessDebugDataSchema = external_exports.object({
52306
+ viewer: genericRecordSchema,
52307
+ scope: external_exports.object({
52308
+ scopeType: memberScopeSchema,
52309
+ targetId: external_exports.string()
52310
+ }),
52311
+ entities: external_exports.object({
52312
+ organization: genericRecordSchema.nullable(),
52313
+ project: genericRecordSchema.nullable(),
52314
+ app: genericRecordSchema.nullable()
52315
+ }),
52316
+ binding: external_exports.object({
52317
+ repoRoot: external_exports.string().nullable(),
52318
+ binding: genericRecordSchema.nullable()
52319
+ }),
52320
+ access: external_exports.object({
52321
+ appContext: genericRecordSchema.nullable(),
52322
+ viewerMember: genericRecordSchema.nullable(),
52323
+ viewerProjectMember: genericRecordSchema.nullable(),
52324
+ inviteForViewerEmail: genericRecordSchema.nullable(),
52325
+ effectiveAppAccess: genericRecordSchema.nullable()
52326
+ }),
52327
+ members: external_exports.array(genericRecordSchema),
52328
+ membersPageInfo: paginationSchema,
52329
+ invites: external_exports.array(genericRecordSchema),
52330
+ invitesPageInfo: paginationSchema
51946
52331
  });
51947
52332
  var updateMemberRoleDataSchema = external_exports.object({
51948
52333
  scopeType: memberScopeSchema,
@@ -51956,6 +52341,7 @@ var remixSuccessSchema = makeSuccessSchema(remixDataSchema);
51956
52341
  var checkoutSuccessSchema = makeSuccessSchema(checkoutDataSchema);
51957
52342
  var addSuccessSchema = makeSuccessSchema(addDataSchema);
51958
52343
  var recordTurnSuccessSchema = makeSuccessSchema(recordTurnDataSchema);
52344
+ var finalizeTurnSuccessSchema = makeSuccessSchema(finalizeTurnDataSchema);
51959
52345
  var syncSuccessSchema = makeSuccessSchema(syncDataSchema);
51960
52346
  var requestMergeSuccessSchema = makeSuccessSchema(requestMergeDataSchema);
51961
52347
  var mergeRequestQueueSuccessSchema = makeSuccessSchema(mergeRequestQueueDataSchema);
@@ -51966,14 +52352,12 @@ var syncUpstreamSuccessSchema = makeSuccessSchema(syncUpstreamDataSchema);
51966
52352
  var reconcileSuccessSchema = makeSuccessSchema(reconcileDataSchema);
51967
52353
  var inviteSuccessSchema = makeSuccessSchema(inviteDataSchema);
51968
52354
  var listMembersSuccessSchema = makeSuccessSchema(listMembersDataSchema);
52355
+ var listInvitesSuccessSchema = makeSuccessSchema(listInvitesDataSchema);
52356
+ var resendInviteSuccessSchema = makeSuccessSchema(resendInviteDataSchema);
52357
+ var revokeInviteSuccessSchema = makeSuccessSchema(revokeInviteDataSchema);
52358
+ var acceptInvitationSuccessSchema = makeSuccessSchema(acceptInvitationDataSchema);
52359
+ var accessDebugSuccessSchema = makeSuccessSchema(accessDebugDataSchema);
51969
52360
  var updateMemberRoleSuccessSchema = makeSuccessSchema(updateMemberRoleDataSchema);
51970
- function unwrapResponseObject2(resp, label) {
51971
- const obj = resp?.responseObject;
51972
- if (obj === void 0 || obj === null) {
51973
- throw new Error(typeof resp?.message === "string" && resp.message.trim() ? resp.message : `Missing ${label} response`);
51974
- }
51975
- return obj;
51976
- }
51977
52361
  function getRiskLevel(status) {
51978
52362
  if (status.recommendedAction === "reconcile") return "high";
51979
52363
  if (status.recommendedAction === "sync" || status.remote.incomingOpenMergeRequestCount) return "medium";
@@ -51999,12 +52383,12 @@ function getRecommendedNextActions(status) {
51999
52383
  return [];
52000
52384
  }
52001
52385
  }
52002
- function collectWarnings(value) {
52386
+ function collectWarnings2(value) {
52003
52387
  if (!value || !Array.isArray(value)) return [];
52004
52388
  return value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
52005
52389
  }
52006
52390
  function collectResultWarnings(value) {
52007
- return collectWarnings(value.warnings);
52391
+ return collectWarnings2(value.warnings);
52008
52392
  }
52009
52393
  function truncateText(value, maxChars) {
52010
52394
  if (value.length <= maxChars) {
@@ -52060,13 +52444,20 @@ async function initCollab(params) {
52060
52444
  };
52061
52445
  }
52062
52446
  async function listApps(params) {
52063
- const api = await createApiClient2();
52064
- const resp = await api.listApps({ forked: params.forked ?? "all" });
52065
- const apps = unwrapResponseObject2(resp, "apps");
52447
+ const api = await createCollabApiClient();
52448
+ const result = await collabList({
52449
+ api,
52450
+ ownership: params.ownership,
52451
+ accessScope: params.accessScope,
52452
+ createdBy: params.createdBy,
52453
+ forked: params.forked,
52454
+ limit: params.limit,
52455
+ offset: params.offset
52456
+ });
52066
52457
  return {
52067
- data: { apps },
52458
+ data: result,
52068
52459
  warnings: [],
52069
- recommendedNextActions: [],
52460
+ recommendedNextActions: result.pagination.hasMore ? [`Pass offset=${result.pagination.offset + result.pagination.limit} to load the next page.`] : [],
52070
52461
  logContext: {}
52071
52462
  };
52072
52463
  }
@@ -52107,70 +52498,28 @@ async function checkoutCollab(params) {
52107
52498
  }
52108
52499
  };
52109
52500
  }
52110
- async function addCollabStep(params) {
52501
+ async function finalizeCollabTurn(params) {
52111
52502
  const api = await createCollabApiClient();
52112
52503
  const repoRoot = await findGitRoot(params.cwd);
52113
- const preHead = await getHeadCommitHash(repoRoot);
52114
- const untrackedBefore = params.diffSource === "worktree" ? await listUntrackedFiles(repoRoot) : [];
52115
- const changeStep = await collabAdd({
52504
+ const result = await collabFinalizeTurn({
52116
52505
  api,
52117
52506
  cwd: params.cwd,
52118
52507
  prompt: params.prompt,
52119
- assistantResponse: params.assistantResponse ?? null,
52508
+ assistantResponse: params.assistantResponse,
52120
52509
  diff: params.externalDiff ?? null,
52121
52510
  diffSource: params.diffSource,
52122
- allowBranchMismatch: params.allowBranchMismatch ?? false,
52123
- idempotencyKey: params.idempotencyKey ?? null,
52124
- actor: params.agent
52125
- });
52126
- const postHead = await getHeadCommitHash(repoRoot);
52127
- const autoSyncEligible = params.diffSource === "worktree";
52128
- const localRepoMutated = autoSyncEligible && preHead !== postHead;
52129
- return {
52130
- data: {
52131
- changeStep,
52132
- autoSync: {
52133
- requested: true,
52134
- eligible: autoSyncEligible,
52135
- attempted: autoSyncEligible,
52136
- applied: autoSyncEligible,
52137
- trackedChangesDiscarded: autoSyncEligible,
52138
- capturedUntrackedPathsCandidate: untrackedBefore,
52139
- localHeadBefore: preHead,
52140
- localHeadAfter: postHead,
52141
- localRepoMutated
52142
- }
52143
- },
52144
- warnings: [
52145
- ...collectResultWarnings(changeStep),
52146
- ...params.diffSource === "external" ? [
52147
- "Automatic local discard+sync was skipped because the diff came from an external source and may not match the current worktree."
52148
- ] : []
52149
- ],
52150
- recommendedNextActions: [],
52151
- logContext: {
52152
- repoRoot
52153
- }
52154
- };
52155
- }
52156
- async function recordCollabTurn(params) {
52157
- const api = await createCollabApiClient();
52158
- const result = await collabRecordTurn({
52159
- api,
52160
- cwd: params.cwd,
52161
- prompt: params.prompt,
52162
- assistantResponse: params.assistantResponse,
52511
+ sync: params.sync,
52163
52512
  allowBranchMismatch: params.allowBranchMismatch ?? false,
52164
52513
  idempotencyKey: params.idempotencyKey ?? null,
52165
52514
  actor: params.agent
52166
52515
  });
52167
52516
  return {
52168
52517
  data: result,
52169
- warnings: [],
52518
+ warnings: result.warnings,
52170
52519
  recommendedNextActions: [],
52171
52520
  logContext: {
52172
- repoRoot: params.cwd,
52173
- appId: result.appId
52521
+ repoRoot,
52522
+ appId: result.changeStep?.appId ?? result.collabTurn?.appId ?? null
52174
52523
  }
52175
52524
  };
52176
52525
  }
@@ -52212,16 +52561,19 @@ async function reviewQueue(params) {
52212
52561
  api,
52213
52562
  queue: "reviewable",
52214
52563
  status: params.status ?? "open",
52215
- kind: params.kind ?? "merge"
52564
+ kind: params.kind ?? "merge",
52565
+ limit: params.limit,
52566
+ offset: params.offset
52216
52567
  });
52217
52568
  return {
52218
52569
  data: {
52219
52570
  queue: result.queue,
52220
52571
  appId: result.appId,
52221
- mergeRequests: result.mergeRequests
52572
+ mergeRequests: result.mergeRequests,
52573
+ pagination: result.pagination
52222
52574
  },
52223
52575
  warnings: [],
52224
- recommendedNextActions: [],
52576
+ recommendedNextActions: result.pagination.hasMore ? [`Pass offset=${result.pagination.offset + result.pagination.limit} to load the next page.`] : [],
52225
52577
  logContext: {}
52226
52578
  };
52227
52579
  }
@@ -52231,16 +52583,19 @@ async function myMergeRequests(params) {
52231
52583
  api,
52232
52584
  queue: "created_by_me",
52233
52585
  status: params.status ?? "open",
52234
- kind: params.kind ?? "merge"
52586
+ kind: params.kind ?? "merge",
52587
+ limit: params.limit,
52588
+ offset: params.offset
52235
52589
  });
52236
52590
  return {
52237
52591
  data: {
52238
52592
  queue: result.queue,
52239
52593
  appId: result.appId,
52240
- mergeRequests: result.mergeRequests
52594
+ mergeRequests: result.mergeRequests,
52595
+ pagination: result.pagination
52241
52596
  },
52242
52597
  warnings: [],
52243
- recommendedNextActions: [],
52598
+ recommendedNextActions: result.pagination.hasMore ? [`Pass offset=${result.pagination.offset + result.pagination.limit} to load the next page.`] : [],
52244
52599
  logContext: {}
52245
52600
  };
52246
52601
  }
@@ -52252,16 +52607,19 @@ async function listAppMergeRequests(params) {
52252
52607
  appId: params.appId,
52253
52608
  queue: params.queue,
52254
52609
  status: params.status ?? "open",
52255
- kind: params.kind ?? "merge"
52610
+ kind: params.kind ?? "merge",
52611
+ limit: params.limit,
52612
+ offset: params.offset
52256
52613
  });
52257
52614
  return {
52258
52615
  data: {
52259
52616
  queue: result.queue,
52260
52617
  appId: result.appId,
52261
- mergeRequests: result.mergeRequests
52618
+ mergeRequests: result.mergeRequests,
52619
+ pagination: result.pagination
52262
52620
  },
52263
52621
  warnings: [],
52264
- recommendedNextActions: [],
52622
+ recommendedNextActions: result.pagination.hasMore ? [`Pass offset=${result.pagination.offset + result.pagination.limit} to load the next page.`] : [],
52265
52623
  logContext: {
52266
52624
  appId: result.appId
52267
52625
  }
@@ -52354,7 +52712,7 @@ async function reconcile(params) {
52354
52712
  });
52355
52713
  return {
52356
52714
  data: result,
52357
- warnings: collectWarnings(result.warnings),
52715
+ warnings: collectWarnings2(result.warnings),
52358
52716
  recommendedNextActions: params.dryRun ? ["Run remix_collab_reconcile_apply with confirm=true only if the preview is acceptable. Do not replace this with raw git history-rewrite commands."] : [],
52359
52717
  risks: params.dryRun ? ["Reconcile apply rewrites local history and creates a backup branch."] : [],
52360
52718
  logContext: {
@@ -52386,12 +52744,14 @@ async function listMembers(params) {
52386
52744
  api,
52387
52745
  cwd: params.cwd,
52388
52746
  scope: params.scope,
52389
- targetId: params.targetId ?? null
52747
+ targetId: params.targetId ?? null,
52748
+ limit: params.limit,
52749
+ offset: params.offset
52390
52750
  });
52391
52751
  return {
52392
52752
  data: result,
52393
52753
  warnings: [],
52394
- recommendedNextActions: [],
52754
+ recommendedNextActions: result.pagination.hasMore ? [`Pass offset=${result.pagination.offset + result.pagination.limit} to load the next page.`] : [],
52395
52755
  logContext: {}
52396
52756
  };
52397
52757
  }
@@ -52412,35 +52772,517 @@ async function updateMemberRole(params) {
52412
52772
  logContext: {}
52413
52773
  };
52414
52774
  }
52415
- function getAnnotations(access) {
52416
- if (access === "read") {
52417
- return {
52418
- readOnlyHint: true,
52419
- idempotentHint: true,
52420
- openWorldHint: false
52421
- };
52775
+ function unwrapResponseObject2(resp, label) {
52776
+ const obj = resp?.responseObject;
52777
+ if (obj === void 0 || obj === null) {
52778
+ throw new Error(typeof resp?.message === "string" && resp.message.trim() ? resp.message : `Missing ${label} response`);
52779
+ }
52780
+ return obj;
52781
+ }
52782
+ async function maybeFindGitRoot(cwd) {
52783
+ try {
52784
+ return await findGitRoot(cwd);
52785
+ } catch {
52786
+ return null;
52422
52787
  }
52788
+ }
52789
+ async function loadBindingContext(cwd) {
52790
+ if (!cwd) return { repoRoot: null, binding: null };
52791
+ const repoRoot = await maybeFindGitRoot(cwd);
52792
+ if (!repoRoot) return { repoRoot: null, binding: null };
52793
+ const binding = await readCollabBinding(repoRoot);
52423
52794
  return {
52424
- readOnlyHint: false,
52425
- destructiveHint: access === "local_write",
52426
- idempotentHint: false,
52427
- openWorldHint: false
52795
+ repoRoot,
52796
+ binding
52428
52797
  };
52429
52798
  }
52430
- function buildSuccessEnvelope(tool, requestId, result) {
52431
- return {
52432
- schemaVersion: SCHEMA_VERSION,
52433
- ok: true,
52434
- tool,
52435
- requestId: requestId ?? null,
52436
- data: result.data,
52437
- warnings: result.warnings ?? [],
52438
- risks: result.risks ?? [],
52799
+ function makeNotBoundError(message = "Repository is not bound to Remix.", hint) {
52800
+ const error2 = new Error(message);
52801
+ error2.hint = hint ?? "Run `remix_collab_init` in this repository, or pass the explicit id for a direct read.";
52802
+ return error2;
52803
+ }
52804
+ function parseJsonObject2(value) {
52805
+ if (!value) return null;
52806
+ try {
52807
+ const parsed = JSON.parse(value);
52808
+ return parsed && typeof parsed === "object" ? parsed : null;
52809
+ } catch {
52810
+ return null;
52811
+ }
52812
+ }
52813
+ function getBackendStatusCode(error2) {
52814
+ if (!error2 || typeof error2 !== "object") return null;
52815
+ const hint = "hint" in error2 && typeof error2.hint === "string" ? error2.hint : null;
52816
+ const body = parseJsonObject2(hint);
52817
+ if (typeof body?.statusCode === "number") return body.statusCode;
52818
+ if (typeof body?.statusCode === "string") {
52819
+ const parsed = Number(body.statusCode);
52820
+ return Number.isFinite(parsed) ? parsed : null;
52821
+ }
52822
+ return null;
52823
+ }
52824
+ function isBackendForbidden(error2) {
52825
+ return getBackendStatusCode(error2) === 403;
52826
+ }
52827
+ function isBackendNotFound(error2) {
52828
+ return getBackendStatusCode(error2) === 404;
52829
+ }
52830
+ function createAccessDeniedError(message, hint) {
52831
+ return new RemixMcpError({
52832
+ code: ERROR_CODES.ACCESS_DENIED,
52833
+ message,
52834
+ hint: hint ?? null,
52835
+ retryable: false,
52836
+ category: "remote_state"
52837
+ });
52838
+ }
52839
+ var MEMBERSHIP_PAGE_SIZE = 100;
52840
+ function normalizePagination2(params) {
52841
+ const rawLimit = typeof params?.limit === "number" ? Math.trunc(params.limit) : 25;
52842
+ const rawOffset = typeof params?.offset === "number" ? Math.trunc(params.offset) : 0;
52843
+ return {
52844
+ limit: Math.max(1, Math.min(50, rawLimit)),
52845
+ offset: Math.max(0, rawOffset)
52846
+ };
52847
+ }
52848
+ async function resolveScopeTarget2(api, params) {
52849
+ const explicitTargetId = params.targetId?.trim();
52850
+ const bindingContext = await loadBindingContext(params.cwd);
52851
+ if (explicitTargetId) {
52852
+ return {
52853
+ scopeType: params.scope,
52854
+ targetId: explicitTargetId,
52855
+ repoRoot: bindingContext.repoRoot
52856
+ };
52857
+ }
52858
+ if (!bindingContext.binding) {
52859
+ throw makeNotBoundError("Scope target was not provided and the current repository is not bound to Remix.");
52860
+ }
52861
+ if (params.scope === "app") {
52862
+ return {
52863
+ scopeType: "app",
52864
+ targetId: bindingContext.binding.currentAppId,
52865
+ repoRoot: bindingContext.repoRoot
52866
+ };
52867
+ }
52868
+ const appContext = unwrapResponseObject2(
52869
+ await api.getAppContext(bindingContext.binding.currentAppId),
52870
+ "bound app context"
52871
+ );
52872
+ if (params.scope === "project") {
52873
+ if (!appContext.readableScopes.project) {
52874
+ throw createAccessDeniedError(
52875
+ "The bound app's project is not readable to the current user.",
52876
+ "Use `scope=app` for app-level diagnostics, or pass an explicit readable project id."
52877
+ );
52878
+ }
52879
+ return {
52880
+ scopeType: "project",
52881
+ targetId: appContext.projectId,
52882
+ repoRoot: bindingContext.repoRoot
52883
+ };
52884
+ }
52885
+ if (!appContext.readableScopes.organization) {
52886
+ throw createAccessDeniedError(
52887
+ "The bound app's organization is not readable to the current user.",
52888
+ "Use `scope=app` or `scope=project` for narrower diagnostics, or pass an explicit readable organization id."
52889
+ );
52890
+ }
52891
+ return {
52892
+ scopeType: "organization",
52893
+ targetId: appContext.organizationId,
52894
+ repoRoot: bindingContext.repoRoot
52895
+ };
52896
+ }
52897
+ async function getScopeEntity(api, scopeType, targetId) {
52898
+ if (scopeType === "organization") {
52899
+ return {
52900
+ organization: unwrapResponseObject2(await api.getOrganization(targetId), "organization"),
52901
+ project: null,
52902
+ app: null
52903
+ };
52904
+ }
52905
+ if (scopeType === "project") {
52906
+ const project2 = unwrapResponseObject2(await api.getProject(targetId), "project");
52907
+ const organizationId2 = typeof project2.organizationId === "string" ? project2.organizationId : null;
52908
+ return {
52909
+ organization: organizationId2 == null ? null : unwrapResponseObject2(await api.getOrganization(organizationId2), "organization"),
52910
+ project: project2,
52911
+ app: null
52912
+ };
52913
+ }
52914
+ const app = unwrapResponseObject2(await api.getApp(targetId), "app");
52915
+ const projectId = typeof app.projectId === "string" ? app.projectId : null;
52916
+ const project = projectId == null ? null : unwrapResponseObject2(await api.getProject(projectId), "project");
52917
+ const organizationId = typeof project?.organizationId === "string" ? project.organizationId : null;
52918
+ return {
52919
+ organization: organizationId == null ? null : unwrapResponseObject2(await api.getOrganization(organizationId), "organization"),
52920
+ project,
52921
+ app
52922
+ };
52923
+ }
52924
+ function mapProjectRoleToAppRole(role) {
52925
+ switch (role) {
52926
+ case "owner":
52927
+ case "maintainer":
52928
+ return "maintainer";
52929
+ case "editor":
52930
+ return "editor";
52931
+ case "viewer":
52932
+ return "viewer";
52933
+ default:
52934
+ return null;
52935
+ }
52936
+ }
52937
+ function strongestRole(...roles) {
52938
+ if (roles.includes("owner")) return "owner";
52939
+ if (roles.includes("maintainer")) return "maintainer";
52940
+ if (roles.includes("editor")) return "editor";
52941
+ if (roles.includes("viewer")) return "viewer";
52942
+ return null;
52943
+ }
52944
+ function resolveAppAccessSource(params) {
52945
+ if (params.directAppRole && params.inheritedProjectRole) return "both";
52946
+ if (params.directAppRole) return "direct_app_membership";
52947
+ if (params.inheritedProjectRole) return "project_membership";
52948
+ return "none";
52949
+ }
52950
+ function buildEffectiveAppAccess(params) {
52951
+ const directAppRole = params.directAppRole ?? null;
52952
+ const inheritedProjectRole = mapProjectRoleToAppRole(params.projectRole);
52953
+ const effectiveRole = strongestRole(directAppRole, inheritedProjectRole);
52954
+ return {
52955
+ effectiveRole,
52956
+ directAppRole,
52957
+ projectRole: params.projectRole,
52958
+ inheritedProjectRole,
52959
+ accessSource: resolveAppAccessSource({ directAppRole, inheritedProjectRole }),
52960
+ canReadWorkflow: effectiveRole !== null,
52961
+ canEdit: effectiveRole === "owner" || effectiveRole === "maintainer" || effectiveRole === "editor",
52962
+ canManage: effectiveRole === "owner" || effectiveRole === "maintainer",
52963
+ isOwner: directAppRole === "owner"
52964
+ };
52965
+ }
52966
+ async function listMembersForScope(api, scopeType, targetId, params) {
52967
+ if (scopeType === "organization") {
52968
+ return unwrapResponseObject2(await api.listOrganizationMembers(targetId, params), "organization members");
52969
+ }
52970
+ if (scopeType === "project") {
52971
+ return unwrapResponseObject2(await api.listProjectMembers(targetId, params), "project members");
52972
+ }
52973
+ return unwrapResponseObject2(await api.listAppMembers(targetId, params), "app members");
52974
+ }
52975
+ async function loadFirstPageSample(fetchPage) {
52976
+ const items = await fetchPage(MEMBERSHIP_PAGE_SIZE, 0);
52977
+ const hasMore = items.length < MEMBERSHIP_PAGE_SIZE ? false : (await fetchPage(1, MEMBERSHIP_PAGE_SIZE)).length > 0;
52978
+ return {
52979
+ items,
52980
+ pageInfo: {
52981
+ limit: MEMBERSHIP_PAGE_SIZE,
52982
+ offset: 0,
52983
+ hasMore
52984
+ }
52985
+ };
52986
+ }
52987
+ function emptyFirstPageSample() {
52988
+ return {
52989
+ items: [],
52990
+ pageInfo: {
52991
+ limit: MEMBERSHIP_PAGE_SIZE,
52992
+ offset: 0,
52993
+ hasMore: false
52994
+ }
52995
+ };
52996
+ }
52997
+ async function listInvitesForScope(api, scopeType, targetId, params) {
52998
+ if (scopeType === "organization") {
52999
+ return unwrapResponseObject2(
53000
+ await api.listOrganizationInvites(targetId, params),
53001
+ "organization invites"
53002
+ );
53003
+ }
53004
+ if (scopeType === "project") {
53005
+ return unwrapResponseObject2(
53006
+ await api.listProjectInvites(targetId, params),
53007
+ "project invites"
53008
+ );
53009
+ }
53010
+ return unwrapResponseObject2(await api.listAppInvites(targetId, params), "app invites");
53011
+ }
53012
+ function getSelfMember(meId, members) {
53013
+ return meId == null ? null : members.find((member) => member.userId === meId || member.user_id === meId) ?? null;
53014
+ }
53015
+ async function findPendingInviteForEmailForScope(api, scopeType, targetId, email2) {
53016
+ if (email2 == null) return null;
53017
+ let offset = 0;
53018
+ for (; ; ) {
53019
+ const invites = await listInvitesForScope(api, scopeType, targetId, {
53020
+ limit: MEMBERSHIP_PAGE_SIZE,
53021
+ offset
53022
+ });
53023
+ const match = invites.find((invite) => invite.email.toLowerCase() === email2 && invite.state === "pending") ?? null;
53024
+ if (match) return match;
53025
+ if (invites.length < MEMBERSHIP_PAGE_SIZE) return null;
53026
+ offset += MEMBERSHIP_PAGE_SIZE;
53027
+ }
53028
+ }
53029
+ async function findSelfMemberForScope(api, scopeType, targetId, meId) {
53030
+ if (meId == null) return null;
53031
+ let offset = 0;
53032
+ for (; ; ) {
53033
+ const members = scopeType === "organization" ? unwrapResponseObject2(
53034
+ await api.listOrganizationMembers(targetId, { limit: MEMBERSHIP_PAGE_SIZE, offset }),
53035
+ "organization members"
53036
+ ) : scopeType === "project" ? unwrapResponseObject2(
53037
+ await api.listProjectMembers(targetId, { limit: MEMBERSHIP_PAGE_SIZE, offset }),
53038
+ "project members"
53039
+ ) : unwrapResponseObject2(
53040
+ await api.listAppMembers(targetId, { limit: MEMBERSHIP_PAGE_SIZE, offset }),
53041
+ "app members"
53042
+ );
53043
+ const match = getSelfMember(meId, members);
53044
+ if (match) return match;
53045
+ if (members.length < MEMBERSHIP_PAGE_SIZE) return null;
53046
+ offset += MEMBERSHIP_PAGE_SIZE;
53047
+ }
53048
+ }
53049
+ async function listInvites(params) {
53050
+ const api = await createApiClient2();
53051
+ const target = await resolveScopeTarget2(api, {
53052
+ scope: params.scope ?? "project",
53053
+ targetId: params.targetId,
53054
+ cwd: params.cwd
53055
+ });
53056
+ const pagination = normalizePagination2(params);
53057
+ const invites = await listInvitesForScope(api, target.scopeType, target.targetId, {
53058
+ limit: pagination.limit + 1,
53059
+ offset: pagination.offset
53060
+ });
53061
+ return {
53062
+ data: {
53063
+ scopeType: target.scopeType,
53064
+ targetId: target.targetId,
53065
+ invites: invites.slice(0, pagination.limit),
53066
+ pagination: {
53067
+ ...pagination,
53068
+ hasMore: invites.length > pagination.limit
53069
+ }
53070
+ },
53071
+ warnings: [],
53072
+ recommendedNextActions: invites.length > pagination.limit ? [`Pass offset=${pagination.offset + pagination.limit} to load the next page.`] : invites.length > 0 ? ["Use `remix_collab_resend_invite` or `remix_collab_revoke_invite` for lifecycle actions on a selected invite id."] : ["Use `remix_collab_invite` if you need to create a new invitation for this scope."],
53073
+ logContext: {
53074
+ repoRoot: target.repoRoot
53075
+ }
53076
+ };
53077
+ }
53078
+ async function resendInvite(params) {
53079
+ const api = await createApiClient2();
53080
+ const target = await resolveScopeTarget2(api, {
53081
+ scope: params.scope ?? "project",
53082
+ targetId: params.targetId,
53083
+ cwd: params.cwd
53084
+ });
53085
+ const response = target.scopeType === "organization" ? await api.resendOrganizationInvite(target.targetId, params.inviteId, { ttlDays: params.ttlDays }) : target.scopeType === "project" ? await api.resendProjectInvite(target.targetId, params.inviteId, { ttlDays: params.ttlDays }) : await api.resendAppInvite(target.targetId, params.inviteId, { ttlDays: params.ttlDays });
53086
+ return {
53087
+ data: unwrapResponseObject2(response, "resent invite"),
53088
+ warnings: [],
53089
+ recommendedNextActions: ["Use `remix_collab_list_invites` to confirm the refreshed expiry and delivery state."],
53090
+ logContext: {
53091
+ repoRoot: target.repoRoot
53092
+ }
53093
+ };
53094
+ }
53095
+ async function revokeInvite(params) {
53096
+ const api = await createApiClient2();
53097
+ const target = await resolveScopeTarget2(api, {
53098
+ scope: params.scope ?? "project",
53099
+ targetId: params.targetId,
53100
+ cwd: params.cwd
53101
+ });
53102
+ if (target.scopeType === "organization") {
53103
+ await api.revokeOrganizationInvite(target.targetId, params.inviteId);
53104
+ } else if (target.scopeType === "project") {
53105
+ await api.revokeProjectInvite(target.targetId, params.inviteId);
53106
+ } else {
53107
+ await api.revokeAppInvite(target.targetId, params.inviteId);
53108
+ }
53109
+ return {
53110
+ data: {
53111
+ scopeType: target.scopeType,
53112
+ targetId: target.targetId,
53113
+ inviteId: params.inviteId,
53114
+ revoked: true
53115
+ },
53116
+ warnings: [],
53117
+ recommendedNextActions: ["Use `remix_collab_list_invites` to confirm the invite state is now `revoked`."],
53118
+ logContext: {
53119
+ repoRoot: target.repoRoot
53120
+ }
53121
+ };
53122
+ }
53123
+ async function acceptInvitation(params) {
53124
+ const api = await createApiClient2();
53125
+ const result = unwrapResponseObject2(await api.acceptInvitation({ token: params.token }), "accepted invitation");
53126
+ return {
53127
+ data: result,
53128
+ warnings: [],
53129
+ recommendedNextActions: result.redirectPath ? [`The invitation is accepted. Use the returned redirect metadata to continue with the newly granted Remix scope.`] : [],
53130
+ logContext: {}
53131
+ };
53132
+ }
53133
+ async function accessDebug(params) {
53134
+ const api = await createApiClient2();
53135
+ const target = await resolveScopeTarget2(api, {
53136
+ scope: params.scope ?? "project",
53137
+ targetId: params.targetId,
53138
+ cwd: params.cwd
53139
+ });
53140
+ const bindingContext = await loadBindingContext(params.cwd);
53141
+ const viewer = unwrapResponseObject2(await api.getMe(), "current user");
53142
+ const viewerId = typeof viewer.id === "string" ? viewer.id : null;
53143
+ const viewerEmail = typeof viewer.email === "string" ? viewer.email.toLowerCase() : null;
53144
+ const warnings = [...bindingContext.binding ? [] : ["No local Remix binding was detected for the provided cwd."]];
53145
+ let entities;
53146
+ let appContext = null;
53147
+ let membersPage = emptyFirstPageSample();
53148
+ let invitesPage = emptyFirstPageSample();
53149
+ let viewerMember = null;
53150
+ let viewerProjectMember = null;
53151
+ let inviteForViewerEmail = null;
53152
+ let effectiveAppAccess = null;
53153
+ if (target.scopeType !== "app") {
53154
+ [entities, membersPage, invitesPage] = await Promise.all([
53155
+ getScopeEntity(api, target.scopeType, target.targetId),
53156
+ loadFirstPageSample((limit, offset) => listMembersForScope(api, target.scopeType, target.targetId, { limit, offset })),
53157
+ loadFirstPageSample((limit, offset) => listInvitesForScope(api, target.scopeType, target.targetId, { limit, offset }))
53158
+ ]);
53159
+ viewerMember = await findSelfMemberForScope(api, target.scopeType, target.targetId, viewerId);
53160
+ inviteForViewerEmail = await findPendingInviteForEmailForScope(api, target.scopeType, target.targetId, viewerEmail);
53161
+ } else {
53162
+ const [app, loadedAppContext] = await Promise.all([
53163
+ unwrapResponseObject2(await api.getApp(target.targetId), "app"),
53164
+ unwrapResponseObject2(await api.getAppContext(target.targetId), "app context")
53165
+ ]);
53166
+ appContext = loadedAppContext;
53167
+ entities = {
53168
+ organization: null,
53169
+ project: null,
53170
+ app
53171
+ };
53172
+ if (appContext.readableScopes.project) {
53173
+ try {
53174
+ entities.project = unwrapResponseObject2(await api.getProject(appContext.projectId), "project");
53175
+ } catch (error2) {
53176
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
53177
+ warnings.push("The app is readable, but its project/workspace metadata is not currently readable to the current user.");
53178
+ }
53179
+ } else {
53180
+ warnings.push("The app is readable, but its project/workspace is not readable to the current user.");
53181
+ }
53182
+ if (appContext.readableScopes.organization) {
53183
+ try {
53184
+ entities.organization = unwrapResponseObject2(await api.getOrganization(appContext.organizationId), "organization");
53185
+ } catch (error2) {
53186
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
53187
+ warnings.push("The app is readable, but its organization metadata is not currently readable to the current user.");
53188
+ }
53189
+ } else {
53190
+ warnings.push("The app's organization is not readable to the current user.");
53191
+ }
53192
+ effectiveAppAccess = {
53193
+ ...buildEffectiveAppAccess({
53194
+ directAppRole: appContext.roles.appRole,
53195
+ projectRole: appContext.roles.projectRole
53196
+ }),
53197
+ accessPath: appContext.accessPath,
53198
+ readableScopes: appContext.readableScopes,
53199
+ visibility: appContext.visibility,
53200
+ organizationRole: appContext.roles.organizationRole ?? null
53201
+ };
53202
+ if (appContext.capabilities.canReadWorkflow) {
53203
+ membersPage = await loadFirstPageSample((limit, offset) => listMembersForScope(api, "app", target.targetId, { limit, offset }));
53204
+ viewerMember = await findSelfMemberForScope(api, "app", target.targetId, viewerId);
53205
+ if (appContext.readableScopes.project) {
53206
+ viewerProjectMember = await findSelfMemberForScope(api, "project", appContext.projectId, viewerId);
53207
+ }
53208
+ try {
53209
+ invitesPage = await loadFirstPageSample((limit, offset) => listInvitesForScope(api, "app", target.targetId, { limit, offset }));
53210
+ inviteForViewerEmail = await findPendingInviteForEmailForScope(api, "app", target.targetId, viewerEmail);
53211
+ } catch (error2) {
53212
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
53213
+ warnings.push("App invite data is not readable to the current user, so invite diagnostics are partial.");
53214
+ }
53215
+ } else {
53216
+ warnings.push("The current viewer can read the app, but cannot read workflow-scoped app membership data.");
53217
+ }
53218
+ }
53219
+ if (membersPage.pageInfo.hasMore) {
53220
+ warnings.push("The `members` array is a first-page sample only; use the scope member list tool to inspect the remaining entries.");
53221
+ }
53222
+ if (invitesPage.pageInfo.hasMore) {
53223
+ warnings.push("The `invites` array is a first-page sample only; use the invite list tool with pagination to inspect the remaining entries.");
53224
+ }
53225
+ return {
53226
+ data: {
53227
+ viewer,
53228
+ scope: {
53229
+ scopeType: target.scopeType,
53230
+ targetId: target.targetId
53231
+ },
53232
+ entities,
53233
+ binding: {
53234
+ repoRoot: bindingContext.repoRoot,
53235
+ binding: bindingContext.binding
53236
+ },
53237
+ access: {
53238
+ appContext,
53239
+ viewerMember,
53240
+ viewerProjectMember,
53241
+ inviteForViewerEmail,
53242
+ effectiveAppAccess: effectiveAppAccess ?? null
53243
+ },
53244
+ members: membersPage.items,
53245
+ membersPageInfo: membersPage.pageInfo,
53246
+ invites: invitesPage.items,
53247
+ invitesPageInfo: invitesPage.pageInfo
53248
+ },
53249
+ warnings,
53250
+ recommendedNextActions: inviteForViewerEmail ? ["A pending invite exists for the current viewer email. Use `remix_collab_accept_invitation` if the viewer should accept it."] : target.scopeType === "app" ? ["Use `access.appContext` and `access.effectiveAppAccess` together to explain app-level visibility versus workspace-level visibility."] : ["Use the member and invite lists above to explain missing access, role mismatches, or stale invite state."],
53251
+ logContext: {
53252
+ repoRoot: target.repoRoot,
53253
+ appId: entities.app?.id ?? bindingContext.binding?.currentAppId ?? null
53254
+ }
53255
+ };
53256
+ }
53257
+ function getAnnotations(access, options) {
53258
+ if (access === "read") {
53259
+ return {
53260
+ readOnlyHint: true,
53261
+ idempotentHint: true,
53262
+ openWorldHint: false
53263
+ };
53264
+ }
53265
+ return {
53266
+ readOnlyHint: false,
53267
+ destructiveHint: access === "local_write",
53268
+ idempotentHint: options?.idempotent ?? false,
53269
+ openWorldHint: false
53270
+ };
53271
+ }
53272
+ function buildSuccessEnvelope(tool, requestId, result) {
53273
+ return {
53274
+ schemaVersion: SCHEMA_VERSION,
53275
+ ok: true,
53276
+ tool,
53277
+ requestId: requestId ?? null,
53278
+ data: result.data,
53279
+ warnings: result.warnings ?? [],
53280
+ risks: result.risks ?? [],
52439
53281
  recommendedNextActions: result.recommendedNextActions ?? []
52440
53282
  };
52441
53283
  }
52442
53284
  function deriveErrorRisks(tool, normalized) {
52443
- if ((tool === "remix_collab_add" || tool === "remix_collab_add_change_step") && normalized.message === "Change step succeeded remotely, but automatic local sync failed.") {
53285
+ if (isFinalizeTurnLocalSyncFailure(tool, normalized)) {
52444
53286
  return ["The change step succeeded remotely, but the local repository may need manual recovery or a follow-up sync."];
52445
53287
  }
52446
53288
  if (normalized.code === "DESTRUCTIVE_OPERATION_BLOCKED") {
@@ -52454,9 +53296,16 @@ function deriveErrorRisks(tool, normalized) {
52454
53296
  }
52455
53297
  return [];
52456
53298
  }
53299
+ function isFinalizeTurnLocalSyncFailure(tool, normalized) {
53300
+ return tool === "remix_collab_finalize_turn" && normalized.message === "Change step succeeded remotely, but automatic local sync failed.";
53301
+ }
52457
53302
  function buildErrorEnvelope(tool, requestId, error2) {
52458
53303
  const normalized = normalizeToolError(error2);
52459
- const recommendedNextActions = normalized.code === "AUTH_REQUIRED" ? ["Set COMERGE_ACCESS_TOKEN, then retry the tool call."] : normalized.code === "REPO_LOCK_TIMEOUT" ? ["Wait for the active Remix mutation to finish, then retry the tool call."] : normalized.code === "REPO_STATE_CHANGED_DURING_OPERATION" ? ["Review local repository changes, then rerun the tool once the worktree is stable."] : normalized.code === "PREFERRED_BRANCH_MISMATCH" ? ["Switch to the repository's preferred Remix branch, or rerun with allowBranchMismatch=true if intentional."] : [];
53304
+ const recommendedNextActions = isFinalizeTurnLocalSyncFailure(tool, normalized) ? [
53305
+ "Run `remix_collab_status` to confirm the bound repo state before attempting recovery.",
53306
+ "Run `remix_collab_sync_preview` next, then `remix_collab_sync_apply` with `confirm=true` if the preview looks correct.",
53307
+ "Inspect `error.hint` for any preserved diff backup path before retrying local recovery, and do not rerun `remix_collab_finalize_turn` immediately."
53308
+ ] : normalized.code === "AUTH_REQUIRED" ? ["Set COMERGE_ACCESS_TOKEN, then retry the tool call."] : normalized.code === "REPO_LOCK_TIMEOUT" ? ["Wait for the active Remix mutation to finish, then retry the tool call."] : normalized.code === "REPO_STATE_CHANGED_DURING_OPERATION" ? ["Review local repository changes, then rerun the tool once the worktree is stable."] : normalized.code === "PREFERRED_BRANCH_MISMATCH" ? ["Switch to the repository's preferred Remix branch, or rerun with allowBranchMismatch=true if intentional."] : [];
52460
53309
  return {
52461
53310
  schemaVersion: SCHEMA_VERSION,
52462
53311
  ok: false,
@@ -52477,7 +53326,7 @@ function registerTool(server, context, params) {
52477
53326
  description: params.description,
52478
53327
  inputSchema: params.inputSchema,
52479
53328
  outputSchema: params.outputSchema,
52480
- annotations: getAnnotations(params.access)
53329
+ annotations: params.annotations ?? getAnnotations(params.access)
52481
53330
  },
52482
53331
  async (rawArgs) => {
52483
53332
  const requestId = typeof rawArgs.requestId === "string" ? rawArgs.requestId : void 0;
@@ -52551,13 +53400,20 @@ function registerCollabTools(server, context) {
52551
53400
  });
52552
53401
  registerTool(server, context, {
52553
53402
  name: "remix_collab_list",
52554
- description: "List Remix apps visible to the current authenticated user.",
53403
+ description: "List Remix apps visible to the current authenticated user. Defaults to membership-oriented discovery; pass accessScope=all_readable explicitly for broader readable discovery.",
52555
53404
  access: "read",
52556
53405
  inputSchema: listInputSchema,
52557
53406
  outputSchema: listSuccessSchema,
52558
53407
  run: async (args) => {
52559
53408
  const input = external_exports.object(listInputSchema).parse(args);
52560
- return listApps({ forked: input.forked });
53409
+ return listApps({
53410
+ ownership: input.ownership,
53411
+ accessScope: input.accessScope,
53412
+ createdBy: input.createdBy,
53413
+ forked: input.forked,
53414
+ limit: input.limit,
53415
+ offset: input.offset
53416
+ });
52561
53417
  }
52562
53418
  });
52563
53419
  registerTool(server, context, {
@@ -52594,89 +53450,25 @@ function registerCollabTools(server, context) {
52594
53450
  }
52595
53451
  });
52596
53452
  registerTool(server, context, {
52597
- name: "remix_collab_add",
52598
- description: "Authoritative way to record completed code changes for the current bound repository, using the live worktree diff by default instead of raw git commit or push.",
52599
- access: "local_write",
52600
- inputSchema: addInputSchema,
52601
- outputSchema: addSuccessSchema,
52602
- run: async (args) => {
52603
- const input = external_exports.object(addInputSchema).parse(args);
52604
- const cwd = resolvePolicyCwd(context.policy, input.cwd);
52605
- const diffSource = input.diffSource ?? "worktree";
52606
- if (diffSource === "external") {
52607
- const externalDiff = input.externalDiff ?? "";
52608
- assertDiffWithinLimit(context.policy, externalDiff);
52609
- }
52610
- return addCollabStep({
52611
- cwd,
52612
- prompt: input.prompt,
52613
- assistantResponse: input.assistantResponse,
52614
- diffSource,
52615
- externalDiff: input.externalDiff,
52616
- allowBranchMismatch: input.allowBranchMismatch ?? false,
52617
- idempotencyKey: input.idempotencyKey,
52618
- agent: context.agentMetadata
52619
- });
52620
- }
52621
- });
52622
- registerTool(server, context, {
52623
- name: "remix_collab_add_change_step",
52624
- description: "Alias of remix_collab_add with a more explicit name: record a code-diff change step for the current bound repository.",
53453
+ name: "remix_collab_finalize_turn",
53454
+ description: "Primary turn recorder for the current bound repository. Call this exactly once before the final response; it records a changed turn when the worktree has a diff, records a no-diff turn when it does not, and can accept an explicit external diff when needed.",
52625
53455
  access: "local_write",
52626
- inputSchema: addInputSchema,
52627
- outputSchema: addSuccessSchema,
53456
+ inputSchema: finalizeTurnInputSchema,
53457
+ outputSchema: finalizeTurnSuccessSchema,
53458
+ annotations: getAnnotations("local_write", { idempotent: true }),
52628
53459
  run: async (args) => {
52629
- const input = external_exports.object(addInputSchema).parse(args);
53460
+ const input = external_exports.object(finalizeTurnInputSchema).parse(args);
52630
53461
  const cwd = resolvePolicyCwd(context.policy, input.cwd);
52631
- const diffSource = input.diffSource ?? "worktree";
52632
- if (diffSource === "external") {
52633
- const externalDiff = input.externalDiff ?? "";
52634
- assertDiffWithinLimit(context.policy, externalDiff);
53462
+ if ((input.diffSource ?? "worktree") === "external" || typeof input.externalDiff === "string") {
53463
+ assertDiffWithinLimit(context.policy, input.externalDiff ?? "");
52635
53464
  }
52636
- return addCollabStep({
53465
+ return finalizeCollabTurn({
52637
53466
  cwd,
52638
53467
  prompt: input.prompt,
52639
53468
  assistantResponse: input.assistantResponse,
52640
- diffSource,
53469
+ diffSource: input.diffSource,
52641
53470
  externalDiff: input.externalDiff,
52642
- allowBranchMismatch: input.allowBranchMismatch ?? false,
52643
- idempotencyKey: input.idempotencyKey,
52644
- agent: context.agentMetadata
52645
- });
52646
- }
52647
- });
52648
- registerTool(server, context, {
52649
- name: "remix_collab_record_turn",
52650
- description: "Record one no-diff collaboration turn for the current bound repository after a completed assistant response. This is for prompt/response history only and will fail if the worktree has code changes.",
52651
- access: "remote_write",
52652
- inputSchema: recordTurnInputSchema,
52653
- outputSchema: recordTurnSuccessSchema,
52654
- run: async (args) => {
52655
- const input = external_exports.object(recordTurnInputSchema).parse(args);
52656
- const cwd = resolvePolicyCwd(context.policy, input.cwd);
52657
- return recordCollabTurn({
52658
- cwd,
52659
- prompt: input.prompt,
52660
- assistantResponse: input.assistantResponse,
52661
- allowBranchMismatch: input.allowBranchMismatch ?? false,
52662
- idempotencyKey: input.idempotencyKey,
52663
- agent: context.agentMetadata
52664
- });
52665
- }
52666
- });
52667
- registerTool(server, context, {
52668
- name: "remix_collab_record_no_diff_turn",
52669
- description: "Alias of remix_collab_record_turn with a more explicit name: record a prompt/response turn only when the worktree has no code diff.",
52670
- access: "remote_write",
52671
- inputSchema: recordTurnInputSchema,
52672
- outputSchema: recordTurnSuccessSchema,
52673
- run: async (args) => {
52674
- const input = external_exports.object(recordTurnInputSchema).parse(args);
52675
- const cwd = resolvePolicyCwd(context.policy, input.cwd);
52676
- return recordCollabTurn({
52677
- cwd,
52678
- prompt: input.prompt,
52679
- assistantResponse: input.assistantResponse,
53471
+ sync: input.sync,
52680
53472
  allowBranchMismatch: input.allowBranchMismatch ?? false,
52681
53473
  idempotencyKey: input.idempotencyKey,
52682
53474
  agent: context.agentMetadata
@@ -52728,7 +53520,12 @@ function registerCollabTools(server, context) {
52728
53520
  outputSchema: mergeRequestQueueSuccessSchema,
52729
53521
  run: async (args) => {
52730
53522
  const input = external_exports.object(reviewQueueInputSchema).parse(args);
52731
- return reviewQueue({ status: input.status, kind: input.kind });
53523
+ return reviewQueue({
53524
+ status: input.status,
53525
+ kind: input.kind,
53526
+ limit: input.limit,
53527
+ offset: input.offset
53528
+ });
52732
53529
  }
52733
53530
  });
52734
53531
  registerTool(server, context, {
@@ -52739,7 +53536,12 @@ function registerCollabTools(server, context) {
52739
53536
  outputSchema: mergeRequestQueueSuccessSchema,
52740
53537
  run: async (args) => {
52741
53538
  const input = external_exports.object(myMergeRequestsInputSchema).parse(args);
52742
- return myMergeRequests({ status: input.status, kind: input.kind });
53539
+ return myMergeRequests({
53540
+ status: input.status,
53541
+ kind: input.kind,
53542
+ limit: input.limit,
53543
+ offset: input.offset
53544
+ });
52743
53545
  }
52744
53546
  });
52745
53547
  registerTool(server, context, {
@@ -52756,7 +53558,9 @@ function registerCollabTools(server, context) {
52756
53558
  appId: input.appId,
52757
53559
  queue: input.queue,
52758
53560
  status: input.status,
52759
- kind: input.kind
53561
+ kind: input.kind,
53562
+ limit: input.limit,
53563
+ offset: input.offset
52760
53564
  });
52761
53565
  }
52762
53566
  });
@@ -52890,33 +53694,680 @@ function registerCollabTools(server, context) {
52890
53694
  return listMembers({
52891
53695
  cwd,
52892
53696
  scope: input.scope,
52893
- targetId: input.targetId
53697
+ targetId: input.targetId,
53698
+ limit: input.limit,
53699
+ offset: input.offset
52894
53700
  });
52895
53701
  }
52896
53702
  });
52897
53703
  registerTool(server, context, {
52898
- name: "remix_collab_update_member_role",
52899
- description: "Update an organization, project, or app member role, using the current repository binding unless targetId is provided.",
53704
+ name: "remix_collab_list_invites",
53705
+ description: "List invitations for an organization, project, or app, using the current repository binding unless targetId is provided.",
53706
+ access: "read",
53707
+ inputSchema: listInvitesInputSchema,
53708
+ outputSchema: listInvitesSuccessSchema,
53709
+ run: async (args) => {
53710
+ const input = external_exports.object(listInvitesInputSchema).parse(args);
53711
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
53712
+ return listInvites({
53713
+ cwd,
53714
+ scope: input.scope ?? "project",
53715
+ targetId: input.targetId,
53716
+ limit: input.limit,
53717
+ offset: input.offset
53718
+ });
53719
+ }
53720
+ });
53721
+ registerTool(server, context, {
53722
+ name: "remix_collab_resend_invite",
53723
+ description: "Resend an existing invitation for an organization, project, or app, using the current repository binding unless targetId is provided.",
52900
53724
  access: "remote_write",
52901
- inputSchema: updateMemberRoleInputSchema,
52902
- outputSchema: updateMemberRoleSuccessSchema,
53725
+ inputSchema: resendInviteInputSchema,
53726
+ outputSchema: resendInviteSuccessSchema,
52903
53727
  run: async (args) => {
52904
- const input = external_exports.object(updateMemberRoleInputSchema).parse(args);
52905
- const cwd = resolvePolicyCwd(context.policy, input.cwd);
52906
- return updateMemberRole({
53728
+ const input = external_exports.object(resendInviteInputSchema).parse(args);
53729
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
53730
+ return resendInvite({
52907
53731
  cwd,
52908
- scope: input.scope,
53732
+ scope: input.scope ?? "project",
52909
53733
  targetId: input.targetId,
52910
- userId: input.userId,
52911
- role: input.role
53734
+ inviteId: input.inviteId,
53735
+ ttlDays: input.ttlDays
52912
53736
  });
52913
53737
  }
52914
53738
  });
52915
- }
53739
+ registerTool(server, context, {
53740
+ name: "remix_collab_revoke_invite",
53741
+ description: "Revoke an existing invitation for an organization, project, or app, using the current repository binding unless targetId is provided.",
53742
+ access: "remote_write",
53743
+ inputSchema: revokeInviteInputSchema,
53744
+ outputSchema: revokeInviteSuccessSchema,
53745
+ run: async (args) => {
53746
+ const input = external_exports.object(revokeInviteInputSchema).parse(args);
53747
+ assertConfirm(input.confirm, "remix_collab_revoke_invite");
53748
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
53749
+ return revokeInvite({
53750
+ cwd,
53751
+ scope: input.scope ?? "project",
53752
+ targetId: input.targetId,
53753
+ inviteId: input.inviteId
53754
+ });
53755
+ }
53756
+ });
53757
+ registerTool(server, context, {
53758
+ name: "remix_collab_accept_invitation",
53759
+ description: "Accept an invitation token for the currently authenticated Remix user.",
53760
+ access: "remote_write",
53761
+ inputSchema: acceptInvitationInputSchema,
53762
+ outputSchema: acceptInvitationSuccessSchema,
53763
+ annotations: getAnnotations("remote_write", { idempotent: true }),
53764
+ run: async (args) => {
53765
+ const input = external_exports.object(acceptInvitationInputSchema).parse(args);
53766
+ return acceptInvitation({
53767
+ token: input.token
53768
+ });
53769
+ }
53770
+ });
53771
+ registerTool(server, context, {
53772
+ name: "remix_access_debug",
53773
+ description: "Explain why the current user does or does not have access to an organization, project, or app by composing binding, membership, invite, and scope context.",
53774
+ access: "read",
53775
+ inputSchema: accessDebugInputSchema,
53776
+ outputSchema: accessDebugSuccessSchema,
53777
+ run: async (args) => {
53778
+ const input = external_exports.object(accessDebugInputSchema).parse(args);
53779
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
53780
+ return accessDebug({
53781
+ cwd,
53782
+ scope: input.scope ?? "project",
53783
+ targetId: input.targetId
53784
+ });
53785
+ }
53786
+ });
53787
+ registerTool(server, context, {
53788
+ name: "remix_collab_update_member_role",
53789
+ description: "Update an organization, project, or app member role, using the current repository binding unless targetId is provided.",
53790
+ access: "remote_write",
53791
+ inputSchema: updateMemberRoleInputSchema,
53792
+ outputSchema: updateMemberRoleSuccessSchema,
53793
+ run: async (args) => {
53794
+ const input = external_exports.object(updateMemberRoleInputSchema).parse(args);
53795
+ const cwd = resolvePolicyCwd(context.policy, input.cwd);
53796
+ return updateMemberRole({
53797
+ cwd,
53798
+ scope: input.scope,
53799
+ targetId: input.targetId,
53800
+ userId: input.userId,
53801
+ role: input.role
53802
+ });
53803
+ }
53804
+ });
53805
+ }
52916
53806
  var genericRecordSchema2 = external_exports.record(external_exports.string(), external_exports.unknown());
52917
53807
  var genericArraySchema2 = external_exports.array(genericRecordSchema2);
53808
+ var paginationSchema2 = external_exports.object({
53809
+ limit: external_exports.number().int().positive(),
53810
+ offset: external_exports.number().int().nonnegative(),
53811
+ hasMore: external_exports.boolean()
53812
+ });
53813
+ var whoamiInputSchema = {
53814
+ ...commonRequestFieldsSchema
53815
+ };
53816
+ var directoryOrganizationInputSchema = {
53817
+ ...commonRequestFieldsSchema,
53818
+ organizationId: external_exports.string().trim().min(1).optional()
53819
+ };
53820
+ var directoryListProjectsInputSchema = {
53821
+ ...commonRequestFieldsSchema,
53822
+ organizationId: external_exports.string().trim().min(1).optional(),
53823
+ clientAppId: external_exports.string().trim().min(1).optional()
53824
+ };
53825
+ var directoryProjectInputSchema = {
53826
+ ...commonRequestFieldsSchema,
53827
+ projectId: external_exports.string().trim().min(1).optional()
53828
+ };
53829
+ var directoryListAppsInputSchema = {
53830
+ ...commonRequestFieldsSchema,
53831
+ projectId: external_exports.string().trim().min(1).optional(),
53832
+ organizationId: external_exports.string().trim().min(1).optional(),
53833
+ ownership: external_exports.enum(["mine", "shared", "all"]).optional(),
53834
+ accessScope: external_exports.enum(["all_readable", "explicit_member"]).optional(),
53835
+ createdBy: external_exports.string().trim().min(1).optional(),
53836
+ forked: external_exports.enum(["only", "exclude", "all"]).optional(),
53837
+ limit: external_exports.number().int().positive().max(50).optional(),
53838
+ offset: external_exports.number().int().nonnegative().optional()
53839
+ };
53840
+ var directoryAppInputSchema = {
53841
+ ...commonRequestFieldsSchema,
53842
+ appId: external_exports.string().trim().min(1).optional()
53843
+ };
53844
+ var whoamiDataSchema = external_exports.object({
53845
+ id: external_exports.string().nullable(),
53846
+ name: external_exports.string().nullable(),
53847
+ email: external_exports.string().nullable(),
53848
+ organizationId: external_exports.string().nullable(),
53849
+ roles: genericRecordSchema2,
53850
+ binding: genericRecordSchema2.nullable()
53851
+ });
53852
+ var listOrganizationsDataSchema = external_exports.object({
53853
+ organizations: genericArraySchema2
53854
+ });
53855
+ var getOrganizationDataSchema = external_exports.object({
53856
+ organization: genericRecordSchema2
53857
+ });
53858
+ var listProjectsDataSchema = external_exports.object({
53859
+ organizationId: external_exports.string().nullable(),
53860
+ projects: genericArraySchema2
53861
+ });
53862
+ var getProjectDataSchema = external_exports.object({
53863
+ project: genericRecordSchema2
53864
+ });
53865
+ var listAppsDataSchema = external_exports.object({
53866
+ apps: genericArraySchema2,
53867
+ pagination: paginationSchema2,
53868
+ filters: external_exports.object({
53869
+ projectId: external_exports.string().nullable(),
53870
+ organizationId: external_exports.string().nullable(),
53871
+ ownership: external_exports.enum(["mine", "shared", "all"]),
53872
+ accessScope: external_exports.enum(["all_readable", "explicit_member"]),
53873
+ createdBy: external_exports.string().nullable(),
53874
+ forked: external_exports.enum(["only", "exclude", "all"])
53875
+ })
53876
+ });
53877
+ var getAppDataSchema = external_exports.object({
53878
+ app: genericRecordSchema2
53879
+ });
53880
+ var whoamiSuccessSchema = makeSuccessSchema(whoamiDataSchema);
53881
+ var listOrganizationsSuccessSchema = makeSuccessSchema(listOrganizationsDataSchema);
53882
+ var getOrganizationSuccessSchema = makeSuccessSchema(getOrganizationDataSchema);
53883
+ var listProjectsSuccessSchema = makeSuccessSchema(listProjectsDataSchema);
53884
+ var getProjectSuccessSchema = makeSuccessSchema(getProjectDataSchema);
53885
+ var listAppsSuccessSchema = makeSuccessSchema(listAppsDataSchema);
53886
+ var getAppSuccessSchema = makeSuccessSchema(getAppDataSchema);
53887
+ function normalizePagination22(params) {
53888
+ const rawLimit = typeof params?.limit === "number" ? Math.trunc(params.limit) : 25;
53889
+ const rawOffset = typeof params?.offset === "number" ? Math.trunc(params.offset) : 0;
53890
+ return {
53891
+ limit: Math.max(1, Math.min(50, rawLimit)),
53892
+ offset: Math.max(0, rawOffset)
53893
+ };
53894
+ }
53895
+ async function resolveOrganizationId(api, params) {
53896
+ const explicitId = params.organizationId?.trim();
53897
+ if (explicitId) return explicitId;
53898
+ const bindingContext = await loadBindingContext(params.cwd);
53899
+ if (!bindingContext.binding) {
53900
+ throw makeNotBoundError("Organization id was not provided and the current repository is not bound to Remix.");
53901
+ }
53902
+ const appContext = unwrapResponseObject2(
53903
+ await api.getAppContext(bindingContext.binding.currentAppId),
53904
+ "bound app context"
53905
+ );
53906
+ if (!appContext.readableScopes.organization) {
53907
+ throw createAccessDeniedError(
53908
+ "The bound app's organization is not readable to the current user.",
53909
+ "Use an explicit organization id you can access, or inspect the bound app with `remix_directory_get_app` / `remix_access_debug` for app-level context."
53910
+ );
53911
+ }
53912
+ return appContext.organizationId;
53913
+ }
53914
+ async function resolveProjectId(api, params) {
53915
+ const explicitId = params.projectId?.trim();
53916
+ if (explicitId) {
53917
+ const bindingContext2 = await loadBindingContext(params.cwd);
53918
+ return { projectId: explicitId, repoRoot: bindingContext2.repoRoot };
53919
+ }
53920
+ const bindingContext = await loadBindingContext(params.cwd);
53921
+ if (!bindingContext.binding) {
53922
+ throw makeNotBoundError("Project id was not provided and the current repository is not bound to Remix.");
53923
+ }
53924
+ const appContext = unwrapResponseObject2(
53925
+ await api.getAppContext(bindingContext.binding.currentAppId),
53926
+ "bound app context"
53927
+ );
53928
+ if (!appContext.readableScopes.project) {
53929
+ throw createAccessDeniedError(
53930
+ "The bound app's project is not readable to the current user.",
53931
+ "Use `remix_directory_get_app` or `remix_access_debug` for app-level diagnostics, or pass an explicit project id you can access."
53932
+ );
53933
+ }
53934
+ return {
53935
+ projectId: appContext.projectId,
53936
+ repoRoot: bindingContext.repoRoot
53937
+ };
53938
+ }
53939
+ async function resolveAppId(params) {
53940
+ const explicitId = params.appId?.trim();
53941
+ if (explicitId) {
53942
+ const bindingContext2 = await loadBindingContext(params.cwd);
53943
+ return { appId: explicitId, repoRoot: bindingContext2.repoRoot };
53944
+ }
53945
+ const bindingContext = await loadBindingContext(params.cwd);
53946
+ if (!bindingContext.binding) {
53947
+ throw makeNotBoundError("App id was not provided and the current repository is not bound to Remix.");
53948
+ }
53949
+ return {
53950
+ appId: bindingContext.binding.currentAppId,
53951
+ repoRoot: bindingContext.repoRoot
53952
+ };
53953
+ }
53954
+ function toEffectiveAppRole(role) {
53955
+ switch (role) {
53956
+ case "owner":
53957
+ case "maintainer":
53958
+ case "editor":
53959
+ case "viewer":
53960
+ return role;
53961
+ default:
53962
+ return null;
53963
+ }
53964
+ }
53965
+ function resolveAppAccessSource2(params) {
53966
+ if (params.directAppRole && params.inheritedProjectRole) return "both";
53967
+ if (params.directAppRole) return "direct_app_membership";
53968
+ if (params.inheritedProjectRole) return "project_membership";
53969
+ return "none";
53970
+ }
53971
+ function emptySelfRoles() {
53972
+ return {
53973
+ organizationRole: null,
53974
+ projectRole: null,
53975
+ appRole: null,
53976
+ directAppRole: null,
53977
+ inheritedProjectRole: null,
53978
+ appAccessSource: "none"
53979
+ };
53980
+ }
53981
+ function resolveSelfRolesFromAppContext(appContext) {
53982
+ if (!appContext) return emptySelfRoles();
53983
+ const directAppRole = toEffectiveAppRole(appContext.roles.appRole);
53984
+ const inheritedProjectRole = toEffectiveAppRole(appContext.roles.inheritedProjectRole);
53985
+ return {
53986
+ organizationRole: appContext.roles.organizationRole ?? null,
53987
+ projectRole: appContext.roles.projectRole ?? null,
53988
+ appRole: toEffectiveAppRole(appContext.roles.effectiveAppRole),
53989
+ directAppRole,
53990
+ inheritedProjectRole,
53991
+ appAccessSource: resolveAppAccessSource2({ directAppRole, inheritedProjectRole })
53992
+ };
53993
+ }
53994
+ async function whoAmI(params) {
53995
+ const api = await createApiClient2();
53996
+ const bindingContext = await loadBindingContext(params.cwd);
53997
+ const me = unwrapResponseObject2(await api.getMe(), "current user");
53998
+ const warnings = bindingContext.binding ? [] : ["No local Remix binding was detected for the provided cwd."];
53999
+ let boundAppContext = null;
54000
+ let boundProject = null;
54001
+ let boundApp = null;
54002
+ if (bindingContext.binding) {
54003
+ try {
54004
+ boundAppContext = unwrapResponseObject2(
54005
+ await api.getAppContext(bindingContext.binding.currentAppId),
54006
+ "bound app context"
54007
+ );
54008
+ } catch (error2) {
54009
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
54010
+ warnings.push(
54011
+ "The bound app context could not be loaded. The local binding may be stale, or the current user may no longer be able to read that app."
54012
+ );
54013
+ }
54014
+ try {
54015
+ boundApp = unwrapResponseObject2(await api.getApp(bindingContext.binding.currentAppId), "app");
54016
+ } catch (error2) {
54017
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
54018
+ warnings.push("The bound app metadata could not be loaded for the current user.");
54019
+ }
54020
+ if (boundAppContext?.readableScopes.project) {
54021
+ try {
54022
+ boundProject = unwrapResponseObject2(await api.getProject(boundAppContext.projectId), "project");
54023
+ } catch (error2) {
54024
+ if (!isBackendForbidden(error2) && !isBackendNotFound(error2)) throw error2;
54025
+ warnings.push("The bound app is readable, but its project metadata is not currently readable to the current user.");
54026
+ }
54027
+ } else if (boundAppContext) {
54028
+ warnings.push("The bound app is readable, but its project/workspace is not readable to the current user.");
54029
+ }
54030
+ }
54031
+ const roles = resolveSelfRolesFromAppContext(boundAppContext);
54032
+ return {
54033
+ data: {
54034
+ id: me.id ?? null,
54035
+ name: me.name ?? null,
54036
+ email: me.email ?? null,
54037
+ organizationId: me.organizationId ?? null,
54038
+ roles,
54039
+ binding: bindingContext.binding == null ? null : {
54040
+ repoRoot: bindingContext.repoRoot,
54041
+ ...bindingContext.binding,
54042
+ projectId: boundAppContext?.projectId ?? bindingContext.binding.projectId,
54043
+ organizationId: boundAppContext?.organizationId ?? null,
54044
+ visibility: boundAppContext?.visibility ?? null,
54045
+ accessPath: boundAppContext?.accessPath ?? null,
54046
+ readableScopes: boundAppContext?.readableScopes ?? null,
54047
+ projectName: boundProject?.name ?? null,
54048
+ appName: boundApp?.name ?? null
54049
+ }
54050
+ },
54051
+ warnings,
54052
+ recommendedNextActions: bindingContext.binding ? ["Use `remix_access_debug` next when you need to explain repository binding or membership issues in this workspace."] : ["Use `remix_directory_list_organizations` to inspect visible tenancy context, or run `remix_collab_init` in a repository to create a local binding."],
54053
+ logContext: {
54054
+ repoRoot: bindingContext.repoRoot,
54055
+ appId: bindingContext.binding?.currentAppId ?? null
54056
+ }
54057
+ };
54058
+ }
54059
+ async function listOrganizations() {
54060
+ const api = await createApiClient2();
54061
+ const organizations = unwrapResponseObject2(await api.listOrganizations(), "organizations");
54062
+ return {
54063
+ data: { organizations },
54064
+ warnings: [],
54065
+ recommendedNextActions: organizations.length ? ["Use `remix_directory_get_organization` for one organization, or `remix_directory_list_projects` to inspect projects under a chosen organization."] : [],
54066
+ logContext: {}
54067
+ };
54068
+ }
54069
+ async function getOrganization(params) {
54070
+ const api = await createApiClient2();
54071
+ const organizationId = await resolveOrganizationId(api, params);
54072
+ const bindingContext = await loadBindingContext(params.cwd);
54073
+ const organization = unwrapResponseObject2(await api.getOrganization(organizationId), "organization");
54074
+ return {
54075
+ data: { organization },
54076
+ warnings: [],
54077
+ recommendedNextActions: ["Use `remix_directory_list_projects` with this organization id to inspect its project directory."],
54078
+ logContext: {
54079
+ repoRoot: bindingContext.repoRoot
54080
+ }
54081
+ };
54082
+ }
54083
+ async function listProjects(params) {
54084
+ const api = await createApiClient2();
54085
+ const bindingContext = await loadBindingContext(params.cwd);
54086
+ const organizationId = params.organizationId !== void 0 ? await resolveOrganizationId(api, { organizationId: params.organizationId, cwd: params.cwd }) : null;
54087
+ const projects = unwrapResponseObject2(
54088
+ await api.listProjects({
54089
+ organizationId: organizationId ?? void 0,
54090
+ clientAppId: params.clientAppId
54091
+ }),
54092
+ "projects"
54093
+ );
54094
+ return {
54095
+ data: {
54096
+ projects,
54097
+ organizationId
54098
+ },
54099
+ warnings: [],
54100
+ recommendedNextActions: projects.length ? ["Use `remix_directory_get_project` for one project, or `remix_directory_list_apps` to inspect apps under a chosen project or organization."] : [],
54101
+ logContext: {
54102
+ repoRoot: bindingContext.repoRoot,
54103
+ appId: bindingContext.binding?.currentAppId ?? null
54104
+ }
54105
+ };
54106
+ }
54107
+ async function getProject(params) {
54108
+ const api = await createApiClient2();
54109
+ const target = await resolveProjectId(api, params);
54110
+ const project = unwrapResponseObject2(await api.getProject(target.projectId), "project");
54111
+ return {
54112
+ data: { project },
54113
+ warnings: [],
54114
+ recommendedNextActions: ["Use `remix_directory_list_apps` with this project id to inspect apps under the project."],
54115
+ logContext: {
54116
+ repoRoot: target.repoRoot
54117
+ }
54118
+ };
54119
+ }
54120
+ async function listApps2(params) {
54121
+ const api = await createApiClient2();
54122
+ const bindingContext = await loadBindingContext(params.cwd);
54123
+ const pagination = normalizePagination22(params);
54124
+ const apps = unwrapResponseObject2(
54125
+ await api.listApps({
54126
+ projectId: params.projectId,
54127
+ organizationId: params.organizationId,
54128
+ ownership: params.ownership ?? "all",
54129
+ accessScope: params.accessScope ?? "explicit_member",
54130
+ createdBy: params.createdBy,
54131
+ forked: params.forked,
54132
+ limit: pagination.limit + 1,
54133
+ offset: pagination.offset
54134
+ }),
54135
+ "apps"
54136
+ );
54137
+ return {
54138
+ data: {
54139
+ apps: apps.slice(0, pagination.limit),
54140
+ pagination: {
54141
+ ...pagination,
54142
+ hasMore: apps.length > pagination.limit
54143
+ },
54144
+ filters: {
54145
+ projectId: params.projectId ?? null,
54146
+ organizationId: params.organizationId ?? null,
54147
+ ownership: params.ownership ?? "all",
54148
+ accessScope: params.accessScope ?? "explicit_member",
54149
+ createdBy: params.createdBy ?? null,
54150
+ forked: params.forked ?? "all"
54151
+ }
54152
+ },
54153
+ warnings: [],
54154
+ recommendedNextActions: apps.length > pagination.limit ? [`Pass offset=${pagination.offset + pagination.limit} to load the next page.`] : ["Use `remix_directory_get_app` for one app, or `remix_context_get_app_overview` for operational context on a chosen app."],
54155
+ logContext: {
54156
+ repoRoot: bindingContext.repoRoot,
54157
+ appId: bindingContext.binding?.currentAppId ?? null
54158
+ }
54159
+ };
54160
+ }
54161
+ async function getApp(params) {
54162
+ const api = await createApiClient2();
54163
+ const target = await resolveAppId(params);
54164
+ const app = unwrapResponseObject2(await api.getApp(target.appId), "app");
54165
+ return {
54166
+ data: { app },
54167
+ warnings: [],
54168
+ recommendedNextActions: ["Use `remix_context_get_app_overview` for status and capability context, or `remix_ops_list_timeline` for bounded historical activity."],
54169
+ logContext: {
54170
+ repoRoot: target.repoRoot,
54171
+ appId: target.appId
54172
+ }
54173
+ };
54174
+ }
54175
+ function getAnnotations2(access) {
54176
+ return {
54177
+ readOnlyHint: access === "read",
54178
+ destructiveHint: false,
54179
+ idempotentHint: true,
54180
+ openWorldHint: false
54181
+ };
54182
+ }
54183
+ function buildSuccessEnvelope2(tool, requestId, result) {
54184
+ return {
54185
+ schemaVersion: SCHEMA_VERSION,
54186
+ ok: true,
54187
+ tool,
54188
+ requestId: requestId ?? null,
54189
+ data: result.data,
54190
+ warnings: result.warnings ?? [],
54191
+ risks: result.risks ?? [],
54192
+ recommendedNextActions: result.recommendedNextActions ?? []
54193
+ };
54194
+ }
54195
+ function deriveErrorRisks2(normalized) {
54196
+ if (normalized.code === "DESTRUCTIVE_OPERATION_BLOCKED") {
54197
+ return ["A policy guard blocked a disallowed operation."];
54198
+ }
54199
+ return [];
54200
+ }
54201
+ function buildErrorEnvelope2(tool, requestId, error2) {
54202
+ const normalized = normalizeToolError(error2);
54203
+ return {
54204
+ schemaVersion: SCHEMA_VERSION,
54205
+ ok: false,
54206
+ tool,
54207
+ requestId: requestId ?? null,
54208
+ error: normalized,
54209
+ warnings: [],
54210
+ risks: deriveErrorRisks2(normalized),
54211
+ recommendedNextActions: normalized.code === "AUTH_REQUIRED" ? ["Run `remix login` or set COMERGE_ACCESS_TOKEN, then retry."] : []
54212
+ };
54213
+ }
54214
+ function registerTool2(server, context, params) {
54215
+ const errorSchema = makeErrorSchema();
54216
+ server.registerTool(
54217
+ params.name,
54218
+ {
54219
+ title: params.name,
54220
+ description: params.description,
54221
+ inputSchema: params.inputSchema,
54222
+ outputSchema: params.outputSchema,
54223
+ annotations: getAnnotations2(params.access)
54224
+ },
54225
+ async (rawArgs) => {
54226
+ const requestId = typeof rawArgs.requestId === "string" ? rawArgs.requestId : void 0;
54227
+ const startedAt = Date.now();
54228
+ try {
54229
+ assertToolAccess(context.policy, params.access);
54230
+ const result = await params.run(rawArgs);
54231
+ const envelope = buildSuccessEnvelope2(params.name, requestId, result);
54232
+ params.outputSchema.parse(envelope);
54233
+ context.logger.log({
54234
+ level: "info",
54235
+ message: "tool_completed",
54236
+ tool: params.name,
54237
+ requestId: envelope.requestId,
54238
+ durationMs: Date.now() - startedAt,
54239
+ result: "success",
54240
+ repoRoot: result.logContext?.repoRoot ?? null,
54241
+ appId: result.logContext?.appId ?? null,
54242
+ mrId: result.logContext?.mrId ?? null
54243
+ });
54244
+ return makeSuccessResult2(envelope);
54245
+ } catch (error2) {
54246
+ const envelope = buildErrorEnvelope2(params.name, requestId, error2);
54247
+ errorSchema.parse(envelope);
54248
+ context.logger.log({
54249
+ level: "error",
54250
+ message: "tool_failed",
54251
+ tool: params.name,
54252
+ requestId: envelope.requestId,
54253
+ durationMs: Date.now() - startedAt,
54254
+ result: "error",
54255
+ errorCode: envelope.error.code
54256
+ });
54257
+ return makeErrorResult(envelope);
54258
+ }
54259
+ }
54260
+ );
54261
+ }
54262
+ function registerIdentityTools(server, context) {
54263
+ registerTool2(server, context, {
54264
+ name: "remix_identity_whoami",
54265
+ description: "Show the authenticated Remix user and, when cwd is provided, the current local binding and any immediately derivable roles for that bound workspace.",
54266
+ access: "read",
54267
+ inputSchema: whoamiInputSchema,
54268
+ outputSchema: whoamiSuccessSchema,
54269
+ run: async (args) => {
54270
+ const input = external_exports.object(whoamiInputSchema).parse(args);
54271
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54272
+ return whoAmI({ cwd });
54273
+ }
54274
+ });
54275
+ registerTool2(server, context, {
54276
+ name: "remix_directory_list_organizations",
54277
+ description: "List organizations visible to the authenticated Remix user.",
54278
+ access: "read",
54279
+ inputSchema: whoamiInputSchema,
54280
+ outputSchema: listOrganizationsSuccessSchema,
54281
+ run: async () => listOrganizations()
54282
+ });
54283
+ registerTool2(server, context, {
54284
+ name: "remix_directory_get_organization",
54285
+ description: "Fetch one organization by id, or infer the bound repository's organization from cwd when possible.",
54286
+ access: "read",
54287
+ inputSchema: directoryOrganizationInputSchema,
54288
+ outputSchema: getOrganizationSuccessSchema,
54289
+ run: async (args) => {
54290
+ const input = external_exports.object(directoryOrganizationInputSchema).parse(args);
54291
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54292
+ return getOrganization({
54293
+ organizationId: input.organizationId,
54294
+ cwd
54295
+ });
54296
+ }
54297
+ });
54298
+ registerTool2(server, context, {
54299
+ name: "remix_directory_list_projects",
54300
+ description: "List projects visible to the authenticated user, optionally narrowed to one organization or client app.",
54301
+ access: "read",
54302
+ inputSchema: directoryListProjectsInputSchema,
54303
+ outputSchema: listProjectsSuccessSchema,
54304
+ run: async (args) => {
54305
+ const input = external_exports.object(directoryListProjectsInputSchema).parse(args);
54306
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54307
+ return listProjects({
54308
+ organizationId: input.organizationId,
54309
+ clientAppId: input.clientAppId,
54310
+ cwd
54311
+ });
54312
+ }
54313
+ });
54314
+ registerTool2(server, context, {
54315
+ name: "remix_directory_get_project",
54316
+ description: "Fetch one project by id, or infer the bound repository's project from cwd when possible.",
54317
+ access: "read",
54318
+ inputSchema: directoryProjectInputSchema,
54319
+ outputSchema: getProjectSuccessSchema,
54320
+ run: async (args) => {
54321
+ const input = external_exports.object(directoryProjectInputSchema).parse(args);
54322
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54323
+ return getProject({
54324
+ projectId: input.projectId,
54325
+ cwd
54326
+ });
54327
+ }
54328
+ });
54329
+ registerTool2(server, context, {
54330
+ name: "remix_directory_list_apps",
54331
+ description: "List apps visible to the authenticated user, with optional organization, project, ownership, and access-scope filters. Defaults to membership-oriented discovery unless accessScope=all_readable is passed explicitly.",
54332
+ access: "read",
54333
+ inputSchema: directoryListAppsInputSchema,
54334
+ outputSchema: listAppsSuccessSchema,
54335
+ run: async (args) => {
54336
+ const input = external_exports.object(directoryListAppsInputSchema).parse(args);
54337
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54338
+ return listApps2({
54339
+ projectId: input.projectId,
54340
+ organizationId: input.organizationId,
54341
+ ownership: input.ownership,
54342
+ accessScope: input.accessScope,
54343
+ createdBy: input.createdBy,
54344
+ forked: input.forked,
54345
+ limit: input.limit,
54346
+ offset: input.offset,
54347
+ cwd
54348
+ });
54349
+ }
54350
+ });
54351
+ registerTool2(server, context, {
54352
+ name: "remix_directory_get_app",
54353
+ description: "Fetch one app by id, or infer the bound repository's current app from cwd when possible.",
54354
+ access: "read",
54355
+ inputSchema: directoryAppInputSchema,
54356
+ outputSchema: getAppSuccessSchema,
54357
+ run: async (args) => {
54358
+ const input = external_exports.object(directoryAppInputSchema).parse(args);
54359
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
54360
+ return getApp({
54361
+ appId: input.appId,
54362
+ cwd
54363
+ });
54364
+ }
54365
+ });
54366
+ }
54367
+ var genericRecordSchema3 = external_exports.record(external_exports.string(), external_exports.unknown());
54368
+ var genericArraySchema3 = external_exports.array(genericRecordSchema3);
52918
54369
  var memoryKindSchema = external_exports.enum(["collab_turn", "change_step", "merge_request", "reconcile"]);
52919
- var paginationSchema = external_exports.object({
54370
+ var paginationSchema3 = external_exports.object({
52920
54371
  limit: external_exports.number().int().nonnegative(),
52921
54372
  offset: external_exports.number().int().nonnegative(),
52922
54373
  hasMore: external_exports.boolean()
@@ -52949,14 +54400,14 @@ var changeStepDiffInputSchema = {
52949
54400
  appId: external_exports.string().trim().min(1).optional(),
52950
54401
  changeStepId: external_exports.string().trim().min(1)
52951
54402
  };
52952
- var memorySummaryDataSchema = genericRecordSchema2;
54403
+ var memorySummaryDataSchema = genericRecordSchema3;
52953
54404
  var memorySearchDataSchema = external_exports.object({
52954
- items: genericArraySchema2,
52955
- pagination: paginationSchema
54405
+ items: genericArraySchema3,
54406
+ pagination: paginationSchema3
52956
54407
  });
52957
54408
  var memoryTimelineDataSchema = external_exports.object({
52958
- items: genericArraySchema2,
52959
- pagination: paginationSchema
54409
+ items: genericArraySchema3,
54410
+ pagination: paginationSchema3
52960
54411
  });
52961
54412
  var changeStepDiffDataSchema = external_exports.object({
52962
54413
  changeStepId: external_exports.string(),
@@ -53044,12 +54495,12 @@ function unwrapResponseObject22(resp, label) {
53044
54495
  }
53045
54496
  return obj;
53046
54497
  }
53047
- function makeNotBoundError() {
54498
+ function makeNotBoundError2() {
53048
54499
  const error2 = new Error("Repository is not bound to Remix.");
53049
54500
  error2.hint = "Run `remix_collab_init` in this repository, or pass `appId` explicitly for a direct memory read.";
53050
54501
  return error2;
53051
54502
  }
53052
- async function maybeFindGitRoot(cwd) {
54503
+ async function maybeFindGitRoot2(cwd) {
53053
54504
  try {
53054
54505
  return await findGitRoot(cwd);
53055
54506
  } catch {
@@ -53061,13 +54512,13 @@ async function resolveMemoryTarget(params) {
53061
54512
  if (explicitAppId) {
53062
54513
  return {
53063
54514
  appId: explicitAppId,
53064
- repoRoot: await maybeFindGitRoot(params.cwd)
54515
+ repoRoot: await maybeFindGitRoot2(params.cwd)
53065
54516
  };
53066
54517
  }
53067
54518
  const repoRoot = await findGitRoot(params.cwd);
53068
54519
  const binding = await readCollabBinding(repoRoot);
53069
54520
  if (!binding) {
53070
- throw makeNotBoundError();
54521
+ throw makeNotBoundError2();
53071
54522
  }
53072
54523
  return {
53073
54524
  appId: binding.currentAppId,
@@ -53135,7 +54586,7 @@ async function getChangeStepDiff(params) {
53135
54586
  logContext: target
53136
54587
  };
53137
54588
  }
53138
- function getAnnotations2(access) {
54589
+ function getAnnotations3(access) {
53139
54590
  return {
53140
54591
  readOnlyHint: access === "read",
53141
54592
  destructiveHint: false,
@@ -53143,7 +54594,7 @@ function getAnnotations2(access) {
53143
54594
  openWorldHint: false
53144
54595
  };
53145
54596
  }
53146
- function buildSuccessEnvelope2(tool, requestId, result) {
54597
+ function buildSuccessEnvelope3(tool, requestId, result) {
53147
54598
  return {
53148
54599
  schemaVersion: SCHEMA_VERSION,
53149
54600
  ok: true,
@@ -53155,7 +54606,7 @@ function buildSuccessEnvelope2(tool, requestId, result) {
53155
54606
  recommendedNextActions: result.recommendedNextActions ?? []
53156
54607
  };
53157
54608
  }
53158
- function buildErrorEnvelope2(tool, requestId, error2) {
54609
+ function buildErrorEnvelope3(tool, requestId, error2) {
53159
54610
  const normalized = normalizeToolError(error2);
53160
54611
  return {
53161
54612
  schemaVersion: SCHEMA_VERSION,
@@ -53164,17 +54615,17 @@ function buildErrorEnvelope2(tool, requestId, error2) {
53164
54615
  requestId: requestId ?? null,
53165
54616
  error: normalized,
53166
54617
  warnings: [],
53167
- risks: deriveErrorRisks2(normalized),
54618
+ risks: deriveErrorRisks3(normalized),
53168
54619
  recommendedNextActions: normalized.code === "AUTH_REQUIRED" ? ["Run `remix login` or set COMERGE_ACCESS_TOKEN, then retry."] : []
53169
54620
  };
53170
54621
  }
53171
- function deriveErrorRisks2(normalized) {
54622
+ function deriveErrorRisks3(normalized) {
53172
54623
  if (normalized.code === "DESTRUCTIVE_OPERATION_BLOCKED") {
53173
54624
  return ["A policy guard blocked a disallowed operation."];
53174
54625
  }
53175
54626
  return [];
53176
54627
  }
53177
- function registerTool2(server, context, params) {
54628
+ function registerTool3(server, context, params) {
53178
54629
  const errorSchema = makeErrorSchema();
53179
54630
  server.registerTool(
53180
54631
  params.name,
@@ -53183,7 +54634,7 @@ function registerTool2(server, context, params) {
53183
54634
  description: params.description,
53184
54635
  inputSchema: params.inputSchema,
53185
54636
  outputSchema: params.outputSchema,
53186
- annotations: getAnnotations2(params.access)
54637
+ annotations: getAnnotations3(params.access)
53187
54638
  },
53188
54639
  async (rawArgs) => {
53189
54640
  const requestId = typeof rawArgs.requestId === "string" ? rawArgs.requestId : void 0;
@@ -53191,7 +54642,7 @@ function registerTool2(server, context, params) {
53191
54642
  try {
53192
54643
  assertToolAccess(context.policy, params.access);
53193
54644
  const result = await params.run(rawArgs);
53194
- const envelope = buildSuccessEnvelope2(params.name, requestId, result);
54645
+ const envelope = buildSuccessEnvelope3(params.name, requestId, result);
53195
54646
  params.outputSchema.parse(envelope);
53196
54647
  context.logger.log({
53197
54648
  level: "info",
@@ -53207,7 +54658,7 @@ function registerTool2(server, context, params) {
53207
54658
  });
53208
54659
  return makeSuccessResult2(envelope);
53209
54660
  } catch (error2) {
53210
- const envelope = buildErrorEnvelope2(params.name, requestId, error2);
54661
+ const envelope = buildErrorEnvelope3(params.name, requestId, error2);
53211
54662
  errorSchema.parse(envelope);
53212
54663
  context.logger.log({
53213
54664
  level: "error",
@@ -53224,7 +54675,7 @@ function registerTool2(server, context, params) {
53224
54675
  );
53225
54676
  }
53226
54677
  function registerMemoryTools(server, context) {
53227
- registerTool2(server, context, {
54678
+ registerTool3(server, context, {
53228
54679
  name: "remix_collab_memory_summary",
53229
54680
  description: "First read for a bound app's current collaboration state, recent reasoning context, and merge or reconcile history before deeper inspection or any raw git history lookup.",
53230
54681
  access: "read",
@@ -53239,7 +54690,7 @@ function registerMemoryTools(server, context) {
53239
54690
  });
53240
54691
  }
53241
54692
  });
53242
- registerTool2(server, context, {
54693
+ registerTool3(server, context, {
53243
54694
  name: "remix_collab_memory_search",
53244
54695
  description: "Default tool for why/history/failed-attempt/user-intent questions. Search prompts, diffs, merge activity, reconciles, and other historical context before using raw git for exact repository facts.",
53245
54696
  access: "read",
@@ -53260,7 +54711,7 @@ function registerMemoryTools(server, context) {
53260
54711
  });
53261
54712
  }
53262
54713
  });
53263
- registerTool2(server, context, {
54714
+ registerTool3(server, context, {
53264
54715
  name: "remix_collab_memory_timeline",
53265
54716
  description: "Chronological view of collaboration memory for understanding what happened and in what order, with optional filters for bounded historical inspection before any exact-facts raw git follow-up.",
53266
54717
  access: "read",
@@ -53280,7 +54731,7 @@ function registerMemoryTools(server, context) {
53280
54731
  });
53281
54732
  }
53282
54733
  });
53283
- registerTool2(server, context, {
54734
+ registerTool3(server, context, {
53284
54735
  name: "remix_collab_memory_change_step_diff",
53285
54736
  description: "Second-hop expansion tool that fetches the full stored diff for a specific change step after memory search, timeline, or review work has identified the relevant `changeStepId`, keeping historical inspection inside Remix before raw git fallback.",
53286
54737
  access: "read",
@@ -53297,13 +54748,441 @@ function registerMemoryTools(server, context) {
53297
54748
  }
53298
54749
  });
53299
54750
  }
54751
+ var genericRecordSchema4 = external_exports.record(external_exports.string(), external_exports.unknown());
54752
+ var appScopedInputSchema = {
54753
+ ...commonRequestFieldsSchema,
54754
+ appId: external_exports.string().trim().min(1).optional()
54755
+ };
54756
+ var editQueueInputSchema = {
54757
+ ...appScopedInputSchema,
54758
+ limit: external_exports.number().int().positive().max(100).optional(),
54759
+ offset: external_exports.number().int().nonnegative().optional()
54760
+ };
54761
+ var bundleInputSchema = {
54762
+ ...appScopedInputSchema,
54763
+ bundleId: external_exports.string().trim().min(1)
54764
+ };
54765
+ var timelineInputSchema = {
54766
+ ...appScopedInputSchema,
54767
+ limit: external_exports.number().int().positive().max(100).optional(),
54768
+ cursor: external_exports.string().trim().min(1).optional()
54769
+ };
54770
+ var agentRunsInputSchema = {
54771
+ ...appScopedInputSchema,
54772
+ limit: external_exports.number().int().positive().max(100).optional(),
54773
+ offset: external_exports.number().int().nonnegative().optional(),
54774
+ status: external_exports.string().trim().min(1).optional(),
54775
+ currentPhase: external_exports.string().trim().min(1).optional(),
54776
+ createdAfter: external_exports.string().datetime().optional(),
54777
+ createdBefore: external_exports.string().datetime().optional()
54778
+ };
54779
+ var agentRunInputSchema = {
54780
+ ...appScopedInputSchema,
54781
+ runId: external_exports.string().trim().min(1)
54782
+ };
54783
+ var agentRunEventsInputSchema = {
54784
+ ...appScopedInputSchema,
54785
+ runId: external_exports.string().trim().min(1),
54786
+ limit: external_exports.number().int().positive().max(100).optional(),
54787
+ offset: external_exports.number().int().nonnegative().optional(),
54788
+ createdAfter: external_exports.string().datetime().optional(),
54789
+ createdBefore: external_exports.string().datetime().optional()
54790
+ };
54791
+ var appOverviewSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54792
+ var editQueueSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54793
+ var bundleSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54794
+ var timelineSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54795
+ var agentRunsSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54796
+ var agentRunSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54797
+ var agentRunEventsSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54798
+ var sandboxStatusSuccessSchema = makeSuccessSchema(genericRecordSchema4);
54799
+ async function resolveAppTarget(_api, params) {
54800
+ const explicitAppId = params.appId?.trim();
54801
+ const bindingContext = await loadBindingContext(params.cwd);
54802
+ if (explicitAppId) {
54803
+ return {
54804
+ appId: explicitAppId,
54805
+ repoRoot: bindingContext.repoRoot
54806
+ };
54807
+ }
54808
+ if (!bindingContext.binding) {
54809
+ throw makeNotBoundError("App id was not provided and the current repository is not bound to Remix.");
54810
+ }
54811
+ return {
54812
+ appId: bindingContext.binding.currentAppId,
54813
+ repoRoot: bindingContext.repoRoot
54814
+ };
54815
+ }
54816
+ async function getAppOverview(params) {
54817
+ const api = await createApiClient2();
54818
+ const target = await resolveAppTarget(api, params);
54819
+ const data = unwrapResponseObject2(await api.getAppOverview(target.appId), "app overview");
54820
+ return {
54821
+ data,
54822
+ warnings: [],
54823
+ recommendedNextActions: [
54824
+ "Use `remix_ops_list_timeline`, `remix_ops_list_agent_runs`, `remix_ops_get_edit_queue`, or `remix_ops_get_sandbox_status` for the next operational drill-down on this app."
54825
+ ],
54826
+ logContext: target
54827
+ };
54828
+ }
54829
+ async function getEditQueue(params) {
54830
+ const api = await createApiClient2();
54831
+ const target = await resolveAppTarget(api, params);
54832
+ const data = unwrapResponseObject2(
54833
+ await api.listAppEditQueue(target.appId, {
54834
+ limit: params.limit,
54835
+ offset: params.offset
54836
+ }),
54837
+ "edit queue"
54838
+ );
54839
+ const pageInfo = typeof data.pageInfo === "object" && data.pageInfo ? data.pageInfo : null;
54840
+ return {
54841
+ data,
54842
+ warnings: [],
54843
+ recommendedNextActions: pageInfo?.hasMore === true && typeof pageInfo.limit === "number" && typeof pageInfo.offset === "number" ? [`Pass offset=${pageInfo.offset + pageInfo.limit} to load the next edit queue page.`] : [],
54844
+ logContext: target
54845
+ };
54846
+ }
54847
+ async function getBundle(params) {
54848
+ const api = await createApiClient2();
54849
+ const target = await resolveAppTarget(api, params);
54850
+ const data = unwrapResponseObject2(await api.getBundle(target.appId, params.bundleId), "bundle");
54851
+ return {
54852
+ data,
54853
+ warnings: [],
54854
+ recommendedNextActions: ["Use the bundle download-url client methods only when you need the actual artifact, not just metadata inspection."],
54855
+ logContext: target
54856
+ };
54857
+ }
54858
+ async function listTimeline(params) {
54859
+ const api = await createApiClient2();
54860
+ const target = await resolveAppTarget(api, params);
54861
+ const data = unwrapResponseObject2(
54862
+ await api.listAppTimeline(target.appId, {
54863
+ limit: params.limit,
54864
+ cursor: params.cursor
54865
+ }),
54866
+ "app timeline"
54867
+ );
54868
+ const pageInfo = typeof data.pageInfo === "object" && data.pageInfo ? data.pageInfo : null;
54869
+ return {
54870
+ data,
54871
+ warnings: [],
54872
+ recommendedNextActions: pageInfo?.hasMore === true && typeof pageInfo.nextCursor === "string" ? [`Pass cursor=${pageInfo.nextCursor} to load the next timeline page.`] : [],
54873
+ logContext: target
54874
+ };
54875
+ }
54876
+ async function listAgentRuns(params) {
54877
+ const api = await createApiClient2();
54878
+ const target = await resolveAppTarget(api, params);
54879
+ const data = unwrapResponseObject2(
54880
+ await api.listAgentRuns(target.appId, {
54881
+ limit: params.limit,
54882
+ offset: params.offset,
54883
+ status: params.status,
54884
+ currentPhase: params.currentPhase,
54885
+ createdAfter: params.createdAfter,
54886
+ createdBefore: params.createdBefore
54887
+ }),
54888
+ "agent runs"
54889
+ );
54890
+ const pageInfo = typeof data.pageInfo === "object" && data.pageInfo ? data.pageInfo : null;
54891
+ const items = Array.isArray(data.items) ? data.items : [];
54892
+ const firstRunId = items.length > 0 && items[0] && typeof items[0] === "object" && typeof items[0].id === "string" ? items[0].id : null;
54893
+ const recommendedNextActions = [];
54894
+ if (firstRunId) {
54895
+ recommendedNextActions.push(
54896
+ `Use \`remix_ops_get_agent_run\` with \`runId=${firstRunId}\` for the top listed run, then \`remix_ops_list_agent_run_events\` if you need its event stream.`
54897
+ );
54898
+ }
54899
+ if (pageInfo?.hasMore === true && typeof pageInfo.limit === "number" && typeof pageInfo.offset === "number") {
54900
+ recommendedNextActions.push(`Pass offset=${pageInfo.offset + pageInfo.limit} to load the next agent-runs page.`);
54901
+ }
54902
+ return {
54903
+ data,
54904
+ warnings: [],
54905
+ recommendedNextActions,
54906
+ logContext: target
54907
+ };
54908
+ }
54909
+ async function getAgentRun(params) {
54910
+ const api = await createApiClient2();
54911
+ const target = await resolveAppTarget(api, params);
54912
+ const data = unwrapResponseObject2(await api.getAgentRun(target.appId, params.runId), "agent run");
54913
+ return {
54914
+ data,
54915
+ warnings: [],
54916
+ recommendedNextActions: [`Use \`remix_ops_list_agent_run_events\` with \`runId=${params.runId}\` for the event stream behind this run.`],
54917
+ logContext: target
54918
+ };
54919
+ }
54920
+ async function listAgentRunEvents(params) {
54921
+ const api = await createApiClient2();
54922
+ const target = await resolveAppTarget(api, params);
54923
+ const data = unwrapResponseObject2(
54924
+ await api.listAgentRunEvents(target.appId, params.runId, {
54925
+ limit: params.limit,
54926
+ offset: params.offset,
54927
+ createdAfter: params.createdAfter,
54928
+ createdBefore: params.createdBefore
54929
+ }),
54930
+ "agent run events"
54931
+ );
54932
+ const pageInfo = typeof data.pageInfo === "object" && data.pageInfo ? data.pageInfo : null;
54933
+ return {
54934
+ data,
54935
+ warnings: [],
54936
+ recommendedNextActions: pageInfo?.hasMore === true && typeof pageInfo.limit === "number" && typeof pageInfo.offset === "number" ? [`Pass offset=${pageInfo.offset + pageInfo.limit} to load the next event page.`] : [],
54937
+ logContext: target
54938
+ };
54939
+ }
54940
+ async function getSandboxStatus(params) {
54941
+ const api = await createApiClient2();
54942
+ const target = await resolveAppTarget(api, params);
54943
+ const data = unwrapResponseObject2(await api.getSandboxStatus(target.appId), "sandbox status");
54944
+ return {
54945
+ data,
54946
+ warnings: [],
54947
+ recommendedNextActions: ["Use the sandbox metadata here to decide whether a resume is plausible before attempting any write-side sandbox action."],
54948
+ logContext: target
54949
+ };
54950
+ }
54951
+ function getAnnotations4(access) {
54952
+ return {
54953
+ readOnlyHint: access === "read",
54954
+ destructiveHint: false,
54955
+ idempotentHint: true,
54956
+ openWorldHint: false
54957
+ };
54958
+ }
54959
+ function buildSuccessEnvelope4(tool, requestId, result) {
54960
+ return {
54961
+ schemaVersion: SCHEMA_VERSION,
54962
+ ok: true,
54963
+ tool,
54964
+ requestId: requestId ?? null,
54965
+ data: result.data,
54966
+ warnings: result.warnings ?? [],
54967
+ risks: result.risks ?? [],
54968
+ recommendedNextActions: result.recommendedNextActions ?? []
54969
+ };
54970
+ }
54971
+ function deriveErrorRisks4(normalized) {
54972
+ if (normalized.code === "DESTRUCTIVE_OPERATION_BLOCKED") {
54973
+ return ["A policy guard blocked a disallowed operation."];
54974
+ }
54975
+ return [];
54976
+ }
54977
+ function buildErrorEnvelope4(tool, requestId, error2) {
54978
+ const normalized = normalizeToolError(error2);
54979
+ return {
54980
+ schemaVersion: SCHEMA_VERSION,
54981
+ ok: false,
54982
+ tool,
54983
+ requestId: requestId ?? null,
54984
+ error: normalized,
54985
+ warnings: [],
54986
+ risks: deriveErrorRisks4(normalized),
54987
+ recommendedNextActions: normalized.code === "AUTH_REQUIRED" ? ["Run `remix login` or set COMERGE_ACCESS_TOKEN, then retry."] : []
54988
+ };
54989
+ }
54990
+ function registerTool4(server, context, params) {
54991
+ const errorSchema = makeErrorSchema();
54992
+ server.registerTool(
54993
+ params.name,
54994
+ {
54995
+ title: params.name,
54996
+ description: params.description,
54997
+ inputSchema: params.inputSchema,
54998
+ outputSchema: params.outputSchema,
54999
+ annotations: getAnnotations4(params.access)
55000
+ },
55001
+ async (rawArgs) => {
55002
+ const requestId = typeof rawArgs.requestId === "string" ? rawArgs.requestId : void 0;
55003
+ const startedAt = Date.now();
55004
+ try {
55005
+ assertToolAccess(context.policy, params.access);
55006
+ const result = await params.run(rawArgs);
55007
+ const envelope = buildSuccessEnvelope4(params.name, requestId, result);
55008
+ params.outputSchema.parse(envelope);
55009
+ context.logger.log({
55010
+ level: "info",
55011
+ message: "tool_completed",
55012
+ tool: params.name,
55013
+ requestId: envelope.requestId,
55014
+ durationMs: Date.now() - startedAt,
55015
+ result: "success",
55016
+ repoRoot: result.logContext?.repoRoot ?? null,
55017
+ appId: result.logContext?.appId ?? null,
55018
+ mrId: result.logContext?.mrId ?? null
55019
+ });
55020
+ return makeSuccessResult2(envelope);
55021
+ } catch (error2) {
55022
+ const envelope = buildErrorEnvelope4(params.name, requestId, error2);
55023
+ errorSchema.parse(envelope);
55024
+ context.logger.log({
55025
+ level: "error",
55026
+ message: "tool_failed",
55027
+ tool: params.name,
55028
+ requestId: envelope.requestId,
55029
+ durationMs: Date.now() - startedAt,
55030
+ result: "error",
55031
+ errorCode: envelope.error.code
55032
+ });
55033
+ return makeErrorResult(envelope);
55034
+ }
55035
+ }
55036
+ );
55037
+ }
55038
+ function registerOpsTools(server, context) {
55039
+ registerTool4(server, context, {
55040
+ name: "remix_context_get_app_overview",
55041
+ description: "Read the current app's overview, capabilities, and workflow readiness without mutating state.",
55042
+ access: "read",
55043
+ inputSchema: appScopedInputSchema,
55044
+ outputSchema: appOverviewSuccessSchema,
55045
+ run: async (args) => {
55046
+ const input = external_exports.object(appScopedInputSchema).parse(args);
55047
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55048
+ return getAppOverview({
55049
+ appId: input.appId,
55050
+ cwd
55051
+ });
55052
+ }
55053
+ });
55054
+ registerTool4(server, context, {
55055
+ name: "remix_ops_get_edit_queue",
55056
+ description: "Inspect the pending edit queue for one app with bounded pagination.",
55057
+ access: "read",
55058
+ inputSchema: editQueueInputSchema,
55059
+ outputSchema: editQueueSuccessSchema,
55060
+ run: async (args) => {
55061
+ const input = external_exports.object(editQueueInputSchema).parse(args);
55062
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55063
+ return getEditQueue({
55064
+ appId: input.appId,
55065
+ cwd,
55066
+ limit: input.limit,
55067
+ offset: input.offset
55068
+ });
55069
+ }
55070
+ });
55071
+ registerTool4(server, context, {
55072
+ name: "remix_ops_get_bundle",
55073
+ description: "Inspect one app bundle by id without downloading the artifact payload.",
55074
+ access: "read",
55075
+ inputSchema: bundleInputSchema,
55076
+ outputSchema: bundleSuccessSchema,
55077
+ run: async (args) => {
55078
+ const input = external_exports.object(bundleInputSchema).parse(args);
55079
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55080
+ return getBundle({
55081
+ appId: input.appId,
55082
+ cwd,
55083
+ bundleId: input.bundleId
55084
+ });
55085
+ }
55086
+ });
55087
+ registerTool4(server, context, {
55088
+ name: "remix_ops_list_timeline",
55089
+ description: "List bounded timeline events for one app using the backend cursor pagination model.",
55090
+ access: "read",
55091
+ inputSchema: timelineInputSchema,
55092
+ outputSchema: timelineSuccessSchema,
55093
+ run: async (args) => {
55094
+ const input = external_exports.object(timelineInputSchema).parse(args);
55095
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55096
+ return listTimeline({
55097
+ appId: input.appId,
55098
+ cwd,
55099
+ limit: input.limit,
55100
+ cursor: input.cursor
55101
+ });
55102
+ }
55103
+ });
55104
+ registerTool4(server, context, {
55105
+ name: "remix_ops_get_agent_run",
55106
+ description: "Fetch one stored agent run for an app, including status, phase, and summary metadata.",
55107
+ access: "read",
55108
+ inputSchema: agentRunInputSchema,
55109
+ outputSchema: agentRunSuccessSchema,
55110
+ run: async (args) => {
55111
+ const input = external_exports.object(agentRunInputSchema).parse(args);
55112
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55113
+ return getAgentRun({
55114
+ appId: input.appId,
55115
+ cwd,
55116
+ runId: input.runId
55117
+ });
55118
+ }
55119
+ });
55120
+ registerTool4(server, context, {
55121
+ name: "remix_ops_list_agent_runs",
55122
+ description: "List paginated agent runs for one app so run ids can be discovered before deeper inspection.",
55123
+ access: "read",
55124
+ inputSchema: agentRunsInputSchema,
55125
+ outputSchema: agentRunsSuccessSchema,
55126
+ run: async (args) => {
55127
+ const input = external_exports.object(agentRunsInputSchema).parse(args);
55128
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55129
+ return listAgentRuns({
55130
+ appId: input.appId,
55131
+ cwd,
55132
+ limit: input.limit,
55133
+ offset: input.offset,
55134
+ status: input.status,
55135
+ currentPhase: input.currentPhase,
55136
+ createdAfter: input.createdAfter,
55137
+ createdBefore: input.createdBefore
55138
+ });
55139
+ }
55140
+ });
55141
+ registerTool4(server, context, {
55142
+ name: "remix_ops_list_agent_run_events",
55143
+ description: "List paginated agent-run events for one stored run, with optional time bounds.",
55144
+ access: "read",
55145
+ inputSchema: agentRunEventsInputSchema,
55146
+ outputSchema: agentRunEventsSuccessSchema,
55147
+ run: async (args) => {
55148
+ const input = external_exports.object(agentRunEventsInputSchema).parse(args);
55149
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55150
+ return listAgentRunEvents({
55151
+ appId: input.appId,
55152
+ cwd,
55153
+ runId: input.runId,
55154
+ limit: input.limit,
55155
+ offset: input.offset,
55156
+ createdAfter: input.createdAfter,
55157
+ createdBefore: input.createdBefore
55158
+ });
55159
+ }
55160
+ });
55161
+ registerTool4(server, context, {
55162
+ name: "remix_ops_get_sandbox_status",
55163
+ description: "Read safe sandbox metadata and the latest migration status for one app without exposing execution handles or secrets.",
55164
+ access: "read",
55165
+ inputSchema: appScopedInputSchema,
55166
+ outputSchema: sandboxStatusSuccessSchema,
55167
+ run: async (args) => {
55168
+ const input = external_exports.object(appScopedInputSchema).parse(args);
55169
+ const cwd = input.cwd ? resolvePolicyCwd(context.policy, input.cwd) : void 0;
55170
+ return getSandboxStatus({
55171
+ appId: input.appId,
55172
+ cwd
55173
+ });
55174
+ }
55175
+ });
55176
+ }
53300
55177
  function createRemixMcpServer(params) {
53301
55178
  const context = createServerContext({ version: params.version });
53302
55179
  const server = new McpServer({
53303
55180
  name: context.serverName,
53304
55181
  version: context.version
53305
55182
  });
55183
+ registerIdentityTools(server, context);
53306
55184
  registerCollabTools(server, context);
55185
+ registerOpsTools(server, context);
53307
55186
  registerMemoryTools(server, context);
53308
55187
  return { server, context };
53309
55188
  }
@@ -53450,7 +55329,7 @@ async function listPendingTurnStateSummaries() {
53450
55329
  // package.json
53451
55330
  var package_default = {
53452
55331
  name: "@remixhq/claude-plugin",
53453
- version: "0.1.12",
55332
+ version: "0.1.15",
53454
55333
  description: "Claude Code plugin for Remix collaboration workflows",
53455
55334
  homepage: "https://github.com/RemixDotOne/remix-claude-plugin",
53456
55335
  license: "MIT",
@@ -53481,8 +55360,8 @@ var package_default = {
53481
55360
  prepack: "npm run build"
53482
55361
  },
53483
55362
  dependencies: {
53484
- "@remixhq/core": "^0.1.8",
53485
- "@remixhq/mcp": "^0.1.8"
55363
+ "@remixhq/core": "^0.1.10",
55364
+ "@remixhq/mcp": "^0.1.10"
53486
55365
  },
53487
55366
  devDependencies: {
53488
55367
  "@types/node": "^25.4.0",
@@ -53575,7 +55454,7 @@ var outputSchema = external_exports.object({
53575
55454
  toolName: external_exports.string().nullable(),
53576
55455
  repoRoot: external_exports.string().nullable(),
53577
55456
  message: external_exports.string().nullable(),
53578
- fields: external_exports.record(external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null()]))
55457
+ fields: external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.null()]))
53579
55458
  })
53580
55459
  ),
53581
55460
  pendingStates: external_exports.array(