@codemation/next-host 0.0.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 (206) hide show
  1. package/README.md +25 -0
  2. package/app/(shell)/credentials/page.tsx +5 -0
  3. package/app/(shell)/dashboard/page.tsx +14 -0
  4. package/app/(shell)/layout.tsx +11 -0
  5. package/app/(shell)/page.tsx +5 -0
  6. package/app/(shell)/users/page.tsx +5 -0
  7. package/app/(shell)/workflows/[workflowId]/page.tsx +19 -0
  8. package/app/(shell)/workflows/page.tsx +5 -0
  9. package/app/api/[[...path]]/route.ts +40 -0
  10. package/app/api/auth/[...nextauth]/route.ts +3 -0
  11. package/app/globals.css +997 -0
  12. package/app/invite/[token]/page.tsx +10 -0
  13. package/app/layout.tsx +65 -0
  14. package/app/login/layout.tsx +25 -0
  15. package/app/login/page.tsx +22 -0
  16. package/components.json +21 -0
  17. package/docs/FORMS.md +46 -0
  18. package/docs/TAILWIND_SHADCN_MIGRATION.md +89 -0
  19. package/eslint.config.mjs +56 -0
  20. package/middleware.ts +29 -0
  21. package/next-env.d.ts +6 -0
  22. package/next.config.ts +34 -0
  23. package/package.json +76 -0
  24. package/postcss.config.mjs +7 -0
  25. package/public/canvas-icons/builtin/openai.svg +5 -0
  26. package/src/api/CodemationApiClient.ts +107 -0
  27. package/src/api/CodemationApiHttpError.ts +17 -0
  28. package/src/auth/CodemationNextAuthConfigResolver.ts +14 -0
  29. package/src/auth/CodemationNextAuthOAuthProviderDescriptorMapper.ts +30 -0
  30. package/src/auth/CodemationNextAuthOAuthProviderSnapshotResolver.ts +17 -0
  31. package/src/auth/CodemationNextAuthProviderCatalog.ts +107 -0
  32. package/src/auth/codemationEdgeAuth.ts +25 -0
  33. package/src/auth/codemationNextAuth.ts +32 -0
  34. package/src/components/Codemation.tsx +6 -0
  35. package/src/components/CodemationDataTable.tsx +37 -0
  36. package/src/components/CodemationDialog.tsx +137 -0
  37. package/src/components/CodemationFormattedDateTime.tsx +46 -0
  38. package/src/components/GoogleColorGIcon.tsx +39 -0
  39. package/src/components/OauthProviderIcon.tsx +33 -0
  40. package/src/components/PasswordStrengthMeter.tsx +59 -0
  41. package/src/components/forms/index.ts +28 -0
  42. package/src/components/json/JsonMonacoEditor.tsx +75 -0
  43. package/src/components/oauthProviderIconData.ts +17 -0
  44. package/src/components/ui/alert.tsx +56 -0
  45. package/src/components/ui/badge.tsx +40 -0
  46. package/src/components/ui/button.tsx +64 -0
  47. package/src/components/ui/card.tsx +70 -0
  48. package/src/components/ui/collapsible.tsx +26 -0
  49. package/src/components/ui/dialog.tsx +137 -0
  50. package/src/components/ui/dropdown-menu.tsx +238 -0
  51. package/src/components/ui/form.tsx +147 -0
  52. package/src/components/ui/input.tsx +19 -0
  53. package/src/components/ui/label.tsx +26 -0
  54. package/src/components/ui/scroll-area.tsx +47 -0
  55. package/src/components/ui/select.tsx +169 -0
  56. package/src/components/ui/separator.tsx +28 -0
  57. package/src/components/ui/switch.tsx +28 -0
  58. package/src/components/ui/table.tsx +72 -0
  59. package/src/components/ui/tabs.tsx +76 -0
  60. package/src/components/ui/textarea.tsx +18 -0
  61. package/src/components/ui/toggle.tsx +41 -0
  62. package/src/features/credentials/components/CredentialConfirmDialog.tsx +58 -0
  63. package/src/features/credentials/components/CredentialDialog.tsx +252 -0
  64. package/src/features/credentials/components/CredentialDialogFeedback.tsx +36 -0
  65. package/src/features/credentials/components/CredentialDialogFieldRows.tsx +257 -0
  66. package/src/features/credentials/components/CredentialDialogFormSections.tsx +230 -0
  67. package/src/features/credentials/components/CredentialEnvFieldStatusRow.tsx +64 -0
  68. package/src/features/credentials/components/CredentialFieldCopyButton.tsx +48 -0
  69. package/src/features/credentials/components/CredentialsScreenHealthBadge.tsx +21 -0
  70. package/src/features/credentials/components/CredentialsScreenInstancesTable.tsx +108 -0
  71. package/src/features/credentials/components/CredentialsScreenTestFailureAlert.tsx +33 -0
  72. package/src/features/credentials/hooks/useCredentialCreateDialog.ts +33 -0
  73. package/src/features/credentials/hooks/useCredentialDialogSession.ts +616 -0
  74. package/src/features/credentials/hooks/useCredentialsScreen.ts +213 -0
  75. package/src/features/credentials/lib/credentialFieldHelpers.ts +35 -0
  76. package/src/features/credentials/lib/credentialFormTypes.ts +1 -0
  77. package/src/features/credentials/lib/credentialInstanceTestPayloadParser.ts +10 -0
  78. package/src/features/credentials/screens/CredentialsScreen.tsx +187 -0
  79. package/src/features/invite/screens/InviteAcceptScreen.tsx +190 -0
  80. package/src/features/users/components/UsersInviteDialog.tsx +121 -0
  81. package/src/features/users/components/UsersRegenerateDialog.tsx +81 -0
  82. package/src/features/users/components/UsersScreenUserStatusBadge.tsx +19 -0
  83. package/src/features/users/schemas/usersInviteFormSchema.ts +7 -0
  84. package/src/features/users/screens/UsersScreen.tsx +240 -0
  85. package/src/features/workflows/components/WorkflowListFolderSection.tsx +91 -0
  86. package/src/features/workflows/components/WorkflowListItemCard.tsx +67 -0
  87. package/src/features/workflows/components/WorkflowListRoot.tsx +39 -0
  88. package/src/features/workflows/components/WorkflowsListTree.tsx +28 -0
  89. package/src/features/workflows/components/canvas/CanvasNodeChromeTooltip.tsx +96 -0
  90. package/src/features/workflows/components/canvas/CanvasNodeIconSlot.tsx +25 -0
  91. package/src/features/workflows/components/canvas/VisibleNodeStatusResolver.tsx +84 -0
  92. package/src/features/workflows/components/canvas/WorkflowCanvas.tsx +248 -0
  93. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNode.tsx +182 -0
  94. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeAccents.tsx +73 -0
  95. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeAgentBottomSourceHandles.tsx +43 -0
  96. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeAgentLabels.tsx +47 -0
  97. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeCard.tsx +202 -0
  98. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeHandles.tsx +77 -0
  99. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeLabelBelow.tsx +51 -0
  100. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeMainGlyph.tsx +64 -0
  101. package/src/features/workflows/components/canvas/WorkflowCanvasCodemationNodeToolbar.tsx +95 -0
  102. package/src/features/workflows/components/canvas/WorkflowCanvasLoadingPlaceholder.tsx +69 -0
  103. package/src/features/workflows/components/canvas/WorkflowCanvasNodeIcon.tsx +102 -0
  104. package/src/features/workflows/components/canvas/WorkflowCanvasSimpleIconGlyph.tsx +21 -0
  105. package/src/features/workflows/components/canvas/WorkflowCanvasStraightCountEdge.tsx +33 -0
  106. package/src/features/workflows/components/canvas/WorkflowCanvasStructureSignature.tsx +7 -0
  107. package/src/features/workflows/components/canvas/WorkflowCanvasSymmetricForkEdge.tsx +32 -0
  108. package/src/features/workflows/components/canvas/WorkflowCanvasToolbarIconButton.tsx +95 -0
  109. package/src/features/workflows/components/canvas/lib/WorkflowCanvasBuiltinIconRegistry.ts +26 -0
  110. package/src/features/workflows/components/canvas/lib/WorkflowCanvasEdgeCountResolver.ts +51 -0
  111. package/src/features/workflows/components/canvas/lib/WorkflowCanvasEdgeStyleResolver.ts +35 -0
  112. package/src/features/workflows/components/canvas/lib/WorkflowCanvasLabelLayoutEstimator.ts +42 -0
  113. package/src/features/workflows/components/canvas/lib/WorkflowCanvasOverlapResolver.ts +78 -0
  114. package/src/features/workflows/components/canvas/lib/WorkflowCanvasPortOrderResolver.ts +25 -0
  115. package/src/features/workflows/components/canvas/lib/WorkflowCanvasRoundedOrthogonalPathPlanner.ts +56 -0
  116. package/src/features/workflows/components/canvas/lib/WorkflowCanvasSiIconRegistry.ts +18 -0
  117. package/src/features/workflows/components/canvas/lib/WorkflowCanvasSymmetricForkPathPlanner.ts +43 -0
  118. package/src/features/workflows/components/canvas/lib/layoutWorkflow.ts +315 -0
  119. package/src/features/workflows/components/canvas/lib/workflowCanvasEdgeGeometry.ts +3 -0
  120. package/src/features/workflows/components/canvas/lib/workflowCanvasEmbeddedStyles.ts +62 -0
  121. package/src/features/workflows/components/canvas/lib/workflowCanvasFlowTypes.ts +10 -0
  122. package/src/features/workflows/components/canvas/lib/workflowCanvasNodeData.ts +41 -0
  123. package/src/features/workflows/components/canvas/lib/workflowCanvasNodeGeometry.ts +99 -0
  124. package/src/features/workflows/components/canvas/workflowCanvasNodeChrome.tsx +46 -0
  125. package/src/features/workflows/components/realtime/RealtimeContext.tsx +14 -0
  126. package/src/features/workflows/components/realtime/WorkflowRealtimeProvider.tsx +15 -0
  127. package/src/features/workflows/components/workflowDetail/NodeCredentialBindingRow.tsx +209 -0
  128. package/src/features/workflows/components/workflowDetail/NodeCredentialBindingsSection.tsx +227 -0
  129. package/src/features/workflows/components/workflowDetail/NodePropertiesConfigSection.tsx +51 -0
  130. package/src/features/workflows/components/workflowDetail/NodePropertiesPanelHeader.tsx +50 -0
  131. package/src/features/workflows/components/workflowDetail/NodePropertiesSlidePanel.tsx +134 -0
  132. package/src/features/workflows/components/workflowDetail/WorkflowActivationErrorDialog.tsx +71 -0
  133. package/src/features/workflows/components/workflowDetail/WorkflowActivationHeaderControl.tsx +64 -0
  134. package/src/features/workflows/components/workflowDetail/WorkflowDetailIcons.tsx +52 -0
  135. package/src/features/workflows/components/workflowDetail/WorkflowExecutionInspector.tsx +110 -0
  136. package/src/features/workflows/components/workflowDetail/WorkflowExecutionInspectorDetailBody.tsx +213 -0
  137. package/src/features/workflows/components/workflowDetail/WorkflowExecutionInspectorPanes.tsx +239 -0
  138. package/src/features/workflows/components/workflowDetail/WorkflowExecutionInspectorSidebarResizer.tsx +31 -0
  139. package/src/features/workflows/components/workflowDetail/WorkflowExecutionInspectorTreePanel.tsx +133 -0
  140. package/src/features/workflows/components/workflowDetail/WorkflowInspectorAttachmentGroupingPresenter.tsx +31 -0
  141. package/src/features/workflows/components/workflowDetail/WorkflowInspectorAttachmentList.tsx +118 -0
  142. package/src/features/workflows/components/workflowDetail/WorkflowInspectorBinaryView.tsx +15 -0
  143. package/src/features/workflows/components/workflowDetail/WorkflowInspectorErrorView.tsx +107 -0
  144. package/src/features/workflows/components/workflowDetail/WorkflowInspectorJsonView.tsx +114 -0
  145. package/src/features/workflows/components/workflowDetail/WorkflowInspectorPrettyTreePresenter.tsx +132 -0
  146. package/src/features/workflows/components/workflowDetail/WorkflowInspectorPrettyTreeViewRenderer.tsx +147 -0
  147. package/src/features/workflows/components/workflowDetail/WorkflowInspectorPrettyView.tsx +65 -0
  148. package/src/features/workflows/components/workflowDetail/WorkflowInspectorViews.tsx +5 -0
  149. package/src/features/workflows/components/workflowDetail/WorkflowJsonEditorBinaryAttachmentRow.tsx +74 -0
  150. package/src/features/workflows/components/workflowDetail/WorkflowJsonEditorBinaryUploadRow.tsx +69 -0
  151. package/src/features/workflows/components/workflowDetail/WorkflowJsonEditorDialog.tsx +254 -0
  152. package/src/features/workflows/components/workflowDetail/WorkflowRunsList.tsx +89 -0
  153. package/src/features/workflows/components/workflowDetail/WorkflowRunsSidebar.tsx +50 -0
  154. package/src/features/workflows/hooks/canvas/useWorkflowCanvasVisibleNodeStatuses.ts +14 -0
  155. package/src/features/workflows/hooks/realtime/realtime.tsx +271 -0
  156. package/src/features/workflows/hooks/realtime/runQueryPolling.ts +34 -0
  157. package/src/features/workflows/hooks/realtime/useWorkflowRealtimeInfrastructure.ts +541 -0
  158. package/src/features/workflows/hooks/realtime/useWorkflowRealtimeShowDisconnectedBadge.ts +9 -0
  159. package/src/features/workflows/hooks/workflowDetail/useWorkflowDetailController.tsx +1300 -0
  160. package/src/features/workflows/lib/realtime/realtimeApi.ts +78 -0
  161. package/src/features/workflows/lib/realtime/realtimeClientBridge.ts +52 -0
  162. package/src/features/workflows/lib/realtime/realtimeDomainTypes.ts +191 -0
  163. package/src/features/workflows/lib/realtime/realtimeQueryKeys.ts +15 -0
  164. package/src/features/workflows/lib/realtime/realtimeRunMutations.ts +167 -0
  165. package/src/features/workflows/lib/realtime/workflowTypes.ts +5 -0
  166. package/src/features/workflows/lib/workflowDetail/PersistedWorkflowSnapshotMapper.ts +205 -0
  167. package/src/features/workflows/lib/workflowDetail/WorkflowActivationHttpErrorFormat.ts +32 -0
  168. package/src/features/workflows/lib/workflowDetail/WorkflowDetailPresenter.ts +1017 -0
  169. package/src/features/workflows/lib/workflowDetail/WorkflowDetailUrlCodec.ts +70 -0
  170. package/src/features/workflows/lib/workflowDetail/workflowDetailTypes.ts +152 -0
  171. package/src/features/workflows/lib/workflowDetailTreeStyles.ts +65 -0
  172. package/src/features/workflows/screens/WorkflowDetailScreen.tsx +236 -0
  173. package/src/features/workflows/screens/WorkflowDetailScreenInspectorPanel.tsx +55 -0
  174. package/src/features/workflows/screens/WorkflowsList.tsx +35 -0
  175. package/src/features/workflows/screens/WorkflowsScreen.tsx +31 -0
  176. package/src/index.ts +1 -0
  177. package/src/lib/utils.ts +6 -0
  178. package/src/middleware/CodemationNextHostMiddlewarePathRules.ts +31 -0
  179. package/src/providers/CodemationSessionProvider.tsx +23 -0
  180. package/src/providers/Providers.tsx +36 -0
  181. package/src/providers/RealtimeBoundary.tsx +17 -0
  182. package/src/providers/WhitelabelProvider.tsx +22 -0
  183. package/src/server/CodemationAuthPrismaClient.ts +21 -0
  184. package/src/server/CodemationNextHost.ts +379 -0
  185. package/src/shell/AppLayout.tsx +141 -0
  186. package/src/shell/AppLayoutNavItems.tsx +129 -0
  187. package/src/shell/AppLayoutPageHeader.tsx +79 -0
  188. package/src/shell/AppLayoutSidebarBrand.tsx +33 -0
  189. package/src/shell/AppMainContent.tsx +17 -0
  190. package/src/shell/AppShellHeaderActions.tsx +12 -0
  191. package/src/shell/AppShellHeaderActionsAuthenticated.tsx +51 -0
  192. package/src/shell/CodemationNextClientShell.tsx +17 -0
  193. package/src/shell/CredentialsSignInRedirectResolver.ts +21 -0
  194. package/src/shell/LoginPageClient.tsx +231 -0
  195. package/src/shell/WorkflowDetailChromeContext.tsx +42 -0
  196. package/src/shell/WorkflowFolderTreeBuilder.ts +62 -0
  197. package/src/shell/WorkflowFolderUi.ts +42 -0
  198. package/src/shell/WorkflowSidebarNavFolder.tsx +112 -0
  199. package/src/shell/WorkflowSidebarNavTree.tsx +68 -0
  200. package/src/shell/appLayoutPageTitle.ts +16 -0
  201. package/src/shell/appLayoutSidebarIcons.tsx +108 -0
  202. package/src/whitelabel/CodemationWhitelabelSnapshot.ts +4 -0
  203. package/src/whitelabel/CodemationWhitelabelSnapshotFactory.ts +18 -0
  204. package/tsconfig.json +40 -0
  205. package/tsconfig.tsbuildinfo +1 -0
  206. package/vitest.config.ts +34 -0
@@ -0,0 +1,78 @@
1
+ import type { CredentialTypeDefinition } from "@codemation/core/browser";
2
+ import type {
3
+ CredentialInstanceDto,
4
+ CredentialInstanceWithSecretsDto,
5
+ WorkflowCredentialHealthDto,
6
+ } from "@codemation/host-src/application/contracts/CredentialContractsRegistry";
7
+ import {
8
+ withUserAccountLoginMethodsDefaults,
9
+ type UserAccountDto,
10
+ } from "@codemation/host-src/application/contracts/userDirectoryContracts.types";
11
+ import type { WorkflowDto, WorkflowSummary } from "@codemation/host-src/application/contracts/WorkflowViewContracts";
12
+ import { ApiPaths } from "@codemation/host-src/presentation/http/ApiPaths";
13
+
14
+ import { codemationApiClient } from "../../../../api/CodemationApiClient";
15
+
16
+ import type { PersistedRunState, RunSummary, WorkflowDebuggerOverlayState } from "./realtimeDomainTypes";
17
+
18
+ export async function fetchWorkflows(): Promise<ReadonlyArray<WorkflowSummary>> {
19
+ return await codemationApiClient.getJson<ReadonlyArray<WorkflowSummary>>(ApiPaths.workflows());
20
+ }
21
+
22
+ export async function fetchWorkflow(workflowId: string): Promise<WorkflowDto> {
23
+ return await codemationApiClient.getJson<WorkflowDto>(ApiPaths.workflow(workflowId));
24
+ }
25
+
26
+ export async function patchWorkflowActivation(
27
+ workflowId: string,
28
+ active: boolean,
29
+ ): Promise<Readonly<{ active: boolean }>> {
30
+ return await codemationApiClient.patchJson<Readonly<{ active: boolean }>>(ApiPaths.workflowActivation(workflowId), {
31
+ active,
32
+ });
33
+ }
34
+
35
+ export async function fetchWorkflowRuns(workflowId: string): Promise<ReadonlyArray<RunSummary>> {
36
+ return await codemationApiClient.getJson<ReadonlyArray<RunSummary>>(ApiPaths.workflowRuns(workflowId));
37
+ }
38
+
39
+ export async function fetchWorkflowDebuggerOverlay(workflowId: string): Promise<WorkflowDebuggerOverlayState> {
40
+ return await codemationApiClient.getJson<WorkflowDebuggerOverlayState>(ApiPaths.workflowDebuggerOverlay(workflowId));
41
+ }
42
+
43
+ export async function fetchRun(
44
+ runId: string,
45
+ options?: Readonly<{ signal?: AbortSignal }>,
46
+ ): Promise<PersistedRunState> {
47
+ const init: RequestInit | undefined = options?.signal ? { signal: options.signal } : undefined;
48
+ return await codemationApiClient.getJson<PersistedRunState>(ApiPaths.runState(runId), init);
49
+ }
50
+
51
+ export async function fetchCredentialTypes(): Promise<ReadonlyArray<CredentialTypeDefinition>> {
52
+ return await codemationApiClient.getJson<ReadonlyArray<CredentialTypeDefinition>>(ApiPaths.credentialTypes());
53
+ }
54
+
55
+ export async function fetchCredentialFieldEnvStatus(): Promise<Readonly<Record<string, boolean>>> {
56
+ return await codemationApiClient.getJson<Readonly<Record<string, boolean>>>(ApiPaths.credentialsEnvStatus());
57
+ }
58
+
59
+ export async function fetchCredentialInstances(): Promise<ReadonlyArray<CredentialInstanceDto>> {
60
+ return await codemationApiClient.getJson<ReadonlyArray<CredentialInstanceDto>>(ApiPaths.credentialInstances());
61
+ }
62
+
63
+ export async function fetchCredentialInstanceWithSecrets(
64
+ instanceId: string,
65
+ ): Promise<CredentialInstanceWithSecretsDto> {
66
+ return await codemationApiClient.getJson<CredentialInstanceWithSecretsDto>(
67
+ ApiPaths.credentialInstance(instanceId, true),
68
+ );
69
+ }
70
+
71
+ export async function fetchWorkflowCredentialHealth(workflowId: string): Promise<WorkflowCredentialHealthDto> {
72
+ return await codemationApiClient.getJson<WorkflowCredentialHealthDto>(ApiPaths.workflowCredentialHealth(workflowId));
73
+ }
74
+
75
+ export async function fetchUserAccounts(): Promise<ReadonlyArray<UserAccountDto>> {
76
+ const rows = await codemationApiClient.getJson<ReadonlyArray<UserAccountDto>>(ApiPaths.users());
77
+ return rows.map((u) => withUserAccountLoginMethodsDefaults(u));
78
+ }
@@ -0,0 +1,52 @@
1
+ import type { WorkflowEvent } from "./realtimeDomainTypes";
2
+
3
+ export type RealtimeServerMessage =
4
+ | Readonly<{ kind: "ready" }>
5
+ | Readonly<{ kind: "subscribed"; roomId: string }>
6
+ | Readonly<{ kind: "unsubscribed"; roomId: string }>
7
+ | Readonly<{ kind: "workflowChanged"; workflowId: string }>
8
+ | Readonly<{ kind: "devBuildStarted"; workflowId: string; buildVersion?: string }>
9
+ | Readonly<{ kind: "devBuildCompleted"; workflowId: string; buildVersion: string }>
10
+ | Readonly<{ kind: "devBuildFailed"; workflowId: string; message: string }>
11
+ | Readonly<{ kind: "event"; event: WorkflowEvent }>
12
+ | Readonly<{ kind: "error"; message: string }>;
13
+
14
+ export type RealtimeClientMessage =
15
+ | Readonly<{ kind: "subscribe"; roomId: string }>
16
+ | Readonly<{ kind: "unsubscribe"; roomId: string }>;
17
+
18
+ export const minimumRealtimeActiveVisibilityMs = 300;
19
+
20
+ export const persistentRealtimeDisconnectWarningDelayMs = 5000;
21
+
22
+ export type RetainWorkflowSubscription = (workflowId: string) => () => void;
23
+
24
+ export type RealtimeBridgeState = {
25
+ retainWorkflowSubscription: RetainWorkflowSubscription | null;
26
+ listeners: Set<() => void>;
27
+ };
28
+
29
+ type RealtimeBridgeGlobal = typeof globalThis & {
30
+ __codemationRealtimeBridge__?: RealtimeBridgeState;
31
+ };
32
+
33
+ export const RealtimeReadyState = {
34
+ UNINSTANTIATED: -1,
35
+ CONNECTING: 0,
36
+ OPEN: 1,
37
+ CLOSING: 2,
38
+ CLOSED: 3,
39
+ } as const;
40
+
41
+ export type RealtimeReadyValue = (typeof RealtimeReadyState)[keyof typeof RealtimeReadyState];
42
+
43
+ export function getRealtimeBridge(): RealtimeBridgeState {
44
+ const realtimeGlobal = globalThis as RealtimeBridgeGlobal;
45
+ if (!realtimeGlobal.__codemationRealtimeBridge__) {
46
+ realtimeGlobal.__codemationRealtimeBridge__ = {
47
+ retainWorkflowSubscription: null,
48
+ listeners: new Set(),
49
+ };
50
+ }
51
+ return realtimeGlobal.__codemationRealtimeBridge__;
52
+ }
@@ -0,0 +1,191 @@
1
+ import type { Item as WorkflowItem, JsonValue } from "@codemation/core/browser";
2
+ import type { WorkflowDto } from "@codemation/host-src/application/contracts/WorkflowViewContracts";
3
+
4
+ export type Item = WorkflowItem;
5
+ export type Items = ReadonlyArray<Item>;
6
+
7
+ export type RunExecutionOptions = Readonly<{
8
+ localOnly?: boolean;
9
+ webhook?: boolean;
10
+ mode?: "manual" | "debug";
11
+ sourceWorkflowId?: string;
12
+ sourceRunId?: string;
13
+ derivedFromRunId?: string;
14
+ isMutable?: boolean;
15
+ }>;
16
+
17
+ export type PersistedWorkflowConnection = Readonly<{
18
+ parentNodeId: string;
19
+ connectionName: string;
20
+ childNodeIds: ReadonlyArray<string>;
21
+ }>;
22
+
23
+ export type PersistedWorkflowSnapshot = Readonly<{
24
+ id: string;
25
+ name: string;
26
+ workflowErrorHandlerConfigured?: boolean;
27
+ connections?: ReadonlyArray<PersistedWorkflowConnection>;
28
+ nodes: ReadonlyArray<
29
+ Readonly<{
30
+ id: string;
31
+ kind: string;
32
+ name?: string;
33
+ nodeTokenId: string;
34
+ configTokenId: string;
35
+ tokenName?: string;
36
+ configTokenName?: string;
37
+ config: unknown;
38
+ }>
39
+ >;
40
+ edges: WorkflowDto["edges"];
41
+ }>;
42
+
43
+ export type PersistedMutableNodeState = Readonly<{
44
+ pinnedOutputsByPort?: Readonly<Record<string, Items>>;
45
+ lastDebugInput?: Items;
46
+ }>;
47
+
48
+ export type PersistedMutableRunState = Readonly<{
49
+ nodesById: Readonly<Record<string, PersistedMutableNodeState>>;
50
+ }>;
51
+
52
+ export type ParentExecutionRef = Readonly<{ runId: string; workflowId: string; nodeId: string }>;
53
+
54
+ export type RunSummary = Readonly<{
55
+ runId: string;
56
+ workflowId: string;
57
+ startedAt: string;
58
+ status: string;
59
+ finishedAt?: string;
60
+ parent?: ParentExecutionRef;
61
+ executionOptions?: RunExecutionOptions;
62
+ }>;
63
+
64
+ export type NodeExecutionSnapshot = Readonly<{
65
+ runId: string;
66
+ workflowId: string;
67
+ nodeId: string;
68
+ activationId?: string;
69
+ parent?: ParentExecutionRef;
70
+ status: "pending" | "queued" | "running" | "completed" | "failed" | "skipped";
71
+ usedPinnedOutput?: boolean;
72
+ queuedAt?: string;
73
+ startedAt?: string;
74
+ finishedAt?: string;
75
+ updatedAt: string;
76
+ inputsByPort?: Readonly<Record<string, Items>>;
77
+ outputs?: Readonly<Record<string, Items>>;
78
+ error?: Readonly<{ message: string; name?: string; stack?: string }>;
79
+ }>;
80
+
81
+ /** One LLM/tool invocation under an agent; mirrors core {@link ConnectionInvocationRecord}. */
82
+ export type ConnectionInvocationRecord = Readonly<{
83
+ invocationId: string;
84
+ runId: string;
85
+ workflowId: string;
86
+ connectionNodeId: string;
87
+ parentAgentNodeId: string;
88
+ parentAgentActivationId: string;
89
+ status: NodeExecutionSnapshot["status"];
90
+ managedInput?: JsonValue;
91
+ managedOutput?: JsonValue;
92
+ error?: NodeExecutionSnapshot["error"];
93
+ queuedAt?: string;
94
+ startedAt?: string;
95
+ finishedAt?: string;
96
+ updatedAt: string;
97
+ }>;
98
+
99
+ export type PendingNodeExecution = Readonly<{
100
+ runId: string;
101
+ activationId: string;
102
+ workflowId: string;
103
+ nodeId: string;
104
+ itemsIn: number;
105
+ inputsByPort: Readonly<Record<string, Items>>;
106
+ receiptId: string;
107
+ queue?: string;
108
+ batchId?: string;
109
+ enqueuedAt: string;
110
+ }>;
111
+
112
+ export type PersistedRunState = Readonly<{
113
+ runId: string;
114
+ workflowId: string;
115
+ startedAt: string;
116
+ parent?: ParentExecutionRef;
117
+ executionOptions?: RunExecutionOptions;
118
+ workflowSnapshot?: PersistedWorkflowSnapshot;
119
+ mutableState?: PersistedMutableRunState;
120
+ status: "running" | "pending" | "completed" | "failed";
121
+ pending?: PendingNodeExecution;
122
+ queue: ReadonlyArray<unknown>;
123
+ outputsByNode: Readonly<Record<string, Readonly<Record<string, Items>>>>;
124
+ nodeSnapshotsByNodeId: Readonly<Record<string, NodeExecutionSnapshot>>;
125
+ connectionInvocations?: ReadonlyArray<ConnectionInvocationRecord>;
126
+ }>;
127
+
128
+ export type RunCurrentState = Readonly<{
129
+ outputsByNode: PersistedRunState["outputsByNode"];
130
+ nodeSnapshotsByNodeId: PersistedRunState["nodeSnapshotsByNodeId"];
131
+ connectionInvocations?: ReadonlyArray<ConnectionInvocationRecord>;
132
+ mutableState?: PersistedMutableRunState;
133
+ }>;
134
+
135
+ export type WorkflowDebuggerOverlayState = Readonly<{
136
+ workflowId: string;
137
+ updatedAt: string;
138
+ copiedFromRunId?: string;
139
+ currentState: RunCurrentState;
140
+ }>;
141
+
142
+ export type WorkflowDevBuildState = Readonly<{
143
+ state: "idle" | "building" | "failed";
144
+ updatedAt: string;
145
+ buildVersion?: string;
146
+ message?: string;
147
+ awaitingWorkflowRefreshAt?: string;
148
+ }>;
149
+
150
+ export type WorkflowEvent =
151
+ | Readonly<{ kind: "runCreated"; runId: string; workflowId: string; parent?: ParentExecutionRef; at: string }>
152
+ | Readonly<{
153
+ kind: "runSaved";
154
+ runId: string;
155
+ workflowId: string;
156
+ parent?: ParentExecutionRef;
157
+ at: string;
158
+ state: PersistedRunState;
159
+ }>
160
+ | Readonly<{
161
+ kind: "nodeQueued";
162
+ runId: string;
163
+ workflowId: string;
164
+ parent?: ParentExecutionRef;
165
+ at: string;
166
+ snapshot: NodeExecutionSnapshot;
167
+ }>
168
+ | Readonly<{
169
+ kind: "nodeStarted";
170
+ runId: string;
171
+ workflowId: string;
172
+ parent?: ParentExecutionRef;
173
+ at: string;
174
+ snapshot: NodeExecutionSnapshot;
175
+ }>
176
+ | Readonly<{
177
+ kind: "nodeCompleted";
178
+ runId: string;
179
+ workflowId: string;
180
+ parent?: ParentExecutionRef;
181
+ at: string;
182
+ snapshot: NodeExecutionSnapshot;
183
+ }>
184
+ | Readonly<{
185
+ kind: "nodeFailed";
186
+ runId: string;
187
+ workflowId: string;
188
+ parent?: ParentExecutionRef;
189
+ at: string;
190
+ snapshot: NodeExecutionSnapshot;
191
+ }>;
@@ -0,0 +1,15 @@
1
+ export const workflowsQueryKey = ["workflows"] as const;
2
+ export const workflowQueryKey = (workflowId: string) => ["workflow", workflowId] as const;
3
+ export const workflowRunsQueryKey = (workflowId: string) => ["workflow-runs", workflowId] as const;
4
+ export const workflowDebuggerOverlayQueryKey = (workflowId: string) =>
5
+ ["workflow-debugger-overlay", workflowId] as const;
6
+ export const workflowDevBuildStateQueryKey = (workflowId: string) => ["workflow-dev-build-state", workflowId] as const;
7
+ export const runQueryKey = (runId: string) => ["run", runId] as const;
8
+ export const credentialTypesQueryKey = ["credential-types"] as const;
9
+ export const credentialFieldEnvStatusQueryKey = ["credential-field-env-status"] as const;
10
+ export const credentialInstancesQueryKey = ["credential-instances"] as const;
11
+ export const credentialInstanceWithSecretsQueryKey = (instanceId: string) =>
12
+ ["credential-instance-with-secrets", instanceId] as const;
13
+ export const workflowCredentialHealthQueryKey = (workflowId: string) =>
14
+ ["workflow-credential-health", workflowId] as const;
15
+ export const userAccountsQueryKey = ["user-accounts"] as const;
@@ -0,0 +1,167 @@
1
+ import type { QueryClient } from "@tanstack/react-query";
2
+
3
+ import { RunFinishedAtFactory } from "@codemation/core/browser";
4
+
5
+ import type { Items, PersistedRunState, RunSummary, WorkflowEvent } from "./realtimeDomainTypes";
6
+ import { runQueryKey, workflowRunsQueryKey } from "./realtimeQueryKeys";
7
+
8
+ function countItems(inputsByPort: Readonly<Record<string, Items>> | undefined): number {
9
+ return Object.values(inputsByPort ?? {}).reduce((sum, items) => sum + items.length, 0);
10
+ }
11
+
12
+ function createInitialRunState(event: Extract<WorkflowEvent, { kind: "runCreated" }>): PersistedRunState {
13
+ return {
14
+ runId: event.runId,
15
+ workflowId: event.workflowId,
16
+ startedAt: event.at,
17
+ parent: event.parent,
18
+ executionOptions: undefined,
19
+ workflowSnapshot: undefined,
20
+ mutableState: undefined,
21
+ status: "running",
22
+ pending: undefined,
23
+ queue: [],
24
+ outputsByNode: {},
25
+ nodeSnapshotsByNodeId: {},
26
+ };
27
+ }
28
+
29
+ function toRunSummary(state: PersistedRunState): RunSummary {
30
+ return {
31
+ runId: state.runId,
32
+ workflowId: state.workflowId,
33
+ startedAt: state.startedAt,
34
+ status: state.status,
35
+ finishedAt: RunFinishedAtFactory.resolveIso(state),
36
+ parent: state.parent,
37
+ executionOptions: state.executionOptions,
38
+ };
39
+ }
40
+
41
+ function mergeRunSummaryList(
42
+ existing: ReadonlyArray<RunSummary> | undefined,
43
+ summary: RunSummary,
44
+ ): ReadonlyArray<RunSummary> {
45
+ const current = [...(existing ?? [])];
46
+ const index = current.findIndex((entry) => entry.runId === summary.runId);
47
+ if (index >= 0) current[index] = summary;
48
+ else current.unshift(summary);
49
+ current.sort((left, right) => right.startedAt.localeCompare(left.startedAt));
50
+ return current;
51
+ }
52
+
53
+ export function reduceWorkflowEventIntoPersistedRunState(
54
+ current: PersistedRunState | undefined,
55
+ event: WorkflowEvent,
56
+ ): PersistedRunState {
57
+ if (event.kind === "runCreated") {
58
+ return createInitialRunState(event);
59
+ }
60
+ if (event.kind === "runSaved") {
61
+ return event.state;
62
+ }
63
+ return mergeSnapshotIntoRunState(
64
+ current,
65
+ event as Extract<WorkflowEvent, { kind: "nodeQueued" | "nodeStarted" | "nodeCompleted" | "nodeFailed" }>,
66
+ );
67
+ }
68
+
69
+ function mergeSnapshotIntoRunState(
70
+ current: PersistedRunState | undefined,
71
+ event: Extract<WorkflowEvent, { kind: "nodeQueued" | "nodeStarted" | "nodeCompleted" | "nodeFailed" }>,
72
+ ): PersistedRunState {
73
+ const base =
74
+ current ??
75
+ ({
76
+ runId: event.runId,
77
+ workflowId: event.workflowId,
78
+ startedAt: event.at,
79
+ parent: event.parent,
80
+ executionOptions: undefined,
81
+ workflowSnapshot: undefined,
82
+ mutableState: undefined,
83
+ status: event.kind === "nodeFailed" ? "failed" : "pending",
84
+ pending: undefined,
85
+ queue: [],
86
+ outputsByNode: {},
87
+ nodeSnapshotsByNodeId: {},
88
+ } satisfies PersistedRunState);
89
+
90
+ const nextNodeSnapshots = {
91
+ ...(base.nodeSnapshotsByNodeId ?? {}),
92
+ [event.snapshot.nodeId]: event.snapshot,
93
+ };
94
+ const nextOutputsByNode =
95
+ event.snapshot.outputs === undefined
96
+ ? base.outputsByNode
97
+ : {
98
+ ...(base.outputsByNode ?? {}),
99
+ [event.snapshot.nodeId]: event.snapshot.outputs,
100
+ };
101
+
102
+ const nextPending =
103
+ event.kind === "nodeQueued" || event.kind === "nodeStarted"
104
+ ? {
105
+ runId: event.runId,
106
+ activationId: event.snapshot.activationId ?? `live_${event.snapshot.nodeId}`,
107
+ workflowId: event.workflowId,
108
+ nodeId: event.snapshot.nodeId,
109
+ itemsIn: countItems(event.snapshot.inputsByPort),
110
+ inputsByPort: event.snapshot.inputsByPort ?? {},
111
+ receiptId: "live",
112
+ enqueuedAt: event.snapshot.queuedAt ?? event.at,
113
+ }
114
+ : base.pending?.nodeId === event.snapshot.nodeId
115
+ ? undefined
116
+ : base.pending;
117
+ const hasActiveSnapshots = Object.values(nextNodeSnapshots).some(
118
+ (snapshot) => snapshot.status === "queued" || snapshot.status === "running",
119
+ );
120
+ const nextStatus =
121
+ event.kind === "nodeFailed"
122
+ ? "failed"
123
+ : event.kind === "nodeCompleted" && !nextPending && !hasActiveSnapshots
124
+ ? "completed"
125
+ : event.kind === "nodeCompleted"
126
+ ? base.status
127
+ : "pending";
128
+
129
+ return {
130
+ ...base,
131
+ parent: base.parent ?? event.parent,
132
+ status: nextStatus,
133
+ pending: nextPending,
134
+ outputsByNode: nextOutputsByNode,
135
+ nodeSnapshotsByNodeId: nextNodeSnapshots,
136
+ };
137
+ }
138
+
139
+ export function applyWorkflowEvent(queryClient: QueryClient, event: WorkflowEvent): void {
140
+ const key = runQueryKey(event.runId);
141
+ const runsKey = workflowRunsQueryKey(event.workflowId);
142
+
143
+ if (event.kind === "runCreated") {
144
+ const next = reduceWorkflowEventIntoPersistedRunState(undefined, event);
145
+ queryClient.setQueryData(key, next);
146
+ queryClient.setQueryData(runsKey, (existing: ReadonlyArray<RunSummary> | undefined) =>
147
+ mergeRunSummaryList(existing, toRunSummary(next)),
148
+ );
149
+ return;
150
+ }
151
+
152
+ if (event.kind === "runSaved") {
153
+ const next = reduceWorkflowEventIntoPersistedRunState(undefined, event);
154
+ queryClient.setQueryData(key, next);
155
+ queryClient.setQueryData(runsKey, (existing: ReadonlyArray<RunSummary> | undefined) =>
156
+ mergeRunSummaryList(existing, toRunSummary(next)),
157
+ );
158
+ return;
159
+ }
160
+
161
+ const current = queryClient.getQueryData<PersistedRunState>(key);
162
+ const nextRunState = reduceWorkflowEventIntoPersistedRunState(current, event);
163
+ queryClient.setQueryData(key, nextRunState);
164
+ queryClient.setQueryData(runsKey, (existing: ReadonlyArray<RunSummary> | undefined) =>
165
+ mergeRunSummaryList(existing, toRunSummary(nextRunState)),
166
+ );
167
+ }
@@ -0,0 +1,5 @@
1
+ export type {
2
+ WorkflowDto,
3
+ WorkflowEdgeDto,
4
+ WorkflowNodeDto,
5
+ } from "@codemation/host-src/application/contracts/WorkflowViewContracts";