@dxos/plugin-automation 0.8.4-main.9be5663bfe → 0.8.4-main.abd8ff62ef

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 (192) hide show
  1. package/dist/lib/browser/{chunk-WQLEMRPU.mjs → chunk-CHUTFU3D.mjs} +1 -1
  2. package/dist/lib/browser/chunk-CHUTFU3D.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-POEIL4RN.mjs → chunk-RE64VLSV.mjs} +3 -3
  4. package/dist/lib/browser/{chunk-POEIL4RN.mjs.map → chunk-RE64VLSV.mjs.map} +3 -3
  5. package/dist/lib/browser/{create-trigger-from-template-JZ62EZTB.mjs → create-trigger-from-template-JLBSJRVB.mjs} +9 -16
  6. package/dist/lib/browser/create-trigger-from-template-JLBSJRVB.mjs.map +7 -0
  7. package/dist/lib/browser/hooks/index.mjs +61 -17
  8. package/dist/lib/browser/hooks/index.mjs.map +3 -3
  9. package/dist/lib/browser/index.mjs +6 -71
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/operations/index.mjs +4 -4
  13. package/dist/lib/browser/operations/index.mjs.map +3 -3
  14. package/dist/lib/browser/translations.mjs +47 -0
  15. package/dist/lib/browser/translations.mjs.map +7 -0
  16. package/dist/lib/browser/types/index.mjs +1 -1
  17. package/dist/lib/node-esm/{chunk-SP3P4OUI.mjs → chunk-HHIHREME.mjs} +3 -3
  18. package/dist/lib/node-esm/{chunk-SP3P4OUI.mjs.map → chunk-HHIHREME.mjs.map} +3 -3
  19. package/dist/lib/node-esm/{chunk-JWZAVQLF.mjs → chunk-NWQMBY32.mjs} +1 -1
  20. package/dist/lib/node-esm/chunk-NWQMBY32.mjs.map +7 -0
  21. package/dist/lib/node-esm/{create-trigger-from-template-224Z7WJI.mjs → create-trigger-from-template-FUQ3LUIF.mjs} +9 -16
  22. package/dist/lib/node-esm/create-trigger-from-template-FUQ3LUIF.mjs.map +7 -0
  23. package/dist/lib/node-esm/hooks/index.mjs +61 -17
  24. package/dist/lib/node-esm/hooks/index.mjs.map +3 -3
  25. package/dist/lib/node-esm/index.mjs +6 -71
  26. package/dist/lib/node-esm/index.mjs.map +4 -4
  27. package/dist/lib/node-esm/meta.json +1 -1
  28. package/dist/lib/node-esm/operations/index.mjs +4 -4
  29. package/dist/lib/node-esm/operations/index.mjs.map +3 -3
  30. package/dist/lib/node-esm/translations.mjs +48 -0
  31. package/dist/lib/node-esm/translations.mjs.map +7 -0
  32. package/dist/lib/node-esm/types/index.mjs +1 -1
  33. package/dist/types/src/AutomationPlugin.d.ts +1 -0
  34. package/dist/types/src/AutomationPlugin.d.ts.map +1 -1
  35. package/dist/types/src/{cli/plugin.d.ts → AutomationPlugin.node.d.ts} +2 -1
  36. package/dist/types/src/AutomationPlugin.node.d.ts.map +1 -0
  37. package/dist/types/src/AutomationPlugin.test.d.ts +2 -0
  38. package/dist/types/src/AutomationPlugin.test.d.ts.map +1 -0
  39. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  40. package/dist/types/src/capabilities/compute-runtime.d.ts +8 -0
  41. package/dist/types/src/capabilities/compute-runtime.d.ts.map +1 -1
  42. package/dist/types/src/capabilities/index.d.ts +1 -1
  43. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  44. package/dist/types/src/capabilities/node.d.ts +3 -0
  45. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  46. package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
  47. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
  48. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  49. package/dist/types/src/commands/index.d.ts.map +1 -0
  50. package/dist/types/src/{cli/commands → commands}/trigger/create/index.d.ts +6 -6
  51. package/dist/types/src/commands/trigger/create/index.d.ts.map +1 -0
  52. package/dist/types/src/{cli/commands → commands}/trigger/create/queue.d.ts +1 -1
  53. package/dist/types/src/commands/trigger/create/queue.d.ts.map +1 -0
  54. package/dist/types/src/{cli/commands → commands}/trigger/create/subscription.d.ts +1 -1
  55. package/dist/types/src/commands/trigger/create/subscription.d.ts.map +1 -0
  56. package/dist/types/src/{cli/commands → commands}/trigger/create/timer.d.ts +1 -1
  57. package/dist/types/src/commands/trigger/create/timer.d.ts.map +1 -0
  58. package/dist/types/src/{cli/commands → commands}/trigger/index.d.ts +7 -7
  59. package/dist/types/src/commands/trigger/index.d.ts.map +1 -0
  60. package/dist/types/src/commands/trigger/list.d.ts.map +1 -0
  61. package/dist/types/src/commands/trigger/options.d.ts.map +1 -0
  62. package/dist/types/src/{cli/commands → commands}/trigger/remove.d.ts +1 -1
  63. package/dist/types/src/commands/trigger/remove.d.ts.map +1 -0
  64. package/dist/types/src/{cli/commands → commands}/trigger/update/index.d.ts +5 -5
  65. package/dist/types/src/commands/trigger/update/index.d.ts.map +1 -0
  66. package/dist/types/src/commands/trigger/update/queue.d.ts.map +1 -0
  67. package/dist/types/src/commands/trigger/update/subscription.d.ts.map +1 -0
  68. package/dist/types/src/commands/trigger/update/timer.d.ts.map +1 -0
  69. package/dist/types/src/{cli/commands → commands}/trigger/util.d.ts +2 -2
  70. package/dist/types/src/commands/trigger/util.d.ts.map +1 -0
  71. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts +1 -1
  72. package/dist/types/src/components/AutomationPanel/AutomationPanel.d.ts.map +1 -1
  73. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts +32 -29
  74. package/dist/types/src/components/AutomationPanel/AutomationPanel.stories.d.ts.map +1 -1
  75. package/dist/types/src/components/AutomationPanel/index.d.ts.map +1 -1
  76. package/dist/types/src/components/FunctionsPanel/FunctionsPanel.d.ts.map +1 -1
  77. package/dist/types/src/components/FunctionsPanel/index.d.ts.map +1 -1
  78. package/dist/types/src/components/FunctionsRegistry/FunctionsRegistry.d.ts.map +1 -1
  79. package/dist/types/src/components/FunctionsRegistry/index.d.ts.map +1 -1
  80. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts +5 -5
  81. package/dist/types/src/components/TriggerEditor/FunctionInputEditor.d.ts.map +1 -1
  82. package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts +4 -4
  83. package/dist/types/src/components/TriggerEditor/SpecSelector.d.ts.map +1 -1
  84. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -1
  85. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
  86. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +95 -91
  87. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
  88. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts +3 -1
  89. package/dist/types/src/containers/AutomationSettings/AutomationSettings.d.ts.map +1 -1
  90. package/dist/types/src/containers/FunctionsContainer/FunctionsContainer.d.ts +2 -4
  91. package/dist/types/src/containers/FunctionsContainer/FunctionsContainer.d.ts.map +1 -1
  92. package/dist/types/src/containers/TriggerSettings/TriggerSettings.d.ts +3 -3
  93. package/dist/types/src/containers/TriggerSettings/TriggerSettings.d.ts.map +1 -1
  94. package/dist/types/src/hooks/useComputeRuntime.d.ts +1 -0
  95. package/dist/types/src/hooks/useComputeRuntime.d.ts.map +1 -1
  96. package/dist/types/src/hooks/useComputeRuntimeCallback.d.ts.map +1 -1
  97. package/dist/types/src/hooks/useComputeRuntimeService.d.ts +14 -2
  98. package/dist/types/src/hooks/useComputeRuntimeService.d.ts.map +1 -1
  99. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +1 -1
  100. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
  101. package/dist/types/src/index.d.ts +2 -1
  102. package/dist/types/src/index.d.ts.map +1 -1
  103. package/dist/types/src/operations/create-trigger-from-template.d.ts +1 -1
  104. package/dist/types/src/operations/create-trigger-from-template.d.ts.map +1 -1
  105. package/dist/types/src/operations/definitions.d.ts +4 -4
  106. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  107. package/dist/types/src/operations/index.d.ts +1 -1
  108. package/dist/types/src/operations/index.d.ts.map +1 -1
  109. package/dist/types/src/testing/test-functions.d.ts +77 -77
  110. package/dist/types/src/translations.d.ts +32 -30
  111. package/dist/types/src/translations.d.ts.map +1 -1
  112. package/dist/types/src/types/capabilities.d.ts +6 -7
  113. package/dist/types/src/types/capabilities.d.ts.map +1 -1
  114. package/dist/types/src/types/events.d.ts.map +1 -1
  115. package/dist/types/src/types/schema.d.ts.map +1 -1
  116. package/dist/types/tsconfig.tsbuildinfo +1 -1
  117. package/package.json +60 -60
  118. package/src/{cli/plugin.ts → AutomationPlugin.node.ts} +8 -2
  119. package/src/AutomationPlugin.test.ts +27 -0
  120. package/src/AutomationPlugin.tsx +6 -6
  121. package/src/capabilities/app-graph-builder.ts +10 -6
  122. package/src/capabilities/compute-runtime.ts +216 -139
  123. package/src/capabilities/index.ts +1 -1
  124. package/src/capabilities/node.ts +6 -0
  125. package/src/capabilities/operation-handler.ts +1 -1
  126. package/src/capabilities/react-surface.tsx +6 -6
  127. package/src/{cli/commands → commands}/trigger/create/queue.ts +2 -6
  128. package/src/{cli/commands → commands}/trigger/create/subscription.ts +6 -10
  129. package/src/{cli/commands → commands}/trigger/create/timer.ts +2 -6
  130. package/src/{cli/commands → commands}/trigger/list.ts +5 -3
  131. package/src/{cli/commands → commands}/trigger/remove.ts +1 -1
  132. package/src/{cli/commands → commands}/trigger/update/queue.ts +5 -6
  133. package/src/{cli/commands → commands}/trigger/update/subscription.ts +5 -6
  134. package/src/{cli/commands → commands}/trigger/update/timer.ts +5 -6
  135. package/src/{cli/commands → commands}/trigger/util.ts +5 -4
  136. package/src/components/AutomationPanel/AutomationPanel.stories.tsx +2 -3
  137. package/src/components/AutomationPanel/AutomationPanel.tsx +9 -6
  138. package/src/components/FunctionsPanel/FunctionsPanel.tsx +1 -2
  139. package/src/components/FunctionsRegistry/FunctionsRegistry.tsx +1 -1
  140. package/src/components/TriggerEditor/FunctionInputEditor.tsx +1 -1
  141. package/src/components/TriggerEditor/SpecSelector.tsx +6 -11
  142. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +4 -5
  143. package/src/components/TriggerEditor/TriggerEditor.tsx +2 -3
  144. package/src/containers/AutomationSettings/AutomationSettings.tsx +5 -2
  145. package/src/containers/FunctionsContainer/FunctionsContainer.tsx +3 -4
  146. package/src/containers/TriggerSettings/TriggerSettings.tsx +29 -7
  147. package/src/hooks/useComputeRuntime.ts +17 -3
  148. package/src/hooks/useComputeRuntimeService.ts +49 -9
  149. package/src/hooks/useTriggerRuntimeControls.ts +6 -3
  150. package/src/index.ts +5 -1
  151. package/src/operations/create-trigger-from-template.ts +6 -10
  152. package/src/operations/definitions.ts +1 -1
  153. package/src/operations/index.ts +1 -1
  154. package/src/translations.ts +8 -6
  155. package/src/types/capabilities.ts +9 -18
  156. package/dist/lib/browser/chunk-WQLEMRPU.mjs.map +0 -7
  157. package/dist/lib/browser/cli/index.mjs +0 -1122
  158. package/dist/lib/browser/cli/index.mjs.map +0 -7
  159. package/dist/lib/browser/create-trigger-from-template-JZ62EZTB.mjs.map +0 -7
  160. package/dist/lib/node-esm/chunk-JWZAVQLF.mjs.map +0 -7
  161. package/dist/lib/node-esm/cli/index.mjs +0 -1123
  162. package/dist/lib/node-esm/cli/index.mjs.map +0 -7
  163. package/dist/lib/node-esm/create-trigger-from-template-224Z7WJI.mjs.map +0 -7
  164. package/dist/types/src/cli/commands/index.d.ts.map +0 -1
  165. package/dist/types/src/cli/commands/trigger/create/index.d.ts.map +0 -1
  166. package/dist/types/src/cli/commands/trigger/create/queue.d.ts.map +0 -1
  167. package/dist/types/src/cli/commands/trigger/create/subscription.d.ts.map +0 -1
  168. package/dist/types/src/cli/commands/trigger/create/timer.d.ts.map +0 -1
  169. package/dist/types/src/cli/commands/trigger/index.d.ts.map +0 -1
  170. package/dist/types/src/cli/commands/trigger/list.d.ts.map +0 -1
  171. package/dist/types/src/cli/commands/trigger/options.d.ts.map +0 -1
  172. package/dist/types/src/cli/commands/trigger/remove.d.ts.map +0 -1
  173. package/dist/types/src/cli/commands/trigger/update/index.d.ts.map +0 -1
  174. package/dist/types/src/cli/commands/trigger/update/queue.d.ts.map +0 -1
  175. package/dist/types/src/cli/commands/trigger/update/subscription.d.ts.map +0 -1
  176. package/dist/types/src/cli/commands/trigger/update/timer.d.ts.map +0 -1
  177. package/dist/types/src/cli/commands/trigger/util.d.ts.map +0 -1
  178. package/dist/types/src/cli/index.d.ts +0 -2
  179. package/dist/types/src/cli/index.d.ts.map +0 -1
  180. package/dist/types/src/cli/plugin.d.ts.map +0 -1
  181. package/src/cli/index.ts +0 -5
  182. /package/dist/types/src/{cli/commands → commands}/index.d.ts +0 -0
  183. /package/dist/types/src/{cli/commands → commands}/trigger/list.d.ts +0 -0
  184. /package/dist/types/src/{cli/commands → commands}/trigger/options.d.ts +0 -0
  185. /package/dist/types/src/{cli/commands → commands}/trigger/update/queue.d.ts +0 -0
  186. /package/dist/types/src/{cli/commands → commands}/trigger/update/subscription.d.ts +0 -0
  187. /package/dist/types/src/{cli/commands → commands}/trigger/update/timer.d.ts +0 -0
  188. /package/src/{cli/commands → commands}/index.ts +0 -0
  189. /package/src/{cli/commands → commands}/trigger/create/index.ts +0 -0
  190. /package/src/{cli/commands → commands}/trigger/index.ts +0 -0
  191. /package/src/{cli/commands → commands}/trigger/options.ts +0 -0
  192. /package/src/{cli/commands → commands}/trigger/update/index.ts +0 -0
@@ -7,33 +7,37 @@ import * as BrowserKeyValueStore from '@effect/platform-browser/BrowserKeyValueS
7
7
  import * as KeyValueStore from '@effect/platform/KeyValueStore';
8
8
  import * as Context from 'effect/Context';
9
9
  import * as Effect from 'effect/Effect';
10
+ import * as Fiber from 'effect/Fiber';
10
11
  import * as Layer from 'effect/Layer';
11
12
  import * as ManagedRuntime from 'effect/ManagedRuntime';
12
13
 
13
- import { AiService, GenericToolkit } from '@dxos/ai';
14
+ import { AiService, OpaqueToolkit } from '@dxos/ai';
14
15
  import { Capabilities, Capability, type CapabilityManager } from '@dxos/app-framework';
15
16
  import { AppCapabilities } from '@dxos/app-toolkit';
16
- import {
17
- AgentService,
18
- AiContextBinder,
19
- AiContextService,
20
- AiConversation,
21
- AiConversationService,
22
- ToolExecutionServices,
23
- } from '@dxos/assistant';
24
- import { Blueprint } from '@dxos/blueprints';
17
+ import { AiContextBinder, AiContextService, AiSession, AiSessionService } from '@dxos/assistant';
18
+ import { McpServer } from '@dxos/assistant-toolkit';
25
19
  import { ClientService } from '@dxos/client';
26
- import { SpaceProperties } from '@dxos/client/echo';
20
+ import { SpaceProperties } from '@dxos/client-protocol';
21
+ import {
22
+ Blueprint,
23
+ Credential,
24
+ Operation,
25
+ OperationHandlerSet,
26
+ OperationRegistry,
27
+ ServiceNotAvailableError,
28
+ } from '@dxos/compute';
27
29
  import { Resource } from '@dxos/context';
28
- import { Database, DXN, Feed, Obj, Query, Ref } from '@dxos/echo';
30
+ import { Database, DXN, Feed, Filter, Obj } from '@dxos/echo';
31
+ import { AtomObj } from '@dxos/echo-atom';
29
32
  import { createFeedServiceLayer } from '@dxos/echo-db';
30
- import { acquireReleaseResource } from '@dxos/effect';
33
+ import { acquireReleaseResource, asyncTaskTaggingLayer } from '@dxos/effect';
31
34
  import {
32
- CredentialsService,
35
+ FunctionInvocationService,
33
36
  feedServiceFromQueueServiceLayer,
34
37
  QueueService,
35
- ServiceNotAvailableError,
38
+ credentialsLayerFromDatabase,
36
39
  } from '@dxos/functions';
40
+ import { AgentService } from '@dxos/functions-runtime';
37
41
  import {
38
42
  FeedTraceSink,
39
43
  FunctionImplementationResolver,
@@ -41,13 +45,12 @@ import {
41
45
  ProcessManager,
42
46
  RemoteFunctionExecutionService,
43
47
  ServiceResolver,
44
- TracingServiceExt,
45
48
  TriggerDispatcher,
46
49
  TriggerStateStore,
47
50
  } from '@dxos/functions-runtime';
48
51
  import { invariant } from '@dxos/invariant';
49
52
  import { type SpaceId } from '@dxos/keys';
50
- import { OperationHandlerSet, OperationRegistry } from '@dxos/operation';
53
+ import { log } from '@dxos/log';
51
54
  import { ClientCapabilities } from '@dxos/plugin-client/types';
52
55
 
53
56
  import { AutomationCapabilities } from '#types';
@@ -62,11 +65,30 @@ export default Capability.makeModule(
62
65
  }),
63
66
  );
64
67
 
68
+ declare global {
69
+ interface ImportMeta {
70
+ env: ImportMetaEnv;
71
+ }
72
+
73
+ interface ImportMetaEnv {
74
+ DEV: boolean;
75
+ }
76
+ }
77
+
78
+ const isDev = import.meta.env.DEV ?? false;
79
+
80
+ /** Node / test environments have no `localStorage`; browser keeps persistent trigger state. */
81
+ const triggerStateStoreLayer =
82
+ typeof globalThis.localStorage !== 'undefined'
83
+ ? TriggerStateStore.layerKv.pipe(Layer.provide(BrowserKeyValueStore.layerLocalStorage))
84
+ : TriggerStateStore.layerMemory;
85
+
65
86
  /**
66
87
  * Adapts plugin capabilities to runtime layers.
67
88
  */
68
89
  class ComputeRuntimeProviderImpl extends Resource implements AutomationCapabilities.ComputeRuntimeProvider {
69
90
  readonly #runtimes = new Map<SpaceId, AutomationCapabilities.ComputeRuntime>();
91
+ readonly #subscriptions = new Map<SpaceId, () => void>();
70
92
  readonly #capabilities: CapabilityManager.CapabilityManager;
71
93
 
72
94
  constructor(capabilities: CapabilityManager.CapabilityManager) {
@@ -77,17 +99,24 @@ class ComputeRuntimeProviderImpl extends Resource implements AutomationCapabilit
77
99
  protected override async _open() {}
78
100
 
79
101
  protected override async _close() {
102
+ for (const unsubscribe of this.#subscriptions.values()) {
103
+ unsubscribe();
104
+ }
105
+ this.#subscriptions.clear();
80
106
  await Promise.all(Array.from(this.#runtimes.values()).map((rt) => rt.dispose()));
81
107
  this.#runtimes.clear();
82
108
  }
83
109
 
84
110
  getRuntime(spaceId: SpaceId): AutomationCapabilities.ComputeRuntime {
85
111
  if (this.#runtimes.has(spaceId)) {
112
+ log('getRuntime cache hit', { spaceId });
86
113
  return this.#runtimes.get(spaceId)!;
87
114
  }
115
+ log('getRuntime building', { spaceId });
88
116
 
89
- const layer = Layer.unwrapEffect(
117
+ const layer = Layer.unwrapScoped(
90
118
  Effect.gen(this, function* () {
119
+ log('compute runtime layer build: start', { spaceId });
91
120
  const client = this.#capabilities.get(ClientCapabilities.Client);
92
121
  const aiServiceLayer =
93
122
  this.#capabilities.get(AppCapabilities.AiServiceLayer) ?? Layer.die('AiService not found');
@@ -98,10 +127,10 @@ class ComputeRuntimeProviderImpl extends Resource implements AutomationCapabilit
98
127
  ...this.#capabilities.getAll(Capabilities.OperationHandler),
99
128
  );
100
129
 
101
- const genericToolkitProvider = Layer.succeed(GenericToolkit.GenericToolkitProvider, {
130
+ const opaqueToolkitProvider = Layer.succeed(OpaqueToolkit.OpaqueToolkitProvider, {
102
131
  getToolkit: () => {
103
132
  const toolkits = this.#capabilities.getAll(AppCapabilities.Toolkit);
104
- return GenericToolkit.merge(...toolkits);
133
+ return OpaqueToolkit.merge(...toolkits);
105
134
  },
106
135
  });
107
136
 
@@ -111,138 +140,186 @@ class ComputeRuntimeProviderImpl extends Resource implements AutomationCapabilit
111
140
 
112
141
  const space = client.spaces.get(spaceId);
113
142
  invariant(space, `Invalid space: ${spaceId}`);
143
+ log('compute runtime layer build: waiting for space ready', { spaceId });
144
+ const waitStarted = Date.now();
114
145
  yield* Effect.promise(() => space.waitUntilReady());
146
+ log('compute runtime layer build: space ready', { spaceId, waitMs: Date.now() - waitStarted });
147
+
148
+ // Maintain a live query of space-level MCP server configs.
149
+ const mcpQuery = space.db.query(Filter.type(McpServer.McpServer));
150
+ this.#subscriptions.set(spaceId, mcpQuery.subscribe());
115
151
 
116
- return Layer.mergeAll(
117
- TriggerDispatcher.layer({ timeControl: 'natural' }),
118
- Layer.succeed(Blueprint.RegistryService, new Blueprint.Registry(blueprints)),
119
- ).pipe(
120
- Layer.provideMerge(AgentService.layer()),
121
- Layer.provideMerge(ProcessManager.ProcessOperationInvoker.layer),
122
- Layer.provideMerge(ProcessManager.layer()),
123
- // TODO(dmaretskyi): Duped in assistant testing layer.
124
- Layer.provideMerge(
125
- // TODO(dmaretskyi): Refactor to be able to merge resovler layers, also consider service mesh achitecture.
126
- Layer.effect(
127
- ServiceResolver.ServiceResolver,
128
- Effect.gen(function* () {
129
- const services = yield* Effect.context<Database.Service | Feed.FeedService>().pipe(
130
- Effect.map(Context.pick(Database.Service, Feed.FeedService)),
131
- Effect.map(Layer.succeedContext),
132
- );
133
- // AiContextBinder.
134
- return ServiceResolver.compose(
135
- ServiceResolver.succeed(AiContextService, (context) =>
136
- Effect.gen(function* () {
137
- if (!context.conversation) {
138
- return yield* Effect.fail(new ServiceNotAvailableError(AiContextService.key));
139
- }
140
- const feed = yield* Database.resolve(DXN.parse(context.conversation), Feed.Feed).pipe(
141
- Effect.orDie,
142
- );
143
- const runtime = yield* Effect.runtime<Feed.FeedService>();
144
- const binder = yield* acquireReleaseResource(
145
- () =>
146
- new AiContextBinder({
147
- feed,
148
- runtime,
149
- }),
150
- );
151
- return { binder };
152
- }).pipe(Effect.provide(services)),
153
- ),
154
- // AiConversationService.
155
- ServiceResolver.succeed(AiConversationService, (context) =>
156
- Effect.gen(function* () {
157
- if (!context.conversation) {
158
- return yield* Effect.fail(new ServiceNotAvailableError(AiConversationService.key));
159
- }
160
- const feed = yield* Database.resolve(DXN.parse(context.conversation), Feed.Feed).pipe(
161
- Effect.orDie,
162
- );
163
- const runtime = yield* Effect.runtime<Feed.FeedService>();
164
- const conversation = yield* acquireReleaseResource(
165
- () =>
166
- new AiConversation({
167
- feed,
168
- runtime,
169
- }),
170
- );
171
- return conversation;
172
- }).pipe(Effect.provide(services)),
173
- ),
174
- yield* ServiceResolver.fromRequirements(
175
- Database.Service,
176
- GenericToolkit.GenericToolkitProvider,
177
- Feed.FeedService,
178
- QueueService,
179
- AiService.AiService,
180
- OperationRegistry.Service,
181
- Blueprint.RegistryService,
182
- CredentialsService,
183
- ),
184
- );
152
+ log('compute runtime layer build: composing inner layer', { spaceId });
153
+ return Layer.scopedDiscard(
154
+ Effect.gen(function* () {
155
+ log('compute runtime inner layer: acquiring services', { spaceId });
156
+ const registry = yield* Registry.AtomRegistry;
157
+ const triggerDispatcher = yield* TriggerDispatcher;
158
+ log('compute runtime inner layer: services acquired', { spaceId });
159
+ // Track the in-flight start/stop so a new transition cancels the previous one
160
+ // (preserving ordering on rapid toggles) and surfaces failures via the Effect logger.
161
+ let inFlight: Fiber.RuntimeFiber<unknown, unknown> | undefined;
162
+ const transition = (effect: Effect.Effect<unknown, unknown>) => {
163
+ if (inFlight) {
164
+ Effect.runFork(Fiber.interrupt(inFlight));
165
+ }
166
+ inFlight = Effect.runFork(
167
+ effect.pipe(
168
+ Effect.tapErrorCause((cause) => Effect.logError('trigger dispatcher transition failed', cause)),
169
+ ),
170
+ );
171
+ };
172
+ const unsubscribe = registry.subscribe(
173
+ AtomObj.make(space.properties),
174
+ (properties: Obj.Snapshot<SpaceProperties>) => {
175
+ const computeEnvironment = properties.computeEnvironment ?? 'local';
176
+ transition(computeEnvironment === 'local' ? triggerDispatcher.start() : triggerDispatcher.stop());
177
+ },
178
+ { immediate: true },
179
+ );
180
+ yield* Effect.addFinalizer(() =>
181
+ Effect.sync(() => {
182
+ log('compute runtime inner layer: finalize', { spaceId });
183
+ unsubscribe();
184
+ if (inFlight) {
185
+ Effect.runFork(Fiber.interrupt(inFlight));
186
+ }
187
+ }),
188
+ );
189
+ log('compute runtime inner layer: acquire complete', { spaceId });
190
+ }),
191
+ )
192
+ .pipe(
193
+ Layer.provideMerge(TriggerDispatcher.layer({ timeControl: 'natural' })),
194
+ Layer.provideMerge(
195
+ AgentService.layer({
196
+ getMcpServers: () =>
197
+ mcpQuery.results
198
+ .filter(Obj.instanceOf(McpServer.McpServer))
199
+ .filter((server) => server.enabled !== false)
200
+ .map(({ url, protocol, apiKey }) => ({ url, protocol, apiKey })),
185
201
  }),
186
202
  ),
187
- ),
188
- Layer.provideMerge(Layer.succeed(Blueprint.RegistryService, new Blueprint.Registry(blueprints))),
189
- Layer.provideMerge(OperationRegistry.layer),
190
- Layer.provideMerge(Layer.succeed(Capability.Service, this.#capabilities)),
191
- Layer.provideMerge(Layer.succeed(Registry.AtomRegistry, registry)),
192
- Layer.provideMerge(
193
- Layer.mergeAll(
194
- TracingServiceLive,
195
- FeedTraceSink.layerLive,
196
- TriggerStateStore.layerKv.pipe(Layer.provide(BrowserKeyValueStore.layerLocalStorage)),
197
- ToolExecutionServices,
198
- KeyValueStore.layerMemory,
203
+ Layer.provideMerge(ProcessManager.ProcessOperationInvoker.layer),
204
+ Layer.provideMerge(ProcessManager.layer()),
205
+ // TODO(dmaretskyi): Duped in assistant testing layer.
206
+ Layer.provideMerge(
207
+ // TODO(dmaretskyi): Refactor to be able to merge resovler layers, also consider service mesh achitecture.
208
+ Layer.effect(
209
+ ServiceResolver.ServiceResolver,
210
+ Effect.gen(function* () {
211
+ const services = yield* Effect.context<Database.Service | Feed.FeedService>().pipe(
212
+ Effect.map(Context.pick(Database.Service, Feed.FeedService)),
213
+ Effect.map(Layer.succeedContext),
214
+ );
215
+ // AiContextBinder.
216
+ return ServiceResolver.compose(
217
+ ServiceResolver.succeed(AiContextService, (context) =>
218
+ Effect.gen(function* () {
219
+ if (!context.conversation) {
220
+ return yield* Effect.fail(new ServiceNotAvailableError(AiContextService.key));
221
+ }
222
+ const feed = yield* Database.resolve(DXN.parse(context.conversation), Feed.Feed).pipe(
223
+ Effect.orDie,
224
+ );
225
+ const runtime = yield* Effect.runtime<Feed.FeedService>();
226
+ const binder = yield* acquireReleaseResource(
227
+ () =>
228
+ new AiContextBinder({
229
+ feed,
230
+ runtime,
231
+ }),
232
+ );
233
+ return { binder };
234
+ }).pipe(Effect.provide(services)),
235
+ ),
236
+ // AiSessionService.
237
+ ServiceResolver.succeed(AiSessionService, (context) =>
238
+ Effect.gen(function* () {
239
+ if (!context.conversation) {
240
+ return yield* Effect.fail(new ServiceNotAvailableError(AiSessionService.key));
241
+ }
242
+ const feed = yield* Database.resolve(DXN.parse(context.conversation), Feed.Feed).pipe(
243
+ Effect.orDie,
244
+ );
245
+ const runtime = yield* Effect.runtime<Feed.FeedService>();
246
+ const session = yield* acquireReleaseResource(
247
+ () =>
248
+ new AiSession({
249
+ feed,
250
+ runtime,
251
+ }),
252
+ );
253
+ return session;
254
+ }).pipe(Effect.provide(services)),
255
+ ),
256
+ yield* ServiceResolver.fromRequirements(
257
+ Database.Service,
258
+ OpaqueToolkit.OpaqueToolkitProvider,
259
+ Feed.FeedService,
260
+ QueueService,
261
+ AiService.AiService,
262
+ OperationRegistry.Service,
263
+ Blueprint.RegistryService,
264
+ Credential.CredentialsService,
265
+ ),
266
+ );
267
+ }),
268
+ ),
269
+ ),
270
+ Layer.provideMerge(Layer.succeed(Blueprint.RegistryService, new Blueprint.Registry(blueprints))),
271
+ Layer.provideMerge(Layer.succeed(Capability.Service, this.#capabilities)),
272
+ Layer.provideMerge(Layer.succeed(Registry.AtomRegistry, registry)),
273
+ Layer.provideMerge(
274
+ Layer.mergeAll(FeedTraceSink.layerLive, triggerStateStoreLayer, KeyValueStore.layerMemory),
275
+ ),
276
+ Layer.provideMerge(OperationRegistry.layer),
277
+ Layer.provideMerge(feedServiceFromQueueServiceLayer),
278
+ Layer.provideMerge(OperationHandlerSet.provide(operationHandlers)),
279
+ Layer.provideMerge(
280
+ Layer.effect(
281
+ Operation.Service,
282
+ Effect.gen(function* () {
283
+ const fis = yield* FunctionInvocationService;
284
+ return {
285
+ invoke: (op: any, ...args: any[]) => (fis.invokeFunction as any)(op, args[0]),
286
+ schedule: (op: any, ...args: any[]) =>
287
+ (fis.invokeFunction as any)(op, args[0]).pipe(Effect.fork, Effect.asVoid),
288
+ invokePromise: async () => ({ error: new Error('Not implemented') }),
289
+ } as unknown as Operation.OperationService;
290
+ }),
291
+ ),
199
292
  ),
200
- ),
201
- Layer.provideMerge(feedServiceFromQueueServiceLayer),
202
- Layer.provideMerge(OperationHandlerSet.provide(operationHandlers)),
203
- Layer.provideMerge(
204
- FunctionInvocationServiceLayerWithLocalLoopbackExecutor.pipe(
205
- Layer.provideMerge(genericToolkitProvider),
206
- Layer.provideMerge(FunctionImplementationResolver.layerTest({ functions: operationHandlers })),
207
- Layer.provideMerge(
208
- RemoteFunctionExecutionService.fromClient(
209
- client,
210
- client.config.get('runtime.client.edgeFeatures.agents') ? spaceId : undefined,
293
+ Layer.provideMerge(
294
+ FunctionInvocationServiceLayerWithLocalLoopbackExecutor.pipe(
295
+ Layer.provideMerge(FunctionImplementationResolver.layerTest({ functions: operationHandlers })),
296
+ Layer.provideMerge(
297
+ client.config.values.runtime?.services?.edge?.url
298
+ ? RemoteFunctionExecutionService.fromClient(
299
+ client,
300
+ client.config.get('runtime.client.edgeFeatures.agents') ? spaceId : undefined,
301
+ )
302
+ : RemoteFunctionExecutionService.layerMock,
211
303
  ),
212
304
  ),
213
- Layer.provideMerge(aiServiceLayer),
214
- Layer.provideMerge(CredentialsService.layerFromDatabase()),
215
- Layer.provideMerge(ClientService.fromClient(client)),
216
- Layer.provideMerge(space ? Database.layer(space.db) : Database.notAvailable),
217
- Layer.provideMerge(space ? QueueService.layer(space.queues) : QueueService.notAvailable),
218
- Layer.provideMerge(space ? createFeedServiceLayer(space.queues) : Feed.notAvailable),
219
305
  ),
220
- ),
221
- );
306
+ Layer.provideMerge(opaqueToolkitProvider),
307
+ Layer.provideMerge(aiServiceLayer),
308
+ Layer.provideMerge(credentialsLayerFromDatabase()),
309
+ Layer.provideMerge(ClientService.fromClient(client)),
310
+ Layer.provideMerge(space ? Database.layer(space.db) : Database.notAvailable),
311
+ )
312
+ .pipe(
313
+ Layer.provideMerge(space ? QueueService.layer(space.queues) : QueueService.notAvailable),
314
+ Layer.provideMerge(space ? createFeedServiceLayer(space.queues) : Feed.notAvailable),
315
+ Layer.provideMerge(isDev ? asyncTaskTaggingLayer() : Layer.empty),
316
+ );
222
317
  }),
223
318
  );
224
319
 
225
320
  const runtime = ManagedRuntime.make(layer);
321
+ log('getRuntime ready (managed runtime created)', { spaceId });
226
322
  this.#runtimes.set(spaceId, runtime);
227
323
  return runtime;
228
324
  }
229
325
  }
230
-
231
- const TracingServiceLive = Layer.unwrapEffect(
232
- Effect.gen(function* () {
233
- const objects = yield* Database.runQuery(Query.type(SpaceProperties));
234
- const [properties] = objects;
235
- invariant(properties);
236
- // TODO(burdon): Check ref target has loaded?
237
- if (!properties.invocationTraceQueue || !properties.invocationTraceQueue.target) {
238
- const queue = yield* QueueService.createQueue({ subspaceTag: 'trace' });
239
- Obj.change(properties, (properties) => {
240
- properties.invocationTraceQueue = Ref.fromDXN(queue.dxn);
241
- });
242
- }
243
-
244
- const queue = properties.invocationTraceQueue!.target;
245
- invariant(queue);
246
- return TracingServiceExt.layerInvocationsQueue({ invocationTraceQueue: queue });
247
- }),
248
- );
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Capability } from '@dxos/app-framework';
6
- import { OperationHandlerSet } from '@dxos/operation';
6
+ import { OperationHandlerSet } from '@dxos/compute';
7
7
 
8
8
  export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
9
9
  export const ComputeRuntime = Capability.lazy('ComputeRuntime', () => import('./compute-runtime'));
@@ -3,5 +3,11 @@
3
3
  //
4
4
 
5
5
  import { Capability } from '@dxos/app-framework';
6
+ import { OperationHandlerSet } from '@dxos/compute';
6
7
 
8
+ export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
7
9
  export const ComputeRuntime = Capability.lazy('ComputeRuntime', () => import('./compute-runtime'));
10
+ export const OperationHandler = Capability.lazy<OperationHandlerSet.OperationHandlerSet>(
11
+ 'OperationHandler',
12
+ () => import('./operation-handler'),
13
+ );
@@ -5,7 +5,7 @@
5
5
  import * as Effect from 'effect/Effect';
6
6
 
7
7
  import { Capabilities, Capability } from '@dxos/app-framework';
8
- import type { OperationHandlerSet } from '@dxos/operation';
8
+ import type { OperationHandlerSet } from '@dxos/compute';
9
9
 
10
10
  import { AutomationOperationHandlerSet } from '#operations';
11
11
 
@@ -18,8 +18,7 @@ export default Capability.makeModule(() =>
18
18
  Capability.contributes(Capabilities.ReactSurface, [
19
19
  Surface.create({
20
20
  id: 'space-settings-functions',
21
- role: 'article',
22
- filter: AppSurface.literalSection(`${meta.id}.space-settings-functions`),
21
+ filter: AppSurface.literal(AppSurface.Article, `${meta.id}.space-settings-functions`),
23
22
  component: () => {
24
23
  const space = useActiveSpace();
25
24
  if (!space) {
@@ -31,8 +30,7 @@ export default Capability.makeModule(() =>
31
30
  }),
32
31
  Surface.create({
33
32
  id: 'space-settings-automation',
34
- role: 'article',
35
- filter: AppSurface.literalSection(`${meta.id}.space-settings-automation`),
33
+ filter: AppSurface.literal(AppSurface.Article, `${meta.id}.space-settings-automation`),
36
34
  component: () => {
37
35
  const space = useActiveSpace();
38
36
  if (!space) {
@@ -44,8 +42,10 @@ export default Capability.makeModule(() =>
44
42
  }),
45
43
  Surface.create({
46
44
  id: 'companion.automation',
47
- role: 'article',
48
- filter: AppSurface.and(AppSurface.literalArticle('automation'), AppSurface.companionArticle()),
45
+ filter: AppSurface.allOf(
46
+ AppSurface.literal(AppSurface.Article, 'automation'),
47
+ AppSurface.companion(AppSurface.Article),
48
+ ),
49
49
  component: ({ data }) => {
50
50
  const space = getSpace(data.companionTo);
51
51
  if (!space) {
@@ -13,9 +13,8 @@ import * as Option from 'effect/Option';
13
13
  import { CommandConfig } from '@dxos/cli-util';
14
14
  import { flushAndSync, print, spaceLayer, withTypes } from '@dxos/cli-util';
15
15
  import { Common } from '@dxos/cli-util';
16
+ import { Operation, Trigger } from '@dxos/compute';
16
17
  import { Database, Filter, JsonSchema, Ref } from '@dxos/echo';
17
- import { Trigger } from '@dxos/functions';
18
- import { Operation } from '@dxos/operation';
19
18
 
20
19
  import { Enabled, Input, Queue } from '../options';
21
20
  import { printTrigger, promptForSchemaInput, selectFunction, selectQueue } from '../util';
@@ -66,10 +65,7 @@ export const queue = Command.make(
66
65
  const trigger = Trigger.make({
67
66
  function: Ref.make(fn),
68
67
  enabled,
69
- spec: {
70
- kind: 'queue',
71
- queue: queueDxn,
72
- },
68
+ spec: Trigger.specQueue(queueDxn),
73
69
  input,
74
70
  });
75
71
 
@@ -13,9 +13,8 @@ import * as Option from 'effect/Option';
13
13
  import { CommandConfig } from '@dxos/cli-util';
14
14
  import { flushAndSync, print, spaceLayer, withTypes } from '@dxos/cli-util';
15
15
  import { Common } from '@dxos/cli-util';
16
+ import { Operation, Trigger } from '@dxos/compute';
16
17
  import { Database, Filter, JsonSchema, Query, Ref } from '@dxos/echo';
17
- import { Trigger } from '@dxos/functions';
18
- import { Operation } from '@dxos/operation';
19
18
 
20
19
  import { Deep, Delay, Enabled, Input, Typename } from '../options';
21
20
  import { printTrigger, promptForSchemaInput, selectFunction } from '../util';
@@ -52,7 +51,7 @@ export const subscription = Command.make(
52
51
  }).pipe(Prompt.run),
53
52
  onSome: (value) => Effect.succeed(value),
54
53
  });
55
- const queryAst = Query.select(Filter.type(typename)).ast;
54
+ const subscriptionQuery = Query.select(Filter.type(typename));
56
55
 
57
56
  const deepOption = yield* Option.match(options.deep, {
58
57
  onNone: () =>
@@ -103,13 +102,10 @@ export const subscription = Command.make(
103
102
  const trigger = Trigger.make({
104
103
  function: Ref.make(fn),
105
104
  enabled,
106
- spec: {
107
- kind: 'subscription',
108
- query: {
109
- ast: queryAst,
110
- },
111
- options: Object.keys(subscriptionOptions).length > 0 ? subscriptionOptions : undefined,
112
- },
105
+ spec: Trigger.specSubscription(
106
+ subscriptionQuery,
107
+ Object.keys(subscriptionOptions).length > 0 ? subscriptionOptions : undefined,
108
+ ),
113
109
  input,
114
110
  });
115
111
  yield* Database.add(trigger);
@@ -13,9 +13,8 @@ import * as Option from 'effect/Option';
13
13
  import { CommandConfig } from '@dxos/cli-util';
14
14
  import { flushAndSync, print, spaceLayer, withTypes } from '@dxos/cli-util';
15
15
  import { Common } from '@dxos/cli-util';
16
+ import { Operation, Trigger } from '@dxos/compute';
16
17
  import { Database, Filter, JsonSchema, Ref } from '@dxos/echo';
17
- import { Trigger } from '@dxos/functions';
18
- import { Operation } from '@dxos/operation';
19
18
 
20
19
  import { Cron, Enabled, Input } from '../options';
21
20
  import { printTrigger, promptForSchemaInput, selectFunction } from '../util';
@@ -70,10 +69,7 @@ export const timer = Command.make(
70
69
  const trigger = Trigger.make({
71
70
  function: Ref.make(fn),
72
71
  enabled,
73
- spec: {
74
- kind: 'timer',
75
- cron,
76
- },
72
+ spec: Trigger.specTimer(cron),
77
73
  input,
78
74
  });
79
75
 
@@ -9,9 +9,9 @@ import * as Effect from 'effect/Effect';
9
9
 
10
10
  import { CommandConfig, Common, printList, spaceIdWithDefault, spaceLayer } from '@dxos/cli-util';
11
11
  import { ClientService } from '@dxos/client';
12
+ import { Trigger } from '@dxos/compute';
12
13
  import { Context } from '@dxos/context';
13
- import { Database, Filter } from '@dxos/echo';
14
- import { Trigger } from '@dxos/functions';
14
+ import { Database, Filter, Query } from '@dxos/echo';
15
15
 
16
16
  import { getTriggerRemoteStatus, printTrigger } from './util';
17
17
 
@@ -24,7 +24,9 @@ export const list = Command.make(
24
24
  const { json } = yield* CommandConfig;
25
25
 
26
26
  // Fetch local triggers
27
- const triggers = yield* Database.runQuery(Filter.type(Trigger.Trigger));
27
+ const triggers = yield* Database.runQuery(
28
+ Query.select(Filter.type(Trigger.Trigger)).debugLabel('cli.trigger.list'),
29
+ );
28
30
 
29
31
  // Fetch remote cron triggers to check availability
30
32
  const remoteCronIds = yield* Effect.gen(function* () {
@@ -9,9 +9,9 @@ import * as Effect from 'effect/Effect';
9
9
  import * as Option from 'effect/Option';
10
10
 
11
11
  import { CommandConfig, Common, print, spaceLayer, withTypes } from '@dxos/cli-util';
12
+ import { Trigger } from '@dxos/compute';
12
13
  import { DXN } from '@dxos/echo';
13
14
  import { Database } from '@dxos/echo';
14
- import { Trigger } from '@dxos/functions';
15
15
 
16
16
  import { TriggerId } from './options';
17
17
  import { printTriggerRemoved, selectTrigger } from './util';