@t4h.framework/amber 0.1.0 → 0.2.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 (177) hide show
  1. package/.ai/skills/framework-amber/SKILL.md +225 -0
  2. package/LICENSE +21 -0
  3. package/README.md +78 -68
  4. package/dist/activities/AbstractAmberHttpRequestActivity.d.ts +2 -5
  5. package/dist/activities/AbstractAmberHttpRequestActivity.d.ts.map +1 -1
  6. package/dist/activities/AbstractAmberHttpRequestActivity.js.map +1 -1
  7. package/dist/activities/AmberTabulateServiceActivity.d.ts +10 -0
  8. package/dist/activities/AmberTabulateServiceActivity.d.ts.map +1 -0
  9. package/dist/activities/AmberTabulateServiceActivity.js +20 -0
  10. package/dist/activities/AmberTabulateServiceActivity.js.map +1 -0
  11. package/dist/activities/AmberTransferServiceActivity.d.ts +86 -0
  12. package/dist/activities/AmberTransferServiceActivity.d.ts.map +1 -0
  13. package/dist/activities/AmberTransferServiceActivity.js +95 -0
  14. package/dist/activities/AmberTransferServiceActivity.js.map +1 -0
  15. package/dist/activities/AmberUpdateServiceActivity.d.ts +10 -0
  16. package/dist/activities/AmberUpdateServiceActivity.d.ts.map +1 -0
  17. package/dist/activities/AmberUpdateServiceActivity.js +23 -0
  18. package/dist/activities/AmberUpdateServiceActivity.js.map +1 -0
  19. package/dist/activities/ticket/AmberCommentTicketActivity.d.ts +10 -0
  20. package/dist/activities/ticket/AmberCommentTicketActivity.d.ts.map +1 -0
  21. package/dist/activities/ticket/AmberCommentTicketActivity.js +19 -0
  22. package/dist/activities/ticket/AmberCommentTicketActivity.js.map +1 -0
  23. package/dist/activities/ticket/AmberCreateTicketActivity.d.ts +13 -0
  24. package/dist/activities/ticket/AmberCreateTicketActivity.d.ts.map +1 -0
  25. package/dist/activities/ticket/AmberCreateTicketActivity.js +47 -0
  26. package/dist/activities/ticket/AmberCreateTicketActivity.js.map +1 -0
  27. package/dist/activities/ticket/AmberFindTicketFieldsActivity.d.ts +7 -0
  28. package/dist/activities/ticket/AmberFindTicketFieldsActivity.d.ts.map +1 -0
  29. package/dist/activities/ticket/AmberFindTicketFieldsActivity.js +20 -0
  30. package/dist/activities/ticket/AmberFindTicketFieldsActivity.js.map +1 -0
  31. package/dist/activities/ticket/AmberGetTicketActivity.d.ts +7 -0
  32. package/dist/activities/ticket/AmberGetTicketActivity.d.ts.map +1 -0
  33. package/dist/activities/ticket/AmberGetTicketActivity.js +27 -0
  34. package/dist/activities/ticket/AmberGetTicketActivity.js.map +1 -0
  35. package/dist/activities/ticket/AmberInteractTicketActivity.d.ts +10 -0
  36. package/dist/activities/ticket/AmberInteractTicketActivity.d.ts.map +1 -0
  37. package/dist/activities/ticket/AmberInteractTicketActivity.js +20 -0
  38. package/dist/activities/ticket/AmberInteractTicketActivity.js.map +1 -0
  39. package/dist/activities/ticket/AmberLockTicketActivity.d.ts +11 -0
  40. package/dist/activities/ticket/AmberLockTicketActivity.d.ts.map +1 -0
  41. package/dist/activities/ticket/AmberLockTicketActivity.js +29 -0
  42. package/dist/activities/ticket/AmberLockTicketActivity.js.map +1 -0
  43. package/dist/activities/ticket/AmberReleaseTicketLockActivity.d.ts +10 -0
  44. package/dist/activities/ticket/AmberReleaseTicketLockActivity.d.ts.map +1 -0
  45. package/dist/activities/ticket/AmberReleaseTicketLockActivity.js +27 -0
  46. package/dist/activities/ticket/AmberReleaseTicketLockActivity.js.map +1 -0
  47. package/dist/activities/ticket/AmberUpdateTicketFieldValueActivity.d.ts +14 -0
  48. package/dist/activities/ticket/AmberUpdateTicketFieldValueActivity.d.ts.map +1 -0
  49. package/dist/activities/ticket/AmberUpdateTicketFieldValueActivity.js +19 -0
  50. package/dist/activities/ticket/AmberUpdateTicketFieldValueActivity.js.map +1 -0
  51. package/dist/constants/urls.d.ts +3 -0
  52. package/dist/constants/urls.d.ts.map +1 -0
  53. package/dist/constants/urls.js +3 -0
  54. package/dist/constants/urls.js.map +1 -0
  55. package/dist/constants/webhook.d.ts +12 -0
  56. package/dist/constants/webhook.d.ts.map +1 -0
  57. package/dist/constants/webhook.js +11 -0
  58. package/dist/constants/webhook.js.map +1 -0
  59. package/dist/errors/AmberRequestError.d.ts +23 -0
  60. package/dist/errors/AmberRequestError.d.ts.map +1 -0
  61. package/dist/errors/AmberRequestError.js +43 -0
  62. package/dist/errors/AmberRequestError.js.map +1 -0
  63. package/dist/index.d.ts +26 -9
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +18 -9
  66. package/dist/index.js.map +1 -1
  67. package/dist/inputs/AmberServiceTabulateEvent.d.ts +75 -0
  68. package/dist/inputs/AmberServiceTabulateEvent.d.ts.map +1 -0
  69. package/dist/inputs/AmberServiceTabulateEvent.js +26 -0
  70. package/dist/inputs/AmberServiceTabulateEvent.js.map +1 -0
  71. package/dist/inputs/AmberWebhookEvent.d.ts +19 -0
  72. package/dist/inputs/AmberWebhookEvent.d.ts.map +1 -0
  73. package/dist/inputs/AmberWebhookEvent.js +15 -0
  74. package/dist/inputs/AmberWebhookEvent.js.map +1 -0
  75. package/dist/models/Amber.d.ts +8 -5
  76. package/dist/models/Amber.d.ts.map +1 -1
  77. package/dist/models/Amber.js +20 -26
  78. package/dist/models/Amber.js.map +1 -1
  79. package/dist/models/Service.d.ts +26 -0
  80. package/dist/models/Service.d.ts.map +1 -0
  81. package/dist/models/Service.js +53 -0
  82. package/dist/models/Service.js.map +1 -0
  83. package/dist/models/Ticket.d.ts +24 -25
  84. package/dist/models/Ticket.d.ts.map +1 -1
  85. package/dist/models/Ticket.js +44 -109
  86. package/dist/models/Ticket.js.map +1 -1
  87. package/dist/tools/AmberWebhook.d.ts +22 -0
  88. package/dist/tools/AmberWebhook.d.ts.map +1 -0
  89. package/dist/tools/AmberWebhook.js +51 -0
  90. package/dist/tools/AmberWebhook.js.map +1 -0
  91. package/dist/typings/ServiceTabulate.d.ts.map +1 -0
  92. package/dist/typings/ServiceTabulate.js.map +1 -0
  93. package/dist/{types → typings}/ServiceTicket.d.ts +4 -4
  94. package/dist/typings/ServiceTicket.d.ts.map +1 -0
  95. package/dist/typings/ServiceTicket.js.map +1 -0
  96. package/dist/typings/ServiceTicketComment.d.ts.map +1 -0
  97. package/dist/typings/ServiceTicketComment.js.map +1 -0
  98. package/dist/typings/ServiceTicketField.d.ts +12 -0
  99. package/dist/typings/ServiceTicketField.d.ts.map +1 -0
  100. package/dist/typings/ServiceTicketField.js +2 -0
  101. package/dist/typings/ServiceTicketField.js.map +1 -0
  102. package/dist/typings/ServiceTicketInteraction.d.ts.map +1 -0
  103. package/dist/typings/ServiceTicketInteraction.js.map +1 -0
  104. package/dist/{types → typings}/ServiceTicketLock.d.ts +0 -1
  105. package/dist/typings/ServiceTicketLock.d.ts.map +1 -0
  106. package/dist/typings/ServiceTicketLock.js.map +1 -0
  107. package/dist/typings/ServiceTransfer.d.ts.map +1 -0
  108. package/dist/typings/ServiceTransfer.js.map +1 -0
  109. package/dist/typings/ServiceUpdate.d.ts.map +1 -0
  110. package/dist/typings/ServiceUpdate.js.map +1 -0
  111. package/package.json +10 -7
  112. package/dist/activities/AmberCommentTicketActivity.d.ts +0 -13
  113. package/dist/activities/AmberCommentTicketActivity.d.ts.map +0 -1
  114. package/dist/activities/AmberCommentTicketActivity.js +0 -22
  115. package/dist/activities/AmberCommentTicketActivity.js.map +0 -1
  116. package/dist/activities/AmberCreateTicketActivity.d.ts +0 -15
  117. package/dist/activities/AmberCreateTicketActivity.d.ts.map +0 -1
  118. package/dist/activities/AmberCreateTicketActivity.js +0 -68
  119. package/dist/activities/AmberCreateTicketActivity.js.map +0 -1
  120. package/dist/activities/AmberGetTicketActivity.d.ts +0 -12
  121. package/dist/activities/AmberGetTicketActivity.d.ts.map +0 -1
  122. package/dist/activities/AmberGetTicketActivity.js +0 -30
  123. package/dist/activities/AmberGetTicketActivity.js.map +0 -1
  124. package/dist/activities/AmberInteractTicketActivity.d.ts +0 -13
  125. package/dist/activities/AmberInteractTicketActivity.d.ts.map +0 -1
  126. package/dist/activities/AmberInteractTicketActivity.js +0 -23
  127. package/dist/activities/AmberInteractTicketActivity.js.map +0 -1
  128. package/dist/activities/AmberLockTicketActivity.d.ts +0 -14
  129. package/dist/activities/AmberLockTicketActivity.d.ts.map +0 -1
  130. package/dist/activities/AmberLockTicketActivity.js +0 -33
  131. package/dist/activities/AmberLockTicketActivity.js.map +0 -1
  132. package/dist/activities/AmberReleaseTicketLockActivity.d.ts +0 -12
  133. package/dist/activities/AmberReleaseTicketLockActivity.d.ts.map +0 -1
  134. package/dist/activities/AmberReleaseTicketLockActivity.js +0 -30
  135. package/dist/activities/AmberReleaseTicketLockActivity.js.map +0 -1
  136. package/dist/activities/AmberTabulateTicketActivity.d.ts +0 -13
  137. package/dist/activities/AmberTabulateTicketActivity.d.ts.map +0 -1
  138. package/dist/activities/AmberTabulateTicketActivity.js +0 -22
  139. package/dist/activities/AmberTabulateTicketActivity.js.map +0 -1
  140. package/dist/activities/AmberTransferTicketActivity.d.ts +0 -77
  141. package/dist/activities/AmberTransferTicketActivity.d.ts.map +0 -1
  142. package/dist/activities/AmberTransferTicketActivity.js +0 -121
  143. package/dist/activities/AmberTransferTicketActivity.js.map +0 -1
  144. package/dist/activities/AmberUpdateTicketActivity.d.ts +0 -13
  145. package/dist/activities/AmberUpdateTicketActivity.d.ts.map +0 -1
  146. package/dist/activities/AmberUpdateTicketActivity.js +0 -22
  147. package/dist/activities/AmberUpdateTicketActivity.js.map +0 -1
  148. package/dist/models/AmberConnection.d.ts +0 -7
  149. package/dist/models/AmberConnection.d.ts.map +0 -1
  150. package/dist/models/AmberConnection.js +0 -11
  151. package/dist/models/AmberConnection.js.map +0 -1
  152. package/dist/types/ServiceTabulate.d.ts.map +0 -1
  153. package/dist/types/ServiceTabulate.js.map +0 -1
  154. package/dist/types/ServiceTicket.d.ts.map +0 -1
  155. package/dist/types/ServiceTicket.js.map +0 -1
  156. package/dist/types/ServiceTicketComment.d.ts.map +0 -1
  157. package/dist/types/ServiceTicketComment.js.map +0 -1
  158. package/dist/types/ServiceTicketInteraction.d.ts.map +0 -1
  159. package/dist/types/ServiceTicketInteraction.js.map +0 -1
  160. package/dist/types/ServiceTicketLock.d.ts.map +0 -1
  161. package/dist/types/ServiceTicketLock.js.map +0 -1
  162. package/dist/types/ServiceTransfer.d.ts.map +0 -1
  163. package/dist/types/ServiceTransfer.js.map +0 -1
  164. package/dist/types/ServiceUpdate.d.ts.map +0 -1
  165. package/dist/types/ServiceUpdate.js.map +0 -1
  166. /package/dist/{types → typings}/ServiceTabulate.d.ts +0 -0
  167. /package/dist/{types → typings}/ServiceTabulate.js +0 -0
  168. /package/dist/{types → typings}/ServiceTicket.js +0 -0
  169. /package/dist/{types → typings}/ServiceTicketComment.d.ts +0 -0
  170. /package/dist/{types → typings}/ServiceTicketComment.js +0 -0
  171. /package/dist/{types → typings}/ServiceTicketInteraction.d.ts +0 -0
  172. /package/dist/{types → typings}/ServiceTicketInteraction.js +0 -0
  173. /package/dist/{types → typings}/ServiceTicketLock.js +0 -0
  174. /package/dist/{types → typings}/ServiceTransfer.d.ts +0 -0
  175. /package/dist/{types → typings}/ServiceTransfer.js +0 -0
  176. /package/dist/{types → typings}/ServiceUpdate.d.ts +0 -0
  177. /package/dist/{types → typings}/ServiceUpdate.js +0 -0
@@ -0,0 +1,225 @@
1
+ ---
2
+ name: framework-amber
3
+ description: >-
4
+ Guides correct use of @t4h.framework/amber in T4H Framework workflows: the
5
+ `Amber` client, the generic `Service` model and the `Ticket` model, the
6
+ workflow-run lock, waiting for an agent to tabulate a ticket, the webhook
7
+ event schema, `AmberWebhook.authorization`, host registration of the
8
+ activities, and how to test workflows that use them. Use when a workflow
9
+ must open or drive Amber tickets, when wiring an Amber webhook channel to a
10
+ host, or when working in packages/amber.
11
+ ---
12
+
13
+ # @t4h.framework/amber
14
+
15
+ Drive an Amber **webhook channel** from a workflow: create tickets, act on
16
+ them, and suspend until something happens on the Amber side (an agent
17
+ tabulates the ticket) without polling. Package path:
18
+ `alexandria/packages/amber`. Peer dependencies: `@t4h.framework/core`, `@t4h.framework/http`, `@t4h.framework/fs`,
19
+ `@t4h.framework/cache`, `typebox`.
20
+
21
+ ## Import surface
22
+
23
+ Import from the package root only. Everything else under `src/` (form
24
+ builders, message converters, webhook header constants, schema factories) is
25
+ internal and not exported.
26
+
27
+ ```typescript
28
+ import {
29
+ Amber,
30
+ Service,
31
+ Ticket,
32
+ AmberWebhook,
33
+ AMBER_WEBHOOK_EVENT_TYPES,
34
+ AmberServiceTabulateEventSchema,
35
+ type AmberConfig,
36
+ type ServiceRequestConfig,
37
+ } from '@t4h.framework/amber'
38
+ ```
39
+
40
+ `Service` is the generic base (`transfer`, `tabulate`, `update`, `finish`);
41
+ `Ticket` adds the ticket-only methods. Workflow code uses **`Amber` /
42
+ `Ticket`**. The activity classes (`Amber*Activity`) are exported so hosts can
43
+ register them; workflow code never instantiates them.
44
+
45
+ ## Configuration
46
+
47
+ ```typescript
48
+ const amber = new Amber({
49
+ url: env.AMBER_URL, // Amber API root, e.g. https://amber.example.com
50
+ tenant: env.AMBER_TENANT,
51
+ channel: env.AMBER_CHANNEL, // the webhook channel id
52
+ clientId: env.AMBER_CLIENT_ID,
53
+ clientSecret: env.AMBER_CLIENT_SECRET,
54
+ })
55
+ ```
56
+
57
+ Every request goes to `{url}/v1/tenants/{tenant}/channels/{channel}` with the
58
+ channel credentials as basic auth. Secrets come from `env`, never literals.
59
+ Every method takes an optional last argument `{ retry }` (`ServiceRequestConfig`)
60
+ forwarded to the HTTP activity.
61
+
62
+ ## Tickets
63
+
64
+ ```typescript
65
+ const ticket = await amber.createTicket({
66
+ protocol: 'P-123',
67
+ skill: 'skill-id',
68
+ tabulationOption: 'option-id',
69
+ customers: [{ isOwner: true, type: 'customer' }],
70
+ fields: { customer: [{ name: 'email', value: 'a@b.c' }] },
71
+ })
72
+
73
+ await ticket.comment({ type: 'public', content: 'Looking into it' })
74
+ await ticket.interact({ content: 'Hello', contentType: 'text/plain' })
75
+ await ticket.updateField({ field: 'field-id', value: 'new value' })
76
+ const fields = await ticket.fields()
77
+ await ticket.lock({ expiresAt: new Date(Date.now() + 3600_000) })
78
+ await ticket.releaseLock()
79
+ await ticket.tabulate({ tabulationOption: 'option-id', notes: [{ type: 'public', content: 'ok' }] })
80
+ await ticket.finish() // update({ status: 'finished' })
81
+
82
+ const again = await amber.getTicket(ticket.id) // rejects if the service is not a ticket
83
+ ```
84
+
85
+ ### The workflow lock
86
+
87
+ A ticket is **born locked** with `ref` = the workflow unique identifier
88
+ (`GetWorkflowUniqueIdentifierClaim`), so no agent picks it up while the workflow
89
+ still works on it. `lock`, `releaseLock` and the `lockRelease` of a transfer all
90
+ use the same ref, which is why they need no state passed between them.
91
+
92
+ - `createTicket({ lock: false })` creates it unlocked.
93
+ - `createTicket({ lock: { expiresAt, metadata } })` customises the lock.
94
+ - The ref is never user-supplied; do not try to release a lock owned by
95
+ another workflow.
96
+
97
+ ### Handing the ticket to a human and waiting
98
+
99
+ ```typescript
100
+ const transfer = await ticket.transfer({
101
+ skill: 'human-skill-id',
102
+ status: 'in-queue',
103
+ })
104
+
105
+ const { tabulation } = await transfer.wait()
106
+ tabulation?.tabulationOption.id
107
+ tabulation?.notes
108
+ ```
109
+
110
+ - `transfer` (like every async activity bound through `History.bind`) returns
111
+ an `AsyncActivityAwaitable`; the output comes from `await transfer.wait()`.
112
+ Do other work between the two awaits if you need to.
113
+ - `status: 'in-queue'` releases the workflow lock and `wait()` **suspends** the
114
+ workflow until an agent tabulates the ticket (`service:tabulate` event).
115
+ Informative tabulations are ignored; the wait continues.
116
+ - A transfer to a `user` or without `status: 'in-queue'` settles at once and
117
+ `wait()` resolves with `{ service, serviceTransfer }` and no `tabulation`.
118
+ Add `lockRelease: true` to release the lock on those too.
119
+ - There is no timeout on the transfer wait. Wrap it in your own deadline logic
120
+ if the workflow must not hang forever.
121
+ - An HTTP status other than 200 on the transfer request rejects the activity.
122
+
123
+ ## Activities (host registration)
124
+
125
+ Every model method is an activity recorded in the history and replayable.
126
+ Hosts register them by class:
127
+
128
+ | Activity | Kind | Claims used |
129
+ |---|---|---|
130
+ | `AmberCreateTicketActivity` | HTTP | `HttpClientRequestClaim`, `FileSystemClaim`, `GetWorkflowUniqueIdentifierClaim` |
131
+ | `AmberLockTicketActivity`, `AmberReleaseTicketLockActivity` | HTTP | same as above |
132
+ | `AmberGetTicketActivity`, `AmberCommentTicketActivity`, `AmberInteractTicketActivity`, `AmberFindTicketFieldsActivity`, `AmberUpdateTicketFieldValueActivity` | HTTP | `HttpClientRequestClaim`, `FileSystemClaim` |
133
+ | `AmberTabulateServiceActivity`, `AmberUpdateServiceActivity` | HTTP | `HttpClientRequestClaim`, `FileSystemClaim` |
134
+ | `AmberTransferServiceActivity` | **Async** | `HttpClientRequestClaim`, `GetWorkflowUniqueIdentifierClaim` |
135
+
136
+ HTTP activities extend `AbstractAmberHttpRequestActivity`, which extends the
137
+ `http` package's `AbstractHttpRequestActivity` (hence `FileSystemClaim`, where
138
+ the response body is persisted). Extend it only when adding a new Amber
139
+ endpoint to this package.
140
+
141
+ ## Webhook channel and host contract
142
+
143
+ Amber emits events (`service:tabulate`) to the URL configured on the webhook
144
+ channel. Point it at the **events route** of the workflow on the host that
145
+ runs it:
146
+
147
+ ```
148
+ POST {runtime}/tenants/{tenant}/projects/{project}/workflows/{workflow}/events
149
+ ```
150
+
151
+ Nothing is stored on the Amber side to find the run back (no metadata, no ids
152
+ in the ticket). The host must:
153
+
154
+ 1. Ask each pending async activity for `toCorrelationKey(event)`.
155
+ `AmberTransferServiceActivity` answers with the Amber **service id** taken
156
+ from `event.body.data.service.id`, or `undefined` when the event is not
157
+ theirs (it also ignores `isInformative: true`).
158
+ 2. Verify the signature with the `auth` the pending declares:
159
+ `AmberWebhook.authorization(channelUrl)` returns an
160
+ `AsyncActivityCallbackAuthJwks` (detached signature over `{timestamp}.{body}`,
161
+ key resolved by `kid` at `{url}/tenants/{tenant}/.well-known/jwks.json`,
162
+ 300 s tolerance). The host needs the `jwks` authorizer from
163
+ `@t4h.framework/jwks/callback` and the **raw body**.
164
+ 3. Validate the body against the pending `schema`
165
+ (`AmberServiceTabulateEventSchema`) and advance.
166
+
167
+ `AmberWebhook.isEvent(body, type)` and `AmberWebhook.serviceId(event, type)`
168
+ are the helpers the activities use and are safe for host-side routing.
169
+ `AMBER_WEBHOOK_EVENT_TYPES` holds the event type strings; Amber may prefix
170
+ them (`amber.service:tabulate`), the matchers accept both.
171
+
172
+ **One webhook channel serves one workflow.** A project with several Amber
173
+ workflows needs one channel per workflow, because correlation is by service id
174
+ only.
175
+
176
+ ## Testing
177
+
178
+ Test the **workflow**, not the activities, with `TestWorkflowEnvironment`
179
+ from `@t4h.framework/core/testing` (see the **framework-workflow-testing**
180
+ skill). Provide:
181
+
182
+ - `HttpClientRequestClaim` and `FileSystemClaim` mocks for the HTTP activities
183
+ (same shape as in the **framework-http** skill). Create/get responses must be
184
+ `200` with a JSON body carrying `id` and, for `get`, `type: 'ticket'`.
185
+ - `GetWorkflowUniqueIdentifierClaim` returning a fixed string; it becomes the
186
+ lock `ref` you can assert on.
187
+ - `mockAsync()` outcomes for the async activity:
188
+
189
+ ```typescript
190
+ import { mockAsync, fulfilled, rejected } from '@t4h.framework/core/testing'
191
+ import { AmberTransferServiceActivity } from '@t4h.framework/amber'
192
+
193
+ mockAsyncActivity: mockAsync().on(
194
+ AmberTransferServiceActivity,
195
+ fulfilled({
196
+ service: 'svc-1',
197
+ serviceTransfer: 'transfer-1',
198
+ tabulation: {
199
+ id: 'tabulation-1',
200
+ name: 'Outcome',
201
+ tabulationOption: { id: 'opt-1', name: 'Resolved' },
202
+ notes: [],
203
+ },
204
+ }),
205
+ )
206
+ ```
207
+
208
+ Use `rejected({ reason: 'timeout', service: 'svc-1', serviceTransfer: 'transfer-1' })`
209
+ to exercise the transfer timeout path.
210
+
211
+ ## Pitfalls
212
+
213
+ - Do not import from `@t4h.framework/amber/dist/...` or `src/...`; only the root
214
+ export is stable.
215
+ - Do not create the ticket unlocked and lock it later "to be safe"; the default
216
+ lock already covers the window between creation and the first transfer.
217
+ - `ticket.transfer` returns an awaitable, not the output. Forgetting `.wait()`
218
+ gives you an object with no `tabulation` and no type error at the call site.
219
+ - `ticket.transfer` without `status: 'in-queue'` does **not** wait. If the
220
+ workflow expects a tabulation, it must send `in-queue`.
221
+ - `transfer` without `timeoutInMs` suspends indefinitely if nobody tabulates.
222
+ - `amber.getTicket` on a service that is not a ticket rejects; the model
223
+ returned by `createTicket` is already the right type.
224
+ - `Amber` and `Ticket` hold credentials in memory only; they are rebuilt from
225
+ the activity output on replay, never persisted by you.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tech for humans
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @t4h.framework/amber
2
2
 
3
- Amber module for the [T4H Framework](https://github.com/tech4humans-brasil/alexandria). It provides a client for the Amber service API with support for creating and managing service tickets, using OAuth2 client credentials (LapisLazuli) for authentication.
3
+ Amber module for the [T4H Framework](https://github.com/tech4humans-brasil/alexandria). It drives an Amber **webhook channel** from a workflow: create tickets, act on them, and wait for what happens on the Amber side (an agent tabulating a ticket) without polling.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,107 +8,117 @@ Amber module for the [T4H Framework](https://github.com/tech4humans-brasil/alexa
8
8
  yarn add @t4h.framework/amber
9
9
  ```
10
10
 
11
- **Peer dependencies:** `@t4h.framework/core`, `@t4h.framework/http`, `@t4h.framework/metadata`, `@t4h.framework/runtime-claims`, and `typebox`.
11
+ **Peer dependencies:** `@t4h.framework/core`, `@t4h.framework/http`, `@t4h.framework/fs`, `@t4h.framework/cache` and `typebox`.
12
12
 
13
13
  ## Configuration
14
14
 
15
- Create a `Amber` instance with the Amber base URL and LapisLazuli OAuth2 credentials:
16
-
17
15
  ```ts
18
16
  import { Amber } from '@t4h.framework/amber'
19
17
 
20
18
  const amber = new Amber({
21
- url: 'https://your-amber-api.example.com',
22
- auth: {
23
- tokenUrl: 'https://auth.example.com/oauth/token',
24
- clientId: 'your-client-id',
25
- clientSecret: 'your-client-secret',
26
- tenantId: 'your-tenant-id',
27
- },
19
+ url: 'https://amber.example.com', // Amber API root
20
+ tenant: 'your-tenant-id',
21
+ channel: 'your-webhook-channel-id',
22
+ clientId: 'channel-client-id',
23
+ clientSecret: 'channel-client-secret',
28
24
  })
29
25
  ```
30
26
 
31
- ## Usage
27
+ Every call goes to `{url}/v1/tenants/{tenant}/channels/{channel}` with the channel credentials as basic auth.
28
+
29
+ ### Point the channel webhook at the workflow
30
+
31
+ Amber emits its events (`service:tabulate`, …) to the URL configured on the webhook channel. Set it to the **events route** of the workflow that uses this package, on the host that runs it:
32
+
33
+ ```
34
+ POST {runtime}/tenants/{tenant}/projects/{project}/workflows/{workflow}/events
35
+ ```
36
+
37
+ The host asks the waiting activities which event is theirs (`toCorrelationKey`, keyed by the Amber service id), verifies the signature Amber puts on every event (detached signature over `timestamp.body`, key resolved by `kid` at `{url}/tenants/{tenant}/.well-known/jwks.json`) and advances the right wait. Nothing is stored on the Amber side to find the run back: no metadata, no ids in the ticket.
38
+
39
+ One webhook channel serves one workflow. A project with several Amber workflows needs one channel per workflow.
32
40
 
33
- ### Creating a ticket
41
+ ## Tickets
34
42
 
35
43
  ```ts
36
44
  const ticket = await amber.createTicket({
37
- input: {
38
- type: 'ticket',
39
- channel: 'your-channel',
40
- protocol: 'protocol-id',
41
- skill: 'skill-id',
42
- tabulationOption: 'option-id',
43
- customers: [
44
- {
45
- isOwner: true,
46
- type: 'customer-type',
47
- },
48
- ],
49
- },
45
+ protocol: 'P-123',
46
+ skill: 'skill-id',
47
+ tabulationOption: 'option-id',
48
+ customers: [{ isOwner: true, type: 'customer' }],
49
+ fields: { customer: [{ name: 'email', value: 'a@b.c' }] },
50
+ })
51
+ ```
52
+
53
+ A ticket is **born locked** by the workflow (`lock: { ref: <workflow id> }`), so no agent picks it up while the workflow still works on it. Pass `lock: false` to create it unlocked, or `lock: { expiresAt, metadata }` to customize the lock.
54
+
55
+ The lock `ref` is the **workflow id** the host reports through `GetWorkflowUniqueIdentifierClaim` (`amber-ticket` for a workflow declared with `id: 'amber-ticket'`), not the id of the run. `lock()`, `releaseLock()` and the lock release of `transfer()` use the same `ref`, so every run of a workflow can release a lock another run of it took.
56
+
57
+ A locked ticket still takes comments, interactions and field updates from the workflow, but Amber answers `423` to a `lock()` while a lock exists (release first, lock again) and to a `tabulate()` while the ticket is locked, even by the workflow itself. Release the lock before tabulating or finishing the ticket. Transfers release it for you with `status: 'in-queue'` or `lockRelease: true`.
58
+
59
+ ```ts
60
+ await ticket.comment({ type: 'public', content: 'Looking into it' })
61
+ await ticket.interact({ content: 'Hello', contentType: 'text/plain' })
62
+ await ticket.updateField({ field: 'field-id', value: 'new value' })
63
+ const fields = await ticket.fields()
64
+
65
+ await ticket.lock({ expiresAt: new Date(Date.now() + 3600_000) })
66
+ await ticket.releaseLock()
67
+ ```
68
+
69
+ ### Handing the ticket to a human and waiting
70
+
71
+ ```ts
72
+ const transfer = await ticket.transfer({
73
+ skill: 'human-skill-id',
74
+ status: 'in-queue',
50
75
  })
76
+
77
+ const { tabulation } = await transfer.wait()
51
78
  ```
52
79
 
53
- `createTicket` returns a `Ticket` instance you can use to perform further actions.
80
+ `transfer` returns an awaitable. Transferring to `in-queue` **releases the workflow lock**, and `wait()` suspends the workflow until an agent tabulates the ticket, resolving with the tabulation the agent chose (`tabulation.tabulationOption`, `tabulation.notes`). Informative tabulations are ignored. A transfer to a user or without `status: 'in-queue'` settles at once and `wait()` resolves without `tabulation`; add `lockRelease: true` to release the lock on those too.
54
81
 
55
- ### Getting a ticket
82
+ The wait has no deadline by default. Pass `timeoutInMs` in the second argument, next to `retry`, to bound it; `wait()` then rejects with `{ reason: 'timeout', service, serviceTransfer }` when the agent has not tabulated in time:
56
83
 
57
84
  ```ts
58
- const ticket = await amber.getTicket({ id: 'ticket-id' })
85
+ const transfer = await ticket.transfer(
86
+ { skill: 'human-skill-id', status: 'in-queue' },
87
+ { timeoutInMs: 24 * 60 * 60 * 1000, retry: true },
88
+ )
59
89
  ```
60
90
 
61
- ### Working with a ticket
91
+ When the transfer released the lock (`status: 'in-queue'` or `lockRelease: true`), `wait()` on a **ticket** **locks it back** for the workflow before resolving, with no expiration, so no agent picks it up again while the workflow finishes it. Pass `lock: false` in the second argument to skip that, or `lock: { expiresAt, metadata }` to customize the lock. The lock is a separate `AmberLockTicketActivity` recorded after the transfer, and a refusal by Amber rejects `wait()` with its `AmberRequestError`.
62
92
 
63
- Once you have a `Ticket` (from `createTicket` or `getTicket`), you can:
93
+ ```ts
94
+ const transfer = await ticket.transfer(
95
+ { skill: 'human-skill-id', status: 'in-queue' },
96
+ { lock: { expiresAt: new Date(Date.now() + 3600_000) } },
97
+ )
64
98
 
65
- - **Comment** — add a comment to the ticket
66
- - **Interact** — record a service interaction
67
- - **Tabulate** — update tabulation data
68
- - **Transfer** — transfer the ticket
69
- - **Update** — update ticket fields
70
- - **Finish** — set the ticket status to finished
99
+ const { tabulation } = await transfer.wait() // ticket locked again here
100
+ ```
71
101
 
72
102
  ```ts
73
- await ticket.comment({ input: { body: 'Comment text' } })
74
- await ticket.interact({
75
- input: {
76
- /* interaction data */
77
- },
78
- })
79
103
  await ticket.tabulate({
80
- input: {
81
- /* tabulation data */
82
- },
83
- })
84
- await ticket.transfer({
85
- input: {
86
- /* transfer data */
87
- },
104
+ tabulationOption: 'option-id',
105
+ notes: [{ type: 'public', content: 'ok' }],
88
106
  })
89
- await ticket.update({ input: { status: 'in-attendance' } })
90
107
  await ticket.finish()
91
108
  ```
92
109
 
93
- ## Activities
94
-
95
- The package also exports individual activities for use within T4H workflows:
110
+ ## Errors
96
111
 
97
- - `AmberCreateTicketActivity`
98
- - `AmberGetTicketActivity`
99
- - `AmberCommentTicketActivity`
100
- - `AmberInteractTicketActivity`
101
- - `AmberTabulateTicketActivity`
102
- - `AmberTransferTicketActivity`
103
- - `AmberUpdateTicketActivity`
112
+ Every call that Amber answers with a status other than `200` rejects with an `AmberRequestError`. Its `message` carries the status and the response body, which is where Amber says what it refused, so the reason shows up in any log that prints only the message:
104
113
 
105
- These are used internally by `Amber` and `Ticket`; use the `Amber`/`Ticket` API unless you need to plug activities directly into your workflow.
114
+ ```
115
+ Failed to create ticket: Amber responded 400 {"errors":{"$.tabulationOption":["Not found tabulation option"]}}
116
+ ```
106
117
 
107
- ## Requirements
118
+ The same data is available as `error.status`, `error.body` and `error.cause` (`{ httpStatusCode, body }`). Bodies longer than 2000 characters are truncated. The activity that waits on Amber events, `transfer()`, rejects its awaitable with that message as the payload instead.
108
119
 
109
- - **Node.js** ≥ 22
110
- - T4H Framework peer packages
120
+ ## Activities
111
121
 
112
- ## License
122
+ Every method above is an activity, recorded in the workflow history and replayable. Hosts register them by class: `AmberCreateTicketActivity`, `AmberGetTicketActivity`, `AmberCommentTicketActivity`, `AmberInteractTicketActivity`, `AmberTabulateServiceActivity`, `AmberTransferServiceActivity`, `AmberUpdateServiceActivity`, `AmberLockTicketActivity`, `AmberReleaseTicketLockActivity`, `AmberFindTicketFieldsActivity`, `AmberUpdateTicketFieldValueActivity`.
113
123
 
114
- MIT © [Tech4Humans](https://tech4h.com.br)
124
+ `AmberTransferServiceActivity` is the one that waits on Amber events; the schema it validates the events against (`AmberServiceTabulateEventSchema`) and the `auth` it declares (`AmberWebhook.authorization(channelUrl)`) are exported by the package.
@@ -1,9 +1,6 @@
1
- import { AbstractHttpRequestActivity, type HttpRequestActivityInput, type HttpRequestActivityOutput } from '@t4h.framework/http';
1
+ import { AbstractHttpRequestActivity, type HttpRequestActivityInput, type HttpRequestActivityOutput, type HttpRequestBasicAuth } from '@t4h.framework/http';
2
2
  export type AmberHttpRequestActivityInput = HttpRequestActivityInput & {
3
- auth: {
4
- username: string;
5
- password: string;
6
- };
3
+ auth: HttpRequestBasicAuth;
7
4
  };
8
5
  export declare abstract class AbstractAmberHttpRequestActivity<TArgs extends readonly any[], TInput extends AmberHttpRequestActivityInput, TOutput = any> extends AbstractHttpRequestActivity<TArgs, TInput, HttpRequestActivityOutput, TOutput> {
9
6
  protected toHttpInput(input: AmberHttpRequestActivityInput): HttpRequestActivityInput;
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractAmberHttpRequestActivity.d.ts","sourceRoot":"","sources":["../../src/activities/AbstractAmberHttpRequestActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAA;AAE5B,MAAM,MAAM,6BAA6B,GAAG,wBAAwB,GAAG;IACrE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7C,CAAA;AAED,8BAAsB,gCAAgC,CACpD,KAAK,SAAS,SAAS,GAAG,EAAE,EAC5B,MAAM,SAAS,6BAA6B,EAC5C,OAAO,GAAG,GAAG,CACb,SAAQ,2BAA2B,CACnC,KAAK,EACL,MAAM,EACN,yBAAyB,EACzB,OAAO,CACR;IACC,SAAS,CAAC,WAAW,CACnB,KAAK,EAAE,6BAA6B,GACnC,wBAAwB;IAgB3B,SAAS,CAAC,YAAY,CACpB,MAAM,EAAE,yBAAyB,GAChC,yBAAyB;CAG7B"}
1
+ {"version":3,"file":"AbstractAmberHttpRequestActivity.d.ts","sourceRoot":"","sources":["../../src/activities/AbstractAmberHttpRequestActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAE5B,MAAM,MAAM,6BAA6B,GAAG,wBAAwB,GAAG;IACrE,IAAI,EAAE,oBAAoB,CAAA;CAC3B,CAAA;AAED,8BAAsB,gCAAgC,CACpD,KAAK,SAAS,SAAS,GAAG,EAAE,EAC5B,MAAM,SAAS,6BAA6B,EAC5C,OAAO,GAAG,GAAG,CACb,SAAQ,2BAA2B,CACnC,KAAK,EACL,MAAM,EACN,yBAAyB,EACzB,OAAO,CACR;IACC,SAAS,CAAC,WAAW,CACnB,KAAK,EAAE,6BAA6B,GACnC,wBAAwB;IAgB3B,SAAS,CAAC,YAAY,CACpB,MAAM,EAAE,yBAAyB,GAChC,yBAAyB;CAG7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractAmberHttpRequestActivity.js","sourceRoot":"","sources":["../../src/activities/AbstractAmberHttpRequestActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,GAG5B,MAAM,qBAAqB,CAAA;AAM5B,MAAM,OAAgB,gCAIpB,SAAQ,2BAKT;IACW,WAAW,CACnB,KAAoC;QAEpC,MAAM,SAAS,GAA6B;YAC1C,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAA;QAED,IAAI,KAAK,CAAC,MAAM;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;QAEjD,IAAI,KAAK,CAAC,IAAI;YAAE,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QAE3C,IAAI,KAAK,CAAC,KAAK;YAAE,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;QAE9C,OAAO,SAAS,CAAA;IAClB,CAAC;IAES,YAAY,CACpB,MAAiC;QAEjC,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
1
+ {"version":3,"file":"AbstractAmberHttpRequestActivity.js","sourceRoot":"","sources":["../../src/activities/AbstractAmberHttpRequestActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,GAI5B,MAAM,qBAAqB,CAAA;AAM5B,MAAM,OAAgB,gCAIpB,SAAQ,2BAKT;IACW,WAAW,CACnB,KAAoC;QAEpC,MAAM,SAAS,GAA6B;YAC1C,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;YAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;SACjB,CAAA;QAED,IAAI,KAAK,CAAC,MAAM;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAA;QAEjD,IAAI,KAAK,CAAC,IAAI;YAAE,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;QAE3C,IAAI,KAAK,CAAC,KAAK;YAAE,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAA;QAE9C,OAAO,SAAS,CAAA;IAClB,CAAC;IAES,YAAY,CACpB,MAAiC;QAEjC,OAAO,MAAM,CAAA;IACf,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import { AbstractAmberHttpRequestActivity, type AmberHttpRequestActivityInput } from './AbstractAmberHttpRequestActivity.js';
2
+ import type { ServiceTabulationInput } from '../typings/ServiceTabulate.js';
3
+ export type AmberTabulateServiceActivityInput = ServiceTabulationInput & {
4
+ id: string;
5
+ };
6
+ export declare class AmberTabulateServiceActivity extends AbstractAmberHttpRequestActivity<readonly [AmberTabulateServiceActivityInput, AmberHttpRequestActivityInput], AmberHttpRequestActivityInput> {
7
+ toInput(input: AmberTabulateServiceActivityInput, settings: AmberHttpRequestActivityInput): AmberHttpRequestActivityInput;
8
+ toOutput(output: any, input: AmberTabulateServiceActivityInput): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=AmberTabulateServiceActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmberTabulateServiceActivity.d.ts","sourceRoot":"","sources":["../../src/activities/AmberTabulateServiceActivity.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,gCAAgC,EAChC,KAAK,6BAA6B,EACnC,MAAM,uCAAuC,CAAA;AAE9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAE3E,MAAM,MAAM,iCAAiC,GAAG,sBAAsB,GAAG;IACvE,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,qBAAa,4BAA6B,SAAQ,gCAAgC,CAChF,SAAS,CAAC,iCAAiC,EAAE,6BAA6B,CAAC,EAC3E,6BAA6B,CAC9B;IACQ,OAAO,CACZ,KAAK,EAAE,iCAAiC,EACxC,QAAQ,EAAE,6BAA6B,GACtC,6BAA6B;IAWnB,QAAQ,CACnB,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,IAAI,CAAC;CASjB"}
@@ -0,0 +1,20 @@
1
+ import { Response } from '@t4h.framework/http';
2
+ import { AbstractAmberHttpRequestActivity, } from './AbstractAmberHttpRequestActivity.js';
3
+ import { AmberRequestError } from '../errors/AmberRequestError.js';
4
+ export class AmberTabulateServiceActivity extends AbstractAmberHttpRequestActivity {
5
+ toInput(input, settings) {
6
+ const { id, ...tabulation } = input;
7
+ return {
8
+ ...settings,
9
+ url: `${settings.url}/services/${id}/tabulations`,
10
+ method: 'POST',
11
+ body: { json: tabulation },
12
+ };
13
+ }
14
+ async toOutput(output, input) {
15
+ const response = new Response(output);
16
+ if (response.status !== 200)
17
+ throw await AmberRequestError.from(`Failed to tabulate service ${input.id}`, response);
18
+ }
19
+ }
20
+ //# sourceMappingURL=AmberTabulateServiceActivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmberTabulateServiceActivity.js","sourceRoot":"","sources":["../../src/activities/AmberTabulateServiceActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,OAAO,EACL,gCAAgC,GAEjC,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAOlE,MAAM,OAAO,4BAA6B,SAAQ,gCAGjD;IACQ,OAAO,CACZ,KAAwC,EACxC,QAAuC;QAEvC,MAAM,EAAE,EAAE,EAAE,GAAG,UAAU,EAAE,GAAG,KAAK,CAAA;QAEnC,OAAO;YACL,GAAG,QAAQ;YACX,GAAG,EAAE,GAAG,QAAQ,CAAC,GAAG,aAAa,EAAE,cAAc;YACjD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;SAC3B,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,QAAQ,CACnB,MAAW,EACX,KAAwC;QAExC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAA;QAErC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YACzB,MAAM,MAAM,iBAAiB,CAAC,IAAI,CAChC,8BAA8B,KAAK,CAAC,EAAE,EAAE,EACxC,QAAQ,CACT,CAAA;IACL,CAAC;CACF"}
@@ -0,0 +1,86 @@
1
+ import { AsyncActivity, type AsyncActivityCallback, type AsyncActivityResultPending } from '@t4h.framework/core';
2
+ import type { Type } from 'typebox';
3
+ import type { AmberHttpRequestActivityInput } from './AbstractAmberHttpRequestActivity.js';
4
+ import { AmberServiceTabulateEventSchema } from '../inputs/AmberServiceTabulateEvent.js';
5
+ import type { ServiceTransferInput } from '../typings/ServiceTransfer.js';
6
+ export type AmberTransferServiceActivityInput = ServiceTransferInput & {
7
+ id: string;
8
+ /**
9
+ * How long an `in-queue` transfer waits for the agent's tabulation before
10
+ * rejecting with `{ reason: 'timeout' }`. Waits indefinitely when omitted.
11
+ */
12
+ timeoutInMs?: number;
13
+ };
14
+ export type AmberTransferServiceActivityBootstrap = {
15
+ service: string;
16
+ serviceTransfer: string;
17
+ };
18
+ export type AmberTransferServiceActivityOutput = AmberTransferServiceActivityBootstrap & {
19
+ tabulation?: {
20
+ id: string;
21
+ name: string;
22
+ tabulationOption: {
23
+ id: string;
24
+ name: string;
25
+ };
26
+ notes: {
27
+ id: string;
28
+ type: 'public' | 'private';
29
+ content: string;
30
+ createdAt: string;
31
+ }[];
32
+ };
33
+ };
34
+ type AmberTransferServiceActivityBootstrapInput = AmberTransferServiceActivityInput & {
35
+ settings: AmberHttpRequestActivityInput;
36
+ };
37
+ export declare class AmberTransferServiceActivity extends AsyncActivity<readonly [AmberTransferServiceActivityInput, AmberHttpRequestActivityInput], AmberTransferServiceActivityBootstrapInput, AmberTransferServiceActivityOutput, AmberTransferServiceActivityOutput, AmberTransferServiceActivityBootstrap, typeof AmberServiceTabulateEventSchema> {
38
+ private readonly claims;
39
+ toInput(input: AmberTransferServiceActivityInput, settings: AmberHttpRequestActivityInput): AmberTransferServiceActivityBootstrapInput;
40
+ bootstrap(input: AmberTransferServiceActivityBootstrapInput): Promise<AsyncActivityResultPending<AmberTransferServiceActivityBootstrap, Type.TObject<{
41
+ specversion: Type.TString;
42
+ id: Type.TString;
43
+ type: Type.TString;
44
+ source: Type.TString;
45
+ subject: Type.TString;
46
+ time: Type.TString;
47
+ data: Type.TObject<{
48
+ id: Type.TString;
49
+ isInformative: Type.TBoolean;
50
+ tabulationOption: Type.TObject<{
51
+ id: Type.TString;
52
+ name: Type.TString;
53
+ tabulation: Type.TObject<{
54
+ id: Type.TString;
55
+ name: Type.TString;
56
+ }>;
57
+ }>;
58
+ serviceTransfer: Type.TObject<{
59
+ id: Type.TString;
60
+ skill: Type.TObject<{
61
+ id: Type.TString;
62
+ name: Type.TString;
63
+ }>;
64
+ }>;
65
+ notes: Type.TArray<Type.TObject<{
66
+ id: Type.TString;
67
+ type: Type.TUnion<[Type.TLiteral<"public">, Type.TLiteral<"private">]>;
68
+ content: Type.TString;
69
+ createdAt: Type.TString;
70
+ }>>;
71
+ service: Type.TObject<{
72
+ id: Type.TString;
73
+ }>;
74
+ tenant: Type.TObject<{
75
+ id: Type.TString;
76
+ name: Type.TOptional<Type.TString>;
77
+ }>;
78
+ }>;
79
+ }>> | import("@t4h.framework/core").AsyncActivityResultRejected<void | import("@t4h.framework/core").Serializable> | import("@t4h.framework/core").AsyncActivityResultFulfilled<AmberTransferServiceActivityOutput | undefined>>;
80
+ toCorrelationKey(event: AsyncActivityCallback.Event): string | undefined;
81
+ advance(event: Type.Static<typeof AmberServiceTabulateEventSchema>): import("@t4h.framework/core").AsyncActivityResultFulfilled<AmberTransferServiceActivityOutput | undefined>;
82
+ onTimeout(bootstrap: AsyncActivityResultPending): import("@t4h.framework/core").AsyncActivityResultRejected<void | import("@t4h.framework/core").Serializable>;
83
+ toOutput(output: AmberTransferServiceActivityOutput): AmberTransferServiceActivityOutput;
84
+ }
85
+ export {};
86
+ //# sourceMappingURL=AmberTransferServiceActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmberTransferServiceActivity.d.ts","sourceRoot":"","sources":["../../src/activities/AmberTransferServiceActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAIb,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAEnC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAA;AAG1F,OAAO,EAAE,+BAA+B,EAAE,MAAM,wCAAwC,CAAA;AAExF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAEzE,MAAM,MAAM,iCAAiC,GAAG,oBAAoB,GAAG;IACrE,EAAE,EAAE,MAAM,CAAA;IACV;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qCAAqC,GAAG;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,kCAAkC,GAC5C,qCAAqC,GAAG;IACtC,UAAU,CAAC,EAAE;QACX,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,gBAAgB,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAA;QAC9C,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAA;YACV,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAA;YAC1B,OAAO,EAAE,MAAM,CAAA;YACf,SAAS,EAAE,MAAM,CAAA;SAClB,EAAE,CAAA;KACJ,CAAA;CACF,CAAA;AAEH,KAAK,0CAA0C,GAC7C,iCAAiC,GAAG;IAClC,QAAQ,EAAE,6BAA6B,CAAA;CACxC,CAAA;AAEH,qBAAa,4BAA6B,SAAQ,aAAa,CAC7D,SAAS,CAAC,iCAAiC,EAAE,6BAA6B,CAAC,EAC3E,0CAA0C,EAC1C,kCAAkC,EAClC,kCAAkC,EAClC,qCAAqC,EACrC,OAAO,+BAA+B,CACvC;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;IAEK,OAAO,CACZ,KAAK,EAAE,iCAAiC,EACxC,QAAQ,EAAE,6BAA6B,GACtC,0CAA0C;IAIhC,SAAS,CAAC,KAAK,EAAE,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAyDxD,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,KAAK;IAe5D,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,+BAA+B,CAAC;IAuBzD,SAAS,CAAC,SAAS,EAAE,0BAA0B;IAYxD,QAAQ,CACb,MAAM,EAAE,kCAAkC,GACzC,kCAAkC;CAGtC"}