@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,16 +1,19 @@
1
+ import { ROW_ID_FIELD } from './schema.js';
1
2
  function formatValues(values) {
2
3
  return values.join(', ');
3
4
  }
4
5
  /**
5
6
  * Type changes that only widen: every stored value of `before` is a valid value of `after`
6
- * (18-record-search-index §5, 27 §2.3): a short value as a long one; an option or a time of day as
7
- * a short value.
7
+ * (18-record-search-index §5, 27 §2.3): an option or a time of day as a short value. Nothing becomes
8
+ * `text`: a `text` field is not in the field index, so the change would drop every stored entry of the
9
+ * field at once, in the release's go-live (2026-11-10).
8
10
  */
9
- const WIDENINGS = new Set(['string>text', 'select>string', 'select>text', 'time>string', 'time>text']);
10
- function normalFieldIssues(path, before, after) {
11
+ const WIDENINGS = new Set(['select>string', 'time>string']);
12
+ const NOT_TO_TEXT = 'a released field does not become text: add a text field and mark this one deprecated';
13
+ function fieldIssues(path, before, after) {
11
14
  const issues = [];
12
15
  if (before.dataType !== after.dataType && !WIDENINGS.has(`${before.dataType}>${after.dataType}`)) {
13
- issues.push(`field '${path}' dataType: ${before.dataType} → ${after.dataType}`);
16
+ issues.push(`field '${path}' dataType: ${before.dataType} → ${after.dataType}${after.dataType === 'text' ? ` (${NOT_TO_TEXT})` : ''}`);
14
17
  }
15
18
  // More options only widen; a dropped one may be stored.
16
19
  if (before.dataType === after.dataType && before.options && after.options) {
@@ -54,37 +57,34 @@ function refIssues(path, before, after) {
54
57
  }
55
58
  return [];
56
59
  }
57
- function fieldIssues(path, before, after) {
58
- return normalFieldIssues(path, before, after);
59
- }
60
- /** A session field has no ref: the rest of a company field's rules. */
61
- function sessionFieldIssues(path, before, after) {
62
- return normalFieldIssues(path, before, after);
63
- }
64
60
  /**
65
61
  * Why `after`'s company schema cannot replace `before`'s without breaking slot data stored under
66
- * it; empty for an additive (01-slot-db §2.3) evolution. One pass covers the whole repo: sequence
67
- * overlays only change usage. The session fields (`schema/session.ts`) follow the same rules, since
68
- * `Session.data` keeps their values (11-remove-sequence-schema §3.1).
62
+ * it; empty for an additive (01-slot-db §2.3) evolution. Both are a build's compiled schema
63
+ * (`CompanyPart.schema`): one for the whole repo, sequences have none of their own. The session
64
+ * table (`schema/session.ts`) follows the same rules, since `Session.data` keeps its values
65
+ * (11-remove-sequence-schema §3.1); a session field has no ref, so the ref rules never apply to it.
69
66
  *
70
67
  * Compatible: new tables (with their parent), fields (lookups included), more options, a widened
71
- * type (`string` → `text`, `select` / `time` → `string`), and presentation changes (label,
68
+ * type (`select` / `time` → `string`), and presentation changes (label,
72
69
  * description, extraction, deprecated); a new field may be `unique`. Incompatible: removing a table or
73
- * field (mark it `deprecated` instead); any other change of a field's dataType, `unique` added to or
70
+ * field (mark it `deprecated` instead); any other change of a field's dataType (to `text` included), `unique` added to or
74
71
  * dropped from a field (18-record-search-index §4.5), any ref change (added, removed, retargeted, parent ↔ lookup), a parent added to a
75
72
  * table `before` has (its stored rows have no parent edge, 13-data-model-v1 §22.5), a removed option.
76
73
  */
77
- export function companyMetadataCompatibilityIssues(before, after) {
74
+ export function companySchemaCompatibilityIssues(before, after) {
78
75
  const issues = [];
79
- for (const [tableName, beforeTable] of Object.entries(before.tables)) {
80
- const afterTable = after.tables[tableName];
76
+ for (const [tableName, beforeTable] of Object.entries(before)) {
77
+ const afterTable = Object.hasOwn(after, tableName) ? after[tableName] : undefined;
81
78
  if (!afterTable) {
82
79
  issues.push(`table '${tableName}' was removed`);
83
80
  continue;
84
81
  }
85
82
  for (const [fieldName, beforeField] of Object.entries(beforeTable.fields)) {
83
+ // The row id is the platform's, the same on every table.
84
+ if (fieldName === ROW_ID_FIELD)
85
+ continue;
86
86
  const path = `${tableName}.${fieldName}`;
87
- const afterField = afterTable.fields[fieldName];
87
+ const afterField = Object.hasOwn(afterTable.fields, fieldName) ? afterTable.fields[fieldName] : undefined;
88
88
  if (!afterField) {
89
89
  const instead = beforeField.ref?.kind === 'parent' ? PARENT_FIXED : 'mark it deprecated instead';
90
90
  issues.push(`field '${path}' was removed (${instead})`);
@@ -93,20 +93,11 @@ export function companyMetadataCompatibilityIssues(before, after) {
93
93
  issues.push(...fieldIssues(path, beforeField, afterField));
94
94
  }
95
95
  for (const [fieldName, afterField] of Object.entries(afterTable.fields)) {
96
- if (fieldName in beforeTable.fields || afterField.ref?.kind !== 'parent')
96
+ if (Object.hasOwn(beforeTable.fields, fieldName) || afterField.ref?.kind !== 'parent')
97
97
  continue;
98
98
  issues.push(`table '${tableName}' gained a parent '${fieldName}': its stored rows have none (${PARENT_FIXED})`);
99
99
  }
100
100
  }
101
- for (const [fieldName, beforeField] of Object.entries(before.session.fields)) {
102
- const path = `session.${fieldName}`;
103
- const afterField = after.session.fields[fieldName];
104
- if (!afterField) {
105
- issues.push(`field '${path}' was removed (mark it deprecated instead)`);
106
- continue;
107
- }
108
- issues.push(...sessionFieldIssues(path, beforeField, afterField));
109
- }
110
101
  return issues;
111
102
  }
112
103
  //# sourceMappingURL=schema-compat.js.map
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
2
  /**
3
- * A field's type (18-record-search-index §4.2): `string` is a short value (at most 255 characters,
4
- * `LIMITS.stringChars`), `text` a long one (notes, descriptions; not indexed); `phone` is stored in
3
+ * A field's type (18-record-search-index §4.2): `string` is a value to find and sort by, `text` one
4
+ * only kept (notes, descriptions; not indexed); a `string` holds up to `LIMITS.stringBytes` (its index
5
+ * entries keep it whole), a `text` up to `LIMITS.textBytes` (34-string-length); `phone` is stored in
5
6
  * E.164 and `email` lower-cased, both checked on write. `select` is one of the field's `options`,
6
7
  * `multi_select` a list of them, `time` a time of day `HH:mm` (27-field-types-and-history).
7
8
  */
@@ -374,62 +375,5 @@ export declare const sessionSchemaSchema: z.ZodObject<{
374
375
  deprecated: z.ZodOptional<z.ZodBoolean>;
375
376
  }, z.core.$strict>>;
376
377
  }, z.core.$strict>;
377
- export declare const compiledCompanyMetadataSchema: z.ZodObject<{
378
- tables: z.ZodRecord<z.ZodString, z.ZodObject<{
379
- label: z.ZodString;
380
- description: z.ZodString;
381
- fields: z.ZodRecord<z.ZodString, z.ZodObject<{
382
- label: z.ZodString;
383
- dataType: z.ZodEnum<{
384
- boolean: "boolean";
385
- contact_schedule: "contact_schedule";
386
- date: "date";
387
- datetime: "datetime";
388
- email: "email";
389
- multi_select: "multi_select";
390
- number: "number";
391
- phone: "phone";
392
- select: "select";
393
- string: "string";
394
- text: "text";
395
- time: "time";
396
- }>;
397
- extraction: z.ZodString;
398
- options: z.ZodOptional<z.ZodArray<z.ZodString>>;
399
- ref: z.ZodOptional<z.ZodObject<{
400
- table: z.ZodString;
401
- kind: z.ZodEnum<{
402
- lookup: "lookup";
403
- parent: "parent";
404
- }>;
405
- relatedName: z.ZodOptional<z.ZodString>;
406
- }, z.core.$strict>>;
407
- unique: z.ZodOptional<z.ZodLiteral<true>>;
408
- deprecated: z.ZodOptional<z.ZodBoolean>;
409
- }, z.core.$strict>>;
410
- }, z.core.$strict>>;
411
- session: z.ZodObject<{
412
- fields: z.ZodRecord<z.ZodString, z.ZodObject<{
413
- label: z.ZodString;
414
- extraction: z.ZodString;
415
- options: z.ZodOptional<z.ZodArray<z.ZodString>>;
416
- dataType: z.ZodEnum<{
417
- boolean: "boolean";
418
- date: "date";
419
- datetime: "datetime";
420
- email: "email";
421
- multi_select: "multi_select";
422
- number: "number";
423
- phone: "phone";
424
- select: "select";
425
- string: "string";
426
- text: "text";
427
- time: "time";
428
- }>;
429
- deprecated: z.ZodOptional<z.ZodBoolean>;
430
- }, z.core.$strict>>;
431
- }, z.core.$strict>;
432
- }, z.core.$strict>;
433
- export type CompiledCompanyMetadata = z.infer<typeof compiledCompanyMetadataSchema>;
434
378
  export declare function isCompanySchema(value: unknown): value is CompanySchema;
435
379
  //# sourceMappingURL=schema.d.ts.map
@@ -164,21 +164,6 @@ export const sessionFieldDefSchema = normalFieldCoreSchema
164
164
  export const sessionSchemaSchema = z
165
165
  .object({ fields: z.record(z.string().min(1), sessionFieldDefSchema) })
166
166
  .strict();
167
- export const compiledCompanyMetadataSchema = z
168
- .object({
169
- /**
170
- * The whole company schema of the build: every table and field, without sequence overlays.
171
- * Prod keeps it additive-only (01-slot-db §2.3).
172
- */
173
- tables: companySchemaSchema,
174
- /** The session fields (`schema/session.ts`), additive-only like the tables. */
175
- session: sessionSchemaSchema,
176
- })
177
- .strict()
178
- .refine((metadata) => !!metadata.tables.contact, {
179
- message: 'company metadata must define the contact table',
180
- path: ['tables', 'contact'],
181
- });
182
167
  export function isCompanySchema(value) {
183
168
  return companySchemaSchema.safeParse(value).success;
184
169
  }
@@ -1,14 +1,10 @@
1
1
  import type { ContactSchedule, DataType, TableRef } from './schema.js';
2
2
  import type { FieldState } from '../context/types.js';
3
3
  export type UpdatedBy = 'slot-filling' | 'function' | 'human' | 'import' | 'platform';
4
- /** Prior generation archived into FieldValue.history (no reason — 01-slot-db §4.1). */
5
- export type FieldHistoryEntry = {
6
- value: SlotValue;
7
- state: FieldState;
8
- at: number;
9
- by: UpdatedBy;
10
- };
11
- /** In-memory field envelope (01-slot-design §2 + 01-slot-db §4 history). */
4
+ /**
5
+ * In-memory field envelope (01-slot-design §2): the current value only. Earlier values are in the
6
+ * change log (`SlotWriteLog`, 36 §3).
7
+ */
12
8
  export type FieldValue = {
13
9
  /**
14
10
  * Dialogue evidence quote or write justification (`null` when the writer gave none: plain
@@ -25,8 +21,6 @@ export type FieldValue = {
25
21
  /** Epoch milliseconds of the last value/state change. */
26
22
  updatedAt: number;
27
23
  updatedBy: UpdatedBy;
28
- /** Past generations ascending; excludes current. Appended only on C5 change. */
29
- history: FieldHistoryEntry[];
30
24
  };
31
25
  export type SlotValue = string | number | boolean | string[] | ContactSchedule | null;
32
26
  export type RuntimeFieldDef = {
@@ -20,6 +20,8 @@ export declare const EMAIL_VALUE_PATTERN: string;
20
20
  export declare function stringChars(value: string): number;
21
21
  /** UTF-8 bytes of a string. */
22
22
  export declare function utf8Bytes(value: string): number;
23
+ /** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
24
+ export declare function indexedBytes(value: string): number;
23
25
  /** What a value of `dataType` must look like, for messages. */
24
26
  export declare function dataTypeFormat(dataType: DataType): string;
25
27
  export declare function isValidDataTypeValue(dataType: DataType, value: unknown): boolean;
@@ -33,11 +33,15 @@ export function stringChars(value) {
33
33
  export function utf8Bytes(value) {
34
34
  return utf8.encode(value).length;
35
35
  }
36
+ /** UTF-8 bytes a `string` takes in its indexes: as written, or lower-cased if that is longer. */
37
+ export function indexedBytes(value) {
38
+ return Math.max(utf8Bytes(value), utf8Bytes(value.toLowerCase()));
39
+ }
36
40
  /** What a value of `dataType` must look like, for messages. */
37
41
  export function dataTypeFormat(dataType) {
38
42
  switch (dataType) {
39
43
  case 'string':
40
- return `a string of at most ${LIMITS.stringChars} characters (use text for longer)`;
44
+ return `a string of at most ${LIMITS.stringBytes} bytes (UTF-8; a longer value is a text field)`;
41
45
  case 'text':
42
46
  return `a string of at most ${LIMITS.textBytes} bytes`;
43
47
  case 'phone':
@@ -63,7 +67,7 @@ export function isValidDataTypeValue(dataType, value) {
63
67
  return true;
64
68
  switch (dataType) {
65
69
  case 'string':
66
- return typeof value === 'string' && stringChars(value) <= LIMITS.stringChars;
70
+ return typeof value === 'string' && indexedBytes(value) <= LIMITS.stringBytes;
67
71
  case 'text':
68
72
  return typeof value === 'string' && utf8Bytes(value) <= LIMITS.textBytes;
69
73
  case 'phone':
@@ -1,6 +1,5 @@
1
1
  import type { ActionDataSlice } from '../fn-context/types.js';
2
- import type { CompanyBuild } from '../builder/types.js';
3
- import type { CompiledCompanyMetadata } from '../core/slot/schema.js';
2
+ import type { CompanyBuild, SourceMaps } from '../builder/types.js';
4
3
  import type { ComputeInvocation } from '../compute-host/compute-host.js';
5
4
  /**
6
5
  * Serve takes the whole environment (22-sequence-as-business-unit §6): while a session holds it, every
@@ -42,6 +41,14 @@ export declare const OVERLAY_REPLACED_CLOSE_CODE = 4000;
42
41
  * Informational only: the session keeps serving. Sent e.g. when the pushed company schema is not
43
42
  * backward compatible with this environment's or prod's live release.
44
43
  */
44
+ /**
45
+ * The push of `generation` is served: registered, so every api instance runs it from now on. Sent after
46
+ * each push; a client may wait for it before it calls anything that should run the pushed code.
47
+ */
48
+ export type OverlayOkMessage = {
49
+ type: 'overlay.ok';
50
+ generation: number;
51
+ };
45
52
  export type OverlayNoticeMessage = {
46
53
  type: 'notice';
47
54
  message: string;
@@ -51,9 +58,13 @@ export type OverlayNoticeMessage = {
51
58
  export type OverlayPushMessage = {
52
59
  type: 'overlay';
53
60
  generation: number;
61
+ /** `build.company.schema` is compiled from the local `schema/`; the backend uses it while serving. */
54
62
  build: CompanyBuild;
55
- /** Company metadata compiled from the local `schema/`; the backend uses it while serving. */
56
- companyMetadata: CompiledCompanyMetadata;
63
+ /**
64
+ * Source maps of the code serve hands the backend to run (its page scripts), by `functionKey`: a page's
65
+ * failure is shown on the repository's own files with them.
66
+ */
67
+ sourceMaps?: SourceMaps;
57
68
  };
58
69
  export type OverlayExecuteMessage = {
59
70
  type: 'execute';
@@ -68,6 +79,13 @@ export type OverlayExecuteMessage = {
68
79
  logRequestId?: string;
69
80
  /** Logger tags inherited from the backend execution context. */
70
81
  logTags?: string[];
82
+ /**
83
+ * Epoch ms after which the backend no longer waits for this request: serve does not start it then, so
84
+ * a request reported as failed never runs later. Set once by the process that started the call, by the
85
+ * backend's clock; serve compares it with its own, which assumes the two agree (NTP) to well within the
86
+ * execute timeout.
87
+ */
88
+ deadline: number;
71
89
  };
72
90
  export type OverlayExecuteResultMessage = {
73
91
  type: 'execute.result';
@@ -79,9 +97,24 @@ export type OverlayExecuteResultMessage = {
79
97
  requestId: string;
80
98
  ok: false;
81
99
  error: string;
100
+ /**
101
+ * Where it failed: the error's first line and the frames of the repository's own files, by their
102
+ * path from its root (the company's logs show it). Absent when the error had no stack.
103
+ */
104
+ stack?: string;
105
+ /**
106
+ * Nothing of the company's ran (expired before it started, an unknown sequence): the platform's
107
+ * failure, not the company's code's (67 §4.1).
108
+ */
109
+ notStarted?: true;
110
+ /**
111
+ * The code failed on a `PlatformUnavailableError` it did not catch (74 §3.2): the platform's failure,
112
+ * not the company's code's.
113
+ */
114
+ platform?: true;
82
115
  };
83
116
  export type OverlayClientMessage = OverlayAuthMessage | OverlayPushMessage | OverlayExecuteResultMessage;
84
- export type OverlayServerMessage = OverlayAuthOkMessage | OverlayAuthErrorMessage | OverlayReplacedMessage | OverlayExecuteMessage | OverlayNoticeMessage;
117
+ export type OverlayServerMessage = OverlayAuthOkMessage | OverlayAuthErrorMessage | OverlayReplacedMessage | OverlayExecuteMessage | OverlayNoticeMessage | OverlayOkMessage;
85
118
  export type OverlayMessage = OverlayClientMessage | OverlayServerMessage;
86
119
  export declare function encodeOverlayMessage(message: OverlayMessage): string;
87
120
  export declare function parseOverlayMessage(raw: string): OverlayMessage;
@@ -1,5 +1,7 @@
1
1
  import { bindLogMeta } from './log.js';
2
- import { dayIn, formatTime } from '../core/page/time-format.js';
2
+ import { dayIn, formatTime, timeAt, timeParts } from '../core/page/time-format.js';
3
+ /** A run in an environment that is not being tested (68 §6.2): every contact hour holds. */
4
+ const NOTHING_IGNORED = Object.freeze({ contactHours: false, contactSchedule: false });
3
5
  function resolveRunScope(data, options) {
4
6
  return {
5
7
  companyId: options.run?.companyId ?? data.meta.companyId,
@@ -7,9 +9,13 @@ function resolveRunScope(data, options) {
7
9
  entry: options.run?.entry ?? data.meta.entry,
8
10
  };
9
11
  }
12
+ /** What the call brought for the api, besides the context: the integrations the platform listed. */
13
+ function given(data) {
14
+ return data.surfaces ? { surfaces: data.surfaces } : {};
15
+ }
10
16
  function assembleContext(data, meta, api) {
11
17
  return {
12
- time: { ...data.time, format: formatTime, day: dayIn },
18
+ time: { ...data.time, ignore: data.time.ignore ?? NOTHING_IGNORED, format: formatTime, day: dayIn, at: timeAt, parts: timeParts },
13
19
  meta,
14
20
  config: data.config,
15
21
  api: { ...api, log: bindLogMeta(api.log, data.meta) },
@@ -20,12 +26,12 @@ function assembleContext(data, meta, api) {
20
26
  * Shared by local unit, remote-fc, and (later) Worker-side invoke.
21
27
  */
22
28
  export async function buildActionContext(data, host, options = {}) {
23
- const api = await host.buildApi(resolveRunScope(data, options));
29
+ const api = await host.buildApi(resolveRunScope(data, options), given(data));
24
30
  return assembleContext(data, data.meta, api);
25
31
  }
26
32
  /** Assemble the `orchestrator` ctx (without `params`), its api from the host. */
27
33
  export async function buildCaseOrchestratorContext(data, host, options = {}) {
28
- const api = await host.buildCaseOrchestratorApi(resolveRunScope(data, options));
34
+ const api = await host.buildCaseOrchestratorApi(resolveRunScope(data, options), given(data));
29
35
  return assembleContext(data, data.meta, api);
30
36
  }
31
37
  //# sourceMappingURL=build-context.js.map
@@ -14,6 +14,8 @@ export type FakeApiHostOptions = PlatformApiOverrides & {
14
14
  /** Every table, every method: rejects when called (`what` names it in the error). */
15
15
  /** A stand-in whose every call rejects, saying it is not faked. */
16
16
  export declare function unfaked<T extends object>(what: string): T;
17
+ /** `ctx.api.tools` for fake contexts: a tool left out rejects when called. */
18
+ export declare function fakeTools(overrides?: Partial<CaseOrchestratorTools>): CaseOrchestratorTools;
17
19
  /** In-process ApiHost for local unit tests (`makeCtx` uses this). */
18
20
  export declare function createFakeApiHost(options?: FakeApiHostOptions): ApiHost & CaseOrchestratorApiHost;
19
21
  //# sourceMappingURL=index.d.ts.map
@@ -12,7 +12,8 @@ export function unfaked(what) {
12
12
  }),
13
13
  });
14
14
  }
15
- function fakeTools(overrides = {}) {
15
+ /** `ctx.api.tools` for fake contexts: a tool left out rejects when called. */
16
+ export function fakeTools(overrides = {}) {
16
17
  const tools = CASE_ORCHESTRATOR_TOOL_NAMES.map((tool) => [
17
18
  tool,
18
19
  overrides[tool] ??
@@ -33,14 +34,15 @@ export function createFakeApiHost(options = {}) {
33
34
  integration,
34
35
  log: options.log ?? noopLog,
35
36
  db: options.db ?? unfaked('db'),
37
+ // Every function's (38 §2.7).
38
+ tools: fakeTools(options.tools),
36
39
  };
37
- const tools = fakeTools(options.tools);
38
40
  return {
39
41
  async buildApi() {
40
42
  return api;
41
43
  },
42
44
  async buildCaseOrchestratorApi() {
43
- return { ...api, tools };
45
+ return api;
44
46
  },
45
47
  };
46
48
  }
@@ -1,6 +1,3 @@
1
- /**
2
- * `invocation.params` for `case` / `noCase` functions: an object (empty when omitted).
3
- * The case (`c`: `{ subject, instanceId }`) is passed apart, not here.
4
- */
5
- export declare function resolveFnParams(params: unknown): object;
1
+ /** A function's `args` (38 §2.1): an object, `{}` when the caller gave none. */
2
+ export declare function resolveFnParams(args: unknown): object;
6
3
  //# sourceMappingURL=fn-params.d.ts.map
@@ -1,13 +1,10 @@
1
- /**
2
- * `invocation.params` for `case` / `noCase` functions: an object (empty when omitted).
3
- * The case (`c`: `{ subject, instanceId }`) is passed apart, not here.
4
- */
5
- export function resolveFnParams(params) {
6
- if (params == null)
1
+ /** A function's `args` (38 §2.1): an object, `{}` when the caller gave none. */
2
+ export function resolveFnParams(args) {
3
+ if (args == null)
7
4
  return {};
8
- if (typeof params !== 'object' || Array.isArray(params)) {
9
- throw new Error('function params must be an object');
5
+ if (typeof args !== 'object' || Array.isArray(args)) {
6
+ throw new Error('function args must be an object');
10
7
  }
11
- return params;
8
+ return args;
12
9
  }
13
10
  //# sourceMappingURL=fn-params.js.map
@@ -1,4 +1,4 @@
1
- export type { ActionContext, ActionDataSlice, ApiHost, CaseOrchestratorActionContext, CaseOrchestratorApiHost, CaseOrchestratorRunScope, RunClaims, RunScope, } from './types.js';
1
+ export type { ActionContext, ActionDataSlice, ApiGiven, ApiHost, CaseOrchestratorActionContext, CaseOrchestratorApiHost, CaseOrchestratorRunScope, RunClaims, RunScope, } from './types.js';
2
2
  export { buildActionContext, buildCaseOrchestratorContext, type BuildActionContextOptions, } from './build-context.js';
3
3
  export { asCaseOrchestratorRun } from './run-scope.js';
4
4
  export { resolveFnParams } from './fn-params.js';
@@ -1,14 +1,14 @@
1
1
  import { buildActionContext, buildCaseOrchestratorContext } from './build-context.js';
2
- import { createFakeApiHost, unfaked } from './fake/index.js';
2
+ import { createFakeApiHost, fakeTools, unfaked } from './fake/index.js';
3
3
  import { defaultPlatformApis, emptyIntegration } from './fake/empty-api.js';
4
4
  import { bindLogMeta, noopLog } from './log.js';
5
- import { dayIn, formatTime } from '../core/page/time-format.js';
5
+ import { dayIn, formatTime, timeAt, timeParts } from '../core/page/time-format.js';
6
6
  function toDataSlice(overrides) {
7
7
  const timezone = overrides.timezone ?? 'UTC';
8
8
  const today = overrides.today ?? '1970-01-01';
9
9
  const now = overrides.now ?? Date.parse(`${today}T00:00:00.000Z`);
10
10
  return {
11
- time: { now, timezone, today },
11
+ time: { now, timezone, today, ignore: overrides.ignore ?? { contactHours: false, contactSchedule: false } },
12
12
  meta: {
13
13
  companyId: 'company',
14
14
  environmentId: 'sandbox',
@@ -35,8 +35,9 @@ export function makeCtx(overrides = {}) {
35
35
  integration: { ...emptyIntegration(), ...overrides.api?.integration },
36
36
  log: bindLogMeta(overrides.api?.log ?? noopLog, data.meta),
37
37
  db: overrides.api?.db ?? unfaked('db'),
38
+ tools: fakeTools(overrides.api?.tools),
38
39
  };
39
- return { ...data, meta: data.meta, time: { ...data.time, format: formatTime, day: dayIn }, api };
40
+ return { ...data, meta: data.meta, time: { ...data.time, ignore: data.time.ignore ?? { contactHours: false, contactSchedule: false }, format: formatTime, day: dayIn, at: timeAt, parts: timeParts }, api };
40
41
  }
41
42
  /** Async makeCtx via {@link buildActionContext} + FakeApiHost (same result as {@link makeCtx}). */
42
43
  export async function makeCtxAsync(overrides = {}) {
@@ -2,20 +2,28 @@ import { type RpcContext } from './trpc-init.js';
2
2
  export type CaseOrchestratorToolInvokeHandler = (input: {
3
3
  tool: string;
4
4
  input: unknown;
5
- callKey: string;
6
5
  ctx: RpcContext;
7
6
  }) => Promise<unknown>;
8
7
  export declare function createCaseOrchestratorToolsRouter(invoke: CaseOrchestratorToolInvokeHandler): import("@trpc/server").TRPCBuiltRouter<{
9
8
  ctx: RpcContext;
10
9
  meta: object;
11
- errorShape: import("@trpc/server").TRPCDefaultErrorShape;
10
+ errorShape: import("@trpc/server").TRPCDefaultErrorShape | {
11
+ message: string;
12
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
13
+ data: {
14
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
15
+ httpStatus: number;
16
+ path?: string;
17
+ stack?: string;
18
+ reason: string;
19
+ };
20
+ };
12
21
  transformer: false;
13
22
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
14
23
  invoke: import("@trpc/server").TRPCMutationProcedure<{
15
24
  input: {
16
25
  tool: string;
17
26
  input: unknown;
18
- callKey: string;
19
27
  };
20
28
  output: unknown;
21
29
  meta: object;
@@ -3,7 +3,6 @@ import { publicProcedure, router } from './trpc-init.js';
3
3
  const invokeInput = z.object({
4
4
  tool: z.string().min(1),
5
5
  input: z.unknown(),
6
- callKey: z.string().min(1).max(200),
7
6
  });
8
7
  export function createCaseOrchestratorToolsRouter(invoke) {
9
8
  return router({
@@ -22,4 +22,17 @@ export declare class ScriptInputError extends Error implements RpcCodedError {
22
22
  });
23
23
  }
24
24
  export declare function parseScriptInput<S extends z.ZodType>(schema: S, input: unknown): z.infer<S>;
25
+ /**
26
+ * The business code a refused call carries to company code as `error.code` (`subject_busy`, `run_ended`, a
27
+ * write's code, 13 §16.3 item 8): the message reads `<reason>: <message>` for people, and the reason travels
28
+ * apart from it (`data.reason`), so `catch (error) { if (error.code === 'subject_busy') … }` works (64 §12).
29
+ */
30
+ export declare class RpcReasonError extends Error {
31
+ readonly reason: string;
32
+ constructor(reason: string, message: string);
33
+ }
34
+ /** A refusal with the HTTP-like `code` tRPC answers with and the business `reason` the caller sees. */
35
+ export declare function reasonError(code: RpcErrorCode, reason: string, message: string): TRPCError;
36
+ /** The business reason a server error carries, if any. */
37
+ export declare function rpcErrorReason(error: unknown): string | undefined;
25
38
  //# sourceMappingURL=errors.d.ts.map
@@ -1,3 +1,4 @@
1
+ import { TRPCError } from '@trpc/server';
1
2
  export function isRpcCodedError(error) {
2
3
  return error instanceof Error && typeof error.rpcCode === 'string';
3
4
  }
@@ -20,4 +21,25 @@ export function parseScriptInput(schema, input) {
20
21
  }
21
22
  return parsed.data;
22
23
  }
24
+ /**
25
+ * The business code a refused call carries to company code as `error.code` (`subject_busy`, `run_ended`, a
26
+ * write's code, 13 §16.3 item 8): the message reads `<reason>: <message>` for people, and the reason travels
27
+ * apart from it (`data.reason`), so `catch (error) { if (error.code === 'subject_busy') … }` works (64 §12).
28
+ */
29
+ export class RpcReasonError extends Error {
30
+ reason;
31
+ constructor(reason, message) {
32
+ super(message);
33
+ this.reason = reason;
34
+ this.name = 'RpcReasonError';
35
+ }
36
+ }
37
+ /** A refusal with the HTTP-like `code` tRPC answers with and the business `reason` the caller sees. */
38
+ export function reasonError(code, reason, message) {
39
+ return new TRPCError({ code, message: `${reason}: ${message}`, cause: new RpcReasonError(reason, message) });
40
+ }
41
+ /** The business reason a server error carries, if any. */
42
+ export function rpcErrorReason(error) {
43
+ return error instanceof RpcReasonError ? error.reason : undefined;
44
+ }
23
45
  //# sourceMappingURL=errors.js.map
@@ -1,6 +1,6 @@
1
1
  export { createAppRouter, type AppRouter } from './trpc-router-factory.js';
2
2
  export type { RpcContext } from './trpc-init.js';
3
- export { ScriptInputError, isRpcCodedError, parseScriptInput, type RpcCodedError, type RpcErrorCode, } from './errors.js';
3
+ export { ScriptInputError, isRpcCodedError, parseScriptInput, reasonError, RpcReasonError, type RpcCodedError, type RpcErrorCode, } from './errors.js';
4
4
  export { createIntegrationRouter, type IntegrationInvokeHandler } from './integration/index.js';
5
5
  export { createListSurfacesProcedure } from './integration/list-surfaces.js';
6
6
  export { createPlatformRouter, type PlatformInvokeHandler } from './platform.js';
@@ -1,5 +1,5 @@
1
1
  export { createAppRouter } from './trpc-router-factory.js';
2
- export { ScriptInputError, isRpcCodedError, parseScriptInput, } from './errors.js';
2
+ export { ScriptInputError, isRpcCodedError, parseScriptInput, reasonError, RpcReasonError, } from './errors.js';
3
3
  export { createIntegrationRouter } from './integration/index.js';
4
4
  export { createListSurfacesProcedure } from './integration/list-surfaces.js';
5
5
  export { createPlatformRouter } from './platform.js';
@@ -17,7 +17,17 @@ export declare function createIntegrationRouter(modules: {
17
17
  }): import("@trpc/server").TRPCBuiltRouter<{
18
18
  ctx: RpcContext;
19
19
  meta: object;
20
- errorShape: import("@trpc/server").TRPCDefaultErrorShape;
20
+ errorShape: import("@trpc/server").TRPCDefaultErrorShape | {
21
+ message: string;
22
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
23
+ data: {
24
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
25
+ httpStatus: number;
26
+ path?: string;
27
+ stack?: string;
28
+ reason: string;
29
+ };
30
+ };
21
31
  transformer: false;
22
32
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
23
33
  listSurfaces: import("@trpc/server").TRPCQueryProcedure<{
@@ -20,7 +20,17 @@ export type LogEmitHandler = (input: {
20
20
  export declare function createLogRouter(emit: LogEmitHandler): import("@trpc/server").TRPCBuiltRouter<{
21
21
  ctx: RpcContext;
22
22
  meta: object;
23
- errorShape: import("@trpc/server").TRPCDefaultErrorShape;
23
+ errorShape: import("@trpc/server").TRPCDefaultErrorShape | {
24
+ message: string;
25
+ code: import("@trpc/server").TRPC_ERROR_CODE_NUMBER;
26
+ data: {
27
+ code: import("@trpc/server").TRPC_ERROR_CODE_KEY;
28
+ httpStatus: number;
29
+ path?: string;
30
+ stack?: string;
31
+ reason: string;
32
+ };
33
+ };
24
34
  transformer: false;
25
35
  }, import("@trpc/server").TRPCDecorateCreateRouterOptions<{
26
36
  emit: import("@trpc/server").TRPCMutationProcedure<{