@superpanel-sdk/runtime 0.0.1-internal.1

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 (169) hide show
  1. package/README.md +35 -0
  2. package/bin/superpanel-sdk-runtime.mjs +22 -0
  3. package/dist/builder/codegen/emit.d.ts +17 -0
  4. package/dist/builder/codegen/emit.js +143 -0
  5. package/dist/builder/codegen/generate.d.ts +21 -0
  6. package/dist/builder/codegen/generate.js +90 -0
  7. package/dist/builder/compile/compile-agenda.d.ts +15 -0
  8. package/dist/builder/compile/compile-agenda.js +59 -0
  9. package/dist/builder/compile/compile-sequence.d.ts +24 -0
  10. package/dist/builder/compile/compile-sequence.js +121 -0
  11. package/dist/builder/compile/function-code.d.ts +6 -0
  12. package/dist/builder/compile/function-code.js +30 -0
  13. package/dist/builder/compile/registry.d.ts +13 -0
  14. package/dist/builder/compile/registry.js +42 -0
  15. package/dist/builder/load.d.ts +22 -0
  16. package/dist/builder/load.js +169 -0
  17. package/dist/builder/merge.d.ts +4 -0
  18. package/dist/builder/merge.js +19 -0
  19. package/dist/builder/paths.d.ts +10 -0
  20. package/dist/builder/paths.js +22 -0
  21. package/dist/builder/types.d.ts +31 -0
  22. package/dist/builder/types.js +2 -0
  23. package/dist/cli/compile/index.d.ts +4 -0
  24. package/dist/cli/compile/index.js +11 -0
  25. package/dist/cli/index.d.ts +3 -0
  26. package/dist/cli/index.js +64 -0
  27. package/dist/cli/serve/index.d.ts +9 -0
  28. package/dist/cli/serve/index.js +340 -0
  29. package/dist/cli/type-gen/index.d.ts +5 -0
  30. package/dist/cli/type-gen/index.js +90 -0
  31. package/dist/compute-host/compute-host.d.ts +38 -0
  32. package/dist/compute-host/compute-host.js +45 -0
  33. package/dist/compute-host/index.d.ts +5 -0
  34. package/dist/compute-host/index.js +3 -0
  35. package/dist/compute-host/source-compute-host.d.ts +29 -0
  36. package/dist/compute-host/source-compute-host.js +72 -0
  37. package/dist/core/context/account-fields.d.ts +12 -0
  38. package/dist/core/context/account-fields.js +2 -0
  39. package/dist/core/context/contact.d.ts +60 -0
  40. package/dist/core/context/contact.js +34 -0
  41. package/dist/core/context/db.d.ts +69 -0
  42. package/dist/core/context/db.js +44 -0
  43. package/dist/core/context/docusign.d.ts +134 -0
  44. package/dist/core/context/docusign.js +108 -0
  45. package/dist/core/context/env.d.ts +9 -0
  46. package/dist/core/context/env.js +19 -0
  47. package/dist/core/context/filevine.d.ts +323 -0
  48. package/dist/core/context/filevine.js +254 -0
  49. package/dist/core/context/http.d.ts +9 -0
  50. package/dist/core/context/http.js +4 -0
  51. package/dist/core/context/hubspot.d.ts +250 -0
  52. package/dist/core/context/hubspot.js +191 -0
  53. package/dist/core/context/platform-registry.d.ts +67 -0
  54. package/dist/core/context/platform-registry.js +11 -0
  55. package/dist/core/context/platform.d.ts +33 -0
  56. package/dist/core/context/platform.js +2 -0
  57. package/dist/core/context/twilio.d.ts +50 -0
  58. package/dist/core/context/twilio.js +42 -0
  59. package/dist/core/context/types.d.ts +87 -0
  60. package/dist/core/context/types.js +9 -0
  61. package/dist/core/functions/define/case-context.d.ts +14 -0
  62. package/dist/core/functions/define/case-context.js +15 -0
  63. package/dist/core/functions/define/compute.d.ts +7 -0
  64. package/dist/core/functions/define/compute.js +17 -0
  65. package/dist/core/functions/define/custom.d.ts +4 -0
  66. package/dist/core/functions/define/custom.js +8 -0
  67. package/dist/core/functions/define/system.d.ts +7 -0
  68. package/dist/core/functions/define/system.js +12 -0
  69. package/dist/core/functions/func-ref.d.ts +16 -0
  70. package/dist/core/functions/func-ref.js +20 -0
  71. package/dist/core/functions/types.d.ts +78 -0
  72. package/dist/core/functions/types.js +5 -0
  73. package/dist/core/slot/compile-schema.d.ts +24 -0
  74. package/dist/core/slot/compile-schema.js +336 -0
  75. package/dist/core/slot/deps.d.ts +15 -0
  76. package/dist/core/slot/deps.js +88 -0
  77. package/dist/core/slot/derived.d.ts +32 -0
  78. package/dist/core/slot/derived.js +115 -0
  79. package/dist/core/slot/field.d.ts +36 -0
  80. package/dist/core/slot/field.js +97 -0
  81. package/dist/core/slot/id-ref.d.ts +4 -0
  82. package/dist/core/slot/id-ref.js +15 -0
  83. package/dist/core/slot/index.d.ts +15 -0
  84. package/dist/core/slot/index.js +14 -0
  85. package/dist/core/slot/path.d.ts +18 -0
  86. package/dist/core/slot/path.js +22 -0
  87. package/dist/core/slot/row.d.ts +22 -0
  88. package/dist/core/slot/row.js +54 -0
  89. package/dist/core/slot/schema.d.ts +102 -0
  90. package/dist/core/slot/schema.js +17 -0
  91. package/dist/core/slot/sf-schema.d.ts +23 -0
  92. package/dist/core/slot/sf-schema.js +125 -0
  93. package/dist/core/slot/sf-validate.d.ts +14 -0
  94. package/dist/core/slot/sf-validate.js +132 -0
  95. package/dist/core/slot/snapshot.d.ts +18 -0
  96. package/dist/core/slot/snapshot.js +138 -0
  97. package/dist/core/slot/types.d.ts +144 -0
  98. package/dist/core/slot/types.js +2 -0
  99. package/dist/core/slot/value.d.ts +9 -0
  100. package/dist/core/slot/value.js +97 -0
  101. package/dist/core/slot/write.d.ts +41 -0
  102. package/dist/core/slot/write.js +319 -0
  103. package/dist/core/stage/builders.d.ts +36 -0
  104. package/dist/core/stage/builders.js +28 -0
  105. package/dist/core/stage/condition.d.ts +17 -0
  106. package/dist/core/stage/condition.js +198 -0
  107. package/dist/core/stage/drive.d.ts +43 -0
  108. package/dist/core/stage/drive.js +77 -0
  109. package/dist/core/stage/finish-when.d.ts +20 -0
  110. package/dist/core/stage/finish-when.js +82 -0
  111. package/dist/core/stage/flatten.d.ts +27 -0
  112. package/dist/core/stage/flatten.js +464 -0
  113. package/dist/core/stage/index.d.ts +11 -0
  114. package/dist/core/stage/index.js +10 -0
  115. package/dist/core/stage/simulate.d.ts +24 -0
  116. package/dist/core/stage/simulate.js +33 -0
  117. package/dist/core/stage/transfer-fields.d.ts +14 -0
  118. package/dist/core/stage/transfer-fields.js +88 -0
  119. package/dist/core/stage/types.d.ts +177 -0
  120. package/dist/core/stage/types.js +2 -0
  121. package/dist/core/stage/validate.d.ts +11 -0
  122. package/dist/core/stage/validate.js +226 -0
  123. package/dist/core/stage/walk.d.ts +34 -0
  124. package/dist/core/stage/walk.js +96 -0
  125. package/dist/dev-overlay/protocol.d.ts +53 -0
  126. package/dist/dev-overlay/protocol.js +21 -0
  127. package/dist/fn-context/build-context.d.ts +11 -0
  128. package/dist/fn-context/build-context.js +21 -0
  129. package/dist/fn-context/fake/empty-api.d.ts +9 -0
  130. package/dist/fn-context/fake/empty-api.js +50 -0
  131. package/dist/fn-context/fake/index.d.ts +12 -0
  132. package/dist/fn-context/fake/index.js +22 -0
  133. package/dist/fn-context/index.d.ts +9 -0
  134. package/dist/fn-context/index.js +8 -0
  135. package/dist/fn-context/log.d.ts +8 -0
  136. package/dist/fn-context/log.js +29 -0
  137. package/dist/fn-context/make-ctx.d.ts +9 -0
  138. package/dist/fn-context/make-ctx.js +51 -0
  139. package/dist/fn-context/rpc/errors.d.ts +25 -0
  140. package/dist/fn-context/rpc/errors.js +23 -0
  141. package/dist/fn-context/rpc/index.d.ts +10 -0
  142. package/dist/fn-context/rpc/index.js +9 -0
  143. package/dist/fn-context/rpc/integration/index.d.ts +51 -0
  144. package/dist/fn-context/rpc/integration/index.js +19 -0
  145. package/dist/fn-context/rpc/integration/list-bindings.d.ts +21 -0
  146. package/dist/fn-context/rpc/integration/list-bindings.js +18 -0
  147. package/dist/fn-context/rpc/log.d.ts +36 -0
  148. package/dist/fn-context/rpc/log.js +16 -0
  149. package/dist/fn-context/rpc/platform.d.ts +28 -0
  150. package/dist/fn-context/rpc/platform.js +15 -0
  151. package/dist/fn-context/rpc/request-id.d.ts +5 -0
  152. package/dist/fn-context/rpc/request-id.js +13 -0
  153. package/dist/fn-context/rpc/trpc-client.d.ts +7 -0
  154. package/dist/fn-context/rpc/trpc-client.js +109 -0
  155. package/dist/fn-context/rpc/trpc-init.d.ts +17 -0
  156. package/dist/fn-context/rpc/trpc-init.js +17 -0
  157. package/dist/fn-context/rpc/trpc-router-factory.d.ts +84 -0
  158. package/dist/fn-context/rpc/trpc-router-factory.js +9 -0
  159. package/dist/fn-context/types.d.ts +17 -0
  160. package/dist/fn-context/types.js +2 -0
  161. package/dist/index.d.ts +47 -0
  162. package/dist/index.js +34 -0
  163. package/dist/voice-service/actions.d.ts +20 -0
  164. package/dist/voice-service/actions.js +2 -0
  165. package/dist/voice-service/index.d.ts +3 -0
  166. package/dist/voice-service/index.js +3 -0
  167. package/dist/voice-service/types.d.ts +1010 -0
  168. package/dist/voice-service/types.js +16 -0
  169. package/package.json +55 -0
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # @superpanel-sdk/runtime
2
+
3
+ Slot + Stage runtime used by company repos and the platform: schema, writes, derived recompute, agenda compile/walk/simulate, and company-repo CLI.
4
+
5
+ This package is currently published as an **internal prerelease**. Install a tagged build, not `latest`:
6
+
7
+ ```bash
8
+ npm i @superpanel-sdk/runtime@next
9
+ ```
10
+
11
+ Requires Node.js `>=20.12`.
12
+
13
+ ## CLI
14
+
15
+ ```bash
16
+ npx superpanel-sdk-runtime type:gen
17
+ npx superpanel-sdk-runtime type:gen --watch
18
+ npx superpanel-sdk-runtime type:gen --check
19
+ npx superpanel-sdk-runtime compile
20
+ npx superpanel-sdk-runtime compile --sequence <id>
21
+ npx superpanel-sdk-runtime serve
22
+ ```
23
+
24
+ `serve` reads `.env` from the current working directory:
25
+
26
+ - `SUPERPANEL_SDK_COMPANY_ID` / `--company`
27
+ - `SUPERPANEL_SDK_API_KEY` / `--api-key`
28
+ - `SUPERPANEL_SDK_BACKEND_URL` / `--url`
29
+
30
+ ## Imports
31
+
32
+ ```ts
33
+ import { makeCtx, applyWrites, createAppRouter } from '@superpanel-sdk/runtime';
34
+ import { createFakeApiHost } from '@superpanel-sdk/runtime/fn-context';
35
+ ```
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { spawnSync } from 'node:child_process';
4
+ import path from 'node:path';
5
+ import { fileURLToPath, pathToFileURL } from 'node:url';
6
+
7
+ const here = path.dirname(fileURLToPath(import.meta.url));
8
+ const runtimeRoot = path.join(here, '..');
9
+ const cli = path.join(runtimeRoot, 'dist', 'cli', 'index.js');
10
+
11
+ // Resolve tsx from @superpanel-sdk/runtime (not the company-repo cwd).
12
+ // Package export "." → dist/loader.mjs
13
+ const requireFromRuntime = createRequire(path.join(runtimeRoot, 'package.json'));
14
+ const tsxLoader = pathToFileURL(requireFromRuntime.resolve('tsx')).href;
15
+
16
+ const result = spawnSync(process.execPath, ['--import', tsxLoader, cli, ...process.argv.slice(2)], {
17
+ cwd: process.cwd(),
18
+ stdio: 'inherit',
19
+ env: process.env,
20
+ });
21
+
22
+ process.exit(result.status ?? 1);
@@ -0,0 +1,17 @@
1
+ import type { EffectiveSchema } from '../../core/slot/schema.js';
2
+ /** Emit `__gen/slots.type.ts` — Slots only (no CaseContext; avoids cycle with view.ts). */
3
+ export declare function emitSlotsSource(schema: EffectiveSchema): string;
4
+ /**
5
+ * Emit `__gen/case-context.type.ts`.
6
+ * Separate from slots.type.ts so dependencies stay one-way:
7
+ * view.ts → slots.type.ts
8
+ * case-context.type.ts → view.ts | slots.type.ts
9
+ * functions → case-context.type.ts
10
+ */
11
+ export declare function emitCaseContextSource(options: {
12
+ hasCaseContextView: boolean;
13
+ }): string;
14
+ /** Stub written when a sequence has no gen file yet. */
15
+ export declare function emitSlotsStub(): string;
16
+ export declare function emitCaseContextStub(): string;
17
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1,143 @@
1
+ import { slotFieldEntries } from '../../core/slot/row.js';
2
+ function quoteLiteral(v) {
3
+ return typeof v === 'number' ? String(v) : JSON.stringify(v);
4
+ }
5
+ function dataTypeToTs(dataType) {
6
+ switch (dataType) {
7
+ case 'string':
8
+ case 'date':
9
+ case 'datetime':
10
+ return 'string';
11
+ case 'number':
12
+ return 'number';
13
+ case 'boolean':
14
+ return 'boolean';
15
+ }
16
+ }
17
+ function valueTypeExpr(field) {
18
+ let base;
19
+ if (field.enum && field.enum.length > 0) {
20
+ base = field.enum.map(quoteLiteral).join(' | ');
21
+ }
22
+ else {
23
+ base = dataTypeToTs(field.dataType);
24
+ }
25
+ // Runtime envelopes always allow null on value (empty / declined / no conclusion).
26
+ if (field.nullable) {
27
+ return `${base} | null`;
28
+ }
29
+ return `${base} | null`;
30
+ }
31
+ function emitRowFields(fields) {
32
+ const fieldLines = [];
33
+ for (const [fieldName, field] of slotFieldEntries(fields)) {
34
+ const valueTs = valueTypeExpr(field);
35
+ fieldLines.push(` ${fieldName}: FieldValueBase & { value: ${valueTs} };`);
36
+ }
37
+ return fieldLines;
38
+ }
39
+ function emitTableType(tableName, rows, fields) {
40
+ const fieldLines = emitRowFields(fields);
41
+ const rowBody = ` id: string;\n${fieldLines.join('\n')}`;
42
+ if (rows === 'multi') {
43
+ return ` ${tableName}: {
44
+ ${rowBody}
45
+ }[];`;
46
+ }
47
+ return ` ${tableName}: {
48
+ ${rowBody}
49
+ };`;
50
+ }
51
+ /** Emit `__gen/slots.type.ts` — Slots only (no CaseContext; avoids cycle with view.ts). */
52
+ export function emitSlotsSource(schema) {
53
+ const tableBlocks = [];
54
+ for (const [tableName, table] of Object.entries(schema)) {
55
+ tableBlocks.push(emitTableType(tableName, table.rows, table.fields));
56
+ }
57
+ return `// GENERATED — do not edit
58
+ // Source: company schema + sequence slots → effective schema
59
+ // Regenerate: superpanel-sdk-runtime type:gen
60
+
61
+ export type FieldState = "empty" | "filled" | "asked_unknown" | "declined";
62
+
63
+ export type FieldHistoryEntry = {
64
+ value: string | number | boolean | null;
65
+ state: FieldState;
66
+ at: number;
67
+ by:
68
+ | "slot-filling"
69
+ | "derived"
70
+ | "function"
71
+ | "human"
72
+ | "import"
73
+ | "platform";
74
+ };
75
+
76
+ export type FieldValueBase = {
77
+ reason: string | null;
78
+ state: FieldState;
79
+ updatedAt: number;
80
+ updatedBy:
81
+ | "slot-filling"
82
+ | "derived"
83
+ | "function"
84
+ | "human"
85
+ | "import"
86
+ | "platform";
87
+ history: FieldHistoryEntry[];
88
+ };
89
+
90
+ export type Slots = {
91
+ current: {
92
+ contactId: string;
93
+ caseContactId: string;
94
+ caseFileId: string;
95
+ sessionId: string | null;
96
+ };
97
+ ${tableBlocks.join('\n')}
98
+ };
99
+ `;
100
+ }
101
+ /**
102
+ * Emit `__gen/case-context.type.ts`.
103
+ * Separate from slots.type.ts so dependencies stay one-way:
104
+ * view.ts → slots.type.ts
105
+ * case-context.type.ts → view.ts | slots.type.ts
106
+ * functions → case-context.type.ts
107
+ */
108
+ export function emitCaseContextSource(options) {
109
+ if (options.hasCaseContextView) {
110
+ return `// GENERATED — do not edit
111
+ // CaseContext from sequence view.ts
112
+ // Regenerate: superpanel-sdk-runtime type:gen
113
+
114
+ export type { CaseContext } from '../view.ts';
115
+ `;
116
+ }
117
+ return `// GENERATED — do not edit
118
+ // No view.ts — CaseContext is identity with Slots
119
+ // Regenerate: superpanel-sdk-runtime type:gen
120
+
121
+ import type { Slots } from './slots.type.ts';
122
+
123
+ export type CaseContext = Slots;
124
+ `;
125
+ }
126
+ /** Stub written when a sequence has no gen file yet. */
127
+ export function emitSlotsStub() {
128
+ return `// GENERATED — do not edit
129
+ // Stub — run: superpanel-sdk-runtime type:gen
130
+
131
+ export type Slots = Record<string, unknown>;
132
+ `;
133
+ }
134
+ export function emitCaseContextStub() {
135
+ return `// GENERATED — do not edit
136
+ // Stub — run: superpanel-sdk-runtime type:gen
137
+
138
+ import type { Slots } from './slots.type.ts';
139
+
140
+ export type CaseContext = Slots;
141
+ `;
142
+ }
143
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1,21 @@
1
+ import { listSequenceIds } from '../load.js';
2
+ export { listSequenceIds };
3
+ export type GenerateResult = {
4
+ sequenceId: string;
5
+ outPath: string;
6
+ caseContextOutPath: string;
7
+ source: string;
8
+ caseContextSource: string;
9
+ wrote: boolean;
10
+ };
11
+ export declare function generateSequence(repoRoot: string, sequenceId: string, options?: {
12
+ dryRun?: boolean;
13
+ }): Promise<GenerateResult>;
14
+ export declare function generateAll(repoRoot: string, options?: {
15
+ dryRun?: boolean;
16
+ sequenceIds?: string[];
17
+ }): Promise<GenerateResult[]>;
18
+ export declare function checkSequence(repoRoot: string, sequenceId: string): Promise<void>;
19
+ export declare function checkAll(repoRoot: string): Promise<void>;
20
+ export declare function ensureStub(repoRoot: string, sequenceId: string): void;
21
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1,90 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { listSequenceIds, loadCompanySchema, loadSequenceSlots } from '../load.js';
4
+ import { mergeEffectiveSchema } from '../merge.js';
5
+ import { findTsModule, resolveTsModule } from '../paths.js';
6
+ import { emitCaseContextSource, emitCaseContextStub, emitSlotsSource, emitSlotsStub } from './emit.js';
7
+ export { listSequenceIds };
8
+ function sequenceSlotsGenPath(repoRoot, sequenceId) {
9
+ return path.join(repoRoot, 'sequences', sequenceId, '__gen', 'slots.type.ts');
10
+ }
11
+ function sequenceCaseContextGenPath(repoRoot, sequenceId) {
12
+ return path.join(repoRoot, 'sequences', sequenceId, '__gen', 'case-context.type.ts');
13
+ }
14
+ export async function generateSequence(repoRoot, sequenceId, options = {}) {
15
+ const schemaPath = resolveTsModule(repoRoot, 'schema', `No company schema found. Expected schema.ts or schema/index.ts under ${repoRoot}`);
16
+ const slotsPath = resolveTsModule(path.join(repoRoot, 'sequences', sequenceId), 'slots', `No sequence slots found. Expected sequences/${sequenceId}/slots.ts or sequences/${sequenceId}/slots/index.ts`);
17
+ const company = await loadCompanySchema(schemaPath);
18
+ const slots = await loadSequenceSlots(slotsPath);
19
+ const effective = mergeEffectiveSchema(company, slots);
20
+ const sequenceDir = path.join(repoRoot, 'sequences', sequenceId);
21
+ const hasCaseContextView = findTsModule(sequenceDir, 'view') !== undefined;
22
+ const source = emitSlotsSource(effective);
23
+ const caseContextSource = emitCaseContextSource({ hasCaseContextView });
24
+ const outPath = sequenceSlotsGenPath(repoRoot, sequenceId);
25
+ const caseContextOutPath = sequenceCaseContextGenPath(repoRoot, sequenceId);
26
+ if (!options.dryRun) {
27
+ mkdirSync(path.dirname(outPath), { recursive: true });
28
+ writeFileSync(outPath, source, 'utf8');
29
+ writeFileSync(caseContextOutPath, caseContextSource, 'utf8');
30
+ }
31
+ return {
32
+ sequenceId,
33
+ outPath,
34
+ caseContextOutPath,
35
+ source,
36
+ caseContextSource,
37
+ wrote: !options.dryRun,
38
+ };
39
+ }
40
+ export async function generateAll(repoRoot, options = {}) {
41
+ const ids = options.sequenceIds ?? listSequenceIds(repoRoot);
42
+ if (ids.length === 0) {
43
+ throw new Error(`No sequences with slots found under ${path.join(repoRoot, 'sequences')} (expected slots.ts or slots/index.ts)`);
44
+ }
45
+ const results = [];
46
+ for (const sequenceId of ids) {
47
+ results.push(await generateSequence(repoRoot, sequenceId, options));
48
+ }
49
+ return results;
50
+ }
51
+ function assertFileMatches(outPath, next, repoRoot) {
52
+ let current = '';
53
+ try {
54
+ current = readFileSync(outPath, 'utf8');
55
+ }
56
+ catch {
57
+ throw new Error(`Missing ${outPath}; run: superpanel-sdk-runtime type:gen`);
58
+ }
59
+ if (current !== next) {
60
+ throw new Error(`${path.relative(repoRoot, outPath)} is stale. Run \`superpanel-sdk-runtime type:gen\`.`);
61
+ }
62
+ }
63
+ export async function checkSequence(repoRoot, sequenceId) {
64
+ const { outPath, caseContextOutPath, source, caseContextSource } = await generateSequence(repoRoot, sequenceId, {
65
+ dryRun: true,
66
+ });
67
+ assertFileMatches(outPath, source, repoRoot);
68
+ assertFileMatches(caseContextOutPath, caseContextSource, repoRoot);
69
+ }
70
+ export async function checkAll(repoRoot) {
71
+ const ids = listSequenceIds(repoRoot);
72
+ if (ids.length === 0) {
73
+ throw new Error(`No sequences with slots found under ${path.join(repoRoot, 'sequences')} (expected slots.ts or slots/index.ts)`);
74
+ }
75
+ for (const sequenceId of ids) {
76
+ await checkSequence(repoRoot, sequenceId);
77
+ }
78
+ }
79
+ export function ensureStub(repoRoot, sequenceId) {
80
+ const slotsPath = sequenceSlotsGenPath(repoRoot, sequenceId);
81
+ const caseContextPath = sequenceCaseContextGenPath(repoRoot, sequenceId);
82
+ mkdirSync(path.dirname(slotsPath), { recursive: true });
83
+ if (!existsSync(slotsPath)) {
84
+ writeFileSync(slotsPath, emitSlotsStub(), 'utf8');
85
+ }
86
+ if (!existsSync(caseContextPath)) {
87
+ writeFileSync(caseContextPath, emitCaseContextStub(), 'utf8');
88
+ }
89
+ }
90
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1,15 @@
1
+ import type { EffectiveSchema } from '../../core/slot/schema.js';
2
+ import type { CompiledSlotSchema, ValidationIssue } from '../../core/slot/types.js';
3
+ import type { FuncMap } from '../../core/functions/types.js';
4
+ import { fatalAgendaIssues, type CompiledAgenda } from '../../core/stage/index.js';
5
+ export type CompileAgendasResult = {
6
+ schema: CompiledSlotSchema;
7
+ effectiveSchema: EffectiveSchema;
8
+ agendas: Record<string, CompiledAgenda>;
9
+ issues: ValidationIssue[];
10
+ };
11
+ export declare function compileSequenceAgendas(schema: CompiledSlotSchema, raw: unknown, options?: {
12
+ functions?: FuncMap;
13
+ }): CompileAgendasResult;
14
+ export { fatalAgendaIssues };
15
+ //# sourceMappingURL=compile-agenda.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { toEffectiveSchema } from '../../core/slot/compile-schema.js';
2
+ import { collectTransferBlocks, fatalAgendaIssues, flattenAgendaPlacements, flattenAgendaTree, isAgendaTree, isSequenceAgendas, normalizeSequenceAgendas, registerTransferSessionFields, validateCompiledAgenda, } from '../../core/stage/index.js';
3
+ function asAgendaTrees(raw) {
4
+ if (isAgendaTree(raw))
5
+ return [raw];
6
+ if (Array.isArray(raw) && raw.length > 0 && raw.every(isAgendaTree))
7
+ return raw;
8
+ if (raw != null && typeof raw === 'object' && !Array.isArray(raw) && !isSequenceAgendas(raw)) {
9
+ const values = Object.values(raw);
10
+ if (values.length > 0 && values.every(isAgendaTree))
11
+ return values;
12
+ }
13
+ return null;
14
+ }
15
+ function compileOneFlat(agendaId, header, flattened, schema, functions, issues) {
16
+ issues.push(...flattened.issues);
17
+ const agenda = { header, flat: flattened.items };
18
+ const validated = validateCompiledAgenda(agenda, { schema, functions, agendaId });
19
+ if (!validated.ok)
20
+ issues.push(...validated.issues);
21
+ return agenda;
22
+ }
23
+ export function compileSequenceAgendas(schema, raw, options = {}) {
24
+ const issues = [];
25
+ if (raw == null) {
26
+ return { schema, effectiveSchema: toEffectiveSchema(schema), agendas: {}, issues };
27
+ }
28
+ const trees = asAgendaTrees(raw);
29
+ if (trees) {
30
+ const transferIds = collectTransferBlocks({}, trees.flatMap((tree) => tree.tree)).map((block) => block.id);
31
+ const withTransfer = registerTransferSessionFields(schema, transferIds);
32
+ const compiled = {};
33
+ for (const tree of trees) {
34
+ compiled[tree.id] = compileOneFlat(tree.id, tree.header, flattenAgendaTree(tree.tree, { functions: options.functions }), withTransfer, options.functions, issues);
35
+ }
36
+ return { schema: withTransfer, effectiveSchema: toEffectiveSchema(withTransfer), agendas: compiled, issues };
37
+ }
38
+ let agendasInput;
39
+ try {
40
+ agendasInput = isSequenceAgendas(raw) ? raw : normalizeSequenceAgendas(raw);
41
+ }
42
+ catch (error) {
43
+ issues.push({
44
+ code: 'invalid-agendas',
45
+ message: error instanceof Error ? error.message : String(error),
46
+ path: 'agendas',
47
+ });
48
+ return { schema, effectiveSchema: toEffectiveSchema(schema), agendas: {}, issues };
49
+ }
50
+ const transferIds = collectTransferBlocks(agendasInput.blocks).map((block) => block.id);
51
+ const withTransfer = registerTransferSessionFields(schema, transferIds);
52
+ const compiled = {};
53
+ for (const [agendaId, config] of Object.entries(agendasInput.agendas)) {
54
+ compiled[agendaId] = compileOneFlat(agendaId, config.header, flattenAgendaPlacements(config.placements, agendasInput.blocks, { functions: options.functions }), withTransfer, options.functions, issues);
55
+ }
56
+ return { schema: withTransfer, effectiveSchema: toEffectiveSchema(withTransfer), agendas: compiled, issues };
57
+ }
58
+ export { fatalAgendaIssues };
59
+ //# sourceMappingURL=compile-agenda.js.map
@@ -0,0 +1,24 @@
1
+ import type { FuncMap } from '../../core/functions/types.js';
2
+ import type { CompanySchema } from '../../core/slot/schema.js';
3
+ import type { SequenceBuild } from '../types.js';
4
+ /** Deep-clone company schema with derived computeFn normalized to string names. */
5
+ export declare function snapshotCompanySchema(company: CompanySchema, functions?: FuncMap): CompanySchema;
6
+ export declare function sequenceBuildPath(repoRoot: string, sequenceId: string): string;
7
+ export type CompileSequenceOptions = {
8
+ dryRun?: boolean;
9
+ /** When false, skip esbuild and omit registry `code` (local serve overlay). Default true. */
10
+ includeCode?: boolean;
11
+ /** Persist on SequenceBuild.sha. Defaults to `local`. */
12
+ sha?: string;
13
+ };
14
+ export type CompileSequenceResult = {
15
+ sequenceId: string;
16
+ outPath: string;
17
+ build: SequenceBuild;
18
+ wrote: boolean;
19
+ };
20
+ export declare function compileSequence(repoRoot: string, sequenceId: string, options?: CompileSequenceOptions): Promise<CompileSequenceResult>;
21
+ export declare function compileAll(repoRoot: string, options?: CompileSequenceOptions & {
22
+ sequenceIds?: string[];
23
+ }): Promise<CompileSequenceResult[]>;
24
+ //# sourceMappingURL=compile-sequence.d.ts.map
@@ -0,0 +1,121 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { resolveCaseContextViewFn } from '../../core/functions/define/case-context.js';
5
+ import { resolveFuncName } from '../../core/functions/func-ref.js';
6
+ import { compileSlotSchema } from '../../core/slot/compile-schema.js';
7
+ import { listSequenceIds, loadCompanySchema, loadSequenceAgendas, loadSequenceCaseContextView, loadSequenceFunctions, loadSequenceSlots, } from '../load.js';
8
+ import { findTsModule, resolveTsModule } from '../paths.js';
9
+ import { compileSequenceAgendas, fatalAgendaIssues } from './compile-agenda.js';
10
+ import { toCaseContextViewRegistry, toFunctionRegistry } from './registry.js';
11
+ const FATAL_CODES = new Set([
12
+ 'unknown-table',
13
+ 'unknown-field',
14
+ 'missing-session',
15
+ 'missing-compute-fn',
16
+ 'cyclic-dependency',
17
+ 'multi-derived-forbidden',
18
+ 'session-derived-forbidden',
19
+ 'unknown-ref-table',
20
+ 'invalid-id-field',
21
+ 'missing-id-field',
22
+ 'id-cannot-ref',
23
+ 'reserved-table-name',
24
+ ]);
25
+ function runtimePackageVersion() {
26
+ const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'package.json');
27
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
28
+ return pkg.version ?? '0.0.0';
29
+ }
30
+ /** Deep-clone company schema with derived computeFn normalized to string names. */
31
+ export function snapshotCompanySchema(company, functions) {
32
+ const tables = {};
33
+ for (const [tableName, table] of Object.entries(company)) {
34
+ const fields = {};
35
+ for (const [fieldName, field] of Object.entries(table.fields)) {
36
+ if (field.derived) {
37
+ fields[fieldName] = {
38
+ ...field,
39
+ computeFn: resolveFuncName(field.computeFn, functions),
40
+ };
41
+ }
42
+ else {
43
+ fields[fieldName] = { ...field };
44
+ }
45
+ }
46
+ tables[tableName] = { ...table, fields };
47
+ }
48
+ return tables;
49
+ }
50
+ export function sequenceBuildPath(repoRoot, sequenceId) {
51
+ return path.join(repoRoot, 'sequences', sequenceId, 'build', 'sequence-build.json');
52
+ }
53
+ export async function compileSequence(repoRoot, sequenceId, options = {}) {
54
+ const schemaPath = resolveTsModule(repoRoot, 'schema', `No company schema found. Expected schema.ts or schema/index.ts under ${repoRoot}`);
55
+ const sequenceDir = path.join(repoRoot, 'sequences', sequenceId);
56
+ const slotsPath = resolveTsModule(sequenceDir, 'slots', `No sequence slots found. Expected sequences/${sequenceId}/slots.ts or sequences/${sequenceId}/slots/index.ts`);
57
+ const functionsPath = findTsModule(sequenceDir, 'functions');
58
+ if (!functionsPath) {
59
+ throw new Error(`No sequence functions found. Expected sequences/${sequenceId}/functions.ts or sequences/${sequenceId}/functions/index.ts`);
60
+ }
61
+ const company = await loadCompanySchema(schemaPath);
62
+ const slots = await loadSequenceSlots(slotsPath);
63
+ const functions = await loadSequenceFunctions(functionsPath);
64
+ const viewPath = findTsModule(sequenceDir, 'view');
65
+ const caseContextView = viewPath ? await loadSequenceCaseContextView(viewPath) : undefined;
66
+ if (viewPath && !resolveCaseContextViewFn(caseContextView)) {
67
+ throw new Error(`sequences/${sequenceId}/view.ts did not export a caseContextView function`);
68
+ }
69
+ const { schema, validation } = compileSlotSchema(company, slots, {
70
+ functions,
71
+ computeFns: new Set(Object.keys(functions)),
72
+ });
73
+ if (!validation.ok) {
74
+ const fatal = validation.issues.filter((i) => FATAL_CODES.has(i.code));
75
+ if (fatal.length > 0) {
76
+ throw new Error(fatal.map((i) => i.message).join('; '));
77
+ }
78
+ }
79
+ const agendasPath = findTsModule(sequenceDir, 'agendas');
80
+ const rawAgendas = agendasPath ? await loadSequenceAgendas(agendasPath) : null;
81
+ const compiledAgendas = compileSequenceAgendas(schema, rawAgendas, { functions });
82
+ const fatalAgenda = fatalAgendaIssues(compiledAgendas.issues);
83
+ if (fatalAgenda.length > 0) {
84
+ throw new Error(fatalAgenda.map((i) => i.message).join('; '));
85
+ }
86
+ const includeCode = options.includeCode ?? true;
87
+ const [functionsRegistry, caseContextViewEntry] = await Promise.all([
88
+ toFunctionRegistry(functions, { includeCode }),
89
+ toCaseContextViewRegistry(caseContextView, { includeCode }),
90
+ ]);
91
+ const build = {
92
+ sequenceId,
93
+ sha: options.sha ?? 'local',
94
+ engineVersion: runtimePackageVersion(),
95
+ compiledAt: new Date().toISOString(),
96
+ companySchemaSnapshot: snapshotCompanySchema(company, functions),
97
+ schema: compiledAgendas.schema,
98
+ effectiveSchema: compiledAgendas.effectiveSchema,
99
+ functions: functionsRegistry,
100
+ caseContextView: caseContextViewEntry,
101
+ agendas: compiledAgendas.agendas,
102
+ };
103
+ const outPath = sequenceBuildPath(repoRoot, sequenceId);
104
+ if (!options.dryRun) {
105
+ mkdirSync(path.dirname(outPath), { recursive: true });
106
+ writeFileSync(outPath, `${JSON.stringify(build, null, 2)}\n`, 'utf8');
107
+ }
108
+ return { sequenceId, outPath, build, wrote: !options.dryRun };
109
+ }
110
+ export async function compileAll(repoRoot, options = {}) {
111
+ const ids = options.sequenceIds ?? listSequenceIds(repoRoot);
112
+ if (ids.length === 0) {
113
+ throw new Error(`No sequences with slots found under ${path.join(repoRoot, 'sequences')} (expected slots.ts or slots/index.ts)`);
114
+ }
115
+ const results = [];
116
+ for (const sequenceId of ids) {
117
+ results.push(await compileSequence(repoRoot, sequenceId, options));
118
+ }
119
+ return results;
120
+ }
121
+ //# sourceMappingURL=compile-sequence.js.map
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Compile a single function implementation to a standalone JS expression string
3
+ * suitable for QuickJS `eval` / registry `code` fields (minified).
4
+ */
5
+ export declare function compileFunctionCode(fn: (...args: never[]) => unknown): Promise<string>;
6
+ //# sourceMappingURL=function-code.d.ts.map
@@ -0,0 +1,30 @@
1
+ import * as esbuild from 'esbuild';
2
+ /**
3
+ * Compile a single function implementation to a standalone JS expression string
4
+ * suitable for QuickJS `eval` / registry `code` fields (minified).
5
+ */
6
+ export async function compileFunctionCode(fn) {
7
+ const raw = fn.toString().trim();
8
+ // No `format:` — esbuild emits `export default <expr>;` (stable to strip).
9
+ const result = await esbuild.transform(`export default ${raw}`, {
10
+ loader: 'js',
11
+ target: 'es2022',
12
+ minify: true,
13
+ logLevel: 'silent',
14
+ });
15
+ const text = result.code.trim();
16
+ if (text.includes('@superpanel-sdk/runtime') ||
17
+ text.includes('defineComputeFunc') ||
18
+ text.includes('defineCustomFunc') ||
19
+ text.includes('defineBoolComputeFunc') ||
20
+ text.includes('defineSystemFunc') ||
21
+ text.includes('defineCaseContext')) {
22
+ throw new Error('compiled function code still references define* / @superpanel-sdk/runtime');
23
+ }
24
+ const m = /^export\s+default\s*/.exec(text);
25
+ if (!m) {
26
+ throw new Error(`Unexpected esbuild emit (expected export default …):\n${text}`);
27
+ }
28
+ return text.slice(m[0].length).replace(/;?\s*$/, '');
29
+ }
30
+ //# sourceMappingURL=function-code.js.map
@@ -0,0 +1,13 @@
1
+ import type { CaseContextViewRegistryEntry, FuncMap, FunctionRegistry } from '../../core/functions/types.js';
2
+ export type BuildRegistryOptions = {
3
+ /** When false, skip esbuild and omit `code` (local serve overlay). Default true. */
4
+ includeCode?: boolean;
5
+ };
6
+ /**
7
+ * Project author FuncMap → JSON-safe registry.
8
+ * Published builds include per-function compiled `code`; overlay omits it.
9
+ */
10
+ export declare function toFunctionRegistry(functions: FuncMap, options?: BuildRegistryOptions): Promise<FunctionRegistry>;
11
+ /** Compile optional caseContextView to registry entry. */
12
+ export declare function toCaseContextViewRegistry(view: unknown, options?: BuildRegistryOptions): Promise<CaseContextViewRegistryEntry | null>;
13
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1,42 @@
1
+ import { resolveCaseContextViewFn } from '../../core/functions/define/case-context.js';
2
+ import { compileFunctionCode } from './function-code.js';
3
+ function withCode(entry, code) {
4
+ if (code === undefined)
5
+ return entry;
6
+ return { ...entry, code };
7
+ }
8
+ /**
9
+ * Project author FuncMap → JSON-safe registry.
10
+ * Published builds include per-function compiled `code`; overlay omits it.
11
+ */
12
+ export async function toFunctionRegistry(functions, options = {}) {
13
+ const includeCode = options.includeCode ?? true;
14
+ const out = {};
15
+ for (const [name, def] of Object.entries(functions)) {
16
+ const code = includeCode ? await compileFunctionCode(def.main) : undefined;
17
+ let entry;
18
+ if (def.kind === 'custom') {
19
+ entry = withCode({ kind: 'custom', writes: [] }, code);
20
+ }
21
+ else if (def.kind === 'system') {
22
+ entry = withCode({ kind: 'system' }, code);
23
+ }
24
+ else {
25
+ entry = withCode({ kind: def.kind }, code);
26
+ }
27
+ out[name] = entry;
28
+ }
29
+ return out;
30
+ }
31
+ /** Compile optional caseContextView to registry entry. */
32
+ export async function toCaseContextViewRegistry(view, options = {}) {
33
+ const fn = resolveCaseContextViewFn(view);
34
+ if (!fn)
35
+ return null;
36
+ if (!(options.includeCode ?? true)) {
37
+ return { kind: 'caseContextView' };
38
+ }
39
+ const code = await compileFunctionCode(fn);
40
+ return { kind: 'caseContextView', code };
41
+ }
42
+ //# sourceMappingURL=registry.js.map