@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
@@ -0,0 +1,244 @@
1
+ /** The wall-clock parts of an instant in `timezone`, from one formatter (plus its UTC offset when asked). */
2
+ function localParts(at, timezone, withOffset = false) {
3
+ const parts = Object.fromEntries(new Intl.DateTimeFormat('en-US', {
4
+ timeZone: timezone,
5
+ hourCycle: 'h23',
6
+ year: 'numeric',
7
+ month: '2-digit',
8
+ day: '2-digit',
9
+ hour: '2-digit',
10
+ minute: '2-digit',
11
+ second: '2-digit',
12
+ ...(withOffset ? { timeZoneName: 'longOffset' } : {}),
13
+ })
14
+ .formatToParts(at)
15
+ .map((part) => [part.type, part.value]));
16
+ return parts;
17
+ }
18
+ /** `YYYY-MM-DD` of an instant in `timezone`. */
19
+ export function localDay(at, timezone) {
20
+ const parts = localParts(new Date(at), timezone);
21
+ return `${parts.year}-${parts.month}-${parts.day}`;
22
+ }
23
+ /** `YYYY-MM-DD HH:mm:ss` of an instant in `timezone`. */
24
+ export function localDateTime(at, timezone) {
25
+ const parts = localParts(new Date(at), timezone);
26
+ return `${parts.year}-${parts.month}-${parts.day} ${parts.hour}:${parts.minute}:${parts.second}`;
27
+ }
28
+ /** ISO 8601 in `timezone` with its UTC offset, e.g. `2026-10-09T06:25:00-04:00`: a time that names its own zone. */
29
+ export function zonedIso(at, timezone) {
30
+ const parts = localParts(new Date(at), timezone, true);
31
+ const name = parts.timeZoneName ?? 'GMT';
32
+ const offset = name === 'GMT' ? '+00:00' : name.replace('GMT', '');
33
+ return `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}${offset}`;
34
+ }
35
+ /** `Current local time: 2026-10-08 10:05:00, Thursday, and October has 31 days`. */
36
+ function renderLocalClock(now, timezone) {
37
+ const parts = localParts(now, timezone);
38
+ const weekday = new Intl.DateTimeFormat('en-US', { timeZone: timezone, weekday: 'long' }).format(now);
39
+ const month = new Intl.DateTimeFormat('en-US', { timeZone: timezone, month: 'long' }).format(now);
40
+ const daysInMonth = new Date(Date.UTC(Number(parts.year), Number(parts.month), 0)).getUTCDate();
41
+ return `Current local time: ${localDateTime(now, timezone)}, ${weekday}, and ${month} has ${daysInMonth} days`;
42
+ }
43
+ function todayCounts(today) {
44
+ return `calls ${today.calls} (answered ${today.answeredCalls}), sms out ${today.smsOut}, sms in ${today.smsIn}, emails out ${today.emailsOut}, emails in ${today.emailsIn}`;
45
+ }
46
+ /** One party: `Today is [day 3]` and today's counts. */
47
+ function partyActivitySummary(party) {
48
+ return `Today is [day ${party.dayNumber}]\nToday so far: ${todayCounts(party.today)}`;
49
+ }
50
+ /** The whole case: the Case day and today's counts. */
51
+ function caseActivitySummary(activity) {
52
+ const { all, timezone } = activity;
53
+ const since = all.firstAt ? `day 1 = ${localDay(all.firstAt, timezone)}, ${timezone}` : 'no interactions yet';
54
+ return `Case day: [day ${all.dayNumber}] (${since})\nCase today so far: ${todayCounts(all.today)}`;
55
+ }
56
+ const WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
57
+ const WEEKDAY_NAMES = { mon: 'Mon', tue: 'Tue', wed: 'Wed', thu: 'Thu', fri: 'Fri', sat: 'Sat', sun: 'Sun' };
58
+ /** `09:00-12:00, 14:00-17:00`, or `none`. */
59
+ function hoursText(windows) {
60
+ return windows.length > 0 ? windows.map((window) => `${window.start}-${window.end}`).join(', ') : 'none';
61
+ }
62
+ /**
63
+ * The party's own contact hours (their `contact_schedule`), in their timezone: a line per weekday
64
+ * (`every day` when all are the same), then one per date that differs. None on file: one line saying
65
+ * so. The company's rules for when to reach them are its own (25 §3), not shown here.
66
+ */
67
+ function partyContactHours(party) {
68
+ const { source, weekly, dateOverrides } = party.contactHours;
69
+ if (source === 'none')
70
+ return "Customer's own contact hours: none on file.";
71
+ const days = WEEKDAYS.map((day) => hoursText(weekly[day]));
72
+ const sameEveryDay = days.every((text) => text === days[0]);
73
+ return [
74
+ "Customer's own contact hours (from their contact schedule; reach them only inside these):",
75
+ ...(sameEveryDay ? [`- every day: ${days[0]}`] : WEEKDAYS.map((day, i) => `- ${WEEKDAY_NAMES[day]}: ${days[i]}`)),
76
+ ...dateOverrides.map((override) => `- ${override.date} only: ${hoursText(override.windows)}`),
77
+ ].join('\n');
78
+ }
79
+ const CHANNEL_ORDER = ['sms', 'email', 'call'];
80
+ function unavailableReason(channel, availability) {
81
+ const reason = availability.unavailableChannels[channel];
82
+ if (reason === 'opted_out')
83
+ return ' (opted out)';
84
+ if (reason === 'unreachable')
85
+ return ' (the number cannot take texts)';
86
+ if (reason === 'no_address')
87
+ return channel === 'email' ? ' (no email address on file)' : ' (no phone number on file)';
88
+ return '';
89
+ }
90
+ /** `sms: true` per channel; an unavailable one says why. */
91
+ function partyChannelAvailability(availability) {
92
+ return CHANNEL_ORDER.map((channel) => availability.channels[channel]
93
+ ? `${channel}: true`
94
+ : `${channel}: false${unavailableReason(channel, availability)}`).join('\n');
95
+ }
96
+ /** ` [13s]` for a call whose length is known. */
97
+ function duration(event) {
98
+ return event.durationSec === null ? '' : ` [${event.durationSec}s]`;
99
+ }
100
+ function describeEvent(event) {
101
+ if (event.channel === 'call') {
102
+ const result = event.result === 'answered' ? 'answered' : event.result === 'failed' ? 'failed' : 'no answer';
103
+ return `call [${event.direction}] [${result}]${duration(event)}`;
104
+ }
105
+ if (event.direction === 'inbound')
106
+ return `${event.channel} [customer] [reply]`;
107
+ return `${event.channel} [agent] [${event.result === 'failed' ? 'failed' : 'follow-up'}]`;
108
+ }
109
+ /** Events grouped by day: `[day N] [YYYY-MM-DD]:`, then `[YYYY-MM-DD HH:mm:ss] <event> exchangeId …`. */
110
+ function partyTimeline(party, options = {}) {
111
+ let events = party.recent;
112
+ if (options.sinceDays !== undefined) {
113
+ const firstDay = party.dayNumber - options.sinceDays + 1;
114
+ events = events.filter((event) => event.dayNumber >= firstDay);
115
+ }
116
+ if (options.limit !== undefined)
117
+ events = events.slice(-options.limit);
118
+ const hidden = party.total > events.length;
119
+ if (events.length === 0) {
120
+ return party.total === 0
121
+ ? 'No interactions found.'
122
+ : 'No interactions in this range. Earlier exchanges are not shown; use searchExchanges for them.';
123
+ }
124
+ const days = [];
125
+ let current = null;
126
+ let lines = [];
127
+ const flush = () => {
128
+ if (lines.length > 0)
129
+ days.push(lines.join('\n'));
130
+ lines = [];
131
+ };
132
+ for (const event of events) {
133
+ if (event.dayNumber !== current) {
134
+ flush();
135
+ current = event.dayNumber;
136
+ lines.push(`[day ${event.dayNumber}] [${localDay(event.occurredAt, party.timezone)}]:`);
137
+ }
138
+ const scheduled = event.scheduledActionId ? ` scheduledActionId ${event.scheduledActionId}` : '';
139
+ lines.push(`[${localDateTime(event.occurredAt, party.timezone)}] ${describeEvent(event)} exchangeId ${event.exchangeId}${scheduled}`);
140
+ }
141
+ flush();
142
+ const text = days.join('\n\n');
143
+ return hidden ? `${text}\n\nEarlier exchanges are not shown; use searchExchanges for them.` : text;
144
+ }
145
+ /** ` [agreed in <exchangeId> at <local time of the party's message>]` on an agreed follow-up. */
146
+ function agreedMark(action, timezone) {
147
+ const agreement = action.input.agreement;
148
+ return agreement ? ` [agreed in ${agreement.exchangeId} at ${localDateTime(agreement.agreedAt, timezone)}]` : '';
149
+ }
150
+ /**
151
+ * `- <id>: <kind> at <local time> [agreed in …] (<note or reason>) {"timing":…}`; an agreed
152
+ * follow-up is marked, scheduled slot writes say why and carry their `writes`, a hand-over names its
153
+ * sequence, a wake-up its name. `(none)` when empty.
154
+ */
155
+ function pendingActions(actions, timezone) {
156
+ if (actions.length === 0)
157
+ return '(none)';
158
+ return actions
159
+ .map((action) => {
160
+ const head = `- ${action.id}: ${action.kind} at ${localDateTime(action.scheduledFor, timezone)}`;
161
+ const why = action.reason ? ` (${action.reason})` : '';
162
+ if (action.kind === 'update_slots') {
163
+ const { timing, writes } = action.input;
164
+ return `${head}${why} ${JSON.stringify({ timing, writes })}`;
165
+ }
166
+ if (action.kind === 'next_sequence') {
167
+ const { timing, sequence, subjectRecordId } = action.input;
168
+ return `${head}${why} ${JSON.stringify({ timing, sequence, ...(subjectRecordId ? { subjectRecordId } : {}) })}`;
169
+ }
170
+ if (action.kind === 'wake') {
171
+ const { timing } = action.input;
172
+ const name = action.name;
173
+ return `${head} ${name}${why} ${JSON.stringify({ timing })}`;
174
+ }
175
+ const { timing } = action.input;
176
+ return `${head}${agreedMark(action, timezone)}${why} ${JSON.stringify({ timing })}`;
177
+ })
178
+ .join('\n');
179
+ }
180
+ /**
181
+ * Why the Run woke up when nothing happened in a conversation (25 §6): each `timer` (a wake-up the
182
+ * Orchestrator booked) and `external` trigger (company code's `instances.notify`), as
183
+ * `- timer <name> at <local time> (<note>)` / `- external <reason> at <local time>`.
184
+ * `(none)` when there are none.
185
+ */
186
+ function wakeUps(triggers, timezone) {
187
+ const lines = triggers.flatMap((trigger) => {
188
+ const at = localDateTime(trigger.occurredAt, timezone);
189
+ if (trigger.type === 'timer')
190
+ return [`- timer ${trigger.name} at ${at}${trigger.note ? ` (${trigger.note})` : ''}`];
191
+ if (trigger.type === 'external')
192
+ return [`- external ${trigger.reason} at ${at}`];
193
+ if (trigger.type === 'inbound.paused')
194
+ return [`- inbound ${trigger.channel} ${trigger.exchangeId} at ${at}, not answered: the case was paused`];
195
+ if (trigger.type === 'scheduled_action.ended') {
196
+ return [`- scheduled ${trigger.kind} ${trigger.scheduledActionId} at ${at}: ${trigger.outcome === 'not_sent' ? `not sent (${trigger.reason ?? 'decided'})` : 'slots written'}`];
197
+ }
198
+ return [];
199
+ });
200
+ return lines.length > 0 ? lines.join('\n') : '(none)';
201
+ }
202
+ /**
203
+ * Finished agreed follow-ups: `- <id>: <kind> at <local time> [agreed in …], <status> at <local time> (<note>)`,
204
+ * the second time being when it finished. `(none)` when empty.
205
+ */
206
+ function recentAgreedActions(actions, timezone) {
207
+ if (actions.length === 0)
208
+ return '(none)';
209
+ return actions
210
+ .map((action) => `- ${action.id}: ${action.kind} at ${localDateTime(action.scheduledFor, timezone)}${agreedMark(action, timezone)}, ${action.status} at ${localDateTime(action.finishedAt, timezone)}${action.reason ? ` (${action.reason})` : ''}`)
211
+ .join('\n');
212
+ }
213
+ /**
214
+ * One exchange's words (a `readExchange` result): a head line naming it, then
215
+ * `[YYYY-MM-DD HH:mm:ss] customer|rep: <text>` per entry, in `timezone`.
216
+ */
217
+ function conversation(result, timezone, options = {}) {
218
+ const entries = options.limit !== undefined ? result.entries.slice(-options.limit) : result.entries;
219
+ const party = result.contactId ? ` with customer ${result.contactId}` : '';
220
+ const head = `${result.channel} [${result.direction}] exchangeId ${result.exchangeId}${party}:`;
221
+ if (entries.length === 0)
222
+ return `${head}\n(nothing was said)`;
223
+ const earlier = result.range.from > 0 || entries.length < result.entries.length ? 'Earlier entries are not shown.\n' : '';
224
+ const lines = entries.map((entry) => `[${localDateTime(entry.at, timezone)}] ${entry.speaker === 'party' ? 'customer' : 'rep'}: ${entry.text}`);
225
+ return `${head}\n${earlier}${lines.join('\n')}`;
226
+ }
227
+ /**
228
+ * Text for company code to show or log (docs/design/08-case-orchestrator.md §5.3), in the mars next-step
229
+ * format. Party functions take one contact's activity (`activity.byContact[contactId]`) and
230
+ * write its local wall-clock times.
231
+ */
232
+ export const render = {
233
+ localClock: renderLocalClock,
234
+ activitySummary: partyActivitySummary,
235
+ caseActivitySummary,
236
+ contactHours: partyContactHours,
237
+ channelAvailability: partyChannelAvailability,
238
+ timeline: partyTimeline,
239
+ pendingActions,
240
+ recentAgreedActions,
241
+ wakeUps,
242
+ conversation,
243
+ };
244
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Picking a time for a contact in company code (25 §4): the platform runs an action at its `at`,
3
+ * exactly, so spreading contacts is the code's own choice. Part of the company API (`src/index.ts`),
4
+ * bundled into company code as is: no imports.
5
+ */
6
+ /**
7
+ * A time in [`from`, `to`) (each a Date, ISO string or epoch ms), as an ISO string for `at`. With `seed` the same seed always gives the same
8
+ * time (a Run that is retried books the same moment); without one it is random.
9
+ */
10
+ export declare function randomTimeBetween(from: Date | string | number, to: Date | string | number, seed?: string): string;
11
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Picking a time for a contact in company code (25 §4): the platform runs an action at its `at`,
3
+ * exactly, so spreading contacts is the code's own choice. Part of the company API (`src/index.ts`),
4
+ * bundled into company code as is: no imports.
5
+ */
6
+ /** A 32-bit FNV-1a hash of `text`, as a fraction in [0, 1). */
7
+ function fraction(text) {
8
+ let hash = 0x811c9dc5;
9
+ for (let i = 0; i < text.length; i += 1) {
10
+ hash ^= text.charCodeAt(i);
11
+ hash = Math.imul(hash, 0x01000193) >>> 0;
12
+ }
13
+ return hash / 2 ** 32;
14
+ }
15
+ /**
16
+ * A time in [`from`, `to`) (each a Date, ISO string or epoch ms), as an ISO string for `at`. With `seed` the same seed always gives the same
17
+ * time (a Run that is retried books the same moment); without one it is random.
18
+ */
19
+ export function randomTimeBetween(from, to, seed) {
20
+ const start = new Date(from).getTime();
21
+ const end = new Date(to).getTime();
22
+ if (!Number.isFinite(start) || !Number.isFinite(end))
23
+ throw new Error('randomTimeBetween: from and to must be times');
24
+ if (end <= start)
25
+ throw new Error('randomTimeBetween: to must be later than from');
26
+ const share = seed === undefined ? Math.random() : fraction(seed);
27
+ return new Date(start + Math.floor(share * (end - start))).toISOString();
28
+ }
29
+ //# sourceMappingURL=time.js.map