@lowdefy/api 0.0.0-experimental-20260929101721 → 0.0.0-experimental-20260929135001

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.
@@ -24,8 +24,9 @@ function createEvaluateOperators(context) {
24
24
  secrets,
25
25
  user
26
26
  });
27
- function evaluateOperators({ arrayIndices, error, input, items, literalData, location, payload, state, steps }) {
27
+ function evaluateOperators({ agent, arrayIndices, error, input, items, literalData, location, payload, state, steps }) {
28
28
  const { output, errors } = operatorsParser.parse({
29
+ agent,
29
30
  arrayIndices,
30
31
  error,
31
32
  input,
@@ -35,6 +35,12 @@ async function prepareAgent(context, { agentId, agentContext, endpointDepth = 0,
35
35
  authorizeAgent(context, {
36
36
  agentConfig
37
37
  });
38
+ // What `_agent` reads in the tool and hook endpoints this agent calls. Built here from the
39
+ // agent being run and its conversation, so no tool input can set or change it.
40
+ const agent = {
41
+ id: agentId,
42
+ conversationId: agentContext.conversationId ?? null
43
+ };
38
44
  // Evaluate operators in agent properties (e.g. _user, _secret, _payload)
39
45
  agentConfig.properties = context.evaluateOperators({
40
46
  input: agentConfig.properties ?? {},
@@ -91,6 +97,7 @@ async function prepareAgent(context, { agentId, agentContext, endpointDepth = 0,
91
97
  }),
92
98
  callEndpoint: async (endpointId, { payload })=>{
93
99
  const { error, response, status } = await invokeEndpoint(context, {
100
+ agent,
94
101
  endpointId,
95
102
  payload,
96
103
  endpointDepth
@@ -66,7 +66,8 @@ async function handleEndpointCall(context, routineContext, { step }) {
66
66
  payload: serializer.serialize(evaluatedProperties.payload ?? {}),
67
67
  principal: {
68
68
  user: serializer.serialize(context.user ?? null),
69
- system: context.system === true
69
+ system: context.system === true,
70
+ agent: routineContext.agent ?? null
70
71
  }
71
72
  })
72
73
  }));
@@ -88,6 +89,7 @@ async function handleEndpointCall(context, routineContext, { step }) {
88
89
  };
89
90
  }
90
91
  const result = await invokeEndpoint(context, {
92
+ agent: routineContext.agent,
91
93
  endpointId: evaluatedProperties.endpointId,
92
94
  payload: evaluatedProperties.payload,
93
95
  endpointDepth: routineContext.endpointDepth
@@ -70,6 +70,7 @@ async function handleRequest(context, routineContext, { request }) {
70
70
  requestProperties
71
71
  });
72
72
  const result = await callRequestResolver(context, {
73
+ agent: routineContext.agent,
73
74
  connectionProperties,
74
75
  endpointDepth: routineContext.endpointDepth,
75
76
  requestConfig,
@@ -18,7 +18,7 @@ import authorizeApiEndpoint from './authorizeApiEndpoint.js';
18
18
  import getEndpointConfig from './getEndpointConfig.js';
19
19
  import runRoutine from './runRoutine.js';
20
20
  import validatePayload from './validatePayload.js';
21
- async function invokeEndpoint(context, { endpointId, payload, endpointDepth, literalData = null }) {
21
+ async function invokeEndpoint(context, { agent = null, endpointId, payload, endpointDepth, literalData = null }) {
22
22
  if (endpointDepth >= 10) {
23
23
  throw new ConfigError('Endpoint call depth exceeded maximum of 10. Check for recursive endpoint calls.');
24
24
  }
@@ -41,6 +41,10 @@ async function invokeEndpoint(context, { endpointId, payload, endpointDepth, lit
41
41
  items: {},
42
42
  state: {},
43
43
  endpointDepth: endpointDepth + 1,
44
+ // The agent ({ id, conversationId }) whose tool call started this chain of endpoint calls, or
45
+ // null. Set by the engine from the running agent, never from the payload, so `_agent` can mark
46
+ // agent work.
47
+ agent,
44
48
  // Set only for the endpoint a Dynamic block calls: its :return becomes page
45
49
  // config, so data read into it must not carry operators. Nested CallApi
46
50
  // endpoints get a fresh context without it; their result arrives through
@@ -15,8 +15,9 @@
15
15
  */ // The routine fields operators can read. A field added to the routine frame goes here, so every
16
16
  // routine step and control sees it rather than only the ones that remembered to pass it.
17
17
  function operatorScope(routineContext) {
18
- const { error, items, payload, state, steps } = routineContext;
18
+ const { agent, error, items, payload, state, steps } = routineContext;
19
19
  return {
20
+ agent: agent ?? null,
20
21
  error: error ?? null,
21
22
  items,
22
23
  payload,
@@ -79,7 +79,9 @@ async function runDetachedEndpoint(context, { endpointId, payload, principal })
79
79
  error: null,
80
80
  items: {},
81
81
  state: {},
82
- endpointDepth: 0
82
+ endpointDepth: 0,
83
+ // The dispatcher's agent, carried in the principal like its identity.
84
+ agent: principal?.agent ?? null
83
85
  };
84
86
  const { error, response, status } = await runRoutine(context, routineContext, {
85
87
  routine: endpointConfig.routine
@@ -15,7 +15,7 @@
15
15
  */ import { RequestError, ServiceError, UserError } from '@lowdefy/errors';
16
16
  import getCurrentEnvironment from '../../context/getCurrentEnvironment.js';
17
17
  import invokeEndpoint from '../endpoints/invokeEndpoint.js';
18
- async function callRequestResolver(context, { connectionProperties, endpointDepth, requestConfig, requestProperties, requestResolver, tenant, tenantGuard }) {
18
+ async function callRequestResolver(context, { agent = null, connectionProperties, endpointDepth, requestConfig, requestProperties, requestResolver, tenant, tenantGuard }) {
19
19
  const { blockId, endpointId, logger, pageId, payload, signal } = context;
20
20
  // stepId for endpoint steps (after build), requestId for page requests
21
21
  const stepOrRequestId = requestConfig.stepId ?? requestConfig.requestId;
@@ -27,6 +27,7 @@ async function callRequestResolver(context, { connectionProperties, endpointDept
27
27
  endpointId: targetEndpointId
28
28
  });
29
29
  const result = await invokeEndpoint(context, {
30
+ agent,
30
31
  endpointId: targetEndpointId,
31
32
  payload: targetPayload,
32
33
  endpointDepth
@@ -0,0 +1,22 @@
1
+ /*
2
+ Copyright 2020-2026 Lowdefy, Inc
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */ import { serializer } from '@lowdefy/helpers';
16
+ // Serialized like page config: the ~k markers, non-enumerable once the artifact
17
+ // is read, must reach the browser so app event errors resolve to their config.
18
+ async function getAppEvents({ readConfigFile }) {
19
+ const events = await readConfigFile('events.json');
20
+ return serializer.serialize(events);
21
+ }
22
+ export default getAppEvents;
@@ -12,18 +12,21 @@
12
12
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
- */ import getHomeAndMenus from './getHomeAndMenus.js';
15
+ */ import getAppEvents from './getAppEvents.js';
16
+ import getHomeAndMenus from './getHomeAndMenus.js';
16
17
  import getLowdefyGlobal from './getLowdefyGlobal.js';
17
18
  import getLowdefyI18n from './getLowdefyI18n.js';
18
19
  import getLowdefyTheme from './getLowdefyTheme.js';
19
20
  async function getRootConfig(context) {
20
- const [lowdefyGlobal, theme, i18n, { home, menus }] = await Promise.all([
21
+ const [events, lowdefyGlobal, theme, i18n, { home, menus }] = await Promise.all([
22
+ getAppEvents(context),
21
23
  getLowdefyGlobal(context),
22
24
  getLowdefyTheme(context),
23
25
  getLowdefyI18n(context),
24
26
  getHomeAndMenus(context)
25
27
  ]);
26
28
  return {
29
+ events,
27
30
  home,
28
31
  i18n,
29
32
  lowdefyApp: context.appMeta,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowdefy/api",
3
- "version": "0.0.0-experimental-20260929101721",
3
+ "version": "0.0.0-experimental-20260929135001",
4
4
  "license": "Apache-2.0",
5
5
  "description": "",
6
6
  "homepage": "https://lowdefy.com",
@@ -37,16 +37,16 @@
37
37
  "@better-auth/cimd": "1.7.0",
38
38
  "@better-auth/oauth-provider": "1.7.0",
39
39
  "@better-auth/passkey": "1.7.0",
40
- "@lowdefy/ajv": "0.0.0-experimental-20260929101721",
41
- "@lowdefy/build": "0.0.0-experimental-20260929101721",
42
- "@lowdefy/connection-smtp": "0.0.0-experimental-20260929101721",
43
- "@lowdefy/email-templates": "0.0.0-experimental-20260929101721",
44
- "@lowdefy/errors": "0.0.0-experimental-20260929101721",
45
- "@lowdefy/helpers": "0.0.0-experimental-20260929101721",
46
- "@lowdefy/node-utils": "0.0.0-experimental-20260929101721",
47
- "@lowdefy/nunjucks": "0.0.0-experimental-20260929101721",
48
- "@lowdefy/operators": "0.0.0-experimental-20260929101721",
49
- "@lowdefy/operators-js": "0.0.0-experimental-20260929101721",
40
+ "@lowdefy/ajv": "0.0.0-experimental-20260929135001",
41
+ "@lowdefy/build": "0.0.0-experimental-20260929135001",
42
+ "@lowdefy/connection-smtp": "0.0.0-experimental-20260929135001",
43
+ "@lowdefy/email-templates": "0.0.0-experimental-20260929135001",
44
+ "@lowdefy/errors": "0.0.0-experimental-20260929135001",
45
+ "@lowdefy/helpers": "0.0.0-experimental-20260929135001",
46
+ "@lowdefy/node-utils": "0.0.0-experimental-20260929135001",
47
+ "@lowdefy/nunjucks": "0.0.0-experimental-20260929135001",
48
+ "@lowdefy/operators": "0.0.0-experimental-20260929135001",
49
+ "@lowdefy/operators-js": "0.0.0-experimental-20260929135001",
50
50
  "@modelcontextprotocol/sdk": "1.29.0",
51
51
  "better-auth": "1.7.0",
52
52
  "jose": "^6.2.3",
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "devDependencies": {
56
56
  "@jest/globals": "28.1.3",
57
- "@lowdefy/connection-mongodb": "0.0.0-experimental-20260929101721",
57
+ "@lowdefy/connection-mongodb": "0.0.0-experimental-20260929135001",
58
58
  "@shelf/jest-mongodb": "4.3.2",
59
59
  "@swc/cli": "0.8.1",
60
60
  "@swc/core": "1.15.32",