@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
@@ -0,0 +1,177 @@
1
+ import type { TopLevelCondition } from 'json-rules-engine';
2
+ import type { FuncRef } from '../functions/func-ref.js';
3
+ import type { FieldPath } from '../slot/path.js';
4
+ export type Channel = 'call' | 'sms' | 'email' | 'webchat';
5
+ /** Nested condition from the engine (`all` members): leaf or `TopLevelCondition`. */
6
+ export type Condition = Extract<TopLevelCondition, {
7
+ all: unknown;
8
+ }>['all'][number];
9
+ export type JsonRulesCondition = Condition;
10
+ /**
11
+ * Shared by applyWhen and finishWhen:
12
+ * json-rules object, JSON string, boolFunction, or null (always).
13
+ */
14
+ export type When = FuncRef | Condition | Condition[] | null;
15
+ export type ApplyWhen = When;
16
+ export type FinishWhen = When;
17
+ /** Compile-time sentinel for branch()/switchOn(); expanded before flatten. */
18
+ export type OtherwiseSentinel = {
19
+ op: 'otherwise';
20
+ notAny?: When[];
21
+ };
22
+ export type AuthoringWhen = When | OtherwiseSentinel;
23
+ export type CompiledWhen = {
24
+ kind: 'always';
25
+ } | {
26
+ kind: 'fn';
27
+ fn: string;
28
+ } | {
29
+ kind: 'rules';
30
+ condition: JsonRulesCondition;
31
+ };
32
+ export type OnNoProgress = {
33
+ maxTurns: number;
34
+ action: 'move-on' | 'handoff' | 'schedule-callback';
35
+ };
36
+ export type FirstMessage = {
37
+ kind: 'template';
38
+ text: string;
39
+ } | {
40
+ kind: 'fn';
41
+ fn: string;
42
+ };
43
+ export type Interrupt = {
44
+ id: string;
45
+ label: string;
46
+ tool: {
47
+ name: string;
48
+ description: string;
49
+ };
50
+ action: {
51
+ type: 'transfer';
52
+ numbers: string[];
53
+ mode: 'cold' | 'warm';
54
+ } | {
55
+ type: 'switch-language';
56
+ languages: string[];
57
+ };
58
+ priority: number;
59
+ };
60
+ export type AgendaHeader = {
61
+ channel: Channel;
62
+ systemPrompt: string | null;
63
+ firstMessage: FirstMessage | null;
64
+ firstMessageMode: 'assistant-speaks-first' | 'user-speaks-first' | null;
65
+ voicemailPrompt: string | null;
66
+ interrupts: Interrupt[];
67
+ };
68
+ export type TopicBlock = {
69
+ kind: 'topic';
70
+ id: string;
71
+ label: string;
72
+ instructions: string;
73
+ fields: FieldPath[] | null;
74
+ finishWhen: FinishWhen;
75
+ onNoProgress: OnNoProgress | null;
76
+ };
77
+ export type ActionBlock = {
78
+ kind: 'action';
79
+ id: string;
80
+ label: string;
81
+ run: FuncRef;
82
+ finishWhen: FinishWhen;
83
+ say: string | null;
84
+ };
85
+ export type TransferBlock = {
86
+ kind: 'transfer';
87
+ id: string;
88
+ label: string;
89
+ numbers: string[];
90
+ mode: 'cold' | 'warm';
91
+ say: string;
92
+ unsuccessfulSay: string | null;
93
+ };
94
+ export type AgendaBlock = TopicBlock | ActionBlock | TransferBlock;
95
+ export type CompiledTopicBlock = Omit<TopicBlock, 'fields' | 'finishWhen'> & {
96
+ fields: FieldPath[];
97
+ finishWhen: CompiledWhen;
98
+ };
99
+ export type CompiledActionBlock = Omit<ActionBlock, 'run' | 'finishWhen'> & {
100
+ run: string;
101
+ finishWhen: CompiledWhen;
102
+ };
103
+ export type CompiledTransferBlock = TransferBlock & {
104
+ finishWhen: CompiledWhen;
105
+ resultField: FieldPath;
106
+ };
107
+ export type CompiledAgendaBlock = CompiledTopicBlock | CompiledActionBlock | CompiledTransferBlock;
108
+ export type SectionPlacement = {
109
+ kind: 'section';
110
+ placementId: string;
111
+ label: string;
112
+ applyWhen: AuthoringWhen;
113
+ children: Placement[];
114
+ };
115
+ export type NodePlacement = {
116
+ kind: 'node';
117
+ placementId: string;
118
+ blockId: string;
119
+ applyWhen: AuthoringWhen;
120
+ };
121
+ export type Placement = SectionPlacement | NodePlacement;
122
+ export type AgendaConfig = {
123
+ id: string;
124
+ header: AgendaHeader | null;
125
+ placements: Placement[];
126
+ };
127
+ export type SequenceAgendas = {
128
+ blocks: Record<string, AgendaBlock>;
129
+ agendas: Record<string, AgendaConfig>;
130
+ };
131
+ export type FlatNodePlacement = {
132
+ placementId: string;
133
+ applyWhen: CompiledWhen;
134
+ groupPath: string[];
135
+ };
136
+ export type FlatTopicItem = CompiledTopicBlock & FlatNodePlacement;
137
+ export type FlatActionItem = CompiledActionBlock & FlatNodePlacement;
138
+ export type FlatTransferItem = CompiledTransferBlock & FlatNodePlacement;
139
+ export type FlatAgendaItem = FlatTopicItem | FlatActionItem | FlatTransferItem;
140
+ export type CompiledAgenda = {
141
+ header: AgendaHeader | null;
142
+ flat: FlatAgendaItem[];
143
+ };
144
+ export type TopicNode = TopicBlock & {
145
+ applyWhen: AuthoringWhen;
146
+ };
147
+ export type ActionNode = ActionBlock & {
148
+ applyWhen: AuthoringWhen;
149
+ };
150
+ export type TransferNode = TransferBlock & {
151
+ applyWhen: AuthoringWhen;
152
+ };
153
+ export type SectionNode = {
154
+ kind: 'section';
155
+ id: string;
156
+ label: string;
157
+ applyWhen: AuthoringWhen;
158
+ children: AuthoringNode[];
159
+ };
160
+ export type BranchNode = {
161
+ kind: 'branch';
162
+ children: AuthoringNode[];
163
+ };
164
+ export type SwitchOnNode = {
165
+ kind: 'switchOn';
166
+ field: FieldPath;
167
+ cases: Record<string, AuthoringNode[]>;
168
+ otherwise?: AuthoringNode[];
169
+ };
170
+ export type AuthoringNode = TopicNode | ActionNode | TransferNode | SectionNode | BranchNode | SwitchOnNode;
171
+ export type AgendaTree = {
172
+ kind: 'agenda';
173
+ id: string;
174
+ header: AgendaHeader | null;
175
+ tree: AuthoringNode[];
176
+ };
177
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,11 @@
1
+ import type { FuncMap } from '../functions/types.js';
2
+ import type { CompiledSlotSchema, ValidationIssue, ValidationResult } from '../slot/types.js';
3
+ import type { CompiledAgenda } from './types.js';
4
+ export type ValidateAgendaOptions = {
5
+ schema: CompiledSlotSchema;
6
+ functions?: FuncMap;
7
+ agendaId?: string;
8
+ };
9
+ export declare function validateCompiledAgenda(compiled: CompiledAgenda, options: ValidateAgendaOptions): ValidationResult;
10
+ export declare function fatalAgendaIssues(issues: ValidationIssue[]): ValidationIssue[];
11
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1,226 @@
1
+ import { getCompiledTable } from '../slot/compile-schema.js';
2
+ import { parseFieldPath } from '../slot/path.js';
3
+ import { extractTemplateFields } from './condition.js';
4
+ import { whenFields } from './finish-when.js';
5
+ import { LAST_TRANSFER_RESULT_FIELD } from './transfer-fields.js';
6
+ function fieldExists(schema, path) {
7
+ const parsed = parseFieldPath(path);
8
+ if (!parsed)
9
+ return false;
10
+ return getCompiledTable(schema, parsed.table)?.fields[parsed.field] != null;
11
+ }
12
+ function requireFields(schema, fields, issues, path, code = 'unknown-field') {
13
+ for (const field of fields) {
14
+ if (!parseFieldPath(field)) {
15
+ issues.push({ code: 'invalid-field-path', message: `Invalid field path: ${field}`, path: `${path}:${field}` });
16
+ continue;
17
+ }
18
+ if (!fieldExists(schema, field)) {
19
+ issues.push({ code, message: `Unknown field: ${field}`, path: `${path}:${field}` });
20
+ }
21
+ }
22
+ }
23
+ function earlierCollected(items, index) {
24
+ const collected = new Set();
25
+ for (let i = 0; i < index; i++) {
26
+ const item = items[i];
27
+ if (item.kind === 'topic') {
28
+ for (const field of item.fields)
29
+ collected.add(field);
30
+ }
31
+ }
32
+ return collected;
33
+ }
34
+ function transferIndexByResultField(items) {
35
+ const map = new Map();
36
+ items.forEach((item, index) => {
37
+ if (item.kind === 'transfer') {
38
+ map.set(item.resultField, index);
39
+ }
40
+ });
41
+ return map;
42
+ }
43
+ function listedCustomFunctions(functions) {
44
+ const names = Object.entries(functions)
45
+ .filter(([, def]) => def.kind === 'custom')
46
+ .map(([name]) => name)
47
+ .sort((a, b) => a.localeCompare(b));
48
+ return names.length > 0 ? names.join(', ') : 'none';
49
+ }
50
+ function requireBoolWhen(when, functions, issues, path, label) {
51
+ if (when.kind === 'fn') {
52
+ const def = functions?.[when.fn];
53
+ if (functions && !def) {
54
+ issues.push({ code: 'unknown-function', message: `${label} fn not found: ${when.fn}`, path });
55
+ }
56
+ else if (def && def.kind !== 'boolCompute') {
57
+ issues.push({
58
+ code: label === 'applyWhen' ? 'apply-when-not-bool' : 'finish-when-not-bool',
59
+ message: `${label} fn '${when.fn}' must be defineBoolComputeFunc`,
60
+ path,
61
+ });
62
+ }
63
+ return;
64
+ }
65
+ }
66
+ function firstTransferIndex(items) {
67
+ return items.findIndex((item) => item.kind === 'transfer');
68
+ }
69
+ export function validateCompiledAgenda(compiled, options) {
70
+ const issues = [];
71
+ const { schema, functions } = options;
72
+ const prefix = options.agendaId ?? 'agenda';
73
+ const items = compiled.flat;
74
+ const seenPlacement = new Set();
75
+ const transferByResult = transferIndexByResultField(items);
76
+ const firstTransfer = firstTransferIndex(items);
77
+ if (compiled.header?.channel && compiled.header.channel !== 'call') {
78
+ for (const item of items) {
79
+ if (item.kind === 'transfer') {
80
+ issues.push({
81
+ code: 'transfer-channel',
82
+ message: `Transfer ${item.id} is only valid on call agendas`,
83
+ path: `${prefix}/${item.placementId}`,
84
+ });
85
+ }
86
+ }
87
+ }
88
+ if (compiled.header?.firstMessage?.kind === 'template') {
89
+ requireFields(schema, extractTemplateFields(compiled.header.firstMessage.text), issues, `${prefix}/header/firstMessage`);
90
+ }
91
+ if (compiled.header?.firstMessage?.kind === 'fn') {
92
+ const name = compiled.header.firstMessage.fn;
93
+ const def = functions?.[name];
94
+ if (functions && !def) {
95
+ issues.push({
96
+ code: 'unknown-function',
97
+ message: `firstMessage fn not found: ${name}`,
98
+ path: `${prefix}/header/firstMessage`,
99
+ });
100
+ }
101
+ else if (def && def.kind !== 'system') {
102
+ issues.push({
103
+ code: 'invalid-function-kind',
104
+ message: `firstMessage fn must be a system function: ${name}`,
105
+ path: `${prefix}/header/firstMessage`,
106
+ });
107
+ }
108
+ }
109
+ for (let index = 0; index < items.length; index++) {
110
+ const item = items[index];
111
+ const path = `${prefix}/${item.placementId}`;
112
+ if (seenPlacement.has(item.placementId)) {
113
+ issues.push({ code: 'duplicate-placement', message: `Duplicate placementId: ${item.placementId}`, path });
114
+ }
115
+ seenPlacement.add(item.placementId);
116
+ requireFields(schema, whenFields(item.applyWhen), issues, `${path}/applyWhen`);
117
+ const collected = earlierCollected(items, index);
118
+ for (const field of whenFields(item.applyWhen)) {
119
+ if (field.startsWith('session.transfer_') && field.endsWith('_result')) {
120
+ const writer = transferByResult.get(field);
121
+ if (writer == null || writer >= index) {
122
+ issues.push({
123
+ code: 'transfer-result-before-node',
124
+ message: `applyWhen reads ${field} before the transfer node`,
125
+ path: `${path}/applyWhen`,
126
+ });
127
+ }
128
+ continue;
129
+ }
130
+ if (field === LAST_TRANSFER_RESULT_FIELD) {
131
+ if (firstTransfer < 0 || firstTransfer >= index) {
132
+ issues.push({
133
+ code: 'transfer-result-before-node',
134
+ message: `applyWhen reads ${LAST_TRANSFER_RESULT_FIELD} before any transfer`,
135
+ path: `${path}/applyWhen`,
136
+ });
137
+ }
138
+ continue;
139
+ }
140
+ const parsed = parseFieldPath(field);
141
+ const def = parsed ? getCompiledTable(schema, parsed.table)?.fields[parsed.field] : undefined;
142
+ if (def?.derived)
143
+ continue;
144
+ if (def && !def.derived && def.source === 'system')
145
+ continue;
146
+ if (!collected.has(field)) {
147
+ issues.push({
148
+ code: 'fork-field-not-collected',
149
+ message: `applyWhen field ${field} is not collected by an earlier topic`,
150
+ path: `${path}/applyWhen`,
151
+ });
152
+ }
153
+ }
154
+ requireBoolWhen(item.applyWhen, functions, issues, `${path}/applyWhen`, 'applyWhen');
155
+ if (item.kind === 'topic') {
156
+ requireFields(schema, item.fields, issues, `${path}/fields`);
157
+ const referenced = whenFields(item.finishWhen);
158
+ requireFields(schema, referenced, issues, `${path}/finishWhen`);
159
+ requireBoolWhen(item.finishWhen, functions, issues, `${path}/finishWhen`, 'finishWhen');
160
+ if (item.finishWhen.kind !== 'fn') {
161
+ for (const field of referenced) {
162
+ if (!item.fields.includes(field)) {
163
+ issues.push({
164
+ code: 'finish-when-not-in-fields',
165
+ message: `finishWhen field ${field} is not in topic fields`,
166
+ path: `${path}/finishWhen`,
167
+ });
168
+ }
169
+ }
170
+ }
171
+ }
172
+ if (item.kind === 'action') {
173
+ requireBoolWhen(item.finishWhen, functions, issues, `${path}/finishWhen`, 'finishWhen');
174
+ if (item.finishWhen.kind === 'rules') {
175
+ requireFields(schema, whenFields(item.finishWhen), issues, `${path}/finishWhen`);
176
+ }
177
+ const run = functions?.[item.run];
178
+ if (functions && !run) {
179
+ issues.push({
180
+ code: 'unknown-function',
181
+ message: `Action '${item.id}' runs unknown function '${item.run}'. Custom functions: ${listedCustomFunctions(functions)}`,
182
+ path: `${path}/run`,
183
+ });
184
+ }
185
+ else if (run && run.kind !== 'custom') {
186
+ issues.push({
187
+ code: 'action-run-not-custom',
188
+ message: `Action '${item.id}' runs '${item.run}', which is ${run.kind}. Actions must use defineCustomFunc.`,
189
+ path: `${path}/run`,
190
+ });
191
+ }
192
+ }
193
+ if (item.kind === 'transfer') {
194
+ for (const number of item.numbers) {
195
+ requireFields(schema, extractTemplateFields(number), issues, `${path}/numbers`);
196
+ }
197
+ requireFields(schema, [item.resultField, LAST_TRANSFER_RESULT_FIELD], issues, `${path}/result`);
198
+ }
199
+ }
200
+ return issues.length === 0 ? { ok: true } : { ok: false, issues };
201
+ }
202
+ const FATAL_AGENDA_CODES = new Set([
203
+ 'unknown-block',
204
+ 'unknown-field',
205
+ 'invalid-field-path',
206
+ 'invalid-finish-when',
207
+ 'unknown-function',
208
+ 'finish-when-not-bool',
209
+ 'apply-when-not-bool',
210
+ 'invalid-apply-when',
211
+ 'finish-when-not-in-fields',
212
+ 'fork-field-not-collected',
213
+ 'otherwise-not-unique',
214
+ 'otherwise-not-last',
215
+ 'branch-no-explicit',
216
+ 'otherwise-unexpanded',
217
+ 'transfer-channel',
218
+ 'transfer-result-before-node',
219
+ 'action-run-not-custom',
220
+ 'duplicate-placement',
221
+ 'block-kind-mismatch',
222
+ ]);
223
+ export function fatalAgendaIssues(issues) {
224
+ return issues.filter((issue) => FATAL_AGENDA_CODES.has(issue.code));
225
+ }
226
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1,34 @@
1
+ import type { ComputeHost } from '../../compute-host/compute-host.js';
2
+ import type { FieldPath } from '../slot/path.js';
3
+ import type { RuntimeSlotsSnapshot } from '../slot/types.js';
4
+ import type { FlatAgendaItem } from './types.js';
5
+ export type WalkSkipReason = 'folded' | 'done' | 'skipped';
6
+ export type WalkSkip = {
7
+ placementId: string;
8
+ blockId: string;
9
+ reason: WalkSkipReason;
10
+ };
11
+ export type WalkHitReason = 'sticky' | 'scan';
12
+ export type WalkResult = {
13
+ hit: FlatAgendaItem | null;
14
+ reason: WalkHitReason | 'complete';
15
+ skipped: WalkSkip[];
16
+ decisions: WalkDecision[];
17
+ };
18
+ export type WalkDecision = {
19
+ placementId: string;
20
+ blockId: string;
21
+ status: 'folded' | 'done' | 'hit' | 'skipped';
22
+ via: WalkHitReason;
23
+ applyWhen: boolean | null;
24
+ finishWhen: boolean | null;
25
+ };
26
+ export type WalkOptions = {
27
+ currentPlacementId?: string | null;
28
+ /** This-tick skips (action returned null). */
29
+ skipPlacementIds?: ReadonlySet<string>;
30
+ compute?: ComputeHost;
31
+ };
32
+ export declare function walkAgenda(items: FlatAgendaItem[], snapshot: RuntimeSlotsSnapshot, options?: WalkOptions): Promise<WalkResult>;
33
+ export declare function unresolvedFinishWhenFields(item: FlatAgendaItem, snapshot: RuntimeSlotsSnapshot, compute?: ComputeHost): Promise<FieldPath[]>;
34
+ //# sourceMappingURL=walk.d.ts.map
@@ -0,0 +1,96 @@
1
+ import { evaluateWhen } from './finish-when.js';
2
+ function startsWithGroup(groupPath, prefix) {
3
+ if (prefix.length === 0)
4
+ return true;
5
+ if (groupPath.length < prefix.length)
6
+ return false;
7
+ return prefix.every((id, i) => groupPath[i] === id);
8
+ }
9
+ async function consider(item, snapshot, compute, skip, via, skipped, decisions) {
10
+ if (skip.has(item.placementId)) {
11
+ skipped.push({ placementId: item.placementId, blockId: item.id, reason: 'skipped' });
12
+ decisions.push({
13
+ placementId: item.placementId,
14
+ blockId: item.id,
15
+ status: 'skipped',
16
+ via,
17
+ applyWhen: null,
18
+ finishWhen: null,
19
+ });
20
+ return 'skip';
21
+ }
22
+ const applies = await evaluateWhen(item.applyWhen, snapshot, compute);
23
+ if (!applies.pass) {
24
+ skipped.push({ placementId: item.placementId, blockId: item.id, reason: 'folded' });
25
+ decisions.push({
26
+ placementId: item.placementId,
27
+ blockId: item.id,
28
+ status: 'folded',
29
+ via,
30
+ applyWhen: false,
31
+ finishWhen: null,
32
+ });
33
+ return 'fold';
34
+ }
35
+ const finished = await evaluateWhen(item.finishWhen, snapshot, compute);
36
+ if (finished.done) {
37
+ skipped.push({ placementId: item.placementId, blockId: item.id, reason: 'done' });
38
+ decisions.push({
39
+ placementId: item.placementId,
40
+ blockId: item.id,
41
+ status: 'done',
42
+ via,
43
+ applyWhen: true,
44
+ finishWhen: true,
45
+ });
46
+ return 'done';
47
+ }
48
+ decisions.push({
49
+ placementId: item.placementId,
50
+ blockId: item.id,
51
+ status: 'hit',
52
+ via,
53
+ applyWhen: true,
54
+ finishWhen: false,
55
+ });
56
+ return 'hit';
57
+ }
58
+ async function firstHit(items, snapshot, compute, skip, via, skipped, decisions, considered) {
59
+ for (const item of items) {
60
+ if (considered.has(item.placementId))
61
+ continue;
62
+ considered.add(item.placementId);
63
+ if ((await consider(item, snapshot, compute, skip, via, skipped, decisions)) === 'hit') {
64
+ return item;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ export async function walkAgenda(items, snapshot, options = {}) {
70
+ const skip = options.skipPlacementIds ?? new Set();
71
+ const skipped = [];
72
+ const decisions = [];
73
+ const considered = new Set();
74
+ const currentId = options.currentPlacementId ?? null;
75
+ if (currentId) {
76
+ const current = items.find((item) => item.placementId === currentId);
77
+ if (current && current.groupPath.length > 0) {
78
+ for (let depth = current.groupPath.length; depth >= 1; depth--) {
79
+ const prefix = current.groupPath.slice(0, depth);
80
+ const groupItems = items.filter((item) => startsWithGroup(item.groupPath, prefix));
81
+ const hit = await firstHit(groupItems, snapshot, options.compute, skip, 'sticky', skipped, decisions, considered);
82
+ if (hit) {
83
+ return { hit, reason: 'sticky', skipped, decisions };
84
+ }
85
+ }
86
+ }
87
+ }
88
+ const hit = await firstHit(items, snapshot, options.compute, skip, 'scan', skipped, decisions, considered);
89
+ if (hit)
90
+ return { hit, reason: 'scan', skipped, decisions };
91
+ return { hit: null, reason: 'complete', skipped, decisions };
92
+ }
93
+ export async function unresolvedFinishWhenFields(item, snapshot, compute) {
94
+ return (await evaluateWhen(item.finishWhen, snapshot, compute)).failedFields;
95
+ }
96
+ //# sourceMappingURL=walk.js.map
@@ -0,0 +1,53 @@
1
+ import type { ActionDataSlice } from '../fn-context/types.js';
2
+ import type { SequenceBuild } from '../builder/types.js';
3
+ export type OverlayAuthMessage = {
4
+ type: 'auth';
5
+ apiKey: string;
6
+ companyId: string;
7
+ names?: string[];
8
+ };
9
+ export type OverlayAuthOkMessage = {
10
+ type: 'auth.ok';
11
+ };
12
+ export type OverlayAuthErrorMessage = {
13
+ type: 'auth.error';
14
+ error: string;
15
+ };
16
+ export type OverlayReplacedMessage = {
17
+ type: 'replaced';
18
+ };
19
+ export declare const OVERLAY_REPLACED_CLOSE_CODE = 4000;
20
+ export type OverlayPushMessage = {
21
+ type: 'overlay';
22
+ sequenceId: string;
23
+ generation: number;
24
+ build: SequenceBuild;
25
+ };
26
+ export type OverlayExecuteMessage = {
27
+ type: 'execute';
28
+ requestId: string;
29
+ sequenceId: string;
30
+ name: string;
31
+ args?: unknown[];
32
+ data?: ActionDataSlice;
33
+ runToken?: string;
34
+ /** Logger request id for `ctx.api` RPC; not the overlay execute correlation id. */
35
+ logRequestId?: string;
36
+ };
37
+ export type OverlayExecuteResultMessage = {
38
+ type: 'execute.result';
39
+ requestId: string;
40
+ ok: true;
41
+ result: unknown;
42
+ } | {
43
+ type: 'execute.result';
44
+ requestId: string;
45
+ ok: false;
46
+ error: string;
47
+ };
48
+ export type OverlayClientMessage = OverlayAuthMessage | OverlayPushMessage | OverlayExecuteResultMessage;
49
+ export type OverlayServerMessage = OverlayAuthOkMessage | OverlayAuthErrorMessage | OverlayReplacedMessage | OverlayExecuteMessage;
50
+ export type OverlayMessage = OverlayClientMessage | OverlayServerMessage;
51
+ export declare function encodeOverlayMessage(message: OverlayMessage): string;
52
+ export declare function parseOverlayMessage(raw: string): OverlayMessage;
53
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1,21 @@
1
+ export const OVERLAY_REPLACED_CLOSE_CODE = 4000;
2
+ function isRecord(value) {
3
+ return value != null && typeof value === 'object' && !Array.isArray(value);
4
+ }
5
+ export function encodeOverlayMessage(message) {
6
+ return JSON.stringify(message);
7
+ }
8
+ export function parseOverlayMessage(raw) {
9
+ let parsed;
10
+ try {
11
+ parsed = JSON.parse(raw);
12
+ }
13
+ catch {
14
+ throw new Error('overlay message is not JSON');
15
+ }
16
+ if (!isRecord(parsed) || typeof parsed.type !== 'string') {
17
+ throw new Error('overlay message missing type');
18
+ }
19
+ return parsed;
20
+ }
21
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1,11 @@
1
+ import type { ActionContext, ActionDataSlice, ApiHost, RunScope } from './types.js';
2
+ export type BuildActionContextOptions = {
3
+ /** Defaults from `data.meta` when omitted. */
4
+ run?: Partial<RunScope>;
5
+ };
6
+ /**
7
+ * Assemble ActionContext = JSON data slice + api from ApiHost.
8
+ * Shared by local unit, remote-fc, and (later) Worker-side invoke.
9
+ */
10
+ export declare function buildActionContext(data: ActionDataSlice, host: ApiHost, options?: BuildActionContextOptions): Promise<ActionContext>;
11
+ //# sourceMappingURL=build-context.d.ts.map
@@ -0,0 +1,21 @@
1
+ import { bindLogMeta } from './log.js';
2
+ /**
3
+ * Assemble ActionContext = JSON data slice + api from ApiHost.
4
+ * Shared by local unit, remote-fc, and (later) Worker-side invoke.
5
+ */
6
+ export async function buildActionContext(data, host, options = {}) {
7
+ const run = {
8
+ companyId: options.run?.companyId ?? data.meta.companyId,
9
+ environmentId: options.run?.environmentId ?? data.meta.environmentId,
10
+ sequenceId: options.run?.sequenceId ?? data.meta.sequenceId,
11
+ entry: options.run?.entry ?? data.meta.entry,
12
+ };
13
+ const api = await host.buildApi(run);
14
+ return {
15
+ time: data.time,
16
+ meta: data.meta,
17
+ config: data.config,
18
+ api: { ...api, log: bindLogMeta(api.log, data.meta) },
19
+ };
20
+ }
21
+ //# sourceMappingURL=build-context.js.map
@@ -0,0 +1,9 @@
1
+ import { type PlatformApis, type PlatformSurfaceKey } from '../../core/context/platform-registry.js';
2
+ import type { IntegrationApi } from '../../core/context/types.js';
3
+ export declare const emptyIntegration: () => IntegrationApi;
4
+ export type PlatformApiOverrides = Partial<{
5
+ [K in PlatformSurfaceKey]: Partial<PlatformApis[K]>;
6
+ }>;
7
+ /** Each registered surface backed by its mock, with per-method overrides applied on top. */
8
+ export declare const defaultPlatformApis: (overrides?: PlatformApiOverrides) => PlatformApis;
9
+ //# sourceMappingURL=empty-api.d.ts.map