@indexnetwork/protocol 4.5.0-rc.322.1 → 4.5.0-rc.324.1

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 (111) hide show
  1. package/dist/agent/agent.tools.js +1 -1
  2. package/dist/agent/agent.tools.js.map +1 -1
  3. package/dist/chat/chat.interrupt.classifier.js +1 -1
  4. package/dist/chat/chat.interrupt.classifier.js.map +1 -1
  5. package/dist/chat/chat.suggester.js +3 -3
  6. package/dist/chat/chat.suggester.js.map +1 -1
  7. package/dist/chat/chat.title.generator.js +2 -2
  8. package/dist/chat/chat.title.generator.js.map +1 -1
  9. package/dist/contact/contact.tools.js +1 -1
  10. package/dist/contact/contact.tools.js.map +1 -1
  11. package/dist/enrichment/enrichment.graph.d.ts.map +1 -1
  12. package/dist/enrichment/enrichment.graph.js +9 -3
  13. package/dist/enrichment/enrichment.graph.js.map +1 -1
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/integration/integration.tools.js +1 -1
  19. package/dist/integration/integration.tools.js.map +1 -1
  20. package/dist/intent/intent.graph.d.ts.map +1 -1
  21. package/dist/intent/intent.graph.js +12 -10
  22. package/dist/intent/intent.graph.js.map +1 -1
  23. package/dist/intent/intent.indexer.d.ts.map +1 -1
  24. package/dist/intent/intent.indexer.js +4 -3
  25. package/dist/intent/intent.indexer.js.map +1 -1
  26. package/dist/intent/intent.inferrer.d.ts.map +1 -1
  27. package/dist/intent/intent.inferrer.js +2 -1
  28. package/dist/intent/intent.inferrer.js.map +1 -1
  29. package/dist/intent/intent.reconciler.d.ts.map +1 -1
  30. package/dist/intent/intent.reconciler.js +5 -4
  31. package/dist/intent/intent.reconciler.js.map +1 -1
  32. package/dist/intent/intent.verifier.d.ts.map +1 -1
  33. package/dist/intent/intent.verifier.js +4 -3
  34. package/dist/intent/intent.verifier.js.map +1 -1
  35. package/dist/maintenance/maintenance.graph.d.ts.map +1 -1
  36. package/dist/maintenance/maintenance.graph.js +27 -5
  37. package/dist/maintenance/maintenance.graph.js.map +1 -1
  38. package/dist/mcp/mcp.server.d.ts.map +1 -1
  39. package/dist/mcp/mcp.server.js +5 -4
  40. package/dist/mcp/mcp.server.js.map +1 -1
  41. package/dist/negotiation/insight.generator.js +2 -2
  42. package/dist/negotiation/insight.generator.js.map +1 -1
  43. package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
  44. package/dist/negotiation/negotiation.graph.js +15 -11
  45. package/dist/negotiation/negotiation.graph.js.map +1 -1
  46. package/dist/negotiation/negotiation.tools.js +1 -1
  47. package/dist/negotiation/negotiation.tools.js.map +1 -1
  48. package/dist/network/network.recommender.d.ts.map +1 -1
  49. package/dist/network/network.recommender.js +5 -4
  50. package/dist/network/network.recommender.js.map +1 -1
  51. package/dist/network/network.tools.d.ts.map +1 -1
  52. package/dist/network/network.tools.js +4 -2
  53. package/dist/network/network.tools.js.map +1 -1
  54. package/dist/opportunity/feed/feed.graph.d.ts.map +1 -1
  55. package/dist/opportunity/feed/feed.graph.js +30 -23
  56. package/dist/opportunity/feed/feed.graph.js.map +1 -1
  57. package/dist/opportunity/opportunity.discover.d.ts.map +1 -1
  58. package/dist/opportunity/opportunity.discover.js +6 -4
  59. package/dist/opportunity/opportunity.discover.js.map +1 -1
  60. package/dist/opportunity/opportunity.enricher.js +2 -2
  61. package/dist/opportunity/opportunity.enricher.js.map +1 -1
  62. package/dist/opportunity/opportunity.evaluator.d.ts.map +1 -1
  63. package/dist/opportunity/opportunity.evaluator.js +9 -7
  64. package/dist/opportunity/opportunity.evaluator.js.map +1 -1
  65. package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
  66. package/dist/opportunity/opportunity.graph.js +123 -105
  67. package/dist/opportunity/opportunity.graph.js.map +1 -1
  68. package/dist/opportunity/opportunity.introducer.js +5 -5
  69. package/dist/opportunity/opportunity.introducer.js.map +1 -1
  70. package/dist/opportunity/opportunity.persist.js +2 -2
  71. package/dist/opportunity/opportunity.persist.js.map +1 -1
  72. package/dist/opportunity/opportunity.presenter.d.ts.map +1 -1
  73. package/dist/opportunity/opportunity.presenter.js +4 -2
  74. package/dist/opportunity/opportunity.presenter.js.map +1 -1
  75. package/dist/opportunity/opportunity.tools.d.ts.map +1 -1
  76. package/dist/opportunity/opportunity.tools.js +2 -1
  77. package/dist/opportunity/opportunity.tools.js.map +1 -1
  78. package/dist/opportunity/opportunity.utils.d.ts.map +1 -1
  79. package/dist/opportunity/opportunity.utils.js +29 -5
  80. package/dist/opportunity/opportunity.utils.js.map +1 -1
  81. package/dist/premise/premise.analyzer.d.ts.map +1 -1
  82. package/dist/premise/premise.analyzer.js +3 -2
  83. package/dist/premise/premise.analyzer.js.map +1 -1
  84. package/dist/premise/premise.decomposer.d.ts.map +1 -1
  85. package/dist/premise/premise.decomposer.js +12 -3
  86. package/dist/premise/premise.decomposer.js.map +1 -1
  87. package/dist/premise/premise.graph.d.ts.map +1 -1
  88. package/dist/premise/premise.graph.js +19 -9
  89. package/dist/premise/premise.graph.js.map +1 -1
  90. package/dist/premise/premise.indexer.d.ts.map +1 -1
  91. package/dist/premise/premise.indexer.js +2 -1
  92. package/dist/premise/premise.indexer.js.map +1 -1
  93. package/dist/premise/premise.tools.d.ts.map +1 -1
  94. package/dist/premise/premise.tools.js +8 -4
  95. package/dist/premise/premise.tools.js.map +1 -1
  96. package/dist/shared/agent/tool.factory.d.ts.map +1 -1
  97. package/dist/shared/agent/tool.factory.js +4 -2
  98. package/dist/shared/agent/tool.factory.js.map +1 -1
  99. package/dist/shared/agent/tool.registry.d.ts.map +1 -1
  100. package/dist/shared/agent/tool.registry.js +6 -4
  101. package/dist/shared/agent/tool.registry.js.map +1 -1
  102. package/dist/shared/interfaces/database.interface.d.ts +1 -1
  103. package/dist/shared/interfaces/database.interface.js.map +1 -1
  104. package/dist/shared/observability/log.d.ts +3 -2
  105. package/dist/shared/observability/log.d.ts.map +1 -1
  106. package/dist/shared/observability/log.js +72 -9
  107. package/dist/shared/observability/log.js.map +1 -1
  108. package/dist/shared/observability/protocol.logger.d.ts.map +1 -1
  109. package/dist/shared/observability/protocol.logger.js +5 -3
  110. package/dist/shared/observability/protocol.logger.js.map +1 -1
  111. package/package.json +5 -5
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { error, success } from '../shared/agent/tool.helpers.js';
3
3
  import { protocolLogger } from '../shared/observability/protocol.logger.js';
4
- const logger = protocolLogger('AgentTools');
4
+ const logger = protocolLogger('ChatTools:Agent');
5
5
  const AGENT_ACTIONS = [
6
6
  'manage:profile',
7
7
  'manage:intents',
@@ -1 +1 @@
1
- {"version":3,"file":"agent.tools.js","sourceRoot":"/","sources":["agent/agent.tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAE5E,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;AAE5C,MAAM,aAAa,GAAG;IACpB,gBAAgB;IAChB,gBAAgB;IAChB,iBAAiB;IACjB,iBAAiB;IACjB,sBAAsB;IACtB,qBAAqB;CACb,CAAC;AAEX,SAAS,oBAAoB,CAAC,MAAc;IAC1C,OAAO,mBAAmB,MAAM,oBAAoB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,OAAQ,aAAmC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAc;IAC1C,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC,aAAa,CAAC;AAC5B,CAAC;AAED,SAAS,uBAAuB,CAAC,OAA6B,EAAE,gBAAwB;IACtF,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QAC5D,OAAO,kDAAkD,CAAC;IAC5D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,sBAAsB,CAAyF,KAAQ;IAC9H,OAAO;QACL,GAAG,KAAK;QACR,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC9B,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,SAAS,oBAAoB,CAAC,WAAiC;IAC7D,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAsB,EAAE,IAAc;IACrE,MAAM,OAAO,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC;QAC/B,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,gGAAgG;YAChG,sDAAsD;QACxD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC;YAC/D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACnE,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;SACtG,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,KAAK,CACV,oFAAoF;oBACpF,8FAA8F,CAC/F,CAAC;YACJ,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,OAAO,KAAK,CAAC,yBAAyB,CAAC,CAAC;gBAC1C,CAAC;gBAED,MAAM,WAAW,GAAG,oBAAoB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBAC5D,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;oBACrC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;wBAC/B,OAAO,KAAK,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,CAAC;oBACjD,CAAC;gBACH,CAAC;gBAED,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;oBACtC,OAAO,EAAE,OAAO,CAAC,MAAM;oBACvB,IAAI;oBACJ,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,SAAS;oBACnD,IAAI,EAAE,UAAU;iBACjB,CAAC,CAAC;gBAEH,IAAI,CAAC;oBACH,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBAC3B,MAAM,OAAO,CAAC,eAAe,CAAC;4BAC5B,OAAO,EAAE,KAAK,CAAC,EAAE;4BACjB,MAAM,EAAE,OAAO,CAAC,MAAM;4BACtB,KAAK,EAAE,QAAQ;4BACf,OAAO,EAAE,WAAW;yBACrB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAAC,OAAO,UAAU,EAAE,CAAC;oBACpB,IAAI,CAAC;wBACH,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBACtC,CAAC;oBAAC,MAAM,CAAC;wBACP,2EAA2E;oBAC7E,CAAC;oBAED,MAAM,UAAU,CAAC;gBACnB,CAAC;gBAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAChE,OAAO,OAAO,CAAC;oBACb,OAAO,EAAE,UAAU,KAAK,CAAC,IAAI,4BAA4B;oBACzD,KAAK,EAAE,sBAAsB,CAAC,SAAS,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC5F,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBAClD,OAAO,KAAK,CAAC,6CAA6C,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,UAAU,CAAC;QAC5B,IAAI,EAAE,aAAa;QACnB,WAAW,EAAE,0DAA0D;QACvE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/D,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO;oBACpC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC;oBACxD,CAAC,CAAC,MAAM,CAAC;gBACX,OAAO,OAAO,CAAC;oBACb,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;oBACpE,KAAK,EAAE,cAAc,CAAC,MAAM;iBAC7B,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBAC/C,OAAO,KAAK,CAAC,0CAA0C,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,UAAU,CAAC;QAC7B,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,+CAA+C;QAC5D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;YAC/D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC7D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACnE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAC9E,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC/C,OAAO,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAClC,CAAC;gBAED,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,OAAO,KAAK,CAAC,kCAAkC,CAAC,CAAC;gBACnD,CAAC;gBAED,MAAM,OAAO,GAAmF,EAAE,CAAC;gBACnG,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;oBAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;wBACV,OAAO,KAAK,CAAC,wBAAwB,CAAC,CAAC;oBACzC,CAAC;oBACD,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;gBACtB,CAAC;gBACD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;oBACpC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;gBACzD,CAAC;gBACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;oBACjB,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;gBAChC,CAAC;gBAED,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtC,OAAO,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBAClD,CAAC;gBAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnE,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAClC,CAAC;gBAED,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACtE,OAAO,OAAO,CAAC;oBACb,OAAO,EAAE,gBAAgB;oBACzB,KAAK,EAAE,sBAAsB,CAAC,SAAS,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;iBAC9F,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBAChD,OAAO,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,UAAU,CAAC;QAC7B,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,6DAA6D;QAC1E,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;SAChE,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC/C,OAAO,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAClC,CAAC;gBACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC5B,OAAO,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBAClD,CAAC;gBAED,MAAM,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC1C,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,UAAU,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;YAChE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBAChD,OAAO,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,oBAAoB,GAAG,UAAU,CAAC;QACtC,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,kEAAkE;YAC7E,6HAA6H;QAC/H,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,uCAAuC,CAAC;YAC7E,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yJAAyJ,CAAC;YACvM,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;YAC9F,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;SACrF,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;YAED,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC7D,CAAC;YAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3B,OAAO,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;YAED,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;gBACrF,OAAO,KAAK,CAAC,4BAA4B,KAAK,CAAC,KAAK,eAAe,CAAC,CAAC;YACvE,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACrD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC/C,OAAO,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAClC,CAAC;gBAED,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC;oBAC/C,OAAO,EAAE,KAAK,CAAC,QAAQ;oBACvB,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,OAAO,EAAE,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE;oBACnG,OAAO;iBACR,CAAC,CAAC;gBAEH,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,CAAC,CAAC;YACjE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBACpD,OAAO,KAAK,CAAC,+CAA+C,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,qBAAqB,GAAG,UAAU,CAAC;QACvC,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,6CAA6C;QAC1D,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,wCAAwC,CAAC;YAC9E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;SAC1E,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpE,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC;YAC3B,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAClE,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC/C,OAAO,KAAK,CAAC,iBAAiB,CAAC,CAAC;gBAClC,CAAC;gBAED,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,aAAa,CAAC,CAAC;gBACrF,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,OAAO,KAAK,CAAC,sBAAsB,CAAC,CAAC;gBACvC,CAAC;gBAED,MAAM,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;gBACpD,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrD,OAAO,KAAK,CAAC,gDAAgD,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,OAAO;QACL,aAAa;QACb,UAAU;QACV,WAAW;QACX,WAAW;QACX,oBAAoB;QACpB,qBAAqB;KACb,CAAC;AACb,CAAC","sourcesContent":["import { z } from 'zod';\n\nimport type { DefineTool, ToolDeps } from '../shared/agent/tool.helpers.js';\nimport { error, success } from '../shared/agent/tool.helpers.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('AgentTools');\n\nconst AGENT_ACTIONS = [\n 'manage:profile',\n 'manage:intents',\n 'manage:networks',\n 'manage:contacts',\n 'manage:opportunities',\n 'manage:negotiations',\n] as const;\n\nfunction invalidActionMessage(action: string) {\n return `Invalid action: ${action}. Valid actions: ${AGENT_ACTIONS.join(', ')}`;\n}\n\nfunction isValidAction(action: string): action is (typeof AGENT_ACTIONS)[number] {\n return (AGENT_ACTIONS as readonly string[]).includes(action);\n}\n\nfunction requireAgentDatabase(deps: ToolDeps) {\n if (!deps.agentDatabase) {\n return null;\n }\n\n return deps.agentDatabase;\n}\n\nfunction ensureAgentScopedAccess(context: { agentId?: string }, requestedAgentId: string): string | null {\n if (context.agentId && context.agentId !== requestedAgentId) {\n return 'This agent can only manage its own registration.';\n }\n\n return null;\n}\n\nfunction sanitizeAgentForOutput<T extends { transports?: Array<{ channel: string; config: Record<string, unknown> }> }>(agent: T): T {\n return {\n ...agent,\n transports: agent.transports,\n };\n}\n\nfunction sanitizeAgentName(name: string): string | null {\n const cleanName = name.trim();\n return cleanName ? cleanName : null;\n}\n\nfunction normalizePermissions(permissions: string[] | undefined): string[] {\n return [...new Set((permissions ?? []).map((action) => action.trim()).filter(Boolean))];\n}\n\nexport function createAgentTools(defineTool: DefineTool, deps: ToolDeps) {\n const agentDb = requireAgentDatabase(deps);\n if (!agentDb) {\n return [];\n }\n\n const registerAgent = defineTool({\n name: 'register_agent',\n description:\n 'Register a new personal agent for the current user. Optionally configure initial permissions. ' +\n 'Use this when connecting an external agent to Index.',\n querySchema: z.object({\n name: z.string().min(1).describe('Display name for the agent.'),\n description: z.string().optional().describe('What the agent does.'),\n permissions: z.array(z.string()).optional().describe('Optional initial permission actions to grant.'),\n }),\n handler: async ({ context, query }) => {\n if (context.agentId) {\n return error(\n 'Agent registration must be done from a user session (web UI or personal API key), ' +\n 'not from within an existing agent context. To register a new agent, visit the Index web app.'\n );\n }\n\n try {\n const name = sanitizeAgentName(query.name);\n if (!name) {\n return error('Agent name is required.');\n }\n\n const permissions = normalizePermissions(query.permissions);\n for (const permission of permissions) {\n if (!isValidAction(permission)) {\n return error(invalidActionMessage(permission));\n }\n }\n\n const agent = await agentDb.createAgent({\n ownerId: context.userId,\n name,\n description: query.description?.trim() || undefined,\n type: 'personal',\n });\n\n try {\n if (permissions.length > 0) {\n await agentDb.grantPermission({\n agentId: agent.id,\n userId: context.userId,\n scope: 'global',\n actions: permissions,\n });\n }\n } catch (setupError) {\n try {\n await agentDb.deleteAgent(agent.id);\n } catch {\n // Best-effort cleanup to avoid leaving partially registered agents behind.\n }\n\n throw setupError;\n }\n\n const fullAgent = await agentDb.getAgentWithRelations(agent.id);\n return success({\n message: `Agent \"${agent.name}\" registered successfully.`,\n agent: sanitizeAgentForOutput(fullAgent ?? ({ ...agent, transports: [], permissions: [] })),\n });\n } catch (err) {\n logger.error('Failed to register agent', { err });\n return error('Failed to register agent. Please try again.');\n }\n },\n });\n\n const listAgents = defineTool({\n name: 'list_agents',\n description: 'List all agents the current user owns or has authorized.',\n querySchema: z.object({}),\n handler: async ({ context }) => {\n try {\n const agents = await agentDb.listAgentsForUser(context.userId);\n const filteredAgents = context.agentId\n ? agents.filter((agent) => agent.id === context.agentId)\n : agents;\n return success({\n agents: filteredAgents.map((agent) => sanitizeAgentForOutput(agent)),\n count: filteredAgents.length,\n });\n } catch (err) {\n logger.error('Failed to list agents', { err });\n return error('Failed to list agents. Please try again.');\n }\n },\n });\n\n const updateAgent = defineTool({\n name: 'update_agent',\n description: 'Update an agent name, description, or status.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to update.'),\n name: z.string().optional().describe('Updated display name.'),\n description: z.string().optional().describe('Updated description.'),\n status: z.enum(['active', 'inactive']).optional().describe('Updated status.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n if (agent.type === 'system') {\n return error('System agents cannot be modified');\n }\n\n const updates: { name?: string; description?: string | null; status?: 'active' | 'inactive' } = {};\n if (query.name !== undefined) {\n const name = query.name.trim();\n if (!name) {\n return error('Agent name is required');\n }\n updates.name = name;\n }\n if (query.description !== undefined) {\n updates.description = query.description.trim() || null;\n }\n if (query.status) {\n updates.status = query.status;\n }\n\n if (Object.keys(updates).length === 0) {\n return error('At least one field is required.');\n }\n\n const updated = await agentDb.updateAgent(query.agent_id, updates);\n if (!updated) {\n return error('Agent not found');\n }\n\n const fullAgent = await agentDb.getAgentWithRelations(query.agent_id);\n return success({\n message: 'Agent updated.',\n agent: sanitizeAgentForOutput(fullAgent ?? ({ ...updated, transports: [], permissions: [] })),\n });\n } catch (err) {\n logger.error('Failed to update agent', { err });\n return error('Failed to update agent. Please try again.');\n }\n },\n });\n\n const deleteAgent = defineTool({\n name: 'delete_agent',\n description: 'Soft-delete a personal agent and deactivate its transports.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to delete.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n if (agent.type === 'system') {\n return error('System agents cannot be deleted');\n }\n\n await agentDb.deleteAgent(query.agent_id);\n return success({ message: `Agent \"${agent.name}\" deleted.` });\n } catch (err) {\n logger.error('Failed to delete agent', { err });\n return error('Failed to delete agent. Please try again.');\n }\n },\n });\n\n const grantAgentPermission = defineTool({\n name: 'grant_agent_permission',\n description: 'Grant one or more permissions to an agent for the current user. ' +\n 'Valid actions: manage:profile, manage:intents, manage:networks, manage:contacts, manage:opportunities, manage:negotiations.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to grant permissions to.'),\n actions: z.array(z.string()).min(1).describe('Permission actions to grant. Valid values: manage:profile, manage:intents, manage:networks, manage:contacts, manage:opportunities, manage:negotiations.'),\n scope: z.enum(['global', 'node', 'network']).optional().describe('Optional permission scope.'),\n scope_id: z.string().optional().describe('Scope target ID for node/network scopes.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n const actions = normalizePermissions(query.actions);\n if (actions.length === 0) {\n return error('At least one non-empty action is required.');\n }\n\n for (const action of actions) {\n if (!isValidAction(action)) {\n return error(invalidActionMessage(action));\n }\n }\n\n if ((query.scope === 'network' || query.scope === 'node') && !query.scope_id?.trim()) {\n return error(`scope_id is required for ${query.scope} permissions.`);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n const permission = await agentDb.grantPermission({\n agentId: query.agent_id,\n userId: context.userId,\n scope: query.scope,\n scopeId: query.scope === 'global' || query.scope === undefined ? undefined : query.scope_id?.trim(),\n actions,\n });\n\n return success({ message: 'Permission granted.', permission });\n } catch (err) {\n logger.error('Failed to grant permission', { err });\n return error('Failed to grant permission. Please try again.');\n }\n },\n });\n\n const revokeAgentPermission = defineTool({\n name: 'revoke_agent_permission',\n description: 'Revoke a specific permission from an agent.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID that owns the permission.'),\n permission_id: z.string().min(1).describe('The permission ID to revoke.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgentWithRelations(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n const permission = agent.permissions.find((item) => item.id === query.permission_id);\n if (!permission) {\n return error('Permission not found');\n }\n\n await agentDb.revokePermission(query.permission_id);\n return success({ message: 'Permission revoked.' });\n } catch (err) {\n logger.error('Failed to revoke permission', { err });\n return error('Failed to revoke permission. Please try again.');\n }\n },\n });\n\n return [\n registerAgent,\n listAgents,\n updateAgent,\n deleteAgent,\n grantAgentPermission,\n revokeAgentPermission,\n ] as const;\n}\n"]}
1
+ {"version":3,"file":"agent.tools.js","sourceRoot":"/","sources":["agent/agent.tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\n\nimport type { DefineTool, ToolDeps } from '../shared/agent/tool.helpers.js';\nimport { error, success } from '../shared/agent/tool.helpers.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('ChatTools:Agent');\n\nconst AGENT_ACTIONS = [\n 'manage:profile',\n 'manage:intents',\n 'manage:networks',\n 'manage:contacts',\n 'manage:opportunities',\n 'manage:negotiations',\n] as const;\n\nfunction invalidActionMessage(action: string) {\n return `Invalid action: ${action}. Valid actions: ${AGENT_ACTIONS.join(', ')}`;\n}\n\nfunction isValidAction(action: string): action is (typeof AGENT_ACTIONS)[number] {\n return (AGENT_ACTIONS as readonly string[]).includes(action);\n}\n\nfunction requireAgentDatabase(deps: ToolDeps) {\n if (!deps.agentDatabase) {\n return null;\n }\n\n return deps.agentDatabase;\n}\n\nfunction ensureAgentScopedAccess(context: { agentId?: string }, requestedAgentId: string): string | null {\n if (context.agentId && context.agentId !== requestedAgentId) {\n return 'This agent can only manage its own registration.';\n }\n\n return null;\n}\n\nfunction sanitizeAgentForOutput<T extends { transports?: Array<{ channel: string; config: Record<string, unknown> }> }>(agent: T): T {\n return {\n ...agent,\n transports: agent.transports,\n };\n}\n\nfunction sanitizeAgentName(name: string): string | null {\n const cleanName = name.trim();\n return cleanName ? cleanName : null;\n}\n\nfunction normalizePermissions(permissions: string[] | undefined): string[] {\n return [...new Set((permissions ?? []).map((action) => action.trim()).filter(Boolean))];\n}\n\nexport function createAgentTools(defineTool: DefineTool, deps: ToolDeps) {\n const agentDb = requireAgentDatabase(deps);\n if (!agentDb) {\n return [];\n }\n\n const registerAgent = defineTool({\n name: 'register_agent',\n description:\n 'Register a new personal agent for the current user. Optionally configure initial permissions. ' +\n 'Use this when connecting an external agent to Index.',\n querySchema: z.object({\n name: z.string().min(1).describe('Display name for the agent.'),\n description: z.string().optional().describe('What the agent does.'),\n permissions: z.array(z.string()).optional().describe('Optional initial permission actions to grant.'),\n }),\n handler: async ({ context, query }) => {\n if (context.agentId) {\n return error(\n 'Agent registration must be done from a user session (web UI or personal API key), ' +\n 'not from within an existing agent context. To register a new agent, visit the Index web app.'\n );\n }\n\n try {\n const name = sanitizeAgentName(query.name);\n if (!name) {\n return error('Agent name is required.');\n }\n\n const permissions = normalizePermissions(query.permissions);\n for (const permission of permissions) {\n if (!isValidAction(permission)) {\n return error(invalidActionMessage(permission));\n }\n }\n\n const agent = await agentDb.createAgent({\n ownerId: context.userId,\n name,\n description: query.description?.trim() || undefined,\n type: 'personal',\n });\n\n try {\n if (permissions.length > 0) {\n await agentDb.grantPermission({\n agentId: agent.id,\n userId: context.userId,\n scope: 'global',\n actions: permissions,\n });\n }\n } catch (setupError) {\n try {\n await agentDb.deleteAgent(agent.id);\n } catch {\n // Best-effort cleanup to avoid leaving partially registered agents behind.\n }\n\n throw setupError;\n }\n\n const fullAgent = await agentDb.getAgentWithRelations(agent.id);\n return success({\n message: `Agent \"${agent.name}\" registered successfully.`,\n agent: sanitizeAgentForOutput(fullAgent ?? ({ ...agent, transports: [], permissions: [] })),\n });\n } catch (err) {\n logger.error('Failed to register agent', { err });\n return error('Failed to register agent. Please try again.');\n }\n },\n });\n\n const listAgents = defineTool({\n name: 'list_agents',\n description: 'List all agents the current user owns or has authorized.',\n querySchema: z.object({}),\n handler: async ({ context }) => {\n try {\n const agents = await agentDb.listAgentsForUser(context.userId);\n const filteredAgents = context.agentId\n ? agents.filter((agent) => agent.id === context.agentId)\n : agents;\n return success({\n agents: filteredAgents.map((agent) => sanitizeAgentForOutput(agent)),\n count: filteredAgents.length,\n });\n } catch (err) {\n logger.error('Failed to list agents', { err });\n return error('Failed to list agents. Please try again.');\n }\n },\n });\n\n const updateAgent = defineTool({\n name: 'update_agent',\n description: 'Update an agent name, description, or status.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to update.'),\n name: z.string().optional().describe('Updated display name.'),\n description: z.string().optional().describe('Updated description.'),\n status: z.enum(['active', 'inactive']).optional().describe('Updated status.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n if (agent.type === 'system') {\n return error('System agents cannot be modified');\n }\n\n const updates: { name?: string; description?: string | null; status?: 'active' | 'inactive' } = {};\n if (query.name !== undefined) {\n const name = query.name.trim();\n if (!name) {\n return error('Agent name is required');\n }\n updates.name = name;\n }\n if (query.description !== undefined) {\n updates.description = query.description.trim() || null;\n }\n if (query.status) {\n updates.status = query.status;\n }\n\n if (Object.keys(updates).length === 0) {\n return error('At least one field is required.');\n }\n\n const updated = await agentDb.updateAgent(query.agent_id, updates);\n if (!updated) {\n return error('Agent not found');\n }\n\n const fullAgent = await agentDb.getAgentWithRelations(query.agent_id);\n return success({\n message: 'Agent updated.',\n agent: sanitizeAgentForOutput(fullAgent ?? ({ ...updated, transports: [], permissions: [] })),\n });\n } catch (err) {\n logger.error('Failed to update agent', { err });\n return error('Failed to update agent. Please try again.');\n }\n },\n });\n\n const deleteAgent = defineTool({\n name: 'delete_agent',\n description: 'Soft-delete a personal agent and deactivate its transports.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to delete.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n if (agent.type === 'system') {\n return error('System agents cannot be deleted');\n }\n\n await agentDb.deleteAgent(query.agent_id);\n return success({ message: `Agent \"${agent.name}\" deleted.` });\n } catch (err) {\n logger.error('Failed to delete agent', { err });\n return error('Failed to delete agent. Please try again.');\n }\n },\n });\n\n const grantAgentPermission = defineTool({\n name: 'grant_agent_permission',\n description: 'Grant one or more permissions to an agent for the current user. ' +\n 'Valid actions: manage:profile, manage:intents, manage:networks, manage:contacts, manage:opportunities, manage:negotiations.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID to grant permissions to.'),\n actions: z.array(z.string()).min(1).describe('Permission actions to grant. Valid values: manage:profile, manage:intents, manage:networks, manage:contacts, manage:opportunities, manage:negotiations.'),\n scope: z.enum(['global', 'node', 'network']).optional().describe('Optional permission scope.'),\n scope_id: z.string().optional().describe('Scope target ID for node/network scopes.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n const actions = normalizePermissions(query.actions);\n if (actions.length === 0) {\n return error('At least one non-empty action is required.');\n }\n\n for (const action of actions) {\n if (!isValidAction(action)) {\n return error(invalidActionMessage(action));\n }\n }\n\n if ((query.scope === 'network' || query.scope === 'node') && !query.scope_id?.trim()) {\n return error(`scope_id is required for ${query.scope} permissions.`);\n }\n\n try {\n const agent = await agentDb.getAgent(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n const permission = await agentDb.grantPermission({\n agentId: query.agent_id,\n userId: context.userId,\n scope: query.scope,\n scopeId: query.scope === 'global' || query.scope === undefined ? undefined : query.scope_id?.trim(),\n actions,\n });\n\n return success({ message: 'Permission granted.', permission });\n } catch (err) {\n logger.error('Failed to grant permission', { err });\n return error('Failed to grant permission. Please try again.');\n }\n },\n });\n\n const revokeAgentPermission = defineTool({\n name: 'revoke_agent_permission',\n description: 'Revoke a specific permission from an agent.',\n querySchema: z.object({\n agent_id: z.string().min(1).describe('The agent ID that owns the permission.'),\n permission_id: z.string().min(1).describe('The permission ID to revoke.'),\n }),\n handler: async ({ context, query }) => {\n const scopeError = ensureAgentScopedAccess(context, query.agent_id);\n if (scopeError) {\n return error(scopeError);\n }\n\n try {\n const agent = await agentDb.getAgentWithRelations(query.agent_id);\n if (!agent || agent.ownerId !== context.userId) {\n return error('Agent not found');\n }\n\n const permission = agent.permissions.find((item) => item.id === query.permission_id);\n if (!permission) {\n return error('Permission not found');\n }\n\n await agentDb.revokePermission(query.permission_id);\n return success({ message: 'Permission revoked.' });\n } catch (err) {\n logger.error('Failed to revoke permission', { err });\n return error('Failed to revoke permission. Please try again.');\n }\n },\n });\n\n return [\n registerAgent,\n listAgents,\n updateAgent,\n deleteAgent,\n grantAgentPermission,\n revokeAgentPermission,\n ] as const;\n}\n"]}
@@ -49,7 +49,7 @@ export class ChatInterruptClassifier {
49
49
  return "steer";
50
50
  }
51
51
  catch (error) {
52
- logger.warn("[ChatInterruptClassifier.classify] Classification failed, defaulting to steer", {
52
+ logger.warn("Classification failed, defaulting to steer", {
53
53
  error: error instanceof Error ? error.message : String(error),
54
54
  });
55
55
  return "steer";
@@ -1 +1 @@
1
- {"version":3,"file":"chat.interrupt.classifier.js","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAEvD,MAAM,aAAa,GAAG;;;;;;oCAMc,CAAC;AAYrC;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IAGlC;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,QAAQ,CAAC,KAA6B;QAC1C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CACd,2BAA2B,UAAU,IAAI,MAAM,0BAA0B,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAC/G;aACF,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAEjE,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO,OAAO,CAAC;YAC7C,yDAAyD;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,+EAA+E,EAAE;gBAC3F,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AAvBO;IADL,KAAK,EAAE;;;;uDAuBP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatInterruptClassifier\");\n\nconst SYSTEM_PROMPT = `You decide whether a new user message sent during an active AI process should STEER or QUEUE.\n\nRules:\n- Reply with ONLY one word: steer or queue (lowercase).\n- STEER: the message redirects, corrects, stops, contradicts, or changes what the AI is doing. Keywords: \"wait\", \"stop\", \"actually\", \"ignore that\", \"instead\", \"no\", \"cancel\".\n- QUEUE: the message adds context, asks a follow-up, or complements what the AI is doing. Keywords: \"also\", \"and\", \"when done\", \"additionally\", \"plus\".\n- When ambiguous, default to steer.`;\n\nexport interface ClassifyInterruptInput {\n /** The new user message sent while the agent is running. */\n message: string;\n /**\n * Current agent activity summary derived from the last few SSE trace event names\n * (e.g. \"tool_start: discover_opportunities, graph_start: opportunity\").\n */\n agentState: string;\n}\n\n/**\n * Binary classifier that decides whether a mid-stream user message should steer\n * (interrupt the current run) or queue (buffer until the run completes).\n * Uses a low-temperature, minimal-token model for sub-1 s latency.\n */\nexport class ChatInterruptClassifier {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"interruptClassifier\");\n }\n\n /**\n * Classify a mid-stream interrupt as steer or queue.\n *\n * @param input - The new message and current agent state context\n * @returns \"steer\" to interrupt the current run; \"queue\" to buffer\n */\n @Timed()\n async classify(input: ClassifyInterruptInput): Promise<\"steer\" | \"queue\"> {\n const { message, agentState } = input;\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(\n `Current agent activity: ${agentState || \"idle\"}\\n\\nNew user message: \"${message.slice(0, 500)}\"\\n\\nDecision:`,\n ),\n ]);\n\n const text = String(response.content ?? \"\").trim().toLowerCase();\n\n if (text.startsWith(\"queue\")) return \"queue\";\n // Default to steer on any ambiguity or unexpected output\n return \"steer\";\n } catch (error) {\n logger.warn(\"[ChatInterruptClassifier.classify] Classification failed, defaulting to steer\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"steer\";\n }\n }\n}\n"]}
1
+ {"version":3,"file":"chat.interrupt.classifier.js","sourceRoot":"/","sources":["chat/chat.interrupt.classifier.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AAEvD,MAAM,aAAa,GAAG;;;;;;oCAMc,CAAC;AAYrC;;;;GAIG;AACH,MAAM,OAAO,uBAAuB;IAGlC;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC;IAED;;;;;OAKG;IAEG,AAAN,KAAK,CAAC,QAAQ,CAAC,KAA6B;QAC1C,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;QAEtC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CACd,2BAA2B,UAAU,IAAI,MAAM,0BAA0B,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAC/G;aACF,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAEjE,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBAAE,OAAO,OAAO,CAAC;YAC7C,yDAAyD;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE;gBACxD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AAvBO;IADL,KAAK,EAAE;;;;uDAuBP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatInterruptClassifier\");\n\nconst SYSTEM_PROMPT = `You decide whether a new user message sent during an active AI process should STEER or QUEUE.\n\nRules:\n- Reply with ONLY one word: steer or queue (lowercase).\n- STEER: the message redirects, corrects, stops, contradicts, or changes what the AI is doing. Keywords: \"wait\", \"stop\", \"actually\", \"ignore that\", \"instead\", \"no\", \"cancel\".\n- QUEUE: the message adds context, asks a follow-up, or complements what the AI is doing. Keywords: \"also\", \"and\", \"when done\", \"additionally\", \"plus\".\n- When ambiguous, default to steer.`;\n\nexport interface ClassifyInterruptInput {\n /** The new user message sent while the agent is running. */\n message: string;\n /**\n * Current agent activity summary derived from the last few SSE trace event names\n * (e.g. \"tool_start: discover_opportunities, graph_start: opportunity\").\n */\n agentState: string;\n}\n\n/**\n * Binary classifier that decides whether a mid-stream user message should steer\n * (interrupt the current run) or queue (buffer until the run completes).\n * Uses a low-temperature, minimal-token model for sub-1 s latency.\n */\nexport class ChatInterruptClassifier {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"interruptClassifier\");\n }\n\n /**\n * Classify a mid-stream interrupt as steer or queue.\n *\n * @param input - The new message and current agent state context\n * @returns \"steer\" to interrupt the current run; \"queue\" to buffer\n */\n @Timed()\n async classify(input: ClassifyInterruptInput): Promise<\"steer\" | \"queue\"> {\n const { message, agentState } = input;\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(\n `Current agent activity: ${agentState || \"idle\"}\\n\\nNew user message: \"${message.slice(0, 500)}\"\\n\\nDecision:`,\n ),\n ]);\n\n const text = String(response.content ?? \"\").trim().toLowerCase();\n\n if (text.startsWith(\"queue\")) return \"queue\";\n // Default to steer on any ambiguity or unexpected output\n return \"steer\";\n } catch (error) {\n logger.warn(\"Classification failed, defaulting to steer\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"steer\";\n }\n }\n}\n"]}
@@ -67,7 +67,7 @@ export class SuggestionGenerator {
67
67
  ]);
68
68
  const parsed = suggestionsSchema.safeParse(result);
69
69
  if (!parsed.success) {
70
- logger.warn("[SuggestionGenerator] Parse failed", { error: parsed.error.message });
70
+ logger.warn("Parse failed", { error: parsed.error.message });
71
71
  return [];
72
72
  }
73
73
  const out = parsed.data.suggestions.map((s) => ({
@@ -76,11 +76,11 @@ export class SuggestionGenerator {
76
76
  ...(s.type === "direct" && s.followupText != null && { followupText: s.followupText }),
77
77
  ...(s.type === "prompt" && s.prefill != null && { prefill: s.prefill }),
78
78
  }));
79
- logger.verbose("[SuggestionGenerator] Generated", { count: out.length });
79
+ logger.verbose("Generated", { count: out.length });
80
80
  return out;
81
81
  }
82
82
  catch (error) {
83
- logger.warn("[SuggestionGenerator] Failed", {
83
+ logger.warn("Failed", {
84
84
  error: error instanceof Error ? error.message : String(error),
85
85
  });
86
86
  return [];
@@ -1 +1 @@
1
- {"version":3,"file":"chat.suggester.js","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":"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","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\nimport type { ChatSuggestion } from \"./chat-streaming.types.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"SuggestionGenerator\");\n\nconst suggestionItemSchema = z.object({\n label: z.string().describe(\"Short label for the chip (2-5 words)\"),\n type: z.enum([\"direct\", \"prompt\"]).describe(\"direct = auto-submit message; prompt = prefill input\"),\n followupText: z.string().nullable().describe(\"For type=direct: full message to send when clicked; null for prompt type\"),\n prefill: z.string().nullable().describe(\"For type=prompt: text to prefill the input; null for direct type\"),\n});\n\nconst suggestionsSchema = z.object({\n suggestions: z\n .array(suggestionItemSchema)\n .min(1)\n .max(6)\n .describe(\"3-5 follow-up suggestions based on the conversation\"),\n});\n\nconst SYSTEM_PROMPT = `You generate follow-up suggestions for a chat user based on their conversation.\n\nRules:\n- Return 3-5 suggestions. Mix of \"direct\" (one-click send) and \"prompt\" (prefill for user to edit).\n- Labels must be short: 2-5 words (e.g. \"Find collaborators\", \"Add more details\").\n- For type=direct: provide followupText as the exact message to send (complete sentence).\n- For type=prompt: provide prefill as the start of a sentence the user can complete (e.g. \"I need help with \").\n- Suggestions must be relevant to the last exchange and natural next steps.\n- Do not repeat what the user or assistant just said; suggest logical follow-ups.\n- Voice: Calm, direct; no hype or networking clichés. Prefer words like opportunity, overlap, signal, pattern, relevant. Avoid: search, leverage, networking, match, optimize, scale.`;\n\nexport interface SuggestionGeneratorInput {\n /** Last few messages (user and assistant) to derive context */\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n /** Optional index/community context to tailor suggestions */\n indexContext?: string;\n}\n\n/**\n * Lightweight generator for context-aware chat follow-up suggestions.\n * Uses a fast model and structured output to return 3-5 suggestions per call.\n */\nexport class SuggestionGenerator {\n private model: ReturnType<typeof createStructuredModel>;\n\n constructor() {\n this.model = createStructuredModel(\"suggestionGenerator\", suggestionsSchema, { name: \"chat_suggestions\" });\n }\n\n /**\n * Generate follow-up suggestions from the last exchange.\n * Returns empty array on failure (graceful degradation).\n */\n @Timed()\n async generate(input: SuggestionGeneratorInput): Promise<ChatSuggestion[]> {\n const { messages, indexContext } = input;\n if (messages.length === 0) return [];\n\n const excerpt = messages\n .slice(-6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 300)}`)\n .join(\"\\n\\n\");\n\n const userContent = indexContext\n ? `Conversation (community context: ${indexContext}):\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`\n : `Conversation:\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`;\n\n try {\n const result = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(userContent),\n ]);\n const parsed = suggestionsSchema.safeParse(result);\n if (!parsed.success) {\n logger.warn(\"[SuggestionGenerator] Parse failed\", { error: parsed.error.message });\n return [];\n }\n const out: ChatSuggestion[] = parsed.data.suggestions.map((s) => ({\n label: s.label,\n type: s.type,\n ...(s.type === \"direct\" && s.followupText != null && { followupText: s.followupText }),\n ...(s.type === \"prompt\" && s.prefill != null && { prefill: s.prefill }),\n }));\n logger.verbose(\"[SuggestionGenerator] Generated\", { count: out.length });\n return out;\n } catch (error) {\n logger.warn(\"[SuggestionGenerator] Failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n}\n"]}
1
+ {"version":3,"file":"chat.suggester.js","sourceRoot":"/","sources":["chat/chat.suggester.ts"],"names":[],"mappings":"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","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\nimport { z } from \"zod\";\nimport type { ChatSuggestion } from \"./chat-streaming.types.js\";\nimport { protocolLogger } from \"../shared/observability/protocol.logger.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\nimport { createStructuredModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = protocolLogger(\"SuggestionGenerator\");\n\nconst suggestionItemSchema = z.object({\n label: z.string().describe(\"Short label for the chip (2-5 words)\"),\n type: z.enum([\"direct\", \"prompt\"]).describe(\"direct = auto-submit message; prompt = prefill input\"),\n followupText: z.string().nullable().describe(\"For type=direct: full message to send when clicked; null for prompt type\"),\n prefill: z.string().nullable().describe(\"For type=prompt: text to prefill the input; null for direct type\"),\n});\n\nconst suggestionsSchema = z.object({\n suggestions: z\n .array(suggestionItemSchema)\n .min(1)\n .max(6)\n .describe(\"3-5 follow-up suggestions based on the conversation\"),\n});\n\nconst SYSTEM_PROMPT = `You generate follow-up suggestions for a chat user based on their conversation.\n\nRules:\n- Return 3-5 suggestions. Mix of \"direct\" (one-click send) and \"prompt\" (prefill for user to edit).\n- Labels must be short: 2-5 words (e.g. \"Find collaborators\", \"Add more details\").\n- For type=direct: provide followupText as the exact message to send (complete sentence).\n- For type=prompt: provide prefill as the start of a sentence the user can complete (e.g. \"I need help with \").\n- Suggestions must be relevant to the last exchange and natural next steps.\n- Do not repeat what the user or assistant just said; suggest logical follow-ups.\n- Voice: Calm, direct; no hype or networking clichés. Prefer words like opportunity, overlap, signal, pattern, relevant. Avoid: search, leverage, networking, match, optimize, scale.`;\n\nexport interface SuggestionGeneratorInput {\n /** Last few messages (user and assistant) to derive context */\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n /** Optional index/community context to tailor suggestions */\n indexContext?: string;\n}\n\n/**\n * Lightweight generator for context-aware chat follow-up suggestions.\n * Uses a fast model and structured output to return 3-5 suggestions per call.\n */\nexport class SuggestionGenerator {\n private model: ReturnType<typeof createStructuredModel>;\n\n constructor() {\n this.model = createStructuredModel(\"suggestionGenerator\", suggestionsSchema, { name: \"chat_suggestions\" });\n }\n\n /**\n * Generate follow-up suggestions from the last exchange.\n * Returns empty array on failure (graceful degradation).\n */\n @Timed()\n async generate(input: SuggestionGeneratorInput): Promise<ChatSuggestion[]> {\n const { messages, indexContext } = input;\n if (messages.length === 0) return [];\n\n const excerpt = messages\n .slice(-6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 300)}`)\n .join(\"\\n\\n\");\n\n const userContent = indexContext\n ? `Conversation (community context: ${indexContext}):\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`\n : `Conversation:\\n\\n${excerpt}\\n\\nGenerate 3-5 follow-up suggestions.`;\n\n try {\n const result = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(userContent),\n ]);\n const parsed = suggestionsSchema.safeParse(result);\n if (!parsed.success) {\n logger.warn(\"Parse failed\", { error: parsed.error.message });\n return [];\n }\n const out: ChatSuggestion[] = parsed.data.suggestions.map((s) => ({\n label: s.label,\n type: s.type,\n ...(s.type === \"direct\" && s.followupText != null && { followupText: s.followupText }),\n ...(s.type === \"prompt\" && s.prefill != null && { prefill: s.prefill }),\n }));\n logger.verbose(\"Generated\", { count: out.length });\n return out;\n } catch (error) {\n logger.warn(\"Failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return [];\n }\n }\n}\n"]}
@@ -47,11 +47,11 @@ export class ChatTitleGenerator {
47
47
  ]);
48
48
  const text = typeof response.content === "string" ? response.content : String(response.content ?? "").trim();
49
49
  const title = text.slice(0, 80).trim() || "New chat";
50
- logger.verbose("[ChatTitleGenerator.invoke] Title generated", { titleLength: title.length });
50
+ logger.verbose("Title generated", { titleLength: title.length });
51
51
  return title;
52
52
  }
53
53
  catch (error) {
54
- logger.warn("[ChatTitleGenerator.invoke] Failed to generate title", {
54
+ logger.warn("Failed to generate title", {
55
55
  error: error instanceof Error ? error.message : String(error),
56
56
  });
57
57
  return "New chat";
@@ -1 +1 @@
1
- {"version":3,"file":"chat.title.generator.js","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAElD,MAAM,aAAa,GAAG;;;;;;+DAMyC,CAAC;AAMhE;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAG7B;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAE7C,MAAM,OAAO,GAAG,QAAQ;aACrB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aACrF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CAAC,kBAAkB,OAAO,sBAAsB,CAAC;aAClE,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7G,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC;YACrD,MAAM,CAAC,OAAO,CAAC,6CAA6C,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7F,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;gBAClE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AA1BO;IADL,KAAK,EAAE;;;;gDA0BP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatTitleGenerator\");\n\nconst SYSTEM_PROMPT = `You suggest a very short title for a chat conversation.\n\nRules:\n- Reply with ONLY the title, no quotes or punctuation.\n- Maximum 6 words.\n- If the conversation is just greetings (hi, hello, hey, thanks) or has no clear topic yet, reply with exactly: New chat\n- Otherwise summarize the main topic or intent in a few words.`;\n\nexport interface TitleGeneratorInput {\n messages: Array<{ role: string; content: string }>;\n}\n\n/**\n * Generates a short, descriptive title for a chat session using the first exchange.\n * Only meaningful when there is at least one user message and one assistant message.\n */\nexport class ChatTitleGenerator {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"chatTitleGenerator\");\n }\n\n /**\n * Suggests a title from the conversation excerpt.\n * Call only when there is at least one user and one assistant message.\n */\n @Timed()\n async invoke(input: TitleGeneratorInput): Promise<string> {\n const { messages } = input;\n if (messages.length === 0) return \"New chat\";\n\n const excerpt = messages\n .slice(0, 6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 200)}`)\n .join(\"\\n\");\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(`Conversation:\\n${excerpt}\\n\\nSuggested title:`),\n ]);\n\n const text = typeof response.content === \"string\" ? response.content : String(response.content ?? \"\").trim();\n const title = text.slice(0, 80).trim() || \"New chat\";\n logger.verbose(\"[ChatTitleGenerator.invoke] Title generated\", { titleLength: title.length });\n return title;\n } catch (error) {\n logger.warn(\"[ChatTitleGenerator.invoke] Failed to generate title\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"New chat\";\n }\n }\n}\n"]}
1
+ {"version":3,"file":"chat.title.generator.js","sourceRoot":"/","sources":["chat/chat.title.generator.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAE/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAElD,MAAM,aAAa,GAAG;;;;;;+DAMyC,CAAC;AAMhE;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAG7B;QACE,IAAI,CAAC,KAAK,GAAG,oBAAoB,CAAC,oBAAoB,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IAEG,AAAN,KAAK,CAAC,MAAM,CAAC,KAA0B;QACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;QAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAE7C,MAAM,OAAO,GAAG,QAAQ;aACrB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;aACrF,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,KAAK,EAAE;gBACvD,IAAI,aAAa,CAAC,aAAa,CAAC;gBAChC,IAAI,YAAY,CAAC,kBAAkB,OAAO,sBAAsB,CAAC;aAClE,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7G,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC;YACrD,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;YACjE,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE;gBACtC,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AA1BO;IADL,KAAK,EAAE;;;;gDA0BP","sourcesContent":["import { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\n\nimport { log } from \"../shared/observability/log.js\";\nimport { Timed } from \"../shared/observability/performance.js\";\n\nimport { createResilientModel } from \"../shared/agent/model.config.js\";\nimport { invokeWithAbortSignal } from \"../shared/agent/model-signal.js\";\n\nconst logger = log.lib.from(\"ChatTitleGenerator\");\n\nconst SYSTEM_PROMPT = `You suggest a very short title for a chat conversation.\n\nRules:\n- Reply with ONLY the title, no quotes or punctuation.\n- Maximum 6 words.\n- If the conversation is just greetings (hi, hello, hey, thanks) or has no clear topic yet, reply with exactly: New chat\n- Otherwise summarize the main topic or intent in a few words.`;\n\nexport interface TitleGeneratorInput {\n messages: Array<{ role: string; content: string }>;\n}\n\n/**\n * Generates a short, descriptive title for a chat session using the first exchange.\n * Only meaningful when there is at least one user message and one assistant message.\n */\nexport class ChatTitleGenerator {\n private model: ReturnType<typeof createResilientModel>;\n\n constructor() {\n this.model = createResilientModel(\"chatTitleGenerator\");\n }\n\n /**\n * Suggests a title from the conversation excerpt.\n * Call only when there is at least one user and one assistant message.\n */\n @Timed()\n async invoke(input: TitleGeneratorInput): Promise<string> {\n const { messages } = input;\n if (messages.length === 0) return \"New chat\";\n\n const excerpt = messages\n .slice(0, 6)\n .map((m) => `${m.role === \"user\" ? \"User\" : \"Assistant\"}: ${m.content.slice(0, 200)}`)\n .join(\"\\n\");\n\n try {\n const response = await invokeWithAbortSignal(this.model, [\n new SystemMessage(SYSTEM_PROMPT),\n new HumanMessage(`Conversation:\\n${excerpt}\\n\\nSuggested title:`),\n ]);\n\n const text = typeof response.content === \"string\" ? response.content : String(response.content ?? \"\").trim();\n const title = text.slice(0, 80).trim() || \"New chat\";\n logger.verbose(\"Title generated\", { titleLength: title.length });\n return title;\n } catch (error) {\n logger.warn(\"Failed to generate title\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"New chat\";\n }\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { success, error } from '../shared/agent/tool.helpers.js';
3
3
  import { protocolLogger } from '../shared/observability/protocol.logger.js';
4
- const logger = protocolLogger('ContactTools');
4
+ const logger = protocolLogger('ChatTools:Contact');
5
5
  /**
6
6
  * Creates contact management tools for the chat agent.
7
7
  * Enables importing, listing, and managing the user's network.
@@ -1 +1 @@
1
- {"version":3,"file":"contact.tools.js","sourceRoot":"/","sources":["contact/contact.tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport type { DefineTool, ToolDeps } from '../shared/agent/tool.helpers.js';\nimport { success, error } from '../shared/agent/tool.helpers.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('ContactTools');\n\n/**\n * Creates contact management tools for the chat agent.\n * Enables importing, listing, and managing the user's network.\n */\nexport function createContactTools(defineTool: DefineTool, deps: ToolDeps) {\n const { contactService } = deps;\n // Contact import / manual-add create ghost users. These are gated behind the\n // CONTACTS_ENABLED flag (injected as deps.contactsEnabled). Read/remove/search\n // tools below are always available so existing contacts stay manageable.\n const contactsEnabled = deps.contactsEnabled === true;\n\n // Only register when enabled: in the registry path defineTool registers as a\n // side effect, so the call itself must be gated, not just the returned array.\n const import_contacts = contactsEnabled ? defineTool({\n name: 'import_contacts',\n description:\n \"Bulk-imports contacts into the authenticated user's personal network (personal network). Contacts become members of the user's \" +\n \"personal network with 'contact' permission, making them available for opportunity discovery.\\n\\n\" +\n \"**What happens:** Each contact is matched by email. If the email belongs to an existing user, they're linked directly. \" +\n \"If not, a 'ghost user' is created — a placeholder account enriched with public profile data (from LinkedIn, GitHub, etc.) \" +\n \"that participates in opportunity matching even before the person joins the platform.\\n\\n\" +\n \"**When to use:** When the user provides a list of contacts to add (from CSV, manual input, or any source other than Gmail). \" +\n \"For Gmail specifically, use import_gmail_contacts instead.\\n\\n\" +\n \"**Returns:** Import statistics: imported (total processed), skipped (invalid), newContacts (ghost users created), \" +\n \"existingContacts (already in network). Use list_contacts to see all contacts after import.\",\n querySchema: z.object({\n contacts: z.array(z.object({\n name: z.string().describe('Full name of the contact (e.g. \"Jane Smith\")'),\n email: z.string().describe('Email address — used as the unique identifier for matching existing users'),\n })).describe('Array of contact objects to import. Each must have name and email. Duplicates (by email) are skipped.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const result = await contactService.importContacts(\n context.userId,\n query.contacts\n );\n return success({\n message: `Imported ${result.imported} contacts to your network.`,\n imported: result.imported,\n skipped: result.skipped,\n newContacts: result.newContacts,\n existingContacts: result.existingContacts,\n });\n } catch (err) {\n logger.error('Failed to import contacts', { err });\n return error('Failed to import contacts. Please try again.');\n }\n },\n }) : null;\n\n const list_contacts = defineTool({\n name: 'list_contacts',\n description:\n \"Lists all contacts in the authenticated user's personal network. Contacts are people the user has added \" +\n \"(via import_contacts, add_contact, or import_gmail_contacts) stored as members of their personal network.\\n\\n\" +\n \"**When to use:** To see who's in the user's network, find a contact's userId for other operations, \" +\n \"or check if a specific person is already a contact.\\n\\n\" +\n \"**Returns:** Array of contacts, each with: userId (use with read_user_contexts or discover_opportunities), \" +\n \"name, email, avatar URL, and isGhost (true = no account yet, profile enriched from public data). \" +\n \"Use the userId with read_user_contexts(userId) to get the full profile, or with discover_opportunities(targetUserId) to connect.\",\n querySchema: z.object({\n limit: z.number().optional().describe('Maximum number of contacts to return. Omit to return all contacts. Use for large networks to paginate results.'),\n }),\n handler: async ({ context, query }) => {\n try {\n let contacts = await contactService.listContacts(context.userId);\n\n if (query.limit && query.limit > 0) {\n contacts = contacts.slice(0, query.limit);\n }\n\n return success({\n count: contacts.length,\n contacts: contacts.map(c => ({\n userId: c.userId,\n name: c.user.name,\n email: c.user.email,\n avatar: c.user.avatar,\n isGhost: c.user.isGhost,\n })),\n });\n } catch (err) {\n logger.error('Failed to list contacts', { err });\n return error('Failed to list contacts. Please try again.');\n }\n },\n });\n\n const add_contact = contactsEnabled ? defineTool({\n name: 'add_contact',\n description:\n \"Adds a single contact to the authenticated user's personal network by email address. \" +\n \"For bulk imports, use import_contacts instead.\\n\\n\" +\n \"**What happens:** Looks up the email. If an account exists, links that user as a contact. \" +\n \"If not, creates a ghost user (placeholder enriched with public profile data) and adds them. \" +\n \"The contact can then appear in opportunity discovery within the user's personal network.\\n\\n\" +\n \"**When to use:** When the user wants to add a specific person (e.g. 'add john@example.com to my network').\\n\\n\" +\n \"**Returns:** Confirmation with the contact's userId and whether a new ghost user was created (isNewGhost). \" +\n \"Use the userId with discover_opportunities(targetUserId) to find connection opportunities.\",\n querySchema: z.object({\n email: z.string().describe('Email address of the person to add. Used as unique identifier — if already a contact, the operation is idempotent.'),\n name: z.string().optional().describe('Full name of the contact. Optional — if omitted, the email prefix is used as name. Provide when known for better profile enrichment.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const result = await contactService.addContact(context.userId, query.email, { name: query.name, restore: true });\n\n return success({\n added: true,\n message: result.isNew\n ? `Added ${query.name || query.email} to your network. Their profile is being enriched.`\n : `Added ${query.name || query.email} to your network.`,\n userId: result.userId,\n isNewGhost: result.isNew,\n });\n } catch (err) {\n logger.error('Failed to add contact', { err });\n return error('Failed to add contact. Please try again.');\n }\n },\n }) : null;\n\n const remove_contact = defineTool({\n name: 'remove_contact',\n description:\n \"Removes a contact from the authenticated user's personal network. The contact relationship is deleted — \" +\n \"the person is no longer a member of the user's personal network and won't appear in personal-network-scoped discovery.\\n\\n\" +\n \"**When to use:** When the user wants to remove someone from their network (e.g. 'remove John from my contacts').\\n\\n\" +\n \"**Note:** This only removes the contact relationship. If the contact is a real user (not a ghost), \" +\n \"they still exist on the platform and may appear in shared network discovery.\\n\\n\" +\n \"**Returns:** Confirmation that the contact was removed.\",\n querySchema: z.object({\n contactUserId: z.string().describe('The userId of the contact to remove. Get this from list_contacts results.'),\n }),\n handler: async ({ context, query }) => {\n try {\n await contactService.removeContact(context.userId, query.contactUserId);\n return success({ removed: true, message: 'Contact removed from your network.' });\n } catch (err) {\n logger.error('Failed to remove contact', { err });\n return error('Failed to remove contact. Please try again.');\n }\n },\n });\n\n const search_contacts = defineTool({\n name: 'search_contacts',\n description:\n \"Searches the authenticated user's personal network by name or email (case-insensitive substring). \" +\n \"Use when the user refers to a contact by partial name or email and you need their userId for another tool \" +\n \"(e.g. read_user_contexts, discover_opportunities).\\n\\n\" +\n \"**When to use:** Before list_contacts when the network is large — returns only matching contacts, bounded by limit.\\n\\n\" +\n \"**Returns:** Array of matching contacts: userId, name, email, avatar, isGhost.\",\n querySchema: z.object({\n query: z.string().trim().min(1).describe('Free-text query matched against contact name and email (case-insensitive, substring).'),\n limit: z.number().int().positive().max(100).optional().describe('Maximum rows to return. Defaults to 25.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const rows = await contactService.searchContacts(context.userId, query.query, query.limit ?? 25);\n return success({\n count: rows.length,\n contacts: rows.map(r => ({\n userId: r.contactId,\n name: r.name,\n email: r.email,\n avatar: r.avatar,\n isGhost: r.isGhost,\n })),\n });\n } catch (err) {\n logger.error('Failed to search contacts', { err });\n return error('Failed to search contacts. Please try again.');\n }\n },\n });\n\n return [\n ...(import_contacts ? [import_contacts] : []),\n ...(add_contact ? [add_contact] : []),\n list_contacts,\n remove_contact,\n search_contacts,\n ];\n}\n"]}
1
+ {"version":3,"file":"contact.tools.js","sourceRoot":"/","sources":["contact/contact.tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport type { DefineTool, ToolDeps } from '../shared/agent/tool.helpers.js';\nimport { success, error } from '../shared/agent/tool.helpers.js';\nimport { protocolLogger } from '../shared/observability/protocol.logger.js';\n\nconst logger = protocolLogger('ChatTools:Contact');\n\n/**\n * Creates contact management tools for the chat agent.\n * Enables importing, listing, and managing the user's network.\n */\nexport function createContactTools(defineTool: DefineTool, deps: ToolDeps) {\n const { contactService } = deps;\n // Contact import / manual-add create ghost users. These are gated behind the\n // CONTACTS_ENABLED flag (injected as deps.contactsEnabled). Read/remove/search\n // tools below are always available so existing contacts stay manageable.\n const contactsEnabled = deps.contactsEnabled === true;\n\n // Only register when enabled: in the registry path defineTool registers as a\n // side effect, so the call itself must be gated, not just the returned array.\n const import_contacts = contactsEnabled ? defineTool({\n name: 'import_contacts',\n description:\n \"Bulk-imports contacts into the authenticated user's personal network (personal network). Contacts become members of the user's \" +\n \"personal network with 'contact' permission, making them available for opportunity discovery.\\n\\n\" +\n \"**What happens:** Each contact is matched by email. If the email belongs to an existing user, they're linked directly. \" +\n \"If not, a 'ghost user' is created — a placeholder account enriched with public profile data (from LinkedIn, GitHub, etc.) \" +\n \"that participates in opportunity matching even before the person joins the platform.\\n\\n\" +\n \"**When to use:** When the user provides a list of contacts to add (from CSV, manual input, or any source other than Gmail). \" +\n \"For Gmail specifically, use import_gmail_contacts instead.\\n\\n\" +\n \"**Returns:** Import statistics: imported (total processed), skipped (invalid), newContacts (ghost users created), \" +\n \"existingContacts (already in network). Use list_contacts to see all contacts after import.\",\n querySchema: z.object({\n contacts: z.array(z.object({\n name: z.string().describe('Full name of the contact (e.g. \"Jane Smith\")'),\n email: z.string().describe('Email address — used as the unique identifier for matching existing users'),\n })).describe('Array of contact objects to import. Each must have name and email. Duplicates (by email) are skipped.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const result = await contactService.importContacts(\n context.userId,\n query.contacts\n );\n return success({\n message: `Imported ${result.imported} contacts to your network.`,\n imported: result.imported,\n skipped: result.skipped,\n newContacts: result.newContacts,\n existingContacts: result.existingContacts,\n });\n } catch (err) {\n logger.error('Failed to import contacts', { err });\n return error('Failed to import contacts. Please try again.');\n }\n },\n }) : null;\n\n const list_contacts = defineTool({\n name: 'list_contacts',\n description:\n \"Lists all contacts in the authenticated user's personal network. Contacts are people the user has added \" +\n \"(via import_contacts, add_contact, or import_gmail_contacts) stored as members of their personal network.\\n\\n\" +\n \"**When to use:** To see who's in the user's network, find a contact's userId for other operations, \" +\n \"or check if a specific person is already a contact.\\n\\n\" +\n \"**Returns:** Array of contacts, each with: userId (use with read_user_contexts or discover_opportunities), \" +\n \"name, email, avatar URL, and isGhost (true = no account yet, profile enriched from public data). \" +\n \"Use the userId with read_user_contexts(userId) to get the full profile, or with discover_opportunities(targetUserId) to connect.\",\n querySchema: z.object({\n limit: z.number().optional().describe('Maximum number of contacts to return. Omit to return all contacts. Use for large networks to paginate results.'),\n }),\n handler: async ({ context, query }) => {\n try {\n let contacts = await contactService.listContacts(context.userId);\n\n if (query.limit && query.limit > 0) {\n contacts = contacts.slice(0, query.limit);\n }\n\n return success({\n count: contacts.length,\n contacts: contacts.map(c => ({\n userId: c.userId,\n name: c.user.name,\n email: c.user.email,\n avatar: c.user.avatar,\n isGhost: c.user.isGhost,\n })),\n });\n } catch (err) {\n logger.error('Failed to list contacts', { err });\n return error('Failed to list contacts. Please try again.');\n }\n },\n });\n\n const add_contact = contactsEnabled ? defineTool({\n name: 'add_contact',\n description:\n \"Adds a single contact to the authenticated user's personal network by email address. \" +\n \"For bulk imports, use import_contacts instead.\\n\\n\" +\n \"**What happens:** Looks up the email. If an account exists, links that user as a contact. \" +\n \"If not, creates a ghost user (placeholder enriched with public profile data) and adds them. \" +\n \"The contact can then appear in opportunity discovery within the user's personal network.\\n\\n\" +\n \"**When to use:** When the user wants to add a specific person (e.g. 'add john@example.com to my network').\\n\\n\" +\n \"**Returns:** Confirmation with the contact's userId and whether a new ghost user was created (isNewGhost). \" +\n \"Use the userId with discover_opportunities(targetUserId) to find connection opportunities.\",\n querySchema: z.object({\n email: z.string().describe('Email address of the person to add. Used as unique identifier — if already a contact, the operation is idempotent.'),\n name: z.string().optional().describe('Full name of the contact. Optional — if omitted, the email prefix is used as name. Provide when known for better profile enrichment.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const result = await contactService.addContact(context.userId, query.email, { name: query.name, restore: true });\n\n return success({\n added: true,\n message: result.isNew\n ? `Added ${query.name || query.email} to your network. Their profile is being enriched.`\n : `Added ${query.name || query.email} to your network.`,\n userId: result.userId,\n isNewGhost: result.isNew,\n });\n } catch (err) {\n logger.error('Failed to add contact', { err });\n return error('Failed to add contact. Please try again.');\n }\n },\n }) : null;\n\n const remove_contact = defineTool({\n name: 'remove_contact',\n description:\n \"Removes a contact from the authenticated user's personal network. The contact relationship is deleted — \" +\n \"the person is no longer a member of the user's personal network and won't appear in personal-network-scoped discovery.\\n\\n\" +\n \"**When to use:** When the user wants to remove someone from their network (e.g. 'remove John from my contacts').\\n\\n\" +\n \"**Note:** This only removes the contact relationship. If the contact is a real user (not a ghost), \" +\n \"they still exist on the platform and may appear in shared network discovery.\\n\\n\" +\n \"**Returns:** Confirmation that the contact was removed.\",\n querySchema: z.object({\n contactUserId: z.string().describe('The userId of the contact to remove. Get this from list_contacts results.'),\n }),\n handler: async ({ context, query }) => {\n try {\n await contactService.removeContact(context.userId, query.contactUserId);\n return success({ removed: true, message: 'Contact removed from your network.' });\n } catch (err) {\n logger.error('Failed to remove contact', { err });\n return error('Failed to remove contact. Please try again.');\n }\n },\n });\n\n const search_contacts = defineTool({\n name: 'search_contacts',\n description:\n \"Searches the authenticated user's personal network by name or email (case-insensitive substring). \" +\n \"Use when the user refers to a contact by partial name or email and you need their userId for another tool \" +\n \"(e.g. read_user_contexts, discover_opportunities).\\n\\n\" +\n \"**When to use:** Before list_contacts when the network is large — returns only matching contacts, bounded by limit.\\n\\n\" +\n \"**Returns:** Array of matching contacts: userId, name, email, avatar, isGhost.\",\n querySchema: z.object({\n query: z.string().trim().min(1).describe('Free-text query matched against contact name and email (case-insensitive, substring).'),\n limit: z.number().int().positive().max(100).optional().describe('Maximum rows to return. Defaults to 25.'),\n }),\n handler: async ({ context, query }) => {\n try {\n const rows = await contactService.searchContacts(context.userId, query.query, query.limit ?? 25);\n return success({\n count: rows.length,\n contacts: rows.map(r => ({\n userId: r.contactId,\n name: r.name,\n email: r.email,\n avatar: r.avatar,\n isGhost: r.isGhost,\n })),\n });\n } catch (err) {\n logger.error('Failed to search contacts', { err });\n return error('Failed to search contacts. Please try again.');\n }\n },\n });\n\n return [\n ...(import_contacts ? [import_contacts] : []),\n ...(add_contact ? [add_contact] : []),\n list_contacts,\n remove_contact,\n search_contacts,\n ];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"enrichment.graph.d.ts","sourceRoot":"/","sources":["enrichment/enrichment.graph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACxG,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAIpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,KAAK,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;QACjC,aAAa,EAAE,QAAQ,CAAC;QACxB,wEAAwE;QACxE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,yEAAyE;QACzE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC/C,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,OAAO,CAAC;QACV,OAAO,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QACrC,+EAA+E;QAC/E,WAAW,CAAC,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QAC3F,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC,CAAC;CACJ;AA+BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAC;gBAJb,QAAQ,EAAE,uBAAuB,EACjC,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,eAAe,YAAA,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,YAAA,EACvC,YAAY,CAAC,EAAE,oBAAoB,YAAA;IAGtC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBALC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiwBrB"}
1
+ {"version":3,"file":"enrichment.graph.d.ts","sourceRoot":"/","sources":["enrichment/enrichment.graph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACxG,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAC;AACpE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8CAA8C,CAAC;AAIpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,KAAK,EAAE;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,WAAW,GAAG,YAAY,CAAC;QACjC,aAAa,EAAE,QAAQ,CAAC;QACxB,wEAAwE;QACxE,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,yEAAyE;QACzE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,gBAAgB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC/C,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B,GAAG,OAAO,CAAC;QACV,OAAO,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QACrC,+EAA+E;QAC/E,WAAW,CAAC,EAAE;YAAE,SAAS,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;QAC3F,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KAC5B,CAAC,CAAC;CACJ;AA+BD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,iBAAiB,CAAC;IAC1B,OAAO,CAAC,YAAY,CAAC;gBAJb,QAAQ,EAAE,uBAAuB,EACjC,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,eAAe,YAAA,EAC1B,iBAAiB,CAAC,EAAE,mBAAmB,YAAA,EACvC,YAAY,CAAC,EAAE,oBAAoB,YAAA;IAGtC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBALC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;kBAAD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuwBrB"}
@@ -553,7 +553,9 @@ export class EnrichmentGraphFactory {
553
553
  }
554
554
  }
555
555
  if (retracted > 0) {
556
- logger.verbose(`Retracted ${retracted}/${retractionIds.length} premise(s) disavowed by input`, {
556
+ logger.verbose('Retracted premises disavowed by input', {
557
+ retracted,
558
+ requested: retractionIds.length,
557
559
  userId: state.userId,
558
560
  });
559
561
  }
@@ -586,7 +588,8 @@ export class EnrichmentGraphFactory {
586
588
  ...(retracted > 0 || bioRevised ? { operationsPerformed: { decomposedPremises: true } } : {}),
587
589
  };
588
590
  }
589
- logger.verbose(`Creating ${result.premises.length} premise(s) via premise graph`, {
591
+ logger.verbose('Creating premises via premise graph', {
592
+ count: result.premises.length,
590
593
  userId: state.userId,
591
594
  });
592
595
  let created = 0;
@@ -630,7 +633,10 @@ export class EnrichmentGraphFactory {
630
633
  });
631
634
  }
632
635
  }
633
- logger.verbose(`Created ${created}/${result.premises.length} premise(s) (${skippedDuplicates} skipped as near-duplicates)`, {
636
+ logger.verbose('Created premises', {
637
+ created,
638
+ requested: result.premises.length,
639
+ skippedDuplicates,
634
640
  userId: state.userId,
635
641
  });
636
642
  return {