chatwoot-router 0.5.2 → 0.6.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/CHANGELOG.md CHANGED
@@ -7,8 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.6.0] - 2026-10-05
11
+
12
+ ### Added
13
+
14
+ - `routing.kinds.<id>.<name>.label` (default `true`): `false` handles the kind without giving the ticket its label,
15
+ for a kind that is not a kind of ticket, such as a thank-you that is only resolved.
16
+
10
17
  ## [0.5.2] - 2026-10-05
11
18
 
19
+ ### Fixed
20
+
21
+ - Clear a request's timeout once its response has been read. The pending `AbortSignal.timeout` timer kept a
22
+ Durable Object invocation open until it fired, so most alarms were billed and reported at about 60 seconds.
23
+
12
24
  ## [0.5.1] - 2026-10-05
13
25
 
14
26
  ### Fixed
@@ -17,11 +29,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
29
  (`Contact#webhook_data`; users and bots have one), and the router required `type: "contact"`, so it ignored
18
30
  every customer message and a new ticket waited for the five-minute sweep.
19
31
 
20
- ### Fixed
21
-
22
- - Clear a request's timeout once its response has been read. The pending `AbortSignal.timeout` timer kept a
23
- Durable Object invocation open until it fired, so most alarms were billed and reported at about 60 seconds.
24
-
25
32
  ## [0.5.0] - 2026-10-05
26
33
 
27
34
  ### Fixed
@@ -127,7 +134,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
127
134
  `routing_kind`.
128
135
  - The `chatwoot-router-store-config` command and `chatwoot-router/stored-config`, for a configuration in KV.
129
136
 
130
- [Unreleased]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.5.2...HEAD
137
+ [Unreleased]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.6.0...HEAD
138
+ [0.6.0]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.5.2...chatwoot-router@0.6.0
131
139
  [0.5.2]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.5.1...chatwoot-router@0.5.2
132
140
  [0.5.1]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.5.0...chatwoot-router@0.5.1
133
141
  [0.5.0]: https://github.com/Phala-Network/chatwoot-workers/compare/chatwoot-router@0.4.0...chatwoot-router@0.5.0
package/README.md CHANGED
@@ -126,6 +126,7 @@ no unpublished shared package needs installing.
126
126
  | `routing.kinds.<id>.<name>.covers` | 1–1000 characters | required | What the kind is: Jev's criterion for recognizing it. |
127
127
  | `routing.kinds.<id>.<name>.cannedResponse` | short code | unset | The account's Chatwoot canned response sent to the customer once, by the account's agent bot (`CHATWOOT_AGENT_BOT_TOKENS`); handoff if it is missing. |
128
128
  | `routing.kinds.<id>.<name>.status` | `resolved` or `snoozed` | unset | Set instead of routing the ticket (`snoozed`: until the customer's next message), after the reply of a `cannedResponse`; a new customer message reopens it. |
129
+ | `routing.kinds.<id>.<name>.label` | boolean | `true` | Whether the ticket gets the kind's label; `false` for a kind that is not a kind of ticket, such as a thank-you that is only resolved. |
129
130
 
130
131
  ### Secrets
131
132
 
@@ -141,7 +141,12 @@ var configSchema = z2.strictObject({
141
141
  * or `snoozed` until the customer's next message. A new message from the customer
142
142
  * reopens either.
143
143
  */
144
- status: z2.enum(["resolved", "snoozed"]).optional()
144
+ status: z2.enum(["resolved", "snoozed"]).optional(),
145
+ /**
146
+ * Whether the ticket gets the kind's label (the default). False for a kind that is not a kind of
147
+ * ticket, such as a thank-you that is only resolved.
148
+ */
149
+ label: z2.boolean().default(true)
145
150
  })
146
151
  )
147
152
  ).optional()
@@ -93,7 +93,12 @@ var configSchema = z2.strictObject({
93
93
  * or `snoozed` until the customer's next message. A new message from the customer
94
94
  * reopens either.
95
95
  */
96
- status: z2.enum(["resolved", "snoozed"]).optional()
96
+ status: z2.enum(["resolved", "snoozed"]).optional(),
97
+ /**
98
+ * Whether the ticket gets the kind's label (the default). False for a kind that is not a kind of
99
+ * ticket, such as a thank-you that is only resolved.
100
+ */
101
+ label: z2.boolean().default(true)
97
102
  })
98
103
  )
99
104
  ).optional()
@@ -21,6 +21,7 @@ export declare const configSchema: z.ZodObject<{
21
21
  resolved: "resolved";
22
22
  snoozed: "snoozed";
23
23
  }>>;
24
+ label: z.ZodDefault<z.ZodBoolean>;
24
25
  }, z.core.$strict>>>>;
25
26
  }, z.core.$strict>;
26
27
  }, z.core.$strict>;
@@ -363,6 +363,16 @@ function chatwootClient(baseUrl, token, fetch2) {
363
363
  );
364
364
  },
365
365
  /** The account's label names (Chatwoot saves them in lower case). */
366
+ /** The contact's latest 25 conversations, newest first, that this user may see. */
367
+ async contactConversations(accountId2, contactId) {
368
+ const list = await data(
369
+ "list contact conversations",
370
+ client.GET("/api/v1/accounts/{account_id}/contacts/{id}/conversations", {
371
+ params: { path: { account_id: accountId2, id: contactId } }
372
+ })
373
+ );
374
+ return list.payload ?? [];
375
+ },
366
376
  async listLabels(accountId2) {
367
377
  const list = await data(
368
378
  "list labels",
@@ -450,6 +460,7 @@ function toRelayConversation(conversationId, conversation) {
450
460
  priority: conversation.priority ?? null,
451
461
  labels: conversation.labels ?? [],
452
462
  contact: {
463
+ id: meta?.sender?.id ?? null,
453
464
  name: meta?.sender?.name ?? null,
454
465
  email: meta?.sender?.email ?? null,
455
466
  phone: meta?.sender?.phone_number ?? null,
@@ -875,7 +886,7 @@ async function routeConversation(ctx, accountId2, conversationId) {
875
886
  const labels = [
876
887
  .../* @__PURE__ */ new Set([
877
888
  ...current.conversation.labels,
878
- ...[topic, kind ? decision.kind : null].filter((label) => label !== null)
889
+ ...[topic, kind?.label ? decision.kind : null].filter((label) => label !== null)
879
890
  ])
880
891
  ];
881
892
  if (labels.length !== current.conversation.labels.length) await bot.setLabels(accountId2, conversationId, labels);
@@ -1083,7 +1094,12 @@ var configSchema = z5.strictObject({
1083
1094
  * or `snoozed` until the customer's next message. A new message from the customer
1084
1095
  * reopens either.
1085
1096
  */
1086
- status: z5.enum(["resolved", "snoozed"]).optional()
1097
+ status: z5.enum(["resolved", "snoozed"]).optional(),
1098
+ /**
1099
+ * Whether the ticket gets the kind's label (the default). False for a kind that is not a kind of
1100
+ * ticket, such as a thank-you that is only resolved.
1101
+ */
1102
+ label: z5.boolean().default(true)
1087
1103
  })
1088
1104
  )
1089
1105
  ).optional()
@@ -185,6 +185,8 @@ export declare function chatwootClient(baseUrl: string, token: string, fetch: Fe
185
185
  */
186
186
  unassign(accountId: number, conversationId: number): Promise<void>;
187
187
  /** The account's label names (Chatwoot saves them in lower case). */
188
+ /** The contact's latest 25 conversations, newest first, that this user may see. */
189
+ contactConversations(accountId: number, contactId: number): Promise<ChatwootConversation[]>;
188
190
  listLabels(accountId: number): Promise<string[]>;
189
191
  conversationLabels(accountId: number, conversationId: number): Promise<string[]>;
190
192
  /** Replaces the conversation's labels (the spec's "Add Labels" overwrites the list). */
@@ -43,6 +43,8 @@ export interface RelayConversation {
43
43
  priority?: string | null;
44
44
  labels: string[];
45
45
  contact: {
46
+ /** The contact's Chatwoot id. */
47
+ id?: number | null;
46
48
  name?: string | null;
47
49
  email?: string | null;
48
50
  phone?: string | null;
@@ -80,6 +82,8 @@ export interface RelayMessage {
80
82
  /** The Discord avatar of the linked agent who sent the message, if any. */
81
83
  discordAvatarUrl?: string;
82
84
  sender?: {
85
+ /** The Chatwoot id of the contact, user, or agent bot (see `type`). */
86
+ id?: number | null | undefined;
83
87
  name?: string | null | undefined;
84
88
  email?: string | null | undefined;
85
89
  type?: string | null | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatwoot-router",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "Route Chatwoot conversations with TypeSafe Jev on Cloudflare Workers.",
5
5
  "keywords": [
6
6
  "chatwoot",