@ixo/editor 5.25.0 → 5.26.0

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.
@@ -206,6 +206,32 @@ function buildServicesFromHandlers(handlers) {
206
206
  matrix: handlers?.storeMatrixCredential ? {
207
207
  storeCredential: async (params) => handlers.storeMatrixCredential(params)
208
208
  } : void 0,
209
+ // Claim-collection lifecycle service (IXO-2573/2579). The consumer exposes
210
+ // a fully-formed `handlers.collection` service group (get + create + the
211
+ // five updates); wire each method straight through. The core run()
212
+ // dispatcher resolves admin from the on-chain collection.admin and
213
+ // re-fetches via `get` after every write, so we only forward calls here.
214
+ collection: handlers?.collection?.get && handlers?.collection?.create && handlers?.collection?.updateState && handlers?.collection?.updateDates && handlers?.collection?.updateQuota && handlers?.collection?.updatePayments && handlers?.collection?.updateIntents ? {
215
+ get: async (params) => handlers.collection.get(params),
216
+ create: async (params) => handlers.collection.create(params),
217
+ updateState: async (params) => handlers.collection.updateState(params),
218
+ updateDates: async (params) => handlers.collection.updateDates(params),
219
+ updateQuota: async (params) => handlers.collection.updateQuota(params),
220
+ updatePayments: async (params) => handlers.collection.updatePayments(params),
221
+ updateIntents: async (params) => handlers.collection.updateIntents(params)
222
+ } : void 0,
223
+ // Claim-collection user-management service (IXO-2586). The consumer exposes a
224
+ // fully-formed `handlers.collectionUsers` service group (grant + revoke +
225
+ // list + classifyAddress + enumerateMembers); wire each method straight
226
+ // through. The core run() dispatcher validates inputs and proof-guards the
227
+ // results, so we only forward calls here.
228
+ collectionUsers: handlers?.collectionUsers?.grant && handlers?.collectionUsers?.revoke && handlers?.collectionUsers?.list && handlers?.collectionUsers?.classifyAddress && handlers?.collectionUsers?.enumerateMembers ? {
229
+ grant: async (params) => handlers.collectionUsers.grant(params),
230
+ revoke: async (params) => handlers.collectionUsers.revoke(params),
231
+ list: async (params) => handlers.collectionUsers.list(params),
232
+ classifyAddress: async (params) => handlers.collectionUsers.classifyAddress(params),
233
+ enumerateMembers: async (params) => handlers.collectionUsers.enumerateMembers(params)
234
+ } : void 0,
209
235
  integrations: handlers?.integrations?.executeTool ? {
210
236
  executeTool: async (args) => handlers.integrations.executeTool(args),
211
237
  fetchCurrentState: handlers.integrations.fetchCurrentState ? async (args) => handlers.integrations.fetchCurrentState(args) : void 0,
@@ -4866,6 +4892,350 @@ registerAction({
4866
4892
  }
4867
4893
  });
4868
4894
 
4895
+ // src/core/lib/actionRegistry/actions/collection/index.ts
4896
+ var COLLECTION_LIFECYCLE_ACTION_TYPE = "qi/collection.lifecycle";
4897
+ var COLLECTION_LIFECYCLE_OUTPUT_SCHEMA = [
4898
+ { path: "collectionId", displayName: "Collection ID", type: "string", description: "Chain-assigned collection identifier" },
4899
+ { path: "entity", displayName: "Entity DID", type: "string", description: "Entity (deed) DID the collection belongs to" },
4900
+ { path: "protocol", displayName: "Protocol", type: "string", description: "Protocol DID/id the collection follows" },
4901
+ { path: "admin", displayName: "Admin Address", type: "string", description: "Address authorised to mutate the collection" },
4902
+ { path: "state", displayName: "State", type: "number", description: "Lifecycle state (0=OPEN, 1=PAUSED, 2=CLOSED)" },
4903
+ { path: "startDate", displayName: "Start Date", type: "string", description: "ISO-8601 start date" },
4904
+ { path: "endDate", displayName: "End Date", type: "string", description: "ISO-8601 end date" },
4905
+ { path: "quota", displayName: "Quota", type: "string", description: "Max claims; 0 = unlimited" },
4906
+ { path: "count", displayName: "Count", type: "string", description: "Number of claims submitted" },
4907
+ { path: "evaluated", displayName: "Evaluated", type: "string", description: "Number of claims evaluated" },
4908
+ { path: "approved", displayName: "Approved", type: "string", description: "Number of approved claims" },
4909
+ { path: "rejected", displayName: "Rejected", type: "string", description: "Number of rejected claims" },
4910
+ { path: "disputed", displayName: "Disputed", type: "string", description: "Number of disputed claims" },
4911
+ { path: "payments", displayName: "Payments", type: "object", description: "Payment legs (submission/evaluation/approval/rejection)" },
4912
+ { path: "intents", displayName: "Intents", type: "object", description: "Intent configuration" }
4913
+ ];
4914
+ var COLLECTION_CREATED_EVENT_NAME = "created";
4915
+ var COLLECTION_CREATED_EVENT = {
4916
+ name: COLLECTION_CREATED_EVENT_NAME,
4917
+ displayName: "Collection created",
4918
+ description: "Fires once when a new claim collection is created on-chain. Carries the collection id, entity (deed) DID and protocol so a listener can manage the new collection.",
4919
+ payloadSchema: [
4920
+ { path: "collectionId", displayName: "Collection ID", type: "string", description: "Chain-assigned collection identifier" },
4921
+ { path: "entity", displayName: "Entity DID", type: "string", description: "Entity (deed) DID the collection belongs to" },
4922
+ { path: "protocol", displayName: "Protocol", type: "string", description: "Protocol DID/id the collection follows" },
4923
+ { path: "transactionHash", displayName: "Tx Hash", type: "string", description: "MsgCreateCollection broadcast transaction hash" }
4924
+ ],
4925
+ pendingDisplayFields: ["collectionId", "entity"]
4926
+ };
4927
+
4928
+ // src/core/lib/actionRegistry/types.ts
4929
+ var CollectionStateEnum = /* @__PURE__ */ ((CollectionStateEnum2) => {
4930
+ CollectionStateEnum2[CollectionStateEnum2["OPEN"] = 0] = "OPEN";
4931
+ CollectionStateEnum2[CollectionStateEnum2["PAUSED"] = 1] = "PAUSED";
4932
+ CollectionStateEnum2[CollectionStateEnum2["CLOSED"] = 2] = "CLOSED";
4933
+ return CollectionStateEnum2;
4934
+ })(CollectionStateEnum || {});
4935
+
4936
+ // src/core/lib/actionRegistry/actions/collection/collection.ts
4937
+ function normalizeQuota(quota) {
4938
+ if (quota === void 0 || quota === null) return void 0;
4939
+ const trimmed = String(quota).trim();
4940
+ return trimmed === "" ? void 0 : trimmed;
4941
+ }
4942
+ function assertQuotaNotBelowCount(quota, count) {
4943
+ if (quota === "0") return;
4944
+ const quotaNum = Number(quota);
4945
+ const countNum = Number(count);
4946
+ if (!Number.isFinite(quotaNum) || quotaNum < 0) {
4947
+ throw new Error(`Invalid quota "${quota}". Quota must be a non-negative integer string ("0" = unlimited).`);
4948
+ }
4949
+ if (Number.isFinite(countNum) && quotaNum < countNum) {
4950
+ throw new Error(`Quota ${quota} is below the current submitted count ${count} (ErrCollectionQuotaBelowCount). Quota must be 0 (unlimited) or >= ${count}.`);
4951
+ }
4952
+ }
4953
+ function assertNonEmptyCollection(state, collectionId) {
4954
+ if (!state || !String(state.collectionId || "").trim()) {
4955
+ throw new Error(
4956
+ `Collection read-back returned empty state for collectionId "${collectionId}". Broadcast may have succeeded but chain state is not yet readable \u2014 retry via refresh.`
4957
+ );
4958
+ }
4959
+ }
4960
+ registerAction({
4961
+ type: COLLECTION_LIFECYCLE_ACTION_TYPE,
4962
+ can: "collection/lifecycle",
4963
+ sideEffect: true,
4964
+ defaultRequiresConfirmation: true,
4965
+ requiredCapability: "flow/block/execute",
4966
+ outputSchema: COLLECTION_LIFECYCLE_OUTPUT_SCHEMA,
4967
+ getDynamicOutputSchema: () => COLLECTION_LIFECYCLE_OUTPUT_SCHEMA,
4968
+ // Static vocabulary (used by the pending-invocation preview / compiler).
4969
+ events: [COLLECTION_CREATED_EVENT],
4970
+ // Only a CREATE entry point (no bound collectionId) can emit `created`, so a
4971
+ // manage-mode block bound to an existing collection is hidden from the
4972
+ // trigger picker as a source (IXO-2595).
4973
+ getDynamicEvents: (inputs) => String(inputs?.collectionId || "").trim() ? [] : [COLLECTION_CREATED_EVENT],
4974
+ run: async (inputs, ctx) => {
4975
+ const service = ctx.services.collection;
4976
+ if (!service) {
4977
+ throw new Error("collection service not configured (ctx.services.collection is undefined)");
4978
+ }
4979
+ const operation = inputs.operation;
4980
+ if (!operation) {
4981
+ throw new Error("operation is required (create | updateState | updateDates | updateQuota | updatePayments | updateIntents | refresh)");
4982
+ }
4983
+ if (operation === "create") {
4984
+ const entity = String(inputs.entity || "").trim();
4985
+ const protocol = String(inputs.protocol || "").trim();
4986
+ if (!entity) throw new Error("create: entity is required");
4987
+ if (!protocol) throw new Error("create: protocol is required");
4988
+ if (!protocol.startsWith("did:") || protocol.includes("#")) {
4989
+ throw new Error(
4990
+ `create: protocol "${protocol}" is not a valid DID. The selected claim protocol did not resolve to a ledgered did:ixo: identifier (it may be an unresolved template reference). Re-pick the protocol from the entity's linked claims.`
4991
+ );
4992
+ }
4993
+ const quota = normalizeQuota(inputs.quota);
4994
+ const createParams = {
4995
+ entity,
4996
+ protocol,
4997
+ state: inputs.state,
4998
+ startDate: inputs.startDate,
4999
+ endDate: inputs.endDate,
5000
+ quota,
5001
+ payments: inputs.payments,
5002
+ intents: inputs.intents
5003
+ };
5004
+ const result = await service.create(createParams);
5005
+ const transactionHash2 = String(result?.transactionHash || "").trim();
5006
+ const collectionId2 = String(result?.collectionId || "").trim();
5007
+ if (!transactionHash2) {
5008
+ throw new Error("create: service returned no transactionHash. Collection was not created.");
5009
+ }
5010
+ if (!collectionId2) {
5011
+ throw new Error("create: service returned no collectionId. Cannot read back collection state.");
5012
+ }
5013
+ const state = await service.get({ collectionId: collectionId2 });
5014
+ assertNonEmptyCollection(state, collectionId2);
5015
+ return {
5016
+ output: state,
5017
+ events: [
5018
+ {
5019
+ name: COLLECTION_CREATED_EVENT_NAME,
5020
+ payload: {
5021
+ collectionId: String(state.collectionId || collectionId2),
5022
+ entity: String(state.entity || entity),
5023
+ protocol: String(state.protocol || protocol),
5024
+ transactionHash: transactionHash2
5025
+ }
5026
+ }
5027
+ ]
5028
+ };
5029
+ }
5030
+ if (operation === "refresh") {
5031
+ const collectionId2 = String(inputs.collectionId || "").trim();
5032
+ if (!collectionId2) throw new Error("refresh: collectionId is required");
5033
+ const state = await service.get({ collectionId: collectionId2 });
5034
+ assertNonEmptyCollection(state, collectionId2);
5035
+ return { output: state };
5036
+ }
5037
+ const writeOp = operation;
5038
+ const collectionId = String(inputs.collectionId || "").trim();
5039
+ if (!collectionId) throw new Error(`${writeOp}: collectionId is required`);
5040
+ const current = await service.get({ collectionId });
5041
+ assertNonEmptyCollection(current, collectionId);
5042
+ const adminAddress = String(current.admin || "").trim();
5043
+ if (!adminAddress) {
5044
+ throw new Error(`${writeOp}: could not resolve admin address for collection "${collectionId}" (chain state has no admin). Cannot authorise the update.`);
5045
+ }
5046
+ let transactionHash = "";
5047
+ switch (writeOp) {
5048
+ case "updateState": {
5049
+ const state = inputs.state;
5050
+ if (state === void 0 || state === null) {
5051
+ throw new Error("updateState: state is required (0=OPEN, 1=PAUSED, 2=CLOSED)");
5052
+ }
5053
+ if (!(state in CollectionStateEnum) || typeof state !== "number") {
5054
+ throw new Error(`updateState: invalid state "${String(state)}". Expected 0 (OPEN), 1 (PAUSED) or 2 (CLOSED).`);
5055
+ }
5056
+ const res = await service.updateState({ collectionId, state, adminAddress });
5057
+ transactionHash = String(res?.transactionHash || "").trim();
5058
+ break;
5059
+ }
5060
+ case "updateDates": {
5061
+ const startDate = inputs.startDate;
5062
+ const endDate = inputs.endDate;
5063
+ if (!startDate && !endDate) {
5064
+ throw new Error("updateDates: at least one of startDate or endDate is required");
5065
+ }
5066
+ const res = await service.updateDates({ collectionId, startDate, endDate, adminAddress });
5067
+ transactionHash = String(res?.transactionHash || "").trim();
5068
+ break;
5069
+ }
5070
+ case "updateQuota": {
5071
+ const quota = normalizeQuota(inputs.quota);
5072
+ if (quota === void 0) {
5073
+ throw new Error('updateQuota: quota is required ("0" = unlimited)');
5074
+ }
5075
+ assertQuotaNotBelowCount(quota, String(current.count || "0"));
5076
+ const res = await service.updateQuota({ collectionId, quota, adminAddress });
5077
+ transactionHash = String(res?.transactionHash || "").trim();
5078
+ break;
5079
+ }
5080
+ case "updatePayments": {
5081
+ const payments = inputs.payments;
5082
+ if (!payments || typeof payments !== "object") {
5083
+ throw new Error("updatePayments: payments is required");
5084
+ }
5085
+ const res = await service.updatePayments({ collectionId, payments, adminAddress });
5086
+ transactionHash = String(res?.transactionHash || "").trim();
5087
+ break;
5088
+ }
5089
+ case "updateIntents": {
5090
+ const intents = inputs.intents;
5091
+ if (!intents || typeof intents !== "object") {
5092
+ throw new Error("updateIntents: intents is required");
5093
+ }
5094
+ const res = await service.updateIntents({ collectionId, intents, adminAddress });
5095
+ transactionHash = String(res?.transactionHash || "").trim();
5096
+ break;
5097
+ }
5098
+ default: {
5099
+ const _exhaustive = writeOp;
5100
+ throw new Error(`Unsupported collection operation: ${String(_exhaustive)}`);
5101
+ }
5102
+ }
5103
+ if (!transactionHash) {
5104
+ throw new Error(`${writeOp}: service returned no transactionHash. The update was not broadcast.`);
5105
+ }
5106
+ const updated = await service.get({ collectionId });
5107
+ assertNonEmptyCollection(updated, collectionId);
5108
+ return { output: updated };
5109
+ }
5110
+ });
5111
+
5112
+ // src/core/lib/actionRegistry/actions/collectionUsers/index.ts
5113
+ var COLLECTION_USERS_ACTION_TYPE = "qi/collection.users";
5114
+ var COLLECTION_USERS_OUTPUT_SCHEMA = [
5115
+ { path: "transactionHash", displayName: "Tx Hash", type: "string", description: "Broadcast transaction hash (add/revoke)" },
5116
+ { path: "grantedCount", displayName: "Granted Count", type: "number", description: "Number of grants broadcast (fan-out)" },
5117
+ { path: "role", displayName: "Role", type: "string", description: "submit or evaluate" },
5118
+ { path: "collectionId", displayName: "Collection ID", type: "string", description: "Target claim collection identifier" },
5119
+ { path: "granteeAddress", displayName: "Grantee Address", type: "string", description: "Address granted/revoked" },
5120
+ {
5121
+ path: "grantees",
5122
+ displayName: "Grantees",
5123
+ type: "array",
5124
+ description: "Grantees holding a constraint for the collection (list)",
5125
+ itemSchema: [
5126
+ { path: "address", displayName: "Address", type: "string" },
5127
+ { path: "role", displayName: "Role", type: "string" },
5128
+ { path: "agentQuota", displayName: "Agent Quota", type: "string" },
5129
+ { path: "intentDurationNs", displayName: "Intent Duration (ns)", type: "string" }
5130
+ ]
5131
+ }
5132
+ ];
5133
+
5134
+ // src/core/lib/actionRegistry/actions/collectionUsers/collectionUsers.ts
5135
+ function normalizeRole(value) {
5136
+ const normalized = String(value || "").trim().toLowerCase();
5137
+ if (normalized === "submit" || normalized === "evaluate") return normalized;
5138
+ throw new Error('role must be either "submit" or "evaluate"');
5139
+ }
5140
+ registerAction({
5141
+ type: COLLECTION_USERS_ACTION_TYPE,
5142
+ can: "collection/users",
5143
+ sideEffect: true,
5144
+ defaultRequiresConfirmation: true,
5145
+ requiredCapability: "flow/block/execute",
5146
+ outputSchema: COLLECTION_USERS_OUTPUT_SCHEMA,
5147
+ getDynamicOutputSchema: () => COLLECTION_USERS_OUTPUT_SCHEMA,
5148
+ // Can be wired to a `block.event` trigger (IXO-2596) — e.g. listen for the
5149
+ // `created` event from a Claim Collection block and manage the new
5150
+ // collection's users. When invoked from a pending invocation, `collectionId`
5151
+ // arrives via the event payload (merged into inputs by name); the FlowDetail
5152
+ // resolves the entity admin account from the payload `entity` and passes it
5153
+ // as `adminAddress`.
5154
+ eligibleForEventTrigger: true,
5155
+ run: async (inputs, ctx) => {
5156
+ const service = ctx.services.collectionUsers;
5157
+ if (!service) {
5158
+ throw new Error("collectionUsers service not configured (ctx.services.collectionUsers is undefined)");
5159
+ }
5160
+ const operation = inputs.operation;
5161
+ if (!operation) {
5162
+ throw new Error("operation is required (add | revoke | list)");
5163
+ }
5164
+ const collectionId = String(inputs.collectionId || "").trim();
5165
+ const adminAddress = String(inputs.adminAddress || "").trim();
5166
+ if (operation === "list") {
5167
+ if (!collectionId) throw new Error("list: collectionId is required");
5168
+ if (!adminAddress) throw new Error("list: adminAddress (entity admin account) is required");
5169
+ const result2 = await service.list({ granterAdminAddress: adminAddress, collectionId });
5170
+ const grantees = Array.isArray(result2?.grantees) ? result2.grantees : void 0;
5171
+ if (!grantees) {
5172
+ throw new Error("list: service returned no grantees array. Check the [collection:list] handler logs.");
5173
+ }
5174
+ return { output: { grantees, collectionId } };
5175
+ }
5176
+ if (!collectionId) throw new Error(`${operation}: collectionId is required`);
5177
+ if (!adminAddress) throw new Error(`${operation}: adminAddress (entity admin account) is required`);
5178
+ const role = normalizeRole(inputs.role);
5179
+ const deedDid = String(inputs.deedDid || "").trim() || void 0;
5180
+ if (operation === "revoke") {
5181
+ const granteeAddress2 = String(inputs.granteeAddress || "").trim();
5182
+ if (!granteeAddress2) throw new Error("revoke: granteeAddress is required");
5183
+ const result2 = await service.revoke({ granterAdminAddress: adminAddress, granteeAddress: granteeAddress2, collectionId, role });
5184
+ const transactionHash2 = String(result2?.transactionHash || "").trim();
5185
+ if (!transactionHash2) {
5186
+ throw new Error("revoke: service returned no transactionHash. The revoke was not broadcast.");
5187
+ }
5188
+ return { output: { transactionHash: transactionHash2, role, collectionId, granteeAddress: granteeAddress2 } };
5189
+ }
5190
+ const granteeKind = inputs.granteeKind || "user";
5191
+ const agentQuota = inputs.agentQuota !== void 0 && inputs.agentQuota !== null ? String(inputs.agentQuota).trim() || void 0 : void 0;
5192
+ const maxAmount = Array.isArray(inputs.maxAmount) ? inputs.maxAmount : void 0;
5193
+ const intentDurationNs = String(inputs.intentDurationNs || "").trim() || void 0;
5194
+ if (granteeKind === "group-members") {
5195
+ const members = Array.isArray(inputs.members) ? inputs.members.filter((m) => !!String(m?.address || "").trim()) : [];
5196
+ if (members.length === 0) {
5197
+ throw new Error("add (group-members): no members resolved to grant to. Enumerate the group members before signing.");
5198
+ }
5199
+ const transactionHashes = [];
5200
+ for (const member of members) {
5201
+ const granteeAddress2 = String(member.address).trim();
5202
+ const res = await service.grant({ granterAdminAddress: adminAddress, granteeAddress: granteeAddress2, collectionId, role, agentQuota, maxAmount, intentDurationNs, deedDid });
5203
+ const hash = String(res?.transactionHash || "").trim();
5204
+ if (!hash) {
5205
+ throw new Error(`add (group-members): grant to ${granteeAddress2} returned no transactionHash. ${transactionHashes.length} of ${members.length} grants completed.`);
5206
+ }
5207
+ transactionHashes.push(hash);
5208
+ }
5209
+ return {
5210
+ output: {
5211
+ transactionHash: transactionHashes[transactionHashes.length - 1],
5212
+ transactionHashes,
5213
+ grantedCount: transactionHashes.length,
5214
+ role,
5215
+ collectionId
5216
+ }
5217
+ };
5218
+ }
5219
+ const granteeAddress = String(inputs.granteeAddress || "").trim();
5220
+ if (!granteeAddress) throw new Error("add: granteeAddress is required");
5221
+ const result = await service.grant({ granterAdminAddress: adminAddress, granteeAddress, collectionId, role, agentQuota, maxAmount, intentDurationNs, deedDid });
5222
+ const transactionHash = String(result?.transactionHash || "").trim();
5223
+ if (!transactionHash) {
5224
+ throw new Error("add: service returned no transactionHash. The grant was not broadcast.");
5225
+ }
5226
+ return {
5227
+ output: {
5228
+ transactionHash,
5229
+ transactionHashes: [transactionHash],
5230
+ grantedCount: 1,
5231
+ role,
5232
+ collectionId,
5233
+ granteeAddress
5234
+ }
5235
+ };
5236
+ }
5237
+ });
5238
+
4869
5239
  // src/core/lib/actionRegistry/actions/calendar/eventCreate.types.ts
4870
5240
  var EMPTY = {
4871
5241
  connection: null,
@@ -5494,7 +5864,7 @@ registerDiffResolver("bid", {
5494
5864
  if (!inputs.surveyStarted) return [];
5495
5865
  const collectionId = String(inputs.collectionId || "").trim();
5496
5866
  const role = String(inputs.role || "").trim();
5497
- const roleLabel = role === "evaluation_agent" || role === "ea" ? "Evaluator" : role ? "Contributor" : "Selected at runtime";
5867
+ const roleLabel2 = role === "evaluation_agent" || role === "ea" ? "Evaluator" : role ? "Contributor" : "Selected at runtime";
5498
5868
  return [
5499
5869
  {
5500
5870
  key: "applicationStatus",
@@ -5508,7 +5878,7 @@ registerDiffResolver("bid", {
5508
5878
  key: "role",
5509
5879
  label: "Role",
5510
5880
  before: "None",
5511
- after: roleLabel,
5881
+ after: roleLabel2,
5512
5882
  changeType: role ? "replace" : "unchanged"
5513
5883
  },
5514
5884
  {
@@ -5545,7 +5915,7 @@ registerDiffResolver("evaluateBid", {
5545
5915
  const applicantDid = String(inputs.applicantDid || "").trim();
5546
5916
  const roleLower = role.toLowerCase();
5547
5917
  const isEvaluator = roleLower === "evaluation_agent" || roleLower === "ea";
5548
- const roleLabel = isEvaluator ? "Evaluator" : roleLower === "service_agent" || roleLower === "sa" ? "Contributor" : role || "Unknown";
5918
+ const roleLabel2 = isEvaluator ? "Evaluator" : roleLower === "service_agent" || roleLower === "sa" ? "Contributor" : role || "Unknown";
5549
5919
  const isApprove = decision === "approve";
5550
5920
  const isReject = decision === "reject";
5551
5921
  const decisionLabel = isApprove ? "Approve" : isReject ? "Reject" : "Not selected";
@@ -5569,8 +5939,8 @@ registerDiffResolver("evaluateBid", {
5569
5939
  {
5570
5940
  key: "applicantRole",
5571
5941
  label: "Applicant Role",
5572
- before: roleLabel,
5573
- after: roleLabel,
5942
+ before: roleLabel2,
5943
+ after: roleLabel2,
5574
5944
  changeType: "unchanged"
5575
5945
  },
5576
5946
  {
@@ -6178,6 +6548,367 @@ registerDiffResolver("qi/wallet.fund", {
6178
6548
  }
6179
6549
  });
6180
6550
 
6551
+ // src/core/lib/actionRegistry/actions/collection/collection.diff.ts
6552
+ var STATE_LABELS = {
6553
+ [0 /* OPEN */]: "Open",
6554
+ [1 /* PAUSED */]: "Paused",
6555
+ [2 /* CLOSED */]: "Closed"
6556
+ };
6557
+ function stateLabel(value) {
6558
+ if (value === void 0 || value === null || value === "") return null;
6559
+ const n = typeof value === "number" ? value : Number(value);
6560
+ if (!Number.isFinite(n)) return null;
6561
+ return STATE_LABELS[n] ?? `Unknown (${n})`;
6562
+ }
6563
+ function readCurrentState(inputs) {
6564
+ const candidate = inputs?.currentState ?? inputs?.__currentState ?? inputs?.__currentOutput ?? inputs?.currentOutput ?? inputs?.output ?? void 0;
6565
+ if (candidate && typeof candidate === "object") return candidate;
6566
+ return {};
6567
+ }
6568
+ function formatQuota(value) {
6569
+ if (value === void 0 || value === null || value === "") return "Unlimited";
6570
+ const s = String(value).trim();
6571
+ if (s === "" || s === "0") return "Unlimited";
6572
+ return s;
6573
+ }
6574
+ function toNumberOrNull(value) {
6575
+ if (value === void 0 || value === null || value === "") return null;
6576
+ const n = Number(value);
6577
+ return Number.isFinite(n) ? n : null;
6578
+ }
6579
+ function formatDate(value) {
6580
+ if (value === void 0 || value === null || value === "") return "Not set";
6581
+ return String(value);
6582
+ }
6583
+ var USDC_IBC_DENOM = "ibc/6BBE9BD4246F8E04948D5A4EEE7164B2630263B9EBB5E7DC5F0A46C62A2FF97B";
6584
+ function formatCoin3(amount, denom) {
6585
+ const rawAmount = amount ?? "?";
6586
+ if (denom === "uixo") {
6587
+ const n = Number(rawAmount);
6588
+ return `${Number.isFinite(n) ? n / 1e6 : rawAmount} IXO`;
6589
+ }
6590
+ if (denom === USDC_IBC_DENOM || (denom ?? "").startsWith("ibc/")) {
6591
+ const n = Number(rawAmount);
6592
+ return `${Number.isFinite(n) ? n / 1e6 : rawAmount} USDC`;
6593
+ }
6594
+ return `${rawAmount} ${denom ?? ""}`.trim();
6595
+ }
6596
+ function summarisePaymentLeg(leg) {
6597
+ if (!leg || typeof leg !== "object") return "None";
6598
+ const parts = [];
6599
+ const coins = Array.isArray(leg.amount) ? leg.amount : [];
6600
+ if (coins.length > 0) {
6601
+ parts.push(coins.map((c) => formatCoin3(c?.amount, c?.denom)).join(", "));
6602
+ }
6603
+ if (Array.isArray(leg.cw20Payment) && leg.cw20Payment.length > 0) {
6604
+ parts.push(`${leg.cw20Payment.length} CW20`);
6605
+ }
6606
+ if (leg.contract_1155Payment) {
6607
+ parts.push("1155");
6608
+ }
6609
+ if (leg.account) {
6610
+ parts.push(`\u2192 ${leg.account}`);
6611
+ }
6612
+ if (leg.isOraclePayment) {
6613
+ parts.push("(oracle)");
6614
+ }
6615
+ return parts.length > 0 ? parts.join(" ") : "None";
6616
+ }
6617
+ function summarisePayments(payments) {
6618
+ const p = payments && typeof payments === "object" ? payments : {};
6619
+ return {
6620
+ submission: summarisePaymentLeg(p.submission),
6621
+ evaluation: summarisePaymentLeg(p.evaluation),
6622
+ approval: summarisePaymentLeg(p.approval),
6623
+ rejection: summarisePaymentLeg(p.rejection)
6624
+ };
6625
+ }
6626
+ function summariseIntents(intents) {
6627
+ const i = intents && typeof intents === "object" ? intents : {};
6628
+ return {
6629
+ allowed: i.allowed === void 0 ? "Not set" : i.allowed ? "Allowed" : "Disallowed",
6630
+ timeout: i.timeoutNs ? String(i.timeoutNs) : "Not set",
6631
+ payment: summarisePaymentLeg(i.payment)
6632
+ };
6633
+ }
6634
+ function changeFor(before, after) {
6635
+ if (before === after) return "unchanged";
6636
+ if (before === null || before === void 0 || before === "") return "add";
6637
+ if (after === null || after === void 0 || after === "") return "remove";
6638
+ if (typeof before === "number" && typeof after === "number") {
6639
+ if (after > before) return "increase";
6640
+ if (after < before) return "decrease";
6641
+ }
6642
+ return "replace";
6643
+ }
6644
+ function diffCreate(inputs) {
6645
+ const results = [];
6646
+ if (inputs.entity) {
6647
+ results.push({ key: "entity", label: "Entity", before: null, after: String(inputs.entity), changeType: "add" });
6648
+ }
6649
+ if (inputs.protocol) {
6650
+ results.push({ key: "protocol", label: "Protocol", before: null, after: String(inputs.protocol), changeType: "add" });
6651
+ }
6652
+ results.push({
6653
+ key: "state",
6654
+ label: "State",
6655
+ before: null,
6656
+ after: stateLabel(inputs.state) ?? STATE_LABELS[0 /* OPEN */],
6657
+ changeType: "add"
6658
+ });
6659
+ results.push({
6660
+ key: "startDate",
6661
+ label: "Start Date",
6662
+ before: null,
6663
+ after: inputs.startDate ? String(inputs.startDate) : "Not set",
6664
+ changeType: inputs.startDate ? "add" : "unchanged"
6665
+ });
6666
+ results.push({
6667
+ key: "endDate",
6668
+ label: "End Date",
6669
+ before: null,
6670
+ after: inputs.endDate ? String(inputs.endDate) : "Not set",
6671
+ changeType: inputs.endDate ? "add" : "unchanged"
6672
+ });
6673
+ results.push({
6674
+ key: "quota",
6675
+ label: "Quota",
6676
+ before: null,
6677
+ after: formatQuota(inputs.quota),
6678
+ changeType: "add",
6679
+ severity: "warning",
6680
+ unit: formatQuota(inputs.quota) === "Unlimited" ? void 0 : "claims"
6681
+ });
6682
+ if (inputs.payments) {
6683
+ const after = summarisePayments(inputs.payments);
6684
+ ["submission", "evaluation", "approval", "rejection"].forEach((leg) => {
6685
+ if (after[leg] !== "None") {
6686
+ results.push({
6687
+ key: `payments.${leg}`,
6688
+ label: `Payment \u2014 ${leg.charAt(0).toUpperCase()}${leg.slice(1)}`,
6689
+ before: null,
6690
+ after: after[leg],
6691
+ changeType: "add"
6692
+ });
6693
+ }
6694
+ });
6695
+ }
6696
+ if (inputs.intents) {
6697
+ const after = summariseIntents(inputs.intents);
6698
+ results.push({ key: "intents.allowed", label: "Intents \u2014 Allowed", before: null, after: after.allowed, changeType: "add" });
6699
+ if (after.timeout !== "Not set") {
6700
+ results.push({ key: "intents.timeout", label: "Intents \u2014 Timeout (ns)", before: null, after: after.timeout, changeType: "add" });
6701
+ }
6702
+ if (after.payment !== "None") {
6703
+ results.push({ key: "intents.payment", label: "Intents \u2014 Payment", before: null, after: after.payment, changeType: "add" });
6704
+ }
6705
+ }
6706
+ return results;
6707
+ }
6708
+ function diffUpdateState(inputs, current) {
6709
+ const before = stateLabel(current.state);
6710
+ const after = stateLabel(inputs.state);
6711
+ return [
6712
+ {
6713
+ key: "state",
6714
+ label: "State",
6715
+ before: before ?? "Unknown",
6716
+ after: after ?? "Unchanged",
6717
+ changeType: changeFor(before, after),
6718
+ severity: after === STATE_LABELS[2 /* CLOSED */] ? "warning" : "info"
6719
+ }
6720
+ ];
6721
+ }
6722
+ function diffUpdateDates(inputs, current) {
6723
+ const results = [];
6724
+ const beforeStart = formatDate(current.startDate);
6725
+ const afterStart = inputs.startDate !== void 0 ? formatDate(inputs.startDate) : beforeStart;
6726
+ results.push({
6727
+ key: "startDate",
6728
+ label: "Start Date",
6729
+ before: beforeStart,
6730
+ after: afterStart,
6731
+ changeType: changeFor(beforeStart === "Not set" ? null : beforeStart, afterStart === "Not set" ? null : afterStart)
6732
+ });
6733
+ const beforeEnd = formatDate(current.endDate);
6734
+ const afterEnd = inputs.endDate !== void 0 ? formatDate(inputs.endDate) : beforeEnd;
6735
+ results.push({
6736
+ key: "endDate",
6737
+ label: "End Date",
6738
+ before: beforeEnd,
6739
+ after: afterEnd,
6740
+ changeType: changeFor(beforeEnd === "Not set" ? null : beforeEnd, afterEnd === "Not set" ? null : afterEnd)
6741
+ });
6742
+ return results;
6743
+ }
6744
+ function diffUpdateQuota(inputs, current) {
6745
+ const beforeQuotaStr = formatQuota(current.quota);
6746
+ const afterQuotaStr = formatQuota(inputs.quota);
6747
+ const beforeNum = beforeQuotaStr === "Unlimited" ? null : toNumberOrNull(current.quota);
6748
+ const afterNum = afterQuotaStr === "Unlimited" ? null : toNumberOrNull(inputs.quota);
6749
+ let changeType;
6750
+ if (beforeQuotaStr === afterQuotaStr) {
6751
+ changeType = "unchanged";
6752
+ } else if (beforeNum !== null && afterNum !== null) {
6753
+ changeType = afterNum > beforeNum ? "increase" : afterNum < beforeNum ? "decrease" : "replace";
6754
+ } else {
6755
+ changeType = "replace";
6756
+ }
6757
+ const count = toNumberOrNull(current.count);
6758
+ const belowCount = afterNum !== null && count !== null && afterNum < count;
6759
+ return [
6760
+ {
6761
+ key: "quota",
6762
+ label: "Quota",
6763
+ before: beforeQuotaStr,
6764
+ after: belowCount ? `${afterQuotaStr} (below current count ${count} \u2014 chain will reject)` : afterQuotaStr,
6765
+ changeType,
6766
+ severity: belowCount ? "critical" : "info",
6767
+ unit: afterQuotaStr === "Unlimited" ? void 0 : "claims"
6768
+ }
6769
+ ];
6770
+ }
6771
+ function diffUpdatePayments(inputs, current) {
6772
+ const before = summarisePayments(current.payments);
6773
+ const after = summarisePayments(inputs.payments);
6774
+ return ["submission", "evaluation", "approval", "rejection"].map((leg) => ({
6775
+ key: `payments.${leg}`,
6776
+ label: `Payment \u2014 ${leg.charAt(0).toUpperCase()}${leg.slice(1)}`,
6777
+ before: before[leg],
6778
+ after: after[leg],
6779
+ changeType: changeFor(before[leg] === "None" ? null : before[leg], after[leg] === "None" ? null : after[leg])
6780
+ }));
6781
+ }
6782
+ function diffUpdateIntents(inputs, current) {
6783
+ const before = summariseIntents(current.intents);
6784
+ const after = summariseIntents(inputs.intents);
6785
+ return [
6786
+ {
6787
+ key: "intents.allowed",
6788
+ label: "Intents \u2014 Allowed",
6789
+ before: before.allowed,
6790
+ after: after.allowed,
6791
+ changeType: changeFor(before.allowed === "Not set" ? null : before.allowed, after.allowed === "Not set" ? null : after.allowed)
6792
+ },
6793
+ {
6794
+ key: "intents.timeout",
6795
+ label: "Intents \u2014 Timeout (ns)",
6796
+ before: before.timeout,
6797
+ after: after.timeout,
6798
+ changeType: changeFor(before.timeout === "Not set" ? null : before.timeout, after.timeout === "Not set" ? null : after.timeout)
6799
+ },
6800
+ {
6801
+ key: "intents.payment",
6802
+ label: "Intents \u2014 Payment",
6803
+ before: before.payment,
6804
+ after: after.payment,
6805
+ changeType: changeFor(before.payment === "None" ? null : before.payment, after.payment === "None" ? null : after.payment)
6806
+ }
6807
+ ];
6808
+ }
6809
+ registerDiffResolver(COLLECTION_LIFECYCLE_ACTION_TYPE, {
6810
+ resolver: async (inputs, _ctx) => {
6811
+ const safeInputs = inputs && typeof inputs === "object" ? inputs : {};
6812
+ const operation = String(safeInputs.operation || "").trim();
6813
+ const current = readCurrentState(safeInputs);
6814
+ switch (operation) {
6815
+ case "create":
6816
+ return diffCreate(safeInputs);
6817
+ case "updateState":
6818
+ return diffUpdateState(safeInputs, current);
6819
+ case "updateDates":
6820
+ return diffUpdateDates(safeInputs, current);
6821
+ case "updateQuota":
6822
+ return diffUpdateQuota(safeInputs, current);
6823
+ case "updatePayments":
6824
+ return diffUpdatePayments(safeInputs, current);
6825
+ case "updateIntents":
6826
+ return diffUpdateIntents(safeInputs, current);
6827
+ case "refresh":
6828
+ return [];
6829
+ default:
6830
+ return [];
6831
+ }
6832
+ }
6833
+ });
6834
+
6835
+ // src/core/lib/actionRegistry/actions/collectionUsers/collectionUsers.diff.ts
6836
+ function formatQuota2(value) {
6837
+ if (value === void 0 || value === null) return "\u2014";
6838
+ const s = String(value).trim();
6839
+ if (s === "") return "\u2014";
6840
+ return s;
6841
+ }
6842
+ function roleLabel(value) {
6843
+ const r = String(value || "").trim().toLowerCase();
6844
+ if (r === "submit") return "Submit (Contributor)";
6845
+ if (r === "evaluate") return "Evaluate (Evaluator)";
6846
+ return "Unknown role";
6847
+ }
6848
+ function diffAdd(inputs) {
6849
+ const results = [];
6850
+ const kind = String(inputs.granteeKind || "user");
6851
+ results.push({ key: "role", label: "Role", before: null, after: roleLabel(inputs.role), changeType: "add" });
6852
+ if (inputs.collectionId) {
6853
+ results.push({ key: "collectionId", label: "Collection", before: null, after: String(inputs.collectionId), changeType: "add" });
6854
+ }
6855
+ if (kind === "group-members") {
6856
+ const count = Array.isArray(inputs.members) ? inputs.members.filter((m) => !!String(m?.address || "").trim()).length : 0;
6857
+ results.push({
6858
+ key: "grantees",
6859
+ label: "Grantees (fan-out)",
6860
+ before: null,
6861
+ after: `${count} group member${count === 1 ? "" : "s"}`,
6862
+ changeType: "add",
6863
+ severity: "warning"
6864
+ });
6865
+ } else {
6866
+ const label = kind === "group-account" ? "Grantee (group account)" : "Grantee";
6867
+ results.push({ key: "grantee", label, before: null, after: String(inputs.granteeAddress || "\u2014"), changeType: "add" });
6868
+ }
6869
+ results.push({
6870
+ key: "agentQuota",
6871
+ label: "Agent Quota",
6872
+ before: null,
6873
+ after: formatQuota2(inputs.agentQuota),
6874
+ changeType: "add",
6875
+ unit: formatQuota2(inputs.agentQuota) === "\u2014" ? void 0 : "claims"
6876
+ });
6877
+ return results;
6878
+ }
6879
+ function diffRevoke(inputs) {
6880
+ const results = [];
6881
+ results.push({ key: "role", label: "Role", before: roleLabel(inputs.role), after: null, changeType: "remove", severity: "warning" });
6882
+ if (inputs.collectionId) {
6883
+ results.push({ key: "collectionId", label: "Collection", before: String(inputs.collectionId), after: null, changeType: "remove", severity: "warning" });
6884
+ }
6885
+ results.push({
6886
+ key: "grantee",
6887
+ label: "Grantee",
6888
+ before: String(inputs.granteeAddress || "\u2014"),
6889
+ after: null,
6890
+ changeType: "remove",
6891
+ severity: "warning"
6892
+ });
6893
+ return results;
6894
+ }
6895
+ registerDiffResolver(COLLECTION_USERS_ACTION_TYPE, {
6896
+ resolver: async (inputs, _ctx) => {
6897
+ const safeInputs = inputs && typeof inputs === "object" ? inputs : {};
6898
+ const operation = String(safeInputs.operation || "").trim();
6899
+ switch (operation) {
6900
+ case "add":
6901
+ return diffAdd(safeInputs);
6902
+ case "revoke":
6903
+ return diffRevoke(safeInputs);
6904
+ case "list":
6905
+ return [];
6906
+ default:
6907
+ return [];
6908
+ }
6909
+ }
6910
+ });
6911
+
6181
6912
  // src/core/services/ucanService.ts
6182
6913
  import {
6183
6914
  createDelegation as ucanCreateDelegation,
@@ -10799,4 +11530,4 @@ export {
10799
11530
  executeQueuedFlowAgentCoreCommands,
10800
11531
  FlowAgentService
10801
11532
  };
10802
- //# sourceMappingURL=chunk-UMS6GCME.mjs.map
11533
+ //# sourceMappingURL=chunk-RIDIYR53.mjs.map