@proteos/sdk 0.61.0 → 0.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{chunk-OOOTPEJK.js → chunk-3VQQEJV6.js} +71 -11
  2. package/dist/chunk-3VQQEJV6.js.map +1 -0
  3. package/dist/{chunk-25PD6TYH.cjs → chunk-C4CH6CEY.cjs} +75 -10
  4. package/dist/chunk-C4CH6CEY.cjs.map +1 -0
  5. package/dist/index.cjs +379 -130
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +813 -81
  8. package/dist/index.d.ts +813 -81
  9. package/dist/index.js +250 -13
  10. package/dist/index.js.map +1 -1
  11. package/dist/meta/index.cjs +109 -89
  12. package/dist/meta/index.d.cts +1 -1
  13. package/dist/meta/index.d.ts +1 -1
  14. package/dist/meta/index.js +1 -1
  15. package/dist/{types-DQmqR_G8.d.cts → types-Dp-AB2QZ.d.cts} +561 -48
  16. package/dist/{types-DQmqR_G8.d.ts → types-Dp-AB2QZ.d.ts} +561 -48
  17. package/package.json +3 -3
  18. package/src/agent/session-types.ts +8 -1
  19. package/src/agent/sessions.ts +6 -4
  20. package/src/agent/types.ts +9 -0
  21. package/src/auth/platform-entities.ts +6 -0
  22. package/src/client.ts +28 -4
  23. package/src/conversation/index.ts +327 -15
  24. package/src/conversation/types.ts +594 -5
  25. package/src/data/entity-indexes.ts +54 -0
  26. package/src/data/index.ts +12 -0
  27. package/src/data/types.ts +66 -0
  28. package/src/errors.ts +5 -0
  29. package/src/index.ts +57 -0
  30. package/src/meta/components.ts +23 -3
  31. package/src/meta/index.ts +8 -0
  32. package/src/meta/layout/common-props.ts +9 -0
  33. package/src/meta/layout/elements.ts +57 -0
  34. package/src/meta/layout/index.ts +5 -0
  35. package/src/meta/layout/page-layout.ts +15 -3
  36. package/src/meta/types.ts +206 -21
  37. package/src/scheduling/types.ts +5 -1
  38. package/src/workflow/types.ts +10 -2
  39. package/dist/chunk-25PD6TYH.cjs.map +0 -1
  40. package/dist/chunk-OOOTPEJK.js.map +0 -1
package/src/meta/types.ts CHANGED
@@ -657,6 +657,24 @@ export interface EntityContactBindingInput {
657
657
  duplicate_policy?: ContactBindingDuplicatePolicy
658
658
  }
659
659
 
660
+ /**
661
+ * A composite unique constraint: no two records may share the same values for
662
+ * `attributes` (2+). One-attribute constraints are `is_unique` on the
663
+ * attribute. Enforced as a unique index on the record table; a violating write
664
+ * fails with 409 `record_unique_violation` naming the constraint.
665
+ */
666
+ export interface UniqueConstraint {
667
+ /** snake_case, unique within the entity. */
668
+ name: string
669
+ /** Attribute names or object paths (`address.city`); never platform columns. */
670
+ attributes: string[]
671
+ }
672
+
673
+ export const UniqueConstraintSchema = z.object({
674
+ name: z.string(),
675
+ attributes: z.array(z.string()),
676
+ })
677
+
660
678
  export interface Entity extends AuditFields {
661
679
  slug: string
662
680
  name: string
@@ -689,6 +707,8 @@ export interface Entity extends AuditFields {
689
707
  */
690
708
  title_template: string
691
709
  attributes: Attribute[]
710
+ /** Composite unique constraints; absent when none are declared. */
711
+ unique_constraints?: UniqueConstraint[]
692
712
  }
693
713
 
694
714
  export const EntitySchema = AuditFieldsSchema.extend({
@@ -706,6 +726,7 @@ export const EntitySchema = AuditFieldsSchema.extend({
706
726
  // the wire.
707
727
  title_template: z.string().default(''),
708
728
  attributes: z.array(AttributeSchema),
729
+ unique_constraints: z.array(UniqueConstraintSchema).optional(),
709
730
  })
710
731
 
711
732
  /**
@@ -753,6 +774,11 @@ export interface CreateEntityRequest {
753
774
  description: string
754
775
  title_template?: string
755
776
  attributes: Attribute[]
777
+ /**
778
+ * Composite unique constraints. Full-replacement on upsert: omitted means
779
+ * none (the `is_unique` ones travel with their attributes).
780
+ */
781
+ unique_constraints?: UniqueConstraint[]
756
782
  }
757
783
 
758
784
  /**
@@ -771,6 +797,8 @@ export interface UpdateEntityRequest {
771
797
  description?: string
772
798
  title_template?: string
773
799
  attributes?: Attribute[]
800
+ /** Omitted leaves the stored list alone; a list (empty included) replaces it. */
801
+ unique_constraints?: UniqueConstraint[]
774
802
  }
775
803
 
776
804
  // ============================================================================
@@ -905,6 +933,14 @@ export interface Component extends AuditFields {
905
933
  bundle_file_id: string
906
934
  /** FK to a tar.gz of the component source directory in storage (provenance / rebuild). Empty until deployed. */
907
935
  source_file_id: string
936
+ /**
937
+ * Content address of the compiled bundle, `sha256:<hex>`, stamped server-side
938
+ * at deploy. Lets `pro module deploy` skip an unchanged upload and lets the
939
+ * runtime fetch the bundle under an immutable URL
940
+ * ({@link ComponentService.bundleUrl}). Absent on rows deployed before
941
+ * checksum stamping.
942
+ */
943
+ bundle_checksum?: string
908
944
  /** The component's JSON Schema, driving the page-designer props editor + runtime validation. `null` until set. */
909
945
  props_schema: Record<string, unknown> | null
910
946
  /**
@@ -914,6 +950,13 @@ export interface Component extends AuditFields {
914
950
  * `functions.actions.invokePublic`.
915
951
  */
916
952
  is_public: boolean
953
+ /**
954
+ * Height in px the host reserves for a placement of this component before
955
+ * it has rendered — when the page element sets no `reserved_height` and no
956
+ * earlier visit is remembered. Declared in the component's manifest.
957
+ * Absent / 0 = undeclared, the host default applies.
958
+ */
959
+ reserved_height?: number
917
960
  }
918
961
 
919
962
  export const ComponentSchema = AuditFieldsSchema.extend({
@@ -923,6 +966,8 @@ export const ComponentSchema = AuditFieldsSchema.extend({
923
966
  module_slug: z.string(),
924
967
  bundle_file_id: z.string(),
925
968
  source_file_id: z.string(),
969
+ bundle_checksum: z.string().optional(),
970
+ reserved_height: z.number().int().nonnegative().optional(),
926
971
  // default(false): rows serialized before the flag existed lack the field.
927
972
  props_schema: z.record(z.unknown()).nullable(),
928
973
  is_public: z.boolean().default(false),
@@ -950,6 +995,8 @@ export interface CreateComponentRequest {
950
995
  props_schema?: Record<string, unknown>
951
996
  /** See {@link Component.is_public}. Manifest-driven: omitting it sets false. */
952
997
  is_public?: boolean
998
+ /** See {@link Component.reserved_height}. Manifest-driven: omitting it sets 0. */
999
+ reserved_height?: number
953
1000
  }
954
1001
 
955
1002
  /**
@@ -962,6 +1009,7 @@ export interface UpdateComponentRequest {
962
1009
  source_file_id?: string
963
1010
  props_schema?: Record<string, unknown>
964
1011
  is_public?: boolean
1012
+ reserved_height?: number
965
1013
  }
966
1014
 
967
1015
  // ============================================================================
@@ -1036,20 +1084,47 @@ export {
1036
1084
  // ============================================================================
1037
1085
 
1038
1086
  /**
1039
- * What a page toolbar button invokes. Absent normalizes to `action` (pages
1087
+ * What an action button invokes. Absent normalizes to `action` (buttons
1040
1088
  * persisted before `kind` existed).
1041
1089
  */
1042
- export type PageActionKind = 'action' | 'workflow'
1090
+ export type PageActionKind = 'action' | 'workflow' | 'agent' | 'intent' | 'link'
1091
+
1092
+ export const PageActionKindSchema = z.enum(['action', 'workflow', 'agent', 'intent', 'link'])
1093
+
1094
+ /** What a `kind: intent` button prepares — the command palette's intent names. */
1095
+ export type PageActionIntent = 'create_record' | 'update_record'
1043
1096
 
1044
1097
  /**
1045
- * Page action definition — one toolbar button. `kind: action` invokes a
1046
- * function-service Action by slug (`action`) and may prefill its params;
1047
- * `kind: workflow` starts a manual run of a workflow by key (`workflow`) and
1048
- * may prefill its manual-trigger inputs. `params` / `inputs` map target field
1049
- * names to Liquid templates rendered against the page scope
1050
- * `{ record, entity, params, user }`; a resolved field is locked in the invoke
1051
- * dialog. `skip_confirmation` fires the target immediately when every required
1052
- * field resolved from the templates.
1098
+ * One action button — a page's or a list's toolbar button, or a conversation
1099
+ * type's next step (a live call's quick action, the wrap-up's "Next steps").
1100
+ * Which target it invokes follows from `kind`:
1101
+ *
1102
+ * - `action` → `action` (slug) + `params`
1103
+ * - `workflow` → `workflow` (key) + `inputs`
1104
+ * - `agent` → `agent` (key) + `prompt` + `context`: opens an Ava chat with
1105
+ * that agent; `prompt` becomes the visible first message (the label when
1106
+ * empty), `context` is handed to the model alongside it and never shown.
1107
+ * - `intent` → `intent` + `entity` (+ `record`) + `prompt` + `context`:
1108
+ * prepares a record proposal (one model call), shows it as an editable
1109
+ * review and saves only what the person confirms. `update_record` targets
1110
+ * `record` when set, else the surface's linked record of `entity`.
1111
+ * - `link` → `url`: opens the rendered address in a new browser tab
1112
+ * (http, https, mailto and tel only). Renders synchronously on the press,
1113
+ * so `| summarize` renders '' there.
1114
+ *
1115
+ * `params` / `inputs` map target field names to Liquid templates; `prompt`,
1116
+ * `context`, `entity`, `record` and `url` are Liquid templates too. Everything
1117
+ * renders client-side against the surface's scope (a page:
1118
+ * `{ record, entity, params, current_user }`; a conversation:
1119
+ * `{ conversation, contact, records, records_by_entity, tags,
1120
+ * tags_by_definition, brief, current_user }`, where `| summarize: "<lens>"`
1121
+ * on the conversation or a tag writes a focused summary of what was said when
1122
+ * the button is pressed). `prompt` is literal message TEXT, never a Prompt
1123
+ * resource key. `visible_when` hides the button unless the surface's subject
1124
+ * matches (the record on a page, the whole scope on a conversation — the
1125
+ * stage is `conversation.status eq active` / `in ended|archived`, a detected
1126
+ * tag `tags_by_definition.<key> not_empty`). `skip_confirmation` fires an
1127
+ * action/workflow immediately when every required field resolved.
1053
1128
  */
1054
1129
  export interface PageAction {
1055
1130
  label: string
@@ -1057,9 +1132,17 @@ export interface PageAction {
1057
1132
  kind?: PageActionKind
1058
1133
  action?: string
1059
1134
  workflow?: string
1135
+ agent?: string
1136
+ intent?: PageActionIntent
1137
+ entity?: string
1138
+ record?: string
1139
+ url?: string
1060
1140
  params?: Record<string, string>
1061
1141
  inputs?: Record<string, string>
1142
+ prompt?: string
1143
+ context?: string
1062
1144
  skip_confirmation?: boolean
1145
+ visible_when?: FilterGroup
1063
1146
  /** List-extension stamp on a toolbar action a list extension appended to its host list. */
1064
1147
  extension_key?: string
1065
1148
  }
@@ -1067,12 +1150,20 @@ export interface PageAction {
1067
1150
  export const PageActionSchema = z.object({
1068
1151
  label: z.string(),
1069
1152
  icon: z.string(),
1070
- kind: z.enum(['action', 'workflow']).optional(),
1153
+ kind: PageActionKindSchema.optional(),
1071
1154
  action: z.string().optional(),
1072
1155
  workflow: z.string().optional(),
1156
+ agent: z.string().optional(),
1157
+ intent: z.enum(['create_record', 'update_record']).optional(),
1158
+ entity: z.string().optional(),
1159
+ record: z.string().optional(),
1160
+ url: z.string().optional(),
1073
1161
  params: z.record(z.string()).optional(),
1074
1162
  inputs: z.record(z.string()).optional(),
1163
+ prompt: z.string().optional(),
1164
+ context: z.string().optional(),
1075
1165
  skip_confirmation: z.boolean().optional(),
1166
+ visible_when: FilterGroupSchema.optional(),
1076
1167
  extension_key: z.string().optional(),
1077
1168
  })
1078
1169
 
@@ -1255,10 +1346,46 @@ export interface UpdateListViewRequest {
1255
1346
  * - `public`: standalone, NO app chrome (bare page at `/p/…`);
1256
1347
  * UNAUTHENTICATED — the layout is world-readable and its components may only
1257
1348
  * call `is_public` global actions.
1349
+ * - `trigger`: what the person sees when they trigger an action or a
1350
+ * workflow — rendered inside the invoke dialog. Bound by `kind` +
1351
+ * `reference` to ONE invocable; its `field` elements bind to that
1352
+ * invocable's params and returns instead of an entity's attributes. Which
1353
+ * dialog phase a trigger page renders in is the app configuration's binding
1354
+ * (`action_pages` / `workflow_pages`), like which record mode a record page
1355
+ * opens in (`record_pages`).
1356
+ */
1357
+ export type PageType = 'record' | 'platform' | 'kiosk' | 'public' | 'trigger'
1358
+
1359
+ export const PageTypeSchema = z.enum(['record', 'platform', 'kiosk', 'public', 'trigger'])
1360
+
1361
+ /**
1362
+ * How the viewer interacts with a record page — the `mode` the Liquid scope
1363
+ * and the component protocol carry (the same three words as `PageMode` in
1364
+ * `@proteos/component-sdk`). A record page serves every mode; which page a
1365
+ * mode opens in is the app configuration's `record_pages` binding.
1366
+ *
1367
+ * - `view`: a read-only record page.
1368
+ * - `create`: the form for a record that is not saved yet.
1369
+ * - `edit`: the form over a saved record.
1258
1370
  */
1259
- export type PageType = 'record' | 'platform' | 'kiosk' | 'public'
1371
+ export type PageMode = 'view' | 'create' | 'edit'
1260
1372
 
1261
- export const PageTypeSchema = z.enum(['record', 'platform', 'kiosk', 'public'])
1373
+ /**
1374
+ * Where an invocation is in the invoke dialog's lifecycle — the `phase` the
1375
+ * dialog's Liquid scope and component protocol carry, and the key of a
1376
+ * `TriggerPageBinding`. Orthogonal to `PageMode`: the input phase renders in
1377
+ * `create` mode, running and result in `view` mode. A trigger page serves
1378
+ * every phase; which page a phase renders is the app configuration's binding.
1379
+ *
1380
+ * - `input`: the form (and the confirm step, rendered read-only) over the
1381
+ * params.
1382
+ * - `running`: while the invoke call runs; for a workflow, the "started" page
1383
+ * after the run was accepted. The params, read-only; the scope also carries
1384
+ * `execution` for workflows.
1385
+ * - `result`: once the action returned (the params plus its returns) or the
1386
+ * workflow run reached a terminal status (`execution` in scope).
1387
+ */
1388
+ export type TriggerPhase = 'input' | 'running' | 'result'
1262
1389
 
1263
1390
  /**
1264
1391
  * Page configuration. A `record` page is the detail-page shape for a single
@@ -1273,8 +1400,13 @@ export interface Page extends AuditFields {
1273
1400
  name: string
1274
1401
  module_slug: string
1275
1402
  type: PageType
1276
- /** Required for `record` pages; absent on `platform` pages. */
1403
+ /** Required for `record` pages; absent on every other type. */
1277
1404
  entity_slug?: string
1405
+ /** Trigger pages only: what the page opens for — `action` (an action slug)
1406
+ * or `workflow` (a workflow key). Absent = `action`. Immutable. */
1407
+ kind?: PageActionKind
1408
+ /** Trigger pages only: the action slug / workflow key. Immutable. */
1409
+ reference?: string
1278
1410
  actions: PageAction[]
1279
1411
  layout: PageLayout
1280
1412
  }
@@ -1285,6 +1417,8 @@ export const PageSchema = AuditFieldsSchema.extend({
1285
1417
  module_slug: z.string(),
1286
1418
  type: PageTypeSchema,
1287
1419
  entity_slug: z.string().optional(),
1420
+ kind: PageActionKindSchema.optional(),
1421
+ reference: z.string().optional(),
1288
1422
  actions: z.array(PageActionSchema),
1289
1423
  layout: PageLayoutSchema,
1290
1424
  })
@@ -1297,6 +1431,10 @@ export const PageSchema = AuditFieldsSchema.extend({
1297
1431
  export interface PublicPageComponent {
1298
1432
  slug: string
1299
1433
  props_schema?: Record<string, unknown>
1434
+ /** Content address of the compiled bundle (`sha256:<hex>`), for the immutable bundle URL. */
1435
+ bundle_checksum?: string
1436
+ /** See {@link Component.reserved_height}. */
1437
+ reserved_height?: number
1300
1438
  }
1301
1439
 
1302
1440
  /**
@@ -1318,12 +1456,16 @@ export interface ListPagesOptions extends MetaListOptions {
1318
1456
  module_slug?: string
1319
1457
  type?: PageType
1320
1458
  entity_slug?: string
1459
+ /** The trigger pages of one invocable. */
1460
+ kind?: PageActionKind
1461
+ reference?: string
1321
1462
  }
1322
1463
 
1323
1464
  /**
1324
1465
  * Request to create a page. `type` defaults to `record` when omitted.
1325
- * `entity_slug` is required for record pages and must be absent for platform
1326
- * pages.
1466
+ * `entity_slug` is required for record pages and must be absent for every
1467
+ * other type. Trigger pages set `reference` (and `kind`, which defaults to
1468
+ * `action`); no other type may.
1327
1469
  */
1328
1470
  export interface CreatePageRequest {
1329
1471
  slug: string
@@ -1331,6 +1473,8 @@ export interface CreatePageRequest {
1331
1473
  module_slug?: string
1332
1474
  type?: PageType
1333
1475
  entity_slug?: string
1476
+ kind?: PageActionKind
1477
+ reference?: string
1334
1478
  actions: PageAction[]
1335
1479
  layout: PageLayout
1336
1480
  }
@@ -1832,6 +1976,37 @@ export const AppHomeSchema = z.object({
1832
1976
  reference: z.string(),
1833
1977
  })
1834
1978
 
1979
+ /**
1980
+ * The record pages one entity opens in, per mode (`PageMode`). Every key
1981
+ * optional; the web falls back create → edit → view → the entity's first
1982
+ * record page. Strict object on the wire — no string shorthand.
1983
+ */
1984
+ export interface RecordPageBinding {
1985
+ view?: string
1986
+ create?: string
1987
+ edit?: string
1988
+ }
1989
+
1990
+ export const RecordPageBindingSchema = z
1991
+ .object({ view: z.string().optional(), create: z.string().optional(), edit: z.string().optional() })
1992
+ .strict()
1993
+
1994
+ /**
1995
+ * The trigger pages one action / workflow opens, per dialog phase
1996
+ * (`TriggerPhase`). Every key optional; an unbound phase falls back to the
1997
+ * invocable's first trigger page, then to the dialog's generated layout. One
1998
+ * page may serve every phase. Strict object on the wire.
1999
+ */
2000
+ export interface TriggerPageBinding {
2001
+ input?: string
2002
+ running?: string
2003
+ result?: string
2004
+ }
2005
+
2006
+ export const TriggerPageBindingSchema = z
2007
+ .object({ input: z.string().optional(), running: z.string().optional(), result: z.string().optional() })
2008
+ .strict()
2009
+
1835
2010
  /**
1836
2011
  * AppConfiguration — a TYPED binding row: "how app X presents itself" to
1837
2012
  * everyone (`profile_slug: ''` = the app's default configuration) or to one
@@ -1855,8 +2030,12 @@ export interface AppConfiguration extends AuditFields {
1855
2030
  default_agent_key?: string
1856
2031
  /** Agents offered in this app; empty = every org agent. */
1857
2032
  agent_keys?: string[]
1858
- /** entity_slug → record page slug opened from this app. */
1859
- record_pages?: Record<string, string>
2033
+ /** entity_slug → the record pages opened from this app, per mode. */
2034
+ record_pages?: Record<string, RecordPageBinding>
2035
+ /** action slug → the trigger pages its invoke dialog renders, per phase. */
2036
+ action_pages?: Record<string, TriggerPageBinding>
2037
+ /** workflow key → the trigger pages its invoke dialog renders, per phase. */
2038
+ workflow_pages?: Record<string, TriggerPageBinding>
1860
2039
  /** Entity slugs the command palette searches (by record title) inside
1861
2040
  * this app; empty = no record search. */
1862
2041
  searchable_entities?: string[]
@@ -1872,7 +2051,9 @@ export const AppConfigurationSchema = AuditFieldsSchema.extend({
1872
2051
  menu_slug: z.string().optional(),
1873
2052
  default_agent_key: z.string().optional(),
1874
2053
  agent_keys: z.array(z.string()).optional(),
1875
- record_pages: z.record(z.string()).optional(),
2054
+ record_pages: z.record(RecordPageBindingSchema).optional(),
2055
+ action_pages: z.record(TriggerPageBindingSchema).optional(),
2056
+ workflow_pages: z.record(TriggerPageBindingSchema).optional(),
1876
2057
  searchable_entities: z.array(z.string()).optional(),
1877
2058
  })
1878
2059
 
@@ -1897,7 +2078,9 @@ export interface CreateAppConfigurationRequest {
1897
2078
  menu_slug?: string
1898
2079
  default_agent_key?: string
1899
2080
  agent_keys?: string[]
1900
- record_pages?: Record<string, string>
2081
+ record_pages?: Record<string, RecordPageBinding>
2082
+ action_pages?: Record<string, TriggerPageBinding>
2083
+ workflow_pages?: Record<string, TriggerPageBinding>
1901
2084
  searchable_entities?: string[]
1902
2085
  }
1903
2086
 
@@ -1911,7 +2094,9 @@ export interface UpdateAppConfigurationRequest {
1911
2094
  menu_slug?: string
1912
2095
  default_agent_key?: string
1913
2096
  agent_keys?: string[]
1914
- record_pages?: Record<string, string>
2097
+ record_pages?: Record<string, RecordPageBinding>
2098
+ action_pages?: Record<string, TriggerPageBinding>
2099
+ workflow_pages?: Record<string, TriggerPageBinding>
1915
2100
  searchable_entities?: string[]
1916
2101
  }
1917
2102
 
@@ -435,7 +435,7 @@ export interface SlotParameters {
435
435
  }
436
436
 
437
437
  /**
438
- * Asks for the bookable starts of some hosts in [from, to) (≤ 31 days).
438
+ * Asks for the bookable starts of some hosts in [from, to) (≤ 42 days).
439
439
  * Exactly one of type_key | link_key | parameters governs the rules;
440
440
  * assignment picks union (single / round_robin) or intersection (collective).
441
441
  * timezone is the requester's zone: slots are grouped by its local day.
@@ -528,6 +528,8 @@ export interface ListCalendarEventsQuery {
528
528
  record_entity_slug?: string
529
529
  record_id?: string
530
530
  contact_id?: string
531
+ /** The instance(s) of one provider event, by iCalendar UID. */
532
+ ical_uid?: string
531
533
  is_deleted_included?: boolean
532
534
  }
533
535
 
@@ -658,6 +660,8 @@ export interface UpdateSchedulingLinkRequest {
658
660
  export interface ListSchedulingLinksQuery {
659
661
  /** Links offering this type. */
660
662
  type_key?: string
663
+ /** Links listing this user among their hosts. */
664
+ host_user_id?: string
661
665
  is_public?: boolean
662
666
  is_enabled?: boolean
663
667
  search?: string
@@ -71,8 +71,11 @@ export interface WorkflowNode {
71
71
  export const DEFAULT_PORT = 'main'
72
72
 
73
73
  /**
74
- * The reserved output-port key the `on_error: continue_error_output` policy
75
- * routes failed items to, when the node's descriptor declares it.
74
+ * The reserved output-port key every non-trigger node implicitly has. Under
75
+ * `on_error: continue_error_output` the engine emits one item per input item
76
+ * on it: the input's `json` plus an `error` object (`code`, `message`,
77
+ * `details`, `is_user_error`), paired to the input index. Descriptors never
78
+ * declare this port.
76
79
  */
77
80
  export const ERROR_PORT = 'error'
78
81
 
@@ -265,6 +268,11 @@ export interface NodeDescriptor {
265
268
  documentation_url?: string
266
269
  /** Liquid over parameters, shown on the canvas node card. */
267
270
  subtitle?: string
271
+ /**
272
+ * Retry policy a node of this type runs with when the graph node sets none.
273
+ * Non-idempotent types pin `max_attempts: 1`; absent = engine defaults.
274
+ */
275
+ default_retry?: NodeRetryPolicy
268
276
  }
269
277
 
270
278
  /** Registry lifecycle of one (type, version) row. */