@stndrds/schema 1.0.0-alpha.281 → 1.0.0-alpha.284

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/all-DanoPxKr.d.ts +879 -0
  2. package/dist/all-bG_ha0VV.d.mts +879 -0
  3. package/dist/{attributes-D8eHv5Kf.d.ts → attributes-CNYwg_Nr.d.ts} +14 -13
  4. package/dist/{attributes--M1ifW8_.d.mts → attributes-CWPLbp7c.d.mts} +14 -13
  5. package/dist/capabilities.d.mts +146 -0
  6. package/dist/capabilities.d.ts +146 -0
  7. package/dist/capabilities.js +77 -0
  8. package/dist/capabilities.mjs +70 -0
  9. package/dist/{chunk-A5PPZ2FM.mjs → chunk-5OBQRDRM.mjs} +7 -3
  10. package/dist/{chunk-ORPCS24B.mjs → chunk-AGRAFDGU.mjs} +72 -16
  11. package/dist/{chunk-LRFLSFIA.js → chunk-BOICAZHR.js} +9 -4
  12. package/dist/{chunk-E47WAI5K.js → chunk-I3EYILYO.js} +5 -5
  13. package/dist/{chunk-OYHBQMC7.js → chunk-K6ET4CXP.js} +3 -3
  14. package/dist/{chunk-MLTXSBOB.mjs → chunk-PNOWKRH2.mjs} +2 -2
  15. package/dist/{chunk-XCLVXM7F.mjs → chunk-R57T4UDX.mjs} +1 -1
  16. package/dist/{chunk-SYQDFZ74.mjs → chunk-RUO25ERR.mjs} +36 -0
  17. package/dist/{chunk-HWZRSXFB.js → chunk-V26R64A4.js} +36 -0
  18. package/dist/{chunk-TU6ECJFZ.js → chunk-YZ5RCMIQ.js} +112 -45
  19. package/dist/exceptions.d.mts +24 -3
  20. package/dist/exceptions.d.ts +24 -3
  21. package/dist/exceptions.js +39 -39
  22. package/dist/exceptions.mjs +1 -1
  23. package/dist/{helpers-DyoPqiSz.d.ts → helpers-CXkVwpsl.d.ts} +3 -3
  24. package/dist/{helpers-BiABdSxK.d.mts → helpers-Dul_r9rJ.d.mts} +3 -3
  25. package/dist/{index-DWoqObyG.d.mts → index-Ca-MzQuU.d.mts} +46 -6
  26. package/dist/{index-TMlrIKAY.d.ts → index-Ns6KGfrZ.d.ts} +46 -6
  27. package/dist/index.d.mts +1508 -357
  28. package/dist/index.d.ts +1508 -357
  29. package/dist/index.js +1396 -363
  30. package/dist/index.mjs +1072 -124
  31. package/dist/{migrations-B1kkIhIX.d.ts → migrations-DaFneOfx.d.ts} +1 -1
  32. package/dist/{migrations-BNlQVzDC.d.mts → migrations-fRvadl6i.d.mts} +1 -1
  33. package/dist/{objects-DmMqHn3L.d.mts → objects-CDwMSnqv.d.mts} +2 -4
  34. package/dist/{objects-DgFojgwH.d.ts → objects-DJv6WrDE.d.ts} +2 -4
  35. package/dist/{types-DHqXzkgW.d.mts → types-CVYiFc69.d.mts} +1 -1
  36. package/dist/{types-DYYFto8d.d.ts → types-NGEww_ln.d.ts} +1 -1
  37. package/dist/utils.js +8 -8
  38. package/dist/utils.mjs +2 -2
  39. package/dist/validation/all.d.mts +7 -7
  40. package/dist/validation/all.d.ts +7 -7
  41. package/dist/validation/all.js +46 -46
  42. package/dist/validation/all.mjs +5 -5
  43. package/dist/validation/complex/currency.d.mts +2 -2
  44. package/dist/validation/complex/currency.d.ts +2 -2
  45. package/dist/validation/complex/location.d.mts +2 -2
  46. package/dist/validation/complex/location.d.ts +2 -2
  47. package/dist/validation/complex/phone.d.mts +2 -2
  48. package/dist/validation/complex/phone.d.ts +2 -2
  49. package/dist/validation/complex/relation.d.mts +2 -2
  50. package/dist/validation/complex/relation.d.ts +2 -2
  51. package/dist/validation/complex/richtext.d.mts +2 -2
  52. package/dist/validation/complex/richtext.d.ts +2 -2
  53. package/dist/validation/complex/select.d.mts +2 -2
  54. package/dist/validation/complex/select.d.ts +2 -2
  55. package/dist/validation/complex/user.d.mts +2 -2
  56. package/dist/validation/complex/user.d.ts +2 -2
  57. package/dist/validation/computed/formula.d.mts +2 -2
  58. package/dist/validation/computed/formula.d.ts +2 -2
  59. package/dist/validation/computed/rollup.d.mts +2 -2
  60. package/dist/validation/computed/rollup.d.ts +2 -2
  61. package/dist/validation/config/index.d.mts +4 -4
  62. package/dist/validation/config/index.d.ts +4 -4
  63. package/dist/validation/config/index.js +15 -11
  64. package/dist/validation/config/index.mjs +2 -2
  65. package/dist/validation/core/index.d.mts +3 -3
  66. package/dist/validation/core/index.d.ts +3 -3
  67. package/dist/validation/object/index.d.mts +5 -5
  68. package/dist/validation/object/index.d.ts +5 -5
  69. package/dist/validation/object/index.js +15 -15
  70. package/dist/validation/object/index.mjs +3 -3
  71. package/dist/validation/primitives/checkbox.d.mts +2 -2
  72. package/dist/validation/primitives/checkbox.d.ts +2 -2
  73. package/dist/validation/primitives/date.d.mts +2 -2
  74. package/dist/validation/primitives/date.d.ts +2 -2
  75. package/dist/validation/primitives/number.d.mts +2 -2
  76. package/dist/validation/primitives/number.d.ts +2 -2
  77. package/dist/validation/primitives/text.d.mts +2 -2
  78. package/dist/validation/primitives/text.d.ts +2 -2
  79. package/package.json +10 -5
  80. package/dist/all-BVp3k9Hi.d.ts +0 -471
  81. package/dist/all-CnIU2anT.d.mts +0 -471
package/dist/index.mjs CHANGED
@@ -1,26 +1,26 @@
1
- import { canonicalStringify, generateId } from './chunk-XCLVXM7F.mjs';
2
- export { asTenantId, asUserId, canonicalStringify, deepEqual, generateId, indexBy } from './chunk-XCLVXM7F.mjs';
3
- import { SYSTEM_FILTER_ATTRIBUTE_TYPES, RESERVED_OBJECT_NAMES, listViewConfigSchema, detailViewConfigSchema, LIST_VIEW_TAB_VISIBILITIES, RESERVED_ATTRIBUTE_NAMES, isAttributeSortable, getAttributeCapabilities, resolveIsWithinBounds, normalizeForEdgeRpc, getOperatorPolarity, extractCurrencyFilterValue } from './chunk-ORPCS24B.mjs';
4
- export { ATTRIBUTE_FILTER_OPERATORS, LIST_VIEW_TAB_VISIBILITIES, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, REMOVED_OPERATOR_REPLACEMENTS, RESERVED_ATTRIBUTE_NAMES, RESERVED_OBJECT_NAMES, RESOURCE_VISIBILITIES, SYNONYM_ALIASES, SYSTEM_ATTRIBUTES, SYSTEM_ATTRIBUTE_I18N_KEYS, SYSTEM_FIELD_NAMES, SYSTEM_FILTER_ATTRIBUTE_TYPES, canonicalizeFilterValue, collectQualifiedRuleIssues, currentActor, detailTabSchema, detailViewConfigSchema, extractCurrencyFilterValue, extractFilterValue, getAttributeCapabilities, getAttributeFilterOperators, getOperatorPolarity, getRollupFilterOperators, getSystemAttributeI18nKey, getSystemAttributeList, inverseSourceSchema, isAttributeFilterable, isAttributeGroupable, isAttributeKanbanGroupable, isAttributeSearchable, isDynamicValue, isManagedSystemAttribute, isNoValueOperator, isRelativeDateValue, isSetMembershipOperator, listViewConfigSchema, listViewTabSchema, normalizeFilterRule, normalizeForEdgeRpc, normalizeOperator, now, parseResourceVisibility, parseViewConfig, relationSourceSchema, resolveEffectiveFilterType, resolveIsWithinBounds, resolveUtcDayBounds, tableSourceSchema, toMultiValueOperator, toUtcDayString, today, validateQualifiedRule, viewConfigByTypeSchema, viewTypeSchema } from './chunk-ORPCS24B.mjs';
5
- import { iconNameSchema, parseAttributeConfigForCreate, parseComputedFormula } from './chunk-A5PPZ2FM.mjs';
6
- export { ComputedFormulaParseError, SCHEMA_LIMITS, colorIdSchema, iconNameSchema, multiselectOptionWriteSchema, parseAttributeConfig, parseAttributeConfigForCreate, parseAttributeConfigForUpdate, parseComputedFormula, selectOptionWriteSchema, statusGroupSchema, statusOptionWriteSchema } from './chunk-A5PPZ2FM.mjs';
7
- import { createObjectValidator, createAttributeValidator, isNullishOrEmptyString } from './chunk-MLTXSBOB.mjs';
8
- export { createFormAttributeValidator, isNullishOrEmptyString, isValuePresent, rejectUnknownAttributesOrThrow, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from './chunk-MLTXSBOB.mjs';
1
+ import { canonicalStringify, generateId } from './chunk-R57T4UDX.mjs';
2
+ export { asTenantId, asUserId, canonicalStringify, deepEqual, generateId, indexBy } from './chunk-R57T4UDX.mjs';
3
+ import { RESERVED_ATTRIBUTE_NAMES, SYSTEM_FILTER_ATTRIBUTE_TYPES, RESERVED_OBJECT_NAMES, listViewConfigSchema, detailViewConfigSchema, detailTabDraftSchema, groupWriteSchema, fieldSlotSchema, sortsSchema, filterStateSchema, columnsSchema, tableSourceSchema, listViewTabSchema, LIST_VIEW_TAB_VISIBILITIES, filterGroupSchema, isAttributeSortable, getAttributeCapabilities, resolveIsWithinBounds, normalizeForEdgeRpc, getOperatorPolarity, extractCurrencyFilterValue, LIST_TAB_KANBAN_KEYS, LIST_TAB_TABLE_KEYS } from './chunk-AGRAFDGU.mjs';
4
+ export { ATTRIBUTE_FILTER_OPERATORS, LIST_TAB_KANBAN_KEYS, LIST_TAB_TABLE_KEYS, LIST_VIEW_TAB_VISIBILITIES, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, REMOVED_OPERATOR_REPLACEMENTS, RESERVED_ATTRIBUTE_NAMES, RESERVED_OBJECT_NAMES, RESOURCE_VISIBILITIES, SYNONYM_ALIASES, SYSTEM_ATTRIBUTES, SYSTEM_ATTRIBUTE_I18N_KEYS, SYSTEM_FIELD_NAMES, SYSTEM_FILTER_ATTRIBUTE_TYPES, canonicalizeFilterValue, collectQualifiedRuleIssues, columnsSchema, currentActor, detailTabDraftSchema, detailTabSchema, detailViewConfigSchema, extractCurrencyFilterValue, extractFilterValue, fieldSchema, fieldShape, fieldSlotSchema, filterGroupSchema, filterStateSchema, getAttributeCapabilities, getAttributeFilterOperators, getOperatorPolarity, getRollupFilterOperators, getSystemAttributeI18nKey, getSystemAttributeList, groupWriteSchema, inverseSourceSchema, isAttributeFilterable, isAttributeGroupable, isAttributeKanbanGroupable, isAttributeSearchable, isDynamicValue, isManagedSystemAttribute, isNoValueOperator, isRelativeDateValue, isSetMembershipOperator, listViewConfigSchema, listViewTabSchema, normalizeFilterRule, normalizeForEdgeRpc, normalizeOperator, now, parseResourceVisibility, parseViewConfig, relationSourceSchema, resolveEffectiveFilterType, resolveIsWithinBounds, resolveUtcDayBounds, sortsSchema, tableSourceSchema, toMultiValueOperator, toUtcDayString, today, validateQualifiedRule, viewConfigByTypeSchema, viewTypeSchema } from './chunk-AGRAFDGU.mjs';
5
+ import { createObjectValidator, createAttributeValidator, validateAttribute, isNullishOrEmptyString } from './chunk-PNOWKRH2.mjs';
6
+ export { createFormAttributeValidator, isNullishOrEmptyString, isValuePresent, rejectUnknownAttributesOrThrow, validateDraft, validateDraftOrThrow, validateObject, validateObjectOrThrow } from './chunk-PNOWKRH2.mjs';
7
+ import './chunk-GO6LQADH.mjs';
9
8
  import './chunk-QVLQPW3O.mjs';
10
9
  import './chunk-ZDQ5AP26.mjs';
11
10
  import './chunk-LV3FEUKU.mjs';
12
11
  import './chunk-UXAHLSWC.mjs';
13
12
  import './chunk-NS63SPNN.mjs';
13
+ import { iconNameSchema, parseAttributeConfigForCreate, parseComputedFormula, getAttributeConfigWriteSchema } from './chunk-5OBQRDRM.mjs';
14
+ export { ComputedFormulaParseError, SCHEMA_LIMITS, colorIdSchema, iconNameSchema, multiselectOptionWriteSchema, parseAttributeConfig, parseAttributeConfigForCreate, parseAttributeConfigForUpdate, parseComputedFormula, selectOptionWriteSchema, statusGroupSchema, statusOptionWriteSchema } from './chunk-5OBQRDRM.mjs';
14
15
  export { createCheckboxValidator } from './chunk-OSSGN43B.mjs';
15
16
  export { createDateValidator } from './chunk-Q44QKLN4.mjs';
16
17
  export { createNumberValidator } from './chunk-UANQJ2GH.mjs';
17
18
  export { TEXT_FORMAT_PATTERNS, createTextValidator, resolveTextPattern } from './chunk-O73ROMWQ.mjs';
18
- import { SchemaError, SchemaErrorCode, ValidationError, DuplicateError, NotFoundError } from './chunk-SYQDFZ74.mjs';
19
- export { AccessDeniedError, AttributeInUseError, AttributeNotFoundError, ChangeTypeNotSupportedError, ConcurrentModificationError, DestructiveSyncNotAllowedError, DuplicateError, ForbiddenError, MemoryNotFoundError, MigrationTimeoutError, NotFoundError, NotImplementedError, ObjectNotFoundError, ObjectReferencedError, OrphanSystemAttributeError, ProtectedResourceError, ProtectedRoleError, RecordNotFoundError, RecordReferencedError, RepositoryError, RoleNotFoundError, SchemaError, SchemaErrorCode, SchemaPlanNotFoundError, SearchBackendError, StorageError, SyncCascadeError, SyncConflictError, SyncError, SystemEntityImmutableError, ValidationError, isAttributeInUseError, isNotFoundError, isObjectReferencedError, isProtectedResourceError, isRecordReferencedError, isSchemaError, isValidationError } from './chunk-SYQDFZ74.mjs';
19
+ import { ValidationError, SchemaError, SchemaErrorCode, DuplicateError, NotFoundError } from './chunk-RUO25ERR.mjs';
20
+ export { AccessDeniedError, AttributeInUseError, AttributeNotFoundError, ChangeTypeNotSupportedError, ConcurrentModificationError, DestructiveSyncNotAllowedError, DuplicateError, ForbiddenError, MemoryNotFoundError, MigrationTimeoutError, NotFoundError, NotImplementedError, ObjectNotFoundError, ObjectReferencedError, OrphanSystemAttributeError, ProtectedResourceError, ProtectedRoleError, RecordNotFoundError, RecordReferencedError, RepositoryError, RoleNotFoundError, SchemaError, SchemaErrorCode, SchemaPlanNotFoundError, SearchBackendError, StorageError, SyncCascadeError, SyncConflictError, SyncError, SystemEntityImmutableError, ValidationError, isAttributeInUseError, isNotFoundError, isObjectReferencedError, isProtectedResourceError, isRecordReferencedError, isSchemaError, isValidationError } from './chunk-RUO25ERR.mjs';
20
21
  import './chunk-AYVHMVKQ.mjs';
21
22
  import './chunk-YUFTHPOE.mjs';
22
23
  import { formatPhoneForDisplay, normalizeCountrylessPhoneNumber, normalizePhoneNumber } from './chunk-R5LAJCBU.mjs';
23
- import './chunk-GO6LQADH.mjs';
24
24
  export { DEFAULT_VALIDATION_MESSAGES, formatZodErrors } from './chunk-HRQEZUAA.mjs';
25
25
  import { ICONS, SKILL_NAME_MAX_LENGTH, SKILL_DESCRIPTION_MAX_LENGTH, MEMORY_NAME_MAX_LENGTH, MEMORY_DESCRIPTION_MAX_LENGTH, getCountryDisplayNameByIso3 } from '@stndrds/constants';
26
26
  import z2, { z } from 'zod';
@@ -69,6 +69,24 @@ var BEHAVIOR_PROPERTIES = [
69
69
  var PRESENTATION_PROPERTIES = ["label", "description", "placeholder", "icon"];
70
70
 
71
71
  // src/types/attributes.ts
72
+ var ATTRIBUTE_TYPES = [
73
+ "text",
74
+ "richtext",
75
+ "number",
76
+ "checkbox",
77
+ "date",
78
+ "phone",
79
+ "currency",
80
+ "status",
81
+ "location",
82
+ "select",
83
+ "multiselect",
84
+ "user",
85
+ "relation",
86
+ "formula",
87
+ "rollup",
88
+ "document"
89
+ ];
72
90
  var RELATION_TARGET_ANY = "*";
73
91
  function isUniversalRelation(attr) {
74
92
  return attr.targets.length === 1 && attr.targets[0].object === RELATION_TARGET_ANY;
@@ -205,6 +223,25 @@ var TODO_PLAN_STATUSES = ["active", "completed", "abandoned"];
205
223
  function agentDisplayName(agent2) {
206
224
  return agent2.label?.trim() || agent2.name;
207
225
  }
226
+ var TOOL_APPROVAL_STATES = [
227
+ "approval-requested",
228
+ "approval-responded",
229
+ "approval-dispatched"
230
+ ];
231
+ var OPEN_TOOL_PART_STATES = ["streaming", "running", ...TOOL_APPROVAL_STATES];
232
+ function isOpenToolPartState(state) {
233
+ return OPEN_TOOL_PART_STATES.includes(state);
234
+ }
235
+ function isToolApprovalState(state) {
236
+ return TOOL_APPROVAL_STATES.includes(state);
237
+ }
238
+ function compareAgentSessionMessages(left, right) {
239
+ const createdAtOrder = left.createdAt.getTime() - right.createdAt.getTime();
240
+ return createdAtOrder === 0 ? left.id.localeCompare(right.id) : createdAtOrder;
241
+ }
242
+ function orderAgentSessionMessages(messages) {
243
+ return [...messages].sort(compareAgentSessionMessages);
244
+ }
208
245
  var TODO_STATUSES = ["pending", "in_progress", "completed", "blocked"];
209
246
  var MAX_TODOS = 50;
210
247
  var MAX_TODO_ID_CHARS = 80;
@@ -308,6 +345,15 @@ function resolveFieldRequired(input) {
308
345
  function getSlotFieldTargets(field) {
309
346
  return field.additionalSlotIds?.length ? [field.slotId, ...field.additionalSlotIds] : [field.slotId];
310
347
  }
348
+ function formFieldKey(field) {
349
+ return isFormSlotFieldRef(field) ? `${field.slotId}.${field.attribute}` : `free.${field.attribute.name}`;
350
+ }
351
+ function formFieldFlatKey(field) {
352
+ return isFormSlotFieldRef(field) ? field.attribute : field.attribute.name;
353
+ }
354
+ function readFormFieldValue(values, field) {
355
+ return values[formFieldKey(field)] ?? values[formFieldFlatKey(field)];
356
+ }
311
357
 
312
358
  // src/types/forms/rows.ts
313
359
  function isFormFieldsRow(row) {
@@ -395,8 +441,7 @@ function parseCountMode(value) {
395
441
  return value;
396
442
  }
397
443
  throw new ValidationError(
398
- // biome-ignore lint/style/useTemplate: see the comment above.
399
- "countMode must be one of: " + COUNT_MODES.join(", ") + " (received: " + String(value) + ")",
444
+ `countMode must be one of: ${COUNT_MODES.join(", ")} (received: ${String(value)})`,
400
445
  []
401
446
  );
402
447
  }
@@ -868,6 +913,12 @@ function relationPropertyDefs(attribute) {
868
913
  if (attribute?.type !== "relation") return void 0;
869
914
  return attribute.properties?.definitions;
870
915
  }
916
+ function qualifiedPropertyDefs(attribute) {
917
+ if (attribute?.type === "relation" || attribute?.type === "document") {
918
+ return attribute.properties?.definitions;
919
+ }
920
+ return void 0;
921
+ }
871
922
  function extractValueRefs(value) {
872
923
  if (isNullishOrEmptyString(value)) return [];
873
924
  if (typeof value === "string") return [{ id: value }];
@@ -1108,6 +1159,12 @@ function assertUniqueBy(items, getKey, buildError) {
1108
1159
  seen.add(key);
1109
1160
  }
1110
1161
  }
1162
+ var ATTRIBUTE_NAME_SCHEMA = z2.string().min(1, "Attribute name cannot be empty").max(MAX_NAME_LENGTH, `Attribute name is too long (max ${MAX_NAME_LENGTH} characters)`).regex(ATTRIBUTE_NAME_REGEX, {
1163
+ message: "Invalid attribute name format.\nName must be a valid variable identifier:\n \u2705 Valid: 'firstName', 'first_name', 'FirstName', 'FIRST_NAME'\n \u274C Invalid: 'first-name', 'first name', '123name', 'first.name'"
1164
+ }).refine(
1165
+ (name) => !RESERVED_ATTRIBUTE_NAMES.includes(name),
1166
+ { message: "This is a reserved attribute name" }
1167
+ );
1111
1168
  function validateAttributeName(name) {
1112
1169
  if (!name || name.length === 0) {
1113
1170
  throw new Error("[AttributeBuilder] Attribute name cannot be empty");
@@ -2131,6 +2188,16 @@ var RollupAttributeBuilder = class extends BaseAttributeBuilder {
2131
2188
  this.attr.targetAttributeOptions = options;
2132
2189
  return this;
2133
2190
  }
2191
+ /**
2192
+ * Set the currency code a sum/avg over a currency target renders with
2193
+ * (#2644). Mirror of the target attribute's `defaultCurrency` — the stored
2194
+ * value stays a bare number; this only carries the symbol to the screen.
2195
+ * @param code - ISO 4217 code (e.g. "EUR")
2196
+ */
2197
+ targetCurrency(code) {
2198
+ this.attr.targetCurrencyCode = code;
2199
+ return this;
2200
+ }
2134
2201
  /**
2135
2202
  * Build the attribute, validating computed-field configuration eagerly so a
2136
2203
  * misconfiguration surfaces at schema-definition time (with a fix-it hint)
@@ -5220,6 +5287,8 @@ function liveChannelKey(channel) {
5220
5287
  return `user:${encodeURIComponent(channel.actorId)}`;
5221
5288
  case "conversation":
5222
5289
  return `conversation:${encodeURIComponent(channel.sessionId)}`;
5290
+ case "architect-draft":
5291
+ return `architect-draft:${encodeURIComponent(channel.actorId)}`;
5223
5292
  }
5224
5293
  }
5225
5294
  function decodeLiveChannelPart(part) {
@@ -5261,6 +5330,10 @@ function parseLiveChannelKey(key) {
5261
5330
  const actorId = decodeLiveChannelPart(parts[1]);
5262
5331
  return actorId ? { kind: "user", actorId } : null;
5263
5332
  }
5333
+ if (parts[0] === "architect-draft" && parts.length === 2 && parts[1]) {
5334
+ const actorId = decodeLiveChannelPart(parts[1]);
5335
+ return actorId ? { kind: "architect-draft", actorId } : null;
5336
+ }
5264
5337
  if (parts[0] === "conversation" && parts.length === 2 && parts[1]) {
5265
5338
  const sessionId = decodeLiveChannelPart(parts[1]);
5266
5339
  return sessionId ? { kind: "conversation", sessionId } : null;
@@ -5281,8 +5354,13 @@ var LIVE_EVENT_TYPE_REGISTRY = {
5281
5354
  "notification.created": true,
5282
5355
  "notification.recipient.patch": true,
5283
5356
  "notification.count.patch": true,
5357
+ "notification.inbox.archived": true,
5284
5358
  "conversation.renamed": true,
5285
5359
  "browser.preview.updated": true,
5360
+ "reflex.state.changed": true,
5361
+ "reflex.run.completed": true,
5362
+ "reflex.authoring.progress": true,
5363
+ "architect.draft.updated": true,
5286
5364
  "channel.revoked": true
5287
5365
  };
5288
5366
  var LIVE_EVENT_TYPES = Object.keys(LIVE_EVENT_TYPE_REGISTRY);
@@ -5348,6 +5426,13 @@ var RECORD_LIVE_SNAPSHOT_KEYS = [
5348
5426
  "lastUpdatedBy",
5349
5427
  "schemaVersion"
5350
5428
  ];
5429
+ var NOTIFICATION_INBOX_ARCHIVED_PAYLOAD_KEYS = [
5430
+ "type",
5431
+ "targetActorId",
5432
+ "archivedCount",
5433
+ "version",
5434
+ "updatedAt"
5435
+ ];
5351
5436
  function isLiveEventType(value) {
5352
5437
  return typeof value === "string" && LIVE_EVENT_TYPES.includes(value);
5353
5438
  }
@@ -5382,10 +5467,20 @@ function isLiveEventPayloadForType(type, payload) {
5382
5467
  return isNotificationRecipientPatchPayload(payload);
5383
5468
  case "notification.count.patch":
5384
5469
  return isNotificationCountPatchPayload(payload);
5470
+ case "notification.inbox.archived":
5471
+ return isNotificationInboxArchivedPayload(payload);
5385
5472
  case "conversation.renamed":
5386
5473
  return isConversationRenamedPayload(payload);
5387
5474
  case "browser.preview.updated":
5388
5475
  return isBrowserPreviewUpdatedPayload(payload);
5476
+ case "reflex.state.changed":
5477
+ return isReflexStateChangedPayload(payload);
5478
+ case "reflex.run.completed":
5479
+ return isReflexRunCompletedPayload(payload);
5480
+ case "reflex.authoring.progress":
5481
+ return isReflexAuthoringProgressPayload(payload);
5482
+ case "architect.draft.updated":
5483
+ return isArchitectDraftUpdatedPayload(payload);
5389
5484
  case "channel.revoked":
5390
5485
  return isChannelRevokedPayload(payload);
5391
5486
  default:
@@ -5460,7 +5555,9 @@ function isRecordFieldPatch(value) {
5460
5555
  return isRecord2(value) && hasString(value, "fieldKey") && Object.hasOwn(value, "value") && hasVersion(value, "version");
5461
5556
  }
5462
5557
  function isRecordPatchPayload(payload) {
5463
- return payload.type === "record.patch" && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion") && hasOptional(payload, "label", isString) && hasOptional(payload, "metadata", isRecord2) && Array.isArray(payload.fieldPatches) && payload.fieldPatches.every(isRecordFieldPatch) && hasString(payload, "updatedAt");
5558
+ return payload.type === "record.patch" && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion") && hasOptional(payload, "label", isString) && hasOptional(payload, "metadata", isRecord2) && // Strictly `true`: the applier evicts an entity on this bit, so truthy
5559
+ // junk on the wire must not pass as the presence flag (#2637).
5560
+ hasOptional(payload, "fieldsWithheld", (value) => value === true) && Array.isArray(payload.fieldPatches) && payload.fieldPatches.every(isRecordFieldPatch) && hasString(payload, "updatedAt");
5464
5561
  }
5465
5562
  function isRecordDeletedPayload(payload) {
5466
5563
  return payload.type === "record.deleted" && hasString(payload, "objectId") && hasString(payload, "recordId") && hasVersion(payload, "recordVersion") && hasString(payload, "deletedAt");
@@ -5509,6 +5606,9 @@ function isNotificationRecipientPatchPayload(payload) {
5509
5606
  function isNotificationCountPatchPayload(payload) {
5510
5607
  return payload.type === "notification.count.patch" && hasString(payload, "targetActorId") && hasVersion(payload, "unread") && hasVersion(payload, "pendingWork") && hasVersion(payload, "version") && hasIsoDateString(payload, "updatedAt");
5511
5608
  }
5609
+ function isNotificationInboxArchivedPayload(payload) {
5610
+ return payload.type === "notification.inbox.archived" && hasOnlyKeys(payload, NOTIFICATION_INBOX_ARCHIVED_PAYLOAD_KEYS) && hasNonEmptyString(payload, "targetActorId") && hasVersion(payload, "archivedCount") && hasVersion(payload, "version") && hasIsoDateString(payload, "updatedAt");
5611
+ }
5512
5612
  function isConversationRenamedPayload(payload) {
5513
5613
  return payload.type === "conversation.renamed" && hasString(payload, "sessionId") && hasString(payload, "title") && hasVersion(payload, "version") && hasString(payload, "updatedAt");
5514
5614
  }
@@ -5516,6 +5616,41 @@ function isBrowserPreviewUpdatedPayload(payload) {
5516
5616
  const preview = payload.preview;
5517
5617
  return payload.type === "browser.preview.updated" && hasOnlyKeys(payload, BROWSER_PREVIEW_UPDATED_PAYLOAD_KEYS) && isRecord2(preview) && hasOnlyKeys(preview, BROWSER_PREVIEW_DESCRIPTOR_KEYS) && hasNonEmptyString(preview, "previewId") && hasNonEmptyString(preview, "rootSessionId") && hasNonEmptyString(preview, "agentSessionId") && hasNonEmptyString(preview, "browserSession") && isOneOf(preview.status, BROWSER_PREVIEW_STATUSES) && hasVersion(preview, "sequence") && hasIsoDateString(preview, "updatedAt") && preview.previewId === `browser:${preview.agentSessionId}:${preview.browserSession}`;
5518
5618
  }
5619
+ var REFLEX_STATES = ["armed", "disarmed"];
5620
+ var REFLEX_AUTHORING_STATUSES = [
5621
+ "authoring",
5622
+ "compiling",
5623
+ "replaying",
5624
+ "promoted",
5625
+ "failed"
5626
+ ];
5627
+ var REFLEX_SERVED_MODES = [
5628
+ "promoted",
5629
+ "lkg"
5630
+ ];
5631
+ var ARCHITECT_DRAFT_STATUSES = [
5632
+ "composing",
5633
+ "published",
5634
+ "discarded"
5635
+ ];
5636
+ function isArchitectDraftUpdatedPayload(payload) {
5637
+ if (payload.type !== "architect.draft.updated" || !isRecord2(payload.draft)) {
5638
+ return false;
5639
+ }
5640
+ const draft = payload.draft;
5641
+ return hasNonEmptyString(draft, "id") && hasNonEmptyString(draft, "actorId") && isNullableString(draft.agentSessionId) && // Each operation was parsed by the registry before it was persisted; the
5642
+ // wire check stops at the shape realtime itself is responsible for.
5643
+ Array.isArray(draft.operations) && draft.operations.every(isRecord2) && isRecord2(draft.baselines) && isOneOf(draft.status, ARCHITECT_DRAFT_STATUSES);
5644
+ }
5645
+ function isReflexStateChangedPayload(payload) {
5646
+ return payload.type === "reflex.state.changed" && hasNonEmptyString(payload, "reflexId") && isOneOf(payload.state, REFLEX_STATES) && hasIsoDateString(payload, "updatedAt");
5647
+ }
5648
+ function isReflexRunCompletedPayload(payload) {
5649
+ return payload.type === "reflex.run.completed" && hasNonEmptyString(payload, "reflexId") && hasNonEmptyString(payload, "runId") && isOneOf(payload.served, REFLEX_SERVED_MODES) && hasVersion(payload, "version") && hasVersion(payload, "wallMs") && hasIsoDateString(payload, "completedAt");
5650
+ }
5651
+ function isReflexAuthoringProgressPayload(payload) {
5652
+ return payload.type === "reflex.authoring.progress" && hasNonEmptyString(payload, "reflexId") && isOneOf(payload.status, REFLEX_AUTHORING_STATUSES) && hasIsoDateString(payload, "updatedAt");
5653
+ }
5519
5654
  function isChannelRevokedPayload(payload) {
5520
5655
  return payload.type === "channel.revoked" && hasString(payload, "channel") && isOneOf(payload.reason, CHANNEL_REVOKED_REASONS);
5521
5656
  }
@@ -6305,7 +6440,11 @@ function evaluateCallNode(functionName, args, input) {
6305
6440
  assertComputedFunctionName(functionName);
6306
6441
  validateArity(functionName, args.length);
6307
6442
  if (functionName === "if") {
6308
- return evaluateAst(args[0], input) ? evaluateAst(args[1], input) : evaluateAst(args[2], input);
6443
+ const condition = evaluateAst(args[0], input);
6444
+ if (condition === null) {
6445
+ return null;
6446
+ }
6447
+ return condition ? evaluateAst(args[1], input) : evaluateAst(args[2], input);
6309
6448
  }
6310
6449
  return evaluateCall(
6311
6450
  functionName,
@@ -6351,8 +6490,10 @@ function evaluateBinary(operator, left, right) {
6351
6490
  return compareWith(left, right, (result) => result <= 0);
6352
6491
  case "==":
6353
6492
  return equalScalar(left, right);
6354
- case "!=":
6355
- return !equalScalar(left, right);
6493
+ case "!=": {
6494
+ const equal = equalScalar(left, right);
6495
+ return equal === null ? null : !equal;
6496
+ }
6356
6497
  default:
6357
6498
  return unreachable(operator);
6358
6499
  }
@@ -6368,6 +6509,9 @@ function compareWith(left, right, predicate) {
6368
6509
  return result === null ? null : predicate(result);
6369
6510
  }
6370
6511
  function compare(left, right) {
6512
+ if (!areCommensurable([left, right])) {
6513
+ return null;
6514
+ }
6371
6515
  const leftNumber = toFiniteNumber(left);
6372
6516
  const rightNumber = toFiniteNumber(right);
6373
6517
  if (leftNumber !== null && rightNumber !== null) {
@@ -6384,6 +6528,9 @@ function equalScalar(left, right) {
6384
6528
  if (left === null || left === void 0 || right === null || right === void 0) {
6385
6529
  return false;
6386
6530
  }
6531
+ if (!areCommensurable([left, right])) {
6532
+ return null;
6533
+ }
6387
6534
  return compare(left, right) === 0;
6388
6535
  }
6389
6536
  function assertComputedFunctionName(name) {
@@ -6404,8 +6551,14 @@ function evaluateCall(functionName, args) {
6404
6551
  case "concat":
6405
6552
  return args.filter((arg) => arg !== null && arg !== void 0).map(String).join("");
6406
6553
  case "sum":
6554
+ if (!areCommensurable(args)) {
6555
+ return null;
6556
+ }
6407
6557
  return numericValues(args).reduce((total, value) => total + value, 0);
6408
6558
  case "avg": {
6559
+ if (!areCommensurable(args)) {
6560
+ return null;
6561
+ }
6409
6562
  const values = numericValues(args);
6410
6563
  return values.length > 0 ? values.reduce((total, value) => total + value, 0) / values.length : null;
6411
6564
  }
@@ -6443,7 +6596,22 @@ function unreachable(value) {
6443
6596
  function numericValues(values) {
6444
6597
  return flatten(values).map(toFiniteNumber).filter((value) => value !== null);
6445
6598
  }
6599
+ function areCommensurable(values) {
6600
+ const codes = /* @__PURE__ */ new Set();
6601
+ for (const value of flatten(values)) {
6602
+ if (isCurrencyValue(value)) {
6603
+ codes.add(currencyCode(value));
6604
+ }
6605
+ }
6606
+ return codes.size <= 1;
6607
+ }
6608
+ function currencyCode(value) {
6609
+ return value.code.toUpperCase();
6610
+ }
6446
6611
  function numericBinary(left, right, operation) {
6612
+ if (!areCommensurable([left, right])) {
6613
+ return null;
6614
+ }
6447
6615
  const leftNumber = toFiniteNumber(left);
6448
6616
  const rightNumber = toFiniteNumber(right);
6449
6617
  if (leftNumber === null || rightNumber === null) {
@@ -6453,6 +6621,9 @@ function numericBinary(left, right, operation) {
6453
6621
  return Number.isFinite(result) ? result : null;
6454
6622
  }
6455
6623
  function minMax(values, mode) {
6624
+ if (!areCommensurable(values)) {
6625
+ return null;
6626
+ }
6456
6627
  const numbers = numericValues(values);
6457
6628
  if (numbers.length > 0) {
6458
6629
  return mode === "min" ? Math.min(...numbers) : Math.max(...numbers);
@@ -6531,6 +6702,9 @@ function toDate(value) {
6531
6702
  return Number.isNaN(date2.getTime()) ? null : date2;
6532
6703
  }
6533
6704
  function uniqueKey(value) {
6705
+ if (isCurrencyValue(value)) {
6706
+ return `currency:${currencyCode(value)}:${value.value}`;
6707
+ }
6534
6708
  const numberValue = toFiniteNumber(value);
6535
6709
  if (numberValue !== null) {
6536
6710
  return `number:${numberValue}`;
@@ -7482,11 +7656,243 @@ var persistedSchemaPlanSchema = z.preprocess(
7482
7656
  boundSerializedPlanInput,
7483
7657
  structuralPersistedSchemaPlanSchema
7484
7658
  );
7659
+ var nonNegativeNumberSchema = z.number().finite().nonnegative();
7660
+ var toolImpactSchema = z.object({
7661
+ label: z.string(),
7662
+ denied: z.boolean().optional(),
7663
+ deletion: z.object({
7664
+ target: z.string().optional(),
7665
+ count: nonNegativeNumberSchema.optional(),
7666
+ restorableDays: nonNegativeNumberSchema.optional()
7667
+ }).strict().optional(),
7668
+ counts: z.record(z.string(), nonNegativeNumberSchema).optional(),
7669
+ warnings: z.array(z.string()).optional()
7670
+ }).strict();
7671
+ var agentMessagePartSchema = z.union([
7672
+ z.object({ type: z.literal("text"), text: z.string() }).strict(),
7673
+ z.object({ type: z.literal("reasoning"), text: z.string() }).strict(),
7674
+ z.object({ type: z.literal("error"), error: z.string(), errorClass: z.string().optional() }).strict(),
7675
+ z.object({
7676
+ type: z.literal("tool"),
7677
+ toolCallId: z.string(),
7678
+ name: z.string(),
7679
+ args: z.record(z.string(), z.unknown()),
7680
+ result: z.unknown().optional(),
7681
+ error: z.string().optional(),
7682
+ errorCode: z.enum(["output_limit_reached", "interrupted"]).optional(),
7683
+ state: z.enum([
7684
+ "streaming",
7685
+ "running",
7686
+ "completed",
7687
+ "error",
7688
+ "approval-requested",
7689
+ "approval-responded",
7690
+ "approval-dispatched"
7691
+ ]),
7692
+ durationMs: nonNegativeNumberSchema.optional(),
7693
+ approvalId: z.string().optional(),
7694
+ approvalImpact: toolImpactSchema.optional(),
7695
+ approved: z.boolean().optional(),
7696
+ approvalReason: z.string().optional(),
7697
+ approvalRelaxableByAuto: z.boolean().optional()
7698
+ }).strict(),
7699
+ z.object({
7700
+ type: z.literal("file"),
7701
+ fileId: z.string(),
7702
+ name: z.string(),
7703
+ mimeType: z.string()
7704
+ }).strict(),
7705
+ z.object({
7706
+ type: z.literal("compaction"),
7707
+ state: z.literal("in-progress"),
7708
+ reason: z.enum(["preflight_threshold", "overflow_recovery"]),
7709
+ estimatedTokens: nonNegativeNumberSchema.optional(),
7710
+ reportedTokens: nonNegativeNumberSchema.optional()
7711
+ }).strict(),
7712
+ z.object({
7713
+ type: z.literal("compaction"),
7714
+ state: z.literal("completed"),
7715
+ tokensBefore: nonNegativeNumberSchema,
7716
+ tokensAfter: nonNegativeNumberSchema,
7717
+ tokensSaved: nonNegativeNumberSchema,
7718
+ strategy: z.enum(["no-op", "summary", "truncation"]),
7719
+ durationMs: nonNegativeNumberSchema,
7720
+ summary: z.string().optional()
7721
+ }).strict(),
7722
+ z.object({
7723
+ type: z.literal("compaction"),
7724
+ state: z.literal("failed"),
7725
+ reason: z.string(),
7726
+ durationMs: nonNegativeNumberSchema.optional()
7727
+ }).strict()
7728
+ ]);
7729
+ var agentMessageAttachmentSchema = z.object({
7730
+ id: z.string(),
7731
+ name: z.string(),
7732
+ mimeType: z.string(),
7733
+ size: nonNegativeNumberSchema
7734
+ }).strict();
7735
+ var mentionReferenceSchema = z.object({
7736
+ id: z.string(),
7737
+ // `MentionEntityType` is `"user" | "record" | (string & {})`, which accepts
7738
+ // exactly what `string` accepts but is not `Equal` to it, so a bare
7739
+ // `z.string()` fails this file's drift guard. The identity transform types
7740
+ // the output without touching validation: `z.string()` still runs first, so
7741
+ // a non-string is still rejected as `invalid_type` with the same message and
7742
+ // path — which matters, because `agentUIValidationError` copies the issue
7743
+ // code into the ValidationError it throws.
7744
+ type: z.string().transform((value) => value),
7745
+ entityId: z.string(),
7746
+ label: z.string(),
7747
+ objectName: z.string().optional(),
7748
+ startIndex: nonNegativeNumberSchema,
7749
+ endIndex: nonNegativeNumberSchema
7750
+ }).strict();
7751
+ var modelDefinitionSchema = z.object({
7752
+ provider: z.enum(["anthropic", "openai", "google", "mistral"]),
7753
+ model: z.string(),
7754
+ maxTokens: nonNegativeNumberSchema.optional(),
7755
+ contextWindow: nonNegativeNumberSchema.optional()
7756
+ }).strict();
7757
+ var durableDateSchema = z.union([
7758
+ z.date(),
7759
+ z.string().datetime({ offset: true }).transform((value) => new Date(value))
7760
+ ]);
7761
+ var agentSessionMessageSchema = z.object({
7762
+ id: z.string(),
7763
+ sessionId: z.string(),
7764
+ tenantId: z.string().optional(),
7765
+ runId: z.string().optional(),
7766
+ role: z.enum(["user", "assistant", "system", "tool"]),
7767
+ parts: z.array(agentMessagePartSchema),
7768
+ attachments: z.array(agentMessageAttachmentSchema).optional(),
7769
+ mentions: z.array(mentionReferenceSchema).optional(),
7770
+ model: modelDefinitionSchema.optional(),
7771
+ tokenUsage: z.object({ input: nonNegativeNumberSchema, output: nonNegativeNumberSchema }).strict().optional(),
7772
+ metadata: z.record(z.string(), z.unknown()).optional(),
7773
+ createdAt: durableDateSchema
7774
+ }).strict();
7775
+ var todoItemSchema = z.object({
7776
+ id: z.string(),
7777
+ description: z.string(),
7778
+ status: z.enum(["pending", "in_progress", "completed", "blocked"]),
7779
+ result: z.string().optional(),
7780
+ updatedAt: nonNegativeNumberSchema.optional()
7781
+ }).strict();
7782
+ var todoPlanSchema = z.object({
7783
+ id: z.string(),
7784
+ sessionId: z.string(),
7785
+ status: z.enum(["active", "completed", "abandoned"]),
7786
+ todos: z.array(todoItemSchema),
7787
+ version: nonNegativeNumberSchema,
7788
+ createdAt: z.string(),
7789
+ updatedAt: z.string(),
7790
+ completedAt: z.string().optional()
7791
+ }).strict();
7792
+ var customDataChunkSchemas = {
7793
+ "session-named": z.object({ name: z.string() }).strict(),
7794
+ "compaction-start": z.object({
7795
+ reason: z.enum(["preflight_threshold", "overflow_recovery"]),
7796
+ estimatedTokens: nonNegativeNumberSchema.optional(),
7797
+ reportedTokens: nonNegativeNumberSchema.optional()
7798
+ }).strict(),
7799
+ "compaction-end": z.object({
7800
+ tokensBefore: nonNegativeNumberSchema,
7801
+ tokensAfter: nonNegativeNumberSchema,
7802
+ tokensSaved: nonNegativeNumberSchema,
7803
+ strategy: z.enum(["no-op", "summary", "truncation"]),
7804
+ durationMs: nonNegativeNumberSchema,
7805
+ summary: z.string().optional()
7806
+ }).strict(),
7807
+ "compaction-failed": z.object({ reason: z.string() }).strict(),
7808
+ usage: z.object({
7809
+ inputTokens: nonNegativeNumberSchema,
7810
+ outputTokens: nonNegativeNumberSchema,
7811
+ totalTokens: nonNegativeNumberSchema,
7812
+ cacheReadTokens: nonNegativeNumberSchema.optional(),
7813
+ cacheCreationTokens: nonNegativeNumberSchema.optional(),
7814
+ contextWindow: nonNegativeNumberSchema,
7815
+ residentTokens: nonNegativeNumberSchema,
7816
+ utilization: z.number().finite().min(0).max(1),
7817
+ costUsd: nonNegativeNumberSchema.optional()
7818
+ }).strict(),
7819
+ "message-persisted": z.object({ message: agentSessionMessageSchema }).strict(),
7820
+ "message-updated": z.object({ message: agentSessionMessageSchema }).strict(),
7821
+ "todo-plan-update": z.object({ plan: todoPlanSchema }).strict(),
7822
+ "approval-context": z.object({
7823
+ approvalId: z.string(),
7824
+ toolCallId: z.string(),
7825
+ impact: toolImpactSchema.optional(),
7826
+ relaxableByAuto: z.boolean().optional()
7827
+ }).strict()
7828
+ };
7829
+ function isAgentUIDataName(value) {
7830
+ return value in customDataChunkSchemas;
7831
+ }
7832
+ function agentUIValidationError(issues) {
7833
+ return new ValidationError(
7834
+ "Invalid agent UI message chunk",
7835
+ issues.map((issue) => ({
7836
+ path: issue.path.map(String),
7837
+ message: issue.message,
7838
+ code: issue.code
7839
+ }))
7840
+ );
7841
+ }
7842
+ function assertCustomAgentUIMessageChunk(value) {
7843
+ if (typeof value !== "object" || value === null || typeof value.type !== "string") {
7844
+ throw new ValidationError("Invalid agent UI message chunk", [
7845
+ { path: ["type"], message: "Expected UI message chunk type", code: "invalid_type" }
7846
+ ]);
7847
+ }
7848
+ const type = value.type;
7849
+ if (!type.startsWith("data-")) {
7850
+ throw new ValidationError("Invalid agent UI message chunk", [
7851
+ { path: ["type"], message: "Expected agent data chunk type", code: "invalid_value" }
7852
+ ]);
7853
+ }
7854
+ const name = type.slice("data-".length);
7855
+ if (!isAgentUIDataName(name)) {
7856
+ throw new ValidationError("Invalid agent UI message chunk", [
7857
+ { path: ["type"], message: `Unknown agent UI data type: ${name}`, code: "invalid_value" }
7858
+ ]);
7859
+ }
7860
+ const chunkResult = z.object({
7861
+ type: z.literal(`data-${name}`),
7862
+ id: z.string().optional(),
7863
+ data: customDataChunkSchemas[name],
7864
+ transient: z.boolean().optional()
7865
+ }).strict().safeParse(value);
7866
+ if (!chunkResult.success) throw agentUIValidationError(chunkResult.error.issues);
7867
+ return chunkResult.data;
7868
+ }
7869
+ function agentDataChunk(name, data, options) {
7870
+ return assertCustomAgentUIMessageChunk({
7871
+ type: `data-${name}`,
7872
+ ...options?.id !== void 0 ? { id: options.id } : {},
7873
+ data,
7874
+ ...options?.transient !== void 0 ? { transient: options.transient } : {}
7875
+ });
7876
+ }
7485
7877
 
7486
7878
  // src/architect/define-operation.ts
7487
7879
  function defineOperation(def) {
7488
7880
  return def;
7489
7881
  }
7882
+ function definePresentation(focus, impact, propertyPath) {
7883
+ const navigation = impact === "atomic" ? "none" : impact === "local" ? "if-not-visible" : "follow";
7884
+ return (op) => {
7885
+ const path = propertyPath?.(op);
7886
+ return {
7887
+ impact,
7888
+ navigation,
7889
+ focus: {
7890
+ ...focus(op),
7891
+ ...path === void 0 ? {} : { propertyPath: path }
7892
+ }
7893
+ };
7894
+ };
7895
+ }
7490
7896
  var operationBase = { id: z.string().min(1) };
7491
7897
  var viewOperationBase = { ...operationBase, viewId: z.string().min(1) };
7492
7898
  function mapView(state, viewId, fn) {
@@ -7536,18 +7942,47 @@ function locateField(tab, fieldId) {
7536
7942
  }
7537
7943
  throw new ValidationError(`Field slot "${fieldId}" is not in tab "${tab.id}"`, []);
7538
7944
  }
7539
- var tabPayload = z.custom(
7540
- (value) => typeof value === "object" && value !== null && "id" in value && "type" in value,
7541
- { message: "A tab must be an object carrying id and type" }
7542
- );
7543
- var groupPayload = z.custom(
7544
- (value) => typeof value === "object" && value !== null && "id" in value && "fields" in value,
7545
- { message: "A group must be an object carrying id and fields" }
7546
- );
7547
- var fieldPayload = z.custom(
7548
- (value) => typeof value === "object" && value !== null && "id" in value,
7549
- { message: "A field slot must be an object carrying an id" }
7550
- );
7945
+ function viewFocus(op) {
7946
+ return { viewId: op.viewId };
7947
+ }
7948
+ function tabFocus(op) {
7949
+ return { viewId: op.viewId, tabId: op.tabId };
7950
+ }
7951
+ function groupFocus(op) {
7952
+ return { viewId: op.viewId, tabId: op.tabId, groupId: op.groupId };
7953
+ }
7954
+ function fieldFocus(op) {
7955
+ return { viewId: op.viewId, tabId: op.tabId, fieldId: op.fieldId };
7956
+ }
7957
+ function addTabFocus(op) {
7958
+ return { viewId: op.viewId, tabId: op.tab.id };
7959
+ }
7960
+ function addGroupFocus(op) {
7961
+ return { viewId: op.viewId, tabId: op.tabId, groupId: op.group.id };
7962
+ }
7963
+ function addFieldFocus(op) {
7964
+ return {
7965
+ viewId: op.viewId,
7966
+ tabId: op.tabId,
7967
+ groupId: op.groupId,
7968
+ fieldId: op.field.id
7969
+ };
7970
+ }
7971
+ function moveFieldFocus(op) {
7972
+ return {
7973
+ viewId: op.viewId,
7974
+ tabId: op.tabId,
7975
+ groupId: op.toGroupId,
7976
+ fieldId: op.fieldId
7977
+ };
7978
+ }
7979
+ function firstChangedProperty(op) {
7980
+ const keys = Object.keys(op.changes).sort();
7981
+ return keys.length === 1 ? [keys[0]] : void 0;
7982
+ }
7983
+ var tabPayload = detailTabDraftSchema;
7984
+ var groupPayload = groupWriteSchema;
7985
+ var fieldPayload = fieldSlotSchema;
7551
7986
  var addTabSchema = z.object({
7552
7987
  ...viewOperationBase,
7553
7988
  type: z.literal("add_tab"),
@@ -7562,7 +7997,8 @@ var addTab = defineOperation({
7562
7997
  }
7563
7998
  return { ...view, tabs: [...view.tabs, op.tab] };
7564
7999
  }),
7565
- focus: (op) => ({ viewId: op.viewId, tabId: op.tab.id }),
8000
+ focus: addTabFocus,
8001
+ presentation: definePresentation(addTabFocus, "local"),
7566
8002
  describe: (op) => `Ajoute l'onglet \xAB ${op.tab.label} \xBB`
7567
8003
  });
7568
8004
  var removeTabSchema = z.object({
@@ -7579,18 +8015,30 @@ var removeTab = defineOperation({
7579
8015
  }
7580
8016
  return { ...view, tabs: view.tabs.filter((t) => t.id !== op.tabId) };
7581
8017
  }),
7582
- focus: (op) => ({ viewId: op.viewId }),
8018
+ focus: tabFocus,
8019
+ presentation: definePresentation(tabFocus, "local"),
7583
8020
  describe: (op) => `Supprime l'onglet ${op.tabId}`
7584
8021
  });
8022
+ var updateTabChanges = z.object({
8023
+ label: z.string().min(1).optional(),
8024
+ icon: iconNameSchema.optional(),
8025
+ order: z.number().int().optional()
8026
+ });
8027
+ var UPDATE_TAB_CHANGE_KEYS = Object.keys(
8028
+ updateTabChanges.shape
8029
+ );
7585
8030
  var updateTabSchema = z.object({
7586
8031
  ...viewOperationBase,
7587
8032
  type: z.literal("update_tab"),
7588
8033
  tabId: z.string().min(1),
7589
- changes: z.object({
7590
- label: z.string().min(1).optional(),
7591
- icon: z.custom((v) => typeof v === "string" && v.length > 0).optional(),
7592
- order: z.number().int().optional()
7593
- }).refine((c) => Object.keys(c).length > 0, "update_tab needs at least one change")
8034
+ changes: updateTabChanges.refine(
8035
+ (c) => Object.keys(c).length > 0,
8036
+ "update_tab needs at least one change"
8037
+ )
8038
+ });
8039
+ var updateTabFocus = (op) => ({
8040
+ viewId: op.viewId,
8041
+ tabId: op.tabId
7594
8042
  });
7595
8043
  var updateTab = defineOperation({
7596
8044
  type: "update_tab",
@@ -7604,7 +8052,8 @@ var updateTab = defineOperation({
7604
8052
  tabs: view.tabs.map((t) => t.id === op.tabId ? { ...t, ...op.changes } : t)
7605
8053
  };
7606
8054
  }),
7607
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8055
+ focus: updateTabFocus,
8056
+ presentation: definePresentation(updateTabFocus, "atomic", firstChangedProperty),
7608
8057
  describe: (op) => op.changes.label ? `Renomme l'onglet en \xAB ${op.changes.label} \xBB` : `Modifie l'onglet ${op.tabId}`
7609
8058
  });
7610
8059
  var reorderTabsSchema = z.object({
@@ -7619,7 +8068,8 @@ var reorderTabs = defineOperation({
7619
8068
  ...view,
7620
8069
  tabs: reorderById(view.tabs, op.tabOrder, "Tab")
7621
8070
  })),
7622
- focus: (op) => ({ viewId: op.viewId }),
8071
+ focus: viewFocus,
8072
+ presentation: definePresentation(viewFocus, "local"),
7623
8073
  describe: () => "R\xE9ordonne les onglets"
7624
8074
  });
7625
8075
  var addGroupSchema = z.object({
@@ -7644,7 +8094,8 @@ var addGroup = defineOperation({
7644
8094
  return { ...tab, groups: [...tab.groups, op.group] };
7645
8095
  })
7646
8096
  ),
7647
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId, groupId: op.group.id }),
8097
+ focus: addGroupFocus,
8098
+ presentation: definePresentation(addGroupFocus, "local"),
7648
8099
  describe: (op) => `Ajoute le groupe \xAB ${op.group.label} \xBB`
7649
8100
  });
7650
8101
  var removeGroupSchema = z.object({
@@ -7664,19 +8115,31 @@ var removeGroup = defineOperation({
7664
8115
  return { ...tab, groups: tab.groups.filter((g) => g.id !== op.groupId) };
7665
8116
  })
7666
8117
  ),
7667
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8118
+ focus: groupFocus,
8119
+ presentation: definePresentation(groupFocus, "local"),
7668
8120
  describe: (op) => `Supprime le groupe ${op.groupId}`
7669
8121
  });
7670
- var setGroupLabelSchema = z.object({
8122
+ var updateGroupSchema = z.object({
7671
8123
  ...viewOperationBase,
7672
- type: z.literal("set_group_label"),
8124
+ type: z.literal("update_group"),
7673
8125
  tabId: z.string().min(1),
7674
8126
  groupId: z.string().min(1),
7675
- label: z.string().min(1)
8127
+ changes: z.object({
8128
+ label: z.string().min(1).optional(),
8129
+ description: z.string().optional(),
8130
+ collapsible: z.boolean().optional(),
8131
+ collapsed: z.boolean().optional(),
8132
+ order: z.number().int().optional()
8133
+ }).refine((c) => Object.keys(c).length > 0, "update_group needs at least one change")
7676
8134
  });
7677
- var setGroupLabel = defineOperation({
7678
- type: "set_group_label",
7679
- schema: setGroupLabelSchema,
8135
+ var updateGroupFocus = (op) => ({
8136
+ viewId: op.viewId,
8137
+ tabId: op.tabId,
8138
+ groupId: op.groupId
8139
+ });
8140
+ var updateGroup = defineOperation({
8141
+ type: "update_group",
8142
+ schema: updateGroupSchema,
7680
8143
  apply: (state, op) => mapView(
7681
8144
  state,
7682
8145
  op.viewId,
@@ -7684,12 +8147,13 @@ var setGroupLabel = defineOperation({
7684
8147
  requireGroup(tab, op.groupId);
7685
8148
  return {
7686
8149
  ...tab,
7687
- groups: tab.groups.map((g) => g.id === op.groupId ? { ...g, label: op.label } : g)
8150
+ groups: tab.groups.map((g) => g.id === op.groupId ? { ...g, ...op.changes } : g)
7688
8151
  };
7689
8152
  })
7690
8153
  ),
7691
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId, groupId: op.groupId }),
7692
- describe: (op) => `Renomme le groupe en \xAB ${op.label} \xBB`
8154
+ focus: updateGroupFocus,
8155
+ presentation: definePresentation(updateGroupFocus, "atomic", firstChangedProperty),
8156
+ describe: (op) => op.changes.label ? `Renomme le groupe en \xAB ${op.changes.label} \xBB` : "Modifie le groupe"
7693
8157
  });
7694
8158
  var reorderGroupsSchema = z.object({
7695
8159
  ...viewOperationBase,
@@ -7708,7 +8172,8 @@ var reorderGroups = defineOperation({
7708
8172
  groups: reorderById(tab.groups, op.groupOrder, "Group")
7709
8173
  }))
7710
8174
  ),
7711
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8175
+ focus: tabFocus,
8176
+ presentation: definePresentation(tabFocus, "local"),
7712
8177
  describe: () => "R\xE9ordonne les groupes"
7713
8178
  });
7714
8179
  var addFieldSchema = z.object({
@@ -7746,12 +8211,8 @@ var addField = defineOperation({
7746
8211
  };
7747
8212
  })
7748
8213
  ),
7749
- focus: (op) => ({
7750
- viewId: op.viewId,
7751
- tabId: op.tabId,
7752
- groupId: op.groupId,
7753
- fieldId: op.field.id
7754
- }),
8214
+ focus: addFieldFocus,
8215
+ presentation: definePresentation(addFieldFocus, "local"),
7755
8216
  describe: (op) => `Ajoute le champ ${op.field.attribute ?? op.field.id}`
7756
8217
  });
7757
8218
  var removeFieldSchema = z.object({
@@ -7776,7 +8237,8 @@ var removeField = defineOperation({
7776
8237
  };
7777
8238
  })
7778
8239
  ),
7779
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8240
+ focus: fieldFocus,
8241
+ presentation: definePresentation(fieldFocus, "local"),
7780
8242
  describe: (op) => `Retire le champ ${op.fieldId}`
7781
8243
  });
7782
8244
  var moveFieldSchema = z.object({
@@ -7826,12 +8288,8 @@ var moveField = defineOperation({
7826
8288
  };
7827
8289
  })
7828
8290
  ),
7829
- focus: (op) => ({
7830
- viewId: op.viewId,
7831
- tabId: op.tabId,
7832
- groupId: op.toGroupId,
7833
- fieldId: op.fieldId
7834
- }),
8291
+ focus: moveFieldFocus,
8292
+ presentation: definePresentation(moveFieldFocus, "local"),
7835
8293
  describe: (op) => `D\xE9place le champ ${op.fieldId} vers le groupe ${op.toGroupId}`
7836
8294
  });
7837
8295
  var updateFieldSchema = z.object({
@@ -7845,6 +8303,11 @@ var updateFieldSchema = z.object({
7845
8303
  span: z.number().int().min(1).max(12).optional()
7846
8304
  }).refine((c) => Object.keys(c).length > 0, "update_field needs at least one change")
7847
8305
  });
8306
+ var updateFieldFocus = (op) => ({
8307
+ viewId: op.viewId,
8308
+ tabId: op.tabId,
8309
+ fieldId: op.fieldId
8310
+ });
7848
8311
  var updateField = defineOperation({
7849
8312
  type: "update_field",
7850
8313
  schema: updateFieldSchema,
@@ -7864,9 +8327,137 @@ var updateField = defineOperation({
7864
8327
  };
7865
8328
  })
7866
8329
  ),
7867
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId, fieldId: op.fieldId }),
8330
+ focus: updateFieldFocus,
8331
+ presentation: definePresentation(updateFieldFocus, "atomic", firstChangedProperty),
7868
8332
  describe: (op) => `Modifie le champ ${op.fieldId}`
7869
8333
  });
8334
+ var updateTableTabChanges = z.object({
8335
+ /**
8336
+ * Where the table reads its rows from — a `TableSource`, not a name: a
8337
+ * direct relation, or the inverse of one. Kept with `columns` on purpose:
8338
+ * the source picker posts `{ source, columns: [] }` as one gesture, and
8339
+ * splitting the pair across two operations would wipe the column list while
8340
+ * the source change vanished (#2763, #2787).
8341
+ */
8342
+ source: tableSourceSchema.optional(),
8343
+ columns: columnsSchema.optional(),
8344
+ // Nullable, not merely optional: the panels clear a filter list or a sort
8345
+ // list by sending `null`, because `undefined` does not survive
8346
+ // `JSON.stringify` and the operation would arrive with no changes at all
8347
+ // (#2787). `apply` drops the key rather than storing the null.
8348
+ filters: filterStateSchema.nullable().optional(),
8349
+ sorts: sortsSchema.nullable().optional(),
8350
+ allowCreate: z.boolean().optional(),
8351
+ allowEdit: z.boolean().optional(),
8352
+ allowDelete: z.boolean().optional(),
8353
+ createMode: z.enum(["redirect", "inline", "peek"]).optional()
8354
+ });
8355
+ var UPDATE_TABLE_TAB_CHANGE_KEYS = Object.keys(
8356
+ updateTableTabChanges.shape
8357
+ );
8358
+ var updateTabConfigChanges = z.object({
8359
+ /** Address attributes an emails/meetings tab reads. */
8360
+ emailAttributeIds: z.array(z.string().min(1)).optional(),
8361
+ /**
8362
+ * The attribute a richtext tab edits, and the one it titles itself with.
8363
+ * `titleAttribute` is nullable because "None" is a real choice — and null,
8364
+ * not undefined, because `JSON.stringify` drops undefined-valued keys and
8365
+ * the operation would arrive with no changes at all.
8366
+ */
8367
+ attribute: z.string().min(1).optional(),
8368
+ titleAttribute: z.string().min(1).nullable().optional(),
8369
+ /**
8370
+ * The component a custom tab renders, and the props handed to it. Both are
8371
+ * clearable for the same reason: the name is emptied on blur and the props
8372
+ * textarea is emptied to mean "none".
8373
+ */
8374
+ component: z.string().nullable().optional(),
8375
+ props: z.record(z.string(), z.unknown()).nullable().optional()
8376
+ });
8377
+ var UPDATE_TAB_CONFIG_CHANGE_KEYS = Object.keys(
8378
+ updateTabConfigChanges.shape
8379
+ );
8380
+ var TAB_CONFIG_FIELD_OWNERS = {
8381
+ emailAttributeIds: ["emails", "meetings"],
8382
+ attribute: ["richtext"],
8383
+ titleAttribute: ["richtext"],
8384
+ component: ["custom"],
8385
+ props: ["custom"]
8386
+ };
8387
+ var updateTabConfigSchema = z.object({
8388
+ ...viewOperationBase,
8389
+ type: z.literal("update_tab_config"),
8390
+ tabId: z.string().min(1),
8391
+ changes: updateTabConfigChanges.refine(
8392
+ (c) => Object.keys(c).length > 0,
8393
+ "update_tab_config needs at least one change"
8394
+ )
8395
+ });
8396
+ var updateTabConfigFocus = (op) => ({
8397
+ viewId: op.viewId,
8398
+ tabId: op.tabId
8399
+ });
8400
+ var updateTabConfig = defineOperation({
8401
+ type: "update_tab_config",
8402
+ schema: updateTabConfigSchema,
8403
+ apply: (state, op) => mapView(state, op.viewId, (view) => {
8404
+ const found = view.tabs.find((t) => t.id === op.tabId);
8405
+ if (!found) {
8406
+ throw new ValidationError(`Tab "${op.tabId}" is not in view "${view.id}"`, []);
8407
+ }
8408
+ for (const key of Object.keys(op.changes)) {
8409
+ const allowed = TAB_CONFIG_FIELD_OWNERS[key];
8410
+ if (allowed && !allowed.includes(found.type)) {
8411
+ throw new ValidationError(`"${key}" is not a setting of a "${found.type}" tab`, []);
8412
+ }
8413
+ }
8414
+ return {
8415
+ ...view,
8416
+ tabs: view.tabs.map((t) => t.id === op.tabId ? { ...t, ...op.changes } : t)
8417
+ };
8418
+ }),
8419
+ focus: updateTabConfigFocus,
8420
+ presentation: definePresentation(updateTabConfigFocus, "atomic", firstChangedProperty),
8421
+ describe: (op) => `Configure ${Object.keys(op.changes).join(", ")} sur l'onglet ${op.tabId}`
8422
+ });
8423
+ var updateTableTabSchema = z.object({
8424
+ ...viewOperationBase,
8425
+ type: z.literal("update_table_tab"),
8426
+ tabId: z.string().min(1),
8427
+ changes: updateTableTabChanges.refine(
8428
+ (c) => Object.keys(c).length > 0,
8429
+ "update_table_tab needs at least one change"
8430
+ )
8431
+ });
8432
+ var updateTableTabFocus = (op) => ({
8433
+ viewId: op.viewId,
8434
+ tabId: op.tabId
8435
+ });
8436
+ var updateTableTab = defineOperation({
8437
+ type: "update_table_tab",
8438
+ schema: updateTableTabSchema,
8439
+ apply: (state, op) => mapView(state, op.viewId, (view) => {
8440
+ const found = view.tabs.find((t) => t.id === op.tabId);
8441
+ if (!found) throw new ValidationError(`Tab "${op.tabId}" is not in view "${view.id}"`, []);
8442
+ if (found.type !== "table") {
8443
+ throw new ValidationError(`Tab "${op.tabId}" is not a table tab`, []);
8444
+ }
8445
+ const entries = Object.entries(op.changes);
8446
+ const applied = Object.fromEntries(entries.filter(([, value]) => value !== null));
8447
+ const cleared = new Set(entries.filter(([, value]) => value === null).map(([key]) => key));
8448
+ return {
8449
+ ...view,
8450
+ tabs: view.tabs.map(
8451
+ (t) => t.id === op.tabId ? Object.fromEntries(
8452
+ Object.entries({ ...t, ...applied }).filter(([key]) => !cleared.has(key))
8453
+ ) : t
8454
+ )
8455
+ };
8456
+ }),
8457
+ focus: updateTableTabFocus,
8458
+ presentation: definePresentation(updateTableTabFocus, "atomic", firstChangedProperty),
8459
+ describe: (op) => op.changes.columns ? `Affiche ${op.changes.columns.length} colonne(s) dans l'onglet ${op.tabId}` : `Modifie l'onglet ${op.tabId}`
8460
+ });
7870
8461
  var setSidePanelSchema = z.object({
7871
8462
  ...viewOperationBase,
7872
8463
  type: z.literal("set_side_panel"),
@@ -7882,7 +8473,8 @@ var setSidePanel = defineOperation({
7882
8473
  sidePanel: op.sidePanel ?? void 0
7883
8474
  }
7884
8475
  })),
7885
- focus: (op) => ({ viewId: op.viewId }),
8476
+ focus: viewFocus,
8477
+ presentation: definePresentation(viewFocus, "atomic", () => ["config", "sidePanel"]),
7886
8478
  describe: (op) => op.sidePanel ? "Active le panneau lat\xE9ral" : "Retire le panneau lat\xE9ral"
7887
8479
  });
7888
8480
  var DETAIL_VIEW_OPERATIONS = [
@@ -7892,15 +8484,54 @@ var DETAIL_VIEW_OPERATIONS = [
7892
8484
  reorderTabs,
7893
8485
  addGroup,
7894
8486
  removeGroup,
7895
- setGroupLabel,
8487
+ updateGroup,
7896
8488
  reorderGroups,
7897
8489
  addField,
7898
8490
  removeField,
7899
8491
  moveField,
7900
8492
  updateField,
8493
+ updateTableTab,
8494
+ updateTabConfig,
7901
8495
  setSidePanel
7902
8496
  ];
7903
8497
  var listTabBase = { ...viewOperationBase, tabId: z.string().min(1) };
8498
+ function viewFocus2(op) {
8499
+ return { viewId: op.viewId };
8500
+ }
8501
+ function tabFocus2(op) {
8502
+ return { viewId: op.viewId, tabId: op.tabId };
8503
+ }
8504
+ function addTabFocus2(op) {
8505
+ return { viewId: op.viewId, tabId: op.tab.id };
8506
+ }
8507
+ function firstChangedProperty2(op) {
8508
+ const keys = Object.keys(op.changes).sort();
8509
+ return keys.length === 1 ? [keys[0]] : void 0;
8510
+ }
8511
+ function withoutKanbanKeys(tab) {
8512
+ const rest = { ...tab };
8513
+ for (const key of LIST_TAB_KANBAN_KEYS) delete rest[key];
8514
+ return rest;
8515
+ }
8516
+ function withoutTableKeys(tab) {
8517
+ const rest = { ...tab };
8518
+ for (const key of LIST_TAB_TABLE_KEYS) delete rest[key];
8519
+ return rest;
8520
+ }
8521
+ function assertStillPublishableTab(before, after, viewId, tabId) {
8522
+ const parsed = listViewTabSchema.safeParse(after);
8523
+ if (!parsed.success) {
8524
+ if (!listViewTabSchema.safeParse(before).success) return after;
8525
+ const detail = parsed.error.issues.map(
8526
+ (issue) => issue.path.length ? `${issue.path.join(".")}: ${issue.message}` : issue.message
8527
+ ).join(", ");
8528
+ throw new ValidationError(
8529
+ `List tab "${tabId}" in view "${viewId}" would no longer be publishable: ${detail}`,
8530
+ []
8531
+ );
8532
+ }
8533
+ return after;
8534
+ }
7904
8535
  function mapListTab(state, viewId, tabId, fn) {
7905
8536
  return mapView(state, viewId, (view) => {
7906
8537
  const tabs = view.config.tabs ?? [];
@@ -7909,18 +8540,18 @@ function mapListTab(state, viewId, tabId, fn) {
7909
8540
  }
7910
8541
  return {
7911
8542
  ...view,
7912
- config: { ...view.config, tabs: tabs.map((t) => t.id === tabId ? fn(t) : t) }
8543
+ config: {
8544
+ ...view.config,
8545
+ tabs: tabs.map(
8546
+ (t) => t.id === tabId ? assertStillPublishableTab(t, fn(t), viewId, tabId) : t
8547
+ )
8548
+ }
7913
8549
  };
7914
8550
  });
7915
8551
  }
7916
- var listTabPayload = z.custom(
7917
- (value) => typeof value === "object" && value !== null && "id" in value,
7918
- { message: "A list tab must be an object carrying an id" }
7919
- );
7920
- var filterGroupPayload = z.custom(
7921
- (value) => value === null || typeof value === "object"
7922
- );
7923
- var sortRulesPayload = z.custom((value) => Array.isArray(value));
8552
+ var listTabPayload = listViewTabSchema;
8553
+ var filterGroupPayload = filterGroupSchema;
8554
+ var sortRulesPayload = sortsSchema;
7924
8555
  function setOnTab(type, key, valueSchema, describe) {
7925
8556
  const schema = z.object({ ...listTabBase, type: z.literal(type), value: valueSchema });
7926
8557
  return defineOperation({
@@ -7933,7 +8564,8 @@ function setOnTab(type, key, valueSchema, describe) {
7933
8564
  }
7934
8565
  return { ...tab, [key]: op.value };
7935
8566
  }),
7936
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8567
+ focus: tabFocus2,
8568
+ presentation: definePresentation(tabFocus2, "atomic", () => [String(key)]),
7937
8569
  describe: (op) => describe(op.value)
7938
8570
  });
7939
8571
  }
@@ -7955,7 +8587,8 @@ var addListTab = defineOperation({
7955
8587
  }
7956
8588
  return { ...view, config: { ...view.config, tabs: [...tabs, op.tab] } };
7957
8589
  }),
7958
- focus: (op) => ({ viewId: op.viewId, tabId: op.tab.id }),
8590
+ focus: addTabFocus2,
8591
+ presentation: definePresentation(addTabFocus2, "local"),
7959
8592
  describe: (op) => `Ajoute l'onglet \xAB ${op.tab.label} \xBB`
7960
8593
  });
7961
8594
  var removeListTabSchema = z.object({
@@ -7975,7 +8608,8 @@ var removeListTab = defineOperation({
7975
8608
  config: { ...view.config, tabs: tabs.filter((t) => t.id !== op.tabId) }
7976
8609
  };
7977
8610
  }),
7978
- focus: (op) => ({ viewId: op.viewId }),
8611
+ focus: tabFocus2,
8612
+ presentation: definePresentation(tabFocus2, "local"),
7979
8613
  describe: (op) => `Supprime l'onglet ${op.tabId}`
7980
8614
  });
7981
8615
  var updateListTabSchema = z.object({
@@ -7983,16 +8617,21 @@ var updateListTabSchema = z.object({
7983
8617
  type: z.literal("update_list_tab"),
7984
8618
  changes: z.object({
7985
8619
  label: z.string().min(1).optional(),
7986
- icon: z.custom((v) => typeof v === "string" && v.length > 0).optional(),
8620
+ icon: iconNameSchema.optional(),
7987
8621
  default: z.boolean().optional(),
7988
8622
  visibility: z.enum(LIST_VIEW_TAB_VISIBILITIES).optional()
7989
8623
  }).refine((c) => Object.keys(c).length > 0, "update_list_tab needs at least one change")
7990
8624
  });
8625
+ var updateListTabFocus = (op) => ({
8626
+ viewId: op.viewId,
8627
+ tabId: op.tabId
8628
+ });
7991
8629
  var updateListTab = defineOperation({
7992
8630
  type: "update_list_tab",
7993
8631
  schema: updateListTabSchema,
7994
8632
  apply: (state, op) => mapListTab(state, op.viewId, op.tabId, (tab) => ({ ...tab, ...op.changes })),
7995
- focus: (op) => ({ viewId: op.viewId, tabId: op.tabId }),
8633
+ focus: updateListTabFocus,
8634
+ presentation: definePresentation(updateListTabFocus, "atomic", firstChangedProperty2),
7996
8635
  describe: (op) => op.changes.label ? `Renomme l'onglet en \xAB ${op.changes.label} \xBB` : `Modifie l'onglet ${op.tabId}`
7997
8636
  });
7998
8637
  var reorderListTabsSchema = z.object({
@@ -8010,7 +8649,8 @@ var reorderListTabs = defineOperation({
8010
8649
  tabs: reorderById(view.config.tabs ?? [], op.tabOrder, "List tab")
8011
8650
  }
8012
8651
  })),
8013
- focus: (op) => ({ viewId: op.viewId }),
8652
+ focus: viewFocus2,
8653
+ presentation: definePresentation(viewFocus2, "local"),
8014
8654
  describe: () => "R\xE9ordonne les onglets"
8015
8655
  });
8016
8656
  var setColumns = setOnTab(
@@ -8027,18 +8667,47 @@ var setColumnSizing = setOnTab(
8027
8667
  z.record(z.string(), z.number().int().positive()),
8028
8668
  () => "Ajuste la largeur des colonnes"
8029
8669
  );
8030
- var setLayout = setOnTab(
8031
- "set_layout",
8032
- "layout",
8033
- z.enum(["table", "kanban"]),
8034
- (value) => `Passe en affichage ${value}`
8035
- );
8036
- var setGroupBy = setOnTab(
8037
- "set_group_by",
8038
- "groupByAttribute",
8039
- z.string().min(1).nullable(),
8040
- (value) => value ? `Regroupe par ${value}` : "Retire le regroupement"
8041
- );
8670
+ var setLayoutSchema = z.object({
8671
+ ...listTabBase,
8672
+ type: z.literal("set_layout"),
8673
+ value: z.enum(["table", "kanban"])
8674
+ });
8675
+ var setLayout = defineOperation({
8676
+ type: "set_layout",
8677
+ schema: setLayoutSchema,
8678
+ apply: (state, op) => mapListTab(state, op.viewId, op.tabId, (tab) => {
8679
+ if (op.value === "table") return { ...withoutKanbanKeys(tab), layout: "table" };
8680
+ if (tab.groupByAttribute === void 0) {
8681
+ throw new ValidationError(
8682
+ `List tab "${op.tabId}" cannot switch to kanban without a group attribute \u2014 use set_group_by, which switches the layout itself`,
8683
+ []
8684
+ );
8685
+ }
8686
+ return { ...withoutTableKeys(tab), layout: "kanban" };
8687
+ }),
8688
+ focus: tabFocus2,
8689
+ presentation: definePresentation(tabFocus2, "atomic", () => ["layout"]),
8690
+ describe: (op) => `Passe en affichage ${op.value}`
8691
+ });
8692
+ var setGroupBySchema = z.object({
8693
+ ...listTabBase,
8694
+ type: z.literal("set_group_by"),
8695
+ value: z.string().min(1).nullable()
8696
+ });
8697
+ var setGroupBy = defineOperation({
8698
+ type: "set_group_by",
8699
+ schema: setGroupBySchema,
8700
+ apply: (state, op) => mapListTab(
8701
+ state,
8702
+ op.viewId,
8703
+ op.tabId,
8704
+ (tab) => op.value === null ? { ...withoutKanbanKeys(tab), layout: "table" } : { ...withoutTableKeys(tab), layout: "kanban", groupByAttribute: op.value }
8705
+ ),
8706
+ focus: tabFocus2,
8707
+ // The layout flip is a side effect; the addressable property stays the group.
8708
+ presentation: definePresentation(tabFocus2, "atomic", () => ["groupByAttribute"]),
8709
+ describe: (op) => op.value ? `Regroupe par ${op.value} en kanban` : "Retire le regroupement, retour en table"
8710
+ });
8042
8711
  var setFilters = setOnTab(
8043
8712
  "set_filters",
8044
8713
  "filters",
@@ -8075,7 +8744,27 @@ var setCardDateAttribute = setOnTab(
8075
8744
  z.string().min(1).nullable(),
8076
8745
  (value) => value ? `Affiche ${value} sur les cartes` : "Retire la date des cartes"
8077
8746
  );
8747
+ var setDefaultFiltersSchema = z.object({
8748
+ ...viewOperationBase,
8749
+ type: z.literal("set_default_filters"),
8750
+ filters: filterGroupPayload.nullable()
8751
+ });
8752
+ var setDefaultFilters = defineOperation({
8753
+ type: "set_default_filters",
8754
+ schema: setDefaultFiltersSchema,
8755
+ apply: (state, op) => mapView(state, op.viewId, (view) => {
8756
+ if (op.filters === null) {
8757
+ const { defaultFilters: _dropped, ...rest } = view.config;
8758
+ return { ...view, config: rest };
8759
+ }
8760
+ return { ...view, config: { ...view.config, defaultFilters: op.filters } };
8761
+ }),
8762
+ focus: viewFocus2,
8763
+ presentation: definePresentation(viewFocus2, "atomic", () => ["config", "defaultFilters"]),
8764
+ describe: (op) => op.filters ? "Modifie les filtres de la vue" : "Retire les filtres de la vue"
8765
+ });
8078
8766
  var LIST_VIEW_OPERATIONS = [
8767
+ setDefaultFilters,
8079
8768
  addListTab,
8080
8769
  removeListTab,
8081
8770
  updateListTab,
@@ -8096,11 +8785,27 @@ function requireObject(state, objectId) {
8096
8785
  throw new ValidationError(`Object "${objectId}" is not in the draftable state`, []);
8097
8786
  }
8098
8787
  }
8099
- var objectOperationBase = { ...operationBase, objectId: z.string().min(1) };
8788
+ function objectFocus(op) {
8789
+ return { objectId: op.objectId };
8790
+ }
8791
+ function recordFocus(op) {
8792
+ return { objectId: op.objectId, recordId: op.recordId };
8793
+ }
8794
+ function attributeFocus(op) {
8795
+ return { objectId: op.objectId, attributeId: op.attributeId };
8796
+ }
8797
+ function firstChangedProperty3(op) {
8798
+ const keys = Object.keys(op.changes).sort();
8799
+ return keys.length === 1 ? [keys[0]] : void 0;
8800
+ }
8801
+ var objectOperationBase = { ...operationBase, objectId: z.string().uuid() };
8100
8802
  var addObjectSchema = z.object({
8101
8803
  ...objectOperationBase,
8102
8804
  type: z.literal("add_object"),
8103
- name: z.string().min(1),
8805
+ // The service's own kebab-case rule, enforced at APPEND: an agent that
8806
+ // names an object "Facture" is refused here with the format spelled out,
8807
+ // not at publish (live QA, 2026-08-17).
8808
+ name: OBJECT_NAME_SCHEMA,
8104
8809
  label: z.string().min(1),
8105
8810
  icon: z.string().min(1).optional()
8106
8811
  });
@@ -8124,7 +8829,8 @@ var addObject = defineOperation({
8124
8829
  },
8125
8830
  // The caller generates objectId, so a draft object is addressable by route
8126
8831
  // before it exists — that is what lets the app navigate to it live.
8127
- focus: (op) => ({ objectId: op.objectId }),
8832
+ focus: objectFocus,
8833
+ presentation: definePresentation(objectFocus, "structural"),
8128
8834
  describe: (op) => `Cr\xE9e l'objet \xAB ${op.label} \xBB`
8129
8835
  });
8130
8836
  var updateObjectSchema = z.object({
@@ -8132,6 +8838,9 @@ var updateObjectSchema = z.object({
8132
8838
  type: z.literal("update_object"),
8133
8839
  changes: z.object({ label: z.string().min(1).optional(), icon: z.string().min(1).optional() }).refine((c) => Object.keys(c).length > 0, "update_object needs at least one change")
8134
8840
  });
8841
+ var updateObjectFocus = (op) => ({
8842
+ objectId: op.objectId
8843
+ });
8135
8844
  var updateObject = defineOperation({
8136
8845
  type: "update_object",
8137
8846
  schema: updateObjectSchema,
@@ -8142,7 +8851,8 @@ var updateObject = defineOperation({
8142
8851
  objects: state.objects.map((o) => o.id === op.objectId ? { ...o, ...op.changes } : o)
8143
8852
  };
8144
8853
  },
8145
- focus: (op) => ({ objectId: op.objectId }),
8854
+ focus: updateObjectFocus,
8855
+ presentation: definePresentation(updateObjectFocus, "atomic", firstChangedProperty3),
8146
8856
  describe: (op) => op.changes.label ? `Renomme l'objet en \xAB ${op.changes.label} \xBB` : "Modifie l'objet"
8147
8857
  });
8148
8858
  var removeObjectSchema = z.object({ ...objectOperationBase, type: z.literal("remove_object") });
@@ -8151,24 +8861,51 @@ var removeObject = defineOperation({
8151
8861
  schema: removeObjectSchema,
8152
8862
  apply: (state, op) => {
8153
8863
  requireObject(state, op.objectId);
8864
+ const objectName = state.objects.find((o) => o.id === op.objectId)?.name;
8154
8865
  return {
8155
8866
  ...state,
8156
8867
  objects: state.objects.filter((o) => o.id !== op.objectId),
8157
8868
  attributes: state.attributes.filter((a) => a.objectId !== op.objectId),
8158
8869
  sampleRecords: state.sampleRecords.filter((r) => r.objectId !== op.objectId),
8159
- views: state.views.filter((v) => v.objectId !== op.objectId)
8870
+ views: state.views.filter((v) => v.objectName !== objectName)
8160
8871
  };
8161
8872
  },
8162
- focus: () => ({}),
8873
+ focus: objectFocus,
8874
+ presentation: definePresentation(objectFocus, "structural"),
8163
8875
  describe: (op) => `Supprime l'objet ${op.objectId}`
8164
8876
  });
8877
+ var DRAFTABLE_ATTRIBUTE_TYPES = ATTRIBUTE_TYPES.filter(
8878
+ (type) => type !== "formula" && type !== "rollup"
8879
+ );
8165
8880
  var addAttributeSchema = z.object({
8166
8881
  ...objectOperationBase,
8167
8882
  type: z.literal("add_attribute"),
8168
8883
  attributeId: z.string().min(1),
8169
- name: z.string().min(1),
8884
+ // The same identifier rule the attribute builder enforces.
8885
+ name: ATTRIBUTE_NAME_SCHEMA,
8170
8886
  label: z.string().min(1),
8171
- attributeType: z.string().min(1)
8887
+ // The canonical union, not a bare string: an agent that invents "num" gets
8888
+ // refused at APPEND, where the error names the valid types and the one
8889
+ // operation to fix — instead of a whole draft failing at publish.
8890
+ attributeType: z.enum(DRAFTABLE_ATTRIBUTE_TYPES),
8891
+ /** Type-specific configuration, published as-is onto the attribute. */
8892
+ config: z.record(z.string(), z.unknown()).optional()
8893
+ }).superRefine((op, ctx) => {
8894
+ try {
8895
+ parseAttributeConfigForCreate(op.attributeType, op.config ?? {});
8896
+ } catch (error) {
8897
+ if (error instanceof ValidationError) {
8898
+ for (const detail of error.errors) {
8899
+ ctx.addIssue({
8900
+ code: "custom",
8901
+ message: detail.message,
8902
+ path: ["config", ...detail.path ?? []]
8903
+ });
8904
+ }
8905
+ return;
8906
+ }
8907
+ throw error;
8908
+ }
8172
8909
  });
8173
8910
  var addAttribute = defineOperation({
8174
8911
  type: "add_attribute",
@@ -8181,25 +8918,28 @@ var addAttribute = defineOperation({
8181
8918
  []
8182
8919
  );
8183
8920
  }
8921
+ const added = {
8922
+ id: op.attributeId,
8923
+ objectId: op.objectId,
8924
+ name: op.name,
8925
+ label: op.label,
8926
+ attributeType: op.attributeType,
8927
+ ...op.config === void 0 ? {} : { config: op.config }
8928
+ };
8929
+ for (const sample of state.sampleRecords) {
8930
+ if (sample.objectId === op.objectId) assertRequiredCovered(sample.id, added, sample.values);
8931
+ }
8184
8932
  return {
8185
8933
  ...state,
8186
- attributes: [
8187
- ...state.attributes,
8188
- {
8189
- id: op.attributeId,
8190
- objectId: op.objectId,
8191
- name: op.name,
8192
- label: op.label,
8193
- attributeType: op.attributeType
8194
- }
8195
- ]
8934
+ attributes: [...state.attributes, added]
8196
8935
  };
8197
8936
  },
8198
- focus: (op) => ({ objectId: op.objectId }),
8937
+ focus: attributeFocus,
8938
+ presentation: definePresentation(attributeFocus, "local"),
8199
8939
  describe: (op) => `Ajoute l'attribut \xAB ${op.label} \xBB`
8200
8940
  });
8201
8941
  var updateAttributeSchema = z.object({
8202
- ...operationBase,
8942
+ ...objectOperationBase,
8203
8943
  type: z.literal("update_attribute"),
8204
8944
  attributeId: z.string().min(1),
8205
8945
  changes: z.object({ label: z.string().min(1).optional() }).refine((c) => Object.keys(c).length > 0, "update_attribute needs at least one change")
@@ -8218,11 +8958,15 @@ var updateAttribute = defineOperation({
8218
8958
  )
8219
8959
  };
8220
8960
  },
8221
- focus: () => ({}),
8961
+ // Carries objectId so the scope can load the attribute's parent. Without it
8962
+ // the reader returns an empty state and the fold rejects the operation before
8963
+ // the draft is ever persisted — renaming an existing field was impossible.
8964
+ focus: attributeFocus,
8965
+ presentation: definePresentation(attributeFocus, "atomic"),
8222
8966
  describe: (op) => op.changes.label ? `Renomme l'attribut en \xAB ${op.changes.label} \xBB` : "Modifie l'attribut"
8223
8967
  });
8224
8968
  var removeAttributeSchema = z.object({
8225
- ...operationBase,
8969
+ ...objectOperationBase,
8226
8970
  type: z.literal("remove_attribute"),
8227
8971
  attributeId: z.string().min(1)
8228
8972
  });
@@ -8230,18 +8974,62 @@ var removeAttribute = defineOperation({
8230
8974
  type: "remove_attribute",
8231
8975
  schema: removeAttributeSchema,
8232
8976
  apply: (state, op) => {
8233
- if (!state.attributes.some((a) => a.id === op.attributeId)) {
8977
+ const removed = state.attributes.find((a) => a.id === op.attributeId);
8978
+ if (!removed) {
8234
8979
  throw new ValidationError(`Attribute "${op.attributeId}" is not in the draftable state`, []);
8235
8980
  }
8981
+ const user2 = state.sampleRecords.find(
8982
+ (r) => r.objectId === removed.objectId && removed.name in r.values
8983
+ );
8984
+ if (user2) {
8985
+ throw new ValidationError(
8986
+ `Attribute "${removed.name}" is still used by sample record "${user2.id}"`,
8987
+ []
8988
+ );
8989
+ }
8236
8990
  return { ...state, attributes: state.attributes.filter((a) => a.id !== op.attributeId) };
8237
8991
  },
8238
- focus: () => ({}),
8992
+ // Same reason as update_attribute: the parent object must be in scope.
8993
+ focus: attributeFocus,
8994
+ presentation: definePresentation(attributeFocus, "local"),
8239
8995
  describe: (op) => `Supprime l'attribut ${op.attributeId}`
8240
8996
  });
8997
+ function assertSampleValue(recordId, key, attribute, value) {
8998
+ const reconstructed = {
8999
+ id: attribute.id,
9000
+ name: attribute.name,
9001
+ label: attribute.label,
9002
+ type: attribute.attributeType,
9003
+ ...attribute.config
9004
+ };
9005
+ try {
9006
+ createAttributeValidator(reconstructed);
9007
+ } catch {
9008
+ return;
9009
+ }
9010
+ const result = validateAttribute(reconstructed, value);
9011
+ if (result.success) return;
9012
+ const errors = result.errors ?? [];
9013
+ const detail = errors.map((error) => error.message).join(", ");
9014
+ throw new ValidationError(
9015
+ `Sample record "${recordId}" has an invalid value for "${key}": ${detail}`,
9016
+ errors.map((error) => ({ path: error.path, message: error.message }))
9017
+ );
9018
+ }
9019
+ function assertRequiredCovered(recordId, attribute, values) {
9020
+ if (attribute.config?.required !== true) return;
9021
+ if (attribute.config?.defaultValue !== void 0) return;
9022
+ if (attribute.name in values && values[attribute.name] !== void 0) return;
9023
+ throw new ValidationError(
9024
+ `Sample record "${recordId}" is missing a value for required attribute "${attribute.name}"`,
9025
+ []
9026
+ );
9027
+ }
8241
9028
  var addSampleRecordSchema = z.object({
8242
9029
  ...objectOperationBase,
8243
9030
  type: z.literal("add_sample_record"),
8244
- recordId: z.string().min(1),
9031
+ // Same rule as objectId: publish inserts it, so it must be a UUID.
9032
+ recordId: z.string().uuid(),
8245
9033
  values: z.record(z.string(), z.unknown())
8246
9034
  });
8247
9035
  var addSampleRecord = defineOperation({
@@ -8252,6 +9040,22 @@ var addSampleRecord = defineOperation({
8252
9040
  if (state.sampleRecords.some((r) => r.id === op.recordId)) {
8253
9041
  throw new ValidationError(`Sample record "${op.recordId}" already exists`, []);
8254
9042
  }
9043
+ const known = new Map(
9044
+ state.attributes.filter((a) => a.objectId === op.objectId).map((a) => [a.name, a])
9045
+ );
9046
+ for (const [key, value] of Object.entries(op.values)) {
9047
+ const attribute = known.get(key);
9048
+ if (!attribute) {
9049
+ throw new ValidationError(
9050
+ `Sample record "${op.recordId}" uses unknown attribute "${key}"`,
9051
+ []
9052
+ );
9053
+ }
9054
+ assertSampleValue(op.recordId, key, attribute, value);
9055
+ }
9056
+ for (const attribute of known.values()) {
9057
+ assertRequiredCovered(op.recordId, attribute, op.values);
9058
+ }
8255
9059
  return {
8256
9060
  ...state,
8257
9061
  sampleRecords: [
@@ -8262,11 +9066,12 @@ var addSampleRecord = defineOperation({
8262
9066
  },
8263
9067
  // A sample is a draft record, not a render-time fiction: publishing
8264
9068
  // materialises it, discarding the draft discards it.
8265
- focus: (op) => ({ objectId: op.objectId, recordId: op.recordId }),
9069
+ focus: recordFocus,
9070
+ presentation: definePresentation(recordFocus, "local"),
8266
9071
  describe: () => "Ajoute un exemple"
8267
9072
  });
8268
9073
  var removeSampleRecordSchema = z.object({
8269
- ...operationBase,
9074
+ ...objectOperationBase,
8270
9075
  type: z.literal("remove_sample_record"),
8271
9076
  recordId: z.string().min(1)
8272
9077
  });
@@ -8274,12 +9079,16 @@ var removeSampleRecord = defineOperation({
8274
9079
  type: "remove_sample_record",
8275
9080
  schema: removeSampleRecordSchema,
8276
9081
  apply: (state, op) => {
8277
- if (!state.sampleRecords.some((r) => r.id === op.recordId)) {
8278
- throw new ValidationError(`Sample record "${op.recordId}" is not in the draft`, []);
9082
+ if (!state.sampleRecords.some((r) => r.id === op.recordId && r.objectId === op.objectId)) {
9083
+ throw new ValidationError(
9084
+ `Sample record "${op.recordId}" is not in object "${op.objectId}"`,
9085
+ []
9086
+ );
8279
9087
  }
8280
9088
  return { ...state, sampleRecords: state.sampleRecords.filter((r) => r.id !== op.recordId) };
8281
9089
  },
8282
- focus: () => ({}),
9090
+ focus: recordFocus,
9091
+ presentation: definePresentation(recordFocus, "local"),
8283
9092
  describe: () => "Retire un exemple"
8284
9093
  });
8285
9094
  var SCHEMA_OPERATIONS = [
@@ -8355,6 +9164,26 @@ function parseOperation(candidate) {
8355
9164
  }
8356
9165
  return parsed.data;
8357
9166
  }
9167
+ function toJsonSchema(schema) {
9168
+ return z.toJSONSchema(schema, { io: "input" });
9169
+ }
9170
+ function describeOperationInput(type) {
9171
+ const definition = OPERATION_REGISTRY.get(type);
9172
+ if (!definition) {
9173
+ throw new ValidationError(`Unknown operation type "${type}"`, []);
9174
+ }
9175
+ return toJsonSchema(definition.schema);
9176
+ }
9177
+ function describeAttributeConfig(type) {
9178
+ const draftable = DRAFTABLE_ATTRIBUTE_TYPES.find((candidate) => candidate === type);
9179
+ if (!draftable) {
9180
+ throw new ValidationError(`Unknown attribute type "${type}"`, []);
9181
+ }
9182
+ return toJsonSchema(getAttributeConfigWriteSchema(draftable));
9183
+ }
9184
+ function listDescribableNames() {
9185
+ return { operations: [...ALL_OPERATION_TYPES], attributeTypes: [...DRAFTABLE_ATTRIBUTE_TYPES] };
9186
+ }
8358
9187
 
8359
9188
  // src/architect/field-ids.ts
8360
9189
  function makeFieldId(groupId, seed, collisionIndex) {
@@ -8383,4 +9212,123 @@ function ensureFieldIds(tabs) {
8383
9212
  );
8384
9213
  }
8385
9214
 
8386
- export { AGENT_UI_BATCH_MAX_BYTES, AGENT_UI_BATCH_MAX_ITEMS, ALLOWED_PROPERTY_TYPES, ALL_ACTIONS, ALL_OPERATION_TYPES, ALL_SYSTEM_RESOURCES, AUDIT_ACTIONS, AUDIT_RESOURCE_TYPES, ActivityTabConfig, AgentBuilder, BEHAVIOR_PROPERTIES, BROWSER_PREVIEW_STATUSES, BYTE_UNIT_LABELS, CLAIMABLE_SESSION_STATUSES, COMPUTED_FUNCTIONS, COMPUTED_FUNCTION_METADATA, COMPUTED_FUNCTION_NAMES, CONNECTOR_CALLBACK_PARAM, COUNT_MODES, ComputedFormulaCompileError, CustomTabConfig, DB_COLUMN_FIELDS, DEFAULT_AGENT_EXECUTION_CONFIG, DEFAULT_APPROVAL_POLICY, DEFAULT_LABEL_FALLBACK, DEFAULT_ROLES, DEFAULT_ROLE_DESCRIPTIONS, DEFAULT_ROLE_LABELS, DEFAULT_ROLE_PERMISSIONS, DOCUMENT_SYSTEM_ATTRIBUTES, DRIVE_LIST_VIEW, DRIVE_OBJECT, DRIVE_OBJECT_NAME, DRIVE_VIEW, DetailViewBuilder, DocumentsTabConfig, EMPTY_VALUE_PLACEHOLDER, ESTIMATED_COUNT_CAP, EmailsTabConfig, FORM_FORBIDDEN_ATTRIBUTE_TYPES, FlagRegistry, FlagService, FormBuilder, FormRegistry, FormRowBuilder, FormStepBuilder, GroupBuilder, IDENTITY_PROPERTIES, LIVE_EVENT_TYPES, ListViewBuilder, ListViewTabConfigBuilder, MAX_PRESET_DEPTH, MAX_TODOS, MAX_TODO_DESCRIPTION_CHARS, MAX_TODO_ID_CHARS, MAX_TODO_RESULT_CHARS, MEMORY_LIST_VIEW, MEMORY_OBJECT, MEMORY_VIEW, MeetingsTabConfig, NATIVE_AGENT_UI_PART_IDS_METADATA_KEY, NATIVE_AGENT_UI_PART_IDS_METADATA_SCHEMA_VERSION, NOTIFICATION_INBOX_STATES, NOTIFICATION_KINDS, NOTIFICATION_PRIORITIES, NOTIFICATION_SENSITIVITIES, NOTIFICATION_TYPES_V1, NOTIFICATION_TYPE_AGENT_QUESTION_REQUESTED, NOTIFICATION_TYPE_AGENT_SESSION_COMPLETED, NOTIFICATION_TYPE_AGENT_SESSION_FAILED, NOTIFICATION_TYPE_AGENT_SESSION_TIMEOUT, NOTIFICATION_TYPE_AGENT_SESSION_WAITING_HUMAN, NOTIFICATION_TYPE_AGENT_TASK_ASSIGNED, NOTIFICATION_WORK_STATES, NoopGeocodingAdapter, OPERATION_REGISTRY, OPERATOR_SPECS, ObjectBuilder, PRESENTATION_PROPERTIES, QUALIFIED_SEPARATOR, RECORD_CREATOR_ROOT_ACTOR_METADATA_KEY, RELATION_TARGET_ANY, RichtextTabConfig, SCHEMA_PLAN_LIMITS, SESSION_TERMINAL_STATUSES, SKILL_LIST_VIEW, SKILL_OBJECT, SKILL_VIEW, STANDARD_SCHEMA_VENDOR, SYSTEM_RESOURCES, SYSTEM_RESOURCE_LABELS, TODAY_DEFAULT, TODO_PLAN_STATUSES, TODO_STATUSES, TabBuilder, TableTabConfig, USER_STATUSES, USER_WORK_POSTURES, accessLevelToActions, actionsToAccessLevel, agent, agentDisplayName, applyOperations, applyPipes, applyRelationProps, assertAcyclicComputedDependencies, booleanFlag, buildAgentFallbackTitle, buildPermissionFlags, buildPropertySchema, buildQualifiedAttribute, checkbox, compileComputedFormula, compileRollupAttribute, computeByteMagnitude, conversationDisplayTitle, createFlagRegistry, createFlagService, createStandardSchemaProps, currency, date, dateInTimezone, dateValueStart, defineOperation, deriveInitials, describeOperations, destructiveSchema, detailView, document, ensureFieldIds, evaluateComputedAst, evaluateComputedFormula, evaluateComputedFormulaWithResult, evaluateFilterState, evaluateRecordFilterState, extractAttributeNames, extractValueRefs, flagRegistry, focusOf, form, formRegistry, formatAttributeValue, formatByteSize, formatComputedResult, formatLocationValue, formula, generateDefaultDetailView, generateDefaultListView, getActiveTab, getErrorMessage, getLiveProtocolPayloadChannel, getRecordCreatorPrincipalId, getSlotFieldTargets, getUserDisplayName, group, hasDestructiveEntries, hasOptions, includesAction, inferInverseCardinality, inferRollupReturnType, isAgentUIMessageBatch, isAttributeSortable2 as isAttributeSortable, isBilateralRelation, isCheckboxEquality, isClaimableSessionStatus, isComputedFunctionName, isDateRangeValue, isDefaultRole, isDetailView, isDocumentAttribute, isEmptyObject, isFieldGroup, isFormDefinition, isFormFieldsRow, isFormFreeFieldRef, isFormHeadingRow, isFormSeparatorRow, isFormSlotFieldRef, isFormTextRow, isLabelExpression, isListView, isLiveEventEnvelope, isLiveEventPayload, isLiveEventPayloadForType, isLiveEventType, isNotEmpty, isPlainRecord2 as isPlainRecord, isStandardSchema, isTerminalSessionStatus, isTerminalState, isUniversalRelation, jsonFlag, legacyStatusToSessionState, listView, liveChannelKey, location, makeFieldId, matchesAccepts, multiselect, nativeAgentUIPartIdMetadataKey, normalizeDateValue, number, numberFlag, object, parseCountMode, parseLiveChannelKey, parseNativeAgentUIPartIdsMetadata, parseOperation, parseOptionalCountMode, parseQualifiedAttribute, persistedDefaultViewTargetSchema, persistedSchemaPlanSchema, phone, plannedAttributeSchema, plannedInlineAttributeSchema, plannedObjectSchema, proposedDefaultViewTargetSchema, registry, relation, relationPropertyDefs, renderLabelExpression, resetViewToDefault, resolveAttributeDefaultValue, resolveFieldRequired, resolvePropertyDefinitions, richtext, rollup, rollupToFormulaExpression, schemaPlanSchema, select, sessionStateToLegacyStatus, status, stringFlag, text, toUndefinedIfEmpty, user, validateAttributeName, validateLabelExpression, validateObjectName, validateViewName, viewRegistry, viewStateKey, viewSyncPayload };
9215
+ // src/architect/presentation.ts
9216
+ function presentationOf(operation) {
9217
+ return defOf(operation).presentation(operation);
9218
+ }
9219
+ function episodeImpactOf(operations) {
9220
+ const presentations = operations.map(presentationOf);
9221
+ const roots = new Set(
9222
+ presentations.map(({ focus }) => focus.viewId ?? focus.objectId).filter((root) => root !== void 0)
9223
+ );
9224
+ if (roots.size > 1) return "structural";
9225
+ if (presentations.some(({ impact }) => impact === "structural")) return "structural";
9226
+ if (presentations.some(({ impact }) => impact === "local")) return "local";
9227
+ return "atomic";
9228
+ }
9229
+ function listTabOf(view, tabId) {
9230
+ return view.config.tabs?.find((tab) => tab.id === tabId);
9231
+ }
9232
+ function snapshotArchitectTarget(state, focus) {
9233
+ const view = focus.viewId ? state.views.find((candidate) => candidate.id === focus.viewId) : void 0;
9234
+ const detailTab = focus.tabId ? view?.tabs.find((candidate) => candidate.id === focus.tabId) : void 0;
9235
+ if (focus.attributeId) {
9236
+ return state.attributes.find((attribute) => attribute.id === focus.attributeId);
9237
+ }
9238
+ if (focus.fieldId) {
9239
+ if (detailTab?.type !== "form") return void 0;
9240
+ for (const group2 of detailTab.groups) {
9241
+ const field = group2.fields.find((candidate) => candidate.id === focus.fieldId);
9242
+ if (field) return field;
9243
+ }
9244
+ return void 0;
9245
+ }
9246
+ if (focus.groupId) {
9247
+ if (detailTab?.type !== "form") return void 0;
9248
+ return detailTab.groups.find((candidate) => candidate.id === focus.groupId);
9249
+ }
9250
+ if (focus.tabId) {
9251
+ if (!view) return void 0;
9252
+ return detailTab ?? listTabOf(view, focus.tabId);
9253
+ }
9254
+ if (focus.recordId) {
9255
+ return state.sampleRecords.find((record) => record.id === focus.recordId);
9256
+ }
9257
+ if (view) return view;
9258
+ if (focus.objectId) {
9259
+ return state.objects.find((object2) => object2.id === focus.objectId);
9260
+ }
9261
+ return void 0;
9262
+ }
9263
+ function deriveArchitectChanges(initial, operations) {
9264
+ let state = initial;
9265
+ return operations.map((operation) => {
9266
+ const presentation = presentationOf(operation);
9267
+ const before = snapshotArchitectTarget(state, presentation.focus);
9268
+ state = applyOperations(state, [operation]);
9269
+ const after = snapshotArchitectTarget(state, presentation.focus);
9270
+ return {
9271
+ operationId: operation.id,
9272
+ operationType: operation.type,
9273
+ presentation,
9274
+ before,
9275
+ after
9276
+ };
9277
+ });
9278
+ }
9279
+
9280
+ // src/architect/object-projection.ts
9281
+ function toDraftableObject(object2) {
9282
+ return {
9283
+ id: object2.id ?? object2.name,
9284
+ name: object2.name,
9285
+ label: object2.label,
9286
+ ...object2.icon === void 0 ? {} : { icon: object2.icon }
9287
+ };
9288
+ }
9289
+ function toDraftableAttributes(object2) {
9290
+ const objectId = object2.id ?? object2.name;
9291
+ return (object2.attributes ?? []).map((attribute) => toDraftableAttribute(attribute, objectId));
9292
+ }
9293
+ function toDraftableAttribute(attribute, objectId) {
9294
+ const { id: _id, name: _name, label: _label, type: _type, ...config } = attribute;
9295
+ return {
9296
+ id: attribute.id ?? attribute.name,
9297
+ objectId,
9298
+ name: attribute.name,
9299
+ label: attribute.label ?? attribute.name,
9300
+ attributeType: attribute.type,
9301
+ config
9302
+ };
9303
+ }
9304
+
9305
+ // src/architect/view-projection.ts
9306
+ function toDraftableView(view) {
9307
+ return {
9308
+ id: view.id ?? "",
9309
+ objectName: view.object,
9310
+ type: view.type,
9311
+ label: view.label,
9312
+ tabs: isDetailView(view) ? view.config.tabs ?? [] : [],
9313
+ config: view.config
9314
+ };
9315
+ }
9316
+ function fromDraftableView(original, drafted) {
9317
+ if (original.type === "detail") {
9318
+ return {
9319
+ ...original,
9320
+ label: drafted.label,
9321
+ config: {
9322
+ ...drafted.config,
9323
+ tabs: drafted.tabs
9324
+ }
9325
+ };
9326
+ }
9327
+ return {
9328
+ ...original,
9329
+ label: drafted.label,
9330
+ config: drafted.config
9331
+ };
9332
+ }
9333
+
9334
+ export { AGENT_UI_BATCH_MAX_BYTES, AGENT_UI_BATCH_MAX_ITEMS, ALLOWED_PROPERTY_TYPES, ALL_ACTIONS, ALL_OPERATION_TYPES, ALL_SYSTEM_RESOURCES, ATTRIBUTE_TYPES, AUDIT_ACTIONS, AUDIT_RESOURCE_TYPES, ActivityTabConfig, AgentBuilder, BEHAVIOR_PROPERTIES, BROWSER_PREVIEW_STATUSES, BYTE_UNIT_LABELS, CLAIMABLE_SESSION_STATUSES, COMPUTED_FUNCTIONS, COMPUTED_FUNCTION_METADATA, COMPUTED_FUNCTION_NAMES, CONNECTOR_CALLBACK_PARAM, COUNT_MODES, ComputedFormulaCompileError, CustomTabConfig, DB_COLUMN_FIELDS, DEFAULT_AGENT_EXECUTION_CONFIG, DEFAULT_APPROVAL_POLICY, DEFAULT_LABEL_FALLBACK, DEFAULT_ROLES, DEFAULT_ROLE_DESCRIPTIONS, DEFAULT_ROLE_LABELS, DEFAULT_ROLE_PERMISSIONS, DOCUMENT_SYSTEM_ATTRIBUTES, DRAFTABLE_ATTRIBUTE_TYPES, DRIVE_LIST_VIEW, DRIVE_OBJECT, DRIVE_OBJECT_NAME, DRIVE_VIEW, DetailViewBuilder, DocumentsTabConfig, EMPTY_VALUE_PLACEHOLDER, ESTIMATED_COUNT_CAP, EmailsTabConfig, FORM_FORBIDDEN_ATTRIBUTE_TYPES, FlagRegistry, FlagService, FormBuilder, FormRegistry, FormRowBuilder, FormStepBuilder, GroupBuilder, IDENTITY_PROPERTIES, LIVE_EVENT_TYPES, ListViewBuilder, ListViewTabConfigBuilder, MAX_PRESET_DEPTH, MAX_TODOS, MAX_TODO_DESCRIPTION_CHARS, MAX_TODO_ID_CHARS, MAX_TODO_RESULT_CHARS, MEMORY_LIST_VIEW, MEMORY_OBJECT, MEMORY_VIEW, MeetingsTabConfig, NATIVE_AGENT_UI_PART_IDS_METADATA_KEY, NATIVE_AGENT_UI_PART_IDS_METADATA_SCHEMA_VERSION, NOTIFICATION_INBOX_STATES, NOTIFICATION_KINDS, NOTIFICATION_PRIORITIES, NOTIFICATION_SENSITIVITIES, NOTIFICATION_TYPES_V1, NOTIFICATION_TYPE_AGENT_QUESTION_REQUESTED, NOTIFICATION_TYPE_AGENT_SESSION_COMPLETED, NOTIFICATION_TYPE_AGENT_SESSION_FAILED, NOTIFICATION_TYPE_AGENT_SESSION_TIMEOUT, NOTIFICATION_TYPE_AGENT_SESSION_WAITING_HUMAN, NOTIFICATION_TYPE_AGENT_TASK_ASSIGNED, NOTIFICATION_WORK_STATES, NoopGeocodingAdapter, OBJECT_NAME_SCHEMA, OPEN_TOOL_PART_STATES, OPERATION_REGISTRY, OPERATOR_SPECS, ObjectBuilder, PRESENTATION_PROPERTIES, QUALIFIED_SEPARATOR, RECORD_CREATOR_ROOT_ACTOR_METADATA_KEY, RELATION_TARGET_ANY, RichtextTabConfig, SCHEMA_PLAN_LIMITS, SESSION_TERMINAL_STATUSES, SKILL_LIST_VIEW, SKILL_OBJECT, SKILL_VIEW, STANDARD_SCHEMA_VENDOR, SYSTEM_RESOURCES, SYSTEM_RESOURCE_LABELS, TODAY_DEFAULT, TODO_PLAN_STATUSES, TODO_STATUSES, TOOL_APPROVAL_STATES, TabBuilder, TableTabConfig, UPDATE_TABLE_TAB_CHANGE_KEYS, UPDATE_TAB_CHANGE_KEYS, UPDATE_TAB_CONFIG_CHANGE_KEYS, USER_STATUSES, USER_WORK_POSTURES, accessLevelToActions, actionsToAccessLevel, agent, agentDataChunk, agentDisplayName, agentMessageAttachmentSchema, agentMessagePartSchema, agentSessionMessageSchema, agentUIValidationError, applyOperations, applyPipes, applyRelationProps, assertAcyclicComputedDependencies, assertCustomAgentUIMessageChunk, booleanFlag, buildAgentFallbackTitle, buildPermissionFlags, buildPropertySchema, buildQualifiedAttribute, checkbox, compareAgentSessionMessages, compileComputedFormula, compileRollupAttribute, computeByteMagnitude, conversationDisplayTitle, createFlagRegistry, createFlagService, createStandardSchemaProps, currency, customDataChunkSchemas, date, dateInTimezone, dateValueStart, defineOperation, definePresentation, deriveArchitectChanges, deriveInitials, describeAttributeConfig, describeOperationInput, describeOperations, destructiveSchema, detailView, document, durableDateSchema, ensureFieldIds, episodeImpactOf, evaluateComputedAst, evaluateComputedFormula, evaluateComputedFormulaWithResult, evaluateFilterState, evaluateRecordFilterState, extractAttributeNames, extractValueRefs, flagRegistry, focusOf, form, formFieldFlatKey, formFieldKey, formRegistry, formatAttributeValue, formatByteSize, formatComputedResult, formatLocationValue, formula, fromDraftableView, generateDefaultDetailView, generateDefaultListView, getActiveTab, getErrorMessage, getLiveProtocolPayloadChannel, getRecordCreatorPrincipalId, getSlotFieldTargets, getUserDisplayName, group, hasDestructiveEntries, hasOptions, includesAction, inferInverseCardinality, inferRollupReturnType, isAgentUIDataName, isAgentUIMessageBatch, isAttributeSortable2 as isAttributeSortable, isBilateralRelation, isCheckboxEquality, isClaimableSessionStatus, isComputedFunctionName, isDateRangeValue, isDefaultRole, isDetailView, isDocumentAttribute, isEmptyObject, isFieldGroup, isFormDefinition, isFormFieldsRow, isFormFreeFieldRef, isFormHeadingRow, isFormSeparatorRow, isFormSlotFieldRef, isFormTextRow, isLabelExpression, isListView, isLiveEventEnvelope, isLiveEventPayload, isLiveEventPayloadForType, isLiveEventType, isNotEmpty, isOpenToolPartState, isPlainRecord2 as isPlainRecord, isStandardSchema, isTerminalSessionStatus, isTerminalState, isToolApprovalState, isUniversalRelation, jsonFlag, legacyStatusToSessionState, listDescribableNames, listView, liveChannelKey, location, makeFieldId, matchesAccepts, mentionReferenceSchema, modelDefinitionSchema, multiselect, nativeAgentUIPartIdMetadataKey, normalizeDateValue, number, numberFlag, object, orderAgentSessionMessages, parseCountMode, parseLiveChannelKey, parseNativeAgentUIPartIdsMetadata, parseOperation, parseOptionalCountMode, parseQualifiedAttribute, persistedDefaultViewTargetSchema, persistedSchemaPlanSchema, phone, plannedAttributeSchema, plannedInlineAttributeSchema, plannedObjectSchema, presentationOf, proposedDefaultViewTargetSchema, qualifiedPropertyDefs, readFormFieldValue, registry, relation, relationPropertyDefs, renderLabelExpression, resetViewToDefault, resolveAttributeDefaultValue, resolveFieldRequired, resolvePropertyDefinitions, richtext, rollup, rollupToFormulaExpression, schemaPlanSchema, select, sessionStateToLegacyStatus, status, stringFlag, text, toDraftableAttributes, toDraftableObject, toDraftableView, toUndefinedIfEmpty, todoItemSchema, todoPlanSchema, toolImpactSchema, user, validateAttributeName, validateLabelExpression, validateObjectName, validateViewName, viewRegistry, viewStateKey, viewSyncPayload };