@whitewall/blip-sdk 0.0.191 → 0.0.193

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 (42) hide show
  1. package/dist/cjs/client.js.map +1 -1
  2. package/dist/cjs/index.js +2 -0
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/flow.js +46 -8
  5. package/dist/cjs/types/flow.js.map +1 -1
  6. package/dist/cjs/utils/builder.js +34 -34
  7. package/dist/cjs/utils/builder.js.map +1 -1
  8. package/dist/cjs/utils/flow-rules.js +304 -0
  9. package/dist/cjs/utils/flow-rules.js.map +1 -0
  10. package/dist/cjs/utils/minifier.js +410 -0
  11. package/dist/cjs/utils/minifier.js.map +1 -0
  12. package/dist/esm/client.js.map +1 -1
  13. package/dist/esm/index.js +2 -0
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/types/flow.js +40 -6
  16. package/dist/esm/types/flow.js.map +1 -1
  17. package/dist/esm/utils/builder.js +31 -30
  18. package/dist/esm/utils/builder.js.map +1 -1
  19. package/dist/esm/utils/flow-rules.js +297 -0
  20. package/dist/esm/utils/flow-rules.js.map +1 -0
  21. package/dist/esm/utils/minifier.js +405 -0
  22. package/dist/esm/utils/minifier.js.map +1 -0
  23. package/dist/types/client.d.ts +2 -1
  24. package/dist/types/client.d.ts.map +1 -1
  25. package/dist/types/index.d.ts +2 -0
  26. package/dist/types/index.d.ts.map +1 -1
  27. package/dist/types/namespaces/account.d.ts +20 -20
  28. package/dist/types/types/flow.d.ts +286 -96
  29. package/dist/types/types/flow.d.ts.map +1 -1
  30. package/dist/types/utils/builder.d.ts +33 -30
  31. package/dist/types/utils/builder.d.ts.map +1 -1
  32. package/dist/types/utils/flow-rules.d.ts +50 -0
  33. package/dist/types/utils/flow-rules.d.ts.map +1 -0
  34. package/dist/types/utils/minifier.d.ts +2857 -0
  35. package/dist/types/utils/minifier.d.ts.map +1 -0
  36. package/package.json +1 -1
  37. package/src/client.ts +2 -1
  38. package/src/index.ts +2 -0
  39. package/src/types/flow.ts +52 -6
  40. package/src/utils/builder.ts +61 -73
  41. package/src/utils/flow-rules.ts +453 -0
  42. package/src/utils/minifier.ts +505 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minifier.d.ts","sourceRoot":"","sources":["../../../src/utils/minifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAOH,KAAK,IAAI,EAQZ,MAAM,kBAAkB,CAAA;AAqHzB,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAA4E,CAAA;AAEtG,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA4E,CAAA;AASrG;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiBnB,CAAA;AAEb;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAI7B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACjE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,CA8CnD;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAwIrF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whitewall/blip-sdk",
3
- "version": "0.0.191",
3
+ "version": "0.0.193",
4
4
  "description": "Blip API wrapper",
5
5
  "exports": {
6
6
  "types": "./dist/types/index.d.ts",
package/src/client.ts CHANGED
@@ -13,6 +13,7 @@ import { TunnelNamespace } from './namespaces/tunnel.ts'
13
13
  import { WhatsAppNamespace } from './namespaces/whatsapp.ts'
14
14
  import { isClosable } from './sender/closable.ts'
15
15
  import { HttpSender } from './sender/http/httpsender.ts'
16
+ import type { NonTransportAuthentication } from './sender/security.ts'
16
17
  import type { ConnectionSender, ConnectionSenderConstructor, Sender } from './sender/sender.ts'
17
18
  import type { Message, MessageTypes } from './types/message.ts'
18
19
  import { type BlipDomain, type Domain, type Identity, Node } from './types/node.ts'
@@ -76,7 +77,7 @@ export class BlipClient<TSender extends Sender = Sender> {
76
77
  }
77
78
 
78
79
  public static async createAccountAndConnect<TSender extends Sender>(
79
- sender: ConnectionSenderConstructor<TSender>,
80
+ sender: ConnectionSenderConstructor<TSender, NonTransportAuthentication>,
80
81
  identity: Identity,
81
82
  password: string,
82
83
  tenantId?: string,
package/src/index.ts CHANGED
@@ -5,6 +5,8 @@ export * from './sender/index.ts'
5
5
  export * from './types/index.ts'
6
6
  export * from './utils/builder.ts'
7
7
  export * from './utils/desk.ts'
8
+ export * from './utils/flow-rules.ts'
9
+ export * from './utils/minifier.ts'
8
10
  export * from './utils/odata.ts'
9
11
  export * from './utils/thread.ts'
10
12
  export * from './utils/uri.ts'
package/src/types/flow.ts CHANGED
@@ -44,6 +44,19 @@ const CONDITION_SOURCES = ['input', 'context'] as const
44
44
  const LOGICAL_OPERATORS = ['or', 'and'] as const
45
45
  const TYPE_OF_STATE_ID = ['state', 'variable'] as const
46
46
 
47
+ export const ROOT_STATE_ID = 'onboarding'
48
+
49
+ export const CUSTOM_ACTION_LISTS = [
50
+ '$enteringCustomActions',
51
+ '$leavingCustomActions',
52
+ '$afterStateChangedActions',
53
+ '$localCustomActions',
54
+ ] as const
55
+
56
+ /** The state that declares `root`, or the conventional id for a flow that predates it. */
57
+ export const resolveEntryPointId = (flow: Record<string, { root?: boolean }>): string | undefined =>
58
+ Object.keys(flow).find((stateId) => flow[stateId].root) ?? (ROOT_STATE_ID in flow ? ROOT_STATE_ID : undefined)
59
+
47
60
  const createVariableNameSchema = (description: string) => z.string().describe(description)
48
61
 
49
62
  const plainTextSchema = z.string()
@@ -142,7 +155,10 @@ const sendMessageActionSettingsSchema = z.object({
142
155
 
143
156
  const sendRawMessageActionSettingsSchema = z.object({
144
157
  $invalid: z.boolean().optional(),
145
- type: z.literal('application/json').optional(),
158
+ // The media type the runtime deserializes the raw content as, so it is not
159
+ // restricted to application/json: a document assembled at runtime is sent as
160
+ // its own lime type, which is how a dynamic menu is rendered.
161
+ type: z.string().optional(),
146
162
  // Useful to send raw channel payloads, such as WhatsApp interactive content.
147
163
  rawContent: z.string(),
148
164
  })
@@ -190,7 +206,7 @@ export const conditionSchema = z.object({
190
206
  values: z.array(z.string()),
191
207
  })
192
208
 
193
- const baseActionSchema = z.object({
209
+ export const baseActionSchema = z.object({
194
210
  $id: z.string(),
195
211
  // Should only exist for SendMessage and SendRawMessage actions. When it is
196
212
  // omitted, GET responses usually return an empty string.
@@ -206,8 +222,9 @@ const baseActionSchema = z.object({
206
222
  position: z.literal('left'),
207
223
  document: z.object({
208
224
  id: z.string(),
209
- // Must match the type defined in the action settings.
210
- type: z.enum(MIME_TYPES).or(z.literal('application/json')),
225
+ // Must match the type defined in the action settings, which for a
226
+ // raw message can be any media type.
227
+ type: z.string(),
211
228
  // Must match the content defined in the action settings.
212
229
  content: flowMessageContentSchema.or(z.string()),
213
230
  textContent: z.string().optional(),
@@ -218,7 +235,7 @@ const baseActionSchema = z.object({
218
235
  continueOnError: z.boolean().optional(),
219
236
  })
220
237
 
221
- const actionTypeSchema = z.discriminatedUnion('type', [
238
+ export const actionTypeSchema = z.discriminatedUnion('type', [
222
239
  z.object({
223
240
  type: z.literal('SendMessage'),
224
241
  settings: sendMessageActionSettingsSchema,
@@ -361,7 +378,7 @@ export const stateSchema = z.object({
361
378
  }),
362
379
  ),
363
380
  id: z.string().optional(),
364
- // Only the special state with id "onboarding" is usually marked as root.
381
+ // Set on the entry point, which the builder always keys as ROOT_STATE_ID.
365
382
  root: z.boolean().optional(),
366
383
  $title: z.string(),
367
384
  $position: z
@@ -389,6 +406,35 @@ export type State = z.infer<typeof stateSchema>
389
406
  export type Flow = z.infer<typeof flowSchema>
390
407
  export type BuilderFlow = Flow
391
408
 
409
+ /**
410
+ * Typing indicators are noise in every projection of a flow, so both the digest
411
+ * and the minifier drop them. The two signals are checked because `$typeOfContent`
412
+ * is absent from a minified flow and can come back empty from a GET, while the
413
+ * settings mime type is absent from a hand-written action.
414
+ */
415
+ export function isChatStateSendMessage(item: {
416
+ action?: { type: string; $typeOfContent?: string; settings: { type?: string; [key: string]: unknown } }
417
+ }): boolean {
418
+ if (item.action?.type !== 'SendMessage') {
419
+ return false
420
+ }
421
+
422
+ return (
423
+ item.action.$typeOfContent === 'chat-state' ||
424
+ item.action.settings.type === 'application/vnd.lime.chatstate+json'
425
+ )
426
+ }
427
+
428
+ /** The input the runtime will use: the first one in the state, if any. */
429
+ export function inputOf<T>(state: { $contentActions: Array<{ input?: T }> }): T | undefined {
430
+ return state.$contentActions.find((item) => item.input)?.input
431
+ }
432
+
433
+ /** The labels of a select's options, which are what a user answers with. */
434
+ export function optionLabels(content: { options?: Array<string | { text?: string }> }): Array<string> {
435
+ return (content.options ?? []).map((option) => (typeof option === 'string' ? option : (option?.text ?? '')))
436
+ }
437
+
392
438
  export type BuilderConfiguration = {
393
439
  'builder:minimumIntentScore'?: string
394
440
  'builder:stateTrack'?: string
@@ -1,54 +1,53 @@
1
- import type { Action, ContentActionItem, State } from '../types/flow.ts'
2
-
3
- export type MinifiedAction = {
1
+ /**
2
+ * Lossy, read-only projection of a builder flow, meant for presenting a state to
3
+ * a human or an LLM. It renames the `$`-prefixed keys to readable ones, drops
4
+ * layout metadata and denormalizes state names, so it cannot be pushed back to
5
+ * the builder. For the round-trippable format, see `./minifier.ts`.
6
+ *
7
+ * Typed over `MinifiedState`, which a full `State` satisfies, so both a pulled
8
+ * flow and a minified one digest without casts.
9
+ */
10
+ import { type Condition, isChatStateSendMessage, resolveEntryPointId } from '../types/flow.ts'
11
+ import type { MinifiedAction, MinifiedInput, MinifiedState } from './minifier.ts'
12
+
13
+ /** A `Condition` with the builder's nullish bookkeeping dropped. */
14
+ export type ConditionDigest = Omit<Condition, 'variable'> & { variable?: string }
15
+
16
+ export type ActionDigest = {
4
17
  type: string
5
18
  settings: Record<string, unknown>
6
- conditions?: Array<{
7
- source: string
8
- variable?: string
9
- comparison: string
10
- operator?: string
11
- values: Array<string>
12
- }>
19
+ conditions?: Array<ConditionDigest>
13
20
  }
14
21
 
15
- export type MinifiedInput = {
22
+ export type InputDigest = {
16
23
  bypass: boolean
17
24
  variable?: string
18
25
  validation?: { rule: string; regex?: string; type?: string; error: string }
19
26
  expiration?: string
20
- conditions?: MinifiedAction['conditions']
27
+ conditions?: Array<ConditionDigest>
21
28
  }
22
29
 
23
- export type MinifiedOutput = {
30
+ export type OutputDigest = {
24
31
  stateId: string
25
32
  stateName?: string
26
33
  typeOfStateId?: string
27
- conditions?: MinifiedAction['conditions']
34
+ conditions?: Array<ConditionDigest>
28
35
  }
29
36
 
30
- export type MinifiedState = {
37
+ export type StateDigest = {
31
38
  id: string
32
39
  name: string
33
40
  root?: boolean
34
- enteringActions?: Array<MinifiedAction>
35
- contentActions?: Array<{ action?: MinifiedAction; input?: MinifiedInput }>
36
- leavingActions?: Array<MinifiedAction>
37
- outputs?: Array<MinifiedOutput>
38
- defaultOutput: { stateId: string; stateName?: string; typeOfStateId?: string }
39
- afterStateChangedActions?: Array<MinifiedAction>
40
- localActions?: Array<MinifiedAction>
41
+ enteringActions?: Array<ActionDigest>
42
+ contentActions?: Array<{ action?: ActionDigest; input?: InputDigest }>
43
+ leavingActions?: Array<ActionDigest>
44
+ outputs?: Array<OutputDigest>
45
+ defaultOutput: OutputDigest
46
+ afterStateChangedActions?: Array<ActionDigest>
47
+ localActions?: Array<ActionDigest>
41
48
  }
42
49
 
43
- function minifyConditions(
44
- conditions?: Array<{
45
- source: string
46
- variable?: string
47
- comparison: string
48
- operator?: string
49
- values: Array<string>
50
- }>,
51
- ): MinifiedAction['conditions'] | undefined {
50
+ function digestConditions(conditions?: Array<Condition>): Array<ConditionDigest> | undefined {
52
51
  if (!conditions || conditions.length === 0) return undefined
53
52
  return conditions.map((c) => ({
54
53
  source: c.source,
@@ -59,26 +58,26 @@ function minifyConditions(
59
58
  }))
60
59
  }
61
60
 
62
- function minifyActionSettings(settings: Record<string, unknown>): Record<string, unknown> {
61
+ function digestActionSettings(settings: Record<string, unknown>): Record<string, unknown> {
63
62
  const clone = { ...settings }
64
63
  delete clone.$invalid
65
64
  delete clone.id
66
65
  return clone
67
66
  }
68
67
 
69
- export function minifyAction(action: Action): MinifiedAction {
70
- const result: MinifiedAction = {
68
+ export function digestAction(action: MinifiedAction): ActionDigest {
69
+ const result: ActionDigest = {
71
70
  type: action.type,
72
- settings: minifyActionSettings(action.settings as Record<string, unknown>),
71
+ settings: digestActionSettings(action.settings as Record<string, unknown>),
73
72
  }
74
- const conditions = minifyConditions(action.conditions as MinifiedAction['conditions'])
73
+ const conditions = digestConditions(action.conditions)
75
74
  if (conditions) result.conditions = conditions
76
75
  return result
77
76
  }
78
77
 
79
- function minifyInput(input: ContentActionItem['input']): MinifiedInput | undefined {
78
+ function digestInput(input: MinifiedInput | undefined): InputDigest | undefined {
80
79
  if (!input) return undefined
81
- const result: MinifiedInput = { bypass: input.bypass }
80
+ const result: InputDigest = { bypass: input.bypass }
82
81
  if (input.variable) result.variable = input.variable
83
82
  if (input.validation) {
84
83
  result.validation = {
@@ -89,76 +88,65 @@ function minifyInput(input: ContentActionItem['input']): MinifiedInput | undefin
89
88
  }
90
89
  }
91
90
  if (input.expiration) result.expiration = input.expiration
92
- const conditions = minifyConditions(input.conditions as MinifiedAction['conditions'])
91
+ const conditions = digestConditions(input.conditions)
93
92
  if (conditions) result.conditions = conditions
94
93
  return result
95
94
  }
96
95
 
97
- export function isChatStateSendMessage(item: ContentActionItem): boolean {
98
- return item.action?.type === 'SendMessage' && item.action.$typeOfContent === 'chat-state'
99
- }
100
-
101
- export function resolveStateName(stateId: string, flow: Record<string, State>): string | undefined {
96
+ export function resolveStateName(stateId: string, flow: Record<string, MinifiedState>): string | undefined {
102
97
  const state = flow[stateId]
103
98
  return state?.$title
104
99
  }
105
100
 
106
- function minifyOutput(
107
- output: { stateId: string; typeOfStateId?: string; conditions?: Array<unknown>; $invalid?: boolean },
108
- flow: Record<string, State>,
109
- ): MinifiedOutput {
110
- const result: MinifiedOutput = {
101
+ function digestOutput(
102
+ output: { stateId: string; typeOfStateId?: string; conditions?: Array<Condition> },
103
+ flow: Record<string, MinifiedState>,
104
+ ): OutputDigest {
105
+ const result: OutputDigest = {
111
106
  stateId: output.stateId,
112
107
  }
113
108
  const name = resolveStateName(output.stateId, flow)
114
109
  if (name) result.stateName = name
115
110
  if (output.typeOfStateId) result.typeOfStateId = output.typeOfStateId
116
- if ('conditions' in output && Array.isArray(output.conditions) && output.conditions.length > 0) {
117
- result.conditions = minifyConditions(output.conditions as MinifiedAction['conditions'])
118
- }
111
+ const conditions = digestConditions(output.conditions)
112
+ if (conditions) result.conditions = conditions
119
113
  return result
120
114
  }
121
115
 
122
- export function minifyState(stateId: string, state: State, flow: Record<string, State>): MinifiedState {
123
- const result: MinifiedState = {
116
+ export function digestState(stateId: string, state: MinifiedState, flow: Record<string, MinifiedState>): StateDigest {
117
+ const result: StateDigest = {
124
118
  id: stateId,
125
119
  name: state.$title,
126
- defaultOutput: {
127
- stateId: state.$defaultOutput.stateId,
128
- ...(resolveStateName(state.$defaultOutput.stateId, flow)
129
- ? { stateName: resolveStateName(state.$defaultOutput.stateId, flow) }
130
- : {}),
131
- ...(state.$defaultOutput.typeOfStateId ? { typeOfStateId: state.$defaultOutput.typeOfStateId } : {}),
132
- },
120
+ defaultOutput: digestOutput(state.$defaultOutput, flow),
133
121
  }
134
122
 
135
- if (state.root) result.root = true
123
+ if (resolveEntryPointId(flow) === stateId) result.root = true
136
124
 
137
- const enteringActions = state.$enteringCustomActions.map(minifyAction)
125
+ const enteringActions = state.$enteringCustomActions.map(digestAction)
138
126
  if (enteringActions.length > 0) result.enteringActions = enteringActions
139
127
 
140
128
  const contentActions = state.$contentActions
141
- .filter((item: ContentActionItem) => !isChatStateSendMessage(item))
142
- .map((item: ContentActionItem) => {
143
- const entry: { action?: MinifiedAction; input?: MinifiedInput } = {}
144
- if (item.action) entry.action = minifyAction(item.action)
145
- const input = minifyInput(item.input)
129
+ .filter((item) => !isChatStateSendMessage(item))
130
+ .map((item) => {
131
+ const entry: { action?: ActionDigest; input?: InputDigest } = {}
132
+ if (item.action) entry.action = digestAction(item.action)
133
+ const input = digestInput(item.input)
146
134
  if (input) entry.input = input
147
135
  return entry
148
136
  })
149
- .filter((entry: { action?: MinifiedAction; input?: MinifiedInput }) => entry.action || entry.input)
137
+ .filter((entry) => entry.action || entry.input)
150
138
  if (contentActions.length > 0) result.contentActions = contentActions
151
139
 
152
- const leavingActions = state.$leavingCustomActions.map(minifyAction)
140
+ const leavingActions = state.$leavingCustomActions.map(digestAction)
153
141
  if (leavingActions.length > 0) result.leavingActions = leavingActions
154
142
 
155
- const outputs = state.$conditionOutputs.map((o: State['$conditionOutputs'][number]) => minifyOutput(o, flow))
143
+ const outputs = state.$conditionOutputs.map((o) => digestOutput(o, flow))
156
144
  if (outputs.length > 0) result.outputs = outputs
157
145
 
158
- const afterStateChangedActions = (state.$afterStateChangedActions ?? []).map(minifyAction)
146
+ const afterStateChangedActions = (state.$afterStateChangedActions ?? []).map(digestAction)
159
147
  if (afterStateChangedActions.length > 0) result.afterStateChangedActions = afterStateChangedActions
160
148
 
161
- const localActions = (state.$localCustomActions ?? []).map(minifyAction)
149
+ const localActions = (state.$localCustomActions ?? []).map(digestAction)
162
150
  if (localActions.length > 0) result.localActions = localActions
163
151
 
164
152
  return result