@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.
- package/README.md +30 -10
- package/dist/builder/codegen/emit.d.ts +25 -12
- package/dist/builder/codegen/emit.js +339 -78
- package/dist/builder/codegen/generate.d.ts +21 -2
- package/dist/builder/codegen/generate.js +147 -34
- package/dist/builder/company-import-graph.d.ts +2 -0
- package/dist/builder/company-import-graph.js +40 -8
- package/dist/builder/company-imports.d.ts +29 -0
- package/dist/builder/company-imports.js +122 -0
- package/dist/builder/compile/compile-sequence.d.ts +61 -8
- package/dist/builder/compile/compile-sequence.js +334 -80
- package/dist/builder/compile/function-code.d.ts +19 -3
- package/dist/builder/compile/function-code.js +123 -45
- package/dist/builder/compile/registry.d.ts +7 -3
- package/dist/builder/compile/registry.js +30 -27
- package/dist/builder/errors.d.ts +9 -0
- package/dist/builder/errors.js +17 -0
- package/dist/builder/function-params.d.ts +10 -0
- package/dist/builder/function-params.js +203 -0
- package/dist/builder/load.d.ts +70 -10
- package/dist/builder/load.js +258 -67
- package/dist/builder/paths.d.ts +9 -1
- package/dist/builder/paths.js +32 -2
- package/dist/builder/schedules.d.ts +25 -0
- package/dist/builder/schedules.js +101 -0
- package/dist/builder/slot-schema-validation.d.ts +4 -0
- package/dist/builder/slot-schema-validation.js +10 -0
- package/dist/builder/typecheck.d.ts +8 -0
- package/dist/builder/typecheck.js +102 -0
- package/dist/builder/types.d.ts +127 -19
- package/dist/builder/types.js +21 -1
- package/dist/cli/auth/auth.d.ts +37 -0
- package/dist/cli/auth/auth.js +211 -0
- package/dist/cli/auth/backend-url.d.ts +5 -0
- package/dist/cli/auth/backend-url.js +25 -0
- package/dist/cli/auth/clipboard.d.ts +9 -0
- package/dist/cli/auth/clipboard.js +38 -0
- package/dist/cli/auth/http.d.ts +20 -0
- package/dist/cli/auth/http.js +27 -0
- package/dist/cli/auth/index.d.ts +10 -0
- package/dist/cli/auth/index.js +27 -0
- package/dist/cli/auth/progress.d.ts +12 -0
- package/dist/cli/auth/progress.js +15 -0
- package/dist/cli/auth/serve-login.d.ts +8 -0
- package/dist/cli/auth/serve-login.js +24 -0
- package/dist/cli/calls/index.d.ts +177 -0
- package/dist/cli/calls/index.js +96 -0
- package/dist/cli/compile/index.js +3 -0
- package/dist/cli/config.d.ts +10 -0
- package/dist/cli/config.js +52 -0
- package/dist/cli/debug/index.d.ts +31 -0
- package/dist/cli/debug/index.js +119 -0
- package/dist/cli/exec/index.d.ts +39 -0
- package/dist/cli/exec/index.js +138 -0
- package/dist/cli/exec/session.d.ts +48 -0
- package/dist/cli/exec/session.js +82 -0
- package/dist/cli/exec/trace.d.ts +18 -0
- package/dist/cli/exec/trace.js +52 -0
- package/dist/cli/index.js +112 -9
- package/dist/cli/logs/index.d.ts +47 -0
- package/dist/cli/logs/index.js +113 -0
- package/dist/cli/mobile/index.d.ts +12 -0
- package/dist/cli/mobile/index.js +405 -0
- package/dist/cli/serve/index.d.ts +109 -3
- package/dist/cli/serve/index.js +506 -118
- package/dist/cli/turns/index.d.ts +105 -0
- package/dist/cli/turns/index.js +128 -0
- package/dist/cli/turns/run.d.ts +13 -0
- package/dist/cli/turns/run.js +57 -0
- package/dist/cli/turns/shadow.d.ts +112 -0
- package/dist/cli/turns/shadow.js +54 -0
- package/dist/cli/type-gen/index.js +9 -9
- package/dist/compiler.d.ts +7 -0
- package/dist/compiler.js +7 -0
- package/dist/compute-host/compute-host.d.ts +14 -23
- package/dist/compute-host/compute-host.js +18 -30
- package/dist/compute-host/index.d.ts +2 -4
- package/dist/compute-host/index.js +1 -2
- package/dist/compute-host/source-compute-host.d.ts +10 -10
- package/dist/compute-host/source-compute-host.js +33 -40
- package/dist/core/case-orchestrator/contact-hours.d.ts +70 -0
- package/dist/core/case-orchestrator/contact-hours.js +127 -0
- package/dist/core/case-orchestrator/index.d.ts +3 -0
- package/dist/core/case-orchestrator/index.js +3 -0
- package/dist/core/case-orchestrator/render.d.ts +75 -0
- package/dist/core/case-orchestrator/render.js +244 -0
- package/dist/core/case-orchestrator/time.d.ts +11 -0
- package/dist/core/case-orchestrator/time.js +29 -0
- package/dist/core/case-orchestrator/types.d.ts +708 -0
- package/dist/core/case-orchestrator/types.js +42 -0
- package/dist/core/context/call.d.ts +291 -0
- package/dist/core/context/call.js +94 -0
- package/dist/core/context/channels.d.ts +60 -0
- package/dist/core/context/channels.js +35 -0
- package/dist/core/context/contact.d.ts +96 -6
- package/dist/core/context/contact.js +48 -2
- package/dist/core/context/email-message.d.ts +198 -0
- package/dist/core/context/email-message.js +86 -0
- package/dist/core/context/email.d.ts +109 -0
- package/dist/core/context/email.js +90 -0
- package/dist/core/context/exchanges.d.ts +167 -0
- package/dist/core/context/exchanges.js +81 -0
- package/dist/core/context/instances.d.ts +307 -0
- package/dist/core/context/instances.js +137 -0
- package/dist/core/context/kv.d.ts +113 -0
- package/dist/core/context/kv.js +60 -0
- package/dist/core/context/platform-registry.d.ts +544 -4
- package/dist/core/context/platform-registry.js +14 -2
- package/dist/core/context/platform.d.ts +2 -1
- package/dist/core/context/sms.d.ts +177 -0
- package/dist/core/context/sms.js +77 -0
- package/dist/core/context/types.d.ts +79 -48
- package/dist/core/context/types.js +1 -7
- package/dist/core/conversation/index.d.ts +85 -0
- package/dist/core/conversation/index.js +133 -0
- package/dist/core/functions/errors.d.ts +74 -0
- package/dist/core/functions/errors.js +26 -0
- package/dist/core/functions/events.d.ts +192 -0
- package/dist/core/functions/events.js +23 -0
- package/dist/core/functions/schedules.d.ts +50 -0
- package/dist/core/functions/schedules.js +20 -0
- package/dist/core/functions/types.d.ts +29 -73
- package/dist/core/functions/types.js +1 -4
- package/dist/core/office-hours/index.d.ts +39 -0
- package/dist/core/office-hours/index.js +187 -0
- package/dist/core/page/define.d.ts +904 -0
- package/dist/core/page/define.js +518 -0
- package/dist/core/page/envelope.d.ts +55 -0
- package/dist/core/page/envelope.js +4 -0
- package/dist/core/page/fns.d.ts +448 -0
- package/dist/core/page/fns.js +539 -0
- package/dist/core/page/memory-reader.d.ts +27 -0
- package/dist/core/page/memory-reader.js +299 -0
- package/dist/core/page/ops.d.ts +58 -0
- package/dist/core/page/ops.js +220 -0
- package/dist/core/page/page-host.d.ts +20 -0
- package/dist/core/page/page-host.js +57 -0
- package/dist/core/page/records-query.d.ts +234 -0
- package/dist/core/page/records-query.js +780 -0
- package/dist/core/page/render.d.ts +295 -0
- package/dist/core/page/render.js +1060 -0
- package/dist/core/page/sandbox.d.ts +85 -0
- package/dist/core/page/sandbox.js +357 -0
- package/dist/core/page/time-format.d.ts +46 -0
- package/dist/core/page/time-format.js +125 -0
- package/dist/core/page/timeline.d.ts +40 -0
- package/dist/core/page/timeline.js +2 -0
- package/dist/core/page/typed.d.ts +648 -0
- package/dist/core/page/typed.js +2 -0
- package/dist/core/page/workspace.d.ts +57 -0
- package/dist/core/page/workspace.js +266 -0
- package/dist/core/party/index.d.ts +3 -0
- package/dist/core/party/index.js +3 -0
- package/dist/core/party/schema.d.ts +208 -0
- package/dist/core/party/schema.js +113 -0
- package/dist/core/party/types.d.ts +35 -0
- package/dist/core/party/types.js +15 -0
- package/dist/core/sequence/define.d.ts +56 -0
- package/dist/core/sequence/define.js +10 -0
- package/dist/core/sequence/index.d.ts +63 -0
- package/dist/core/sequence/index.js +231 -0
- package/dist/core/slot/binding.d.ts +40 -0
- package/dist/core/slot/binding.js +2 -0
- package/dist/core/slot/company-metadata.d.ts +102 -0
- package/dist/core/slot/company-metadata.js +536 -0
- package/dist/core/slot/compile-schema.d.ts +19 -13
- package/dist/core/slot/compile-schema.js +51 -248
- package/dist/core/slot/contact-timezone.d.ts +110 -0
- package/dist/core/slot/contact-timezone.js +186 -0
- package/dist/core/slot/field.d.ts +2 -25
- package/dist/core/slot/field.js +0 -71
- package/dist/core/slot/id-ref.d.ts +17 -2
- package/dist/core/slot/id-ref.js +16 -8
- package/dist/core/slot/index.d.ts +12 -13
- package/dist/core/slot/index.js +11 -12
- package/dist/core/slot/naming.d.ts +15 -0
- package/dist/core/slot/naming.js +96 -0
- package/dist/core/slot/platform-fields.d.ts +119 -0
- package/dist/core/slot/platform-fields.js +121 -0
- package/dist/core/slot/ref.d.ts +16 -0
- package/dist/core/slot/ref.js +14 -0
- package/dist/core/slot/row.d.ts +2 -9
- package/dist/core/slot/row.js +13 -23
- package/dist/core/slot/schema-compat.d.ts +17 -0
- package/dist/core/slot/schema-compat.js +103 -0
- package/dist/core/slot/schema.d.ts +353 -76
- package/dist/core/slot/schema.js +163 -10
- package/dist/core/slot/types.d.ts +30 -103
- package/dist/core/slot/value.d.ts +28 -3
- package/dist/core/slot/value.js +93 -57
- package/dist/dev-overlay/protocol.d.ts +74 -8
- package/dist/fn-context/build-context.d.ts +3 -1
- package/dist/fn-context/build-context.js +26 -10
- package/dist/fn-context/fake/empty-api.js +9 -28
- package/dist/fn-context/fake/index.d.ts +13 -4
- package/dist/fn-context/fake/index.js +29 -2
- package/dist/fn-context/fn-params.d.ts +3 -0
- package/dist/fn-context/fn-params.js +10 -0
- package/dist/fn-context/index.d.ts +5 -5
- package/dist/fn-context/index.js +4 -4
- package/dist/fn-context/log.js +2 -2
- package/dist/fn-context/make-ctx.d.ts +11 -0
- package/dist/fn-context/make-ctx.js +20 -9
- package/dist/fn-context/rpc/case-orchestrator-tools.d.ts +32 -0
- package/dist/fn-context/rpc/case-orchestrator-tools.js +12 -0
- package/dist/fn-context/rpc/errors.d.ts +13 -0
- package/dist/fn-context/rpc/errors.js +22 -0
- package/dist/fn-context/rpc/index.d.ts +4 -2
- package/dist/fn-context/rpc/index.js +4 -2
- package/dist/fn-context/rpc/integration/index.d.ts +15 -5
- package/dist/fn-context/rpc/integration/index.js +1 -1
- package/dist/fn-context/rpc/integration/list-surfaces.d.ts +21 -0
- package/dist/fn-context/rpc/integration/{list-bindings.js → list-surfaces.js} +4 -4
- package/dist/fn-context/rpc/log.d.ts +11 -1
- package/dist/fn-context/rpc/platform.d.ts +13 -3
- package/dist/fn-context/rpc/platform.js +1 -1
- package/dist/fn-context/rpc/records.d.ts +85 -0
- package/dist/fn-context/rpc/records.js +24 -0
- package/dist/fn-context/rpc/trpc-client.d.ts +44 -2
- package/dist/fn-context/rpc/trpc-client.js +222 -12
- package/dist/fn-context/rpc/trpc-init.d.ts +21 -3
- package/dist/fn-context/rpc/trpc-init.js +10 -4
- package/dist/fn-context/rpc/trpc-router-factory.d.ts +111 -7
- package/dist/fn-context/rpc/trpc-router-factory.js +2 -0
- package/dist/fn-context/run-scope.d.ts +4 -0
- package/dist/fn-context/run-scope.js +9 -0
- package/dist/fn-context/types.d.ts +52 -5
- package/dist/index.d.ts +36 -46
- package/dist/index.js +30 -33
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +49 -0
- package/dist/platform.d.ts +75 -0
- package/dist/platform.js +57 -0
- package/dist/testing-compile-child.d.ts +2 -0
- package/dist/testing-compile-child.js +20 -0
- package/dist/testing.d.ts +368 -0
- package/dist/testing.js +439 -0
- package/dist/voice-service/actions.d.ts +50 -6
- package/dist/voice-service/index.d.ts +2 -0
- package/dist/voice-service/index.js +2 -0
- package/dist/voice-service/protocol.d.ts +604 -0
- package/dist/voice-service/protocol.js +67 -0
- package/dist/voice-service/types.d.ts +55 -8
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +11 -0
- package/package.json +38 -15
- package/dist/builder/compile/compile-agenda.d.ts +0 -15
- package/dist/builder/compile/compile-agenda.js +0 -64
- package/dist/builder/merge.d.ts +0 -4
- package/dist/builder/merge.js +0 -19
- package/dist/compute-host/read-only-cache.d.ts +0 -20
- package/dist/compute-host/read-only-cache.js +0 -61
- package/dist/core/context/db.d.ts +0 -69
- package/dist/core/context/db.js +0 -44
- package/dist/core/context/docusign.d.ts +0 -134
- package/dist/core/context/docusign.js +0 -108
- package/dist/core/context/filevine.d.ts +0 -323
- package/dist/core/context/filevine.js +0 -254
- package/dist/core/context/http.d.ts +0 -9
- package/dist/core/context/http.js +0 -4
- package/dist/core/context/hubspot.d.ts +0 -250
- package/dist/core/context/hubspot.js +0 -191
- package/dist/core/context/twilio.d.ts +0 -50
- package/dist/core/context/twilio.js +0 -42
- package/dist/core/functions/define/case-context.d.ts +0 -14
- package/dist/core/functions/define/case-context.js +0 -15
- package/dist/core/functions/define/compute.d.ts +0 -7
- package/dist/core/functions/define/compute.js +0 -17
- package/dist/core/functions/define/custom.d.ts +0 -4
- package/dist/core/functions/define/custom.js +0 -8
- package/dist/core/functions/define/system.d.ts +0 -7
- package/dist/core/functions/define/system.js +0 -12
- package/dist/core/functions/func-ref.d.ts +0 -16
- package/dist/core/functions/func-ref.js +0 -20
- package/dist/core/slot/deps.d.ts +0 -15
- package/dist/core/slot/deps.js +0 -88
- package/dist/core/slot/derived.d.ts +0 -32
- package/dist/core/slot/derived.js +0 -115
- package/dist/core/slot/platform-session-fields.d.ts +0 -38
- package/dist/core/slot/platform-session-fields.js +0 -48
- package/dist/core/slot/sf-schema.d.ts +0 -23
- package/dist/core/slot/sf-schema.js +0 -125
- package/dist/core/slot/sf-validate.d.ts +0 -14
- package/dist/core/slot/sf-validate.js +0 -132
- package/dist/core/slot/snapshot.d.ts +0 -18
- package/dist/core/slot/snapshot.js +0 -138
- package/dist/core/slot/write.d.ts +0 -48
- package/dist/core/slot/write.js +0 -426
- package/dist/core/stage/builders.d.ts +0 -54
- package/dist/core/stage/builders.js +0 -31
- package/dist/core/stage/condition.d.ts +0 -17
- package/dist/core/stage/condition.js +0 -198
- package/dist/core/stage/drive.d.ts +0 -43
- package/dist/core/stage/drive.js +0 -78
- package/dist/core/stage/finish-when.d.ts +0 -20
- package/dist/core/stage/finish-when.js +0 -82
- package/dist/core/stage/flatten.d.ts +0 -27
- package/dist/core/stage/flatten.js +0 -466
- package/dist/core/stage/index.d.ts +0 -15
- package/dist/core/stage/index.js +0 -13
- package/dist/core/stage/interrupts.d.ts +0 -28
- package/dist/core/stage/interrupts.js +0 -120
- package/dist/core/stage/ivr-fields.d.ts +0 -9
- package/dist/core/stage/ivr-fields.js +0 -75
- package/dist/core/stage/simulate.d.ts +0 -24
- package/dist/core/stage/simulate.js +0 -33
- package/dist/core/stage/transfer-fields.d.ts +0 -19
- package/dist/core/stage/transfer-fields.js +0 -129
- package/dist/core/stage/transfer-spec.d.ts +0 -48
- package/dist/core/stage/transfer-spec.js +0 -113
- package/dist/core/stage/types.d.ts +0 -208
- package/dist/core/stage/types.js +0 -2
- package/dist/core/stage/validate.d.ts +0 -11
- package/dist/core/stage/validate.js +0 -330
- package/dist/core/stage/walk.d.ts +0 -39
- package/dist/core/stage/walk.js +0 -119
- package/dist/fn-context/rpc/integration/list-bindings.d.ts +0 -21
- package/dist/fn-context/system-args.d.ts +0 -6
- 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
|