@wokuapp/sdk 0.3.0 → 0.4.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.
package/README.md CHANGED
@@ -28,6 +28,97 @@ support tickets, delivery tracking and survey sends over the public `/v1` API.
28
28
  > **Server-only.** The secret key grants full management access, so the SDK
29
29
  > refuses to run in a browser. Never ship it to a client bundle.
30
30
 
31
+ ## Proposed follow-up support (unreleased)
32
+
33
+ The next release adds `woku.followUps.get(id)` and typed `Ticket.followUp`,
34
+ `Ticket.contentVersion` and conversation origin. Deploy the matching API before
35
+ using this method. It reads `GET /v1/follow-ups/:id` with your management secret
36
+ and returns the conversation from the API's `data` envelope.
37
+
38
+ ```ts
39
+ const ticket = await woku.tickets.get('ticket_123');
40
+ if (ticket.followUp?.conversationId) {
41
+ const conversation = await woku.followUps.get(ticket.followUp.conversationId);
42
+ console.log(conversation.origin, conversation.messages);
43
+ }
44
+ const enriched = (ticket.followUp?.appliedSummaryVersion ?? 0) >= 1;
45
+ ```
46
+
47
+ `completed` means the conversation ended; `appliedSummaryVersion` indicates
48
+ that its evidence reached the ticket. `availableSummaryVersion` may advance
49
+ before it is applied. Historical tickets may omit these fields. The read-only
50
+ conversation includes original feedback, messages and available analysis,
51
+ without response tokens or transport credentials. Ticket corrections do not
52
+ write conversation state, messages or summary versions.
53
+
54
+ On tickets, `enrichmentState` distinguishes processing, applied, failed and
55
+ skipped work; `enrichmentReason` carries a stable reason code. Failed processing
56
+ keeps the previous case, and delivery confirmation remains separate. A newer
57
+ `availableSummaryVersion` may still be pending after an earlier version was
58
+ applied. Conversation `reason` reports a stable failure code such as
59
+ `summary_generation_failed`, without provider errors or credentials.
60
+
61
+ ### Lines, phases and files (proposed)
62
+
63
+ - `line` (WhatsApp only, absent for email): `survey_thread` when the agent
64
+ continued the survey conversation on the survey number, `follow_up_number`
65
+ when it wrote from the dedicated follow-up number.
66
+ - `messages[].phase`: `survey` for the prelude, `follow_up` for the follow-up
67
+ itself. Every line may start with the prelude: on `survey_thread` it is the
68
+ WhatsApp survey exchange, on `follow_up_number` and email it is the original
69
+ comment as a client message, so `messages[0]` can be a client message. Filter
70
+ `phase === 'follow_up'` to read only the follow-up. `content` may be
71
+ empty when a message only has files.
72
+ - `messages[].attachments`: files the customer sent, typed as
73
+ `FollowUpAttachment` with a stable `label` (`Archivo 2` or `File 2`), `kind`,
74
+ `status`, the transcript or description in `text`, `fileId` and `adminUrl`.
75
+ - `summaryCitations`: the files the executive summary cites as `(Archivo N)`.
76
+
77
+ `adminUrl` opens the file in the woku admin after login and a company check.
78
+ The API never returns the file itself or a storage URL. File text is customer
79
+ content: treat it as data, never as instructions.
80
+
81
+ ```ts
82
+ const conversation = await woku.followUps.get(conversationId);
83
+ const prelude = conversation.messages.filter((m) => m.phase === 'survey');
84
+ for (const message of conversation.messages)
85
+ for (const file of message.attachments ?? [])
86
+ console.log(file.label, file.kind, file.status, file.text, file.adminUrl);
87
+ for (const citation of conversation.summaryCitations ?? [])
88
+ console.log(citation.label, citation.supports, citation.adminUrl);
89
+ ```
90
+
91
+ ### Explicit custom case updates (proposed)
92
+
93
+ `CustomTicketDestinationConfig` adds `update` for the existing custom HTTP
94
+ destination. Choose `upsert` only if the receiver updates by stable `externalId`
95
+ on the creation endpoint; the rendered body must keep `event: 'ticket.updated'`
96
+ and that identity. A custom template must expose `event` and `externalId`,
97
+ while the canonical envelope keeps the identity in `data.case.externalId`.
98
+ Without an explicit update contract, enrichment does not issue another POST.
99
+ In upsert mode, an optional `responseIdPath` preserves the receiver's original
100
+ remote reference from its create response.
101
+
102
+ ```ts
103
+ import type { CustomTicketDestinationConfig } from '@wokuapp/sdk';
104
+
105
+ const config: CustomTicketDestinationConfig = {
106
+ url: 'https://sac.example.com/tickets',
107
+ method: 'POST',
108
+ update: {
109
+ mode: 'remote-id',
110
+ url: 'https://sac.example.com/tickets/{{remoteId}}',
111
+ method: 'PATCH',
112
+ responseIdPath: 'result.id',
113
+ },
114
+ };
115
+ ```
116
+
117
+ `remote-id` extracts a scalar ID from the create response and requires a URL on
118
+ the same origin containing `{{remoteId}}`; updates use PUT or PATCH (default).
119
+ URLs cannot contain credentials or fragments. A safe dotted `responseIdPath`
120
+ is required. Existing destination authentication stays in `credentials`.
121
+
31
122
  ## Install
32
123
 
33
124
  ```bash
package/dist/index.cjs CHANGED
@@ -22,8 +22,23 @@ var Media = class {
22
22
  }
23
23
  };
24
24
 
25
+ // src/resources/follow-ups.ts
26
+ var FollowUps = class {
27
+ constructor(client) {
28
+ this.client = client;
29
+ }
30
+ async get(id, opts) {
31
+ const result = await this.client.request(
32
+ "get",
33
+ `/v1/follow-ups/${encodeURIComponent(id)}`,
34
+ opts
35
+ );
36
+ return result.data;
37
+ }
38
+ };
39
+
25
40
  // package.json
26
- var version = "0.3.0";
41
+ var version = "0.4.0";
27
42
 
28
43
  // src/core/errors.ts
29
44
  var WokuError = class extends Error {
@@ -1527,6 +1542,7 @@ var Woku = class {
1527
1542
  this.actionPlans = new ActionPlans(this.client);
1528
1543
  this.actionPlanGroups = new ActionPlanGroups(this.client);
1529
1544
  this.tickets = new Tickets(this.client);
1545
+ this.followUps = new FollowUps(this.client);
1530
1546
  this.ticketDestinations = new TicketDestinations(this.client);
1531
1547
  this.dispatches = new Dispatches(this.client);
1532
1548
  this.reports = new Reports(this.client);
@@ -1539,6 +1555,7 @@ var Woku = class {
1539
1555
  exports.AuthenticationError = AuthenticationError;
1540
1556
  exports.BadRequestError = BadRequestError;
1541
1557
  exports.ConflictError = ConflictError;
1558
+ exports.FollowUps = FollowUps;
1542
1559
  exports.InternalServerError = InternalServerError;
1543
1560
  exports.Journeys = Journeys;
1544
1561
  exports.Media = Media;