@cap-js/agents 0.9.6 → 0.9.8

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 (83) hide show
  1. package/README.md +2 -131
  2. package/_i18n/messages.properties +2 -0
  3. package/_i18n/messages_ar.properties +48 -0
  4. package/_i18n/messages_bg.properties +48 -0
  5. package/_i18n/messages_cs.properties +48 -0
  6. package/_i18n/messages_da.properties +48 -0
  7. package/_i18n/messages_de.properties +48 -0
  8. package/_i18n/messages_el.properties +48 -0
  9. package/_i18n/messages_en.properties +48 -0
  10. package/_i18n/messages_es.properties +48 -0
  11. package/_i18n/messages_es_MX.properties +48 -0
  12. package/_i18n/messages_fi.properties +48 -0
  13. package/_i18n/messages_fr.properties +48 -0
  14. package/_i18n/messages_he.properties +48 -0
  15. package/_i18n/messages_hr.properties +48 -0
  16. package/_i18n/messages_hu.properties +48 -0
  17. package/_i18n/messages_it.properties +48 -0
  18. package/_i18n/messages_ja.properties +48 -0
  19. package/_i18n/messages_kk.properties +48 -0
  20. package/_i18n/messages_ko.properties +48 -0
  21. package/_i18n/messages_ms.properties +48 -0
  22. package/_i18n/messages_nl.properties +48 -0
  23. package/_i18n/messages_no.properties +48 -0
  24. package/_i18n/messages_pl.properties +48 -0
  25. package/_i18n/messages_pt.properties +48 -0
  26. package/_i18n/messages_ro.properties +48 -0
  27. package/_i18n/messages_ru.properties +48 -0
  28. package/_i18n/messages_sh.properties +48 -0
  29. package/_i18n/messages_sk.properties +48 -0
  30. package/_i18n/messages_sl.properties +48 -0
  31. package/_i18n/messages_sv.properties +48 -0
  32. package/_i18n/messages_th.properties +48 -0
  33. package/_i18n/messages_tr.properties +48 -0
  34. package/_i18n/messages_uk.properties +48 -0
  35. package/_i18n/messages_vi.properties +48 -0
  36. package/_i18n/messages_zh_CN.properties +48 -0
  37. package/_i18n/messages_zh_TW.properties +48 -0
  38. package/cds-plugin.js +15 -10
  39. package/lib/agents/middleware/content-filter.js +4 -0
  40. package/lib/agents/middleware/hitl-decision-note-injector.js +18 -6
  41. package/lib/agents/middleware/hitl.js +17 -6
  42. package/lib/agents/middleware/index.js +3 -1
  43. package/lib/agents/middleware/masking.js +127 -0
  44. package/lib/agents/middleware/remote-mcp.js +10 -5
  45. package/lib/agents/middleware/status-update.js +209 -76
  46. package/lib/agents/middleware/tool-wrap.js +1 -2
  47. package/lib/agents/summarize-on-timeout.js +5 -2
  48. package/lib/config/local.js +121 -8
  49. package/lib/eval/eval-run.js +50 -4
  50. package/lib/masking/index.js +90 -0
  51. package/lib/masking/store.js +80 -0
  52. package/lib/masking/structured/findElements.js +459 -0
  53. package/lib/masking/structured/index.js +170 -0
  54. package/lib/masking/unstructured/dpi.js +84 -0
  55. package/lib/masking/unstructured/hana.js +72 -0
  56. package/lib/masking/unstructured/index.js +52 -0
  57. package/lib/models/aicore.js +16 -3
  58. package/lib/models/openai.js +9 -0
  59. package/lib/preview/chat.html +623 -119
  60. package/lib/protocol/persistence/cleanup.js +13 -4
  61. package/lib/telemetry/chat-tracing.js +9 -2
  62. package/lib/telemetry/mlflow/evaluation.js +83 -4
  63. package/lib/telemetry/mlflow/exporter/DatabricksExporter.js +39 -5
  64. package/lib/telemetry/mlflow/exporter/MlflowExporter.js +43 -4
  65. package/lib/telemetry/mlflow/index.js +1 -7
  66. package/lib/telemetry/mlflow/prompts.js +15 -11
  67. package/lib/telemetry/mlflow/tracing.js +3 -3
  68. package/lib/telemetry/span-masking.js +165 -0
  69. package/lib/telemetry/tool-tracing.js +4 -4
  70. package/lib/utils/markdown.js +3 -10
  71. package/lib/utils/resilience.js +2 -1
  72. package/lib/utils/toml.js +67 -0
  73. package/lib/utils/usage.js +34 -0
  74. package/lib/utils/utils.js +43 -1
  75. package/package.json +33 -26
  76. package/srv/handlers/graph-executor/crash-handler.js +47 -0
  77. package/srv/handlers/graph-executor/hitl.js +27 -0
  78. package/srv/handlers/graph-executor.js +69 -20
  79. package/srv/handlers/index.js +6 -1
  80. package/srv/handlers/mcp-tools.js +11 -2
  81. package/srv/handlers/subagent-tools.js +13 -4
  82. package/srv/handlers/system-prompt.js +30 -20
  83. package/srv/handlers/tools.js +14 -13
@@ -78,9 +78,9 @@ function formatToolResult({ text, files }) {
78
78
  /**
79
79
  * Wrap an A2A client as a LangChain tool the agent can call.
80
80
  */
81
- function createA2ATool(client, agentCard) {
81
+ function createA2ATool(client, agentCard, serviceName) {
82
82
  const subagent = agentCard.name
83
- return tool(
83
+ const t = tool(
84
84
  async ({ message }) => {
85
85
  try {
86
86
  const messageId = cds.utils.uuid()
@@ -116,6 +116,8 @@ function createA2ATool(client, agentCard) {
116
116
  }),
117
117
  },
118
118
  )
119
+ t.metadata = { ...t.metadata, kind: "agent", agentName: agentCard.name, serviceName }
120
+ return t
119
121
  }
120
122
 
121
123
  export async function buildSubAgentToolLocally(serviceName) {
@@ -130,7 +132,7 @@ export async function buildSubAgentToolLocally(serviceName) {
130
132
 
131
133
  const { RequestContext, DefaultExecutionEventBus } = await import("@a2a-js/sdk/server")
132
134
 
133
- return tool(
135
+ const localTool = tool(
134
136
  async ({ message }) => {
135
137
  const taskId = cds.utils.uuid()
136
138
  const contextId = cds.utils.uuid()
@@ -221,6 +223,13 @@ export async function buildSubAgentToolLocally(serviceName) {
221
223
  }),
222
224
  },
223
225
  )
226
+ localTool.metadata = {
227
+ ...localTool.metadata,
228
+ kind: "agent",
229
+ agentName: agentCard.name,
230
+ serviceName,
231
+ }
232
+ return localTool
224
233
  }
225
234
 
226
235
  export async function buildSubAgentToolFromConnection(serviceName) {
@@ -334,7 +343,7 @@ export async function buildSubAgentToolFromConnection(serviceName) {
334
343
  )
335
344
  const client = await factory.createFromAgentCard(agentCard)
336
345
 
337
- return createA2ATool(client, agentCard)
346
+ return createA2ATool(client, agentCard, serviceName)
338
347
  }
339
348
 
340
349
  export function buildSubAgentTool(serviceName) {
@@ -1,25 +1,35 @@
1
1
  import cds from "@sap/cds"
2
2
  import { getDescription } from "../../lib/utils/utils.js"
3
+ const LOG = cds.log("agents")
3
4
 
4
5
  export function buildSystemPrompt(srv) {
5
- const serviceDesc = getDescription(srv.definition) || `Service ${srv.name}`
6
-
7
- return [
8
- `You are an AI assistant for the "${srv.name}" service.`,
9
- serviceDesc,
10
- "",
11
- "Always use the provided tools to answer questions - do not make up data.",
12
- "Use the `describe` tool to get information about the service's entities and actions if needed.",
13
- "Use the `query` tool to read data from entities.",
14
- cds.env.agents?.per_action_tool !== false
15
- ? "Call action and function tools directly by name."
16
- : "Use the `call` tool to invoke actions and functions.",
17
- ...(cds.env.agents?.fileIO?.enabled
18
- ? [
19
- "When the user's message contains '[Uploaded files: ...]', use the `read_file` tool to read each listed file before answering.",
20
- "Use `emit_file_part` to return files in your response.",
21
- ]
22
- : []),
23
- "Be concise and helpful.",
24
- ].join("\n")
6
+
7
+ let text = `
8
+
9
+ You are an AI assistant for the local CAP service \`${srv.name}\`.
10
+ ${ getDescription(srv.definition) || '' }
11
+ Use the provided tools to answer questions:
12
+
13
+ - the \`describe\` tool to learn about the service's entities and actions.
14
+ - the \`query\` tool to read data from entities.
15
+ - the \`call\` tool to invoke actions, or individual action tools.
16
+
17
+ IMPORTANT: Don't guess element names when \`query\`ing entities.
18
+ Use the \`describe\` tool instead to find correct element names.
19
+
20
+ ${ cds.env.agents?.fileIO?.enabled ? `## File I/O
21
+ When the incomming request message contains '[Uploaded files: ...]',
22
+ use the \`read_file\` tool to read each listed file before answering.
23
+ Use the \`emit_file_part\` tool to return files in your response.` : ''}
24
+
25
+ ${ cds.env.agents?.masking ? `## How to handle pseudonymized values
26
+ Never comment on pseudonymization and that you had to work with pseudonymized values
27
+ but use the pseudonymized values in responses like it would be regular values!
28
+ The user sees the actual values and thus should not be made aware of any
29
+ pseudonymization that has taken place internally.` : ''}
30
+
31
+ `.replace(/ {4,}/g,'').trim()
32
+
33
+ if (LOG._debug) LOG.debug (srv.name, '-', "using system prompt:", '\n\n'+ text +'\n')
34
+ return text
25
35
  }
@@ -183,31 +183,32 @@ class CallActionTool extends DynamicStructuredTool {
183
183
  * @param {object} srv - CDS ApplicationService
184
184
  */
185
185
  export function generateTools(srv) {
186
- const entities = getFilteredEntities(srv)
187
- const actions = getFilteredActions(srv)
186
+ const entities = getFilteredEntities(srv), has_entities = Object.keys(entities).length > 0
187
+ const actions = getFilteredActions(srv), has_actions = Object.keys(actions).length > 0
188
188
 
189
189
  const tools = []
190
190
 
191
- // Query tool — one tool for reading all entities
192
- const entityNames = Object.keys(entities)
193
- if (entityNames.length > 0) {
194
- tools.push(new GenericReadTool(srv, entities))
195
- }
196
-
197
191
  // Describe tool — introspect service model
198
- const actionNames = Object.keys(actions)
199
- if (entityNames.length > 0 || actionNames.length > 0) {
192
+ if (has_entities || has_actions) {
193
+ LOG.debug(srv.name, '–', `adding generic 'describe' tool`)
200
194
  tools.push(new DescribeTool(srv, entities, actions))
201
195
  }
202
196
 
197
+ // Query tool — one tool for reading all entities
198
+ if (has_entities) {
199
+ LOG.debug(srv.name, '–', `adding generic 'query' entity tool`)
200
+ tools.push(new GenericReadTool(srv, entities))
201
+ }
202
+
203
203
  // Action/function tools — per-action (default) or combined call action
204
- const usePerActionTools = cds.env.agents?.per_action_tool !== false
205
- if (actionNames.length > 0) {
206
- if (usePerActionTools) {
204
+ if (has_actions) {
205
+ if (cds.env.mcp?.per_action_tool) {
207
206
  for (const [name, action] of Object.entries(actions)) {
207
+ LOG.debug(srv.name, '–', `adding specific tool to call action '${name}'`)
208
208
  tools.push(new PerActionTool(srv, name, action))
209
209
  }
210
210
  } else {
211
+ LOG.debug(srv.name, '–', `adding generic 'call' action tool`)
211
212
  tools.push(new CallActionTool(srv, actions))
212
213
  }
213
214
  }