@superpanel-sdk/runtime 0.2.3 → 0.7.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 (319) hide show
  1. package/README.md +30 -10
  2. package/dist/builder/codegen/emit.d.ts +25 -12
  3. package/dist/builder/codegen/emit.js +339 -78
  4. package/dist/builder/codegen/generate.d.ts +21 -2
  5. package/dist/builder/codegen/generate.js +147 -34
  6. package/dist/builder/company-import-graph.d.ts +2 -0
  7. package/dist/builder/company-import-graph.js +40 -8
  8. package/dist/builder/company-imports.d.ts +29 -0
  9. package/dist/builder/company-imports.js +122 -0
  10. package/dist/builder/compile/compile-sequence.d.ts +61 -8
  11. package/dist/builder/compile/compile-sequence.js +334 -80
  12. package/dist/builder/compile/function-code.d.ts +19 -3
  13. package/dist/builder/compile/function-code.js +123 -45
  14. package/dist/builder/compile/registry.d.ts +7 -3
  15. package/dist/builder/compile/registry.js +30 -27
  16. package/dist/builder/errors.d.ts +9 -0
  17. package/dist/builder/errors.js +17 -0
  18. package/dist/builder/function-params.d.ts +10 -0
  19. package/dist/builder/function-params.js +203 -0
  20. package/dist/builder/load.d.ts +70 -10
  21. package/dist/builder/load.js +258 -67
  22. package/dist/builder/paths.d.ts +9 -1
  23. package/dist/builder/paths.js +32 -2
  24. package/dist/builder/schedules.d.ts +25 -0
  25. package/dist/builder/schedules.js +101 -0
  26. package/dist/builder/slot-schema-validation.d.ts +4 -0
  27. package/dist/builder/slot-schema-validation.js +10 -0
  28. package/dist/builder/typecheck.d.ts +8 -0
  29. package/dist/builder/typecheck.js +102 -0
  30. package/dist/builder/types.d.ts +127 -19
  31. package/dist/builder/types.js +21 -1
  32. package/dist/cli/auth/auth.d.ts +37 -0
  33. package/dist/cli/auth/auth.js +211 -0
  34. package/dist/cli/auth/backend-url.d.ts +5 -0
  35. package/dist/cli/auth/backend-url.js +25 -0
  36. package/dist/cli/auth/clipboard.d.ts +9 -0
  37. package/dist/cli/auth/clipboard.js +38 -0
  38. package/dist/cli/auth/http.d.ts +20 -0
  39. package/dist/cli/auth/http.js +27 -0
  40. package/dist/cli/auth/index.d.ts +10 -0
  41. package/dist/cli/auth/index.js +27 -0
  42. package/dist/cli/auth/progress.d.ts +12 -0
  43. package/dist/cli/auth/progress.js +15 -0
  44. package/dist/cli/auth/serve-login.d.ts +8 -0
  45. package/dist/cli/auth/serve-login.js +24 -0
  46. package/dist/cli/calls/index.d.ts +177 -0
  47. package/dist/cli/calls/index.js +96 -0
  48. package/dist/cli/compile/index.js +3 -0
  49. package/dist/cli/config.d.ts +10 -0
  50. package/dist/cli/config.js +52 -0
  51. package/dist/cli/debug/index.d.ts +31 -0
  52. package/dist/cli/debug/index.js +119 -0
  53. package/dist/cli/exec/index.d.ts +39 -0
  54. package/dist/cli/exec/index.js +138 -0
  55. package/dist/cli/exec/session.d.ts +48 -0
  56. package/dist/cli/exec/session.js +82 -0
  57. package/dist/cli/exec/trace.d.ts +18 -0
  58. package/dist/cli/exec/trace.js +52 -0
  59. package/dist/cli/index.js +112 -9
  60. package/dist/cli/logs/index.d.ts +47 -0
  61. package/dist/cli/logs/index.js +113 -0
  62. package/dist/cli/mobile/index.d.ts +12 -0
  63. package/dist/cli/mobile/index.js +405 -0
  64. package/dist/cli/serve/index.d.ts +109 -3
  65. package/dist/cli/serve/index.js +506 -118
  66. package/dist/cli/turns/index.d.ts +105 -0
  67. package/dist/cli/turns/index.js +128 -0
  68. package/dist/cli/turns/run.d.ts +13 -0
  69. package/dist/cli/turns/run.js +57 -0
  70. package/dist/cli/turns/shadow.d.ts +112 -0
  71. package/dist/cli/turns/shadow.js +54 -0
  72. package/dist/cli/type-gen/index.js +9 -9
  73. package/dist/compiler.d.ts +7 -0
  74. package/dist/compiler.js +7 -0
  75. package/dist/compute-host/compute-host.d.ts +14 -23
  76. package/dist/compute-host/compute-host.js +18 -30
  77. package/dist/compute-host/index.d.ts +2 -4
  78. package/dist/compute-host/index.js +1 -2
  79. package/dist/compute-host/source-compute-host.d.ts +10 -10
  80. package/dist/compute-host/source-compute-host.js +33 -40
  81. package/dist/core/case-orchestrator/contact-hours.d.ts +70 -0
  82. package/dist/core/case-orchestrator/contact-hours.js +127 -0
  83. package/dist/core/case-orchestrator/index.d.ts +3 -0
  84. package/dist/core/case-orchestrator/index.js +3 -0
  85. package/dist/core/case-orchestrator/render.d.ts +75 -0
  86. package/dist/core/case-orchestrator/render.js +244 -0
  87. package/dist/core/case-orchestrator/time.d.ts +11 -0
  88. package/dist/core/case-orchestrator/time.js +29 -0
  89. package/dist/core/case-orchestrator/types.d.ts +708 -0
  90. package/dist/core/case-orchestrator/types.js +42 -0
  91. package/dist/core/context/call.d.ts +291 -0
  92. package/dist/core/context/call.js +94 -0
  93. package/dist/core/context/channels.d.ts +60 -0
  94. package/dist/core/context/channels.js +35 -0
  95. package/dist/core/context/contact.d.ts +96 -6
  96. package/dist/core/context/contact.js +48 -2
  97. package/dist/core/context/email-message.d.ts +198 -0
  98. package/dist/core/context/email-message.js +86 -0
  99. package/dist/core/context/email.d.ts +109 -0
  100. package/dist/core/context/email.js +90 -0
  101. package/dist/core/context/exchanges.d.ts +167 -0
  102. package/dist/core/context/exchanges.js +81 -0
  103. package/dist/core/context/instances.d.ts +307 -0
  104. package/dist/core/context/instances.js +137 -0
  105. package/dist/core/context/kv.d.ts +113 -0
  106. package/dist/core/context/kv.js +60 -0
  107. package/dist/core/context/platform-registry.d.ts +544 -4
  108. package/dist/core/context/platform-registry.js +14 -2
  109. package/dist/core/context/platform.d.ts +2 -1
  110. package/dist/core/context/sms.d.ts +177 -0
  111. package/dist/core/context/sms.js +77 -0
  112. package/dist/core/context/types.d.ts +79 -48
  113. package/dist/core/context/types.js +1 -7
  114. package/dist/core/conversation/index.d.ts +85 -0
  115. package/dist/core/conversation/index.js +133 -0
  116. package/dist/core/functions/errors.d.ts +74 -0
  117. package/dist/core/functions/errors.js +26 -0
  118. package/dist/core/functions/events.d.ts +192 -0
  119. package/dist/core/functions/events.js +23 -0
  120. package/dist/core/functions/schedules.d.ts +50 -0
  121. package/dist/core/functions/schedules.js +20 -0
  122. package/dist/core/functions/types.d.ts +29 -73
  123. package/dist/core/functions/types.js +1 -4
  124. package/dist/core/office-hours/index.d.ts +39 -0
  125. package/dist/core/office-hours/index.js +187 -0
  126. package/dist/core/page/define.d.ts +904 -0
  127. package/dist/core/page/define.js +518 -0
  128. package/dist/core/page/envelope.d.ts +55 -0
  129. package/dist/core/page/envelope.js +4 -0
  130. package/dist/core/page/fns.d.ts +448 -0
  131. package/dist/core/page/fns.js +539 -0
  132. package/dist/core/page/memory-reader.d.ts +27 -0
  133. package/dist/core/page/memory-reader.js +299 -0
  134. package/dist/core/page/ops.d.ts +58 -0
  135. package/dist/core/page/ops.js +220 -0
  136. package/dist/core/page/page-host.d.ts +20 -0
  137. package/dist/core/page/page-host.js +57 -0
  138. package/dist/core/page/records-query.d.ts +234 -0
  139. package/dist/core/page/records-query.js +780 -0
  140. package/dist/core/page/render.d.ts +295 -0
  141. package/dist/core/page/render.js +1060 -0
  142. package/dist/core/page/sandbox.d.ts +85 -0
  143. package/dist/core/page/sandbox.js +357 -0
  144. package/dist/core/page/time-format.d.ts +46 -0
  145. package/dist/core/page/time-format.js +125 -0
  146. package/dist/core/page/timeline.d.ts +40 -0
  147. package/dist/core/page/timeline.js +2 -0
  148. package/dist/core/page/typed.d.ts +648 -0
  149. package/dist/core/page/typed.js +2 -0
  150. package/dist/core/page/workspace.d.ts +57 -0
  151. package/dist/core/page/workspace.js +266 -0
  152. package/dist/core/party/index.d.ts +3 -0
  153. package/dist/core/party/index.js +3 -0
  154. package/dist/core/party/schema.d.ts +208 -0
  155. package/dist/core/party/schema.js +113 -0
  156. package/dist/core/party/types.d.ts +35 -0
  157. package/dist/core/party/types.js +15 -0
  158. package/dist/core/sequence/define.d.ts +56 -0
  159. package/dist/core/sequence/define.js +10 -0
  160. package/dist/core/sequence/index.d.ts +63 -0
  161. package/dist/core/sequence/index.js +231 -0
  162. package/dist/core/slot/binding.d.ts +40 -0
  163. package/dist/core/slot/binding.js +2 -0
  164. package/dist/core/slot/company-metadata.d.ts +102 -0
  165. package/dist/core/slot/company-metadata.js +536 -0
  166. package/dist/core/slot/compile-schema.d.ts +19 -13
  167. package/dist/core/slot/compile-schema.js +51 -248
  168. package/dist/core/slot/contact-timezone.d.ts +110 -0
  169. package/dist/core/slot/contact-timezone.js +186 -0
  170. package/dist/core/slot/field.d.ts +2 -25
  171. package/dist/core/slot/field.js +0 -71
  172. package/dist/core/slot/id-ref.d.ts +17 -2
  173. package/dist/core/slot/id-ref.js +16 -8
  174. package/dist/core/slot/index.d.ts +12 -13
  175. package/dist/core/slot/index.js +11 -12
  176. package/dist/core/slot/naming.d.ts +15 -0
  177. package/dist/core/slot/naming.js +96 -0
  178. package/dist/core/slot/platform-fields.d.ts +119 -0
  179. package/dist/core/slot/platform-fields.js +121 -0
  180. package/dist/core/slot/ref.d.ts +16 -0
  181. package/dist/core/slot/ref.js +14 -0
  182. package/dist/core/slot/row.d.ts +2 -9
  183. package/dist/core/slot/row.js +13 -23
  184. package/dist/core/slot/schema-compat.d.ts +17 -0
  185. package/dist/core/slot/schema-compat.js +103 -0
  186. package/dist/core/slot/schema.d.ts +353 -76
  187. package/dist/core/slot/schema.js +163 -10
  188. package/dist/core/slot/types.d.ts +30 -103
  189. package/dist/core/slot/value.d.ts +28 -3
  190. package/dist/core/slot/value.js +93 -57
  191. package/dist/dev-overlay/protocol.d.ts +74 -8
  192. package/dist/fn-context/build-context.d.ts +3 -1
  193. package/dist/fn-context/build-context.js +26 -10
  194. package/dist/fn-context/fake/empty-api.js +9 -28
  195. package/dist/fn-context/fake/index.d.ts +13 -4
  196. package/dist/fn-context/fake/index.js +29 -2
  197. package/dist/fn-context/fn-params.d.ts +3 -0
  198. package/dist/fn-context/fn-params.js +10 -0
  199. package/dist/fn-context/index.d.ts +5 -5
  200. package/dist/fn-context/index.js +4 -4
  201. package/dist/fn-context/log.js +2 -2
  202. package/dist/fn-context/make-ctx.d.ts +11 -0
  203. package/dist/fn-context/make-ctx.js +20 -9
  204. package/dist/fn-context/rpc/case-orchestrator-tools.d.ts +32 -0
  205. package/dist/fn-context/rpc/case-orchestrator-tools.js +12 -0
  206. package/dist/fn-context/rpc/errors.d.ts +13 -0
  207. package/dist/fn-context/rpc/errors.js +22 -0
  208. package/dist/fn-context/rpc/index.d.ts +4 -2
  209. package/dist/fn-context/rpc/index.js +4 -2
  210. package/dist/fn-context/rpc/integration/index.d.ts +15 -5
  211. package/dist/fn-context/rpc/integration/index.js +1 -1
  212. package/dist/fn-context/rpc/integration/list-surfaces.d.ts +21 -0
  213. package/dist/fn-context/rpc/integration/{list-bindings.js → list-surfaces.js} +4 -4
  214. package/dist/fn-context/rpc/log.d.ts +11 -1
  215. package/dist/fn-context/rpc/platform.d.ts +13 -3
  216. package/dist/fn-context/rpc/platform.js +1 -1
  217. package/dist/fn-context/rpc/records.d.ts +85 -0
  218. package/dist/fn-context/rpc/records.js +24 -0
  219. package/dist/fn-context/rpc/trpc-client.d.ts +44 -2
  220. package/dist/fn-context/rpc/trpc-client.js +222 -12
  221. package/dist/fn-context/rpc/trpc-init.d.ts +21 -3
  222. package/dist/fn-context/rpc/trpc-init.js +10 -4
  223. package/dist/fn-context/rpc/trpc-router-factory.d.ts +111 -7
  224. package/dist/fn-context/rpc/trpc-router-factory.js +2 -0
  225. package/dist/fn-context/run-scope.d.ts +4 -0
  226. package/dist/fn-context/run-scope.js +9 -0
  227. package/dist/fn-context/types.d.ts +52 -5
  228. package/dist/index.d.ts +36 -46
  229. package/dist/index.js +30 -33
  230. package/dist/logger.d.ts +11 -0
  231. package/dist/logger.js +49 -0
  232. package/dist/platform.d.ts +75 -0
  233. package/dist/platform.js +57 -0
  234. package/dist/testing-compile-child.d.ts +2 -0
  235. package/dist/testing-compile-child.js +20 -0
  236. package/dist/testing.d.ts +368 -0
  237. package/dist/testing.js +439 -0
  238. package/dist/voice-service/actions.d.ts +50 -6
  239. package/dist/voice-service/index.d.ts +2 -0
  240. package/dist/voice-service/index.js +2 -0
  241. package/dist/voice-service/protocol.d.ts +604 -0
  242. package/dist/voice-service/protocol.js +67 -0
  243. package/dist/voice-service/types.d.ts +55 -8
  244. package/dist/worker.d.ts +11 -0
  245. package/dist/worker.js +11 -0
  246. package/package.json +38 -15
  247. package/dist/builder/compile/compile-agenda.d.ts +0 -15
  248. package/dist/builder/compile/compile-agenda.js +0 -64
  249. package/dist/builder/merge.d.ts +0 -4
  250. package/dist/builder/merge.js +0 -19
  251. package/dist/compute-host/read-only-cache.d.ts +0 -20
  252. package/dist/compute-host/read-only-cache.js +0 -61
  253. package/dist/core/context/db.d.ts +0 -69
  254. package/dist/core/context/db.js +0 -44
  255. package/dist/core/context/docusign.d.ts +0 -134
  256. package/dist/core/context/docusign.js +0 -108
  257. package/dist/core/context/filevine.d.ts +0 -323
  258. package/dist/core/context/filevine.js +0 -254
  259. package/dist/core/context/http.d.ts +0 -9
  260. package/dist/core/context/http.js +0 -4
  261. package/dist/core/context/hubspot.d.ts +0 -250
  262. package/dist/core/context/hubspot.js +0 -191
  263. package/dist/core/context/twilio.d.ts +0 -50
  264. package/dist/core/context/twilio.js +0 -42
  265. package/dist/core/functions/define/case-context.d.ts +0 -14
  266. package/dist/core/functions/define/case-context.js +0 -15
  267. package/dist/core/functions/define/compute.d.ts +0 -7
  268. package/dist/core/functions/define/compute.js +0 -17
  269. package/dist/core/functions/define/custom.d.ts +0 -4
  270. package/dist/core/functions/define/custom.js +0 -8
  271. package/dist/core/functions/define/system.d.ts +0 -7
  272. package/dist/core/functions/define/system.js +0 -12
  273. package/dist/core/functions/func-ref.d.ts +0 -16
  274. package/dist/core/functions/func-ref.js +0 -20
  275. package/dist/core/slot/deps.d.ts +0 -15
  276. package/dist/core/slot/deps.js +0 -88
  277. package/dist/core/slot/derived.d.ts +0 -32
  278. package/dist/core/slot/derived.js +0 -115
  279. package/dist/core/slot/platform-session-fields.d.ts +0 -38
  280. package/dist/core/slot/platform-session-fields.js +0 -48
  281. package/dist/core/slot/sf-schema.d.ts +0 -23
  282. package/dist/core/slot/sf-schema.js +0 -125
  283. package/dist/core/slot/sf-validate.d.ts +0 -14
  284. package/dist/core/slot/sf-validate.js +0 -132
  285. package/dist/core/slot/snapshot.d.ts +0 -18
  286. package/dist/core/slot/snapshot.js +0 -138
  287. package/dist/core/slot/write.d.ts +0 -48
  288. package/dist/core/slot/write.js +0 -426
  289. package/dist/core/stage/builders.d.ts +0 -54
  290. package/dist/core/stage/builders.js +0 -31
  291. package/dist/core/stage/condition.d.ts +0 -17
  292. package/dist/core/stage/condition.js +0 -198
  293. package/dist/core/stage/drive.d.ts +0 -43
  294. package/dist/core/stage/drive.js +0 -78
  295. package/dist/core/stage/finish-when.d.ts +0 -20
  296. package/dist/core/stage/finish-when.js +0 -82
  297. package/dist/core/stage/flatten.d.ts +0 -27
  298. package/dist/core/stage/flatten.js +0 -466
  299. package/dist/core/stage/index.d.ts +0 -15
  300. package/dist/core/stage/index.js +0 -13
  301. package/dist/core/stage/interrupts.d.ts +0 -28
  302. package/dist/core/stage/interrupts.js +0 -120
  303. package/dist/core/stage/ivr-fields.d.ts +0 -9
  304. package/dist/core/stage/ivr-fields.js +0 -75
  305. package/dist/core/stage/simulate.d.ts +0 -24
  306. package/dist/core/stage/simulate.js +0 -33
  307. package/dist/core/stage/transfer-fields.d.ts +0 -19
  308. package/dist/core/stage/transfer-fields.js +0 -129
  309. package/dist/core/stage/transfer-spec.d.ts +0 -48
  310. package/dist/core/stage/transfer-spec.js +0 -113
  311. package/dist/core/stage/types.d.ts +0 -208
  312. package/dist/core/stage/types.js +0 -2
  313. package/dist/core/stage/validate.d.ts +0 -11
  314. package/dist/core/stage/validate.js +0 -330
  315. package/dist/core/stage/walk.d.ts +0 -39
  316. package/dist/core/stage/walk.js +0 -119
  317. package/dist/fn-context/rpc/integration/list-bindings.d.ts +0 -21
  318. package/dist/fn-context/system-args.d.ts +0 -6
  319. package/dist/fn-context/system-args.js +0 -14
@@ -1,17 +1,170 @@
1
- /** Reserved row-identity field name. Authors should not invent another. */
1
+ import { z } from 'zod';
2
+ export const SCALAR_DATA_TYPES = [
3
+ 'string',
4
+ 'text',
5
+ 'phone',
6
+ 'email',
7
+ 'number',
8
+ 'boolean',
9
+ 'date',
10
+ 'datetime',
11
+ 'time',
12
+ 'select',
13
+ 'multi_select',
14
+ ];
15
+ /** The types that take `options` (27 §2–§3). */
16
+ export const OPTION_DATA_TYPES = new Set(['select', 'multi_select']);
17
+ const dataTypeSchema = z.enum([...SCALAR_DATA_TYPES, 'contact_schedule']);
18
+ /** Field keys derived fields used; they were removed (13-data-model-v1 §21) and are reported when found. */
19
+ export const REMOVED_DERIVED_KEYS = ['derived', 'dependsOn', 'computeFn'];
20
+ /** A field's `source`, removed (19-page-writable-cells): a page decides what the AI may write. */
21
+ export const REMOVED_SOURCE_KEY = 'source';
22
+ /**
23
+ * A field's `nullable`, removed: no write ever checked it. Every field starts empty and can be
24
+ * cleared; a page's `required` says when one must be filled, and the platform keeps a row's id and
25
+ * parent itself.
26
+ */
27
+ export const REMOVED_NULLABLE_KEY = 'nullable';
28
+ /**
29
+ * A field's `enum`, removed (27 §2): a field of a known set of values is a `select` (or `multi_select`)
30
+ * with `options`.
31
+ */
32
+ export const REMOVED_ENUM_KEY = 'enum';
33
+ /**
34
+ * A field's `identifier`, removed: nothing found a contact by it. Who a conversation is with is the
35
+ * repo's `resolve` to decide; `ctx.api.contact.find` and clearing a contact use `phone` and `email`.
36
+ */
37
+ export const REMOVED_IDENTIFIER_KEY = 'identifier';
38
+ /** Every row's id: the platform's, on every table; a schema does not write it. */
2
39
  export const ROW_ID_FIELD = 'id';
40
+ /**
41
+ * What every row has besides its fields, the platform's (never a field of a schema): its `id`, when
42
+ * it was created and when it was last written (ISO 8601). A read can filter and order by them.
43
+ */
44
+ export const ROW_SYSTEM_KEYS = ['id', 'createdAt', 'updatedAt'];
45
+ /** The row's times: `createdAt`, `updatedAt`. */
46
+ export const ROW_TIME_KEYS = ['createdAt', 'updatedAt'];
47
+ export function isRowTimeKey(key) {
48
+ return ROW_TIME_KEYS.includes(key);
49
+ }
50
+ /** The definition of every row's `id` (added by the platform to every table and the session). */
3
51
  export const idFieldCore = {
4
- derived: false,
5
52
  label: 'Id',
6
53
  dataType: 'string',
7
- source: 'system',
8
54
  extraction: 'Row identity',
9
- enum: null,
10
- nullable: false,
11
- };
12
- /** Unified row id. Write `id: idField` on every table. */
13
- export const idField = {
14
- ...idFieldCore,
15
- identifier: null,
16
55
  };
56
+ export const normalFieldCoreSchema = z
57
+ .object({
58
+ label: z.string(),
59
+ dataType: dataTypeSchema,
60
+ extraction: z.string(),
61
+ options: z.array(z.string()).optional(),
62
+ })
63
+ .strict();
64
+ export const tableRefSchema = z
65
+ .object({
66
+ table: z.string().min(1),
67
+ kind: z.enum(['parent', 'lookup']),
68
+ relatedName: z.string().optional(),
69
+ })
70
+ .strict();
71
+ export const companyNormalFieldDefSchema = normalFieldCoreSchema
72
+ .extend({
73
+ ref: tableRefSchema.optional(),
74
+ unique: z.literal(true).optional(),
75
+ deprecated: z.boolean().optional(),
76
+ })
77
+ .strict();
78
+ const localTime = /^(?:[01]\d|2[0-3]):[0-5]\d$/;
79
+ const localEndTime = /^(?:(?:[01]\d|2[0-3]):[0-5]\d|24:00)$/;
80
+ const localDate = /^\d{4}-\d{2}-\d{2}$/;
81
+ export const localTimeRangeSchema = z
82
+ .object({ start: z.string().regex(localTime), end: z.string().regex(localEndTime) })
83
+ .strict()
84
+ .refine((range) => range.start < range.end, { message: 'start must be before end' });
85
+ export const weekdaySchema = z.enum(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);
86
+ function validateWindows(windows, ctx) {
87
+ for (let index = 1; index < windows.length; index += 1) {
88
+ const previous = windows[index - 1];
89
+ const current = windows[index];
90
+ if (current.start < previous.start) {
91
+ ctx.addIssue({ code: 'custom', path: [index], message: 'windows must be sorted by start time' });
92
+ }
93
+ else if (current.start < previous.end) {
94
+ ctx.addIssue({ code: 'custom', path: [index], message: 'windows must not overlap' });
95
+ }
96
+ }
97
+ }
98
+ const windowsSchema = z.array(localTimeRangeSchema).superRefine(validateWindows);
99
+ const weeklySchema = z
100
+ .object({
101
+ mon: windowsSchema,
102
+ tue: windowsSchema,
103
+ wed: windowsSchema,
104
+ thu: windowsSchema,
105
+ fri: windowsSchema,
106
+ sat: windowsSchema,
107
+ sun: windowsSchema,
108
+ })
109
+ .strict();
110
+ function isValidLocalDate(value) {
111
+ if (!localDate.test(value))
112
+ return false;
113
+ const [year, month, day] = value.split('-').map(Number);
114
+ const date = new Date(Date.UTC(year, month - 1, day));
115
+ return date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
116
+ }
117
+ export const contactScheduleValueSchema = z
118
+ .object({
119
+ weekly: weeklySchema.nullable(),
120
+ dateOverrides: z.array(z
121
+ .object({
122
+ dates: z.array(z.string().refine(isValidLocalDate, 'expected a valid YYYY-MM-DD date')).min(1),
123
+ windows: windowsSchema,
124
+ })
125
+ .strict()),
126
+ })
127
+ .strict()
128
+ .superRefine((schedule, ctx) => {
129
+ const seen = new Set();
130
+ schedule.dateOverrides.forEach((override, overrideIndex) => {
131
+ override.dates.forEach((date, dateIndex) => {
132
+ if (seen.has(date)) {
133
+ ctx.addIssue({
134
+ code: 'custom',
135
+ path: ['dateOverrides', overrideIndex, 'dates', dateIndex],
136
+ message: 'each override date may appear only once',
137
+ });
138
+ }
139
+ seen.add(date);
140
+ });
141
+ });
142
+ });
143
+ export const companyFieldDefSchema = companyNormalFieldDefSchema;
144
+ export const companyTableDefSchema = z
145
+ .object({
146
+ label: z.string(),
147
+ description: z.string(),
148
+ fields: z.record(z.string(), companyFieldDefSchema),
149
+ })
150
+ .strict();
151
+ export const companySchemaSchema = z
152
+ .record(z.string().min(1), companyTableDefSchema)
153
+ .refine((schema) => Object.keys(schema).length > 0, {
154
+ message: 'company schema must define at least one table',
155
+ });
156
+ /** A company with no `schema/session.ts`: sessions have no fields. */
157
+ export const EMPTY_SESSION_SCHEMA = { fields: {} };
158
+ export const sessionFieldDefSchema = normalFieldCoreSchema
159
+ .extend({
160
+ dataType: z.enum(SCALAR_DATA_TYPES),
161
+ deprecated: z.boolean().optional(),
162
+ })
163
+ .strict();
164
+ export const sessionSchemaSchema = z
165
+ .object({ fields: z.record(z.string().min(1), sessionFieldDefSchema) })
166
+ .strict();
167
+ export function isCompanySchema(value) {
168
+ return companySchemaSchema.safeParse(value).success;
169
+ }
17
170
  //# sourceMappingURL=schema.js.map
@@ -1,89 +1,52 @@
1
- import type { DataType } from './schema.js';
2
- import type { FieldPath } from './path.js';
1
+ import type { ContactSchedule, DataType, TableRef } from './schema.js';
3
2
  import type { FieldState } from '../context/types.js';
4
- export type UpdatedBy = 'slot-filling' | 'derived' | 'function' | 'human' | 'import' | 'platform';
5
- /** Prior generation archived into FieldValue.history (no reason — 01-slot-db §4.1). */
6
- export type FieldHistoryEntry = {
7
- value: string | number | boolean | null;
8
- state: FieldState;
9
- at: number;
10
- by: UpdatedBy;
11
- };
12
- /** In-memory field envelope (01-slot-design §2 + 01-slot-db §4 history). */
3
+ export type UpdatedBy = 'slot-filling' | 'function' | 'human' | 'import' | 'platform';
4
+ /**
5
+ * In-memory field envelope (01-slot-design §2): the current value only. Earlier values are in the
6
+ * change log (`SlotWriteLog`, 36 §3).
7
+ */
13
8
  export type FieldValue = {
9
+ /**
10
+ * Dialogue evidence quote or write justification (`null` when the writer gave none: plain
11
+ * function / platform writes, row inserts, imports).
12
+ * Updating `reason` alone does not count as a C5 state/value change.
13
+ */
14
14
  reason: string | null;
15
- value: string | number | boolean | null;
15
+ /**
16
+ * Current value; always `null` when `state` is `'empty'` or `'declined'`. `'asked_unknown'` is
17
+ * `null` unless the field's extraction allows a coarse value; `'filled'` is non-null.
18
+ */
19
+ value: SlotValue;
16
20
  state: FieldState;
21
+ /** Epoch milliseconds of the last value/state change. */
17
22
  updatedAt: number;
18
23
  updatedBy: UpdatedBy;
19
- /** Past generations ascending; excludes current. Appended only on C5 change. */
20
- history: FieldHistoryEntry[];
21
- };
22
- /** One history append produced by a write batch (for platform write_log). */
23
- export type HistoryAppend = {
24
- path: FieldPath;
25
- entry: FieldHistoryEntry;
26
- /** Set when the write targeted a specific snapshot row. */
27
- rowId?: string;
28
- };
29
- export type ExtractedField = {
30
- reason: string;
31
- value: string | number | boolean | null;
32
- state: 'filled' | 'asked_unknown' | 'declined';
33
24
  };
34
- export type SingleRowProjection = Record<string, ExtractedField>;
35
- export type MultiRowProjection = Array<{
36
- rowKey: string;
37
- fields: Record<string, ExtractedField>;
38
- }>;
39
- export type SlotFillingOutput = Record<string, SingleRowProjection | MultiRowProjection>;
40
- export type RuntimeNormalFieldDef = {
41
- derived: false;
25
+ export type SlotValue = string | number | boolean | string[] | ContactSchedule | null;
26
+ export type RuntimeFieldDef = {
42
27
  label: string;
28
+ /** Sequence-specific field meaning shown to slot-filling consumers. */
29
+ description?: string;
43
30
  dataType: DataType;
44
- source: 'conversation' | 'system';
45
31
  extraction: string;
46
- enum: Array<string | number> | null;
47
- nullable: boolean;
48
- identifier: null | {
49
- kind: 'phone' | 'email';
50
- };
51
- ref: null | {
52
- table: string;
53
- };
32
+ /** A `select` / `multi_select` field's choices; null on every other type. */
33
+ options: string[] | null;
34
+ ref: null | TableRef;
35
+ /** No two rows of the table hold the same value (18-record-search-index §4.5). */
36
+ unique?: true;
54
37
  deprecated?: boolean;
55
38
  };
56
- export type RuntimeDerivedFieldDef = {
57
- derived: true;
58
- label: string;
59
- dataType: DataType;
60
- dependsOn: FieldPath[];
61
- computeFn: string;
62
- deprecated?: boolean;
63
- };
64
- export type RuntimeFieldDef = RuntimeNormalFieldDef | RuntimeDerivedFieldDef;
65
39
  export type RuntimeTableDef = {
66
40
  label: string;
67
- rows: 'single' | 'multi';
68
41
  description: string;
69
42
  fields: Record<string, RuntimeFieldDef>;
70
43
  };
71
44
  /**
72
- * Compiled schema: one key per table, plus derived graph.
73
- * `derivedOrder` / `reverseDeps` are reserved and cannot be table names.
45
+ * Compiled schema: one key per table. Builds compiled before V1.16 also carry `derivedOrder` /
46
+ * `reverseDeps` (always empty there); those names stay reserved and are skipped when reading.
74
47
  */
75
48
  export type CompiledSlotSchema = {
76
- /** Derived fields in topological order (dependencies first). */
77
- derivedOrder: FieldPath[];
78
- /** `table.field` → derived fields that list it in dependsOn. */
79
- reverseDeps: Record<FieldPath, FieldPath[]>;
80
- [table: string]: RuntimeTableDef | FieldPath[] | Record<FieldPath, FieldPath[]>;
81
- };
82
- export type SlotCurrent = {
83
- contactId: string;
84
- caseContactId: string;
85
- caseFileId: string;
86
- sessionId: string | null;
49
+ [table: string]: RuntimeTableDef;
87
50
  };
88
51
  export type SingleRowTableData = {
89
52
  id: string;
@@ -95,15 +58,6 @@ export type MultiRowRecord = {
95
58
  [field: string]: FieldValue | string;
96
59
  };
97
60
  export type MultiRowTableData = MultiRowRecord[];
98
- export type TableData = SingleRowTableData | MultiRowTableData;
99
- /**
100
- * Runtime snapshot: `current` plus one key per table.
101
- * `current` is reserved and cannot be a table name.
102
- */
103
- export type RuntimeSlotsSnapshot = {
104
- current?: SlotCurrent;
105
- [table: string]: TableData | SlotCurrent | undefined;
106
- };
107
61
  export type ValidationIssue = {
108
62
  code: string;
109
63
  message: string;
@@ -115,32 +69,5 @@ export type ValidationResult = {
115
69
  ok: false;
116
70
  issues: ValidationIssue[];
117
71
  };
118
- export type WriteSource = Exclude<UpdatedBy, 'derived'>;
119
- export type ApplyWritesOptions = {
120
- source: WriteSource;
121
- now?: number;
122
- /** When true (default for function/platform), only `source: system` normals. */
123
- systemOnly?: boolean;
124
- };
125
- export type ApplyWritesResult = {
126
- snapshot: RuntimeSlotsSnapshot;
127
- changed: FieldPath[];
128
- /** Previous generations archived into field envelopes this batch. */
129
- history: HistoryAppend[];
130
- };
131
- export type RecomputeResult = {
132
- snapshot: RuntimeSlotsSnapshot;
133
- changed: FieldPath[];
134
- history: HistoryAppend[];
135
- };
136
- export type SlotFillingValidateResult = {
137
- ok: true;
138
- accepted: SlotFillingOutput;
139
- /** Fields that failed type/enum checks — caller may re-extract. */
140
- rejected: FieldPath[];
141
- } | {
142
- ok: false;
143
- reason: 'stale-version' | 'invalid-shape';
144
- issues: ValidationIssue[];
145
- };
72
+ export type WriteSource = UpdatedBy;
146
73
  //# sourceMappingURL=types.d.ts.map
@@ -1,9 +1,34 @@
1
1
  import type { DataType } from './schema.js';
2
- import type { ExtractedField, RuntimeFieldDef, RuntimeNormalFieldDef, ValidationIssue } from './types.js';
2
+ import type { RuntimeFieldDef, ValidationIssue } from './types.js';
3
+ /** date values slot filling must write. Partial precision is the coarse form C3 still accepts. */
4
+ export declare const DATE_VALUE_PATTERN: string;
5
+ export declare const DATE_VALUE_FORMAT = "YYYY, YYYY-MM, or YYYY-MM-DD";
6
+ /** ISO-8601 datetime with a timezone offset or Z. */
7
+ export declare const DATETIME_VALUE_PATTERN: string;
8
+ export declare const DATETIME_VALUE_FORMAT = "ISO-8601 datetime with a timezone offset or Z";
9
+ /** A time of day (27 §4): `HH:mm`, 24-hour, `00:00`–`23:59`. */
10
+ export declare const TIME_VALUE_PATTERN: string;
11
+ export declare const TIME_VALUE_FORMAT = "a time of day HH:mm, 24-hour (15:30)";
12
+ /**
13
+ * A `phone` value as stored: E.164, any country, with an extension in RFC 3966 form when there is one
14
+ * (`+14155550123;ext=123`). The write entry converts what it is given first.
15
+ */
16
+ export declare const PHONE_VALUE_PATTERN: string;
17
+ /** An `email` value as stored: lower-cased (the write entry lower-cases what it is given first). */
18
+ export declare const EMAIL_VALUE_PATTERN: string;
19
+ /** Characters of a string, as Postgres and people count them (a surrogate pair is one). */
20
+ export declare function stringChars(value: string): number;
21
+ /** UTF-8 bytes of a string. */
22
+ export declare function utf8Bytes(value: string): number;
23
+ /** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
24
+ export declare function indexedBytes(value: string): number;
25
+ /** What a value of `dataType` must look like, for messages. */
26
+ export declare function dataTypeFormat(dataType: DataType): string;
3
27
  export declare function isValidDataTypeValue(dataType: DataType, value: unknown): boolean;
4
- export declare function validateExtractedField(field: RuntimeNormalFieldDef, extracted: ExtractedField, path: string): ValidationIssue[];
5
- /** Validate a bare write value for a normal or derived field. */
28
+ /** Validate a bare write value for a field. */
6
29
  export declare function validateBareValue(field: RuntimeFieldDef, value: unknown, path: string, options?: {
7
30
  allowNull?: boolean;
8
31
  }): ValidationIssue[];
32
+ /** What of a `select` / `multi_select` value is not one of the field's options; empty for any other field. */
33
+ export declare function optionsOutside(field: Pick<RuntimeFieldDef, 'options'>, value: unknown): unknown[];
9
34
  //# sourceMappingURL=value.d.ts.map
@@ -1,12 +1,79 @@
1
- const DATE_RE = /^\d{4}(-\d{2}(-\d{2})?)?$/;
2
- // ISO-8601 datetime with timezone offset or Z
3
- const DATETIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
1
+ import { LIMITS } from './company-metadata.js';
2
+ import { contactScheduleValueSchema } from './schema.js';
3
+ /** date values slot filling must write. Partial precision is the coarse form C3 still accepts. */
4
+ export const DATE_VALUE_PATTERN = String.raw `^\d{4}(-\d{2}(-\d{2})?)?$`;
5
+ export const DATE_VALUE_FORMAT = 'YYYY, YYYY-MM, or YYYY-MM-DD';
6
+ /** ISO-8601 datetime with a timezone offset or Z. */
7
+ export const DATETIME_VALUE_PATTERN = String.raw `^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$`;
8
+ export const DATETIME_VALUE_FORMAT = 'ISO-8601 datetime with a timezone offset or Z';
9
+ /** A time of day (27 §4): `HH:mm`, 24-hour, `00:00`–`23:59`. */
10
+ export const TIME_VALUE_PATTERN = String.raw `^(?:[01]\d|2[0-3]):[0-5]\d$`;
11
+ export const TIME_VALUE_FORMAT = 'a time of day HH:mm, 24-hour (15:30)';
12
+ /**
13
+ * A `phone` value as stored: E.164, any country, with an extension in RFC 3966 form when there is one
14
+ * (`+14155550123;ext=123`). The write entry converts what it is given first.
15
+ */
16
+ export const PHONE_VALUE_PATTERN = String.raw `^\+[1-9]\d{6,14}(;ext=\d{1,10})?$`;
17
+ /** An `email` value as stored: lower-cased (the write entry lower-cases what it is given first). */
18
+ export const EMAIL_VALUE_PATTERN = String.raw `^[^\sA-Z@]+@[^\sA-Z@]+\.[^\sA-Z@]+$`;
19
+ const DATE_RE = new RegExp(DATE_VALUE_PATTERN);
20
+ const DATETIME_RE = new RegExp(DATETIME_VALUE_PATTERN);
21
+ const TIME_RE = new RegExp(TIME_VALUE_PATTERN);
22
+ const PHONE_RE = new RegExp(PHONE_VALUE_PATTERN);
23
+ const EMAIL_RE = new RegExp(EMAIL_VALUE_PATTERN);
24
+ const utf8 = new TextEncoder();
25
+ /** Characters of a string, as Postgres and people count them (a surrogate pair is one). */
26
+ export function stringChars(value) {
27
+ let count = 0;
28
+ for (const _ of value)
29
+ count += 1;
30
+ return count;
31
+ }
32
+ /** UTF-8 bytes of a string. */
33
+ export function utf8Bytes(value) {
34
+ return utf8.encode(value).length;
35
+ }
36
+ /** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
37
+ export function indexedBytes(value) {
38
+ return Math.max(utf8Bytes(value), utf8Bytes(value.toLowerCase()));
39
+ }
40
+ /** What a value of `dataType` must look like, for messages. */
41
+ export function dataTypeFormat(dataType) {
42
+ switch (dataType) {
43
+ case 'string':
44
+ return `a string of at most ${LIMITS.stringBytes} bytes (UTF-8; a longer value is a text field)`;
45
+ case 'text':
46
+ return `a string of at most ${LIMITS.textBytes} bytes`;
47
+ case 'phone':
48
+ return 'a phone number, any country (stored as E.164, e.g. +14155550123; with an extension +14155550123;ext=12)';
49
+ case 'email':
50
+ return 'an email address';
51
+ case 'date':
52
+ return DATE_VALUE_FORMAT;
53
+ case 'datetime':
54
+ return DATETIME_VALUE_FORMAT;
55
+ case 'time':
56
+ return TIME_VALUE_FORMAT;
57
+ case 'select':
58
+ return 'one of its options';
59
+ case 'multi_select':
60
+ return 'a list of its options ([] for none of them)';
61
+ default:
62
+ return dataType;
63
+ }
64
+ }
4
65
  export function isValidDataTypeValue(dataType, value) {
5
66
  if (value === null)
6
67
  return true;
7
68
  switch (dataType) {
8
69
  case 'string':
9
- return typeof value === 'string';
70
+ return typeof value === 'string' && indexedBytes(value) <= LIMITS.stringBytes;
71
+ case 'text':
72
+ return typeof value === 'string' && utf8Bytes(value) <= LIMITS.textBytes;
73
+ case 'phone':
74
+ return typeof value === 'string' && PHONE_RE.test(value);
75
+ case 'email':
76
+ return typeof value === 'string' && EMAIL_RE.test(value);
10
77
  case 'number':
11
78
  return typeof value === 'number' && Number.isFinite(value);
12
79
  case 'boolean':
@@ -15,61 +82,22 @@ export function isValidDataTypeValue(dataType, value) {
15
82
  return typeof value === 'string' && DATE_RE.test(value);
16
83
  case 'datetime':
17
84
  return typeof value === 'string' && DATETIME_RE.test(value);
85
+ case 'time':
86
+ return typeof value === 'string' && TIME_RE.test(value);
87
+ case 'select':
88
+ return typeof value === 'string';
89
+ case 'multi_select':
90
+ return Array.isArray(value) && value.every((item) => typeof item === 'string');
91
+ case 'contact_schedule':
92
+ return contactScheduleValueSchema.safeParse(value).success;
18
93
  }
19
94
  }
20
- export function validateExtractedField(field, extracted, path) {
21
- const issues = [];
22
- if (typeof extracted.reason !== 'string' || extracted.reason.length === 0) {
23
- issues.push({
24
- code: 'missing-reason',
25
- message: 'Extracted field requires a non-empty reason',
26
- path,
27
- });
28
- }
29
- if (extracted.state !== 'filled' && extracted.state !== 'asked_unknown' && extracted.state !== 'declined') {
30
- issues.push({
31
- code: 'invalid-state',
32
- message: `Invalid extracted state: ${String(extracted.state)}`,
33
- path,
34
- });
35
- return issues;
36
- }
37
- if (extracted.state === 'declined' && extracted.value !== null) {
38
- issues.push({
39
- code: 'declined-non-null',
40
- message: 'declined fields must have value null',
41
- path,
42
- });
43
- }
44
- if (extracted.state === 'filled' && extracted.value === null && !field.nullable) {
45
- issues.push({
46
- code: 'filled-null',
47
- message: 'filled requires non-null value unless nullable: true',
48
- path,
49
- });
50
- }
51
- if (extracted.value !== null && !isValidDataTypeValue(field.dataType, extracted.value)) {
52
- issues.push({
53
- code: 'type-mismatch',
54
- message: `value does not match dataType ${field.dataType}`,
55
- path,
56
- });
57
- }
58
- if (extracted.value !== null && field.enum && !field.enum.includes(extracted.value)) {
59
- issues.push({
60
- code: 'enum-mismatch',
61
- message: `value ${String(extracted.value)} not in enum`,
62
- path,
63
- });
64
- }
65
- return issues;
66
- }
67
- /** Validate a bare write value for a normal or derived field. */
95
+ /** Validate a bare write value for a field. */
68
96
  export function validateBareValue(field, value, path, options = {}) {
69
97
  const issues = [];
70
98
  const allowNull = options.allowNull ?? true;
71
99
  if (value === null || value === undefined) {
72
- if (!allowNull && !(field.derived === false && field.nullable)) {
100
+ if (!allowNull) {
73
101
  issues.push({
74
102
  code: 'null-not-allowed',
75
103
  message: 'null is not allowed for this field',
@@ -81,17 +109,25 @@ export function validateBareValue(field, value, path, options = {}) {
81
109
  if (!isValidDataTypeValue(field.dataType, value)) {
82
110
  issues.push({
83
111
  code: 'type-mismatch',
84
- message: `value does not match dataType ${field.dataType}`,
112
+ message: `value does not match dataType ${field.dataType}: expected ${dataTypeFormat(field.dataType)}`,
85
113
  path,
86
114
  });
87
115
  }
88
- if (!field.derived && field.enum && !field.enum.includes(value)) {
116
+ const outside = optionsOutside(field, value);
117
+ if (outside.length > 0) {
89
118
  issues.push({
90
- code: 'enum-mismatch',
91
- message: `value ${String(value)} not in enum`,
119
+ code: 'not-an-option',
120
+ message: `${outside.map((v) => JSON.stringify(v)).join(', ')} not one of the options (${field.options.join(', ')})`,
92
121
  path,
93
122
  });
94
123
  }
95
124
  return issues;
96
125
  }
126
+ /** What of a `select` / `multi_select` value is not one of the field's options; empty for any other field. */
127
+ export function optionsOutside(field, value) {
128
+ if (!field.options)
129
+ return [];
130
+ const items = Array.isArray(value) ? value : [value];
131
+ return items.filter((item) => !field.options.includes(item));
132
+ }
97
133
  //# sourceMappingURL=value.js.map