@superpanel-sdk/runtime 0.5.0 → 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 (189) hide show
  1. package/README.md +3 -3
  2. package/dist/builder/codegen/emit.d.ts +5 -10
  3. package/dist/builder/codegen/emit.js +100 -106
  4. package/dist/builder/codegen/generate.d.ts +3 -5
  5. package/dist/builder/codegen/generate.js +13 -32
  6. package/dist/builder/company-imports.d.ts +5 -0
  7. package/dist/builder/company-imports.js +9 -1
  8. package/dist/builder/compile/compile-sequence.d.ts +13 -11
  9. package/dist/builder/compile/compile-sequence.js +135 -83
  10. package/dist/builder/compile/function-code.d.ts +15 -9
  11. package/dist/builder/compile/function-code.js +59 -29
  12. package/dist/builder/compile/registry.d.ts +4 -4
  13. package/dist/builder/compile/registry.js +14 -12
  14. package/dist/builder/errors.d.ts +9 -0
  15. package/dist/builder/errors.js +17 -0
  16. package/dist/builder/function-params.d.ts +10 -0
  17. package/dist/builder/function-params.js +203 -0
  18. package/dist/builder/load.d.ts +17 -17
  19. package/dist/builder/load.js +27 -25
  20. package/dist/builder/paths.d.ts +6 -1
  21. package/dist/builder/paths.js +16 -2
  22. package/dist/builder/schedules.d.ts +9 -7
  23. package/dist/builder/schedules.js +20 -21
  24. package/dist/builder/typecheck.d.ts +1 -1
  25. package/dist/builder/typecheck.js +3 -6
  26. package/dist/builder/types.d.ts +41 -5
  27. package/dist/builder/types.js +19 -0
  28. package/dist/cli/calls/index.d.ts +177 -0
  29. package/dist/cli/calls/index.js +96 -0
  30. package/dist/cli/debug/index.d.ts +31 -0
  31. package/dist/cli/debug/index.js +119 -0
  32. package/dist/cli/exec/index.d.ts +39 -0
  33. package/dist/cli/exec/index.js +138 -0
  34. package/dist/cli/exec/session.d.ts +48 -0
  35. package/dist/cli/exec/session.js +82 -0
  36. package/dist/cli/exec/trace.d.ts +18 -0
  37. package/dist/cli/exec/trace.js +52 -0
  38. package/dist/cli/index.js +84 -1
  39. package/dist/cli/logs/index.d.ts +47 -0
  40. package/dist/cli/logs/index.js +113 -0
  41. package/dist/cli/mobile/index.d.ts +12 -0
  42. package/dist/cli/mobile/index.js +405 -0
  43. package/dist/cli/serve/index.d.ts +40 -4
  44. package/dist/cli/serve/index.js +167 -28
  45. package/dist/cli/turns/index.d.ts +105 -0
  46. package/dist/cli/turns/index.js +128 -0
  47. package/dist/cli/turns/run.d.ts +13 -0
  48. package/dist/cli/turns/run.js +57 -0
  49. package/dist/cli/turns/shadow.d.ts +112 -0
  50. package/dist/cli/turns/shadow.js +54 -0
  51. package/dist/cli/type-gen/index.js +0 -1
  52. package/dist/compute-host/compute-host.d.ts +5 -6
  53. package/dist/compute-host/compute-host.js +4 -13
  54. package/dist/compute-host/source-compute-host.d.ts +5 -7
  55. package/dist/compute-host/source-compute-host.js +12 -33
  56. package/dist/core/case-orchestrator/contact-hours.d.ts +26 -6
  57. package/dist/core/case-orchestrator/contact-hours.js +27 -8
  58. package/dist/core/case-orchestrator/index.d.ts +1 -4
  59. package/dist/core/case-orchestrator/index.js +1 -4
  60. package/dist/core/case-orchestrator/render.d.ts +1 -1
  61. package/dist/core/case-orchestrator/render.js +15 -10
  62. package/dist/core/case-orchestrator/types.d.ts +83 -128
  63. package/dist/core/case-orchestrator/types.js +0 -4
  64. package/dist/core/context/email-message.d.ts +40 -1
  65. package/dist/core/context/email-message.js +27 -0
  66. package/dist/core/context/email.d.ts +13 -1
  67. package/dist/core/context/email.js +2 -3
  68. package/dist/core/context/exchanges.d.ts +25 -0
  69. package/dist/core/context/exchanges.js +25 -7
  70. package/dist/core/context/instances.d.ts +31 -2
  71. package/dist/core/context/instances.js +18 -4
  72. package/dist/core/context/platform-registry.d.ts +35 -0
  73. package/dist/core/context/sms.d.ts +30 -0
  74. package/dist/core/context/sms.js +20 -0
  75. package/dist/core/context/types.d.ts +29 -1
  76. package/dist/core/conversation/index.d.ts +58 -4
  77. package/dist/core/conversation/index.js +123 -4
  78. package/dist/core/functions/errors.d.ts +74 -0
  79. package/dist/core/functions/errors.js +26 -0
  80. package/dist/core/functions/events.d.ts +23 -78
  81. package/dist/core/functions/events.js +8 -17
  82. package/dist/core/functions/schedules.d.ts +9 -10
  83. package/dist/core/functions/schedules.js +2 -2
  84. package/dist/core/functions/types.d.ts +17 -72
  85. package/dist/core/functions/types.js +1 -9
  86. package/dist/core/page/define.d.ts +230 -160
  87. package/dist/core/page/define.js +145 -104
  88. package/dist/core/page/envelope.d.ts +55 -0
  89. package/dist/core/page/envelope.js +4 -0
  90. package/dist/core/page/fns.d.ts +448 -0
  91. package/dist/core/page/fns.js +539 -0
  92. package/dist/core/page/memory-reader.d.ts +27 -0
  93. package/dist/core/page/memory-reader.js +299 -0
  94. package/dist/core/page/page-host.d.ts +20 -0
  95. package/dist/core/page/page-host.js +57 -0
  96. package/dist/core/page/records-query.d.ts +234 -0
  97. package/dist/core/page/records-query.js +780 -0
  98. package/dist/core/page/render.d.ts +67 -25
  99. package/dist/core/page/render.js +492 -272
  100. package/dist/core/page/sandbox.d.ts +85 -0
  101. package/dist/core/page/sandbox.js +357 -0
  102. package/dist/core/page/time-format.d.ts +27 -0
  103. package/dist/core/page/time-format.js +84 -0
  104. package/dist/core/page/typed.d.ts +165 -159
  105. package/dist/core/page/workspace.d.ts +25 -1
  106. package/dist/core/page/workspace.js +48 -13
  107. package/dist/core/party/schema.d.ts +74 -3
  108. package/dist/core/party/schema.js +39 -6
  109. package/dist/core/party/types.d.ts +8 -13
  110. package/dist/core/sequence/define.d.ts +1 -2
  111. package/dist/core/slot/company-metadata.d.ts +11 -22
  112. package/dist/core/slot/company-metadata.js +12 -39
  113. package/dist/core/slot/compile-schema.js +6 -6
  114. package/dist/core/slot/field.d.ts +1 -2
  115. package/dist/core/slot/field.js +0 -2
  116. package/dist/core/slot/index.d.ts +3 -3
  117. package/dist/core/slot/index.js +3 -3
  118. package/dist/core/slot/naming.d.ts +1 -1
  119. package/dist/core/slot/naming.js +1 -1
  120. package/dist/core/slot/platform-fields.d.ts +4 -4
  121. package/dist/core/slot/platform-fields.js +5 -5
  122. package/dist/core/slot/schema-compat.d.ts +8 -7
  123. package/dist/core/slot/schema-compat.js +22 -31
  124. package/dist/core/slot/schema.d.ts +3 -59
  125. package/dist/core/slot/schema.js +0 -15
  126. package/dist/core/slot/types.d.ts +4 -10
  127. package/dist/core/slot/value.d.ts +2 -0
  128. package/dist/core/slot/value.js +6 -2
  129. package/dist/dev-overlay/protocol.d.ts +38 -5
  130. package/dist/fn-context/build-context.js +10 -4
  131. package/dist/fn-context/fake/index.d.ts +2 -0
  132. package/dist/fn-context/fake/index.js +5 -3
  133. package/dist/fn-context/fn-params.d.ts +2 -5
  134. package/dist/fn-context/fn-params.js +6 -9
  135. package/dist/fn-context/index.d.ts +1 -1
  136. package/dist/fn-context/make-ctx.js +5 -4
  137. package/dist/fn-context/rpc/case-orchestrator-tools.d.ts +11 -3
  138. package/dist/fn-context/rpc/case-orchestrator-tools.js +0 -1
  139. package/dist/fn-context/rpc/errors.d.ts +13 -0
  140. package/dist/fn-context/rpc/errors.js +22 -0
  141. package/dist/fn-context/rpc/index.d.ts +1 -1
  142. package/dist/fn-context/rpc/index.js +1 -1
  143. package/dist/fn-context/rpc/integration/index.d.ts +11 -1
  144. package/dist/fn-context/rpc/log.d.ts +11 -1
  145. package/dist/fn-context/rpc/platform.d.ts +11 -1
  146. package/dist/fn-context/rpc/records.d.ts +13 -6
  147. package/dist/fn-context/rpc/records.js +2 -4
  148. package/dist/fn-context/rpc/trpc-client.d.ts +42 -0
  149. package/dist/fn-context/rpc/trpc-client.js +151 -22
  150. package/dist/fn-context/rpc/trpc-init.d.ts +19 -1
  151. package/dist/fn-context/rpc/trpc-init.js +10 -4
  152. package/dist/fn-context/rpc/trpc-router-factory.d.ts +66 -8
  153. package/dist/fn-context/run-scope.js +1 -1
  154. package/dist/fn-context/types.d.ts +20 -6
  155. package/dist/index.d.ts +11 -12
  156. package/dist/index.js +5 -8
  157. package/dist/logger.d.ts +4 -0
  158. package/dist/logger.js +8 -0
  159. package/dist/platform.d.ts +32 -33
  160. package/dist/platform.js +23 -22
  161. package/dist/testing-compile-child.d.ts +2 -0
  162. package/dist/testing-compile-child.js +20 -0
  163. package/dist/testing.d.ts +368 -0
  164. package/dist/testing.js +439 -0
  165. package/dist/voice-service/actions.d.ts +12 -35
  166. package/dist/voice-service/index.d.ts +2 -0
  167. package/dist/voice-service/index.js +2 -0
  168. package/dist/voice-service/protocol.d.ts +604 -0
  169. package/dist/voice-service/protocol.js +67 -0
  170. package/dist/voice-service/types.d.ts +16 -6
  171. package/dist/worker.d.ts +2 -1
  172. package/dist/worker.js +2 -1
  173. package/package.json +20 -16
  174. package/dist/core/case-orchestrator/follow-ups.d.ts +0 -31
  175. package/dist/core/case-orchestrator/follow-ups.js +0 -103
  176. package/dist/core/case-orchestrator/tools.d.ts +0 -29
  177. package/dist/core/case-orchestrator/tools.js +0 -31
  178. package/dist/core/case-orchestrator/validate.d.ts +0 -11
  179. package/dist/core/case-orchestrator/validate.js +0 -63
  180. package/dist/core/functions/define/bind.d.ts +0 -25
  181. package/dist/core/functions/define/bind.js +0 -14
  182. package/dist/core/functions/define/case.d.ts +0 -9
  183. package/dist/core/functions/define/case.js +0 -13
  184. package/dist/core/functions/define/events.d.ts +0 -20
  185. package/dist/core/functions/define/events.js +0 -21
  186. package/dist/core/functions/define/no-case.d.ts +0 -4
  187. package/dist/core/functions/define/no-case.js +0 -9
  188. package/dist/core/functions/func-ref.d.ts +0 -25
  189. package/dist/core/functions/func-ref.js +0 -20
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { type CaseActivity } from '../case-orchestrator/types.js';
2
3
  /**
3
4
  * One exchange, as company code names it (21 §11.4): each channel the way it is told apart — a call by
4
5
  * its id, a text line by our number and theirs, an email by its thread.
@@ -33,6 +34,7 @@ export declare const exchangeLastInput: z.ZodObject<{
33
34
  kind: z.ZodEnum<{
34
35
  email: "email";
35
36
  phone: "phone";
37
+ sip: "sip";
36
38
  }>;
37
39
  value: z.ZodString;
38
40
  }, z.core.$strip>;
@@ -62,6 +64,7 @@ export declare const exchangeEmailThreadInput: z.ZodObject<{
62
64
  kind: z.ZodEnum<{
63
65
  email: "email";
64
66
  phone: "phone";
67
+ sip: "sip";
65
68
  }>;
66
69
  value: z.ZodString;
67
70
  }, z.core.$strip>;
@@ -77,12 +80,25 @@ export declare const exchangeEmailThreadOutput: z.ZodObject<{
77
80
  }, z.core.$strip>>;
78
81
  }, z.core.$strip>;
79
82
  export type ExchangeEmailThreadResult = z.infer<typeof exchangeEmailThreadOutput>;
83
+ /**
84
+ * What one instance exchanged with the contacts its code names (38 §2.8): each one's history, contact
85
+ * hours and channel availability, the instance's together. The Orchestrator reads it to write its
86
+ * prompt; whom to name is its own to read from the business data.
87
+ */
88
+ export declare const exchangeActivityInput: z.ZodObject<{
89
+ instanceId: z.ZodString;
90
+ contactIds: z.ZodArray<z.ZodString>;
91
+ }, z.core.$strip>;
92
+ export type ExchangeActivityParams = z.infer<typeof exchangeActivityInput>;
93
+ export declare const exchangeActivityOutput: z.ZodCustom<CaseActivity, CaseActivity>;
80
94
  /** Platform exchange lookups, reached from scripts as `ctx.api.exchanges` (§18.4). */
81
95
  export type ExchangesApi = {
82
96
  /** The latest exchange between `ours` and `theirs`; null when they never exchanged anything. */
83
97
  last(input: ExchangeLastParams): Promise<ExchangeLastResult>;
84
98
  /** The instance an email thread belongs to; null when no message of it is on an instance. */
85
99
  emailThread(input: ExchangeEmailThreadParams): Promise<ExchangeEmailThreadResult>;
100
+ /** An instance's exchanges with `contactIds`, in that order: the first one's time zone is the instance's. */
101
+ activity(input: ExchangeActivityParams): Promise<CaseActivity>;
86
102
  };
87
103
  /** Stand-in surface for fake contexts and local runs; never touches the database. */
88
104
  export declare const exchangesMockService: ExchangesApi;
@@ -94,6 +110,7 @@ export declare const exchangesSurface: {
94
110
  kind: z.ZodEnum<{
95
111
  email: "email";
96
112
  phone: "phone";
113
+ sip: "sip";
97
114
  }>;
98
115
  value: z.ZodString;
99
116
  }, z.core.$strip>;
@@ -123,6 +140,7 @@ export declare const exchangesSurface: {
123
140
  kind: z.ZodEnum<{
124
141
  email: "email";
125
142
  phone: "phone";
143
+ sip: "sip";
126
144
  }>;
127
145
  value: z.ZodString;
128
146
  }, z.core.$strip>;
@@ -136,6 +154,13 @@ export declare const exchangesSurface: {
136
154
  }, z.core.$strip>>;
137
155
  }, z.core.$strip>;
138
156
  };
157
+ activity: {
158
+ input: z.ZodObject<{
159
+ instanceId: z.ZodString;
160
+ contactIds: z.ZodArray<z.ZodString>;
161
+ }, z.core.$strip>;
162
+ output: z.ZodCustom<CaseActivity, CaseActivity>;
163
+ };
139
164
  };
140
165
  mock: ExchangesApi;
141
166
  };
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { arrivalAddress, partyAddress } from '../party/schema.js';
2
+ import { arrivalAddress } from '../party/schema.js';
3
+ import { EMPTY_CASE_ACTIVITY } from '../case-orchestrator/types.js';
3
4
  /**
4
5
  * One exchange, as company code names it (21 §11.4): each channel the way it is told apart — a call by
5
6
  * its id, a text line by our number and theirs, an email by its thread.
@@ -25,25 +26,38 @@ export const exchangeSummary = z.object({
25
26
  contactId: z.string().nullable(),
26
27
  });
27
28
  export const exchangeLastInput = z.strictObject({
28
- /** Our number or mailbox (`ctx.params.to`). */
29
- ours: partyAddress,
29
+ /** Our number, SIP address or mailbox (`conversation.to` of `resolve`). A SIP address has calls only. */
30
+ ours: arrivalAddress,
30
31
  /**
31
- * Theirs (`ctx.params.from`). Phone exchanges are calls and texts; email ones are emails; a SIP caller's
32
+ * Theirs (`conversation.from`). Phone exchanges are calls and texts; email ones are emails; a SIP caller's
32
33
  * URI finds their calls from it.
33
34
  */
34
35
  theirs: arrivalAddress,
35
36
  });
36
37
  export const exchangeLastOutput = z.object({ exchange: exchangeSummary.nullable() });
37
38
  export const exchangeEmailThreadInput = z.strictObject({
38
- /** Our mailbox the email came to (`ctx.params.to`): a provider thread id is only one mailbox's. */
39
- ours: partyAddress,
40
- /** The provider thread id (`ctx.params.threadId`). */
39
+ /**
40
+ * Our mailbox the email came to (`conversation.to` of `resolve`): a provider thread id is only one
41
+ * mailbox's. A number or SIP address has no threads.
42
+ */
43
+ ours: arrivalAddress,
44
+ /** The provider thread id (`conversation.threadId`). */
41
45
  threadId: z.string().min(1),
42
46
  });
43
47
  /** The instance an email thread already belongs to. */
44
48
  export const exchangeEmailThreadOutput = z.object({
45
49
  thread: z.object({ instanceId: z.string(), sequence: z.string(), instanceActive: z.boolean() }).nullable(),
46
50
  });
51
+ /**
52
+ * What one instance exchanged with the contacts its code names (38 §2.8): each one's history, contact
53
+ * hours and channel availability, the instance's together. The Orchestrator reads it to write its
54
+ * prompt; whom to name is its own to read from the business data.
55
+ */
56
+ export const exchangeActivityInput = z.object({
57
+ instanceId: z.string().min(1),
58
+ contactIds: z.array(z.string().min(1)),
59
+ });
60
+ export const exchangeActivityOutput = z.custom((value) => typeof value === 'object' && value !== null);
47
61
  /** Stand-in surface for fake contexts and local runs; never touches the database. */
48
62
  export const exchangesMockService = {
49
63
  async last() {
@@ -52,11 +66,15 @@ export const exchangesMockService = {
52
66
  async emailThread() {
53
67
  return { thread: null };
54
68
  },
69
+ async activity() {
70
+ return EMPTY_CASE_ACTIVITY;
71
+ },
55
72
  };
56
73
  export const exchangesSurface = {
57
74
  methods: {
58
75
  last: { input: exchangeLastInput, output: exchangeLastOutput },
59
76
  emailThread: { input: exchangeEmailThreadInput, output: exchangeEmailThreadOutput },
77
+ activity: { input: exchangeActivityInput, output: exchangeActivityOutput },
60
78
  },
61
79
  mock: exchangesMockService,
62
80
  };
@@ -56,6 +56,30 @@ export declare const instanceCloseInput: z.ZodObject<{
56
56
  reason: z.ZodString;
57
57
  }, z.core.$strict>;
58
58
  export type InstanceCloseParams = z.infer<typeof instanceCloseInput>;
59
+ /**
60
+ * A close: the instance as it is now, whether it was closed already (then nothing changed: its reason
61
+ * stays the first close's), and the pending scheduled actions this close cancelled.
62
+ */
63
+ export declare const instanceCloseOutput: z.ZodObject<{
64
+ id: z.ZodString;
65
+ sequenceId: z.ZodString;
66
+ sequence: z.ZodString;
67
+ subjectRecordId: z.ZodString;
68
+ status: z.ZodEnum<{
69
+ active: "active";
70
+ closed: "closed";
71
+ }>;
72
+ closeReason: z.ZodNullable<z.ZodString>;
73
+ origin: z.ZodString;
74
+ variables: z.ZodRecord<z.ZodString, z.ZodUnknown>;
75
+ experiments: z.ZodRecord<z.ZodString, z.ZodString>;
76
+ createdAt: z.ZodString;
77
+ lastActivityAt: z.ZodString;
78
+ closedAt: z.ZodNullable<z.ZodString>;
79
+ alreadyClosed: z.ZodBoolean;
80
+ cancelledScheduledActionIds: z.ZodArray<z.ZodString>;
81
+ }, z.core.$strip>;
82
+ export type InstanceCloseResult = z.infer<typeof instanceCloseOutput>;
59
83
  export declare const instanceSetVariablesInput: z.ZodObject<{
60
84
  instanceId: z.ZodString;
61
85
  values: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -114,8 +138,11 @@ export type InstancesApi = {
114
138
  */
115
139
  start(input: InstanceStartParams): Promise<InstanceStartResult>;
116
140
  get(input: InstanceIdParams): Promise<InstanceSummary>;
117
- /** End the instance: its pending scheduled actions are cancelled and no Run follows. Final. */
118
- close(input: InstanceCloseParams): Promise<InstanceSummary>;
141
+ /**
142
+ * End the instance: its pending scheduled actions are cancelled and no Run follows. Final. An
143
+ * instance already closed is returned as it is (`alreadyClosed`). Shown on the case's timeline.
144
+ */
145
+ close(input: InstanceCloseParams): Promise<InstanceCloseResult>;
119
146
  /** Merge run variables by name (atomic per variable; checked against the sequence's declarations). */
120
147
  setVariables(input: InstanceSetVariablesParams): Promise<InstanceSummary>;
121
148
  /**
@@ -207,6 +234,8 @@ export declare const instancesSurface: {
207
234
  createdAt: z.ZodString;
208
235
  lastActivityAt: z.ZodString;
209
236
  closedAt: z.ZodNullable<z.ZodString>;
237
+ alreadyClosed: z.ZodBoolean;
238
+ cancelledScheduledActionIds: z.ZodArray<z.ZodString>;
210
239
  }, z.core.$strip>;
211
240
  };
212
241
  setVariables: {
@@ -39,6 +39,14 @@ export const instanceCloseInput = z.strictObject({
39
39
  /** completed | cancelled | a short text (at most 64 characters). */
40
40
  reason: z.string().min(1).max(64),
41
41
  });
42
+ /**
43
+ * A close: the instance as it is now, whether it was closed already (then nothing changed: its reason
44
+ * stays the first close's), and the pending scheduled actions this close cancelled.
45
+ */
46
+ export const instanceCloseOutput = instanceSummary.extend({
47
+ alreadyClosed: z.boolean(),
48
+ cancelledScheduledActionIds: z.array(z.string()),
49
+ });
42
50
  export const instanceSetVariablesInput = z.strictObject({
43
51
  instanceId: z.string().min(1),
44
52
  /** Variables to set, merged by name (null unsets one). */
@@ -52,8 +60,7 @@ export const instanceFindForContactInput = z.strictObject({
52
60
  export const instanceNotifyInput = z.strictObject({
53
61
  instanceId: z.string().min(1),
54
62
  /**
55
- * What happened, a short stable label (`payment.posted`), for the Run's trigger, its log and the
56
- * Agent's prompt. The facts go in the records first: the Orchestrator reads them when it runs.
63
+ * What happened, a short stable label (`payment.posted`), for the Run's trigger and its log. The facts go in the records first: the Orchestrator reads them when it runs.
57
64
  */
58
65
  reason: z.string().trim().min(1).max(64),
59
66
  /**
@@ -97,7 +104,14 @@ export const instancesMockService = {
97
104
  return { ...mockInstance, id: input.instanceId };
98
105
  },
99
106
  async close(input) {
100
- return { ...mockInstance, id: input.instanceId, status: 'closed', closeReason: input.reason };
107
+ return {
108
+ ...mockInstance,
109
+ id: input.instanceId,
110
+ status: 'closed',
111
+ closeReason: input.reason,
112
+ alreadyClosed: false,
113
+ cancelledScheduledActionIds: [],
114
+ };
101
115
  },
102
116
  async setVariables(input) {
103
117
  return { ...mockInstance, id: input.instanceId, variables: input.values };
@@ -113,7 +127,7 @@ export const instancesSurface = {
113
127
  methods: {
114
128
  start: { input: instanceStartInput, output: instanceStartOutput },
115
129
  get: { input: instanceIdInput, output: instanceSummary },
116
- close: { input: instanceCloseInput, output: instanceSummary },
130
+ close: { input: instanceCloseInput, output: instanceCloseOutput },
117
131
  setVariables: { input: instanceSetVariablesInput, output: instanceSummary },
118
132
  findForContact: { input: instanceFindForContactInput, output: instanceListOutput },
119
133
  notify: { input: instanceNotifyInput, output: instanceNotifyOutput },
@@ -264,6 +264,20 @@ export declare const platformSurfaces: {
264
264
  occurredAt: import("zod").ZodString;
265
265
  }, import("zod/v4/core").$strip>>;
266
266
  };
267
+ send: {
268
+ input: import("zod").ZodObject<{
269
+ to: import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodObject<{
270
+ address: import("zod").ZodString;
271
+ }, import("zod/v4/core").$strict>]>;
272
+ body: import("zod").ZodString;
273
+ subject: import("zod").ZodOptional<import("zod").ZodString>;
274
+ instanceId: import("zod").ZodOptional<import("zod").ZodString>;
275
+ from: import("zod").ZodOptional<import("zod").ZodString>;
276
+ }, import("zod/v4/core").$strict>;
277
+ output: import("zod").ZodObject<{
278
+ exchangeId: import("zod").ZodString;
279
+ }, import("zod/v4/core").$strip>;
280
+ };
267
281
  };
268
282
  mock: import("./email-message.js").EmailHistoryApi;
269
283
  };
@@ -275,6 +289,7 @@ export declare const platformSurfaces: {
275
289
  kind: import("zod").ZodEnum<{
276
290
  email: "email";
277
291
  phone: "phone";
292
+ sip: "sip";
278
293
  }>;
279
294
  value: import("zod").ZodString;
280
295
  }, import("zod/v4/core").$strip>;
@@ -304,6 +319,7 @@ export declare const platformSurfaces: {
304
319
  kind: import("zod").ZodEnum<{
305
320
  email: "email";
306
321
  phone: "phone";
322
+ sip: "sip";
307
323
  }>;
308
324
  value: import("zod").ZodString;
309
325
  }, import("zod/v4/core").$strip>;
@@ -317,6 +333,13 @@ export declare const platformSurfaces: {
317
333
  }, import("zod/v4/core").$strip>>;
318
334
  }, import("zod/v4/core").$strip>;
319
335
  };
336
+ activity: {
337
+ input: import("zod").ZodObject<{
338
+ instanceId: import("zod").ZodString;
339
+ contactIds: import("zod").ZodArray<import("zod").ZodString>;
340
+ }, import("zod/v4/core").$strip>;
341
+ output: import("zod").ZodCustom<import("../case-orchestrator/types.js").CaseActivity, import("../case-orchestrator/types.js").CaseActivity>;
342
+ };
320
343
  };
321
344
  mock: import("./exchanges.js").ExchangesApi;
322
345
  };
@@ -393,6 +416,8 @@ export declare const platformSurfaces: {
393
416
  createdAt: import("zod").ZodString;
394
417
  lastActivityAt: import("zod").ZodString;
395
418
  closedAt: import("zod").ZodNullable<import("zod").ZodString>;
419
+ alreadyClosed: import("zod").ZodBoolean;
420
+ cancelledScheduledActionIds: import("zod").ZodArray<import("zod").ZodString>;
396
421
  }, import("zod/v4/core").$strip>;
397
422
  };
398
423
  setVariables: {
@@ -560,6 +585,16 @@ export declare const platformSurfaces: {
560
585
  occurredAt: import("zod").ZodString;
561
586
  }, import("zod/v4/core").$strip>>;
562
587
  };
588
+ send: {
589
+ input: import("zod").ZodObject<{
590
+ to: import("zod").ZodString;
591
+ body: import("zod").ZodString;
592
+ instanceId: import("zod").ZodOptional<import("zod").ZodString>;
593
+ }, import("zod/v4/core").$strip>;
594
+ output: import("zod").ZodObject<{
595
+ exchangeId: import("zod").ZodString;
596
+ }, import("zod/v4/core").$strip>;
597
+ };
563
598
  };
564
599
  mock: import("./sms.js").SmsApi;
565
600
  };
@@ -79,10 +79,30 @@ export declare const smsGetOutput: z.ZodNullable<z.ZodObject<{
79
79
  errorCode: z.ZodNullable<z.ZodString>;
80
80
  occurredAt: z.ZodString;
81
81
  }, z.core.$strip>>;
82
+ /**
83
+ * A text sent now (32), from any entry (64 §15): to a contact (its row id, not a number: the platform checks
84
+ * their opt-outs and finds their number), from the number of the call the run is on, else the one they are
85
+ * texted from. Stored with the run, then sent. The case it is about: `instanceId` when given (one of this
86
+ * environment's, else refused: `unknown_instance`), else the case the run is on; the case's Orchestrator
87
+ * hears `sms.sent`. With neither it is on no case: in the contact's history only (49), nobody told. Pause
88
+ * and contact hours are not checked: sending is company code's call.
89
+ */
90
+ export declare const smsSendInput: z.ZodObject<{
91
+ to: z.ZodString;
92
+ body: z.ZodString;
93
+ instanceId: z.ZodOptional<z.ZodString>;
94
+ }, z.core.$strip>;
95
+ export type SmsSendParams = z.infer<typeof smsSendInput>;
96
+ /** The exchange the text was recorded as (`sms.sent` on the case's timeline). */
97
+ export declare const smsSendOutput: z.ZodObject<{
98
+ exchangeId: z.ZodString;
99
+ }, z.core.$strip>;
100
+ export type SmsSendResult = z.infer<typeof smsSendOutput>;
82
101
  /** Platform SMS capability, reached from scripts as `ctx.api.sms`. */
83
102
  export type SmsApi = {
84
103
  list(input: SmsListParams): Promise<SmsListResult>;
85
104
  get(id: string): Promise<SmsRecord | null>;
105
+ send(input: SmsSendParams): Promise<SmsSendResult>;
86
106
  };
87
107
  export declare const smsMockService: SmsApi;
88
108
  export declare const smsSurface: {
@@ -141,6 +161,16 @@ export declare const smsSurface: {
141
161
  occurredAt: z.ZodString;
142
162
  }, z.core.$strip>>;
143
163
  };
164
+ send: {
165
+ input: z.ZodObject<{
166
+ to: z.ZodString;
167
+ body: z.ZodString;
168
+ instanceId: z.ZodOptional<z.ZodString>;
169
+ }, z.core.$strip>;
170
+ output: z.ZodObject<{
171
+ exchangeId: z.ZodString;
172
+ }, z.core.$strip>;
173
+ };
144
174
  };
145
175
  mock: SmsApi;
146
176
  };
@@ -39,6 +39,22 @@ export const smsListOutput = z.object({
39
39
  });
40
40
  export const smsGetInput = z.string().min(1);
41
41
  export const smsGetOutput = smsRecord.nullable();
42
+ /**
43
+ * A text sent now (32), from any entry (64 §15): to a contact (its row id, not a number: the platform checks
44
+ * their opt-outs and finds their number), from the number of the call the run is on, else the one they are
45
+ * texted from. Stored with the run, then sent. The case it is about: `instanceId` when given (one of this
46
+ * environment's, else refused: `unknown_instance`), else the case the run is on; the case's Orchestrator
47
+ * hears `sms.sent`. With neither it is on no case: in the contact's history only (49), nobody told. Pause
48
+ * and contact hours are not checked: sending is company code's call.
49
+ */
50
+ export const smsSendInput = z.object({
51
+ to: z.string().min(1),
52
+ body: z.string().min(1),
53
+ /** The case the text is about, any of this environment's; absent: the run's own case, if any. */
54
+ instanceId: z.string().min(1).optional(),
55
+ });
56
+ /** The exchange the text was recorded as (`sms.sent` on the case's timeline). */
57
+ export const smsSendOutput = z.object({ exchangeId: z.string() });
42
58
  export const smsMockService = {
43
59
  async list(input) {
44
60
  return { sms: [], offset: input.offset, limit: input.limit };
@@ -46,11 +62,15 @@ export const smsMockService = {
46
62
  async get() {
47
63
  return null;
48
64
  },
65
+ async send() {
66
+ return { exchangeId: 'mock-sms' };
67
+ },
49
68
  };
50
69
  export const smsSurface = {
51
70
  methods: {
52
71
  list: { input: smsListInput, output: smsListOutput },
53
72
  get: { input: smsGetInput, output: smsGetOutput },
73
+ send: { input: smsSendInput, output: smsSendOutput },
54
74
  },
55
75
  mock: smsMockService,
56
76
  };
@@ -1,8 +1,10 @@
1
+ import type { CaseOrchestratorTools } from '../case-orchestrator/types.js';
1
2
  import type { PlatformApis } from './platform-registry.js';
2
3
  import type { Db } from '../page/define.js';
3
4
  import type { EmailApi } from './email.js';
4
5
  import type { EnvApi } from './env.js';
5
6
  import type { IntegrationAccountFields } from './account-fields.js';
7
+ import type { TimeParts } from '../page/time-format.js';
6
8
  export type { IntegrationAccountFields, IntegrationTarget } from './account-fields.js';
7
9
  /**
8
10
  * Lifecycle state of a slot field (`01-slot-design §2`):
@@ -19,7 +21,7 @@ export type Logger = {
19
21
  warn: (message: string, extra?: Record<string, unknown>) => void;
20
22
  error: (message: string, extra?: Record<string, unknown>) => void;
21
23
  };
22
- export type { EmailApi, EmailAttachment, EmailGetAttachmentInput, EmailGetAttachmentOutput, EmailGetMessageInput, EmailGetMessageOutput, EmailListMessagesInput, EmailListMessagesOutput, EmailProvider, EmailSendEmailInput, EmailSendEmailOutput, EmailService, } from './email.js';
24
+ export type { EmailApi, EmailAttachment, EmailGetAttachmentInput, EmailGetAttachmentOutput, EmailGetMessageInput, EmailGetMessageOutput, EmailListMessagesInput, EmailListMessagesOutput, EmailProvider, EmailProviderService, EmailSendEmailInput, EmailSendEmailOutput, EmailService, } from './email.js';
23
25
  export type { EnvApi, EnvService } from './env.js';
24
26
  export type { ContactApi, ContactListParams, ContactListResult, ContactSummary } from './contact.js';
25
27
  /**
@@ -38,6 +40,11 @@ export type IntegrationSurfaceMeta = IntegrationAccountFields & {
38
40
  surfaceKey: IntegrationSurfaceKey;
39
41
  methods: string[];
40
42
  };
43
+ /** What does not hold while an environment is tested (68 §6.2). */
44
+ export type ContactHoursIgnore = Readonly<{
45
+ contactHours: boolean;
46
+ contactSchedule: boolean;
47
+ }>;
41
48
  /** Context injected into custom and system functions. */
42
49
  export type SystemContext = {
43
50
  time: Readonly<{
@@ -47,6 +54,12 @@ export type SystemContext = {
47
54
  timezone: string;
48
55
  /** Current calendar date (`YYYY-MM-DD`) in `time.timezone`, i.e. the UTC date. */
49
56
  today: string;
57
+ /**
58
+ * What does not hold in this environment while it is tested (68 §6.2, set on the environment, never in
59
+ * prod): `contactHours`, the company's contact hours; `contactSchedule`, contacts' own schedules.
60
+ * `nextContactTime(hours, ctx.time, zone)` and `withinContactHours(…, ctx.time.ignore)` follow it.
61
+ */
62
+ ignore: ContactHoursIgnore;
50
63
  /**
51
64
  * `at` as people read it, in `timeZone` (25 §11): "Tue, Nov 3, 3:00 PM EST" (`style` `'date'` or
52
65
  * `'time'` for one part). A contact's zone is `contactTimezone(…)`.
@@ -57,6 +70,17 @@ export type SystemContext = {
57
70
  }): string;
58
71
  /** The calendar day (`YYYY-MM-DD`) at `at` in `timeZone` (25 §11), to compare days or key a rule by date. */
59
72
  day(at: string | number, timeZone: string): string;
73
+ /**
74
+ * The exact moment (ISO 8601, UTC) a clock in `timeZone` shows `date` (`YYYY-MM-DD`) at `time` (`HH:mm`)
75
+ * (74 §4.7): "the day before delivery at 17:00 her time" is `at(dayBefore, '17:00', zone)`. A time the
76
+ * clocks skip is the moment just after the gap; one they show twice, the first.
77
+ */
78
+ at(date: string, time: string, timeZone: string): string;
79
+ /**
80
+ * `at` on a clock in `timeZone` (74 §4.7): its date, `HH:mm`, hour, minute, ISO weekday (1 Monday … 7
81
+ * Sunday) and offset, to decide "is the office open now" without parsing `format`'s text.
82
+ */
83
+ parts(at: string | number, timeZone: string): TimeParts;
60
84
  }>;
61
85
  meta: Readonly<{
62
86
  companyId: string;
@@ -95,9 +119,13 @@ export type SystemContext = {
95
119
  * write entry, each call its own transaction. Any row of the company and environment.
96
120
  */
97
121
  db: Db;
122
+ /** The platform's tools (38 §2.7): schedule, reschedule, cancel, hand over, read exchanges, on an instance named in each call. */
123
+ tools: CaseOrchestratorTools;
98
124
  };
99
125
  };
100
126
  export type MakeCtxOverrides = {
127
+ /** `ctx.time.ignore`: what does not hold while the environment is tested (68 §6.2); nothing when left out. */
128
+ ignore?: ContactHoursIgnore;
101
129
  today?: string;
102
130
  timezone?: string;
103
131
  now?: number;
@@ -6,13 +6,67 @@ export type Direction = 'inbound' | 'outbound';
6
6
  export declare const CHANNELS: readonly ['call', 'sms', 'email'];
7
7
  export type Channel = (typeof CHANNELS)[number];
8
8
  /**
9
- * The languages the platform speaks: the values of the contact's `language` field. Each needs a voice
10
- * (the default voice profile's settings for it) and the platform's fixed lines in it.
9
+ * The languages a contact can have (`contact.language`, 48 §3) and texts and emails tag their replies with
10
+ * (48 §5.2): BCP-47 base tags. Texts and emails need no voice, so they are not limited to what calls can
11
+ * speak (75 §3); a contact who writes in Chinese keeps `zh`, and a call with them opens in English.
11
12
  */
12
- export declare const SPOKEN_LANGUAGES: readonly ['english', 'spanish'];
13
- /** A spoken language as the contact's `language` field holds it (`english`, `spanish`). */
13
+ export declare const CONTACT_LANGUAGES: readonly ['en', 'fr', 'de', 'es', 'pt', 'zh', 'ja', 'hi', 'it', 'ko', 'nl', 'pl', 'ru', 'sv', 'tr', 'tl', 'bg', 'ro', 'ar', 'cs', 'el', 'fi', 'hr', 'ms', 'sk', 'da', 'ta', 'uk', 'hu', 'no', 'vi', 'bn', 'th', 'he', 'ka', 'id', 'te', 'gu', 'kn', 'ml', 'mr', 'pa'];
14
+ /**
15
+ * The languages calls can speak (48 §4, narrowed by 75 §3): the platform language table's tags, the ones
16
+ * Deepgram Flux (`flux-general-multi`) turns on, all spoken by Cartesia. Each has a native default voice,
17
+ * the platform's fixed lines and STOP words (services' language table). A caller speaking another language
18
+ * is answered in the call's language, told once it cannot be spoken (48 §1 item 6).
19
+ */
20
+ export declare const SPOKEN_LANGUAGES: readonly ['en', 'es', 'fr', 'de', 'hi', 'ru', 'pt', 'ja', 'it', 'nl'];
21
+ /** A language as the platform stores it: a canonical BCP-47 tag (`en`, `es`, `pt-BR`). */
14
22
  export type SpokenLanguage = string;
23
+ /** A language `contact.language` holds, texts and emails are written in: a canonical tag, one of `CONTACT_LANGUAGES`. */
24
+ export type ContactLanguage = string;
25
+ /** One of the table's tags, as a type: a key of `Spoken`. */
26
+ export type SpokenTag = (typeof SPOKEN_LANGUAGES)[number];
27
+ /**
28
+ * A fixed line the platform says word for word to the customer, in each language the page wrote (66 §2):
29
+ * `{ en: 'One moment.', es: 'Un momento.' }`. At least one language; `en` is not required.
30
+ */
31
+ export type Spoken = {
32
+ [K in SpokenTag]: {
33
+ [L in K]: string;
34
+ } & Partial<Record<SpokenTag, string>>;
35
+ }[SpokenTag];
36
+ /**
37
+ * `value` checked as a `Spoken` (66 §2): an object, at least one language, every key a table tag, every
38
+ * text not empty. Copied, in the order written. No `Intl` (the page sandbox has none).
39
+ */
40
+ export declare function checkSpoken(value: unknown, at: string): Spoken;
41
+ /** The text a `Spoken` falls back to (66 §3): `en` when written, else the first language written. */
42
+ export declare function fallbackSpoken(spoken: Spoken): {
43
+ text: string;
44
+ language: SpokenTag;
45
+ };
46
+ /**
47
+ * The line to say on a call in `language` (66 §3): the same tag, else the same base language
48
+ * (`pt-BR` → `pt`), else `en`, else the first written. `missing`: the language it fell back from, to tell
49
+ * the company.
50
+ */
51
+ export declare function pickSpoken(spoken: Spoken, language: string | null | undefined): {
52
+ text: string;
53
+ missing: string | null;
54
+ };
55
+ /** `value` as a canonical BCP-47 tag (`pt-br` → `pt-BR`), or null when it is not one. */
56
+ export declare function canonicalLanguage(value: unknown): string | null;
57
+ /** Whether `value` is one of the table's tags as stored (a language calls can speak). */
15
58
  export declare function isSpokenLanguage(value: unknown): value is SpokenLanguage;
59
+ /** Whether `value` is a language `contact.language` can hold, as stored (texts and emails: any of them). */
60
+ export declare function isContactLanguage(value: unknown): value is ContactLanguage;
61
+ /**
62
+ * The table's language a tag resolves to (48 §2): the same tag, else the first with its base language
63
+ * (`es-MX` → `es`), unless that entry is not the fallback for it (`zh-HK`). Null: calls cannot speak it.
64
+ */
65
+ export declare function matchSpokenLanguage(value: unknown): SpokenLanguage | null;
66
+ /** The contact language a tag resolves to, as {@link matchSpokenLanguage} (`zh-CN` → `zh`). Null: none. */
67
+ export declare function matchContactLanguage(value: unknown): ContactLanguage | null;
68
+ /** A language's name in English, for prompts (`zh` → `Chinese`); the tag itself when it has none. */
69
+ export declare function languageName(tag: string): string;
16
70
  /**
17
71
  * The scheduled action that started an outbound conversation (a scheduled call or message), fixed for
18
72
  * the session. An agreed follow-up has `agreedInExchangeId`; `note` says why it happens