@nex-ai/nex 0.1.22 → 0.1.24

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 (292) hide show
  1. package/README.md +7 -2
  2. package/dist/agent/adoption.d.ts +23 -0
  3. package/dist/agent/adoption.js +87 -0
  4. package/dist/agent/adoption.js.map +1 -0
  5. package/dist/agent/gossip.d.ts +17 -0
  6. package/dist/agent/gossip.js +48 -0
  7. package/dist/agent/gossip.js.map +1 -0
  8. package/dist/agent/loop.d.ts +59 -0
  9. package/dist/agent/loop.js +389 -0
  10. package/dist/agent/loop.js.map +1 -0
  11. package/dist/agent/queues.d.ts +16 -0
  12. package/dist/agent/queues.js +44 -0
  13. package/dist/agent/queues.js.map +1 -0
  14. package/dist/agent/session-store.d.ts +21 -0
  15. package/dist/agent/session-store.js +96 -0
  16. package/dist/agent/session-store.js.map +1 -0
  17. package/dist/agent/templates.d.ts +5 -0
  18. package/dist/agent/templates.js +48 -0
  19. package/dist/agent/templates.js.map +1 -0
  20. package/dist/agent/tools.d.ts +25 -0
  21. package/dist/agent/tools.js +238 -0
  22. package/dist/agent/tools.js.map +1 -0
  23. package/dist/agent/types.d.ts +59 -0
  24. package/dist/agent/types.js +5 -0
  25. package/dist/agent/types.js.map +1 -0
  26. package/dist/calendar/scheduler.d.ts +32 -0
  27. package/dist/calendar/scheduler.js +178 -0
  28. package/dist/calendar/scheduler.js.map +1 -0
  29. package/dist/calendar/store.d.ts +15 -0
  30. package/dist/calendar/store.js +50 -0
  31. package/dist/calendar/store.js.map +1 -0
  32. package/dist/calendar/types.d.ts +17 -0
  33. package/dist/calendar/types.js +5 -0
  34. package/dist/calendar/types.js.map +1 -0
  35. package/dist/chat/channel.d.ts +20 -0
  36. package/dist/chat/channel.js +84 -0
  37. package/dist/chat/channel.js.map +1 -0
  38. package/dist/chat/message-store.d.ts +18 -0
  39. package/dist/chat/message-store.js +82 -0
  40. package/dist/chat/message-store.js.map +1 -0
  41. package/dist/chat/router.d.ts +17 -0
  42. package/dist/chat/router.js +65 -0
  43. package/dist/chat/router.js.map +1 -0
  44. package/dist/chat/suggested-responses.d.ts +6 -0
  45. package/dist/chat/suggested-responses.js +99 -0
  46. package/dist/chat/suggested-responses.js.map +1 -0
  47. package/dist/chat/types.d.ts +28 -0
  48. package/dist/chat/types.js +5 -0
  49. package/dist/chat/types.js.map +1 -0
  50. package/dist/cli.js +3 -1
  51. package/dist/cli.js.map +1 -1
  52. package/dist/commands/dispatch.d.ts +39 -0
  53. package/dist/commands/dispatch.js +1293 -0
  54. package/dist/commands/dispatch.js.map +1 -0
  55. package/dist/commands/init.d.ts +49 -0
  56. package/dist/commands/init.js +315 -0
  57. package/dist/commands/init.js.map +1 -0
  58. package/dist/commands/parse-input.d.ts +5 -0
  59. package/dist/commands/parse-input.js +37 -0
  60. package/dist/commands/parse-input.js.map +1 -0
  61. package/dist/index.d.ts +6 -23
  62. package/dist/index.js +118 -50
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib/client.js +1 -1
  65. package/dist/lib/client.js.map +1 -1
  66. package/dist/lib/errors.js +1 -1
  67. package/dist/lib/errors.js.map +1 -1
  68. package/dist/lib/integrations.d.ts +23 -0
  69. package/dist/lib/integrations.js +25 -0
  70. package/dist/lib/integrations.js.map +1 -0
  71. package/dist/lib/nex-mcp-config.d.ts +14 -0
  72. package/dist/lib/nex-mcp-config.js +26 -0
  73. package/dist/lib/nex-mcp-config.js.map +1 -0
  74. package/dist/orchestration/budget.d.ts +32 -0
  75. package/dist/orchestration/budget.js +72 -0
  76. package/dist/orchestration/budget.js.map +1 -0
  77. package/dist/orchestration/executor.d.ts +59 -0
  78. package/dist/orchestration/executor.js +197 -0
  79. package/dist/orchestration/executor.js.map +1 -0
  80. package/dist/orchestration/router.d.ts +30 -0
  81. package/dist/orchestration/router.js +98 -0
  82. package/dist/orchestration/router.js.map +1 -0
  83. package/dist/orchestration/templates.d.ts +11 -0
  84. package/dist/orchestration/templates.js +99 -0
  85. package/dist/orchestration/templates.js.map +1 -0
  86. package/dist/orchestration/types.d.ts +58 -0
  87. package/dist/orchestration/types.js +7 -0
  88. package/dist/orchestration/types.js.map +1 -0
  89. package/dist/plugin/shared.js +1 -1
  90. package/dist/plugin/shared.js.map +1 -1
  91. package/dist/tui/agent-colors.d.ts +19 -0
  92. package/dist/tui/agent-colors.js +34 -0
  93. package/dist/tui/agent-colors.js.map +1 -0
  94. package/dist/tui/app.d.ts +14 -0
  95. package/dist/tui/app.js +267 -0
  96. package/dist/tui/app.js.map +1 -0
  97. package/dist/tui/channel-colors.d.ts +16 -0
  98. package/dist/tui/channel-colors.js +43 -0
  99. package/dist/tui/channel-colors.js.map +1 -0
  100. package/dist/tui/components/agent-card.d.ts +11 -0
  101. package/dist/tui/components/agent-card.js +40 -0
  102. package/dist/tui/components/agent-card.js.map +1 -0
  103. package/dist/tui/components/banner.d.ts +44 -0
  104. package/dist/tui/components/banner.js +130 -0
  105. package/dist/tui/components/banner.js.map +1 -0
  106. package/dist/tui/components/channel-colors.d.ts +21 -0
  107. package/dist/tui/components/channel-colors.js +53 -0
  108. package/dist/tui/components/channel-colors.js.map +1 -0
  109. package/dist/tui/components/channel-message.d.ts +53 -0
  110. package/dist/tui/components/channel-message.js +66 -0
  111. package/dist/tui/components/channel-message.js.map +1 -0
  112. package/dist/tui/components/chat-input.d.ts +11 -0
  113. package/dist/tui/components/chat-input.js +19 -0
  114. package/dist/tui/components/chat-input.js.map +1 -0
  115. package/dist/tui/components/data-table.d.ts +11 -0
  116. package/dist/tui/components/data-table.js +47 -0
  117. package/dist/tui/components/data-table.js.map +1 -0
  118. package/dist/tui/components/error-box.d.ts +11 -0
  119. package/dist/tui/components/error-box.js +59 -0
  120. package/dist/tui/components/error-box.js.map +1 -0
  121. package/dist/tui/components/help-screen.d.ts +3 -0
  122. package/dist/tui/components/help-screen.js +63 -0
  123. package/dist/tui/components/help-screen.js.map +1 -0
  124. package/dist/tui/components/index.d.ts +17 -0
  125. package/dist/tui/components/index.js +10 -0
  126. package/dist/tui/components/index.js.map +1 -0
  127. package/dist/tui/components/inline-confirm.d.ts +14 -0
  128. package/dist/tui/components/inline-confirm.js +13 -0
  129. package/dist/tui/components/inline-confirm.js.map +1 -0
  130. package/dist/tui/components/inline-select.d.ts +21 -0
  131. package/dist/tui/components/inline-select.js +20 -0
  132. package/dist/tui/components/inline-select.js.map +1 -0
  133. package/dist/tui/components/markdown.d.ts +6 -0
  134. package/dist/tui/components/markdown.js +179 -0
  135. package/dist/tui/components/markdown.js.map +1 -0
  136. package/dist/tui/components/mention-autocomplete.d.ts +77 -0
  137. package/dist/tui/components/mention-autocomplete.js +235 -0
  138. package/dist/tui/components/mention-autocomplete.js.map +1 -0
  139. package/dist/tui/components/message-list.d.ts +18 -0
  140. package/dist/tui/components/message-list.js +29 -0
  141. package/dist/tui/components/message-list.js.map +1 -0
  142. package/dist/tui/components/picker.d.ts +16 -0
  143. package/dist/tui/components/picker.js +32 -0
  144. package/dist/tui/components/picker.js.map +1 -0
  145. package/dist/tui/components/progress-steps.d.ts +13 -0
  146. package/dist/tui/components/progress-steps.js +21 -0
  147. package/dist/tui/components/progress-steps.js.map +1 -0
  148. package/dist/tui/components/slack/compose.d.ts +27 -0
  149. package/dist/tui/components/slack/compose.js +123 -0
  150. package/dist/tui/components/slack/compose.js.map +1 -0
  151. package/dist/tui/components/slack/layout.d.ts +36 -0
  152. package/dist/tui/components/slack/layout.js +96 -0
  153. package/dist/tui/components/slack/layout.js.map +1 -0
  154. package/dist/tui/components/slack/messages.d.ts +72 -0
  155. package/dist/tui/components/slack/messages.js +177 -0
  156. package/dist/tui/components/slack/messages.js.map +1 -0
  157. package/dist/tui/components/slack/quick-switcher.d.ts +33 -0
  158. package/dist/tui/components/slack/quick-switcher.js +98 -0
  159. package/dist/tui/components/slack/quick-switcher.js.map +1 -0
  160. package/dist/tui/components/slack/sidebar-types.d.ts +65 -0
  161. package/dist/tui/components/slack/sidebar-types.js +7 -0
  162. package/dist/tui/components/slack/sidebar-types.js.map +1 -0
  163. package/dist/tui/components/slack/sidebar.d.ts +46 -0
  164. package/dist/tui/components/slack/sidebar.js +52 -0
  165. package/dist/tui/components/slack/sidebar.js.map +1 -0
  166. package/dist/tui/components/slack/thread-panel.d.ts +45 -0
  167. package/dist/tui/components/slack/thread-panel.js +47 -0
  168. package/dist/tui/components/slack/thread-panel.js.map +1 -0
  169. package/dist/tui/components/slash-autocomplete.d.ts +81 -0
  170. package/dist/tui/components/slash-autocomplete.js +218 -0
  171. package/dist/tui/components/slash-autocomplete.js.map +1 -0
  172. package/dist/tui/components/spinner.d.ts +17 -0
  173. package/dist/tui/components/spinner.js +30 -0
  174. package/dist/tui/components/spinner.js.map +1 -0
  175. package/dist/tui/components/status-bar.d.ts +23 -0
  176. package/dist/tui/components/status-bar.js +55 -0
  177. package/dist/tui/components/status-bar.js.map +1 -0
  178. package/dist/tui/components/success-box.d.ts +7 -0
  179. package/dist/tui/components/success-box.js +10 -0
  180. package/dist/tui/components/success-box.js.map +1 -0
  181. package/dist/tui/components/tool-indicator.d.ts +12 -0
  182. package/dist/tui/components/tool-indicator.js +18 -0
  183. package/dist/tui/components/tool-indicator.js.map +1 -0
  184. package/dist/tui/components/viewport.d.ts +9 -0
  185. package/dist/tui/components/viewport.js +24 -0
  186. package/dist/tui/components/viewport.js.map +1 -0
  187. package/dist/tui/generative/bindings.d.ts +27 -0
  188. package/dist/tui/generative/bindings.js +152 -0
  189. package/dist/tui/generative/bindings.js.map +1 -0
  190. package/dist/tui/generative/registry.d.ts +19 -0
  191. package/dist/tui/generative/registry.js +31 -0
  192. package/dist/tui/generative/registry.js.map +1 -0
  193. package/dist/tui/generative/renderer.d.ts +24 -0
  194. package/dist/tui/generative/renderer.js +160 -0
  195. package/dist/tui/generative/renderer.js.map +1 -0
  196. package/dist/tui/generative/types.d.ts +68 -0
  197. package/dist/tui/generative/types.js +7 -0
  198. package/dist/tui/generative/types.js.map +1 -0
  199. package/dist/tui/hooks/use-cancellable.d.ts +28 -0
  200. package/dist/tui/hooks/use-cancellable.js +51 -0
  201. package/dist/tui/hooks/use-cancellable.js.map +1 -0
  202. package/dist/tui/hooks/use-streaming.d.ts +44 -0
  203. package/dist/tui/hooks/use-streaming.js +105 -0
  204. package/dist/tui/hooks/use-streaming.js.map +1 -0
  205. package/dist/tui/index.d.ts +4 -0
  206. package/dist/tui/index.js +7 -0
  207. package/dist/tui/index.js.map +1 -0
  208. package/dist/tui/keybindings.d.ts +25 -0
  209. package/dist/tui/keybindings.js +277 -0
  210. package/dist/tui/keybindings.js.map +1 -0
  211. package/dist/tui/register-views.d.ts +8 -0
  212. package/dist/tui/register-views.js +116 -0
  213. package/dist/tui/register-views.js.map +1 -0
  214. package/dist/tui/router.d.ts +29 -0
  215. package/dist/tui/router.js +87 -0
  216. package/dist/tui/router.js.map +1 -0
  217. package/dist/tui/services/agent-service.d.ts +58 -0
  218. package/dist/tui/services/agent-service.js +197 -0
  219. package/dist/tui/services/agent-service.js.map +1 -0
  220. package/dist/tui/services/calendar-service.d.ts +31 -0
  221. package/dist/tui/services/calendar-service.js +133 -0
  222. package/dist/tui/services/calendar-service.js.map +1 -0
  223. package/dist/tui/services/chat-service.d.ts +28 -0
  224. package/dist/tui/services/chat-service.js +91 -0
  225. package/dist/tui/services/chat-service.js.map +1 -0
  226. package/dist/tui/services/orchestration-service.d.ts +42 -0
  227. package/dist/tui/services/orchestration-service.js +153 -0
  228. package/dist/tui/services/orchestration-service.js.map +1 -0
  229. package/dist/tui/slash-commands.d.ts +106 -0
  230. package/dist/tui/slash-commands.js +1421 -0
  231. package/dist/tui/slash-commands.js.map +1 -0
  232. package/dist/tui/store.d.ts +96 -0
  233. package/dist/tui/store.js +120 -0
  234. package/dist/tui/store.js.map +1 -0
  235. package/dist/tui/theme.d.ts +40 -0
  236. package/dist/tui/theme.js +39 -0
  237. package/dist/tui/theme.js.map +1 -0
  238. package/dist/tui/tui-context.d.ts +22 -0
  239. package/dist/tui/tui-context.js +17 -0
  240. package/dist/tui/tui-context.js.map +1 -0
  241. package/dist/tui/views/agent-list.d.ts +8 -0
  242. package/dist/tui/views/agent-list.js +11 -0
  243. package/dist/tui/views/agent-list.js.map +1 -0
  244. package/dist/tui/views/ask-chat.d.ts +9 -0
  245. package/dist/tui/views/ask-chat.js +40 -0
  246. package/dist/tui/views/ask-chat.js.map +1 -0
  247. package/dist/tui/views/calendar.d.ts +15 -0
  248. package/dist/tui/views/calendar.js +29 -0
  249. package/dist/tui/views/calendar.js.map +1 -0
  250. package/dist/tui/views/chat.d.ts +18 -0
  251. package/dist/tui/views/chat.js +28 -0
  252. package/dist/tui/views/chat.js.map +1 -0
  253. package/dist/tui/views/generative.d.ts +14 -0
  254. package/dist/tui/views/generative.js +37 -0
  255. package/dist/tui/views/generative.js.map +1 -0
  256. package/dist/tui/views/help.d.ts +6 -0
  257. package/dist/tui/views/help.js +9 -0
  258. package/dist/tui/views/help.js.map +1 -0
  259. package/dist/tui/views/home-screen.d.ts +67 -0
  260. package/dist/tui/views/home-screen.js +192 -0
  261. package/dist/tui/views/home-screen.js.map +1 -0
  262. package/dist/tui/views/home.d.ts +33 -0
  263. package/dist/tui/views/home.js +60 -0
  264. package/dist/tui/views/home.js.map +1 -0
  265. package/dist/tui/views/index.d.ts +20 -0
  266. package/dist/tui/views/index.js +11 -0
  267. package/dist/tui/views/index.js.map +1 -0
  268. package/dist/tui/views/insights.d.ts +19 -0
  269. package/dist/tui/views/insights.js +46 -0
  270. package/dist/tui/views/insights.js.map +1 -0
  271. package/dist/tui/views/orchestration.d.ts +18 -0
  272. package/dist/tui/views/orchestration.js +73 -0
  273. package/dist/tui/views/orchestration.js.map +1 -0
  274. package/dist/tui/views/record-detail.d.ts +10 -0
  275. package/dist/tui/views/record-detail.js +22 -0
  276. package/dist/tui/views/record-detail.js.map +1 -0
  277. package/dist/tui/views/record-list.d.ts +15 -0
  278. package/dist/tui/views/record-list.js +22 -0
  279. package/dist/tui/views/record-list.js.map +1 -0
  280. package/dist/tui/views/slack-channel-header.d.ts +15 -0
  281. package/dist/tui/views/slack-channel-header.js +16 -0
  282. package/dist/tui/views/slack-channel-header.js.map +1 -0
  283. package/dist/tui/views/slack-home.d.ts +21 -0
  284. package/dist/tui/views/slack-home.js +572 -0
  285. package/dist/tui/views/slack-home.js.map +1 -0
  286. package/dist/tui/views/task-board.d.ts +21 -0
  287. package/dist/tui/views/task-board.js +33 -0
  288. package/dist/tui/views/task-board.js.map +1 -0
  289. package/dist/tui/views/timeline.d.ts +17 -0
  290. package/dist/tui/views/timeline.js +24 -0
  291. package/dist/tui/views/timeline.js.map +1 -0
  292. package/package.json +8 -3
package/README.md CHANGED
@@ -1,9 +1,14 @@
1
- # @nex-ai/nex
1
+ # Nex: Compounding Intelligence for AI agents
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@nex-ai/nex)](https://www.npmjs.com/package/@nex-ai/nex)
4
4
  [![GitHub](https://img.shields.io/badge/github-nex--crm%2Fnex--as--a--skill-blue)](https://github.com/nex-crm/nex-as-a-skill)
5
+ [![Discord](https://img.shields.io/badge/Discord-Join%20Community-5865F2?logo=discord&logoColor=white)](https://discord.gg/gjSySC3PzV)
5
6
 
6
- Nex CLI provides organizational context & memory to AI agents across 12 platforms.
7
+ Turn all your AI agent conversations into a unified knowledge graph. Supports Claude Code, Codex, OpenClaw, Cursor, OpenCode, etc. Adds additional context from Email, Meetings, Slack, HubSpot, Salesforce.
8
+
9
+ <a href="https://discord.gg/gjSySC3PzV"><img src="https://img.shields.io/badge/Join%20our%20Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Join our Discord" /></a>
10
+
11
+ Talk to the team, share feedback, and connect with other developers building AI agents with Nex.
7
12
 
8
13
  **GitHub**: [github.com/nex-crm/nex-as-a-skill](https://github.com/nex-crm/nex-as-a-skill)
9
14
 
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Selective insight adoption scoring and credibility tracking.
3
+ * Determines whether an agent should adopt, test, or reject a gossip insight.
4
+ */
5
+ import type { GossipInsight } from './gossip.js';
6
+ export interface AdoptionScore {
7
+ sourceCredibility: number;
8
+ semanticRelevance: number;
9
+ temporalFreshness: number;
10
+ total: number;
11
+ decision: 'adopt' | 'test' | 'reject';
12
+ }
13
+ export declare function scoreInsight(insight: GossipInsight, _currentContext: string, sourceCredibility?: number): AdoptionScore;
14
+ export declare class CredibilityTracker {
15
+ private baseDir;
16
+ private filePath;
17
+ private data;
18
+ constructor(baseDir?: string);
19
+ private load;
20
+ private save;
21
+ getCredibility(agentSlug: string): number;
22
+ recordOutcome(agentSlug: string, success: boolean): void;
23
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Selective insight adoption scoring and credibility tracking.
3
+ * Determines whether an agent should adopt, test, or reject a gossip insight.
4
+ */
5
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ const CREDIBILITY_WEIGHT = 0.4;
9
+ const RELEVANCE_WEIGHT = 0.4;
10
+ const FRESHNESS_WEIGHT = 0.2;
11
+ const ADOPT_THRESHOLD = 0.7;
12
+ const TEST_THRESHOLD = 0.4;
13
+ // Insights older than 7 days start losing freshness
14
+ const FRESHNESS_HALF_LIFE_MS = 7 * 24 * 60 * 60 * 1000;
15
+ export function scoreInsight(insight, _currentContext, sourceCredibility) {
16
+ const credibility = sourceCredibility ?? 0.5;
17
+ const semanticRelevance = Math.max(0, Math.min(1, insight.relevance));
18
+ const age = Date.now() - insight.timestamp;
19
+ const temporalFreshness = Math.max(0, Math.exp(-age / FRESHNESS_HALF_LIFE_MS));
20
+ const total = credibility * CREDIBILITY_WEIGHT +
21
+ semanticRelevance * RELEVANCE_WEIGHT +
22
+ temporalFreshness * FRESHNESS_WEIGHT;
23
+ let decision;
24
+ if (total >= ADOPT_THRESHOLD) {
25
+ decision = 'adopt';
26
+ }
27
+ else if (total >= TEST_THRESHOLD) {
28
+ decision = 'test';
29
+ }
30
+ else {
31
+ decision = 'reject';
32
+ }
33
+ return {
34
+ sourceCredibility: credibility,
35
+ semanticRelevance,
36
+ temporalFreshness,
37
+ total,
38
+ decision,
39
+ };
40
+ }
41
+ export class CredibilityTracker {
42
+ baseDir;
43
+ filePath;
44
+ data;
45
+ constructor(baseDir) {
46
+ this.baseDir = baseDir ?? join(homedir(), '.nex-cli', 'credibility');
47
+ this.filePath = join(this.baseDir, 'scores.json');
48
+ this.data = this.load();
49
+ }
50
+ load() {
51
+ try {
52
+ if (!existsSync(this.filePath))
53
+ return {};
54
+ const raw = readFileSync(this.filePath, 'utf-8');
55
+ return JSON.parse(raw);
56
+ }
57
+ catch {
58
+ return {};
59
+ }
60
+ }
61
+ save() {
62
+ mkdirSync(this.baseDir, { recursive: true });
63
+ writeFileSync(this.filePath, JSON.stringify(this.data, null, 2) + '\n', 'utf-8');
64
+ }
65
+ getCredibility(agentSlug) {
66
+ const record = this.data[agentSlug];
67
+ if (!record)
68
+ return 0.5;
69
+ const total = record.successes + record.failures;
70
+ if (total === 0)
71
+ return 0.5;
72
+ return record.successes / total;
73
+ }
74
+ recordOutcome(agentSlug, success) {
75
+ if (!this.data[agentSlug]) {
76
+ this.data[agentSlug] = { successes: 0, failures: 0 };
77
+ }
78
+ if (success) {
79
+ this.data[agentSlug].successes++;
80
+ }
81
+ else {
82
+ this.data[agentSlug].failures++;
83
+ }
84
+ this.save();
85
+ }
86
+ }
87
+ //# sourceMappingURL=adoption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adoption.js","sourceRoot":"","sources":["../../src/agent/adoption.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Gossip layer for knowledge propagation between agents.
3
+ * Uses Nex Ask/Remember APIs to publish and query insights.
4
+ */
5
+ import type { NexClient } from '../lib/client.js';
6
+ export interface GossipInsight {
7
+ content: string;
8
+ source: string;
9
+ timestamp: number;
10
+ relevance: number;
11
+ }
12
+ export declare class GossipLayer {
13
+ private client;
14
+ constructor(client: NexClient);
15
+ publish(agentSlug: string, insight: string, context?: string): Promise<string>;
16
+ query(agentSlug: string, topic: string): Promise<GossipInsight[]>;
17
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Gossip layer for knowledge propagation between agents.
3
+ * Uses Nex Ask/Remember APIs to publish and query insights.
4
+ */
5
+ export class GossipLayer {
6
+ client;
7
+ constructor(client) {
8
+ this.client = client;
9
+ }
10
+ async publish(agentSlug, insight, context) {
11
+ const taggedContent = `[agent:${agentSlug}] ${insight}`;
12
+ const tags = ['gossip', `agent:${agentSlug}`];
13
+ if (context)
14
+ tags.push(`ctx:${context}`);
15
+ const result = await this.client.post('/remember', {
16
+ content: taggedContent,
17
+ tags,
18
+ });
19
+ return result.id ?? 'stored';
20
+ }
21
+ async query(agentSlug, topic) {
22
+ const result = await this.client.post('/search', {
23
+ query: `[gossip] ${topic}`,
24
+ limit: 10,
25
+ });
26
+ if (!result.results || !Array.isArray(result.results))
27
+ return [];
28
+ return result.results
29
+ .filter(r => {
30
+ // Exclude the querying agent's own insights
31
+ const content = r.content ?? '';
32
+ return !content.startsWith(`[agent:${agentSlug}]`);
33
+ })
34
+ .map(r => {
35
+ const content = r.content ?? '';
36
+ const sourceMatch = content.match(/^\[agent:([^\]]+)\]/);
37
+ const source = sourceMatch ? sourceMatch[1] : 'unknown';
38
+ const cleanContent = content.replace(/^\[agent:[^\]]+\]\s*/, '');
39
+ return {
40
+ content: cleanContent,
41
+ source,
42
+ timestamp: Date.now(),
43
+ relevance: r.score ?? 0,
44
+ };
45
+ });
46
+ }
47
+ }
48
+ //# sourceMappingURL=gossip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gossip.js","sourceRoot":"","sources":["../../src/agent/gossip.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,MAAM,OAAO,WAAW;IACd,MAAM,CAAY;IAE1B,YAAY,MAAiB;QAC3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,SAAiB,EAAE,OAAe,EAAE,OAAgB;QAChE,MAAM,aAAa,GAAG,UAAU,SAAS,KAAK,OAAO,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;QAC9C,IAAI,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;QAEzC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAkB,WAAW,EAAE;YAClE,OAAO,EAAE,aAAa;YACtB,IAAI;SACL,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,EAAE,IAAI,QAAQ,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAiB,EAAE,KAAa;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAMlC,SAAS,EAAE;YACZ,KAAK,EAAE,YAAY,KAAK,EAAE;YAC1B,KAAK,EAAE,EAAE;SACV,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,CAAC;QAEjE,OAAO,MAAM,CAAC,OAAO;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE;YACV,4CAA4C;YAC5C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;YAChC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,SAAS,GAAG,CAAC,CAAC;QACrD,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,CAAC,EAAE;YACP,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;YAChC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;YAEjE,OAAO;gBACL,OAAO,EAAE,YAAY;gBACrB,MAAM;gBACN,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,SAAS,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;aACxB,CAAC;QACJ,CAAC,CAAC,CAAC;IACP,CAAC;CACF"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Pi-style state machine agent loop.
3
+ * Runs idle -> build_context -> stream_llm -> execute_tool -> done cycle.
4
+ * Mock streamFn used until real LLM integration.
5
+ */
6
+ import type { AgentConfig, AgentState, StreamFn } from './types.js';
7
+ import type { ToolRegistry } from './tools.js';
8
+ import type { AgentSessionStore } from './session-store.js';
9
+ import type { MessageQueues } from './queues.js';
10
+ import type { GossipLayer } from './gossip.js';
11
+ import type { CredibilityTracker } from './adoption.js';
12
+ type EventName = 'phase_change' | 'tool_call' | 'message' | 'error' | 'done';
13
+ type EventHandler = (...args: unknown[]) => void;
14
+ /**
15
+ * Mock streamFn that simulates LLM responses.
16
+ * Returns a text response, optionally followed by a tool call if tools are available.
17
+ */
18
+ export declare function createMockStreamFn(): StreamFn;
19
+ export declare class AgentLoop {
20
+ private state;
21
+ private tools;
22
+ private sessions;
23
+ private queues;
24
+ private streamFn;
25
+ private gossipLayer;
26
+ private credibilityTracker;
27
+ private running;
28
+ private paused;
29
+ private eventHandlers;
30
+ private pendingToolCall;
31
+ private abortController;
32
+ /** Tracks whether the current task had any errors (tool failures, LLM errors). */
33
+ private taskHadError;
34
+ /** Insights collected during this execution cycle (from tool results, gossip publish calls). */
35
+ private collectedInsights;
36
+ constructor(config: AgentConfig, tools: ToolRegistry, sessions: AgentSessionStore, queues: MessageQueues, streamFn?: StreamFn, gossipLayer?: GossipLayer, credibilityTracker?: CredibilityTracker);
37
+ private setPhase;
38
+ private emit;
39
+ on(event: EventName, handler: EventHandler): void;
40
+ off(event: string, handler: EventHandler): void;
41
+ getState(): AgentState;
42
+ tick(): Promise<void>;
43
+ private buildContext;
44
+ /**
45
+ * Query the gossip layer, score each insight, and inject adopted/test insights
46
+ * into the session as system messages.
47
+ */
48
+ private injectGossipInsights;
49
+ private streamLlm;
50
+ private executeTool;
51
+ private handleDone;
52
+ start(): void;
53
+ stop(): void;
54
+ pause(): void;
55
+ resume(): void;
56
+ /** Allow external code or tools to push insights for gossip publishing at done phase. */
57
+ addInsight(insight: string): void;
58
+ }
59
+ export {};
@@ -0,0 +1,389 @@
1
+ /**
2
+ * Pi-style state machine agent loop.
3
+ * Runs idle -> build_context -> stream_llm -> execute_tool -> done cycle.
4
+ * Mock streamFn used until real LLM integration.
5
+ */
6
+ import { scoreInsight } from './adoption.js';
7
+ /**
8
+ * Mock streamFn that simulates LLM responses.
9
+ * Returns a text response, optionally followed by a tool call if tools are available.
10
+ */
11
+ export function createMockStreamFn() {
12
+ return async function* mockStream(messages, tools) {
13
+ const lastMsg = messages[messages.length - 1];
14
+ const content = lastMsg?.content ?? '';
15
+ // If tools available, simulate a tool call for search-like queries
16
+ if (tools.length > 0 && content.toLowerCase().includes('search')) {
17
+ const searchTool = tools.find(t => t.name.includes('search'));
18
+ if (searchTool) {
19
+ yield {
20
+ type: 'tool_call',
21
+ toolName: searchTool.name,
22
+ toolParams: { query: content },
23
+ };
24
+ return;
25
+ }
26
+ }
27
+ yield {
28
+ type: 'text',
29
+ content: `Processed: ${content}`,
30
+ };
31
+ };
32
+ }
33
+ export class AgentLoop {
34
+ state;
35
+ tools;
36
+ sessions;
37
+ queues;
38
+ streamFn;
39
+ gossipLayer;
40
+ credibilityTracker;
41
+ running = false;
42
+ paused = false;
43
+ eventHandlers = new Map();
44
+ pendingToolCall = null;
45
+ abortController = null;
46
+ /** Tracks whether the current task had any errors (tool failures, LLM errors). */
47
+ taskHadError = false;
48
+ /** Insights collected during this execution cycle (from tool results, gossip publish calls). */
49
+ collectedInsights = [];
50
+ constructor(config, tools, sessions, queues, streamFn, gossipLayer, credibilityTracker) {
51
+ this.tools = tools;
52
+ this.sessions = sessions;
53
+ this.queues = queues;
54
+ this.streamFn = streamFn ?? createMockStreamFn();
55
+ this.gossipLayer = gossipLayer ?? null;
56
+ this.credibilityTracker = credibilityTracker ?? null;
57
+ this.state = {
58
+ phase: 'idle',
59
+ config,
60
+ tokensUsed: 0,
61
+ costUsd: 0,
62
+ };
63
+ }
64
+ setPhase(phase) {
65
+ const prev = this.state.phase;
66
+ this.state.phase = phase;
67
+ this.emit('phase_change', prev, phase);
68
+ }
69
+ emit(event, ...args) {
70
+ const handlers = this.eventHandlers.get(event);
71
+ if (handlers) {
72
+ for (const handler of handlers) {
73
+ try {
74
+ handler(...args);
75
+ }
76
+ catch {
77
+ // swallow handler errors
78
+ }
79
+ }
80
+ }
81
+ }
82
+ on(event, handler) {
83
+ let set = this.eventHandlers.get(event);
84
+ if (!set) {
85
+ set = new Set();
86
+ this.eventHandlers.set(event, set);
87
+ }
88
+ set.add(handler);
89
+ }
90
+ off(event, handler) {
91
+ const set = this.eventHandlers.get(event);
92
+ if (set) {
93
+ set.delete(handler);
94
+ }
95
+ }
96
+ getState() {
97
+ return { ...this.state };
98
+ }
99
+ async tick() {
100
+ if (this.paused)
101
+ return;
102
+ // Check for steer interrupts
103
+ const steerMsg = this.queues.drainSteer(this.state.config.slug);
104
+ if (steerMsg) {
105
+ if (this.state.sessionId) {
106
+ this.sessions.append(this.state.sessionId, {
107
+ type: 'system',
108
+ content: `[STEER] ${steerMsg}`,
109
+ });
110
+ }
111
+ }
112
+ switch (this.state.phase) {
113
+ case 'idle':
114
+ await this.buildContext();
115
+ break;
116
+ case 'build_context':
117
+ await this.streamLlm();
118
+ break;
119
+ case 'stream_llm':
120
+ if (this.pendingToolCall) {
121
+ await this.executeTool();
122
+ }
123
+ else {
124
+ await this.handleDone();
125
+ }
126
+ break;
127
+ case 'execute_tool':
128
+ await this.streamLlm();
129
+ break;
130
+ case 'done':
131
+ await this.handleDone();
132
+ break;
133
+ case 'error':
134
+ // Stay in error until reset
135
+ break;
136
+ }
137
+ }
138
+ async buildContext() {
139
+ this.setPhase('build_context');
140
+ this.taskHadError = false;
141
+ this.collectedInsights = [];
142
+ if (!this.state.sessionId) {
143
+ this.state.sessionId = this.sessions.create(this.state.config.slug);
144
+ }
145
+ // Inject follow-up messages as context
146
+ const followUp = this.queues.drainFollowUp(this.state.config.slug);
147
+ if (followUp) {
148
+ this.sessions.append(this.state.sessionId, {
149
+ type: 'user',
150
+ content: followUp,
151
+ });
152
+ }
153
+ // Query gossip layer for relevant insights from other agents
154
+ if (this.gossipLayer) {
155
+ await this.injectGossipInsights();
156
+ }
157
+ this.setPhase('build_context');
158
+ }
159
+ /**
160
+ * Query the gossip layer, score each insight, and inject adopted/test insights
161
+ * into the session as system messages.
162
+ */
163
+ async injectGossipInsights() {
164
+ if (!this.gossipLayer || !this.state.sessionId)
165
+ return;
166
+ const topic = this.state.config.expertise.join(', ');
167
+ let insights;
168
+ try {
169
+ insights = await this.gossipLayer.query(this.state.config.slug, topic);
170
+ }
171
+ catch {
172
+ // Gossip query failure is non-fatal; continue without insights
173
+ return;
174
+ }
175
+ if (insights.length === 0)
176
+ return;
177
+ const adopted = [];
178
+ const experimental = [];
179
+ for (const insight of insights) {
180
+ const sourceCredibility = this.credibilityTracker
181
+ ? this.credibilityTracker.getCredibility(insight.source)
182
+ : undefined;
183
+ const score = scoreInsight(insight, topic, sourceCredibility);
184
+ if (score.decision === 'adopt') {
185
+ adopted.push({ insight, score: score.total });
186
+ }
187
+ else if (score.decision === 'test') {
188
+ experimental.push({ insight, score: score.total });
189
+ }
190
+ // 'reject' insights are silently dropped
191
+ }
192
+ if (adopted.length > 0) {
193
+ const lines = adopted.map(a => `- [${a.insight.source}] (score ${a.score.toFixed(2)}): ${a.insight.content}`);
194
+ this.sessions.append(this.state.sessionId, {
195
+ type: 'system',
196
+ content: `[GOSSIP:ADOPTED] Trusted insights from other agents:\n${lines.join('\n')}`,
197
+ });
198
+ }
199
+ if (experimental.length > 0) {
200
+ const lines = experimental.map(e => `- [${e.insight.source}] (score ${e.score.toFixed(2)}): ${e.insight.content}`);
201
+ this.sessions.append(this.state.sessionId, {
202
+ type: 'system',
203
+ content: `[GOSSIP:TEST] Consider verifying these insights experimentally:\n${lines.join('\n')}`,
204
+ });
205
+ }
206
+ }
207
+ async streamLlm() {
208
+ this.setPhase('stream_llm');
209
+ const history = this.state.sessionId
210
+ ? this.sessions.getHistory(this.state.sessionId)
211
+ : [];
212
+ const messages = history.map(e => ({
213
+ role: e.type === 'user' ? 'user' : 'assistant',
214
+ content: e.content,
215
+ }));
216
+ if (messages.length === 0) {
217
+ messages.push({
218
+ role: 'system',
219
+ content: `You are ${this.state.config.name}. Expertise: ${this.state.config.expertise.join(', ')}.${this.state.config.personality ? ' ' + this.state.config.personality : ''}`,
220
+ });
221
+ }
222
+ this.abortController = new AbortController();
223
+ const availableTools = this.tools.list().filter(t => !this.state.config.tools || this.state.config.tools.includes(t.name));
224
+ let fullText = '';
225
+ this.pendingToolCall = null;
226
+ try {
227
+ for await (const chunk of this.streamFn(messages, availableTools)) {
228
+ if (this.abortController.signal.aborted)
229
+ break;
230
+ if (chunk.type === 'text' && chunk.content) {
231
+ fullText += chunk.content;
232
+ this.emit('message', chunk.content);
233
+ }
234
+ else if (chunk.type === 'tool_call' && chunk.toolName) {
235
+ this.pendingToolCall = {
236
+ toolName: chunk.toolName,
237
+ params: chunk.toolParams ?? {},
238
+ startedAt: Date.now(),
239
+ };
240
+ break;
241
+ }
242
+ }
243
+ }
244
+ catch (err) {
245
+ this.state.error = err instanceof Error ? err.message : String(err);
246
+ this.setPhase('error');
247
+ this.emit('error', this.state.error);
248
+ return;
249
+ }
250
+ if (fullText && this.state.sessionId) {
251
+ this.sessions.append(this.state.sessionId, {
252
+ type: 'assistant',
253
+ content: fullText,
254
+ });
255
+ }
256
+ }
257
+ async executeTool() {
258
+ if (!this.pendingToolCall) {
259
+ this.setPhase('stream_llm');
260
+ return;
261
+ }
262
+ this.setPhase('execute_tool');
263
+ const call = this.pendingToolCall;
264
+ this.emit('tool_call', call.toolName, call.params);
265
+ const tool = this.tools.get(call.toolName);
266
+ if (!tool) {
267
+ call.error = `Unknown tool: ${call.toolName}`;
268
+ call.completedAt = Date.now();
269
+ this.taskHadError = true;
270
+ if (this.state.sessionId) {
271
+ this.sessions.append(this.state.sessionId, {
272
+ type: 'tool_result',
273
+ content: call.error,
274
+ metadata: { toolName: call.toolName, error: true },
275
+ });
276
+ }
277
+ this.pendingToolCall = null;
278
+ return;
279
+ }
280
+ const validation = this.tools.validate(call.toolName, call.params);
281
+ if (!validation.valid) {
282
+ call.error = `Validation failed: ${validation.errors?.join(', ')}`;
283
+ call.completedAt = Date.now();
284
+ this.taskHadError = true;
285
+ if (this.state.sessionId) {
286
+ this.sessions.append(this.state.sessionId, {
287
+ type: 'tool_result',
288
+ content: call.error,
289
+ metadata: { toolName: call.toolName, error: true },
290
+ });
291
+ }
292
+ this.pendingToolCall = null;
293
+ return;
294
+ }
295
+ if (this.state.sessionId) {
296
+ this.sessions.append(this.state.sessionId, {
297
+ type: 'tool_call',
298
+ content: JSON.stringify({ tool: call.toolName, params: call.params }),
299
+ metadata: { toolName: call.toolName },
300
+ });
301
+ }
302
+ const controller = this.abortController ?? new AbortController();
303
+ try {
304
+ call.result = await tool.execute(call.params, controller.signal, (partial) => {
305
+ this.emit('message', partial);
306
+ });
307
+ call.completedAt = Date.now();
308
+ if (this.state.sessionId) {
309
+ this.sessions.append(this.state.sessionId, {
310
+ type: 'tool_result',
311
+ content: call.result,
312
+ metadata: { toolName: call.toolName },
313
+ });
314
+ }
315
+ }
316
+ catch (err) {
317
+ call.error = err instanceof Error ? err.message : String(err);
318
+ call.completedAt = Date.now();
319
+ this.taskHadError = true;
320
+ if (this.state.sessionId) {
321
+ this.sessions.append(this.state.sessionId, {
322
+ type: 'tool_result',
323
+ content: call.error,
324
+ metadata: { toolName: call.toolName, error: true },
325
+ });
326
+ }
327
+ }
328
+ // Collect insight from gossip_publish tool calls
329
+ if (call.toolName === 'nex_gossip_publish' && call.result && !call.error) {
330
+ const insight = call.params.insight;
331
+ if (typeof insight === 'string') {
332
+ this.collectedInsights.push(insight);
333
+ }
334
+ }
335
+ this.pendingToolCall = null;
336
+ }
337
+ async handleDone() {
338
+ // Check if there's more work from queues
339
+ if (this.queues.hasSteer(this.state.config.slug) || this.queues.hasFollowUp(this.state.config.slug)) {
340
+ this.setPhase('idle');
341
+ return;
342
+ }
343
+ // Publish any collected insights via gossip layer
344
+ if (this.gossipLayer && this.collectedInsights.length > 0) {
345
+ for (const insight of this.collectedInsights) {
346
+ try {
347
+ await this.gossipLayer.publish(this.state.config.slug, insight);
348
+ }
349
+ catch {
350
+ // Gossip publish failure is non-fatal
351
+ }
352
+ }
353
+ this.collectedInsights = [];
354
+ }
355
+ // Update credibility based on task outcome
356
+ if (this.credibilityTracker) {
357
+ this.credibilityTracker.recordOutcome(this.state.config.slug, !this.taskHadError);
358
+ }
359
+ this.setPhase('done');
360
+ this.state.lastHeartbeat = Date.now();
361
+ this.emit('done');
362
+ }
363
+ start() {
364
+ this.running = true;
365
+ this.paused = false;
366
+ if (this.state.phase === 'done' || this.state.phase === 'error') {
367
+ this.setPhase('idle');
368
+ }
369
+ }
370
+ stop() {
371
+ this.running = false;
372
+ this.paused = false;
373
+ if (this.abortController) {
374
+ this.abortController.abort();
375
+ }
376
+ this.setPhase('done');
377
+ }
378
+ pause() {
379
+ this.paused = true;
380
+ }
381
+ resume() {
382
+ this.paused = false;
383
+ }
384
+ /** Allow external code or tools to push insights for gossip publishing at done phase. */
385
+ addInsight(insight) {
386
+ this.collectedInsights.push(insight);
387
+ }
388
+ }
389
+ //# sourceMappingURL=loop.js.map