@datalayer/core 1.1.66 → 1.2.10

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 (210) hide show
  1. package/README.md +41 -18
  2. package/lib/api/constants.d.ts +1 -1
  3. package/lib/api/constants.js +1 -1
  4. package/lib/api/contents/attachments.js +3 -7
  5. package/lib/api/contents/datasets.d.ts +48 -0
  6. package/lib/api/contents/datasets.js +44 -7
  7. package/lib/api/contents/runtimeMounts.js +1 -1
  8. package/lib/api/contents/sandboxUid.d.ts +13 -45
  9. package/lib/api/contents/sandboxUid.js +14 -65
  10. package/lib/api/evals/client.d.ts +402 -0
  11. package/lib/api/evals/client.js +359 -0
  12. package/lib/api/evals/index.d.ts +10 -0
  13. package/lib/api/evals/index.js +18 -0
  14. package/lib/api/evals/request.d.ts +43 -0
  15. package/lib/api/evals/request.js +67 -0
  16. package/lib/api/evals/status.d.ts +27 -0
  17. package/lib/api/evals/status.js +122 -0
  18. package/lib/api/evals/types.d.ts +1335 -0
  19. package/lib/api/evals/types.js +5 -0
  20. package/lib/api/iam/connectedAgents.d.ts +29 -0
  21. package/lib/api/iam/connectedAgents.js +35 -0
  22. package/lib/api/iam/identityProviders.d.ts +76 -0
  23. package/lib/api/iam/identityProviders.js +187 -0
  24. package/lib/api/iam/index.d.ts +1 -0
  25. package/lib/api/iam/index.js +1 -0
  26. package/lib/api/iam/mcpPolicy.d.ts +102 -1
  27. package/lib/api/iam/mcpPolicy.js +38 -2
  28. package/lib/api/iam/profile.d.ts +17 -1
  29. package/lib/api/iam/profile.js +27 -0
  30. package/lib/api/iam/scimTokens.d.ts +79 -0
  31. package/lib/api/iam/scimTokens.js +141 -0
  32. package/lib/api/iam/secrets.js +9 -21
  33. package/lib/api/iam/trials.d.ts +38 -0
  34. package/lib/api/iam/trials.js +66 -0
  35. package/lib/api/index.d.ts +4 -0
  36. package/lib/api/index.js +4 -0
  37. package/lib/api/mcp/observability.d.ts +25 -9
  38. package/lib/api/mcp/observability.js +63 -50
  39. package/lib/api/orchestration/client.d.ts +53 -0
  40. package/lib/api/orchestration/client.js +105 -0
  41. package/lib/api/orchestration/events.d.ts +88 -0
  42. package/lib/api/orchestration/events.js +245 -0
  43. package/lib/api/orchestration/generated.d.ts +693 -0
  44. package/lib/api/orchestration/generated.js +687 -0
  45. package/lib/api/orchestration/index.d.ts +30 -0
  46. package/lib/api/orchestration/index.js +34 -0
  47. package/lib/api/orchestration/lifecycle.d.ts +39 -0
  48. package/lib/api/orchestration/lifecycle.js +57 -0
  49. package/lib/api/orchestration/measures.d.ts +55 -0
  50. package/lib/api/orchestration/measures.js +99 -0
  51. package/lib/api/otel/dashboards.d.ts +56 -0
  52. package/lib/api/otel/dashboards.js +50 -0
  53. package/lib/api/otel/index.d.ts +1 -0
  54. package/lib/api/otel/index.js +1 -0
  55. package/lib/api/otel/metrics.d.ts +16 -0
  56. package/lib/api/otel/metrics.js +15 -0
  57. package/lib/api/scheduler/client.d.ts +32 -0
  58. package/lib/api/scheduler/client.js +42 -0
  59. package/lib/api/scheduler/index.d.ts +8 -0
  60. package/lib/api/scheduler/index.js +16 -0
  61. package/lib/api/scheduler/request.d.ts +28 -0
  62. package/lib/api/scheduler/request.js +50 -0
  63. package/lib/api/scheduler/types.d.ts +88 -0
  64. package/lib/api/scheduler/types.js +5 -0
  65. package/lib/api/spacer/comments.d.ts +97 -0
  66. package/lib/api/spacer/comments.js +45 -0
  67. package/lib/api/spacer/index.d.ts +9 -0
  68. package/lib/api/spacer/index.js +17 -0
  69. package/lib/api/spacer/notebooks.d.ts +33 -0
  70. package/lib/api/spacer/notebooks.js +39 -0
  71. package/lib/api/spacer/request.d.ts +25 -0
  72. package/lib/api/spacer/request.js +46 -0
  73. package/lib/api/spacer/spaces.d.ts +68 -0
  74. package/lib/api/spacer/spaces.js +45 -0
  75. package/lib/api/utils/validation.d.ts +4 -4
  76. package/lib/api/utils/validation.js +10 -7
  77. package/lib/client/constants.d.ts +1 -0
  78. package/lib/client/constants.js +1 -0
  79. package/lib/components/animation/AnimatedText.d.ts +1 -44
  80. package/lib/components/animation/AnimatedText.js +6 -122
  81. package/lib/components/anonymous/AnonymousKeyExpired.d.ts +56 -0
  82. package/lib/components/anonymous/AnonymousKeyExpired.js +96 -0
  83. package/lib/components/anonymous/AnonymousKeyTimer.d.ts +63 -0
  84. package/lib/components/anonymous/AnonymousKeyTimer.js +140 -0
  85. package/lib/components/anonymous/index.d.ts +7 -0
  86. package/lib/components/anonymous/index.js +15 -0
  87. package/lib/components/avatars/UserAvatar.d.ts +7 -1
  88. package/lib/components/avatars/UserAvatar.js +15 -1
  89. package/lib/components/billing/BillingEntitySelect.d.ts +6 -0
  90. package/lib/components/billing/BillingEntitySelect.js +49 -10
  91. package/lib/components/billing/eligibility.d.ts +22 -0
  92. package/lib/components/billing/eligibility.js +27 -0
  93. package/lib/components/billing/index.d.ts +1 -0
  94. package/lib/components/billing/index.js +1 -0
  95. package/lib/components/collaboration/LiveEditorCollaborators.d.ts +5 -0
  96. package/lib/components/collaboration/LiveEditorCollaborators.js +3 -1
  97. package/lib/components/display/DatalayerBox.d.ts +2 -3
  98. package/lib/components/display/DatalayerBox.js +1 -1
  99. package/lib/components/display/NavLink.js +3 -2
  100. package/lib/components/labels/StatusLabels.d.ts +2 -10
  101. package/lib/components/labels/StatusLabels.js +2 -26
  102. package/lib/components/principal/PrincipalAppearance.d.ts +21 -42
  103. package/lib/components/principal/PrincipalAppearance.js +232 -174
  104. package/lib/components/principal/PrincipalAvatar.d.ts +8 -1
  105. package/lib/components/principal/PrincipalAvatar.js +2 -2
  106. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +8 -1
  107. package/lib/components/principal/PrincipalDetailsOverlay.js +2 -2
  108. package/lib/components/screencapture/Screencapture.js +46 -3
  109. package/lib/components/sharing/ShareAccessComponent.d.ts +45 -4
  110. package/lib/components/sharing/ShareAccessComponent.js +110 -78
  111. package/lib/components/sharing/SharingEditor.d.ts +5 -1
  112. package/lib/components/sharing/SharingEditor.js +9 -4
  113. package/lib/components/sharing/index.d.ts +1 -0
  114. package/lib/components/sharing/index.js +1 -0
  115. package/lib/components/sharing/sandboxSharing.d.ts +26 -0
  116. package/lib/components/sharing/sandboxSharing.js +41 -0
  117. package/lib/components/spaces/SpaceDetailsOverlay.d.ts +39 -0
  118. package/lib/components/spaces/SpaceDetailsOverlay.js +80 -0
  119. package/lib/components/spaces/SpaceDisplay.d.ts +38 -0
  120. package/lib/components/spaces/SpaceDisplay.js +92 -0
  121. package/lib/components/spaces/index.d.ts +4 -0
  122. package/lib/components/spaces/index.js +7 -0
  123. package/lib/components/spaces/spaceDisplayModel.d.ts +93 -0
  124. package/lib/components/spaces/spaceDisplayModel.js +170 -0
  125. package/lib/hooks/cacheConverters.d.ts +0 -7
  126. package/lib/hooks/cacheConverters.js +0 -25
  127. package/lib/hooks/index.d.ts +1 -0
  128. package/lib/hooks/index.js +1 -0
  129. package/lib/hooks/useBillingEntityStore.js +3 -0
  130. package/lib/hooks/useCache.d.ts +168 -25
  131. package/lib/hooks/useCache.js +1424 -307
  132. package/lib/hooks/useContents.d.ts +22 -1
  133. package/lib/hooks/useContents.js +90 -21
  134. package/lib/hooks/useMcp.d.ts +87 -1
  135. package/lib/hooks/useMcp.js +247 -12
  136. package/lib/hooks/useNavigate.d.ts +41 -3
  137. package/lib/hooks/useNavigate.js +106 -52
  138. package/lib/hooks/usePrincipalCacheStore.js +3 -0
  139. package/lib/hooks/usePrincipalStore.js +3 -0
  140. package/lib/hooks/useSpaceCacheStore.d.ts +50 -0
  141. package/lib/hooks/useSpaceCacheStore.js +85 -0
  142. package/lib/models/CreditsDTO.d.ts +6 -5
  143. package/lib/models/CreditsDTO.js +7 -5
  144. package/lib/models/McpBinding.d.ts +6 -0
  145. package/lib/models/Organization.d.ts +69 -0
  146. package/lib/models/Organization.js +96 -0
  147. package/lib/models/Secret.d.ts +1 -2
  148. package/lib/models/Secret.js +2 -18
  149. package/lib/models/StartedBy.d.ts +34 -0
  150. package/lib/models/StartedBy.js +36 -0
  151. package/lib/models/Team.d.ts +2 -0
  152. package/lib/models/Team.js +2 -0
  153. package/lib/models/User.d.ts +4 -0
  154. package/lib/models/User.js +3 -0
  155. package/lib/models/UserSettings.d.ts +13 -0
  156. package/lib/models/UserSettings.js +9 -0
  157. package/lib/models/contents/__fixtures__/v1-contracts.json +158 -30
  158. package/lib/navigation/components.js +2 -3
  159. package/lib/routes/publicPaths.js +4 -0
  160. package/lib/state/index.d.ts +1 -0
  161. package/lib/state/index.js +1 -0
  162. package/lib/state/sessionEnd.d.ts +55 -0
  163. package/lib/state/sessionEnd.js +162 -0
  164. package/lib/state/substates/CoreState.js +3 -3
  165. package/lib/state/substates/IAMState.js +7 -0
  166. package/lib/state/substates/LayoutState.js +12 -0
  167. package/lib/state/substates/ProfileState.d.ts +1 -0
  168. package/lib/state/substates/ProfileState.js +1 -0
  169. package/lib/utils/Lazy.d.ts +20 -0
  170. package/lib/utils/Lazy.js +32 -6
  171. package/lib/utils/Screencapture.js +3 -0
  172. package/lib/utils/WithSuspense.d.ts +11 -1
  173. package/lib/utils/WithSuspense.js +11 -1
  174. package/lib/views/mcp/AdmittedClients.d.ts +44 -0
  175. package/lib/views/mcp/AdmittedClients.js +59 -0
  176. package/lib/views/mcp/ApprovalQueue.d.ts +66 -0
  177. package/lib/views/mcp/ApprovalQueue.js +95 -0
  178. package/lib/views/mcp/ConnectedAgents.js +38 -3
  179. package/lib/views/mcp/EnterpriseConsole.d.ts +1 -1
  180. package/lib/views/mcp/EnterpriseConsole.js +23 -1
  181. package/lib/views/mcp/IdentityProviders.d.ts +33 -0
  182. package/lib/views/mcp/IdentityProviders.js +299 -0
  183. package/lib/views/mcp/McpDashboard.js +90 -7
  184. package/lib/views/mcp/McpObservability.d.ts +30 -1
  185. package/lib/views/mcp/McpObservability.js +105 -19
  186. package/lib/views/mcp/NotebookRuns.d.ts +39 -0
  187. package/lib/views/mcp/NotebookRuns.js +44 -0
  188. package/lib/views/mcp/OrganizationPolicy.js +2 -1
  189. package/lib/views/mcp/PersonalPolicy.js +2 -1
  190. package/lib/views/mcp/PolicyForm.d.ts +17 -1
  191. package/lib/views/mcp/PolicyForm.js +25 -3
  192. package/lib/views/mcp/PolicyHistory.d.ts +13 -0
  193. package/lib/views/mcp/PolicyHistory.js +14 -1
  194. package/lib/views/mcp/RunDetail.d.ts +87 -0
  195. package/lib/views/mcp/RunDetail.js +186 -0
  196. package/lib/views/mcp/ScimProvisioning.d.ts +54 -0
  197. package/lib/views/mcp/ScimProvisioning.js +173 -0
  198. package/lib/views/mcp/TeamPolicies.js +66 -5
  199. package/lib/views/mcp/ToolAccess.d.ts +60 -0
  200. package/lib/views/mcp/ToolAccess.js +101 -0
  201. package/lib/views/mcp/TraceTimeline.d.ts +81 -0
  202. package/lib/views/mcp/TraceTimeline.js +132 -0
  203. package/lib/views/mcp/index.d.ts +5 -0
  204. package/lib/views/mcp/index.js +5 -0
  205. package/lib/views/otel/simpleAuthStore.js +3 -0
  206. package/lib/views/secrets/SecretEdit.js +3 -2
  207. package/lib/views/secrets/SecretNew.js +5 -1
  208. package/package.json +269 -264
  209. package/scripts/generate-mcp-types.py +1 -1
  210. package/scripts/generate-orchestration-types.py +920 -0
@@ -0,0 +1,53 @@
1
+ import { type EvalsClientOptions, type EvalsQuery } from '../evals/request';
2
+ import { type AgentsAttach, type AgentsCreate, type AgentsDiscover, type CancelAnswer, type CollectAnswer, type CommandAnswer, type DelegateAnswer, type DiscoverAnswer, type ExecutionAnswer, type ExecutionState, type ExecutionsAnswer, type ExecutionsCancel, type ExecutionsCheckpoint, type ExecutionsCollect, type ExecutionsDelegate, type ExecutionsPause, type ExecutionsResume, type ExecutionsSteer, type ExecutionsTerminate, type OrchestrationOperation, type ReportAnswer, type WorkerAnswer } from './generated';
3
+ /** Who calls: the service origin, the caller's token, and the account the executions belong to. */
4
+ export type OrchestrationClientOptions = EvalsClientOptions;
5
+ /**
6
+ * One operation's method and path under `/api/ai-agents/v1`, with its
7
+ * parameters filled in and encoded.
8
+ *
9
+ * @throws Error when the control plane has no such operation, or a
10
+ * parameter the path names is missing.
11
+ */
12
+ export declare const operationPath: (operation: string, parameters?: Record<string, string>) => {
13
+ method: OrchestrationOperation["method"];
14
+ path: string;
15
+ };
16
+ /** The full URL of one operation, with the account scope and a query. */
17
+ export declare const operationUrl: (options: OrchestrationClientOptions, operation: string, parameters?: Record<string, string>, query?: EvalsQuery) => string;
18
+ /** `agents.discover`: the workers meeting every constraint the command states. */
19
+ export declare const discoverAgents: (options: OrchestrationClientOptions, command: AgentsDiscover) => Promise<DiscoverAnswer>;
20
+ /** `agents.create`: bring a worker's compute up. */
21
+ export declare const createAgent: (options: OrchestrationClientOptions, command: AgentsCreate) => Promise<WorkerAnswer>;
22
+ /** `agents.attach`: a worker or a session that is already there. */
23
+ export declare const attachAgent: (options: OrchestrationClientOptions, command: AgentsAttach) => Promise<WorkerAnswer>;
24
+ /** `executions.delegate`: an objective and its context, to a worker. */
25
+ export declare const delegateExecution: (options: OrchestrationClientOptions, command: ExecutionsDelegate) => Promise<DelegateAnswer>;
26
+ /** `executions.steer`: instructions added while the work runs. */
27
+ export declare const steerExecution: (options: OrchestrationClientOptions, command: ExecutionsSteer) => Promise<CommandAnswer>;
28
+ /** `executions.pause`, where the worker's protocol can pause. */
29
+ export declare const pauseExecution: (options: OrchestrationClientOptions, command: ExecutionsPause) => Promise<CommandAnswer>;
30
+ /** `executions.resume`, from where it stopped or from a checkpoint. */
31
+ export declare const resumeExecution: (options: OrchestrationClientOptions, command: ExecutionsResume) => Promise<CommandAnswer>;
32
+ /** `executions.cancel`: stop the work, and by default everything below it. */
33
+ export declare const cancelExecution: (options: OrchestrationClientOptions, command: ExecutionsCancel) => Promise<CancelAnswer>;
34
+ /** `executions.checkpoint`, where the worker's protocol keeps state. */
35
+ export declare const checkpointExecution: (options: OrchestrationClientOptions, command: ExecutionsCheckpoint) => Promise<CommandAnswer>;
36
+ /** `executions.collect`: the artifacts of an execution and of its children. */
37
+ export declare const collectExecution: (options: OrchestrationClientOptions, command: ExecutionsCollect) => Promise<CollectAnswer>;
38
+ /** `executions.terminate`: release the worker, where its protocol can. */
39
+ export declare const terminateExecution: (options: OrchestrationClientOptions, command: ExecutionsTerminate) => Promise<CommandAnswer>;
40
+ /** One execution, its attempts, and the milestones it reached. */
41
+ export declare const getExecution: (options: OrchestrationClientOptions, executionId: string) => Promise<ExecutionAnswer>;
42
+ /**
43
+ * `executions.report`: the execution's live report, a document in the
44
+ * account's orchestration space, written the first time it is asked for and
45
+ * the same one after that.
46
+ */
47
+ export declare const openExecutionReport: (options: OrchestrationClientOptions, executionId: string) => Promise<ReportAnswer>;
48
+ /** The account's executions, oldest first: a tree by its root, a level by its parent. */
49
+ export declare const listExecutions: (options: OrchestrationClientOptions, filter?: {
50
+ rootExecutionId?: string;
51
+ parentExecutionId?: string;
52
+ status?: ExecutionState;
53
+ }) => Promise<ExecutionsAnswer>;
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2023-2026 Datalayer, Inc.
7
+ * Distributed under the terms of the Modified BSD License.
8
+ */
9
+ /**
10
+ * The orchestration control plane, as a caller reaches it.
11
+ *
12
+ * Every path comes from `ORCHESTRATION_API`, which is generated from the
13
+ * control plane's own OpenAPI document: this module spells no URL itself, so
14
+ * a route that moves on the service moves here when the types are
15
+ * regenerated — or fails the check that they were not. A view calls these
16
+ * functions and never builds an orchestration path of its own.
17
+ *
18
+ * Bodies are the canonical commands as they are and answers the envelopes
19
+ * the service returns; the wire is camel case on both sides, so nothing is
20
+ * converted.
21
+ *
22
+ * @module api/orchestration/client
23
+ */
24
+ import { API_BASE_PATHS } from '../constants.js';
25
+ import { aiAgentsRequest, aiAgentsUrl, } from '../evals/request.js';
26
+ import { ORCHESTRATION_API, } from './generated.js';
27
+ /**
28
+ * One operation's method and path under `/api/ai-agents/v1`, with its
29
+ * parameters filled in and encoded.
30
+ *
31
+ * @throws Error when the control plane has no such operation, or a
32
+ * parameter the path names is missing.
33
+ */
34
+ export const operationPath = (operation, parameters = {}) => {
35
+ const found = ORCHESTRATION_API.find(one => one.operation === operation);
36
+ if (!found) {
37
+ throw new Error(`The control plane has no operation '${operation}'.`);
38
+ }
39
+ const path = found.path.replace(/\{([^}]+)\}/g, (_, name) => {
40
+ const value = parameters[name];
41
+ if (value === undefined || value === '') {
42
+ throw new Error(`'${operation}' needs '${name}'.`);
43
+ }
44
+ return encodeURIComponent(value);
45
+ });
46
+ if (!path.startsWith(API_BASE_PATHS.AI_AGENTS)) {
47
+ throw new Error(`'${operation}' is not under ${API_BASE_PATHS.AI_AGENTS}: ${found.path}`);
48
+ }
49
+ return {
50
+ method: found.method,
51
+ path: path.slice(API_BASE_PATHS.AI_AGENTS.length),
52
+ };
53
+ };
54
+ /** The full URL of one operation, with the account scope and a query. */
55
+ export const operationUrl = (options, operation, parameters = {}, query = {}) => aiAgentsUrl(options, operationPath(operation, parameters).path, query);
56
+ const call = (options, operation, init = {}) => {
57
+ const { method, path } = operationPath(operation, init.parameters);
58
+ return aiAgentsRequest(options, path, {
59
+ method,
60
+ body: init.body,
61
+ query: init.query,
62
+ });
63
+ };
64
+ /** `agents.discover`: the workers meeting every constraint the command states. */
65
+ export const discoverAgents = (options, command) => call(options, 'agents.discover', { body: command });
66
+ /** `agents.create`: bring a worker's compute up. */
67
+ export const createAgent = (options, command) => call(options, 'agents.create', { body: command });
68
+ /** `agents.attach`: a worker or a session that is already there. */
69
+ export const attachAgent = (options, command) => call(options, 'agents.attach', { body: command });
70
+ /** `executions.delegate`: an objective and its context, to a worker. */
71
+ export const delegateExecution = (options, command) => call(options, 'executions.delegate', { body: command });
72
+ /** `executions.steer`: instructions added while the work runs. */
73
+ export const steerExecution = (options, command) => call(options, 'executions.steer', { body: command });
74
+ /** `executions.pause`, where the worker's protocol can pause. */
75
+ export const pauseExecution = (options, command) => call(options, 'executions.pause', { body: command });
76
+ /** `executions.resume`, from where it stopped or from a checkpoint. */
77
+ export const resumeExecution = (options, command) => call(options, 'executions.resume', { body: command });
78
+ /** `executions.cancel`: stop the work, and by default everything below it. */
79
+ export const cancelExecution = (options, command) => call(options, 'executions.cancel', { body: command });
80
+ /** `executions.checkpoint`, where the worker's protocol keeps state. */
81
+ export const checkpointExecution = (options, command) => call(options, 'executions.checkpoint', { body: command });
82
+ /** `executions.collect`: the artifacts of an execution and of its children. */
83
+ export const collectExecution = (options, command) => call(options, 'executions.collect', { body: command });
84
+ /** `executions.terminate`: release the worker, where its protocol can. */
85
+ export const terminateExecution = (options, command) => call(options, 'executions.terminate', { body: command });
86
+ /** One execution, its attempts, and the milestones it reached. */
87
+ export const getExecution = (options, executionId) => call(options, 'executions.get', {
88
+ parameters: { execution_id: executionId },
89
+ });
90
+ /**
91
+ * `executions.report`: the execution's live report, a document in the
92
+ * account's orchestration space, written the first time it is asked for and
93
+ * the same one after that.
94
+ */
95
+ export const openExecutionReport = (options, executionId) => call(options, 'executions.report', {
96
+ parameters: { execution_id: executionId },
97
+ });
98
+ /** The account's executions, oldest first: a tree by its root, a level by its parent. */
99
+ export const listExecutions = (options, filter = {}) => call(options, 'executions.list', {
100
+ query: {
101
+ rootExecutionId: filter.rootExecutionId,
102
+ parentExecutionId: filter.parentExecutionId,
103
+ status: filter.status,
104
+ },
105
+ });
@@ -0,0 +1,88 @@
1
+ import { type OrchestrationClientOptions } from './client';
2
+ import type { ExecutionEvent, LifecycleEvent, TreeSummary } from './generated';
3
+ /** The user channel's event for a tree that moved, and the stream's roll-up. */
4
+ export declare const TREE_EVENT = "orchestration.tree";
5
+ /** One Server-Sent Event, as it was framed. */
6
+ export interface ServerSentEvent {
7
+ id?: string;
8
+ event: string;
9
+ data: string;
10
+ }
11
+ /**
12
+ * Split what has arrived into the complete events and what is left over,
13
+ * which is the beginning of an event still arriving.
14
+ */
15
+ export declare const readServerSentEvents: (buffer: string) => {
16
+ events: ServerSentEvent[];
17
+ rest: string;
18
+ };
19
+ /** The service refused the subscription; asking again would be refused again. */
20
+ export declare class SubscriptionRefused extends Error {
21
+ readonly status: number;
22
+ readonly detail: string;
23
+ constructor(status: number, detail: string);
24
+ }
25
+ /** What `fetch` answers, as much of it as a subscription reads. */
26
+ interface StreamedResponse {
27
+ ok: boolean;
28
+ status: number;
29
+ body: ReadableStream<Uint8Array> | null;
30
+ text(): Promise<string>;
31
+ }
32
+ export interface SubscribeOptions {
33
+ /** Every event of the tree below the execution too; the service's default. */
34
+ includeChildren?: boolean;
35
+ /** Replay the execution's own events after this sequence. */
36
+ fromSequence?: number;
37
+ /** Only these lifecycle events; every event when empty. */
38
+ events?: LifecycleEvent[];
39
+ /** The id of the last event already received, to resume after it. */
40
+ lastEventId?: string;
41
+ /** Each event once, in the order the service sent them, with the cursor it moved the subscription to. */
42
+ onEvent: (event: ExecutionEvent, cursor: string) => void;
43
+ /** What the executions the subscription covers are doing, after each batch of events that changed it. */
44
+ onTree?: (tree: TreeSummary, cursor: string) => void;
45
+ /** The subscription ended because every execution it covers is over. */
46
+ onEnd?: () => void;
47
+ /** How many drops in a row, with no event between them, before giving up. */
48
+ maxReconnects?: number;
49
+ /** How long to wait before reconnecting, in milliseconds. */
50
+ reconnectDelayMs?: number;
51
+ signal?: AbortSignal;
52
+ /** The `fetch` to use; the global one by default. */
53
+ fetch?: (url: string, init: RequestInit) => Promise<StreamedResponse>;
54
+ }
55
+ export interface Subscription {
56
+ /** Settles when the stream ends, is aborted, or cannot be resumed. */
57
+ done: Promise<void>;
58
+ /** The id a later subscription resumes from. */
59
+ lastEventId: () => string | undefined;
60
+ }
61
+ /**
62
+ * Subscribe to an execution — and its tree — until it is over.
63
+ *
64
+ * A dropped connection, before the service answered or in the middle of the
65
+ * stream, is resumed from the last event received. A refusal is not: it
66
+ * rejects `done` with `SubscriptionRefused`. An abort ends the subscription
67
+ * quietly, because stopping is the caller's decision rather than a failure.
68
+ */
69
+ export declare const subscribeToExecution: (options: OrchestrationClientOptions, executionId: string, subscribe: SubscribeOptions) => Subscription;
70
+ /**
71
+ * What a tree is doing, worked out from its canonical events alone (O2-03).
72
+ *
73
+ * The same summary the subscription sends as `orchestration.tree`: each
74
+ * execution's latest state, its parent, its worker and its goal — the message
75
+ * of the event that created it — and its depth below the first execution the
76
+ * events cover. Each execution's events are read in their own sequence,
77
+ * whatever order they arrived in.
78
+ */
79
+ export declare const treeFromEvents: (events: readonly ExecutionEvent[]) => TreeSummary;
80
+ /** A message of the app's user channel announcing that a tree moved. */
81
+ export interface TreeAnnouncement {
82
+ channel: string;
83
+ event: typeof TREE_EVENT;
84
+ data: TreeSummary;
85
+ }
86
+ /** Whether a user-channel message is a tree announcement. */
87
+ export declare const isTreeAnnouncement: (message: unknown) => message is TreeAnnouncement;
88
+ export {};
@@ -0,0 +1,245 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { operationUrl } from './client.js';
6
+ import { isTerminal } from './lifecycle.js';
7
+ /** The user channel's event for a tree that moved, and the stream's roll-up. */
8
+ export const TREE_EVENT = 'orchestration.tree';
9
+ /**
10
+ * Split what has arrived into the complete events and what is left over,
11
+ * which is the beginning of an event still arriving.
12
+ */
13
+ export const readServerSentEvents = (buffer) => {
14
+ const blocks = buffer.replace(/\r\n/g, '\n').split('\n\n');
15
+ const rest = blocks.pop() ?? '';
16
+ const events = blocks
17
+ .filter(block => block.trim() !== '')
18
+ .map(block => {
19
+ const framed = { event: 'message', data: '' };
20
+ const data = [];
21
+ for (const line of block.split('\n')) {
22
+ if (line.startsWith(':')) {
23
+ continue;
24
+ }
25
+ const colon = line.indexOf(':');
26
+ const field = colon === -1 ? line : line.slice(0, colon);
27
+ const value = colon === -1 ? '' : line.slice(colon + 1).replace(/^ /, '');
28
+ if (field === 'id') {
29
+ framed.id = value;
30
+ }
31
+ else if (field === 'event') {
32
+ framed.event = value;
33
+ }
34
+ else if (field === 'data') {
35
+ data.push(value);
36
+ }
37
+ }
38
+ framed.data = data.join('\n');
39
+ return framed;
40
+ });
41
+ return { events, rest };
42
+ };
43
+ /** The service refused the subscription; asking again would be refused again. */
44
+ export class SubscriptionRefused extends Error {
45
+ status;
46
+ detail;
47
+ constructor(status, detail) {
48
+ super(`The subscription was refused with ${status}: ${detail}`);
49
+ this.status = status;
50
+ this.detail = detail;
51
+ this.name = 'SubscriptionRefused';
52
+ }
53
+ }
54
+ const pause = (milliseconds, signal) => new Promise(resolve => {
55
+ if (milliseconds <= 0 || signal?.aborted) {
56
+ resolve();
57
+ return;
58
+ }
59
+ const timer = setTimeout(resolve, milliseconds);
60
+ signal?.addEventListener('abort', () => {
61
+ clearTimeout(timer);
62
+ resolve();
63
+ }, { once: true });
64
+ });
65
+ /**
66
+ * Subscribe to an execution — and its tree — until it is over.
67
+ *
68
+ * A dropped connection, before the service answered or in the middle of the
69
+ * stream, is resumed from the last event received. A refusal is not: it
70
+ * rejects `done` with `SubscriptionRefused`. An abort ends the subscription
71
+ * quietly, because stopping is the caller's decision rather than a failure.
72
+ */
73
+ export const subscribeToExecution = (options, executionId, subscribe) => {
74
+ let lastEventId = subscribe.lastEventId;
75
+ const fetcher = subscribe.fetch ??
76
+ ((url, init) => fetch(url, init));
77
+ const query = {
78
+ includeChildren: subscribe.includeChildren,
79
+ fromSequence: subscribe.fromSequence,
80
+ };
81
+ const address = new URL(operationUrl(options, 'executions.subscribe', { execution_id: executionId }, query));
82
+ for (const wanted of subscribe.events ?? []) {
83
+ address.searchParams.append('events', wanted);
84
+ }
85
+ const url = address.toString();
86
+ const maxReconnects = subscribe.maxReconnects ?? 5;
87
+ const run = async () => {
88
+ let dropsInARow = 0;
89
+ for (;;) {
90
+ const headers = { Accept: 'text/event-stream' };
91
+ if (options.token) {
92
+ headers.Authorization = `Bearer ${options.token}`;
93
+ }
94
+ if (lastEventId) {
95
+ headers['Last-Event-ID'] = lastEventId;
96
+ }
97
+ let response;
98
+ try {
99
+ response = await fetcher(url, {
100
+ headers,
101
+ signal: subscribe.signal,
102
+ credentials: 'include',
103
+ });
104
+ }
105
+ catch {
106
+ if (subscribe.signal?.aborted) {
107
+ return;
108
+ }
109
+ }
110
+ if (response && !response.ok) {
111
+ throw new SubscriptionRefused(response.status, await response.text());
112
+ }
113
+ let ended = false;
114
+ if (response?.body) {
115
+ const reader = response.body.getReader();
116
+ const decoder = new TextDecoder();
117
+ let buffer = '';
118
+ for (;;) {
119
+ let chunk;
120
+ try {
121
+ chunk = await reader.read();
122
+ }
123
+ catch {
124
+ if (subscribe.signal?.aborted) {
125
+ return;
126
+ }
127
+ break;
128
+ }
129
+ if (chunk.done) {
130
+ break;
131
+ }
132
+ buffer += decoder.decode(chunk.value, { stream: true });
133
+ const { events, rest } = readServerSentEvents(buffer);
134
+ buffer = rest;
135
+ for (const framed of events) {
136
+ if (framed.event === 'end') {
137
+ ended = true;
138
+ continue;
139
+ }
140
+ if (framed.id) {
141
+ lastEventId = framed.id;
142
+ }
143
+ if (framed.event === TREE_EVENT) {
144
+ subscribe.onTree?.(JSON.parse(framed.data), framed.id ?? '');
145
+ }
146
+ else {
147
+ subscribe.onEvent(JSON.parse(framed.data), framed.id ?? '');
148
+ }
149
+ dropsInARow = 0;
150
+ }
151
+ }
152
+ }
153
+ if (ended) {
154
+ subscribe.onEnd?.();
155
+ return;
156
+ }
157
+ if (subscribe.signal?.aborted) {
158
+ return;
159
+ }
160
+ dropsInARow += 1;
161
+ if (dropsInARow > maxReconnects) {
162
+ throw new Error(`The subscription to '${executionId}' dropped ${dropsInARow} times with no event in between.`);
163
+ }
164
+ await pause(subscribe.reconnectDelayMs ?? 1000, subscribe.signal);
165
+ }
166
+ };
167
+ return { done: run(), lastEventId: () => lastEventId };
168
+ };
169
+ /**
170
+ * What a tree is doing, worked out from its canonical events alone (O2-03).
171
+ *
172
+ * The same summary the subscription sends as `orchestration.tree`: each
173
+ * execution's latest state, its parent, its worker and its goal — the message
174
+ * of the event that created it — and its depth below the first execution the
175
+ * events cover. Each execution's events are read in their own sequence,
176
+ * whatever order they arrived in.
177
+ */
178
+ export const treeFromEvents = (events) => {
179
+ const nodes = new Map();
180
+ let root = '';
181
+ const ordered = [...events].sort((one, other) => one.executionId === other.executionId
182
+ ? one.sequence - other.sequence
183
+ : one.executionId < other.executionId
184
+ ? -1
185
+ : 1);
186
+ for (const event of ordered) {
187
+ root = root || event.rootExecutionId;
188
+ let node = nodes.get(event.executionId);
189
+ if (!node) {
190
+ node = {
191
+ parent: event.parentExecutionId ?? null,
192
+ goal: event.message ?? '',
193
+ agentId: '',
194
+ updatedAt: event.emittedAt,
195
+ };
196
+ nodes.set(event.executionId, node);
197
+ }
198
+ node.agentId = event.agentId ?? node.agentId;
199
+ node.protocol = event.protocol ?? node.protocol;
200
+ node.status = event.state ?? node.status;
201
+ node.updatedAt = event.emittedAt;
202
+ }
203
+ const depth = (executionId) => {
204
+ const parent = nodes.get(executionId)?.parent;
205
+ return parent && nodes.has(parent) ? depth(parent) + 1 : 0;
206
+ };
207
+ const executions = [];
208
+ for (const [executionId, node] of nodes) {
209
+ if (node.status && node.protocol) {
210
+ executions.push({
211
+ executionId,
212
+ parentExecutionId: node.parent,
213
+ depth: depth(executionId),
214
+ status: node.status,
215
+ agentId: node.agentId,
216
+ protocol: node.protocol,
217
+ goal: node.goal,
218
+ updatedAt: node.updatedAt,
219
+ });
220
+ }
221
+ }
222
+ const counts = {};
223
+ for (const one of executions) {
224
+ counts[one.status] = (counts[one.status] ?? 0) + 1;
225
+ }
226
+ return {
227
+ rootExecutionId: root,
228
+ executions,
229
+ counts,
230
+ terminal: executions.every(one => isTerminal(one.status)),
231
+ };
232
+ };
233
+ /** Whether a user-channel message is a tree announcement. */
234
+ export const isTreeAnnouncement = (message) => {
235
+ if (typeof message !== 'object' || message === null) {
236
+ return false;
237
+ }
238
+ const { event, data } = message;
239
+ return (event === TREE_EVENT &&
240
+ typeof data === 'object' &&
241
+ data !== null &&
242
+ typeof data.rootExecutionId ===
243
+ 'string' &&
244
+ Array.isArray(data.executions));
245
+ };