@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
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # @superpanel-sdk/runtime
2
2
 
3
- Slot + Stage runtime used by company repos and the platform: schema, writes, derived recompute, the page contract (`definePage`: persona, per-channel page functions, regions and todos, channel actions), and company-repo CLI.
3
+ Slot + Stage runtime used by company repos and the platform: schema, writes, the page contract (`definePage`: persona, FAQ, per-channel page functions, channel actions), and company-repo CLI.
4
4
 
5
- This package is currently published as an **internal prerelease**. Install a tagged build, not `latest`:
5
+ Each prod deploy of the platform publishes the runtime it runs as `latest`:
6
6
 
7
7
  ```bash
8
- npm i @superpanel-sdk/runtime@next
8
+ npm i @superpanel-sdk/runtime
9
9
  ```
10
10
 
11
11
  Requires Node.js `>=22.15`.
@@ -4,18 +4,14 @@ import type { CompiledSlotSchema } from '../../core/slot/types.js';
4
4
  * `__gen/tables.type.ts`, the one copy every sequence shares; only the subject is the sequence's.
5
5
  */
6
6
  export declare function emitSlotsSource(subject: string): string;
7
- /**
8
- * Emit `__gen/case-context.type.ts`: what code working on a case receives as `c` — functions, event
9
- * handlers, the Orchestrator: the instance and its business root's id (the page is the conversation's).
10
- */
11
- export declare function emitCaseContextSource(): string;
12
7
  /**
13
8
  * `__gen/index.ts`: the one import a sequence's page, functions and events need. Re-exports the
14
- * generated types, the page helpers bound to the company's tables (17b, 28 §2), and the define helpers bound
15
- * to its case (`CaseInput`). `functionsImport` is relative to `__gen/` (`null` without a functions module).
9
+ * generated types, the page helpers bound to the company's tables (17b, 28 §2), and the types of its
10
+ * functions and entries (`Ctx`, `Events`, `CaseOrchestrator`, `Resolve`, 38). `functionsImport` is relative to `__gen/` (`null` without a functions module),
11
+ * `actionsImport` likewise for the page actions (`actions.ts`, 76 §2.11).
16
12
  * Schema-independent, so the same text serves as the stub.
17
13
  */
18
- export declare function emitGenIndexSource(functionsImport: string | null, variablesImport?: string | null): string;
14
+ export declare function emitGenIndexSource(functionsImport: string | null, variablesImport?: string | null, actionsImport?: string | null): string;
19
15
  /**
20
16
  * Emit the repository root's `__gen/tables.type.ts`: the company's tables, as the code at the root
21
17
  * (`resolve.ts`, `webhook.ts`) reads and writes them with `ctx.api.db`, and as every sequence's
@@ -23,7 +19,7 @@ export declare function emitGenIndexSource(functionsImport: string | null, varia
23
19
  */
24
20
  export declare function emitCompanyTablesSource(schema: CompiledSlotSchema): string;
25
21
  /**
26
- * The repository root's `__gen/index.ts`: what `resolve.ts`, `webhook.ts` and `schedules.ts` import to get
22
+ * The repository root's `__gen/index.ts`: what `resolve.ts`, `webhook.ts`, `schedules.ts` and `errors.ts` import to get
27
23
  * `ctx.api.db` bound to the company's tables. Schema-independent, so the same text serves as the stub.
28
24
  */
29
25
  export declare function emitCompanyGenIndexSource(): string;
@@ -31,5 +27,4 @@ export declare function emitCompanyGenIndexSource(): string;
31
27
  export declare function emitCompanyTablesStub(): string;
32
28
  /** Stub written when a sequence has no gen file yet. */
33
29
  export declare function emitSlotsStub(): string;
34
- export declare function emitCaseContextStub(): string;
35
30
  //# sourceMappingURL=emit.d.ts.map
@@ -126,37 +126,20 @@ export function emitSlotsSource(subject) {
126
126
  // Source: the company's tables (root __gen) and this sequence's subject
127
127
  // Regenerate: superpanel-sdk-runtime type:gen
128
128
 
129
- export type { FieldHistoryEntry, FieldState, FieldValueBase, PageTables, RefTargets, Rows } from '../../../__gen/tables.type.ts';
129
+ export type { FieldState, FieldValueBase, PageTables, RefTargets, Rows } from '../../../__gen/tables.type.ts';
130
130
 
131
131
  /** The table this sequence's runs are about (\`defineSequence({ subject })\`). */
132
132
  export type SubjectTable = ${JSON.stringify(subject)};
133
133
  `;
134
134
  }
135
- /**
136
- * Emit `__gen/case-context.type.ts`: what code working on a case receives as `c` — functions, event
137
- * handlers, the Orchestrator: the instance and its business root's id (the page is the conversation's).
138
- */
139
- export function emitCaseContextSource() {
140
- return `// GENERATED — do not edit
141
- // CaseInput: what functions, event handlers and the Orchestrator receive as c (the instance and its business root)
142
- // Regenerate: superpanel-sdk-runtime type:gen
143
-
144
- import type { CaseInput as RuntimeCaseInput } from '@superpanel-sdk/runtime';
145
- import type { SubjectTable } from './slots.type.ts';
146
-
147
- /** What functions, event handlers, orchestrator and contacts receive as \`c\`: the instance, and its business root's id. */
148
- export type CaseInput = RuntimeCaseInput<SubjectTable>;
149
- /** What orchestrator and contacts receive as \`c\` (the same as \`CaseInput\`). */
150
- export type CaseOrchestratorInput = CaseInput;
151
- `;
152
- }
153
135
  /**
154
136
  * `__gen/index.ts`: the one import a sequence's page, functions and events need. Re-exports the
155
- * generated types, the page helpers bound to the company's tables (17b, 28 §2), and the define helpers bound
156
- * to its case (`CaseInput`). `functionsImport` is relative to `__gen/` (`null` without a functions module).
137
+ * generated types, the page helpers bound to the company's tables (17b, 28 §2), and the types of its
138
+ * functions and entries (`Ctx`, `Events`, `CaseOrchestrator`, `Resolve`, 38). `functionsImport` is relative to `__gen/` (`null` without a functions module),
139
+ * `actionsImport` likewise for the page actions (`actions.ts`, 76 §2.11).
157
140
  * Schema-independent, so the same text serves as the stub.
158
141
  */
159
- export function emitGenIndexSource(functionsImport, variablesImport = null) {
142
+ export function emitGenIndexSource(functionsImport, variablesImport = null, actionsImport = null) {
160
143
  const variablesType = variablesImport
161
144
  ? `type VariablesModule = typeof import(${JSON.stringify(variablesImport)});
162
145
  /** This sequence's run variables (\`variables.ts\`), as \`ctx.api.instances.get\` returns them. */
@@ -167,41 +150,67 @@ export type InstanceVariables = VariablesOf<Record<never, never>>;`;
167
150
  ? `type FunctionsModule = typeof import(${JSON.stringify(functionsImport)});
168
151
  type Functions = FunctionsModule extends { functions: infer F } ? F : FunctionsModule extends { default: infer F } ? F : Record<never, never>;`
169
152
  : `type Functions = Record<never, never>;`;
153
+ const actionsType = actionsImport
154
+ ? `type ActionsModule = typeof import(${JSON.stringify(actionsImport)});
155
+ type Actions = ActionsModule extends { actions: infer A } ? A : Record<never, never>;`
156
+ : `type Actions = Record<never, never>;`;
170
157
  return `// GENERATED — do not edit
171
- // Sequence entry: define helpers bound to this sequence's case and tables, plus generated types
158
+ // Sequence entry: page helpers and function types bound to this sequence's tables, plus generated types
172
159
  // Regenerate: superpanel-sdk-runtime type:gen
173
160
 
174
161
  import {
175
- bindDefines,
176
- defineSchedules as runtimeDefineSchedules,
177
162
  choose as runtimeChoose,
178
- createRow as runtimeCreateRow,
179
- defineAction as runtimeDefineAction,
180
163
  definePage as runtimeDefinePage,
164
+ page as runtimePageFn,
165
+ field as runtimeFieldFn,
166
+ refField as runtimeRefFieldFn,
167
+ createRow as runtimeCreateRow,
168
+ run as runtimeRun,
181
169
  deleteRow as runtimeDeleteRow,
182
- field as runtimeField,
183
- refField as runtimeRefField,
184
- runFunction as runtimeRunFunction,
185
- schemaField as runtimeSchemaField,
170
+ functionHandles as runtimeFunctionHandles,
171
+ actionHandles as runtimeActionHandles,
172
+ type ActionHandles,
173
+ type FunctionHandles,
174
+ type TypedPageFns,
175
+ type Ctx as RuntimeCtx,
186
176
  type CaseOrchestrator as RuntimeCaseOrchestrator,
187
- type CaseOrchestratorContacts as RuntimeCaseOrchestratorContacts,
177
+ type EventHandlers,
188
178
  type Resolve as RuntimeResolve,
189
- type Schedules,
190
179
  type VariablesOf,
191
180
  type RowOf,
192
181
  type TypedDb,
193
182
  type PageChannel,
183
+ type TypedActionContext,
194
184
  type TypedPageContext,
195
185
  type TypedPageModule,
196
186
  type TypedReadDb,
197
187
  } from '@superpanel-sdk/runtime';
198
- export { end, lastActionRun, perform, tried } from '@superpanel-sdk/runtime';
199
- import type { CaseInput, CaseOrchestratorInput } from './case-context.type.ts';
188
+ export { lastActionRun, tried } from '@superpanel-sdk/runtime';
189
+ // The page in functions (76): the ones not bound to this sequence's tables, as they are.
190
+ export {
191
+ announce,
192
+ backgroundTransfer,
193
+ block,
194
+ button,
195
+ cancelFollowUp,
196
+ coldTransfer,
197
+ convertTime,
198
+ data,
199
+ doNow,
200
+ end,
201
+ keypad,
202
+ list,
203
+ pressKeypad,
204
+ scheduleFollowUp,
205
+ text,
206
+ toolbox,
207
+ voicemail,
208
+ warmTransfer,
209
+ } from '@superpanel-sdk/runtime';
200
210
  import type { PageTables, SubjectTable } from './slots.type.ts';
201
211
 
202
- export type { CaseInput, CaseOrchestratorInput } from './case-context.type.ts';
203
212
  export type { PageTables, RefTargets, Rows, SubjectTable } from './slots.type.ts';
204
- export type { Id } from '@superpanel-sdk/runtime';
213
+ export type { ContactSchedule, Email, Id, IsoDate, IsoDateTime, Phone, TimeOfDay } from '@superpanel-sdk/runtime';
205
214
 
206
215
  type PageModule = TypedPageModule<PageTables, SubjectTable>;
207
216
  /**
@@ -212,40 +221,39 @@ export type PageContext<C extends PageChannel = PageChannel> = TypedPageContext<
212
221
  /**
213
222
  * \`context.page.ts\` (17b §9.1): \`export default definePage({ persona: (ctx) => '…', faq: (ctx) => [...], call: async (ctx) => page, sms: …, email: … })\`.
214
223
  * \`persona\` and \`faq\` are called once, when the conversation starts (24 §4).
215
- * \`db\` and \`schemaField\` take the company's tables and fields.
224
+ * \`db\` takes the company's tables and fields.
216
225
  */
217
226
  export const definePage = runtimeDefinePage as unknown as PageModule['definePage'];
218
- /** A cell the AI may write: \`field(slot, { readOnly, expand })\` (a slot placed as is is read-only). How to fill a field on this page: the page's \`$extraction: { 'table.field': '…' }\`. */
219
- export const field = runtimeField as unknown as PageModule['field'];
220
- /**
221
- * A ref field (26 §16.2 #7): \`refField(job.referred_by, { options: choose(regulars, (c) => c.first_name.value ?? '') })\`,
222
- * the rows the AI may set it to, each with its label; \`{ readOnly: true, options: [...] }\` shows who the current one is.
223
- */
224
- export const refField = runtimeRefField as unknown as PageModule['refField'];
225
- /** An action parameter taken from the schema: \`schemaField('providers.name')\`, \`schemaField('injuries.id')\` (a row). */
226
- export const schemaField = runtimeSchemaField as unknown as PageModule['schemaField'];
227
- /** The built-in action that adds a row: \`createRow('injuries', { fields })\`, called to preset values. */
228
- export const createRow = runtimeCreateRow as unknown as PageModule['createRow'];
229
- /** The built-in action that deletes a row (and everything under it): \`deleteRow(row.id)\`. */
230
- export const deleteRow = runtimeDeleteRow as unknown as PageModule['deleteRow'];
231
227
  /**
232
228
  * The rows a row parameter is chosen among (25 §10): \`cancel({ appointment: choose(appointments, (a) => a.date.value) })\`.
233
229
  * The candidates are exactly these rows; with none the button is left off the page.
234
230
  */
235
231
  export const choose = runtimeChoose as unknown as PageModule['choose'];
236
232
  /**
237
- * A custom action, declared like an LLM function call (\`parameters\`). Place it called: a row argument
238
- * prefilled (\`markError({ injury: i.id })\`) or offered with \`choose(...)\` (25 §10).
233
+ * A page action's \`ctx\` (76 §2.11), in \`actions.ts\`: \`export const actions = { verifyPin: async (ctx: ActionCtx, args: { pin: string }) => { … } }\`.
234
+ * It runs next to the database, in one transaction; \`db\` takes the company's tables and fields.
239
235
  */
240
- export const defineAction = runtimeDefineAction as unknown as PageModule['defineAction'];
236
+ export type ActionCtx = TypedActionContext<PageTables, SubjectTable>;
237
+ type Fns = TypedPageFns<PageTables, SubjectTable, Functions>;
238
+ /** The page (76 §2.7): \`page({ guide, voice, extraction }, { …content by name })\`; returned by a page function unless it returns \`doNow()\`. */
239
+ export const page = runtimePageFn as unknown as Fns['page'];
240
+ /** A field the AI may write, or read only: \`field(m.incident_date, { expand: true })\`. A ref field is \`refField()\`. */
241
+ export const field = runtimeFieldFn as unknown as Fns['field'];
242
+ /** A ref field: writable, the rows it may be set to (\`options: choose(rows, label)\`); read-only, who its value is (\`label\`). */
243
+ export const refField = runtimeRefFieldFn as unknown as Fns['refField'];
244
+ /** Add a row of this sequence's tables: \`createRow('injury', { fields: ['body_part'], prefill: { case: c.id } })\`. */
245
+ export const createRow = runtimeCreateRow as unknown as Fns['createRow'];
246
+ /** Run a company function (\`fn.x\`) or a page action: \`run(fn.cancelOrder, { prefill: { order: o.id }, args: { reason: 'In their words' } })\`. */
247
+ export const run = runtimeRun as unknown as Fns['run'];
248
+ /** Delete a row and everything under it: \`deleteRow(injury)\`. */
249
+ export const deleteRow = runtimeDeleteRow as unknown as Fns['deleteRow'];
250
+ /** This sequence's company functions (\`functions/\`), by name, for \`run(fn.x, { … })\` (76 §2.15). */
251
+ export const fn = runtimeFunctionHandles() as unknown as FunctionHandles<Functions>;
241
252
  /**
242
- * A company function (\`functions/\`) as a button, or returned by the page function to run now (20 §6.2):
243
- * \`runFunction('importOrders', { label, say, parameters })\`. The name must be one of this sequence's functions.
253
+ * This sequence's page actions (\`actions.ts\`), by name, for \`run(act.verifyPin, { … })\` (76 §2.11). An action runs
254
+ * next to the database, in one transaction.
244
255
  */
245
- export const runFunction = runtimeRunFunction as unknown as (
246
- name: keyof Functions & string,
247
- options?: Parameters<typeof runtimeRunFunction>[1],
248
- ) => ReturnType<typeof runtimeRunFunction>;
256
+ export const act = runtimeActionHandles() as unknown as ActionHandles<Actions, PageTables, SubjectTable>;
249
257
  /** A row of \`T\` as \`db\` returns it; \`Inc\` what was \`include\`d (\`Row<'case_contact', { contact: true }>\`). */
250
258
  export type Row<T extends keyof PageTables, Inc = undefined> = RowOf<PageTables, T, Inc>;
251
259
  /** \`ctx.api.db\` (and an action's \`db\`): the company's tables, reads and writes. */
@@ -254,30 +262,32 @@ export type Db = TypedDb<PageTables>;
254
262
  export type ReadDb = TypedReadDb<PageTables>;
255
263
 
256
264
 
257
- /** Functions and event handlers get \`c\`: CaseInput; their \`ctx.api.db\` takes the company's tables and fields. */
258
- export const { defineCaseFunc, defineNoCaseFunc, defineEvents } = bindDefines<PageTables, CaseInput>();
265
+ /**
266
+ * A function's \`ctx\` (38 §2.3): \`export async function cancel(ctx: Ctx, args: { appointment: Id<'appointment'>; reason: string })\`;
267
+ * \`ctx.api.db\` takes the company's tables and fields.
268
+ */
269
+ export type Ctx = RuntimeCtx<PageTables>;
270
+
271
+ /**
272
+ * \`events.ts\` (38 §2.2): \`export const events: Events = { 'call.ended': async (ctx, { event, subject, instanceId }) => … }\`.
273
+ */
274
+ export type Events = EventHandlers<PageTables, SubjectTable>;
259
275
 
260
276
  ${functionsType}
277
+ ${actionsType}
261
278
  ${variablesType}
262
279
  /** This sequence's functions (\`functions\` module), by name. */
263
280
  export type FunctionsOf = Functions;
264
281
 
265
282
  /**
266
- * \`orchestrator.ts\`: \`export const orchestrator: CaseOrchestrator = async (c, ctx) => …\`;
267
- * \`ctx.api.db\` take the company's tables and fields.
283
+ * \`orchestrator.ts\`: \`export const orchestrator: CaseOrchestrator = async (ctx, args) => …\`; \`args.subject\` is
284
+ * a row of this sequence's subject table, \`ctx.api.db\` takes the company's tables and fields.
268
285
  */
269
- export type CaseOrchestrator = RuntimeCaseOrchestrator<CaseOrchestratorInput, PageTables>;
270
- /** \`orchestrator.ts\`: \`export const contacts: CaseOrchestratorContacts = async (c, ctx) => contactIds\`. */
271
- export type CaseOrchestratorContacts = RuntimeCaseOrchestratorContacts<CaseOrchestratorInput, PageTables>;
286
+ export type CaseOrchestrator = RuntimeCaseOrchestrator<PageTables, SubjectTable>;
272
287
 
273
- /** \`resolve.ts\`: \`export const resolve: Resolve = async (ctx) => …\`; \`ctx.api.db\` take the company's tables. */
288
+ /** \`resolve.ts\`: \`export const resolve: Resolve = async (ctx, conversation) => …\`; \`ctx.api.db\` take the company's tables. */
274
289
  export type Resolve = RuntimeResolve<PageTables>;
275
290
 
276
- /**
277
- * \`schedules.ts\` (25 §6.4): \`export const schedules = defineSchedules({ dailyRecall: { cron: '0 8 * * 1-5', timezone: 'America/Phoenix', run: async (ctx) => … } })\`.
278
- * No case: \`ctx.api.db\` takes the company's tables; start or notify its instances with \`ctx.api.instances\`.
279
- */
280
- export const defineSchedules = runtimeDefineSchedules as (schedules: Schedules<PageTables>) => Schedules<PageTables>;
281
291
  `;
282
292
  }
283
293
  /**
@@ -295,18 +305,6 @@ import type { CellBinding, ContactSchedule, Id, RowRef } from '@superpanel-sdk/r
295
305
 
296
306
  export type FieldState = "empty" | "filled" | "asked_unknown" | "declined";
297
307
 
298
- export type FieldHistoryEntry = {
299
- value: string | number | boolean | string[] | ContactSchedule | null;
300
- state: FieldState;
301
- at: number;
302
- by:
303
- | "slot-filling"
304
- | "function"
305
- | "human"
306
- | "import"
307
- | "platform";
308
- };
309
-
310
308
  export type FieldValueBase = {
311
309
  reason: string | null;
312
310
  state: FieldState;
@@ -317,7 +315,6 @@ export type FieldValueBase = {
317
315
  | "human"
318
316
  | "import"
319
317
  | "platform";
320
- history: FieldHistoryEntry[];
321
318
  };
322
319
 
323
320
  /** One row of each table, as a view receives it. */
@@ -328,23 +325,24 @@ ${rowBlocks.join('\n')}
328
325
  /** Each table's ref fields and the table each points at (\`q.rows(table).where(field, node)\`, \`node.follow(field)\`). */
329
326
  export type RefTargets = ${objectType(emitRefTargets(schema))};
330
327
 
331
- /** The company's tables as code reads and writes them (\`ctx.api.db\`, a page's \`db\`, actions' \`schemaField\`). */
328
+ /** The company's tables as code reads and writes them (\`ctx.api.db\`, a page's and its actions' \`db\`). */
332
329
  export type PageTables = ${objectType(emitPageTables(schema))};
333
330
  `;
334
331
  }
335
332
  /**
336
- * The repository root's `__gen/index.ts`: what `resolve.ts`, `webhook.ts` and `schedules.ts` import to get
333
+ * The repository root's `__gen/index.ts`: what `resolve.ts`, `webhook.ts`, `schedules.ts` and `errors.ts` import to get
337
334
  * `ctx.api.db` bound to the company's tables. Schema-independent, so the same text serves as the stub.
338
335
  */
339
336
  export function emitCompanyGenIndexSource() {
340
337
  return `// GENERATED — do not edit
341
- // Company entry: types for the code at the repository root (resolve.ts, webhook.ts, schedules.ts), bound to the company's tables
338
+ // Company entry: types for the code at the repository root (resolve.ts, webhook.ts, schedules.ts, errors.ts), bound to the company's tables
342
339
  // Regenerate: superpanel-sdk-runtime type:gen
343
340
 
344
341
  import {
345
342
  defineSchedules as runtimeDefineSchedules,
346
- defineWebhook as runtimeDefineWebhook,
347
343
  type CompanyResolve as RuntimeCompanyResolve,
344
+ type OnError as RuntimeOnError,
345
+ type Ctx as RuntimeCtx,
348
346
  type RowOf,
349
347
  type Schedules,
350
348
  type TypedDb,
@@ -354,16 +352,24 @@ import type { PageTables } from './tables.type.ts';
354
352
 
355
353
  export type { PageTables } from './tables.type.ts';
356
354
  export type { Id } from '@superpanel-sdk/runtime';
355
+ export type { CodeErrorEvent } from '@superpanel-sdk/runtime';
357
356
 
358
- /** \`resolve.ts\`: \`export const resolve: CompanyResolve = async (ctx) => …\`; \`ctx.api.db\` takes the company's tables. */
357
+ /** A function's \`ctx\` (38 §2.3): \`ctx.api.db\` takes the company's tables. */
358
+ export type Ctx = RuntimeCtx<PageTables>;
359
+ /** \`resolve.ts\`: \`export const resolve: CompanyResolve = async (ctx, conversation) => …\`; \`ctx.api.db\` takes the company's tables. */
359
360
  export type CompanyResolve = RuntimeCompanyResolve<PageTables>;
360
- /** \`webhook.ts\`: \`export const received = defineWebhook(async (ctx) => …)\`; \`ctx.api.db\` takes the company's tables. */
361
- export const defineWebhook = runtimeDefineWebhook as (handler: WebhookHandler<PageTables>) => WebhookHandler<PageTables>;
361
+ /** \`webhook.ts\`: \`export const received: Webhook = async (ctx, { event }) => …\`; \`ctx.api.db\` takes the company's tables. */
362
+ export type Webhook = WebhookHandler<PageTables>;
362
363
  /**
363
- * \`schedules.ts\` (25 §6.4): \`export const schedules = defineSchedules({ nightlySync: { cron: '0 2 * * *', timezone: 'UTC', run: async (ctx) => … } })\`.
364
+ * \`schedules.ts\` (25 §6.4): \`export const schedules = defineSchedules({ nightlySync: { cron: '0 2 * * *', timezone: 'UTC', run: async (ctx, { schedule }) => … } })\`.
364
365
  * No case: \`ctx.api.db\` takes the company's tables; start or notify any sequence's instances with \`ctx.api.instances\`.
365
366
  */
366
367
  export const defineSchedules = runtimeDefineSchedules as (schedules: Schedules<PageTables>) => Schedules<PageTables>;
368
+ /**
369
+ * \`errors.ts\` (67 §5): \`export const onError: OnError = async (ctx, { error }) => …\`. Run once for each failure your code
370
+ * did not catch, and each text or email conversation the AI marked stuck; with no case.
371
+ */
372
+ export type OnError = RuntimeOnError<PageTables>;
367
373
  /** A row of \`T\` as \`db\` returns it; \`Inc\` what was \`include\`d. */
368
374
  export type Row<T extends keyof PageTables, Inc = undefined> = RowOf<PageTables, T, Inc>;
369
375
  /** \`ctx.api.db\` of the code at the root: the company's tables, reads and writes. */
@@ -376,7 +382,6 @@ export function emitCompanyTablesStub() {
376
382
  // Stub — run: superpanel-sdk-runtime type:gen
377
383
 
378
384
  export type FieldState = "empty" | "filled" | "asked_unknown" | "declined";
379
- export type FieldHistoryEntry = Record<string, unknown>;
380
385
  export type FieldValueBase = Record<string, unknown>;
381
386
  export type Rows = Record<string, Record<string, unknown>>;
382
387
  export type RefTargets = Record<string, Record<string, string>>;
@@ -389,7 +394,6 @@ export function emitSlotsStub() {
389
394
  // Stub — run: superpanel-sdk-runtime type:gen
390
395
 
391
396
  export type FieldState = "empty" | "filled" | "asked_unknown" | "declined";
392
- export type FieldHistoryEntry = Record<string, unknown>;
393
397
  export type FieldValueBase = Record<string, unknown>;
394
398
  export type Rows = Record<string, Record<string, unknown>>;
395
399
  export type RefTargets = Record<string, Record<string, string>>;
@@ -397,14 +401,4 @@ export type SubjectTable = string;
397
401
  export type PageTables = Record<string, Record<string, { value: unknown; ref?: string; parent?: true } | Record<string, { table: string; field: string }>>>;
398
402
  `;
399
403
  }
400
- export function emitCaseContextStub() {
401
- return `// GENERATED — do not edit
402
- // Stub — run: superpanel-sdk-runtime type:gen
403
-
404
- import type { CaseInput as RuntimeCaseInput } from '@superpanel-sdk/runtime';
405
-
406
- export type CaseInput = RuntimeCaseInput;
407
- export type CaseOrchestratorInput = CaseInput;
408
- `;
409
- }
410
404
  //# sourceMappingURL=emit.js.map
@@ -3,10 +3,8 @@ export { listSequenceIds };
3
3
  export type GenerateResult = {
4
4
  sequenceId: string;
5
5
  outPath: string;
6
- caseContextOutPath: string;
7
6
  indexOutPath: string;
8
7
  source: string;
9
- caseContextSource: string;
10
8
  indexSource: string;
11
9
  /** The root `__gen/tables.type.ts` the sequence's types re-export (28 §2.2). */
12
10
  tablesSource: string;
@@ -21,10 +19,9 @@ export declare function generateSequence(repoRoot: string, sequenceId: string, o
21
19
  dryRun?: boolean;
22
20
  }): Promise<GenerateResult>;
23
21
  /**
24
- * The root `__gen/` alone, from the company schema: what the root code of a repository with no
25
- * sequence is typed by (22 §11). `generateAll` writes it too, with the sequences.
22
+ * The root `__gen/` and every sequence's (or only `sequenceIds`'). A repository with no sequence gets the
23
+ * root's alone, as the release type check does (22 §11), so `type:gen` and `typecheck` pass on it locally too.
26
24
  */
27
- export declare function generateCompany(repoRoot: string): Promise<void>;
28
25
  export declare function generateAll(repoRoot: string, options?: {
29
26
  dryRun?: boolean;
30
27
  sequenceIds?: string[];
@@ -32,6 +29,7 @@ export declare function generateAll(repoRoot: string, options?: {
32
29
  export declare function checkSequence(repoRoot: string, sequenceId: string): Promise<void>;
33
30
  /** The root `__gen/` matches the company schema. */
34
31
  export declare function checkCompany(repoRoot: string): Promise<void>;
32
+ /** The root `__gen/` and every sequence's are up to date; with no sequence, the root's alone. */
35
33
  export declare function checkAll(repoRoot: string): Promise<void>;
36
34
  export declare function ensureStub(repoRoot: string, sequenceId: string): void;
37
35
  /**
@@ -4,9 +4,9 @@ import { subjectTableIssues } from '../../core/slot/company-metadata.js';
4
4
  import { compileSlotSchema } from '../../core/slot/compile-schema.js';
5
5
  import { withCompanyImportGraph } from '../company-import-graph.js';
6
6
  import { assertNoSlotsModule, listSequenceIds, loadCompanySchema, loadSequenceDefinition, loadSessionSchema, } from '../load.js';
7
- import { findTsModule, resolveTsModule } from '../paths.js';
7
+ import { findTsModule, requirePagePath, resolveTsModule } from '../paths.js';
8
8
  import { fatalSlotSchemaIssues } from '../slot-schema-validation.js';
9
- import { emitCaseContextSource, emitCaseContextStub, emitCompanyGenIndexSource, emitCompanyTablesSource, emitCompanyTablesStub, emitGenIndexSource, emitSlotsSource, emitSlotsStub, } from './emit.js';
9
+ import { emitCompanyGenIndexSource, emitCompanyTablesSource, emitCompanyTablesStub, emitGenIndexSource, emitSlotsSource, emitSlotsStub, } from './emit.js';
10
10
  export { listSequenceIds };
11
11
  /** The repository root's `__gen/`: types for `resolve.ts` and `webhook.ts`, bound to the company's tables. */
12
12
  export function companyGenPaths(repoRoot) {
@@ -22,7 +22,8 @@ function sequenceSlotsGenPath(repoRoot, sequenceId) {
22
22
  function legacySlotsConfigGenPath(repoRoot, sequenceId) {
23
23
  return path.join(repoRoot, 'sequences', sequenceId, '__gen', 'slots-config.type.ts');
24
24
  }
25
- function sequenceCaseContextGenPath(repoRoot, sequenceId) {
25
+ /** `__gen/case-context.type.ts` (`CaseInput`, the old `c`): no entry gets a `c` any more (38 §2.2). */
26
+ function legacyCaseContextGenPath(repoRoot, sequenceId) {
26
27
  return path.join(repoRoot, 'sequences', sequenceId, '__gen', 'case-context.type.ts');
27
28
  }
28
29
  /** Generated for the declarative load, which was removed (15 §10.15); type:gen deletes a leftover one. */
@@ -36,7 +37,7 @@ function sequenceGenIndexPath(repoRoot, sequenceId) {
36
37
  function functionsImportFor(repoRoot, sequenceId) {
37
38
  return moduleImportFor(repoRoot, sequenceId, 'functions');
38
39
  }
39
- /** A module of the sequence (`functions`, `variables`) as `__gen/index.ts` imports it; null when absent. */
40
+ /** A module of the sequence (`functions`, `variables`, `actions`) as `__gen/index.ts` imports it; null when absent. */
40
41
  function moduleImportFor(repoRoot, sequenceId, name) {
41
42
  const sequenceDir = path.join(repoRoot, 'sequences', sequenceId);
42
43
  const found = findTsModule(sequenceDir, name);
@@ -91,48 +92,36 @@ async function generateSequenceInGraph(repoRoot, sequenceId, options, { company,
91
92
  if (!options.dryRun)
92
93
  writeCompanyGen(repoRoot, { company, session });
93
94
  // Every sequence has a page script (15 §10.2): the generated page types read it.
94
- if (findTsModule(sequenceDir, 'context.page') === undefined) {
95
- throw new Error(`sequences/${sequenceId}: context.page.ts is required (the conversation's page, 15 §10.2)`);
96
- }
95
+ requirePagePath(sequenceDir, sequenceId);
97
96
  const source = emitSlotsSource(subject);
98
- const caseContextSource = emitCaseContextSource();
99
- const indexSource = emitGenIndexSource(functionsImportFor(repoRoot, sequenceId), moduleImportFor(repoRoot, sequenceId, 'variables'));
97
+ const indexSource = emitGenIndexSource(functionsImportFor(repoRoot, sequenceId), moduleImportFor(repoRoot, sequenceId, 'variables'), moduleImportFor(repoRoot, sequenceId, 'actions'));
100
98
  const outPath = sequenceSlotsGenPath(repoRoot, sequenceId);
101
- const caseContextOutPath = sequenceCaseContextGenPath(repoRoot, sequenceId);
102
99
  const indexOutPath = sequenceGenIndexPath(repoRoot, sequenceId);
103
100
  if (!options.dryRun) {
104
101
  mkdirSync(path.dirname(outPath), { recursive: true });
105
102
  writeFileSync(outPath, source, 'utf8');
106
- writeFileSync(caseContextOutPath, caseContextSource, 'utf8');
107
103
  writeFileSync(indexOutPath, indexSource, 'utf8');
108
104
  rmSync(legacyLoadGenPath(repoRoot, sequenceId), { force: true });
105
+ rmSync(legacyCaseContextGenPath(repoRoot, sequenceId), { force: true });
109
106
  rmSync(legacySlotsConfigGenPath(repoRoot, sequenceId), { force: true });
110
107
  }
111
108
  return {
112
109
  sequenceId,
113
110
  outPath,
114
- caseContextOutPath,
115
111
  indexOutPath,
116
112
  source,
117
- caseContextSource,
118
113
  indexSource,
119
114
  tablesSource,
120
115
  wrote: !options.dryRun,
121
116
  };
122
117
  }
123
118
  /**
124
- * The root `__gen/` alone, from the company schema: what the root code of a repository with no
125
- * sequence is typed by (22 §11). `generateAll` writes it too, with the sequences.
119
+ * The root `__gen/` and every sequence's (or only `sequenceIds`'). A repository with no sequence gets the
120
+ * root's alone, as the release type check does (22 §11), so `type:gen` and `typecheck` pass on it locally too.
126
121
  */
127
- export async function generateCompany(repoRoot) {
128
- return withCompanyImportGraph(repoRoot, async () => writeCompanyGen(repoRoot, await loadCompanySchemas(repoRoot)));
129
- }
130
122
  export async function generateAll(repoRoot, options = {}) {
131
123
  return withCompanyImportGraph(repoRoot, async () => {
132
124
  const ids = options.sequenceIds ?? listSequenceIds(repoRoot);
133
- if (ids.length === 0) {
134
- throw new Error(NO_SEQUENCES(repoRoot));
135
- }
136
125
  const schemas = await loadCompanySchemas(repoRoot);
137
126
  // The root's types depend on the schema only: written with every full run (a schema change is one).
138
127
  if (!options.dryRun && !options.sequenceIds)
@@ -154,7 +143,6 @@ export async function generateAll(repoRoot, options = {}) {
154
143
  return results;
155
144
  });
156
145
  }
157
- const NO_SEQUENCES = (repoRoot) => `No sequences found under ${path.join(repoRoot, 'sequences')} (a sequence is a directory with index.ts)`;
158
146
  function assertFileMatches(outPath, next, repoRoot) {
159
147
  let current = '';
160
148
  try {
@@ -168,9 +156,8 @@ function assertFileMatches(outPath, next, repoRoot) {
168
156
  }
169
157
  }
170
158
  export async function checkSequence(repoRoot, sequenceId) {
171
- const { outPath, caseContextOutPath, indexOutPath, source, caseContextSource, indexSource } = await generateSequence(repoRoot, sequenceId, { dryRun: true });
159
+ const { outPath, indexOutPath, source, indexSource } = await generateSequence(repoRoot, sequenceId, { dryRun: true });
172
160
  assertFileMatches(outPath, source, repoRoot);
173
- assertFileMatches(caseContextOutPath, caseContextSource, repoRoot);
174
161
  assertFileMatches(indexOutPath, indexSource, repoRoot);
175
162
  }
176
163
  /** The root `__gen/` matches the company schema. */
@@ -180,11 +167,9 @@ export async function checkCompany(repoRoot) {
180
167
  assertFileMatches(tablesOutPath, tablesSource, repoRoot);
181
168
  assertFileMatches(indexOutPath, indexSource, repoRoot);
182
169
  }
170
+ /** The root `__gen/` and every sequence's are up to date; with no sequence, the root's alone. */
183
171
  export async function checkAll(repoRoot) {
184
172
  const ids = listSequenceIds(repoRoot);
185
- if (ids.length === 0) {
186
- throw new Error(NO_SEQUENCES(repoRoot));
187
- }
188
173
  await checkCompany(repoRoot);
189
174
  const failures = [];
190
175
  for (const sequenceId of ids) {
@@ -200,17 +185,13 @@ export async function checkAll(repoRoot) {
200
185
  }
201
186
  export function ensureStub(repoRoot, sequenceId) {
202
187
  const slotsPath = sequenceSlotsGenPath(repoRoot, sequenceId);
203
- const caseContextPath = sequenceCaseContextGenPath(repoRoot, sequenceId);
204
188
  mkdirSync(path.dirname(slotsPath), { recursive: true });
205
189
  if (!existsSync(slotsPath)) {
206
190
  writeFileSync(slotsPath, emitSlotsStub(), 'utf8');
207
191
  }
208
- if (!existsSync(caseContextPath)) {
209
- writeFileSync(caseContextPath, emitCaseContextStub(), 'utf8');
210
- }
211
192
  const indexPath = sequenceGenIndexPath(repoRoot, sequenceId);
212
193
  if (!existsSync(indexPath)) {
213
- writeFileSync(indexPath, emitGenIndexSource(functionsImportFor(repoRoot, sequenceId), moduleImportFor(repoRoot, sequenceId, 'variables')), 'utf8');
194
+ writeFileSync(indexPath, emitGenIndexSource(functionsImportFor(repoRoot, sequenceId), moduleImportFor(repoRoot, sequenceId, 'variables'), moduleImportFor(repoRoot, sequenceId, 'actions')), 'utf8');
214
195
  }
215
196
  }
216
197
  /**
@@ -6,6 +6,11 @@
6
6
  * (`function-code.ts`). Both use this one rule, so serve, `compile` and a release agree.
7
7
  */
8
8
  export declare const RUNTIME_PACKAGE = "@superpanel-sdk/runtime";
9
+ /**
10
+ * The runtime's test helpers (`testing.ts`): a test file's import. The compile never loads a test file
11
+ * (it loads a repository from its entries), and refuses this entry in every file it does load.
12
+ */
13
+ export declare const RUNTIME_TESTING_ENTRY = "@superpanel-sdk/runtime/testing";
9
14
  export declare function realPath(filePath: string): string;
10
15
  /** The directory of the nearest `package.json` above `file`, else the file's own directory. */
11
16
  export declare function packageRootOf(file: string): string;
@@ -9,11 +9,16 @@ import path from 'node:path';
9
9
  * (`function-code.ts`). Both use this one rule, so serve, `compile` and a release agree.
10
10
  */
11
11
  export const RUNTIME_PACKAGE = '@superpanel-sdk/runtime';
12
+ /**
13
+ * The runtime's test helpers (`testing.ts`): a test file's import. The compile never loads a test file
14
+ * (it loads a repository from its entries), and refuses this entry in every file it does load.
15
+ */
16
+ export const RUNTIME_TESTING_ENTRY = `${RUNTIME_PACKAGE}/testing`;
12
17
  /**
13
18
  * The company API's files in a runtime package: built (with its types, which a tsconfig `paths` may
14
19
  * name), or the source the runtime's own tests run.
15
20
  */
16
- const COMPANY_API_FILES = new Set([path.join('dist', 'index.js'), path.join('dist', 'index.d.ts'), path.join('src', 'index.ts')]);
21
+ const COMPANY_API_FILES = new Set(['index'].flatMap((name) => [path.join('dist', `${name}.js`), path.join('dist', `${name}.d.ts`), path.join('src', `${name}.ts`)]));
17
22
  const packageNames = new Map();
18
23
  export function realPath(filePath) {
19
24
  try {
@@ -81,6 +86,9 @@ export function specifierIssue(specifier) {
81
86
  }
82
87
  if (!isBareSpecifier(specifier) || specifier === RUNTIME_PACKAGE)
83
88
  return null;
89
+ if (specifier === RUNTIME_TESTING_ENTRY) {
90
+ return `'${specifier}' is for test files only (sequences/<id>/tests/*.test.ts); code a sequence runs imports '${RUNTIME_PACKAGE}'`;
91
+ }
84
92
  if (specifier.startsWith(`${RUNTIME_PACKAGE}/`))
85
93
  return `'${specifier}' is the platform's; company code imports '${RUNTIME_PACKAGE}'`;
86
94
  return `'${specifier}' is a package; company code imports only '${RUNTIME_PACKAGE}' and the repository's own files`;