@xdelivered/emberflow 0.2.0 → 0.5.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 (116) hide show
  1. package/bin/commands.ts +7 -3
  2. package/bin/init.test.ts +94 -0
  3. package/bin/init.ts +108 -2
  4. package/dist/bin/commands.d.ts +1 -0
  5. package/dist/bin/commands.js +6 -3
  6. package/dist/bin/init.d.ts +4 -0
  7. package/dist/bin/init.js +96 -2
  8. package/dist/server/agents/codexParse.js +31 -0
  9. package/dist/server/agents/detect.d.ts +18 -8
  10. package/dist/server/agents/detect.js +78 -13
  11. package/dist/server/agents/modelRejectionHint.js +1 -1
  12. package/dist/server/agents/prompt.d.ts +15 -1
  13. package/dist/server/agents/prompt.js +59 -37
  14. package/dist/server/agents/runManager.d.ts +23 -2
  15. package/dist/server/agents/runManager.js +36 -8
  16. package/dist/server/client.d.ts +1 -0
  17. package/dist/server/client.js +7 -2
  18. package/dist/server/index.js +208 -16
  19. package/dist/server/nodesPayload.d.ts +14 -1
  20. package/dist/server/nodesPayload.js +15 -2
  21. package/dist/server/projectMode.js +5 -2
  22. package/dist/server/runRegistry.d.ts +52 -1
  23. package/dist/server/runRegistry.js +170 -1
  24. package/dist/server/sourceNav.d.ts +77 -0
  25. package/dist/server/sourceNav.js +503 -0
  26. package/dist/server/subflowRunner.d.ts +48 -1
  27. package/dist/server/subflowRunner.js +34 -7
  28. package/dist/server/updateCheck.d.ts +68 -0
  29. package/dist/server/updateCheck.js +142 -0
  30. package/dist/src/engine/executor.js +4 -3
  31. package/dist/src/engine/registry.d.ts +27 -2
  32. package/dist/src/engine/registry.js +84 -2
  33. package/dist/src/nodes/index.d.ts +8 -2
  34. package/dist/src/nodes/index.js +7 -3
  35. package/dist/src/nodes/login.d.ts +3 -1
  36. package/dist/src/nodes/login.js +2 -2
  37. package/package.json +28 -7
  38. package/server/agentRoute.test.ts +20 -0
  39. package/server/agents/codexParse.test.ts +37 -0
  40. package/server/agents/codexParse.ts +34 -0
  41. package/server/agents/detect.test.ts +26 -7
  42. package/server/agents/detect.ts +82 -14
  43. package/server/agents/modelRejectionHint.ts +2 -1
  44. package/server/agents/prompt.test.ts +128 -0
  45. package/server/agents/prompt.ts +102 -3
  46. package/server/agents/runManager.test.ts +9 -0
  47. package/server/agents/runManager.ts +37 -7
  48. package/server/client.ts +10 -4
  49. package/server/index.ts +213 -15
  50. package/server/nodeRun.test.ts +189 -0
  51. package/server/nodesPayload.test.ts +38 -0
  52. package/server/nodesPayload.ts +28 -3
  53. package/server/projectMode.ts +5 -2
  54. package/server/runRegistry.ts +200 -3
  55. package/server/setupStatus.test.ts +3 -0
  56. package/server/sourceNav.test.ts +382 -0
  57. package/server/sourceNav.ts +644 -0
  58. package/server/sourceNavRoute.test.ts +163 -0
  59. package/server/stepDrill.test.ts +380 -0
  60. package/server/subflowRunner.ts +92 -11
  61. package/server/updateCheck.test.ts +209 -0
  62. package/server/updateCheck.ts +175 -0
  63. package/server/workflowTestRoute.test.ts +1 -1
  64. package/src/App.tsx +82 -2
  65. package/src/components/AgentConsole.tsx +7 -280
  66. package/src/components/AgentStream.test.tsx +88 -0
  67. package/src/components/AgentStream.tsx +303 -0
  68. package/src/components/CreateModal.tsx +43 -9
  69. package/src/components/Dock.tsx +1 -1
  70. package/src/components/EmptyState.test.tsx +49 -0
  71. package/src/components/EmptyState.tsx +61 -0
  72. package/src/components/EnvironmentDialog.tsx +4 -1
  73. package/src/components/EnvironmentPicker.tsx +8 -3
  74. package/src/components/EnvironmentsDialog.tsx +4 -1
  75. package/src/components/InfraPanel.tsx +30 -2
  76. package/src/components/InfrastructureDialog.test.tsx +97 -0
  77. package/src/components/InfrastructureDialog.tsx +111 -0
  78. package/src/components/Inspector.tsx +9 -26
  79. package/src/components/RunbookView.tsx +70 -6
  80. package/src/components/SettingsDialog.tsx +4 -59
  81. package/src/components/Sidebar.tsx +6 -26
  82. package/src/components/SourceNavigator.test.tsx +226 -0
  83. package/src/components/SourceNavigator.tsx +520 -0
  84. package/src/components/StatusBar.tsx +227 -26
  85. package/src/components/Toolbar.tsx +28 -16
  86. package/src/components/UpdateChip.test.tsx +31 -0
  87. package/src/components/WelcomeDialog.test.tsx +384 -13
  88. package/src/components/WelcomeDialog.tsx +996 -177
  89. package/src/engine/executor.ts +4 -3
  90. package/src/engine/registry.sourceRef.test.ts +112 -0
  91. package/src/engine/registry.ts +103 -2
  92. package/src/lib/guidedQuestions.test.ts +224 -0
  93. package/src/lib/guidedQuestions.ts +181 -0
  94. package/src/lib/runbookModel.ts +3 -3
  95. package/src/lib/runbookProjection.test.ts +43 -0
  96. package/src/lib/runbookProjection.ts +26 -6
  97. package/src/nodes/index.ts +10 -3
  98. package/src/nodes/login.ts +5 -2
  99. package/src/store/agentClient.ts +27 -8
  100. package/src/store/apiTree.ts +12 -0
  101. package/src/store/builderStore.test.ts +441 -99
  102. package/src/store/builderStore.ts +385 -314
  103. package/src/store/nodeMeta.ts +10 -2
  104. package/src/store/serverRunner.ts +56 -5
  105. package/src/store/setupClient.ts +7 -2
  106. package/src/store/sourceNavClient.ts +48 -0
  107. package/src/store/updateClient.ts +50 -0
  108. package/studio-dist/assets/index-BbzppDpt.js +65 -0
  109. package/studio-dist/assets/index-CLf6blcA.css +1 -0
  110. package/studio-dist/index.html +2 -2
  111. package/templates/skills/emberflow-basics/SKILL.md +29 -1
  112. package/templates/skills/emberflow-model-process/SKILL.md +92 -9
  113. package/templates/skills/emberflow-new-workflow/SKILL.md +8 -1
  114. package/templates/skills/emberflow-review-workflow/SKILL.md +64 -1
  115. package/studio-dist/assets/index-DNJwW-hM.css +0 -1
  116. package/studio-dist/assets/index-O26dKRjW.js +0 -65
@@ -0,0 +1,226 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { NodeCodeView, SourceNavigator } from './SourceNavigator';
4
+ import type { SourceFileFetchResult, SourceFilePayload } from '../store/sourceNavClient';
5
+
6
+ // Props-driven fixtures: renderToStaticMarkup never runs effects, so the
7
+ // fetch cache is pre-populated via initialFiles and the fetcher is inert.
8
+ const neverFetch = () => new Promise<SourceFileFetchResult>(() => {});
9
+
10
+ const NODES_MJS: SourceFilePayload = {
11
+ path: 'nodes.mjs',
12
+ content: [
13
+ "import { deriveTrackingActual } from './shipment-logic.mjs';",
14
+ "import express from 'express';",
15
+ "import { createHash } from 'node:crypto';",
16
+ 'const RATE = 1.2;',
17
+ 'export function handler(input) {',
18
+ ' return deriveTrackingActual(input) * RATE;',
19
+ '}',
20
+ ].join('\n'),
21
+ language: 'js',
22
+ symbols: {
23
+ declarations: [
24
+ { name: 'RATE', kind: 'const', line: 4, endLine: 4, exported: false },
25
+ { name: 'handler', kind: 'fn', line: 5, endLine: 7, exported: true },
26
+ ],
27
+ imports: [
28
+ {
29
+ name: 'deriveTrackingActual',
30
+ local: 'deriveTrackingActual',
31
+ from: './shipment-logic.mjs',
32
+ resolution: { kind: 'project', path: 'shipment-logic.mjs', line: 5 },
33
+ },
34
+ {
35
+ name: 'default',
36
+ local: 'express',
37
+ from: 'express',
38
+ resolution: { kind: 'external', package: 'express' },
39
+ },
40
+ {
41
+ name: 'createHash',
42
+ local: 'createHash',
43
+ from: 'node:crypto',
44
+ resolution: { kind: 'builtin' },
45
+ },
46
+ {
47
+ name: 'import()',
48
+ local: '',
49
+ from: 'x',
50
+ resolution: { kind: 'unresolved', reason: 'dynamic import target is computed' },
51
+ },
52
+ {
53
+ name: '*',
54
+ local: '',
55
+ from: './polyfill.mjs',
56
+ resolution: { kind: 'project', path: 'polyfill.mjs' },
57
+ },
58
+ ],
59
+ reexports: [],
60
+ },
61
+ };
62
+
63
+ const SHIPMENT_MJS: SourceFilePayload = {
64
+ path: 'shipment-logic.mjs',
65
+ content: 'export function deriveTrackingActual(input) { return input.actual; }',
66
+ language: 'js',
67
+ symbols: {
68
+ declarations: [
69
+ { name: 'deriveTrackingActual', kind: 'fn', line: 1, endLine: 1, exported: true },
70
+ ],
71
+ imports: [],
72
+ reexports: [],
73
+ },
74
+ };
75
+
76
+ const files = (payload: SourceFilePayload): Record<string, SourceFileFetchResult> => ({
77
+ [payload.path]: { ok: true, payload },
78
+ });
79
+
80
+ /** Highlighting splits code across token spans; strip tags to assert on the raw text. */
81
+ const text = (html: string): string => html.replace(/<[^>]+>/g, '');
82
+
83
+ describe('SourceNavigator', () => {
84
+ it('renders the file content with local declarations linkified for same-file navigation', () => {
85
+ const out = renderToStaticMarkup(
86
+ <SourceNavigator
87
+ entryFile="nodes.mjs"
88
+ entryLine={5}
89
+ nodeType="DeriveShipmentActuals"
90
+ fetcher={neverFetch}
91
+ initialFiles={files(NODES_MJS)}
92
+ />,
93
+ );
94
+ expect(out).toContain('deriveTrackingActual');
95
+ expect(out).toContain('RATE');
96
+ // Declaration + import identifiers render as link buttons (token linking).
97
+ expect(out).toContain('source-nav-link');
98
+ expect(out).toContain('Jump to line 5'); // handler declaration
99
+ expect(out).toContain('Open shipment-logic.mjs:5'); // project import token
100
+ });
101
+
102
+ it('renders a project import as a clickable path:line link in the Referenced code panel', () => {
103
+ const out = renderToStaticMarkup(
104
+ <SourceNavigator
105
+ entryFile="nodes.mjs"
106
+ nodeType="DeriveShipmentActuals"
107
+ fetcher={neverFetch}
108
+ initialFiles={files(NODES_MJS)}
109
+ />,
110
+ );
111
+ expect(out).toContain('Referenced code');
112
+ expect(out).toContain('shipment-logic.mjs:5');
113
+ expect(out).toContain('project');
114
+ });
115
+
116
+ it('badges external, builtin, and unresolved (with reason) references', () => {
117
+ const out = renderToStaticMarkup(
118
+ <SourceNavigator
119
+ entryFile="nodes.mjs"
120
+ nodeType="DeriveShipmentActuals"
121
+ fetcher={neverFetch}
122
+ initialFiles={files(NODES_MJS)}
123
+ />,
124
+ );
125
+ expect(out).toContain('package: express');
126
+ expect(out).toContain('Node.js builtin');
127
+ expect(out).toContain('unresolved — dynamic import target is computed');
128
+ // Imports without a local binding are still listed: dynamic + side-effect.
129
+ expect(out).toContain('import()');
130
+ expect(out).toContain('(side-effect import)');
131
+ });
132
+
133
+ it('shows the breadcrumb trail and a Back button at depth > 1', () => {
134
+ const out = renderToStaticMarkup(
135
+ <SourceNavigator
136
+ entryFile="nodes.mjs"
137
+ nodeType="DeriveShipmentActuals"
138
+ fetcher={neverFetch}
139
+ initialStack={[{ path: 'nodes.mjs', line: 5 }, { path: 'shipment-logic.mjs', line: 5 }]}
140
+ initialFiles={{ ...files(NODES_MJS), ...files(SHIPMENT_MJS) }}
141
+ />,
142
+ );
143
+ expect(out).toContain('nodes.mjs');
144
+ expect(out).toContain('shipment-logic.mjs');
145
+ expect(out).toContain('›');
146
+ expect(out).toContain('Back');
147
+ // Current file's content is on screen, not the ancestor's.
148
+ expect(text(out)).toContain('return input.actual;');
149
+ });
150
+
151
+ it('hides Back at depth 1', () => {
152
+ const out = renderToStaticMarkup(
153
+ <SourceNavigator
154
+ entryFile="nodes.mjs"
155
+ nodeType="DeriveShipmentActuals"
156
+ fetcher={neverFetch}
157
+ initialFiles={files(NODES_MJS)}
158
+ />,
159
+ );
160
+ expect(out).not.toContain('Back');
161
+ });
162
+
163
+ it('shows the resolver-unavailable banner while still rendering content', () => {
164
+ const degraded: SourceFilePayload = {
165
+ ...SHIPMENT_MJS,
166
+ resolver: 'unavailable',
167
+ symbols: { declarations: [], imports: [], reexports: [] },
168
+ };
169
+ const out = renderToStaticMarkup(
170
+ <SourceNavigator
171
+ entryFile="shipment-logic.mjs"
172
+ nodeType="DeriveShipmentActuals"
173
+ fetcher={neverFetch}
174
+ initialFiles={files(degraded)}
175
+ />,
176
+ );
177
+ expect(out).toContain('Symbol resolution unavailable (typescript not installed)');
178
+ expect(text(out)).toContain('return input.actual;');
179
+ });
180
+
181
+ it('renders the fetch error text (denied / missing / runner down) instead of code', () => {
182
+ const out = renderToStaticMarkup(
183
+ <SourceNavigator
184
+ entryFile=".env"
185
+ nodeType="DeriveShipmentActuals"
186
+ fetcher={neverFetch}
187
+ initialFiles={{ '.env': { ok: false, error: 'Access denied: path not servable' } }}
188
+ />,
189
+ );
190
+ expect(out).toContain('Access denied: path not servable');
191
+ expect(out).not.toContain('Referenced code');
192
+ });
193
+ });
194
+
195
+ describe('NodeCodeView (Inspector code dialog body)', () => {
196
+ it('without sourceRef renders exactly the legacy highlighter view — no Referenced code', () => {
197
+ const out = renderToStaticMarkup(
198
+ <NodeCodeView nodeType="Map" source="async (input) => input" fetcher={neverFetch} />,
199
+ );
200
+ expect(out).toContain('input');
201
+ expect(out).not.toContain('Referenced code');
202
+ expect(out).not.toContain('Built-in node');
203
+ expect(out).not.toContain('source-nav-link');
204
+ });
205
+
206
+ it('builtin nodes keep the legacy view plus a quiet Built-in node badge', () => {
207
+ const out = renderToStaticMarkup(
208
+ <NodeCodeView nodeType="Input" source="async () => ({})" builtin fetcher={neverFetch} />,
209
+ );
210
+ expect(out).toContain('Built-in node');
211
+ expect(out).not.toContain('Referenced code');
212
+ });
213
+
214
+ it('with a sourceRef renders the SourceNavigator (breadcrumb + loading state pre-fetch)', () => {
215
+ const out = renderToStaticMarkup(
216
+ <NodeCodeView
217
+ nodeType="DeriveShipmentActuals"
218
+ source="ignored"
219
+ sourceRef={{ file: 'nodes.mjs', line: 4 }}
220
+ fetcher={neverFetch}
221
+ />,
222
+ );
223
+ expect(out).toContain('nodes.mjs');
224
+ expect(out).toContain('Loading source…');
225
+ });
226
+ });