@north-light/crouter-api 0.3.212 → 0.3.214

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.
@@ -17,6 +17,21 @@ export interface ReviewTicketSummaryDTO {
17
17
  blocked_since: IsoTime;
18
18
  source: TicketSourceDTO;
19
19
  }
20
+ /** One question's recommended option, flat on the wire like every other summary field. */
21
+ export interface RecommendedOptionDTO {
22
+ slot_id: string;
23
+ option_id: string;
24
+ label: string;
25
+ }
26
+ /**
27
+ * What one keypress on an inbox row publishes. `responses` is a complete final response
28
+ * map this daemon already accepts for the ticket, so a client publishes it untouched
29
+ * rather than assembling one from the summary.
30
+ */
31
+ export interface PageFastActionDTO {
32
+ kind: 'answer' | 'acknowledge';
33
+ responses: PageResponsesDTO;
34
+ }
20
35
  export interface PageTicketSummaryDTO {
21
36
  ticket_id: InboxTicketIdDTO;
22
37
  kind: 'page';
@@ -30,6 +45,10 @@ export interface PageTicketSummaryDTO {
30
45
  source: TicketSourceDTO;
31
46
  slot_kinds: string[];
32
47
  awaits_response: boolean;
48
+ /** Omitted when no question recommends an option. */
49
+ recommended_options?: RecommendedOptionDTO[];
50
+ /** Present only on a pending ticket that a row can settle without opening it. */
51
+ fast_action?: PageFastActionDTO;
33
52
  state: 'pending' | 'resolved' | 'canceled' | 'passive';
34
53
  /** Present only on resolved history entries; the stored one-line answer digest. */
35
54
  answer_digest?: string;
@@ -33,7 +33,6 @@ export interface CardEntry {
33
33
  }
34
34
  export interface CardSender {
35
35
  id: string;
36
- name?: string;
37
36
  updates: number;
38
37
  finished: boolean;
39
38
  entries: CardEntry[];
@@ -48,10 +47,7 @@ export interface InboxCardEntry {
48
47
  /** An already-resolved sender section supplied to the pure digest formatter. */
49
48
  export interface InboxCardSection {
50
49
  id: string;
51
- name?: string;
52
50
  entries: readonly InboxCardEntry[];
53
- updates?: number;
54
- finished?: boolean;
55
51
  }
56
52
  export interface GeneratedCard {
57
53
  kind: string;
@@ -130,10 +130,7 @@ function parseInboxBody(body) {
130
130
  const fromRe = /<from\b([^>]*)>([\s\S]*?)<\/from>/g;
131
131
  for (const fromMatch of body.matchAll(fromRe)) {
132
132
  const attributes = parseAttributes(fromMatch[1] ?? '');
133
- if (attributes?.id === undefined || attributes.updates === undefined)
134
- continue;
135
- const updates = Number(attributes.updates);
136
- if (!Number.isFinite(updates))
133
+ if (attributes?.id === undefined)
137
134
  continue;
138
135
  const entries = [];
139
136
  const entryBody = fromMatch[2] ?? '';
@@ -152,10 +149,12 @@ function parseInboxBody(body) {
152
149
  ...(entryAttributes.ref === undefined ? {} : { ref: entryAttributes.ref }),
153
150
  });
154
151
  }
152
+ // `updates` and `finished` are derived from the entry list; pre-cut
153
+ // scrollback still carries them as attributes, honored when present.
154
+ const legacyUpdates = attributes.updates === undefined ? Number.NaN : Number(attributes.updates);
155
155
  senders.push({
156
156
  id: attributes.id,
157
- ...(attributes.name === undefined ? {} : { name: attributes.name }),
158
- updates,
157
+ updates: Number.isFinite(legacyUpdates) ? legacyUpdates : entries.length,
159
158
  finished: attributes.finished === 'true' || entries.some((entry) => entry.kind === 'final'),
160
159
  entries,
161
160
  });
@@ -203,15 +202,13 @@ export function parseCard(message) {
203
202
  /** Format a complete inbox card from report bodies resolved by the caller. */
204
203
  export function formatInboxCard(sections) {
205
204
  const body = sections.map((section) => {
206
- const updates = section.updates ?? section.entries.length;
207
- const finished = section.finished ?? section.entries.some((entry) => entry.kind === 'final');
208
205
  const entries = section.entries.map((entry) => {
209
206
  const disposition = entry.disposition === 'human-answer' || entry.disposition === 'human-canceled'
210
207
  ? entry.disposition
211
208
  : undefined;
212
209
  return `<entry${formatAttributes({ kind: entry.kind, ref: entry.ref, disposition })}>${escapeXmlText(entry.body)}</entry>`;
213
210
  }).join('\n');
214
- return `<from${formatAttributes({ id: section.id, name: section.name, updates, finished: finished || undefined })}>${entries}</from>`;
211
+ return `<from${formatAttributes({ id: section.id })}>${entries}</from>`;
215
212
  }).join('\n');
216
213
  return formatCard('inbox', {}, body);
217
214
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/crouter-api",
3
- "version": "0.3.212",
3
+ "version": "0.3.214",
4
4
  "description": "Typed crtrd /v1 API contract — DTOs, route builders, the error contract, and the CrtrClient. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/api/index.js",
@@ -28,7 +28,7 @@
28
28
  "build": "tsc -p tsconfig.json"
29
29
  },
30
30
  "publishConfig": {
31
- "access": "restricted"
31
+ "access": "public"
32
32
  },
33
33
  "repository": {
34
34
  "type": "git",