@opencxh/domain 1.171.0 → 1.172.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/entities/activity/blocks.d.ts +30 -30
  2. package/dist/entities/activity/catalog.d.ts +63 -86
  3. package/dist/entities/activity/descriptor.d.ts +31 -32
  4. package/dist/entities/activity/index.d.ts +2 -2
  5. package/dist/entities/activity/preview.d.ts +7 -7
  6. package/dist/entities/activity/resolve.d.ts +37 -38
  7. package/dist/entities/activity/types.d.ts +34 -34
  8. package/dist/entities/ai-account/types.d.ts +3 -3
  9. package/dist/entities/ai-account/vendors.d.ts +25 -32
  10. package/dist/entities/ai-budget/types.d.ts +12 -8
  11. package/dist/entities/ai-conversation/types.d.ts +12 -12
  12. package/dist/entities/ai-profile/types.d.ts +21 -26
  13. package/dist/entities/ai-settings/types.d.ts +12 -13
  14. package/dist/entities/analytics/dashboard.d.ts +1 -1
  15. package/dist/entities/analytics/index.d.ts +4 -4
  16. package/dist/entities/analytics/source.d.ts +1 -1
  17. package/dist/entities/analytics/usage.d.ts +23 -28
  18. package/dist/entities/artifact/blocks.d.ts +54 -69
  19. package/dist/entities/artifact/markdown.d.ts +2 -3
  20. package/dist/entities/artifact/types.d.ts +47 -55
  21. package/dist/entities/assignment/types.d.ts +74 -88
  22. package/dist/entities/calendar-event/types.d.ts +1 -1
  23. package/dist/entities/channel/index.d.ts +1 -1
  24. package/dist/entities/channel/signature.d.ts +8 -9
  25. package/dist/entities/communication/index.d.ts +1 -1
  26. package/dist/entities/communication/message-template.d.ts +1 -1
  27. package/dist/entities/company/types.d.ts +1 -1
  28. package/dist/entities/contact/index.d.ts +1 -1
  29. package/dist/entities/contact/provider.d.ts +2 -1
  30. package/dist/entities/contact/types.d.ts +1 -10
  31. package/dist/entities/custom-field-def/types.d.ts +14 -14
  32. package/dist/entities/external-identity/types.d.ts +45 -50
  33. package/dist/entities/interaction/index.d.ts +1 -1
  34. package/dist/entities/interaction/types.d.ts +44 -47
  35. package/dist/entities/live-lens/types.d.ts +39 -44
  36. package/dist/entities/mcp/types.d.ts +53 -57
  37. package/dist/entities/memory/alias.d.ts +7 -7
  38. package/dist/entities/memory/browse.d.ts +21 -21
  39. package/dist/entities/memory/ingest.d.ts +26 -17
  40. package/dist/entities/memory/item.d.ts +53 -58
  41. package/dist/entities/memory/kind.d.ts +26 -26
  42. package/dist/entities/memory/query.d.ts +49 -51
  43. package/dist/entities/playbook/actor.d.ts +20 -19
  44. package/dist/entities/playbook/assignment.d.ts +54 -63
  45. package/dist/entities/playbook/index.d.ts +2 -2
  46. package/dist/entities/playbook/labels.d.ts +4 -4
  47. package/dist/entities/playbook/trigger-vars.d.ts +14 -15
  48. package/dist/entities/playbook/types.d.ts +173 -303
  49. package/dist/entities/resource-reminder/types.d.ts +8 -9
  50. package/dist/entities/scope/actor.d.ts +16 -0
  51. package/dist/entities/{note → scope}/index.d.ts +1 -0
  52. package/dist/entities/scope/scope.test.d.ts +1 -0
  53. package/dist/entities/scope/types.d.ts +53 -0
  54. package/dist/entities/task/types.d.ts +1 -1
  55. package/dist/entities/time-entry/duration.d.ts +11 -11
  56. package/dist/entities/time-entry/types.d.ts +60 -60
  57. package/dist/entities/time-entry/work-type.d.ts +21 -24
  58. package/dist/entities/topic/examples.d.ts +26 -27
  59. package/dist/entities/topic/scope.d.ts +11 -12
  60. package/dist/entities/topic/types.d.ts +28 -28
  61. package/dist/entities/user/types.d.ts +24 -28
  62. package/dist/entities/webhook/types.d.ts +6 -6
  63. package/dist/entities/work/keys.d.ts +25 -26
  64. package/dist/entities/work/ladder.d.ts +48 -52
  65. package/dist/entities/work/types.d.ts +109 -115
  66. package/dist/index.cjs +6 -6
  67. package/dist/index.d.ts +29 -33
  68. package/dist/index.js +1391 -1254
  69. package/dist/platform/account.d.ts +34 -38
  70. package/dist/platform/ai-tools.d.ts +48 -52
  71. package/dist/platform/api.d.ts +9 -8
  72. package/dist/platform/author.d.ts +7 -9
  73. package/dist/platform/capabilities.d.ts +3 -3
  74. package/dist/platform/communication.d.ts +163 -204
  75. package/dist/platform/context.d.ts +8 -8
  76. package/dist/platform/identity.d.ts +16 -19
  77. package/dist/platform/kernel.d.ts +1 -1
  78. package/dist/platform/manifest.d.ts +2 -2
  79. package/dist/platform/media.d.ts +13 -15
  80. package/dist/platform/permission.d.ts +39 -0
  81. package/dist/platform/permission.test.d.ts +1 -0
  82. package/dist/platform/presence.d.ts +30 -30
  83. package/dist/platform/provider.d.ts +14 -76
  84. package/dist/platform/resource-source.d.ts +43 -45
  85. package/dist/platform/resource.d.ts +17 -23
  86. package/dist/platform/scope.d.ts +36 -62
  87. package/dist/platform/services.d.ts +4 -4
  88. package/dist/platform/settings.d.ts +0 -14
  89. package/dist/platform/storage.d.ts +2 -2
  90. package/dist/platform/sync-source.d.ts +196 -216
  91. package/dist/platform/transcript-cadence.d.ts +37 -41
  92. package/dist/platform/ui.d.ts +6 -6
  93. package/dist/text/endpoint.d.ts +11 -27
  94. package/package.json +3 -5
  95. package/dist/entities/note/types.d.ts +0 -14
  96. package/dist/entities/shopify/index.d.ts +0 -1
  97. package/dist/entities/shopify/types.d.ts +0 -79
  98. package/dist/platform/lifecycle.d.ts +0 -13
  99. package/dist/platform/reactive.d.ts +0 -13
  100. package/dist/platform/sdk.d.ts +0 -182
  101. package/dist/platform/service-registry.d.ts +0 -13
@@ -1,18 +1,17 @@
1
- import { ActivityChannelKind, ActivityShape } from './catalog';
2
1
  import { ActivityBlock } from './blocks';
2
+ import { ActivityChannelKind, ActivityShape } from './catalog';
3
3
  import { ActivityTypeDescriptor } from './descriptor';
4
4
  import { Activity } from './types';
5
5
  /**
6
- * Eén antwoord over een activity-type, ongeacht of het van ons is of van een app.
6
+ * One answer about an activity type, whether it is ours or an app's.
7
7
  *
8
- * De ingebouwde catalogus en een gedeclareerde descriptor beschrijven hetzelfde, maar in
9
- * een andere vorm: de eerste gebruikt functies (die geen HTTP-hop overleven), de tweede
10
- * vertaalsleutels. Deze laag vlakt dat verschil af, zodat de feed, de inboxlijst en de
11
- * playbook-builder niet elk hun eigen "is het van ons of niet?"-tak krijgen — precies de
12
- * tweedeling die dit hele traject wilde vermijden.
8
+ * The built-in catalog and a declared descriptor describe the same thing in a different shape: the
9
+ * first uses functions (which do not survive an HTTP hop), the second translation keys. This layer
10
+ * flattens that difference, so the feed, the inbox list and the playbook builder do not each grow
11
+ * their own "is it ours or not?" branch — exactly the split this whole effort wanted to avoid.
13
12
  *
14
- * Ingebouwd wint bij een botsing. Een app die `EMAIL_RECEIVED` claimt kan de mailweergave
15
- * dus niet kapen.
13
+ * Built-in wins on a collision. An app claiming `EMAIL_RECEIVED` therefore cannot hijack the mail
14
+ * view.
16
15
  */
17
16
  export interface ResolvedActivityType {
18
17
  type: string;
@@ -24,65 +23,65 @@ export interface ResolvedActivityType {
24
23
  carriesText: boolean;
25
24
  triggerable: boolean;
26
25
  component?: string;
27
- /** True voor de 41 types die het platform zelf meebrengt. */
26
+ /** True for the 41 types the platform brings itself. */
28
27
  builtIn: boolean;
29
- /** De sleutel voor de naam in keuzelijsten; aanwezig zodra een type triggerbaar is. */
28
+ /** The key for the name in pickers; present as soon as a type is triggerable. */
30
29
  displayNameKey?: string;
31
30
  }
32
- /** Vertaalfunctie voor sleutels uit een meegeleverde locale-bundel. */
31
+ /** Translation function for keys from a supplied locale bundle. */
33
32
  export type Translate = (key: string, params?: Record<string, string>) => string;
34
33
  /**
35
- * Een opzoeker over de ingebouwde types plus wat apps declareerden.
34
+ * A lookup over the built-in types plus whatever apps declared.
36
35
  *
37
- * Bewust een expliciet object en geen module-globale registry: op de server leeft elke
38
- * request in zijn eigen module-instantie, dus een geregistreerde lijst zou daar nooit
39
- * geraakt worden — en dat zou onzichtbaar zijn.
36
+ * Deliberately an explicit object and not a module-global registry: on the server every request
37
+ * lives in its own module instance, so a registered list would never be hit there — and that would
38
+ * be invisible.
40
39
  */
41
40
  export declare class ActivityTypeRegistry {
42
41
  private readonly translate;
43
42
  private readonly declared;
44
43
  constructor(descriptors?: ActivityTypeDescriptor[], translate?: Translate);
45
44
  get(type: string): ResolvedActivityType | undefined;
46
- /** Alles wat als trigger aangeboden mag worden, ingebouwd en gedeclareerd. */
45
+ /** Everything that may be offered as a trigger, built-in and declared. */
47
46
  triggerable(): ResolvedActivityType[];
48
47
  /**
49
- * De tijdlijnregel. Ingebouwd komt uit de catalogus, gedeclareerd uit `text` + de
50
- * meegeleverde vertaling. Zonder bruikbare tekst valt het terug op de ontstreepte
51
- * typenaam — dezelfde regel die de feed altijd al toonde voor onbekende types.
48
+ * The timeline line. Built-in comes from the catalog, declared from `text` plus the supplied
49
+ * translation. Without usable text it falls back to the de-underscored type name — the same line
50
+ * the feed always showed for unknown types.
52
51
  */
53
52
  timelineText(activity: Activity, authorName: string): string;
54
- /** De regel voor de inboxlijst. Leeg wanneer het type niets te tonen heeft. */
53
+ /** The line for the inbox list. Empty when the type has nothing to show. */
55
54
  snippet(activity: Activity): string;
56
- /** De descriptor zoals hij binnenkwam; nodig om `text` als sleutel op te slaan. */
55
+ /** The descriptor as it arrived; needed to store `text` as a key. */
57
56
  descriptor(type: string): ActivityTypeDescriptor | undefined;
58
- /** De declaratieve blokken van een type, als het er heeft. */
57
+ /** A type's declarative blocks, when it has any. */
59
58
  blocks(type: string): ActivityBlock[] | undefined;
60
59
  /**
61
- * Dezelfde semantische vragen als de losse accessors in `catalog.ts`, maar dan óók voor
62
- * types die een app declareerde.
60
+ * The same semantic questions as the standalone accessors in `catalog.ts`, but for types an app
61
+ * declared as well.
63
62
  *
64
- * Dat verschil is de reden dat deze methodes bestaan. `isMessageType(type)` leest alleen
65
- * `ACTIVITY_CATALOG`, dus een gedeclareerd type met `shape: "message"` gaf daar `false` —
66
- * een helpdesk-app kon een berichtsoort meebrengen die vervolgens niet meetelde als
67
- * gesprek, niet antwoordbaar was en niet in de analytics landde. Wie een registry bij de
68
- * hand heeft, hoort deze te gebruiken; wie er geen heeft valt terug op de ingebouwde.
63
+ * That difference is why these methods exist. `isMessageType(type)` reads only
64
+ * `ACTIVITY_CATALOG`, so a declared type with `shape: "message"` returned `false` there — a
65
+ * helpdesk app could bring a message kind that then did not count as a conversation, was not
66
+ * replyable and never landed in the analytics. Anyone with a registry at hand should use these;
67
+ * anyone without falls back to the built-in ones.
69
68
  *
70
- * De regel zelf staat maar op één plek: {@link isMessageShape} en de velden van
69
+ * The rule itself lives in one place: {@link isMessageShape} and the fields of
71
70
  * {@link ResolvedActivityType}.
72
71
  */
73
72
  isMessage(type: string): boolean;
74
- /** Kan een mens hierop antwoorden? Notities niet — die gaan nergens heen. */
73
+ /** Can a person reply to this? Notes cannot — those go nowhere. */
75
74
  isReplyable(type: string): boolean;
76
- /** Leesbare inhoud voor een model: berichten, notities én transcripten. */
75
+ /** Readable content for a model: messages, notes and transcripts. */
77
76
  carriesText(type: string): boolean;
78
- /** Telt mee als in- of uitgaand bericht in de analytics-rollup. */
77
+ /** Counts as an inbound or outbound message in the analytics rollup. */
79
78
  countsAs(type: string): "inbound_message" | "outbound_message" | undefined;
80
- /** `mail` | `chat` | `voice` | `video`, of `undefined` voor een levenscyclus-event. */
79
+ /** `mail` | `chat` | `voice` | `video`, or `undefined` for a lifecycle event. */
81
80
  channelKind(type: string): ActivityChannelKind | undefined;
82
- /** Transcript-achtig artefact: meegeleverde inhoud die leesbare tekst draagt. */
81
+ /** Transcript-like artifact: supplied content carrying readable text. */
83
82
  isTranscript(type: string): boolean;
84
- /** De vertaler die bij deze registry hoort, voor het oplossen van blokteksten. */
83
+ /** The translator belonging to this registry, for resolving block texts. */
85
84
  get translator(): Translate;
86
85
  }
87
- /** De lege registry: alleen de ingebouwde types. Voor code die (nog) geen catalogus laadt. */
86
+ /** The empty registry: built-in types only. For code that does not (yet) load a catalog. */
88
87
  export declare const BUILT_IN_ONLY: ActivityTypeRegistry;
@@ -1,6 +1,6 @@
1
1
  import { ActingIdentity } from '../../platform/identity';
2
- import { AIMessageInput, AIMessageOutput } from '../ai-message/types';
3
2
  import { TranscriptSegment } from '../../platform/media';
3
+ import { AIMessageInput, AIMessageOutput } from '../ai-message/types';
4
4
  export type CallStatus = "new" | "connecting" | "ringing" | "connected" | "held" | "ended" | "failed";
5
5
  export type CallDirection = "inbound" | "outbound";
6
6
  export type CallType = "audio" | "video" | "data" | "screen-share";
@@ -11,9 +11,9 @@ export interface Attachment {
11
11
  mimeType: string;
12
12
  size?: number;
13
13
  url?: string;
14
- /** Content-ID voor inline (cid:) referenties in de body — bare, zonder `<>`. */
14
+ /** Content-ID for inline (cid:) references in the body — bare, without `<>`. */
15
15
  contentId?: string;
16
- /** True wanneer de bijlage inline in de body hoort (cid:), niet als losse chip. */
16
+ /** True when the attachment belongs inline in the body (cid:), not as a separate chip. */
17
17
  isInline?: boolean;
18
18
  }
19
19
  export interface BaseActivity {
@@ -24,12 +24,12 @@ export interface BaseActivity {
24
24
  providerId: string;
25
25
  author: {
26
26
  type: "user" | "contact" | "system" | "app";
27
- /** Provider/account-id (Microsoft user-id, SIP account-id, etc.). */
27
+ /** Provider/account id (Microsoft user id, SIP account id, etc.). */
28
28
  id?: string;
29
29
  name: string;
30
30
  /**
31
- * Resolved-hint naar Contact-entity. Wordt door provider-sync gezet via
32
- * endpoint-lookup. UI mag direct navigeren zonder extra lookup.
31
+ * Resolved hint to a Contact entity. Set by the provider sync through an endpoint lookup. The
32
+ * UI may navigate straight there without an extra lookup.
33
33
  */
34
34
  contactId?: string;
35
35
  };
@@ -37,12 +37,12 @@ export interface BaseActivity {
37
37
  externalIds?: string[];
38
38
  attachments?: Attachment[];
39
39
  /**
40
- * Activity is optimistisch geschreven en wacht op bevestiging vanuit
41
- * provider-sync. Sync zet 'm op `false` zodra de canonieke versie is
42
- * opgehaald. UI kan een "verzenden..." indicator tonen wanneer true.
40
+ * The activity was written optimistically and awaits confirmation from the provider sync. Sync
41
+ * sets it to `false` once the canonical version is fetched. The UI can show a "sending…"
42
+ * indicator while true.
43
43
  */
44
44
  pending?: boolean;
45
- /** Epoch ms — matcht DB-model en Interaction.createdAt. */
45
+ /** Epoch ms — matches the DB model and Interaction.createdAt. */
46
46
  createdAt?: number;
47
47
  updatedAt?: number;
48
48
  }
@@ -166,10 +166,10 @@ export type FileUploadedPayload = {
166
166
  fileId?: string;
167
167
  };
168
168
  /**
169
- * Elke status die `Interaction.status` kan aannemen, `snoozed` inbegrepen. Die ontbrak,
170
- * en daardoor had de tijdlijn een gat precies waar hij het meest verrast: parkeren en
171
- * wakker worden waren de enige twee statuswissels die geen spoor achterlieten, dus een
172
- * gesprek sprong uit en weer in de lijst zonder dat iets vertelde waarom.
169
+ * Every status `Interaction.status` can take, `snoozed` included. That one was missing, leaving
170
+ * the timeline with a gap exactly where it surprises most: snoozing and waking were the only two
171
+ * status changes leaving no trace, so a conversation jumped out of and back into the list without
172
+ * anything saying why.
173
173
  */
174
174
  export type InteractionStatus = "open" | "pending" | "closed" | "snoozed";
175
175
  export type InteractionStatusChangedPayload = {
@@ -206,7 +206,7 @@ export type AIActionProposedPayload = {
206
206
  params?: Record<string, unknown>;
207
207
  }[];
208
208
  status: "pending" | "approved" | "rejected";
209
- /** Namens wie het voorstel is gedaan, zodat de kaart "namens Finance" kan tonen. */
209
+ /** Who the proposal was made on behalf of, so the card can show "on behalf of Finance". */
210
210
  actor?: ActingIdentity;
211
211
  };
212
212
  /** Playbook lifecycle marker in the interaction timeline (system-authored). */
@@ -215,7 +215,7 @@ export type PlaybookLifecyclePayload = {
215
215
  playbookId?: string;
216
216
  playbookName?: string;
217
217
  status?: string;
218
- /** Namens wie de run handelde; voorkomt dat de UI de playbook opnieuw moet ophalen. */
218
+ /** Who the run acted for; saves the UI from fetching the playbook again. */
219
219
  actor?: ActingIdentity;
220
220
  };
221
221
  export type Activity = (BaseActivity & {
@@ -343,34 +343,34 @@ export type Activity = (BaseActivity & {
343
343
  payload: InteractionAssignedPayload;
344
344
  });
345
345
  /**
346
- * Een activity van **welk type dan ook**, inclusief een type dat een app declareerde.
346
+ * An activity of **any type at all**, including a type an app declared.
347
347
  *
348
- * `Activity` is een gesloten unie over de 41 ingebouwde types, en dat is met opzet: alleen zo
349
- * weet TypeScript na `activity.type === "EMAIL_RECEIVED"` dat `payload.from` bestaat. Maar
350
- * `ACTIVITY_TYPE_AUTHORING.md` nodigt apps uit hun eigen type mee te brengen, en zo'n rij
351
- * pást niet in die unie — vandaar de ~40 `as Activity`-casts die door de repo staan.
348
+ * `Activity` is a closed union over the 41 built-in types, deliberately: only that way does
349
+ * TypeScript know after `activity.type === "EMAIL_RECEIVED"` that `payload.from` exists. But
350
+ * `ACTIVITY_TYPE_AUTHORING.md` invites apps to bring their own type, and such a row does not fit
351
+ * that union — hence the ~40 `as Activity` casts across the repo.
352
352
  *
353
- * Een open tak ín `Activity` lost dat niet op: dan wordt `payload` overal een unie met
354
- * `Record<string, unknown>` en verdwijnt precies de versmalling waar de unie voor bestaat.
355
- * Daarom een eigen naam. Code die ook gedeclareerde types verwerkt — de feed, de
356
- * inboxregel, de analytics-rollup — typeert op `AnyActivity` en vraagt de catalogus wat het
357
- * ding is; code die in een payload leest blijft op `Activity` en versmalt.
353
+ * An open arm *inside* `Activity` does not fix it: `payload` would become a union with
354
+ * `Record<string, unknown>` everywhere, removing exactly the narrowing the union exists for. Hence
355
+ * a name of its own. Code that also handles declared types — the feed, the inbox line, the
356
+ * analytics rollup — types on `AnyActivity` and asks the catalog what the thing is; code reading
357
+ * into a payload stays on `Activity` and narrows.
358
358
  */
359
359
  export type AnyActivity = Activity | (BaseActivity & {
360
360
  type: string;
361
361
  payload: Record<string, unknown>;
362
362
  });
363
363
  /**
364
- * Type-guards voor de twee payload-vormen waar de UI rechtstreeks in leest.
364
+ * Type guards for the two payload shapes the UI reads into directly.
365
365
  *
366
- * Dit zijn bewust wél typenamen en geen catalogus-vraag. De catalogus beantwoordt *semantiek*
367
- * ("is dit een bericht", "welk kanaal") en dat hoort nooit als typelijstje in een component.
368
- * Deze twee doen iets anders: ze **versmallen het type**, zodat `activity.payload.from` en
369
- * `activity.payload.text` erna bestaan. Een `channelKindOf(...) === "mail"` kan dat niet — die
370
- * geeft een boolean terug en TypeScript weet daarna nog steeds niet welke payload er ligt.
366
+ * These are deliberately type names and not a catalog question. The catalog answers *semantics*
367
+ * ("is this a message", "which channel") and that never belongs as a type list inside a component.
368
+ * These two do something else: they **narrow the type**, so `activity.payload.from` and
369
+ * `activity.payload.text` exist afterwards. A `channelKindOf(...) === "mail"` cannot do that — it
370
+ * returns a boolean and TypeScript still does not know which payload is there.
371
371
  *
372
- * Ze staan hier, naast de union, zodat er één plek is die de namen kent in plaats van een
373
- * herhaling per component.
372
+ * They live here, next to the union, so one place knows the names instead of a repetition per
373
+ * component.
374
374
  */
375
375
  export declare function isEmailActivity(activity: Activity): activity is Extract<Activity, {
376
376
  type: "EMAIL_RECEIVED" | "EMAIL_SENT";
@@ -4,9 +4,9 @@ export interface AiAccount {
4
4
  vendor: string;
5
5
  apiKey: string;
6
6
  /**
7
- * API-host voor dit account. Alleen in te vullen bij vendors zonder vaste
8
- * host (self-hosted: Ollama, vLLM, een eigen gateway) — bij de rest komt de
9
- * host uit `AI_VENDORS` en wordt dit veld genegeerd.
7
+ * API host for this account. Only fillable for vendors without a fixed host (self-hosted:
8
+ * Ollama, vLLM, a custom gateway) — for the rest the host comes from `AI_VENDORS` and this field
9
+ * is ignored.
10
10
  */
11
11
  baseUrl?: string;
12
12
  isDefaultLlm?: boolean;
@@ -1,61 +1,54 @@
1
1
  /**
2
- * De AI-vendors waar de ai-app een adapter voor heeft.
2
+ * The AI vendors the ai app has an adapter for.
3
3
  *
4
- * Eén bron voor zowel de UI (accountformulier, tabellabels) als de server
5
- * (default-model, API-host). Eerder stonden die lijsten los van elkaar en
6
- * liepen ze uiteen — de UI noemde vendors waarvoor geen adapter bestond.
4
+ * One source for both the UI (account form, table labels) and the server (default model, API
5
+ * host). Those lists used to be separate and drifted apart — the UI named vendors no adapter
6
+ * existed for.
7
7
  *
8
- * Deze catalogus beschrijft *wat* een vendor is. *Hoe* je ertegen praat (welke
9
- * adapterklasse, welk model-filter) staat server-side in `providers/registry`,
10
- * die zich tegen deze lijst verantwoordt: een vendor die hier `"chat"` claimt
11
- * en daar geen chat-adapter heeft, is een testfout.
8
+ * This catalog describes *what* a vendor is. *How* you talk to it (which adapter class, which
9
+ * model filter) lives server-side in `providers/registry`, which answers to this list: a vendor
10
+ * claiming `"chat"` here without a chat adapter there is a test failure.
12
11
  *
13
- * `id` is wat er in `AiAccount.vendor` belandt; die string is dus onderdeel van
14
- * het opslagformaat en mag niet zomaar hernoemd worden.
12
+ * `id` is what ends up in `AiAccount.vendor`, so that string is part of the storage format and
13
+ * must not be renamed casually.
15
14
  */
16
15
  export type AiVendorCapability = "chat" | "transcription" | "embedding";
17
16
  export interface AiVendor {
18
17
  id: string;
19
18
  label: string;
20
- /** Wat deze vendor kan. Bepaalt waar hij in de UI als optie verschijnt. */
19
+ /** What this vendor can do. Decides where it appears as an option in the UI. */
21
20
  capabilities: readonly AiVendorCapability[];
22
- /**
23
- * Model waarmee een aanroep draait die zelf geen model meekrijgt. Afwezig
24
- * voor vendors zonder chat-adapter.
25
- */
21
+ /** Model a call runs on when it carries none itself. Absent for vendors without a chat adapter. */
26
22
  defaultModel?: string;
27
23
  /**
28
- * Vaste API-host. Afwezig betekent dat de user er zelf een moet invullen
29
- * op het account (`AiAccount.baseUrl`) — dat is het geval bij self-hosted
30
- * runtimes en eigen gateways.
24
+ * Fixed API host. Absent means the user has to fill one in on the account (`AiAccount.baseUrl`) —
25
+ * the case for self-hosted runtimes and custom gateways.
31
26
  */
32
27
  baseUrl?: string;
33
28
  /**
34
- * Welke bijlagesoorten deze vendor rechtstreeks aanneemt.
29
+ * Which attachment kinds this vendor accepts directly.
35
30
  *
36
- * Bewust géén waarde in `capabilities`: `findAdapterGaps()` mapt elke
37
- * capability die het niet kent op `"embedding"`, dus een vendor die daar
38
- * `"attachments"` zou claimen wordt gemeld als missende embedding-adapter.
31
+ * Deliberately not a value in `capabilities`: `findAdapterGaps()` maps every capability it does
32
+ * not know to `"embedding"`, so a vendor claiming `"attachments"` there would be reported as a
33
+ * missing embedding adapter.
39
34
  *
40
- * Afwezig of leeg = alleen tekst. Dat is het juiste default voor de
41
- * Chat-Completions-vendors: ze delen één adapter maar niet één set
42
- * mogelijkheden, en een gok levert een 400 midden in een gesprek op.
35
+ * Absent or empty = text only. The right default for the Chat Completions vendors: they share one
36
+ * adapter but not one set of capabilities, and a guess yields a 400 mid-conversation.
43
37
  */
44
38
  attachmentKinds?: readonly ("image" | "pdf")[];
45
39
  }
46
40
  export declare const AI_VENDORS: readonly AiVendor[];
47
41
  export declare function findAiVendor(vendorId: string): AiVendor | undefined;
48
- /** Leesbare naam voor een opgeslagen vendor-id; valt terug op de id zelf. */
42
+ /** Readable name for a stored vendor id; falls back to the id itself. */
49
43
  export declare function aiVendorLabel(vendorId: string): string;
50
44
  /**
51
- * Default-model voor een vendor. De fallback is bewust een bestaand model en
52
- * geen lege string: callers gebruiken dit juist omdat ze zelf geen keuze
53
- * hebben.
45
+ * Default model for a vendor. The fallback is deliberately an existing model and not an empty
46
+ * string: callers use this precisely because they have no choice of their own.
54
47
  */
55
48
  export declare function aiVendorDefaultModel(vendorId: string, fallback?: string): string;
56
- /** Vendors die deze capability aanbieden — voor capability-gefilterde keuzelijsten. */
49
+ /** Vendors offering this capability — for capability-filtered pickers. */
57
50
  export declare function aiVendorsWith(capability: AiVendorCapability): AiVendor[];
58
- /** True wanneer de user zelf een host moet invullen (vendor heeft er geen vaste). */
51
+ /** True when the user has to fill in a host themselves (the vendor has no fixed one). */
59
52
  export declare function aiVendorNeedsBaseUrl(vendorId: string): boolean;
60
- /** Neemt deze vendor deze bijlagesoort aan? Tekst kan altijd — dat is prompt. */
53
+ /** Does this vendor accept this attachment kind? Text always works — that is prompt. */
61
54
  export declare function aiVendorAcceptsAttachment(vendorId: string, kind: "image" | "pdf" | "text"): boolean;
@@ -1,4 +1,4 @@
1
- import { OwnerScope } from '../contact/types';
1
+ import { OwnerScope } from '../scope/types';
2
2
  /**
3
3
  * A ceiling on what may be spent on AI in one period.
4
4
  *
@@ -18,8 +18,12 @@ export interface AiBudget {
18
18
  * tenant, including the ones attributed to nobody (kb indexing, transcription,
19
19
  * playbooks running as the organisation). That unattributed spend is real and
20
20
  * it has to land somewhere.
21
+ *
22
+ * Named `ownerScope` like every other scoped entity. It was `scope` — the one
23
+ * deviation from the platform's convention, where `scope` is reserved for OAuth
24
+ * scopes, an unrelated concept that happens to share the word.
21
25
  */
22
- scope: OwnerScope;
26
+ ownerScope: OwnerScope;
23
27
  /**
24
28
  * Warn here. Absent = never warn, only block. Both absent is allowed and means
25
29
  * the budget does nothing — the UI says so rather than pretending it is armed.
@@ -57,7 +61,7 @@ export type AiBudgetClearable = "softLimitNanos" | "hardLimitNanos";
57
61
  * what an ambiguous sentinel (`0`? that is a real limit) never could.
58
62
  */
59
63
  export interface AiBudgetInput {
60
- scope?: OwnerScope;
64
+ ownerScope?: OwnerScope;
61
65
  softLimitNanos?: number;
62
66
  hardLimitNanos?: number;
63
67
  period?: AiBudgetPeriod;
@@ -118,12 +122,12 @@ export interface AiMyUsage {
118
122
  */
119
123
  export declare function aiBudgetState(budget: Pick<AiBudget, "softLimitNanos" | "hardLimitNanos" | "enabled">, spentNanos: number): AiBudgetState;
120
124
  /**
121
- * "Geen plafond" heeft twee vormen en die moeten hetzelfde betekenen.
125
+ * "No ceiling" has two shapes and they have to mean the same thing.
122
126
  *
123
- * Een gewist plafond wordt als `null` weggeschreven — `undefined` in een `$set`
124
- * laat het veld staan in plaats van het te legen. Bij het teruglezen is `null`
125
- * dus een echte waarde, en `x !== undefined` zou hem als het getal nul opvatten:
126
- * een plafond van nul blokkeert onmiddellijk, zonder dat iemand dat instelde.
127
+ * A cleared ceiling is written as `null` — `undefined` in a `$set` leaves the field standing
128
+ * instead of emptying it. On read-back `null` is therefore a real value, and `x !== undefined`
129
+ * would read it as the number zero: a ceiling of zero blocks immediately, without anyone setting
130
+ * it.
127
131
  */
128
132
  export declare function aiBudgetLimit(value: number | null | undefined): number | undefined;
129
133
  /**
@@ -1,23 +1,23 @@
1
1
  import { AssignmentStatus } from '../assignment/types';
2
2
  export type AIConversationVisibility = "shared" | "personal";
3
3
  /**
4
- * Dat deze draad die van een **agent-opdracht** is, en waar hij bij hoort te verschijnen.
4
+ * That this thread belongs to an **agent assignment**, and where it should appear.
5
5
  *
6
- * De draad van een opdracht leeft op `assignment:<id>` en niet op het onderwerp — dat is precies
7
- * waarom een opdracht meerdere beurten kan overleven terwijl de mensvragen over hetzelfde gesprek
8
- * hun eigen draad houden. Het nadeel was dat er geen enkele ingang naar toe was, behalve de
9
- * agentpagina: het werk was er wel, maar niet te zien op de plek waar het over ging.
6
+ * An assignment's thread lives on `assignment:<id>` and not on the subject — exactly why an
7
+ * assignment can survive several turns while the human questions about the same conversation keep
8
+ * their own thread. The downside was that there was no entrance to it except the agent page: the
9
+ * work was there, but not visible where it was about.
10
10
  *
11
- * Daarom levert `conversation/resolve` de draad van een opdracht ook uit bij de scope van zijn
12
- * **onderwerp**, met dit stempel erop. Niet opgeslagen — het is de stand van nu, gelezen bij het
13
- * ophalen, precies zoals de status van de opdracht zelf.
11
+ * So `conversation/resolve` also delivers an assignment's thread under the scope of its
12
+ * **subject**, with this stamp on it. Not stored — it is the state right now, read on fetch,
13
+ * exactly like the assignment's own status.
14
14
  */
15
15
  export interface AIConversationAgentThread {
16
16
  assignmentId: string;
17
- /** Het `userId` van de agent die deze opdracht doet. */
17
+ /** The `userId` of the agent doing this assignment. */
18
18
  agentId: string;
19
19
  status: AssignmentStatus;
20
- /** De scope waaronder deze draad wordt meegeleverd: het onderwerp van de opdracht. */
20
+ /** The scope this thread is delivered under: the assignment's subject. */
21
21
  subjectScopeKey: string;
22
22
  }
23
23
  /**
@@ -44,8 +44,8 @@ export interface AIConversation {
44
44
  createdAt: number;
45
45
  updatedAt: number;
46
46
  /**
47
- * Gezet bij het ophalen, nooit opgeslagen: deze draad hangt aan een agent-opdracht over de
48
- * gevraagde scope. Aanwezig = meelezen, niet meepraten (zie {@link AIConversationAgentThread}).
47
+ * Set on fetch, never stored: this thread hangs off an agent assignment about the requested
48
+ * scope. Present = read along, not join in (see {@link AIConversationAgentThread}).
49
49
  */
50
50
  agent?: AIConversationAgentThread;
51
51
  }
@@ -1,4 +1,4 @@
1
- import { OwnerScope } from '../contact/types';
1
+ import { OrgTeamScope } from '../scope/types';
2
2
  export interface PredefinedPrompt {
3
3
  name: string;
4
4
  prompt: string;
@@ -7,20 +7,22 @@ export interface AIProfile<T extends Record<string, any> = Record<string, any>>
7
7
  id: string;
8
8
  organizationId: string;
9
9
  /**
10
- * Who may use this profile. Company-wide (`org`) or bound to a `team`; profiles
11
- * are never personal. The server resolves one on create (`normalizeProfileScope`),
12
- * so it is always present.
10
+ * Who may use this profile. Company-wide (`org`) or bound to a `team`; profiles are
11
+ * never personal. The server resolves one on create (`normalizeProfileScope`), so it is
12
+ * always present.
13
+ *
14
+ * "Never personal" was prose while the type allowed it. `OrgTeamScope` states it.
13
15
  */
14
- ownerScope: OwnerScope;
16
+ ownerScope: OrgTeamScope;
15
17
  name: string;
16
18
  description?: string;
17
19
  accountId: string;
18
20
  model: string;
19
21
  providerConfig?: T;
20
22
  /**
21
- * De basisinstructie van dit brein. Optioneel: een profiel dat alleen tools ontsluit heeft
22
- * er geen nodig. Stond hier als verplicht terwijl het schema hem optioneel maakte, waardoor
23
- * elke lezer `?? ""` moest schrijven zonder dat het type dat verklaarde.
23
+ * This brain's base instruction. Optional: a profile that only exposes tools needs none. It was
24
+ * documented as required while the schema made it optional, so every reader had to write `?? ""`
25
+ * without the type explaining why.
24
26
  */
25
27
  systemPrompt?: string;
26
28
  contextIds?: string[];
@@ -28,27 +30,20 @@ export interface AIProfile<T extends Record<string, any> = Record<string, any>>
28
30
  /** Namespaced tool names this profile may use (default: none enabled). */
29
31
  enabledTools?: string[];
30
32
  /**
31
- * Per-tool confirmation policy, stored as a LIST (not a keyed map).
32
- *
33
- * De oorspronkelijke reden was dwingend: de SDK-client transformeerde élke object-key
34
- * camel↔snake, en dat verminkte een genamespacede toolnaam (`communication__compose_email` →
35
- * `communication_ComposeEmail`) zodat hij niet meer matchte met `enabledTools`. **Die transform
36
- * is 17-08-2026 verwijderd**, dus een map zou nu werken.
37
- *
38
- * De lijst blijft staan: hij zit op bestaande profielrijen met een formulier eroverheen, en een
39
- * migratie zou alleen een prettigere vorm opleveren. `enabledTools` ernaast is ook een lijst.
33
+ * Per-tool confirmation policy, stored as a LIST (not a keyed map). It sits on existing profile
34
+ * rows with a form on top, and a migration to a map would only yield a nicer shape;
35
+ * `enabledTools` next to it is a list too.
40
36
  *
41
- * Under autonomy "suggest", write tools are held for approval; reads run freely.
42
- * A tool absent from this list defaults to "write" (safe).
37
+ * Under autonomy "suggest", write tools are held for approval; reads run freely. A tool absent
38
+ * from this list defaults to "write" (safe).
43
39
  *
44
- * **Waar dit wél en níet geldt.** Afgedwongen in `playbook/ai/gate.ts`, en daarmee op elke
45
- * autonome run (workflow of procedure). De interactieve assistent doet er **niets** mee: daar
46
- * bestaat geen bevestigingsstap, en er is ook geen `requiresConfirmation` om aan te haken —
47
- * die stond hier als belofte terwijl er nergens een implementatie was. Een `write`-markering
48
- * die je met een gesprek in de chat verwacht af te dwingen, doet dus niets.
40
+ * **Where this does and does not apply.** Enforced in `playbook/ai/gate.ts`, and thereby on
41
+ * every autonomous run (workflow or procedure). The interactive assistant does **nothing** with
42
+ * it: there is no confirmation step there. So a `write` marking you expect to enforce in a chat
43
+ * conversation does nothing.
49
44
  *
50
- * Dat is een openstaand gat en geen ontwerpkeuze: een bevestigingsstap in de chat is UI plus
51
- * een extra ronde, en hoort een besluit te zijn in plaats van een veld dat stil niets doet.
45
+ * That is an open gap and not a design choice: a confirmation step in the chat is UI plus an
46
+ * extra round, and should be a decision rather than a field that silently does nothing.
52
47
  */
53
48
  toolPolicy?: {
54
49
  name: string;
@@ -1,27 +1,26 @@
1
1
  /**
2
- * Wat een organisatie voor de AI-app als geheel instelt — niet per profiel, niet per gebruiker.
2
+ * What an organisation configures for the AI app as a whole — not per profile, not per user.
3
3
  *
4
- * Eén veld tot nu toe, en dat is met opzet geen `Record<string, unknown>`: een instelling die
5
- * niemand kan opnoemen is een instelling die niemand kan vinden.
4
+ * One field so far, deliberately not a `Record<string, unknown>`: a setting nobody can name is a
5
+ * setting nobody can find.
6
6
  */
7
7
  export interface AiOrgSettings {
8
8
  /**
9
- * Mag de AI-app meeluisteren met gesprekken (spraak naar tekst)?
9
+ * May the AI app listen in on conversations (speech to text)?
10
10
  *
11
- * Dit is de knop die er niet was: de AI-app installeren zette transcriptie aan voor élk
12
- * gesprek in de organisatie, wat een technische toevalligheid was die als beleid gold.
11
+ * The switch that did not exist: installing the AI app turned transcription on for *every*
12
+ * conversation in the organisation, a technical accident acting as policy.
13
13
  */
14
14
  listeningEnabled?: boolean;
15
15
  }
16
16
  /**
17
- * Mag er meegeluisterd worden?
17
+ * May anything listen in?
18
18
  *
19
- * **Afwezig = ja**, en dat is hier de juiste kant: de knop is nieuw, en een organisatie die
20
- * hem nooit heeft aangeraakt hoort niet plotseling zonder transcriptie te zitten. Uit is dus
21
- * een expliciete keuze en niet een lege rij.
19
+ * **Absent = yes**, the right side here: the switch is new, and an organisation that never touched
20
+ * it should not suddenly find itself without transcription. Off is therefore an explicit choice
21
+ * and not an empty row.
22
22
  *
23
- * Eén plek, zodat de client (die de upload overslaat) en de server (die hem weigert) niet
24
- * ieder hun eigen default kunnen hebben — dan zou de een luisteren terwijl de ander denkt van
25
- * niet.
23
+ * One place, so the client (which skips the upload) and the server (which refuses it) cannot each
24
+ * have their own default — then one would listen while the other thinks not.
26
25
  */
27
26
  export declare function listeningAllowed(settings: AiOrgSettings | null | undefined): boolean;
@@ -1,4 +1,4 @@
1
- import { OwnerScope } from '../contact/types';
1
+ import { OwnerScope } from '../scope/types';
2
2
  import { DimensionId } from './dimensions';
3
3
  import { WidgetConfig } from './report';
4
4
  /**