@opencxh/domain 1.172.1 → 1.173.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 (84) 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 +64 -35
  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 +5 -5
  11. package/dist/entities/ai-conversation/types.d.ts +12 -12
  12. package/dist/entities/ai-profile/types.d.ts +14 -21
  13. package/dist/entities/ai-settings/types.d.ts +12 -13
  14. package/dist/entities/analytics/index.d.ts +4 -4
  15. package/dist/entities/analytics/source.d.ts +1 -1
  16. package/dist/entities/analytics/usage.d.ts +23 -28
  17. package/dist/entities/artifact/blocks.d.ts +54 -69
  18. package/dist/entities/artifact/markdown.d.ts +2 -3
  19. package/dist/entities/artifact/types.d.ts +46 -54
  20. package/dist/entities/assignment/types.d.ts +76 -90
  21. package/dist/entities/channel/index.d.ts +1 -1
  22. package/dist/entities/channel/signature.d.ts +8 -9
  23. package/dist/entities/communication/index.d.ts +1 -1
  24. package/dist/entities/contact/index.d.ts +1 -1
  25. package/dist/entities/custom-field-def/types.d.ts +14 -14
  26. package/dist/entities/external-identity/types.d.ts +45 -50
  27. package/dist/entities/interaction/index.d.ts +1 -1
  28. package/dist/entities/interaction/types.d.ts +44 -47
  29. package/dist/entities/live-lens/types.d.ts +39 -44
  30. package/dist/entities/mcp/types.d.ts +53 -57
  31. package/dist/entities/memory/alias.d.ts +7 -7
  32. package/dist/entities/memory/browse.d.ts +21 -21
  33. package/dist/entities/memory/ingest.d.ts +24 -28
  34. package/dist/entities/memory/item.d.ts +53 -58
  35. package/dist/entities/memory/kind.d.ts +25 -25
  36. package/dist/entities/memory/query.d.ts +49 -51
  37. package/dist/entities/playbook/actor.d.ts +17 -17
  38. package/dist/entities/playbook/assignment.d.ts +54 -63
  39. package/dist/entities/playbook/index.d.ts +2 -2
  40. package/dist/entities/playbook/labels.d.ts +4 -4
  41. package/dist/entities/playbook/trigger-vars.d.ts +17 -15
  42. package/dist/entities/playbook/types.d.ts +174 -303
  43. package/dist/entities/resource-reminder/types.d.ts +8 -9
  44. package/dist/entities/time-entry/duration.d.ts +11 -11
  45. package/dist/entities/time-entry/types.d.ts +59 -59
  46. package/dist/entities/time-entry/work-type.d.ts +21 -24
  47. package/dist/entities/topic/examples.d.ts +26 -27
  48. package/dist/entities/topic/scope.d.ts +11 -12
  49. package/dist/entities/topic/types.d.ts +26 -28
  50. package/dist/entities/user/types.d.ts +24 -28
  51. package/dist/entities/webhook/types.d.ts +6 -6
  52. package/dist/entities/work/activity.d.ts +36 -0
  53. package/dist/entities/work/index.d.ts +1 -0
  54. package/dist/entities/work/keys.d.ts +25 -26
  55. package/dist/entities/work/ladder.d.ts +48 -52
  56. package/dist/entities/work/types.d.ts +108 -114
  57. package/dist/index.cjs +6 -6
  58. package/dist/index.d.ts +29 -28
  59. package/dist/index.js +1416 -1258
  60. package/dist/platform/account.d.ts +34 -38
  61. package/dist/platform/ai-tools.d.ts +48 -52
  62. package/dist/platform/api.d.ts +9 -10
  63. package/dist/platform/author.d.ts +7 -9
  64. package/dist/platform/capabilities.d.ts +3 -3
  65. package/dist/platform/communication.d.ts +163 -204
  66. package/dist/platform/context.d.ts +8 -8
  67. package/dist/platform/identity.d.ts +16 -19
  68. package/dist/platform/kernel.d.ts +1 -1
  69. package/dist/platform/manifest.d.ts +2 -2
  70. package/dist/platform/media.d.ts +13 -15
  71. package/dist/platform/permission.d.ts +39 -0
  72. package/dist/platform/permission.test.d.ts +1 -0
  73. package/dist/platform/presence.d.ts +30 -30
  74. package/dist/platform/provider.d.ts +14 -15
  75. package/dist/platform/resource-source.d.ts +43 -45
  76. package/dist/platform/resource.d.ts +17 -23
  77. package/dist/platform/scope.d.ts +35 -61
  78. package/dist/platform/services.d.ts +4 -4
  79. package/dist/platform/storage.d.ts +1 -1
  80. package/dist/platform/sync-source.d.ts +196 -216
  81. package/dist/platform/transcript-cadence.d.ts +37 -41
  82. package/dist/platform/ui.d.ts +6 -6
  83. package/dist/text/endpoint.d.ts +11 -27
  84. package/package.json +3 -2
@@ -1,10 +1,9 @@
1
1
  /**
2
- * Persoonlijke "kom hier later op terug"-markering op een resource, per
3
- * (resourceType, resourceId, userId) - dezelfde ResourceRef-vorm die read-state
4
- * gebruikt.
2
+ * A personal "come back to this later" marker on a resource, per (resourceType, resourceId,
3
+ * userId) - the same ResourceRef shape read-state uses.
5
4
  *
6
- * Anders dan een snooze raakt dit de resource zelf niet: het team blijft het
7
- * gesprek gewoon in zijn lijst zien, alleen jouw aandachtsstapel slaat het over.
5
+ * Unlike a snooze this does not touch the resource itself: the team keeps seeing the conversation
6
+ * in its list, only your attention stack skips it.
8
7
  */
9
8
  export interface ResourceReminder {
10
9
  id: string;
@@ -12,12 +11,12 @@ export interface ResourceReminder {
12
11
  resourceId: string;
13
12
  userId: string;
14
13
  organizationId: string;
15
- /** Epoch-ms waarop het item weer in beeld mag komen. */
14
+ /** Epoch ms at which the item may come back into view. */
16
15
  remindAt: number;
17
16
  /**
18
- * Epoch-ms waarop geparkeerd werd. Bepaalt of latere activiteit de
19
- * herinnering opheft - expliciet veld, niet het framework-`updatedAt`, zodat
20
- * de vervalregel deterministisch en testbaar is.
17
+ * Epoch ms at which it was parked. Decides whether later activity lifts the reminder - an
18
+ * explicit field and not the framework `updatedAt`, so the expiry rule stays deterministic and
19
+ * testable.
21
20
  */
22
21
  parkedAt: number;
23
22
  createdAt?: number;
@@ -1,22 +1,22 @@
1
1
  import { TimeEntry, TimeRounding } from './types';
2
2
  /**
3
- * De verstreken tijd van een regel, in seconden.
3
+ * The elapsed time of an entry, in seconds.
4
4
  *
5
- * In `domain` en niet in de app-server, omdat client én server hetzelfde antwoord moeten geven:
6
- * de server stempelt de duur bij het stoppen, het paneel laat 'm ondertussen elke seconde
7
- * oplopen. Zou het paneel zelf tellen vanaf een eigen nulpunt, dan loopt de zichtbare klok weg
8
- * van wat er uiteindelijk geboekt wordt zodra een tabblad even slaapt.
5
+ * In `domain` and not in the app server, because client and server have to give the same answer:
6
+ * the server stamps the duration on stop, the panel counts it up every second in the meantime. If
7
+ * the panel counted from a zero point of its own, the visible clock would drift from what is
8
+ * eventually booked as soon as a tab sleeps.
9
9
  */
10
10
  export declare function elapsedSeconds(entry: Pick<TimeEntry, "accumulatedSeconds" | "runningSince">, now: number): number;
11
11
  /**
12
- * De geboekte duur die bij een gemeten duur hoort.
12
+ * The booked duration belonging to a measured one.
13
13
  *
14
- * Naar boven en met een minimum van één eenheid: wie "per 15 minuten" kiest, wil dat een klus
15
- * van drie minuten een kwartier wordt en niet nul. Bij `exact` is de bodem één minuut, om
16
- * dezelfde reden — een regel van nul seconden is geen regel.
14
+ * Rounded up and with a minimum of one unit: whoever picks "per 15 minutes" wants a three-minute
15
+ * job to become a quarter of an hour and not zero. With `exact` the floor is one minute, for the
16
+ * same reason — an entry of zero seconds is not an entry.
17
17
  */
18
18
  export declare function applyRounding(rawSeconds: number, rounding: TimeRounding | undefined): number;
19
- /** `0:45` / `2:05` — uren en minuten, zoals de dagtotalen in het paneel. */
19
+ /** `0:45` / `2:05` — hours and minutes, like the day totals in the panel. */
20
20
  export declare function formatHm(totalSeconds: number): string;
21
- /** `12:34` onder het uur, `1:02:03` erboven — de lopende klok. */
21
+ /** `12:34` under the hour, `1:02:03` above it — the running clock. */
22
22
  export declare function formatClock(totalSeconds: number): string;
@@ -1,70 +1,71 @@
1
1
  import { OwnerScope } from '../scope/types';
2
2
  /**
3
- * Waar een urenregel in zijn leven staat.
3
+ * Where a time entry stands in its life.
4
4
  *
5
- * `review` is met opzet een **server**-staat en niet iets wat alleen in het paneel leeft: het
6
- * ontwerp laat je na het stoppen nog afronden, een werksoort kiezen en een notitie bijwerken
7
- * voordat de regel telt. Zat die tussenstap alleen in de client, dan was een dichtgeslagen
8
- * tabblad precies het moment waarop het gewerkte uur verdampt. Nu vindt het paneel de regel bij
9
- * het volgende bezoek gewoon terug en staat de review-kaart er weer.
5
+ * `review` is deliberately a **server** state and not something living only in the panel: the
6
+ * design lets you round off, pick a work type and update a note after stopping, before the entry
7
+ * counts. If that intermediate step lived only in the client, a closed tab would be exactly the
8
+ * moment the worked hour evaporates. Now the panel simply finds the entry again on the next visit,
9
+ * review card and all.
10
10
  *
11
- * `logged` is de enige staat die meetelt in totalen en in de rapportage.
11
+ * `logged` is the only state counting towards totals and reporting.
12
12
  */
13
13
  export type TimeEntryStatus = "running" | "paused" | "review" | "logged";
14
- /** Hoe de gemeten tijd naar een boekbare duur wordt vertaald. */
14
+ /** How measured time is translated into a bookable duration. */
15
15
  export type TimeRounding = "exact" | "15" | "30";
16
- /** Handmatig ingevoerd of daadwerkelijk geklokt — zichtbaar in de rapportage. */
16
+ /** Entered by hand or actually clocked — visible in the reporting. */
17
17
  export type TimeEntrySource = "timer" | "manual";
18
18
  export interface TimeEntry {
19
19
  id: string;
20
20
  organizationId: string;
21
- /** Wie de tijd schreef. Een regel hoort altijd bij precies één mens. */
21
+ /** Who wrote the time. An entry always belongs to exactly one person. */
22
22
  userId: string;
23
23
  /**
24
- * Waarop geboekt wordt: `"interaction:abc"`, `"task:42"`, `"company:xyz"`. Afwezig =
25
- * algemeen werk zonder object.
24
+ * What the time is booked on: `"interaction:abc"`, `"task:42"`, `"company:xyz"`. Absent =
25
+ * general work without an object.
26
26
  *
27
- * Bewust een opake sleutel en geen `interactionId`: de app die de soort bezit beantwoordt
28
- * de toegangsvraag (`assertScopeAccess`), dus urenregistratie hoeft geen enkele andere app
29
- * te kennen om er tijd op te kunnen schrijven.
27
+ * Deliberately an opaque key and not an `interactionId`: the app owning the kind answers the
28
+ * access question (`assertScopeAccess`), so time tracking needs to know no other app at all to
29
+ * be able to write time against it.
30
30
  */
31
31
  scopeKey?: string;
32
- /** Menselijk etiket op schrijfmoment ("Gesprek · RE: EYLO"), zodat een lijst leesbaar blijft
33
- * zonder per regel de bron-app te bevragen. */
32
+ /** Human label at write time ("Gesprek · RE: EYLO"), so a list stays readable without
33
+ * querying the source app per row. */
34
34
  scopeLabel?: string;
35
- /** Dossiersleutels van de resource, platgeslagen bij schrijven — zie de `keys`-conventie. */
35
+ /** File keys of the resource, flattened at write time — see the `keys` convention. */
36
36
  keys?: string[];
37
- /** Eigenaarschap zoals de bron-app het ziet; bepaalt wie de regel in een teamweergave ziet. */
37
+ /** Ownership as the source app sees it; decides who sees the entry in a team view. */
38
38
  ownerScope?: OwnerScope;
39
39
  status: TimeEntryStatus;
40
- /** Epoch ms, gezet door de server. De client rekent alleen af hoe laat het nu is. */
40
+ /** Epoch ms, set by the server. The client only works out what time it is now. */
41
41
  startedAt: number;
42
- /** Epoch ms; gezet zodra de timer stopt. Afwezig zolang hij loopt of gepauzeerd staat. */
42
+ /** Epoch ms; set as soon as the timer stops. Absent while it runs or is paused. */
43
43
  endedAt?: number;
44
44
  /**
45
- * Seconden die vóór het huidige segment al gebankt zijn.
45
+ * Seconds already banked before the current segment.
46
46
  *
47
- * Pauzeren mag geen tweede rij opleveren — het ontwerp belooft één regel per klus, met een
48
- * pauzeknop erin. Daarom telt de server bij elke pauze het gelopen segment hierbij op en
49
- * laat `runningSince` los; hervatten zet alleen `runningSince` opnieuw. De verstreken tijd
50
- * is dus altijd `accumulatedSeconds + (runningSince ? now - runningSince : 0)`, en dat
51
- * antwoord is hetzelfde op elk apparaat.
47
+ * Pausing must not produce a second row — the design promises one entry per job, with a pause
48
+ * button in it. So on every pause the server adds the elapsed segment here and releases
49
+ * `runningSince`; resuming only sets `runningSince` again. Elapsed time is therefore always
50
+ * `accumulatedSeconds + (runningSince ? now - runningSince : 0)`, and that answer is the same on
51
+ * every device.
52
52
  */
53
53
  accumulatedSeconds: number;
54
- /** Epoch ms waarop het lopende segment begon. Afwezig = gepauzeerd of gestopt. */
54
+ /** Epoch ms the running segment started at. Absent = paused or stopped. */
55
55
  runningSince?: number;
56
- /** Wat de klok werkelijk mat. Blijft staan als afronding de geboekte duur optrekt. */
56
+ /** What the clock actually measured. Stays when rounding pulls the booked duration up. */
57
57
  rawSeconds?: number;
58
58
  /**
59
- * De geboekte duur in seconden — dít telt in totalen en facturatie.
59
+ * The booked duration in seconds — *this* is what counts in totals and invoicing.
60
60
  *
61
- * Los van `rawSeconds` omdat afronding een keuze van de gebruiker is en geen meting: wie
62
- * later vraagt "waar komt dat kwartier vandaan" moet de gemeten twee minuten nog kunnen zien.
61
+ * Separate from `rawSeconds` because rounding is a user's choice and not a measurement: whoever
62
+ * asks later "where does that quarter of an hour come from" must still be able to see the two
63
+ * minutes that were measured.
63
64
  */
64
65
  durationSeconds?: number;
65
66
  rounding?: TimeRounding;
66
67
  billable: boolean;
67
- /** Verwijst naar `WorkType.key`. */
68
+ /** Refers to `WorkType.key`. */
68
69
  workType?: string;
69
70
  note?: string;
70
71
  source: TimeEntrySource;
@@ -72,35 +73,34 @@ export interface TimeEntry {
72
73
  updatedAt?: number;
73
74
  }
74
75
  /**
75
- * Een beheerbare werksoort in plaats van een rijtje in code: welke soorten een organisatie
76
- * kent verschilt per bedrijf, en de soort bepaalt of iets standaard declarabel is.
76
+ * A manageable work type instead of a list in code: which types an organisation knows differs per
77
+ * company, and the type decides whether something is billable by default.
77
78
  */
78
79
  export interface WorkType {
79
80
  id: string;
80
81
  organizationId: string;
81
82
  /**
82
- * Stabiele sleutel die op de urenregel belandt.
83
+ * Stable key that lands on the time entry.
83
84
  *
84
- * Uniek binnen de organisatie en niet binnen de scope, hoewel de soort een team kan
85
- * toebehoren: `TimeEntry.workType` bewaart alléén deze sleutel en de rapportage groepeert
86
- * erop. Twee teams met elk een eigen `installatie` zouden daar als één regel uitkomen, met
87
- * twee betekenissen erin.
85
+ * Unique within the organisation and not within the scope, even though a type can belong to a
86
+ * team: `TimeEntry.workType` stores only this key and the reporting groups on it. Two teams each
87
+ * with their own `installatie` would come out as one row there, carrying two meanings.
88
88
  */
89
89
  key: string;
90
90
  label: string;
91
- /** Standaardwaarde voor `TimeEntry.billable`; per regel te overrulen. */
91
+ /** Default for `TimeEntry.billable`; overridable per entry. */
92
92
  defaultBillable: boolean;
93
- /** Meegenomen als dimensie in de rapportage. */
93
+ /** Included as a dimension in the reporting. */
94
94
  reportable?: boolean;
95
95
  order?: number;
96
96
  archived?: boolean;
97
97
  /**
98
- * Van wie deze soort is: de hele organisatie of één team. Bepaalt wie hem in zijn
99
- * urenpaneel ziet en wie hem mag beheren.
98
+ * Whose type this is: the whole organisation or one team. Decides who sees it in their time
99
+ * panel and who may manage it.
100
100
  *
101
- * Geen `personal`, om dezelfde reden als bij `Topic`: een soort die maar één mens kent,
102
- * maakt het geboekte uur onleesbaar voor de collega die de week overneemt. Afwezig telt als
103
- * org-breed — dat is wat elke soort vóór dit veld feitelijk was.
101
+ * No `personal`, for the same reason as with `Topic`: a type only one person knows makes the
102
+ * booked hour unreadable for the colleague taking over the week. Absent counts as org-wide —
103
+ * which is what every type effectively was before this field.
104
104
  */
105
105
  ownerScope?: Extract<OwnerScope, {
106
106
  kind: "org";
@@ -111,10 +111,10 @@ export interface WorkType {
111
111
  updatedAt?: number;
112
112
  }
113
113
  /**
114
- * Wat het beheerscherm naar de server stuurt.
114
+ * What the admin screen sends to the server.
115
115
  *
116
- * Zonder `id` is het een nieuwe soort. `key` staat er met opzet niet in: die leidt de server af
117
- * uit de naam en ligt daarna vast, omdat geboekte uren ernaar verwijzen.
116
+ * Without an `id` it is a new type. `key` is deliberately absent: the server derives it from the
117
+ * name and it is fixed afterwards, because booked hours refer to it.
118
118
  */
119
119
  export interface SaveWorkTypeRequest {
120
120
  id?: string;
@@ -125,13 +125,13 @@ export interface SaveWorkTypeRequest {
125
125
  archived?: boolean;
126
126
  ownerScope?: WorkType["ownerScope"];
127
127
  }
128
- /** Een kandidaat waarop de gebruiker kan klokken, aangeboden in de leegstaat van het paneel. */
128
+ /** A candidate the user can clock on, offered in the panel's empty state. */
129
129
  export interface TimeTarget {
130
130
  scopeKey?: string;
131
- /** Soortlabel boven de titel ("GESPREK OP JE SCHERM", "TAAK"). */
131
+ /** Kind label above the title ("GESPREK OP JE SCHERM", "TAAK"). */
132
132
  kindLabel: string;
133
133
  title: string;
134
- /** Lucide-icoonnaam. */
134
+ /** Lucide icon name. */
135
135
  icon: string;
136
136
  keys?: string[];
137
137
  }
@@ -142,14 +142,14 @@ export interface StartTimerRequest {
142
142
  workType?: string;
143
143
  note?: string;
144
144
  }
145
- /** Wat er bij het opslaan van een regel nog aan te passen valt. */
145
+ /** What can still be adjusted when saving an entry. */
146
146
  export interface SaveTimeEntryRequest {
147
147
  id: string;
148
148
  rounding?: TimeRounding;
149
149
  workType?: string;
150
150
  billable?: boolean;
151
151
  note?: string;
152
- /** Naar een ander object boeken dan waar de timer op startte. */
152
+ /** Book against a different object than the timer started on. */
153
153
  scopeKey?: string;
154
154
  scopeLabel?: string;
155
155
  keys?: string[];
@@ -158,18 +158,18 @@ export interface ManualTimeEntryRequest {
158
158
  scopeKey?: string;
159
159
  scopeLabel?: string;
160
160
  keys?: string[];
161
- /** Epoch ms; de dag waarop de regel valt. */
161
+ /** Epoch ms; the day the entry falls on. */
162
162
  startedAt: number;
163
163
  durationSeconds: number;
164
164
  workType?: string;
165
165
  billable?: boolean;
166
166
  note?: string;
167
167
  }
168
- /** Wat het paneel in één keer ophaalt: de lopende timer plus de dag eromheen. */
168
+ /** What the panel fetches in one go: the running timer plus the day around it. */
169
169
  export interface TimeDaySummary {
170
- /** De regel die nu loopt, gepauzeerd staat of op afronding wacht — er is er hooguit één. */
170
+ /** The entry running, paused or awaiting review right now — there is at most one. */
171
171
  active?: TimeEntry;
172
- /** Afgeronde regels van de opgevraagde dag, oplopend op starttijd. */
172
+ /** Finished entries of the requested day, ascending on start time. */
173
173
  entries: TimeEntry[];
174
174
  totalSeconds: number;
175
175
  billableSeconds: number;
@@ -1,44 +1,41 @@
1
1
  import { WorkType } from './types';
2
2
  /**
3
- * De sleutel die bij een naam hoort: kleine letters, streepjes, geen accenten.
3
+ * The key belonging to a name: lowercase, hyphens, no accents.
4
4
  *
5
- * In `domain` en niet in de app-server omdat het beheerscherm hem al tijdens het typen laat
6
- * zien — wat de gebruiker daar ziet moet exact zijn wat de server straks wegschrijft, anders
7
- * belooft het formulier `installatie-op-locatie` en staat er `installatieoplocatie` in de
8
- * rapportage.
5
+ * In `domain` and not in the app server because the admin screen shows it while you type — what
6
+ * the user sees there has to be exactly what the server writes later, or the form promises
7
+ * `installatie-op-locatie` and the reporting says `installatieoplocatie`.
9
8
  *
10
- * `normalize("NFD")` plus het weghalen van de combineertekens, zodat "Béta" `beta` wordt en niet
11
- * `b-ta`: een leesbare sleutel is het halve doel.
9
+ * `normalize("NFD")` plus stripping the combining marks, so "Béta" becomes `beta` and not `b-ta`:
10
+ * a readable key is half the point.
12
11
  */
13
12
  export declare function workTypeKey(label: string): string;
14
13
  /**
15
- * Dezelfde sleutel, maar gegarandeerd nog vrij binnen de organisatie.
14
+ * The same key, but guaranteed still free within the organisation.
16
15
  *
17
- * Botsingen zijn echt: de sleutel is org-uniek terwijl soorten per team beheerd worden, dus twee
18
- * teams die allebei "Installatie" aanmaken komen hier uit. De tweede krijgt `installatie-2` in
19
- * plaats van een foutmelding — een beheerder die een naam kiest, hoort niet te struikelen over
20
- * een sleutel die hij nooit heeft gezien.
16
+ * Collisions are real: the key is org-unique while types are managed per team, so two teams both
17
+ * creating "Installatie" end up here. The second gets `installatie-2` instead of an error — an
18
+ * admin picking a name should not trip over a key they never saw.
21
19
  *
22
- * `taken` bevat óók gearchiveerde sleutels: die staan nog op geboekte uren, dus hergebruiken zou
23
- * oud werk stilzwijgend onder een nieuwe soort schuiven.
20
+ * `taken` also holds archived keys: those still sit on booked hours, so reusing one would silently
21
+ * shift old work under a new type.
24
22
  */
25
23
  export declare function uniqueWorkTypeKey(label: string, taken: Iterable<string>): string;
26
24
  /**
27
- * Ziet deze gebruiker deze soort?
25
+ * Does this user see this type?
28
26
  *
29
- * Een soort zonder scope is org-breed: rijen zijn ouder dan het veld, en ze wegfilteren zou een
30
- * bestaande organisatie zijn hele lijst kosten.
27
+ * A type without a scope is org-wide: rows are older than the field, and filtering them out would
28
+ * cost an existing organisation its whole list.
31
29
  */
32
30
  export declare function isWorkTypeVisible(workType: Pick<WorkType, "ownerScope">, teamIds: string[]): boolean;
33
31
  /**
34
- * Wat het paneel toont: niet-gearchiveerd, in de juiste volgorde.
32
+ * What the panel shows: not archived, in the right order.
35
33
  *
36
- * Zonder team-argument, en dat is met opzet: de server heeft de teamzichtbaarheid al afgekapt
37
- * voordat de lijst de client bereikt (dat is een rechtenvraag). Zou de client hier nóg eens op
38
- * `teamIds` filteren, dan moest hij het lidmaatschap van de gebruiker kennen — en met een lege
39
- * lijst, zoals hij hem nu heeft, zou hij precies de teamsoorten wegfilteren die de server net
40
- * heeft goedgekeurd.
34
+ * Without a team argument, deliberately: the server already cut team visibility off before the
35
+ * list reaches the client (that is a permission question). If the client filtered on `teamIds`
36
+ * again here it would have to know the user's memberships — and with an empty list, as it has one
37
+ * now, it would filter out precisely the team types the server just approved.
41
38
  */
42
39
  export declare function activeWorkTypes(workTypes: WorkType[]): WorkType[];
43
- /** De volgorde van de chips: `order` eerst, gelijke waarden alfabetisch zodat hij stabiel is. */
40
+ /** The order of the chips: `order` first, ties alphabetical so it stays stable. */
44
41
  export declare function compareWorkTypes(a: WorkType, b: WorkType): number;
@@ -1,46 +1,45 @@
1
1
  import { Topic, TopicExampleCandidate } from './types';
2
2
  /**
3
- * De vorm waarop twee voorbeelden "hetzelfde" zijn.
3
+ * The shape in which two examples are "the same".
4
4
  *
5
- * Alleen voor vergelijken, nooit voor opslaan: wat de beheerder ziet is de originele tekst.
6
- * Tien keer "Ik wil mijn factuur" leert de classifier niets en verdringt wel een voorbeeld dat het
7
- * wél zou doen, dus hoofdletters, leestekens en dubbele spaties mogen dat niet verhullen.
5
+ * For comparing only, never for storing: what the admin sees is the original text. Ten copies of
6
+ * "Ik wil mijn factuur" teach the classifier nothing while crowding out an example that would, so
7
+ * capitals, punctuation and double spaces must not hide that.
8
8
  */
9
9
  export declare function normalizeExample(text: string): string;
10
- /** Afkappen op een hele zin waar dat kan, anders hard op de grens. */
10
+ /** Truncate on a whole sentence where possible, otherwise hard at the limit. */
11
11
  export declare function truncateExample(text: string): string;
12
12
  /**
13
- * Een voorstel toevoegen. Geeft de nieuwe kandidatenlijst terug, of `null` als er niets te
14
- * veranderen viel — de caller slaat dan geen schrijfactie op.
13
+ * Add a suggestion. Returns the new candidate list, or `null` when there was nothing to change —
14
+ * the caller then stores no write.
15
15
  *
16
- * Drie redenen om `null` te geven, en ze zijn alle drie gewoon:
17
- * 1. Lege tekst. Een gesprek zonder inkomend bericht levert geen voorbeeld.
18
- * 2. Het staat al bij `examples`. De beheerder heeft dit al beoordeeld; het opnieuw voorstellen is
19
- * ruis, en na één afwijzing zou het bij elke volgende toekenning terugkomen.
20
- * 3. Het staat al bij de kandidaten. Wel wordt hij dan **bijgewerkt** als de nieuwe melding een
21
- * correctie is: dat is het sterkere signaal en het hoort bovenaan.
16
+ * Three reasons to return `null`, all three ordinary:
17
+ * 1. Empty text. A conversation without an inbound message yields no example.
18
+ * 2. It is already in `examples`. The admin already judged this; suggesting it again is noise, and
19
+ * after one rejection it would come back on every next assignment.
20
+ * 3. It is already among the candidates. It *is* **updated** when the new report is a correction:
21
+ * that is the stronger signal and belongs at the top.
22
22
  */
23
23
  export declare function addExampleCandidate(topic: Pick<Topic, "examples" | "exampleCandidates">, candidate: TopicExampleCandidate): TopicExampleCandidate[] | null;
24
24
  /**
25
- * Een voorstel overnemen: van de kandidatenlijst naar `examples`.
25
+ * Accept a suggestion: from the candidate list into `examples`.
26
26
  *
27
- * Draait in de **editor**, niet op de server — accepteren is een bewerking van het onderwerp en
28
- * gaat mee met de gewone opslag. Dat scheelt een endpoint en houdt "wat de beheerder ziet" en "wat
29
- * er opgeslagen wordt" één ding.
27
+ * Runs in the **editor**, not on the server — accepting is an edit of the topic and travels with
28
+ * the normal save. That saves an endpoint and keeps "what the admin sees" and "what gets stored"
29
+ * one thing.
30
30
  *
31
- * Bij een volle `examples` valt de **oudste** eruit (voorop in de lijst). Dat is niet
32
- * onvermijdelijk goed — de eerste voorbeelden zijn vaak met zorg getypt — maar het alternatief is
33
- * de beheerder een keuze voorleggen op het moment dat hij iets anders aan het doen is. De cap staat
34
- * in de UI vermeld.
31
+ * On a full `examples` the **oldest** falls out (first in the list). Not unavoidably right — the
32
+ * first examples are often typed with care — but the alternative is putting a choice to the admin
33
+ * while they are doing something else. The cap is stated in the UI.
35
34
  */
36
35
  export declare function acceptExampleCandidate(topic: Pick<Topic, "examples" | "exampleCandidates">, text: string): Pick<Topic, "examples" | "exampleCandidates">;
37
36
  /**
38
- * Een voorstel weggooien.
37
+ * Throw a suggestion away.
39
38
  *
40
- * Er wordt **niet** onthouden dat je hem hebt afgewezen. Verschijnt exact dezelfde zin nog eens bij
41
- * een handmatige toekenning, dan staat hij er weer. Bewust geen derde lijst met afgewezen teksten:
42
- * dat is dubbel zoveel state voor een geval dat alleen optreedt bij een generieke openingszin
43
- * ("Hallo, ik heb een vraag") — en dán is terugkomen ook niet gek. Hindert het toch, dan is de
44
- * echte oplossing hem accepteren, want daarna wordt hij nooit meer voorgesteld.
39
+ * Rejecting is **not** remembered. If the exact same sentence shows up again on a manual
40
+ * assignment, it is back. Deliberately no third list of rejected texts: that is twice the state
41
+ * for a case that only occurs with a generic opening line ("Hallo, ik heb een vraag") — and then
42
+ * coming back is not strange either. If it still bothers you, the real fix is to accept it, after
43
+ * which it is never suggested again.
45
44
  */
46
45
  export declare function rejectExampleCandidate(topic: Pick<Topic, "exampleCandidates">, text: string): TopicExampleCandidate[];
@@ -1,20 +1,19 @@
1
1
  import { Topic } from './types';
2
2
  /**
3
- * Mag dit onderwerp aangeboden worden op een gesprek in een inbox van dit team?
3
+ * May this topic be offered on a conversation in an inbox of this team?
4
4
  *
5
- * Let op het woord *aangeboden*. Dit is een **keuzelijst-filter**, geen autorisatie: het
6
- * leesrecht is al afgehandeld door de server (`buildScopeQuery` in
7
- * `apps/communication/server/src/utils/scope.ts`), en wat hier binnenkomt mag de gebruiker dus
8
- * sowieso zien. Wat dit filter toevoegt is relevantie — Sales hoeft de onderwerpen van Support
9
- * niet door te scrollen.
5
+ * Mind the word *offered*. This is a **picker filter**, not authorization: the read right is
6
+ * already handled by the server (`buildScopeQuery` in
7
+ * `apps/communication/server/src/utils/scope.ts`), so whatever arrives here the user may see
8
+ * anyway. What this filter adds is relevance — Sales need not scroll past Support's topics.
10
9
  *
11
- * Daarom mag je hem **nooit** gebruiken om een reeds toegekend onderwerp op te zoeken. Een gesprek
12
- * dat van team wisselt houdt zijn etiket; dat opzoeken in de gefilterde lijst zou het label leeg
13
- * laten terwijl er wel degelijk een onderwerp op staat.
10
+ * So it must **never** be used to look up an already assigned topic. A conversation that changes
11
+ * team keeps its label; looking that up in the filtered list would leave the label empty while a
12
+ * topic is very much set.
14
13
  *
15
- * `personal` valt altijd af: die scope wordt bij het schrijven geweigerd, en komt er ooit toch een
16
- * rij zo binnen, dan hoort hij niet in een gedeelde keuzelijst.
14
+ * `personal` always drops out: that scope is refused at write time, and if a row ever does arrive
15
+ * that way, it does not belong in a shared picker.
17
16
  */
18
17
  export declare function topicOfferedForTeam(topic: Topic, teamId: string | undefined): boolean;
19
- /** {@link topicOfferedForTeam} over een lijst. */
18
+ /** {@link topicOfferedForTeam} over a list. */
20
19
  export declare function topicsForTeam(topics: Topic[], teamId: string | undefined): Topic[];
@@ -1,47 +1,45 @@
1
1
  import { OrgTeamScope } from '../scope/types';
2
2
  /**
3
- * Een onderwerp is een **etiket** op een gesprek: waar gaat dit over. Verder niets.
3
+ * A topic is a **label** on a conversation: what is this about. Nothing more.
4
4
  *
5
- * Er zat ooit ook een kennis-kant in (`knowledgeSources`: urls en kb-artikelen die "bij dit
6
- * onderwerp horen"). Die is eruit gehaald omdat hij door niemand gelezen werd — het formulier
7
- * vulde hem, de entity bewaarde hem, en geen enkele prompt of zoekactie deed er iets mee. Wat hij
8
- * beloofde doet de kennisbank inmiddels beter (hybride RAG over álle artikelen) en het geheugen
9
- * daarnaast (`memory_find_similar`, uit echt verkeer). Zie `docs/TOPICS.md`.
5
+ * It once also had a knowledge side (`knowledgeSources`: urls and kb articles "belonging to this
6
+ * topic"). That was removed because nobody read it — the form filled it, the entity stored it, and
7
+ * no prompt or search did anything with it. What it promised the knowledge base now does better
8
+ * (hybrid RAG over *all* articles) and the memory layer alongside it (`memory_find_similar`, from
9
+ * real traffic). See `docs/TOPICS.md`.
10
10
  */
11
11
  export interface Topic {
12
12
  id: string;
13
13
  organizationId: string;
14
14
  /**
15
- * Van wie dit onderwerp is: `org` of `team`. Een onderwerp dat maar één persoon kent, kan
16
- * een collega niet lezen op een gesprek dat hij overneemt.
17
- *
18
- * Dit stond hier als proza terwijl het type `personal` toestond, dus handhaafde niets het
19
- * behalve de schrijfvalidatie. `OrgTeamScope` zegt het nu in het type.
15
+ * Whose topic this is: `org` or `team`. A topic only one person knows cannot be read by a
16
+ * colleague taking over the conversation. `OrgTeamScope` says so in the type, so it is not only
17
+ * the write validation enforcing it.
20
18
  */
21
19
  ownerScope: OrgTeamScope;
22
20
  name: string;
23
21
  description: string;
24
22
  /**
25
- * Voorbeeldzinnen die de classificatie-prompt meekrijgt. Dit is het enige veld dat de
26
- * classifier scherper maakt, en dus het enige dat het waard is om bij te houden.
23
+ * Example sentences the classification prompt receives. The only field that sharpens the
24
+ * classifier, and therefore the only one worth maintaining.
27
25
  */
28
26
  examples: string[];
29
27
  /**
30
- * Voorgestelde voorbeelden, nog niet overgenomen. Groeit vanzelf: elke keer dat een **mens**
31
- * dit onderwerp op een gesprek zet of corrigeert, komt de openingszin hier terecht.
28
+ * Suggested examples, not accepted yet. Grows by itself: every time a **person** puts this topic
29
+ * on a conversation or corrects it, the opening sentence lands here.
32
30
  *
33
- * Bewust náást `examples` en niet erin: de classificatie-prompt is de plek waar één slecht
34
- * voorbeeld het gedrag van élk volgend gesprek verschuift, en er is geen undo op een prompt die
35
- * drie weken scheef stond. `examples` blijft van de beheerder; dit is een voorstel.
31
+ * Deliberately next to `examples` and not in it: the classification prompt is where one bad
32
+ * example shifts the behaviour of *every* following conversation, and there is no undo on a
33
+ * prompt that sat crooked for three weeks. `examples` stays the admin's; this is a suggestion.
36
34
  */
37
35
  exampleCandidates?: TopicExampleCandidate[];
38
36
  }
39
37
  /**
40
- * Eén voorgesteld voorbeeld.
38
+ * One suggested example.
41
39
  *
42
- * `corrected` onderscheidt "iemand zette een onderwerp op een gesprek dat er nog geen had" van
43
- * "iemand zette het onderwerp om" — dat tweede is een gecorrigeerde fout en daarmee het meest
44
- * informatieve geval dat er is. De UI zet ze daarom bovenaan.
40
+ * `corrected` distinguishes "someone put a topic on a conversation that had none" from "someone
41
+ * changed the topic" — the second is a corrected mistake and thereby the most informative case
42
+ * there is. The UI puts those on top.
45
43
  */
46
44
  export interface TopicExampleCandidate {
47
45
  text: string;
@@ -50,14 +48,14 @@ export interface TopicExampleCandidate {
50
48
  corrected: boolean;
51
49
  }
52
50
  /**
53
- * Hoeveel voorbeelden er per onderwerp mee mogen.
51
+ * How many examples a topic may carry.
54
52
  *
55
- * De hele lijst gaat als JSON de systemprompt in bij élke classificatie
56
- * (`apps/ai/server/src/playbook/ai/classify.ts`), dus ongelimiteerd groeien maakt het classificeren
57
- * per gesprek duurder tot het niet meer past.
53
+ * The whole list goes into the system prompt as JSON on *every* classification
54
+ * (`apps/ai/server/src/playbook/ai/classify.ts`), so unlimited growth makes classifying more
55
+ * expensive per conversation until it no longer fits.
58
56
  */
59
57
  export declare const MAX_TOPIC_EXAMPLES = 20;
60
- /** Idem voor de kandidatenlijst: een voorstellenbak die volloopt, leest niemand meer na. */
58
+ /** Same for the candidate list: a suggestion bucket that fills up is one nobody reviews. */
61
59
  export declare const MAX_TOPIC_CANDIDATES = 20;
62
- /** Een voorbeeld is een openingszin, geen transcript. */
60
+ /** An example is an opening sentence, not a transcript. */
63
61
  export declare const MAX_TOPIC_EXAMPLE_CHARS = 300;