@memberjunction/ai-agents 6.1.0-edge.6 → 6.1.0

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 (67) hide show
  1. package/dist/SkillImportExportService.d.ts +17 -1
  2. package/dist/SkillImportExportService.d.ts.map +1 -1
  3. package/dist/SkillImportExportService.js +57 -5
  4. package/dist/SkillImportExportService.js.map +1 -1
  5. package/dist/SkillMarkdownConverter.d.ts +17 -1
  6. package/dist/SkillMarkdownConverter.d.ts.map +1 -1
  7. package/dist/SkillMarkdownConverter.js +40 -5
  8. package/dist/SkillMarkdownConverter.js.map +1 -1
  9. package/dist/agent-types/base-agent-type.d.ts +26 -1
  10. package/dist/agent-types/base-agent-type.d.ts.map +1 -1
  11. package/dist/agent-types/base-agent-type.js +17 -0
  12. package/dist/agent-types/base-agent-type.js.map +1 -1
  13. package/dist/agent-types/loop-agent-response-type.d.ts +16 -0
  14. package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
  15. package/dist/agent-types/loop-agent-response-type.js +19 -1
  16. package/dist/agent-types/loop-agent-response-type.js.map +1 -1
  17. package/dist/agent-types/loop-agent-type.d.ts +32 -1
  18. package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
  19. package/dist/agent-types/loop-agent-type.js +190 -3
  20. package/dist/agent-types/loop-agent-type.js.map +1 -1
  21. package/dist/base-agent.d.ts +186 -3
  22. package/dist/base-agent.d.ts.map +1 -1
  23. package/dist/base-agent.js +564 -53
  24. package/dist/base-agent.js.map +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/native-tools/action-tool-builder.d.ts +92 -0
  30. package/dist/native-tools/action-tool-builder.d.ts.map +1 -0
  31. package/dist/native-tools/action-tool-builder.js +226 -0
  32. package/dist/native-tools/action-tool-builder.js.map +1 -0
  33. package/dist/native-tools/control-tools.d.ts +52 -0
  34. package/dist/native-tools/control-tools.d.ts.map +1 -0
  35. package/dist/native-tools/control-tools.js +113 -0
  36. package/dist/native-tools/control-tools.js.map +1 -0
  37. package/dist/native-tools/dual-channel.d.ts +16 -0
  38. package/dist/native-tools/dual-channel.d.ts.map +1 -0
  39. package/dist/native-tools/dual-channel.js +44 -0
  40. package/dist/native-tools/dual-channel.js.map +1 -0
  41. package/dist/native-tools/tool-result-turns.d.ts +32 -0
  42. package/dist/native-tools/tool-result-turns.d.ts.map +1 -0
  43. package/dist/native-tools/tool-result-turns.js +29 -0
  44. package/dist/native-tools/tool-result-turns.js.map +1 -0
  45. package/dist/realtime/bridge-realtime-session-factory.d.ts.map +1 -1
  46. package/dist/realtime/bridge-realtime-session-factory.js +22 -2
  47. package/dist/realtime/bridge-realtime-session-factory.js.map +1 -1
  48. package/dist/realtime/realtime-client-session-service.d.ts +104 -17
  49. package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
  50. package/dist/realtime/realtime-client-session-service.js +325 -28
  51. package/dist/realtime/realtime-client-session-service.js.map +1 -1
  52. package/dist/realtime/realtime-coagent-config.d.ts +61 -1
  53. package/dist/realtime/realtime-coagent-config.d.ts.map +1 -1
  54. package/dist/realtime/realtime-coagent-config.js +93 -1
  55. package/dist/realtime/realtime-coagent-config.js.map +1 -1
  56. package/dist/realtime/realtime-session-runner.d.ts +10 -8
  57. package/dist/realtime/realtime-session-runner.d.ts.map +1 -1
  58. package/dist/realtime/realtime-session-runner.js +11 -9
  59. package/dist/realtime/realtime-session-runner.js.map +1 -1
  60. package/dist/realtime/realtime-tool-broker.d.ts +11 -5
  61. package/dist/realtime/realtime-tool-broker.d.ts.map +1 -1
  62. package/dist/realtime/realtime-tool-broker.js +19 -7
  63. package/dist/realtime/realtime-tool-broker.js.map +1 -1
  64. package/dist/scoped-prompt-config-resolver.d.ts +6 -1
  65. package/dist/scoped-prompt-config-resolver.d.ts.map +1 -1
  66. package/dist/scoped-prompt-config-resolver.js.map +1 -1
  67. package/package.json +18 -18
package/dist/index.d.ts CHANGED
@@ -73,4 +73,8 @@ export * from './realtime/agent-media-library.js';
73
73
  export * from './realtime/realtime-recording-capture.js';
74
74
  export * from './realtime/realtime-recording-store.js';
75
75
  export { RerankerService, RerankerConfiguration, parseRerankerConfiguration, RerankServiceResult, RerankObservabilityOptions, LLMReranker, } from '@memberjunction/ai-reranker';
76
+ export * from './native-tools/action-tool-builder.js';
77
+ export * from './native-tools/dual-channel.js';
78
+ export * from './native-tools/control-tools.js';
79
+ export * from './native-tools/tool-result-turns.js';
76
80
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0CAA0C,CAAC;AACzD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AAKnD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACrI,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,iCAAiC,CAAC;AAChD,cAAc,iDAAiD,CAAC;AAChE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,WAAW,GACZ,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0CAA0C,CAAC;AACzD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AAKnD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACrI,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,iCAAiC,CAAC;AAChD,cAAc,iDAAiD,CAAC;AAChE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AAGpD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,mBAAmB,EACnB,0BAA0B,EAC1B,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC"}
package/dist/index.js CHANGED
@@ -78,4 +78,8 @@ export * from './realtime/realtime-recording-capture.js';
78
78
  export * from './realtime/realtime-recording-store.js';
79
79
  // Re-export from ai-reranker for backward compatibility
80
80
  export { RerankerService, parseRerankerConfiguration, LLMReranker, } from '@memberjunction/ai-reranker';
81
+ export * from './native-tools/action-tool-builder.js';
82
+ export * from './native-tools/dual-channel.js';
83
+ export * from './native-tools/control-tools.js';
84
+ export * from './native-tools/tool-result-turns.js';
81
85
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0CAA0C,CAAC;AACzD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,4FAA4F;AAC5F,8FAA8F;AAC9F,2FAA2F;AAC3F,8BAA8B;AAC9B,OAAO,EAAE,kBAAkB,EAAkE,MAAM,iCAAiC,CAAC;AACrI,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,iCAAiC,CAAC;AAChD,cAAc,iDAAiD,CAAC;AAChE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AAEpD,wDAAwD;AACxD,OAAO,EACL,eAAe,EAEf,0BAA0B,EAG1B,WAAW,GACZ,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,wCAAwC,CAAC;AACvD,cAAc,cAAc,CAAC;AAC7B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wCAAwC,CAAC;AACvD,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0CAA0C,CAAC;AACzD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,iCAAiC,CAAC;AAChD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC;AACjC,cAAc,mCAAmC,CAAC;AAClD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oCAAoC,CAAC;AACnD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,4FAA4F;AAC5F,8FAA8F;AAC9F,2FAA2F;AAC3F,8BAA8B;AAC9B,OAAO,EAAE,kBAAkB,EAAkE,MAAM,iCAAiC,CAAC;AACrI,cAAc,4CAA4C,CAAC;AAC3D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yCAAyC,CAAC;AACxD,cAAc,sCAAsC,CAAC;AACrD,cAAc,0CAA0C,CAAC;AACzD,cAAc,mCAAmC,CAAC;AAClD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,iCAAiC,CAAC;AAChD,cAAc,iDAAiD,CAAC;AAChE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AAEpD,wDAAwD;AACxD,OAAO,EACL,eAAe,EAEf,0BAA0B,EAG1B,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @fileoverview Maps MJ Actions onto native tool declarations (plan §8.2).
3
+ * @module @memberjunction/ai-agents
4
+ */
5
+ import type { ChatTool } from '@memberjunction/ai';
6
+ import type { MJActionParamEntity } from '@memberjunction/core-entities';
7
+ import type { MJActionEntityExtended } from '@memberjunction/actions-base';
8
+ /** One Action, and the provider-legal tool name it was declared under. */
9
+ export interface ActionToolBinding {
10
+ /** Discriminant shared with the control-flow bindings in `control-tools.ts`. */
11
+ kind: 'action';
12
+ /** The sanitized name the model calls. */
13
+ toolName: string;
14
+ /** The Action the framework dispatches when that name comes back. */
15
+ action: MJActionEntityExtended;
16
+ tool: ChatTool;
17
+ }
18
+ /**
19
+ * A built tool set plus the reverse map from tool name back to Action.
20
+ *
21
+ * The reverse map is not a convenience — a tool call arrives as a sanitized string, and without it
22
+ * the framework cannot tell which Action to dispatch. It is built alongside the declarations so
23
+ * the two can never disagree.
24
+ */
25
+ export interface ActionToolSet {
26
+ tools: ChatTool[];
27
+ /** Keyed by the sanitized tool name. */
28
+ byToolName: Map<string, ActionToolBinding>;
29
+ }
30
+ /**
31
+ * Ceiling on a tool's `description` — an OPERATING POINT, not a provider limit.
32
+ *
33
+ * No tool-capable vendor enforces a cap anywhere near here: OpenAI (gpt-5.6-luna), Cerebras
34
+ * (gpt-oss-120b) and Gemini (3.7 Flash) each accepted an 8,000-character description on a live
35
+ * call. The number is chosen from measurement instead. A comparison run used the
36
+ * same 1,026-observation corpus at 1,024 and at 4,096 (results doc §10–§11): at 1,024 — where a
37
+ * large Action degrades to output names and result codes with descriptions trimmed — native
38
+ * selection accuracy improved on two of three models (+6.3pp Gemini, +11.3pp GPT 5.6-luna). At
39
+ * 4,096, with every description in full, both gains disappeared, GPT-OSS-120B fell a further 5pp,
40
+ * its prompt grew by ~700 tokens per call, and it began returning no action at all on cases it
41
+ * had handled. Same-case comparison: −10 correct turns net.
42
+ *
43
+ * So the names and codes are what discriminates; the sentences around them are dilution the
44
+ * smallest model pays for most. One A/B at N=3 is directional rather than definitive (envelope-arm
45
+ * run-to-run noise is ±2–3pp), and a per-provider ceiling is the obvious follow-up — but until
46
+ * someone measures that, compact is the point the data favours. The detail-degradation below is
47
+ * therefore the NORMAL path for large Actions, not a safety net.
48
+ */
49
+ export declare const MAX_TOOL_DESCRIPTION_LENGTH = 1024;
50
+ /**
51
+ * Sanitizes an Action name into a provider-legal tool name (§8.2: `[a-zA-Z0-9_-]`, ≤64 chars).
52
+ *
53
+ * "Run Ad-hoc Query" → "run_ad_hoc_query". Deterministic, because a call has to resolve back to
54
+ * the Action that produced it; the collision check lives in {@link buildActionToolSet} rather than
55
+ * here, so this stays a pure function of the name.
56
+ */
57
+ export declare function sanitizeToolName(actionName: string): string;
58
+ /**
59
+ * Builds the `ChatTool` declaration for one Action.
60
+ *
61
+ * Only `Input` and `Both` params are declared: an `Output` param is something the Action returns,
62
+ * and declaring it would invite the model to supply it.
63
+ */
64
+ export declare function buildToolFromAction(action: MJActionEntityExtended, params: readonly MJActionParamEntity[]): ChatTool;
65
+ /**
66
+ * Builds the full tool set for an agent's available Actions, with the reverse map.
67
+ *
68
+ * **A post-sanitization collision is a hard error** (§8.2), not a silent disambiguation. Two
69
+ * Actions whose names differ only by punctuation would otherwise produce one tool name, and every
70
+ * call to it would dispatch whichever Action happened to be registered last — a routing bug that
71
+ * looks like a model error and would be found, if at all, by someone reading eval failures.
72
+ * Failing at build time turns it into a metadata problem with a name attached.
73
+ */
74
+ export declare function buildActionToolSet(actions: readonly MJActionEntityExtended[], paramsByActionId: ReadonlyMap<string, readonly MJActionParamEntity[]>): ActionToolSet;
75
+ /** The two fields of an `MJ: AI Agent Actions` row that declaration control reads. */
76
+ export interface AgentActionDeclarationRow {
77
+ ActionID: string | null;
78
+ DeclareAsNativeTool: boolean;
79
+ }
80
+ /**
81
+ * Removes the Actions an agent has chosen not to declare as native tools.
82
+ *
83
+ * Only an explicit `DeclareAsNativeTool = false` on the agent-action row excludes an action. An
84
+ * action with no row — one granted through a skill at runtime — stays declarable, because the
85
+ * default is to declare. Pure so the rule is testable without the engine; `BaseAgent` supplies the
86
+ * rows from `AIEngine.Instance.AgentActions`.
87
+ *
88
+ * Note the consequence the design accepts: in native mode the prose catalog is not rendered, so an
89
+ * action removed here is unreachable on that turn, not merely de-emphasised.
90
+ */
91
+ export declare function filterDeclarableActions(actions: readonly MJActionEntityExtended[], agentActionRows: ReadonlyArray<AgentActionDeclarationRow>): MJActionEntityExtended[];
92
+ //# sourceMappingURL=action-tool-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-tool-builder.d.ts","sourceRoot":"","sources":["../../src/native-tools/action-tool-builder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,0EAA0E;AAC1E,MAAM,WAAW,iBAAiB;IAC9B,gFAAgF;IAChF,IAAI,EAAE,QAAQ,CAAC;IACf,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,MAAM,EAAE,sBAAsB,CAAC;IAC/B,IAAI,EAAE,QAAQ,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,wCAAwC;IACxC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC9C;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAKhD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAO3D;AAwHD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,SAAS,mBAAmB,EAAE,GAAG,QAAQ,CA4BpH;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,gBAAgB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC,GACtE,aAAa,CAqBf;AAED,sFAAsF;AACtF,MAAM,WAAW,yBAAyB;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,mBAAmB,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACnC,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,eAAe,EAAE,aAAa,CAAC,yBAAyB,CAAC,GAC1D,sBAAsB,EAAE,CAO1B"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @fileoverview Maps MJ Actions onto native tool declarations (plan §8.2).
3
+ * @module @memberjunction/ai-agents
4
+ */
5
+ /** Providers cap tool names at 64 characters. */
6
+ const MAX_TOOL_NAME_LENGTH = 64;
7
+ /**
8
+ * Ceiling on a tool's `description` — an OPERATING POINT, not a provider limit.
9
+ *
10
+ * No tool-capable vendor enforces a cap anywhere near here: OpenAI (gpt-5.6-luna), Cerebras
11
+ * (gpt-oss-120b) and Gemini (3.7 Flash) each accepted an 8,000-character description on a live
12
+ * call. The number is chosen from measurement instead. A comparison run used the
13
+ * same 1,026-observation corpus at 1,024 and at 4,096 (results doc §10–§11): at 1,024 — where a
14
+ * large Action degrades to output names and result codes with descriptions trimmed — native
15
+ * selection accuracy improved on two of three models (+6.3pp Gemini, +11.3pp GPT 5.6-luna). At
16
+ * 4,096, with every description in full, both gains disappeared, GPT-OSS-120B fell a further 5pp,
17
+ * its prompt grew by ~700 tokens per call, and it began returning no action at all on cases it
18
+ * had handled. Same-case comparison: −10 correct turns net.
19
+ *
20
+ * So the names and codes are what discriminates; the sentences around them are dilution the
21
+ * smallest model pays for most. One A/B at N=3 is directional rather than definitive (envelope-arm
22
+ * run-to-run noise is ±2–3pp), and a per-provider ceiling is the obvious follow-up — but until
23
+ * someone measures that, compact is the point the data favours. The detail-degradation below is
24
+ * therefore the NORMAL path for large Actions, not a safety net.
25
+ */
26
+ export const MAX_TOOL_DESCRIPTION_LENGTH = 1024;
27
+ /** Per-item description lengths tried in order until the whole description fits the cap. */
28
+ const DESCRIPTION_DETAIL_LEVELS = [160, 110, 70, 40, 0];
29
+ /**
30
+ * Sanitizes an Action name into a provider-legal tool name (§8.2: `[a-zA-Z0-9_-]`, ≤64 chars).
31
+ *
32
+ * "Run Ad-hoc Query" → "run_ad_hoc_query". Deterministic, because a call has to resolve back to
33
+ * the Action that produced it; the collision check lives in {@link buildActionToolSet} rather than
34
+ * here, so this stays a pure function of the name.
35
+ */
36
+ export function sanitizeToolName(actionName) {
37
+ return actionName
38
+ .trim()
39
+ .replace(/[^a-zA-Z0-9]+/g, '_')
40
+ .replace(/^_+|_+$/g, '')
41
+ .toLowerCase()
42
+ .slice(0, MAX_TOOL_NAME_LENGTH);
43
+ }
44
+ /**
45
+ * Maps one param's `ValueType` onto a JSON Schema fragment (§8.2 table).
46
+ *
47
+ * `ActionParam.ValueType` distinguishes only five coarse kinds, so this mapping is lossy by
48
+ * construction and the prose `Description` carries the real type — exactly as the rendered action
49
+ * catalog does today. Two choices here were settled by measurement rather than by reasoning
50
+ * Measured:
51
+ *
52
+ * - **`Scalar` emits a union type.** It appears to violate the cross-provider common subset —
53
+ * OpenAPI 3.0, which Gemini's classic function declarations follow, has no union `type` — but it
54
+ * measured clean on every provider tested, so the plan's literal mapping stands.
55
+ * - **Everything else emits `string`, not `object`.** §8.2 originally specified `object` for the
56
+ * opaque kinds, reasoning it was "exact parity with the prose catalog". It is not:
57
+ * `Run Ad-hoc Query.Query` is `ValueType: 'Other'` but holds SQL text, and typing it as an
58
+ * object made models emit `Query: {}` on 40% of calls — well-formed, dispatchable and useless,
59
+ * which no well-formedness check catches. Switching to `string` took usable arguments from
60
+ * 60% to 100% on the same prompts. The structural type beats the prose description whenever the
61
+ * two disagree, so it must not disagree.
62
+ */
63
+ function schemaForValueType(valueType) {
64
+ return valueType === 'Scalar'
65
+ ? { type: ['string', 'number', 'boolean'] }
66
+ : { type: 'string' };
67
+ }
68
+ /**
69
+ * Folds the metadata that has nowhere structural to go into the property description.
70
+ *
71
+ * Dropping `DefaultValue` would make the tool strictly less informative than the prose catalog it
72
+ * replaces, which is the one thing this mapping must never be.
73
+ */
74
+ function describeParam(param) {
75
+ const parts = [];
76
+ if (param.Description) {
77
+ parts.push(param.Description.trim());
78
+ }
79
+ if (param.DefaultValue) {
80
+ parts.push(`Default: ${param.DefaultValue}.`);
81
+ }
82
+ return parts.join(' ');
83
+ }
84
+ /** A single clause of the description, trimmed to the current detail level. */
85
+ function clip(text, max) {
86
+ const t = (text ?? '').replace(/\s+/g, ' ').trim();
87
+ if (max === 0 || t.length === 0) {
88
+ return '';
89
+ }
90
+ return t.length <= max ? t : `${t.slice(0, max - 1).trimEnd()}…`;
91
+ }
92
+ /**
93
+ * Composes the tool description at one level of detail. Sections with nothing to say are omitted
94
+ * rather than emitted empty, so an Action with no outputs or result codes reads exactly as before.
95
+ */
96
+ function composeDescription(action, outputs, codes, detail) {
97
+ // §8.2: prescriptive about WHEN to call, not merely what the tool does — it measurably
98
+ // improves should-call rates, and an Action's Description is rarely phrased that way.
99
+ const lines = [`Call this when you need to: ${(action.Description ?? action.Name).trim()}`];
100
+ if (outputs.length > 0) {
101
+ lines.push(`Returns: ${outputs.map((p) => {
102
+ const d = clip(p.Description, detail);
103
+ return d ? `${p.Name} (${d})` : p.Name;
104
+ }).join(', ')}`);
105
+ }
106
+ if (codes.length > 0) {
107
+ lines.push(`Results: ${codes.map((rc) => {
108
+ const d = clip(rc.Description, detail);
109
+ // Mirror the prose catalog's convention, and skip a description that merely restates the code.
110
+ const restates = d.toLowerCase() === rc.ResultCode.toLowerCase();
111
+ return `${rc.ResultCode} ${rc.IsSuccess ? '✓' : '✗'}${d && !restates ? ` ${d}` : ''}`;
112
+ }).join(' · ')}`);
113
+ }
114
+ return lines.join('\n');
115
+ }
116
+ /**
117
+ * Builds the tool's description — everything the prose action catalog says about an Action that
118
+ * has no structural home in the declaration.
119
+ *
120
+ * **Why outputs and result codes are here.** `formatActionDetails`, the prose catalog the envelope
121
+ * path renders, gives the model five things per action: name, description, inputs, outputs and
122
+ * result codes. The first version of this builder gave it three — and measurement showed the
123
+ * consequence. The confusion pairs were identical in both arms (`Run Ad-hoc Query` mistaken for
124
+ * `Search Query Catalog` on every model), but the native arm confused them MORE: P(right tool |
125
+ * acted) fell 82% → 70% on GPT-OSS-120B. For that pair the outputs and result codes are the
126
+ * discriminator — `Search Query Catalog` carries `NO_MATCHES ✓ … Proceed with ad-hoc SQL`, which
127
+ * states the relationship between the two actions in one line. A model reading prose saw it; a
128
+ * model reading the declaration did not. The rule this file already stated — never less
129
+ * informative than the prose catalog — was being broken by two sections out of five.
130
+ *
131
+ * **Why the detail degrades instead of the cap truncating.** Providers cap the description; some
132
+ * Actions have nine result codes with sentence-long explanations. A blind `slice` would keep the
133
+ * first few codes in full and drop the rest entirely, which is the worst trade — names and codes
134
+ * are the cheap, high-information part. So per-item descriptions shrink through
135
+ * {@link DESCRIPTION_DETAIL_LEVELS} until the whole thing fits, and only at detail 0 (names and
136
+ * codes alone) does a hard trim apply as a last resort.
137
+ */
138
+ function describeTool(action, params) {
139
+ const outputs = params.filter((p) => p.Type === 'Output' || p.Type === 'Both');
140
+ // Harness stand-ins may build an Action literal without the related-record collection.
141
+ const codes = action.ResultCodes?.Items ?? [];
142
+ for (const detail of DESCRIPTION_DETAIL_LEVELS) {
143
+ const text = composeDescription(action, outputs, codes, detail);
144
+ if (text.length <= MAX_TOOL_DESCRIPTION_LENGTH) {
145
+ return text;
146
+ }
147
+ }
148
+ return `${composeDescription(action, outputs, codes, 0).slice(0, MAX_TOOL_DESCRIPTION_LENGTH - 1).trimEnd()}…`;
149
+ }
150
+ /**
151
+ * Builds the `ChatTool` declaration for one Action.
152
+ *
153
+ * Only `Input` and `Both` params are declared: an `Output` param is something the Action returns,
154
+ * and declaring it would invite the model to supply it.
155
+ */
156
+ export function buildToolFromAction(action, params) {
157
+ const properties = {};
158
+ const required = [];
159
+ for (const param of params) {
160
+ if (param.Type !== 'Input' && param.Type !== 'Both') {
161
+ continue;
162
+ }
163
+ const element = schemaForValueType(param.ValueType);
164
+ // IsArray wraps the element schema rather than replacing it (§8.2).
165
+ const schema = param.IsArray ? { type: 'array', items: element } : element;
166
+ const description = describeParam(param);
167
+ properties[param.Name] = description ? { ...schema, description } : schema;
168
+ if (param.IsRequired) {
169
+ required.push(param.Name);
170
+ }
171
+ }
172
+ const inputSchema = { type: 'object', properties };
173
+ if (required.length > 0) {
174
+ inputSchema.required = required;
175
+ }
176
+ return {
177
+ name: sanitizeToolName(action.Name),
178
+ description: describeTool(action, params),
179
+ inputSchema
180
+ };
181
+ }
182
+ /**
183
+ * Builds the full tool set for an agent's available Actions, with the reverse map.
184
+ *
185
+ * **A post-sanitization collision is a hard error** (§8.2), not a silent disambiguation. Two
186
+ * Actions whose names differ only by punctuation would otherwise produce one tool name, and every
187
+ * call to it would dispatch whichever Action happened to be registered last — a routing bug that
188
+ * looks like a model error and would be found, if at all, by someone reading eval failures.
189
+ * Failing at build time turns it into a metadata problem with a name attached.
190
+ */
191
+ export function buildActionToolSet(actions, paramsByActionId) {
192
+ const byToolName = new Map();
193
+ const tools = [];
194
+ for (const action of actions) {
195
+ const tool = buildToolFromAction(action, paramsByActionId.get(action.ID) ?? []);
196
+ const existing = byToolName.get(tool.name);
197
+ if (existing) {
198
+ throw new Error(`Action tool name collision: '${existing.action.Name}' and '${action.Name}' both sanitize to `
199
+ + `'${tool.name}'. Rename one of the Actions — a tool call cannot be resolved back to an Action otherwise.`);
200
+ }
201
+ if (tool.name.length === 0) {
202
+ throw new Error(`Action '${action.Name}' sanitizes to an empty tool name — it must contain at least one alphanumeric character.`);
203
+ }
204
+ byToolName.set(tool.name, { kind: 'action', toolName: tool.name, action, tool });
205
+ tools.push(tool);
206
+ }
207
+ return { tools, byToolName };
208
+ }
209
+ /**
210
+ * Removes the Actions an agent has chosen not to declare as native tools.
211
+ *
212
+ * Only an explicit `DeclareAsNativeTool = false` on the agent-action row excludes an action. An
213
+ * action with no row — one granted through a skill at runtime — stays declarable, because the
214
+ * default is to declare. Pure so the rule is testable without the engine; `BaseAgent` supplies the
215
+ * rows from `AIEngine.Instance.AgentActions`.
216
+ *
217
+ * Note the consequence the design accepts: in native mode the prose catalog is not rendered, so an
218
+ * action removed here is unreachable on that turn, not merely de-emphasised.
219
+ */
220
+ export function filterDeclarableActions(actions, agentActionRows) {
221
+ const excluded = new Set(agentActionRows
222
+ .filter((row) => row.DeclareAsNativeTool === false && row.ActionID)
223
+ .map((row) => row.ActionID.toLowerCase()));
224
+ return actions.filter((action) => !excluded.has(action.ID.toLowerCase()));
225
+ }
226
+ //# sourceMappingURL=action-tool-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-tool-builder.js","sourceRoot":"","sources":["../../src/native-tools/action-tool-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @fileoverview Control-flow tools for the implicit protocol (spec §2.2, §4): one tool per
3
+ * sub-agent, `payload_change_request`, `ask_user`. Built beside the Action tools so the reverse map
4
+ * resolves every call the model can make.
5
+ *
6
+ * The agent declares these without knowing which model will answer. The prompt runner keeps them
7
+ * only when the selected model's `LLM.NativeControlFlow` resolves to `'implicit'` and strips them
8
+ * otherwise — see `AIPromptParams.controlFlowToolNames`.
9
+ * @module @memberjunction/ai-agents
10
+ */
11
+ import type { ChatTool } from '@memberjunction/ai';
12
+ import type { MJAIAgentEntityExtended } from '@memberjunction/ai-core-plus';
13
+ import { type ActionToolBinding, type ActionToolSet } from './action-tool-builder.js';
14
+ export declare const PAYLOAD_CHANGE_TOOL = "payload_change_request";
15
+ export declare const ASK_USER_TOOL = "ask_user";
16
+ export declare const SUB_AGENT_TOOL_PREFIX = "delegate_to_";
17
+ /** The fixed control tools. Sub-agent tools are recognised by {@link SUB_AGENT_TOOL_PREFIX}. */
18
+ export declare const NATIVE_CONTROL_TOOL_NAMES: readonly string[];
19
+ /** Every tool the agent can declare, and what a call to it means. Discriminated on `kind`. */
20
+ export type NativeToolBinding = ActionToolBinding | {
21
+ kind: 'subAgent';
22
+ toolName: string;
23
+ agent: MJAIAgentEntityExtended;
24
+ tool: ChatTool;
25
+ } | {
26
+ kind: 'payloadChange';
27
+ toolName: string;
28
+ tool: ChatTool;
29
+ } | {
30
+ kind: 'askUser';
31
+ toolName: string;
32
+ tool: ChatTool;
33
+ };
34
+ export interface NativeToolSet {
35
+ tools: ChatTool[];
36
+ /** Keyed by the declared tool name. */
37
+ byToolName: Map<string, NativeToolBinding>;
38
+ /** Every declared name that is NOT an Action — what the runner strips for hybrid models. */
39
+ controlToolNames: string[];
40
+ }
41
+ /** `payload_change_request` — a state write that continues the loop (spec §3). */
42
+ export declare function buildPayloadChangeTool(): ChatTool;
43
+ /** `ask_user` — the one explicit control tool: the run pauses as `Chat` / `AwaitingFeedback` (spec §1). */
44
+ export declare function buildAskUserTool(): ChatTool;
45
+ /** One tool per sub-agent: `delegate_to_<sanitized name>`, described by the agent's own description. */
46
+ export declare function buildSubAgentTool(agent: MJAIAgentEntityExtended): ChatTool;
47
+ /**
48
+ * Actions, then sub-agents, then the fixed control tools — one reverse map for all of them.
49
+ * Collisions and reserved-name clashes are hard errors, exactly as Action/Action collisions are.
50
+ */
51
+ export declare function buildNativeToolSet(actionSet: ActionToolSet, subAgents: readonly MJAIAgentEntityExtended[]): NativeToolSet;
52
+ //# sourceMappingURL=control-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-tools.d.ts","sourceRoot":"","sources":["../../src/native-tools/control-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAiD,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAElI,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAC5D,eAAO,MAAM,aAAa,aAAa,CAAC;AACxC,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD,gGAAgG;AAChG,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAAyC,CAAC;AAIjG,8FAA8F;AAC9F,MAAM,MAAM,iBAAiB,GACvB,iBAAiB,GACjB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,uBAAuB,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACtF;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,uCAAuC;IACvC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC3C,4FAA4F;IAC5F,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAID,kFAAkF;AAClF,wBAAgB,sBAAsB,IAAI,QAAQ,CAsBjD;AAED,2GAA2G;AAC3G,wBAAgB,gBAAgB,IAAI,QAAQ,CA8B3C;AAED,wGAAwG;AACxG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,uBAAuB,GAAG,QAAQ,CAc1E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,uBAAuB,EAAE,GAAG,aAAa,CA6BzH"}
@@ -0,0 +1,113 @@
1
+ import { sanitizeToolName, MAX_TOOL_DESCRIPTION_LENGTH } from './action-tool-builder.js';
2
+ export const PAYLOAD_CHANGE_TOOL = 'payload_change_request';
3
+ export const ASK_USER_TOOL = 'ask_user';
4
+ export const SUB_AGENT_TOOL_PREFIX = 'delegate_to_';
5
+ /** The fixed control tools. Sub-agent tools are recognised by {@link SUB_AGENT_TOOL_PREFIX}. */
6
+ export const NATIVE_CONTROL_TOOL_NAMES = [PAYLOAD_CHANGE_TOOL, ASK_USER_TOOL];
7
+ /** Providers cap tool names at 64 characters. */
8
+ const MAX_TOOL_NAME_LENGTH = 64;
9
+ const clip = (text, max) => (text.length <= max ? text : `${text.slice(0, max - 1)}…`);
10
+ /** `payload_change_request` — a state write that continues the loop (spec §3). */
11
+ export function buildPayloadChangeTool() {
12
+ const section = (what) => ({ type: 'object', description: what });
13
+ return {
14
+ name: PAYLOAD_CHANGE_TOOL,
15
+ description: clip('Write to the shared payload. Call this when your work has produced results the payload contract says to store ' +
16
+ '(findings, code, results, drafts). Use newElements for keys that do not exist yet, updateElements for surgical ' +
17
+ 'changes to keys that do (only the changing parts; arrays keep unchanged items as {}), replaceElements to swap a whole ' +
18
+ 'object, removeElements to delete keys. The change is applied and the loop continues — when the task is then finished, ' +
19
+ 'reply in plain text. Do not call this to report progress; only to store data.', MAX_TOOL_DESCRIPTION_LENGTH),
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ newElements: section('Keys and values to ADD that are not in the payload yet.'),
24
+ updateElements: section('Existing keys to UPDATE — only the parts that change.'),
25
+ replaceElements: section('Existing objects to REPLACE entirely.'),
26
+ removeElements: section('Keys to REMOVE (value ignored).'),
27
+ reasoning: { type: 'string', description: 'One sentence on why this change.' }
28
+ },
29
+ required: []
30
+ }
31
+ };
32
+ }
33
+ /** `ask_user` — the one explicit control tool: the run pauses as `Chat` / `AwaitingFeedback` (spec §1). */
34
+ export function buildAskUserTool() {
35
+ return {
36
+ name: ASK_USER_TOOL,
37
+ description: clip('Stop and ask the user. Use only when you need something only the user can give you — a choice between ' +
38
+ 'options only they can make, a value that exists nowhere in the payload, conversation or tools, permission. ' +
39
+ 'If a declared sub-agent or an Action can supply what you need, use it instead of asking. The run pauses ' +
40
+ 'until the user answers. Do NOT use this to report results or say you are done: for that, reply in plain ' +
41
+ 'text with no tool call.', MAX_TOOL_DESCRIPTION_LENGTH),
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ message: { type: 'string', description: 'The question or request for the user, in plain language.' },
46
+ responseForm: {
47
+ type: 'object',
48
+ description: 'Optional. A structured form for the answer — the same shape as `responseForm` in the Response Forms ' +
49
+ 'section of your instructions: { title?, description?, submitLabel?, questions: [{ id, label, type, … }] }. ' +
50
+ 'Use it when the user should pick from options or fill in fields; omit it for a free-text question.',
51
+ properties: {
52
+ title: { type: 'string' },
53
+ description: { type: 'string' },
54
+ submitLabel: { type: 'string' },
55
+ questions: { type: 'array', items: { type: 'object' } }
56
+ }
57
+ }
58
+ },
59
+ required: ['message']
60
+ }
61
+ };
62
+ }
63
+ /** One tool per sub-agent: `delegate_to_<sanitized name>`, described by the agent's own description. */
64
+ export function buildSubAgentTool(agent) {
65
+ const name = `${SUB_AGENT_TOOL_PREFIX}${sanitizeToolName(agent.Name)}`.slice(0, MAX_TOOL_NAME_LENGTH);
66
+ return {
67
+ name,
68
+ description: clip(`Delegate to the ${agent.Name} sub-agent. ${agent.Description ?? ''}`.trim(), MAX_TOOL_DESCRIPTION_LENGTH),
69
+ inputSchema: {
70
+ type: 'object',
71
+ properties: {
72
+ message: { type: 'string', description: 'Instructions for the sub-agent — what to do. Not the payload; it receives that separately.' },
73
+ terminateAfter: { type: 'boolean', description: 'true to end your own run when the sub-agent finishes; false (default) to continue with its result.' }
74
+ },
75
+ required: ['message']
76
+ }
77
+ };
78
+ }
79
+ /**
80
+ * Actions, then sub-agents, then the fixed control tools — one reverse map for all of them.
81
+ * Collisions and reserved-name clashes are hard errors, exactly as Action/Action collisions are.
82
+ */
83
+ export function buildNativeToolSet(actionSet, subAgents) {
84
+ const byToolName = new Map(actionSet.byToolName);
85
+ const tools = [...actionSet.tools];
86
+ const controlToolNames = [];
87
+ for (const reserved of NATIVE_CONTROL_TOOL_NAMES) {
88
+ const clash = actionSet.byToolName.get(reserved);
89
+ if (clash) {
90
+ throw new Error(`Action '${clash.action.Name}' sanitizes to '${reserved}', which is a reserved control-tool name. Rename the Action.`);
91
+ }
92
+ }
93
+ for (const agent of subAgents) {
94
+ const tool = buildSubAgentTool(agent);
95
+ const existing = byToolName.get(tool.name);
96
+ if (existing) {
97
+ const other = existing.kind === 'action' ? `Action '${existing.action.Name}'`
98
+ : existing.kind === 'subAgent' ? `sub-agent '${existing.agent.Name}'` : `'${existing.toolName}'`;
99
+ throw new Error(`Tool name collision: sub-agent '${agent.Name}' and ${other} both declare '${tool.name}'. Rename one.`);
100
+ }
101
+ byToolName.set(tool.name, { kind: 'subAgent', toolName: tool.name, agent, tool });
102
+ tools.push(tool);
103
+ controlToolNames.push(tool.name);
104
+ }
105
+ const payload = buildPayloadChangeTool();
106
+ const ask = buildAskUserTool();
107
+ byToolName.set(payload.name, { kind: 'payloadChange', toolName: payload.name, tool: payload });
108
+ byToolName.set(ask.name, { kind: 'askUser', toolName: ask.name, tool: ask });
109
+ tools.push(payload, ask);
110
+ controlToolNames.push(payload.name, ask.name);
111
+ return { tools, byToolName, controlToolNames };
112
+ }
113
+ //# sourceMappingURL=control-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-tools.js","sourceRoot":"","sources":["../../src/native-tools/control-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @fileoverview Detecting a turn that answered on BOTH channels.
3
+ * @module @memberjunction/ai-agents
4
+ */
5
+ /**
6
+ * Whether assistant content is a Loop envelope — a JSON object carrying `taskComplete`,
7
+ * `nextStep` or `payloadChangeRequest` — allowing for a markdown fence.
8
+ *
9
+ * Used on native turns that made tool calls: if this is ALSO true, the model gave two answers and
10
+ * the loop's tool-call-wins rule discards one. The eval's normalizer applies the same test
11
+ * independently (it must stay framework-free), so keep the two in step if this changes.
12
+ *
13
+ * @param content The assistant message content — a string, or an array of content blocks
14
+ */
15
+ export declare function looksLikeLoopEnvelope(content: unknown): boolean;
16
+ //# sourceMappingURL=dual-channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-channel.d.ts","sourceRoot":"","sources":["../../src/native-tools/dual-channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CA0B/D"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @fileoverview Detecting a turn that answered on BOTH channels.
3
+ * @module @memberjunction/ai-agents
4
+ */
5
+ /**
6
+ * Whether assistant content is a Loop envelope — a JSON object carrying `taskComplete`,
7
+ * `nextStep` or `payloadChangeRequest` — allowing for a markdown fence.
8
+ *
9
+ * Used on native turns that made tool calls: if this is ALSO true, the model gave two answers and
10
+ * the loop's tool-call-wins rule discards one. The eval's normalizer applies the same test
11
+ * independently (it must stay framework-free), so keep the two in step if this changes.
12
+ *
13
+ * @param content The assistant message content — a string, or an array of content blocks
14
+ */
15
+ export function looksLikeLoopEnvelope(content) {
16
+ let text;
17
+ if (typeof content === 'string') {
18
+ text = content;
19
+ }
20
+ else if (Array.isArray(content)) {
21
+ text = content
22
+ .filter((block) => typeof block === 'object' && block !== null
23
+ && block.type === 'text'
24
+ && typeof block.content === 'string')
25
+ .map((block) => block.content)
26
+ .join('');
27
+ }
28
+ else {
29
+ return false;
30
+ }
31
+ const stripped = text.trim().replace(/^```[a-zA-Z]*\s*\n?/, '').replace(/\n?```\s*$/, '').trim();
32
+ if (!stripped.startsWith('{')) {
33
+ return false;
34
+ }
35
+ try {
36
+ const parsed = JSON.parse(stripped);
37
+ return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
38
+ && ('taskComplete' in parsed || 'nextStep' in parsed || 'payloadChangeRequest' in parsed);
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ //# sourceMappingURL=dual-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dual-channel.js","sourceRoot":"","sources":["../../src/native-tools/dual-channel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IAClD,IAAI,IAAY,CAAC;IACjB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,GAAG,OAAO,CAAC;IACnB,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,IAAI,GAAG,OAAO;aACT,MAAM,CAAC,CAAC,KAAK,EAA8C,EAAE,CAC1D,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;eACvC,KAA4B,CAAC,IAAI,KAAK,MAAM;eAC7C,OAAQ,KAA+B,CAAC,OAAO,KAAK,QAAQ,CAAC;aACnE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;aAC7B,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;SAAM,CAAC;QACJ,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACjG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC;QACD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;eACvE,CAAC,cAAc,IAAI,MAAM,IAAI,UAAU,IAAI,MAAM,IAAI,sBAAsB,IAAI,MAAM,CAAC,CAAC;IAClG,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}