@minded-ai/mindedjs 1.0.19 → 1.0.21

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 (60) hide show
  1. package/dist/agent.js +13 -8
  2. package/dist/agent.js.map +1 -1
  3. package/dist/checkpointer/checkpointSaverFactory.d.ts +7 -0
  4. package/dist/checkpointer/checkpointSaverFactory.js +30 -0
  5. package/dist/checkpointer/checkpointSaverFactory.js.map +1 -0
  6. package/dist/edges/createPromptRouter.js +1 -1
  7. package/dist/edges/createPromptRouter.js.map +1 -1
  8. package/dist/platform/mindedCheckpointSaver.js +55 -10
  9. package/dist/platform/mindedCheckpointSaver.js.map +1 -1
  10. package/dist/platform/mindedConnection.d.ts +6 -1
  11. package/dist/platform/mindedConnection.js +92 -42
  12. package/dist/platform/mindedConnection.js.map +1 -1
  13. package/dist/platform/mindedConnectionTypes.d.ts +2 -0
  14. package/dist/platform/mindedConnectionTypes.js.map +1 -1
  15. package/dist/platform/mindedRequest.js +1 -1
  16. package/dist/platform/mindedRequest.js.map +1 -1
  17. package/docs/api-reference/classes/index.Agent.html +2 -2
  18. package/docs/api-reference/enums/index.EdgeType.html +2 -2
  19. package/docs/api-reference/enums/index.NodeType.html +2 -2
  20. package/docs/api-reference/enums/index.TriggerType.html +2 -2
  21. package/docs/api-reference/enums/index.events.html +2 -2
  22. package/docs/api-reference/hierarchy.html +1 -1
  23. package/docs/api-reference/index.html +3 -3
  24. package/docs/api-reference/interfaces/index.AppToolNode.html +2 -2
  25. package/docs/api-reference/interfaces/index.AppTriggerNode.html +2 -2
  26. package/docs/api-reference/interfaces/index.Flow.html +2 -2
  27. package/docs/api-reference/interfaces/index.JunctionNode.html +2 -2
  28. package/docs/api-reference/interfaces/index.LogicalConditionEdge.html +2 -2
  29. package/docs/api-reference/interfaces/index.ManualTriggerNode.html +2 -2
  30. package/docs/api-reference/interfaces/index.PromptConditionEdge.html +2 -2
  31. package/docs/api-reference/interfaces/index.PromptNode.html +2 -2
  32. package/docs/api-reference/interfaces/index.StepForwardEdge.html +2 -2
  33. package/docs/api-reference/interfaces/index.Tool.html +2 -2
  34. package/docs/api-reference/interfaces/index.ToolNode.html +2 -2
  35. package/docs/api-reference/modules/index-1.html +1 -1
  36. package/docs/api-reference/modules/index.html +1 -1
  37. package/docs/api-reference/modules.html +1 -1
  38. package/docs/api-reference/types/index.Edge.html +1 -1
  39. package/docs/api-reference/types/index.Node.html +1 -1
  40. package/docs/api-reference/types/index.TriggerNode.html +1 -1
  41. package/docs/examples/order-refund-flow.md +1 -1
  42. package/docs/getting-started/installation.md +3 -3
  43. package/examples/orderRefundAgent/flows/orderRefundFlow.yaml +3 -3
  44. package/examples/orderRefundAgent/orderRefundAgent.ts +9 -3
  45. package/package.json +4 -2
  46. package/src/agent.ts +15 -9
  47. package/src/checkpointer/checkpointSaverFactory.ts +31 -0
  48. package/src/edges/createPromptRouter.ts +1 -1
  49. package/src/platform/mindedCheckpointSaver.ts +75 -18
  50. package/src/platform/mindedConnection.ts +99 -55
  51. package/src/platform/mindedConnectionTypes.ts +4 -5
  52. package/src/platform/mindedRequest.ts +2 -1
  53. package/test/checkpoint-saver/minded-checkpoint-saver-list.test.ts +138 -0
  54. package/test/checkpoint-saver/minded-checkpoint-saver.test.ts +99 -0
  55. package/dist/analytics.d.ts +0 -6
  56. package/dist/analytics.js +0 -19
  57. package/dist/analytics.js.map +0 -1
  58. package/dist/infrastructure.ts/mindedRequest.d.ts +0 -8
  59. package/dist/infrastructure.ts/mindedRequest.js +0 -22
  60. package/dist/infrastructure.ts/mindedRequest.js.map +0 -1
@@ -1 +1 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>TriggerNode | @agentsforce/sdk</title><meta name="description" content="Documentation for @agentsforce/sdk"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@agentsforce/sdk</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/index.html">index</a></li><li><a href="" aria-current="page">TriggerNode</a></li></ul><h1>Type Alias TriggerNode</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">TriggerNode</span><span class="tsd-signature-symbol">:</span> <a href="../interfaces/index.AppTriggerNode.html" class="tsd-signature-type tsd-kind-interface">AppTriggerNode</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">WebhookTriggerNode</span> <span class="tsd-signature-symbol">|</span> <a href="../interfaces/index.ManualTriggerNode.html" class="tsd-signature-type tsd-kind-interface">ManualTriggerNode</a></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/agentsforce/mindedjs/blob/d3db8e73a98eb5a0ea8a43ace8e2bd5ceec39e5e/src/types/Flows.types.ts#L56">src/types/Flows.types.ts:56</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@agentsforce/sdk</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>TriggerNode | @minded-ai/mindedjs</title><meta name="description" content="Documentation for @minded-ai/mindedjs"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@minded-ai/mindedjs</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/index.html">index</a></li><li><a href="" aria-current="page">TriggerNode</a></li></ul><h1>Type Alias TriggerNode</h1></div><div class="tsd-signature"><span class="tsd-kind-type-alias">TriggerNode</span><span class="tsd-signature-symbol">:</span> <a href="../interfaces/index.AppTriggerNode.html" class="tsd-signature-type tsd-kind-interface">AppTriggerNode</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">WebhookTriggerNode</span> <span class="tsd-signature-symbol">|</span> <a href="../interfaces/index.ManualTriggerNode.html" class="tsd-signature-type tsd-kind-interface">ManualTriggerNode</a></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/agentsforce/mindedjs/blob/d3db8e73a98eb5a0ea8a43ace8e2bd5ceec39e5e/src/types/Flows.types.ts#L56">src/types/Flows.types.ts:56</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@minded-ai/mindedjs</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -517,7 +517,7 @@ export { agent, runRefundExample };
517
517
 
518
518
  1. **Install dependencies:**
519
519
  ```bash
520
- npm install @agentsforce/sdk langchain
520
+ npm install @minded-ai/mindedjs langchain
521
521
  ```
522
522
 
523
523
  2. **Set up environment:**
@@ -12,19 +12,19 @@ Get MindedJS up and running in your project.
12
12
  {% tabs %}
13
13
  {% tab title="npm" %}
14
14
  ```bash
15
- npm i @agentsforce/sdk langchain
15
+ npm i @minded-ai/mindedjs langchain
16
16
  ```
17
17
  {% endtab %}
18
18
 
19
19
  {% tab title="yarn" %}
20
20
  ```bash
21
- yarn add @agentsforce/sdk langchain
21
+ yarn add @minded-ai/mindedjs langchain
22
22
  ```
23
23
  {% endtab %}
24
24
 
25
25
  {% tab title="pnpm" %}
26
26
  ```bash
27
- pnpm add @agentsforce/sdk langchain
27
+ pnpm add @minded-ai/mindedjs langchain
28
28
  ```
29
29
  {% endtab %}
30
30
  {% endtabs %}
@@ -2,7 +2,7 @@ name: 'Order refund flow'
2
2
  nodes:
3
3
  - type: 'trigger'
4
4
  triggerType: 'manual'
5
- name: 'CLI Trigger'
5
+ name: 'New Direct Message (Instant)'
6
6
  - type: 'tool'
7
7
  name: 'Refund order'
8
8
  toolName: 'refundOrder'
@@ -17,9 +17,9 @@ nodes:
17
17
  llmConfig:
18
18
  name: 'ChatOpenAI'
19
19
  properties:
20
- model: 'o3'
20
+ model: 'gpt-4o'
21
21
  edges:
22
- - source: 'CLI Trigger'
22
+ - source: 'New Direct Message (Instant)'
23
23
  target: 'Prompt'
24
24
  type: 'stepForward'
25
25
  - source: 'Prompt'
@@ -10,6 +10,7 @@ const agent = new Agent({
10
10
  memorySchema,
11
11
  config: mindedConfig,
12
12
  tools,
13
+ platformToken: '123',
13
14
  });
14
15
 
15
16
  agent.on(events.AI_MESSAGE, async ({ message }) => {
@@ -17,12 +18,17 @@ agent.on(events.AI_MESSAGE, async ({ message }) => {
17
18
  });
18
19
 
19
20
  agent.on(events.TRIGGER_EVENT, async ({ triggerName, triggerBody }) => {
20
- if (triggerName === 'CLI Trigger') {
21
+ if (triggerName == 'onMessage') {
22
+ const text = triggerBody?.content;
21
23
  return {
22
24
  memory: {},
23
- messages: [new HumanMessage(triggerBody)],
25
+ messages: [new HumanMessage({ content: text, response_metadata: {} })],
24
26
  };
25
27
  }
28
+ return {
29
+ memory: {},
30
+ messages: [new HumanMessage({ content: triggerBody?.event?.text || triggerBody?.text || 'Empty message', response_metadata: {} })],
31
+ };
26
32
  });
27
33
 
28
34
  const sendMessage = async (message: string) => {
@@ -49,7 +55,7 @@ if (process.env.NO_PLATFORM_CONNECT === 'true') {
49
55
 
50
56
  await agent.invoke({
51
57
  triggerBody: userInput,
52
- triggerName: 'CLI Trigger',
58
+ triggerName: 'New Direct Message (Instant)',
53
59
  sessionId: 'cli-session',
54
60
  });
55
61
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@minded-ai/mindedjs",
3
- "version": "1.0.19",
4
- "description": "",
3
+ "version": "1.0.21",
4
+ "description": "MindedJS is a TypeScript library for building agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
@@ -21,12 +21,14 @@
21
21
  "@types/chai": "^4.3.11",
22
22
  "@types/mocha": "^10.0.6",
23
23
  "@types/node": "^20.11.19",
24
+ "@types/sinon": "^17.0.4",
24
25
  "chai": "^4.3.10",
25
26
  "dotenv": "^16.4.5",
26
27
  "eslint": "^9.27.0",
27
28
  "globals": "^16.2.0",
28
29
  "mocha": "^10.3.0",
29
30
  "nodemon": "^3.1.10",
31
+ "sinon": "^20.0.0",
30
32
  "ts-node": "^10.9.2",
31
33
  "typedoc": "^0.28.5",
32
34
  "typescript": "^5.3.3",
package/src/agent.ts CHANGED
@@ -3,7 +3,7 @@ import { Tool } from './types/Tools.types';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
4
  import { BaseLanguageModel } from '@langchain/core/language_models/base';
5
5
  import { Command, StateGraph } from '@langchain/langgraph';
6
- import { MemorySaver, BaseCheckpointSaver } from '@langchain/langgraph';
6
+ import { BaseCheckpointSaver } from '@langchain/langgraph';
7
7
  import { nodeFactory } from './nodes/nodeFactory';
8
8
  import { CompiledGraph, PreCompiledGraph, stateAnnotation } from './types/LangGraph.types';
9
9
  import { edgeFactory } from './edges/edgeFactory';
@@ -11,7 +11,7 @@ import { AgentEventRequestPayloads, AgentEventResponsePayloads, AgentEvents } fr
11
11
  import { z } from 'zod';
12
12
 
13
13
  import { MindedConnection } from './platform/mindedConnection';
14
- import { MindedConnectionSocketMessageType } from './platform/mindedConnectionTypes';
14
+ import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType, OnAppTrigger } from './platform/mindedConnectionTypes';
15
15
  import * as fs from 'fs';
16
16
  import * as path from 'path';
17
17
  import * as yaml from 'js-yaml';
@@ -19,6 +19,7 @@ import { MindedSDKConfig } from './types/Agent.types';
19
19
  import { createLlmInstance } from './llm/createLlmInstance';
20
20
  import { config } from 'dotenv';
21
21
  import { resolve } from 'path';
22
+ import { createCheckpointSaver } from './checkpointer/checkpointSaverFactory';
22
23
 
23
24
  config({ path: resolve(__dirname, '../.env') });
24
25
 
@@ -55,15 +56,20 @@ export class Agent {
55
56
  this.tools = tools;
56
57
  this.platformToken = platformToken;
57
58
  this.llm = createLlmInstance(config.llm);
58
- this.checkpointer = memorySaver || new MemorySaver();
59
+ this.checkpointer = memorySaver || createCheckpointSaver('');
59
60
  this.validate();
60
61
  this.compiledGraph = this.initializeGraph();
61
62
 
62
63
  if (process.env.NODE_ENV !== 'test' && process.env.NO_PLATFORM_CONNECT !== 'true') {
63
64
  this.mindedConnection = new MindedConnection();
64
65
  this.mindedConnection.start();
65
- this.mindedConnection.on(MindedConnectionSocketMessageType.OnAppTrigger, (trigger) => {
66
- console.log('Received trigger:', trigger);
66
+ this.mindedConnection.on(MindedConnectionSocketMessageType.OnAppTrigger, async (message: BaseMindedConnectionSocketMessage) => {
67
+ const trigger = message as OnAppTrigger;
68
+ await this.invoke({
69
+ triggerBody: trigger.body,
70
+ triggerName: trigger.name,
71
+ sessionId: trigger.cnvId,
72
+ });
67
73
  });
68
74
  }
69
75
  }
@@ -168,10 +174,10 @@ export class Agent {
168
174
  const messages = handlerResult?.messages ?? [];
169
175
  console.log(`Invoking trigger ${triggerName} with session ${session}`);
170
176
  const config = { configurable: { thread_id: session, recursionLimit: 3 } };
171
- const triggerNode = this.compiledGraph.builder.nodes[triggerName];
172
- if (!triggerNode) {
173
- throw new Error(`Trigger node not found: ${triggerName}`);
174
- }
177
+ // const triggerNode = this.compiledGraph.builder.nodes[triggerName];
178
+ // if (!triggerNode) {
179
+ // throw new Error(`Trigger node not found: ${triggerName}`);
180
+ // }
175
181
  const state = await this.compiledGraph.getState(config);
176
182
  // Resume interruption
177
183
  if (state.tasks?.[0]?.interrupts?.length > 0) {
@@ -0,0 +1,31 @@
1
+ import { BaseCheckpointSaver, MemorySaver } from '@langchain/langgraph';
2
+ import { MindedCheckpointSaver } from '../platform/mindedCheckpointSaver';
3
+
4
+ /**
5
+ * Factory function to create the appropriate checkpoint saver based on environment variables
6
+ * @param platformToken - Optional platform token for remote checkpoint saving
7
+ * @returns BaseCheckpointSaver instance (either MemorySaver or MindedCheckpointSaver)
8
+ */
9
+ export function createCheckpointSaver(platformToken: string): BaseCheckpointSaver {
10
+ const useRemoteCheckpointSaver = process.env.REMOTE_CHECKPOINT_SAVER === 'true';
11
+
12
+ if (!useRemoteCheckpointSaver || process.env.NODE_ENV === 'test') {
13
+ console.log('Using in-memory checkpoint saver');
14
+ return new MemorySaver();
15
+ }
16
+
17
+ // // If not using in-memory, check for platform token and MINDED_SERVER
18
+ // if (!platformToken) {
19
+ // console.warn('No platform token provided, falling back to in-memory checkpoint saver');
20
+ // return new MemorySaver();
21
+ // }
22
+
23
+ const mindedServer = process.env.MINDED_SERVER;
24
+ if (!mindedServer) {
25
+ console.warn('MINDED_SERVER environment variable not set, falling back to in-memory checkpoint saver');
26
+ return new MemorySaver();
27
+ }
28
+
29
+ console.log(`Using remote checkpoint saver with server: ${mindedServer}`);
30
+ return new MindedCheckpointSaver(platformToken);
31
+ }
@@ -25,7 +25,7 @@ Your task is to analyze the current memory state, history and available nodes an
25
25
 
26
26
 
27
27
  Available nodes in the format of {nodeId}: {prompt}:
28
- ${edges.map((edge) => `- ${edge.target}: ${edge.prompt}`).join('\n')}
28
+ ${edges.map((edge) => `- {${edge.target}}: {${edge.prompt}}`).join('\n')}
29
29
 
30
30
  Current memory state:
31
31
  ${JSON.stringify(state.memory)}
@@ -6,6 +6,7 @@ import {
6
6
  ChannelVersions,
7
7
  PendingWrite,
8
8
  CheckpointListOptions,
9
+ CheckpointPendingWrite,
9
10
  } from '@langchain/langgraph-checkpoint';
10
11
  import type { RunnableConfig } from '@langchain/core/runnables';
11
12
  import { mindedRequest } from './mindedRequest';
@@ -16,26 +17,82 @@ export class MindedCheckpointSaver extends BaseCheckpointSaver<number> {
16
17
  }
17
18
 
18
19
  async getTuple(config: RunnableConfig<Record<string, any>>): Promise<CheckpointTuple | undefined> {
19
- return await mindedRequest<CheckpointTuple | undefined, { config: RunnableConfig<Record<string, any>> }>({
20
- path: '/checkpoint/get',
20
+ const response = await mindedRequest<{ tuple: CheckpointTuple | undefined }, { config: RunnableConfig<Record<string, any>> }>({
21
+ path: '/sdk-checkpoints/getTuple',
21
22
  method: 'POST',
22
23
  body: { config },
23
24
  token: this.token,
24
25
  });
26
+
27
+ if (!response.tuple) {
28
+ return undefined;
29
+ }
30
+
31
+ const tuple = response.tuple;
32
+
33
+ // Re-serialize and deserialize checkpoint to restore class information
34
+ const [checkpointType, serializedCheckpoint] = this.serde.dumpsTyped(tuple.checkpoint);
35
+ const checkpoint = (await this.serde.loadsTyped(checkpointType, serializedCheckpoint)) as Checkpoint;
36
+
37
+ // Re-serialize and deserialize metadata to restore class information
38
+ const metadata = tuple.metadata
39
+ ? (() => {
40
+ const [metadataType, serializedMetadata] = this.serde.dumpsTyped(tuple.metadata);
41
+ return this.serde.loadsTyped(metadataType, serializedMetadata) as CheckpointMetadata;
42
+ })()
43
+ : undefined;
44
+
45
+ // Re-serialize and deserialize pending writes to restore class information
46
+ const pendingWrites: CheckpointPendingWrite[] = tuple.pendingWrites
47
+ ? await Promise.all(
48
+ tuple.pendingWrites.map(async (write) => {
49
+ const [taskId, channel, value] = write;
50
+ const [valueType, serializedValue] = this.serde.dumpsTyped(value);
51
+ const deserializedValue = await this.serde.loadsTyped(valueType, serializedValue);
52
+ return [taskId, channel, deserializedValue] as CheckpointPendingWrite;
53
+ }),
54
+ )
55
+ : [];
56
+
57
+ return {
58
+ config: tuple.config,
59
+ checkpoint,
60
+ metadata: await metadata,
61
+ parentConfig: tuple.parentConfig,
62
+ pendingWrites,
63
+ };
25
64
  }
26
65
 
27
66
  async *list(config: RunnableConfig<Record<string, any>>, options?: CheckpointListOptions): AsyncGenerator<CheckpointTuple, any, any> {
28
- const tuples = await mindedRequest<CheckpointTuple[], { config: RunnableConfig<Record<string, any>>; options?: CheckpointListOptions }>(
29
- {
30
- path: '/checkpoint/list',
31
- method: 'POST',
32
- body: { config, options },
33
- token: this.token,
34
- },
35
- );
67
+ const response = await mindedRequest<
68
+ { checkpoints: CheckpointTuple[] },
69
+ { config: RunnableConfig<Record<string, any>>; options?: CheckpointListOptions }
70
+ >({
71
+ path: '/sdk-checkpoints/list',
72
+ method: 'POST',
73
+ body: { config, options },
74
+ token: this.token,
75
+ });
76
+
77
+ for (const tuple of response.checkpoints) {
78
+ // Re-serialize and deserialize checkpoint to restore class information
79
+ const [checkpointType, serializedCheckpoint] = this.serde.dumpsTyped(tuple.checkpoint);
80
+ const checkpoint = (await this.serde.loadsTyped(checkpointType, serializedCheckpoint)) as Checkpoint;
81
+
82
+ // Re-serialize and deserialize metadata to restore class information
83
+ const metadata = tuple.metadata
84
+ ? (() => {
85
+ const [metadataType, serializedMetadata] = this.serde.dumpsTyped(tuple.metadata);
86
+ return this.serde.loadsTyped(metadataType, serializedMetadata) as CheckpointMetadata;
87
+ })()
88
+ : undefined;
36
89
 
37
- for (const tuple of tuples) {
38
- yield tuple;
90
+ yield {
91
+ config: tuple.config,
92
+ checkpoint,
93
+ metadata: await metadata,
94
+ parentConfig: tuple.parentConfig,
95
+ };
39
96
  }
40
97
  }
41
98
 
@@ -45,8 +102,8 @@ export class MindedCheckpointSaver extends BaseCheckpointSaver<number> {
45
102
  metadata: CheckpointMetadata,
46
103
  newVersions: ChannelVersions,
47
104
  ): Promise<RunnableConfig<Record<string, any>>> {
48
- const newConfig = await mindedRequest<
49
- RunnableConfig<Record<string, any>>,
105
+ const response = await mindedRequest<
106
+ { config: RunnableConfig<Record<string, any>> },
50
107
  {
51
108
  config: RunnableConfig<Record<string, any>>;
52
109
  checkpoint: Checkpoint<string, string>;
@@ -54,18 +111,18 @@ export class MindedCheckpointSaver extends BaseCheckpointSaver<number> {
54
111
  newVersions: ChannelVersions;
55
112
  }
56
113
  >({
57
- path: '/checkpoint/put',
114
+ path: '/sdk-checkpoints/put',
58
115
  method: 'POST',
59
116
  body: { config, checkpoint, metadata, newVersions },
60
117
  token: this.token,
61
118
  });
62
119
 
63
- return newConfig;
120
+ return response.config;
64
121
  }
65
122
 
66
123
  async putWrites(config: RunnableConfig<Record<string, any>>, writes: PendingWrite[], taskId: string): Promise<void> {
67
- await mindedRequest<void, { config: RunnableConfig<Record<string, any>>; writes: PendingWrite[]; taskId: string }>({
68
- path: '/checkpoint/put-writes',
124
+ await mindedRequest({
125
+ path: '/sdk-checkpoints/putWrites',
69
126
  method: 'POST',
70
127
  body: { config, writes, taskId },
71
128
  token: this.token,
@@ -1,106 +1,150 @@
1
1
  import { io, Socket } from 'socket.io-client';
2
2
  import * as readline from 'readline';
3
3
  import { BaseMindedConnectionSocketMessage, MindedConnectionSocketMessageType } from './mindedConnectionTypes';
4
+ import * as fs from 'fs';
5
+ import * as path from 'path';
4
6
 
5
7
  export class MindedConnection {
6
8
  private socket: Socket | null = null;
7
9
  private rl: readline.Interface | null = null;
10
+ private readonly tokenPath = path.join(process.cwd(), '.minded-token');
8
11
  listeners: {
9
- [key: string]: ((message: BaseMindedConnectionSocketMessage) => void)[]
12
+ [key: string]: ((message: BaseMindedConnectionSocketMessage) => void)[];
10
13
  } = {};
11
14
 
12
15
  constructor() {
13
- if (!process.env.MINDED_CONNECTION_TOKEN) {
14
- this.rl = readline.createInterface({
15
- input: process.stdin,
16
- output: process.stdout
17
- });
16
+ if (!process.env.MINDED_CONNECTION_TOKEN && !this.getSavedToken()) {
17
+ this.initializeReadline();
18
+ }
19
+ }
20
+
21
+ private initializeReadline() {
22
+ this.rl = readline.createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ });
26
+ }
27
+
28
+ private getSavedToken(): string | null {
29
+ try {
30
+ if (fs.existsSync(this.tokenPath)) {
31
+ return fs.readFileSync(this.tokenPath, 'utf8').trim();
32
+ }
33
+ } catch (error) {
34
+ console.error('Error reading token file:', error);
35
+ }
36
+ return null;
37
+ }
38
+
39
+ private saveToken(token: string): void {
40
+ try {
41
+ fs.writeFileSync(this.tokenPath, token);
42
+ } catch (error) {
43
+ console.error('Error saving token:', error);
18
44
  }
19
45
  }
20
46
 
21
47
  private async getMindedToken(): Promise<string> {
22
48
  const envToken = process.env.MINDED_CONNECTION_TOKEN;
23
-
24
49
  if (envToken) {
50
+ this.saveToken(envToken);
25
51
  return envToken;
26
52
  }
27
53
 
54
+ const savedToken = this.getSavedToken();
55
+ if (savedToken) {
56
+ return savedToken;
57
+ }
58
+
59
+ if (!this.rl) {
60
+ this.initializeReadline();
61
+ }
62
+
28
63
  return new Promise((resolve) => {
29
64
  this.rl!.question('Enter your Minded connection token: ', (token: string) => {
30
- resolve(token);
65
+ this.saveToken(token.trim());
66
+ resolve(token.trim());
31
67
  });
32
68
  });
33
69
  }
34
70
 
35
- public on = (
36
- event: MindedConnectionSocketMessageType,
37
- callback: (message: BaseMindedConnectionSocketMessage) => void,
38
- ) => {
71
+ public on = (event: MindedConnectionSocketMessageType, callback: (message: BaseMindedConnectionSocketMessage) => void) => {
39
72
  if (!this.listeners[event]) {
40
73
  this.listeners[event] = [];
41
74
  }
42
75
  this.listeners[event].push(callback);
43
76
  };
44
77
 
45
-
46
- public emit = (
47
- event: MindedConnectionSocketMessageType,
48
- message: BaseMindedConnectionSocketMessage,
49
- ) => {
78
+ public emit = (event: MindedConnectionSocketMessageType, message: BaseMindedConnectionSocketMessage) => {
50
79
  if (this.socket) {
51
80
  this.socket.emit(event, message);
52
81
  }
53
82
  };
54
83
 
84
+ private async connect(token: string) {
85
+ this.socket = io('http://localhost:8888', {
86
+ path: '/minded-connect',
87
+ query: {
88
+ token,
89
+ },
90
+ });
55
91
 
56
- public start(): void {
57
- this.getMindedToken().then(token => {
58
- this.socket = io('http://localhost:8888', {
59
- path: '/minded-connect',
60
- query: {
61
- token
62
- }
63
- });
64
-
65
- // Connection event handlers
66
- this.socket.on('connect', () => {
67
- console.log('\x1b[32mConnection with Minded platform is live!\x1b[0m');
68
- console.log('\x1b[36mPress Ctrl+C to exit.\x1b[0m');
69
- });
92
+ // Connection event handlers
93
+ this.socket.on('connect', () => {
94
+ console.log('\x1b[32mConnection with Minded platform is live!\x1b[0m');
95
+ console.log('\x1b[36mPress Ctrl+C to exit.\x1b[0m');
96
+ });
70
97
 
71
- this.socket.on('connect_error', () => {
72
- console.error('Failed to connect to minded platform');
73
- });
98
+ this.socket.on('connect_error', () => {
99
+ console.error('Failed to connect to minded platform');
100
+ });
74
101
 
75
- this.socket.on('disconnect', () => {
76
- console.log('Disconnected from local debugging socket');
102
+ this.socket.on('disconnect', () => {
103
+ console.log('Disconnected from local debugging socket');
104
+ });
77
105
 
78
- });
106
+ // Listen for error messages from the server
107
+ this.socket.on('error', async (error: { message: string }) => {
108
+ console.error('Server error:', error.message);
79
109
 
80
- // Listen for error messages from the server
81
- this.socket.on('error', (error: { message: string }) => {
82
- console.error('Server error:', error.message);
83
- });
84
-
85
- // Listen for specific message types
86
- this.socket.onAny((event, message) => {
87
- if (this.listeners[event]) {
88
- this.listeners[event].forEach((listener) => {
89
- listener(message);
90
- });
110
+ if (error.message.includes('Invalid token')) {
111
+ // Delete saved token on connection error
112
+ if (fs.existsSync(this.tokenPath)) {
113
+ fs.unlinkSync(this.tokenPath);
91
114
  }
92
- });
93
115
 
94
- // Handle process termination
95
- process.on('SIGINT', () => {
116
+ // Disconnect current socket
96
117
  if (this.socket?.connected) {
97
- console.log('\nDisconnecting...');
98
118
  this.socket.disconnect();
99
119
  }
100
- process.exit(0);
101
- });
102
120
 
121
+ // Get new token and reconnect
122
+ const newToken = await this.getMindedToken();
123
+ await this.connect(newToken);
124
+ }
125
+ });
126
+
127
+ // Listen for specific message types
128
+ this.socket.onAny((event, message) => {
129
+ if (this.listeners[event]) {
130
+ this.listeners[event].forEach((listener) => {
131
+ listener(message);
132
+ });
133
+ }
134
+ });
135
+
136
+ // Handle process termination
137
+ process.on('SIGINT', () => {
138
+ if (this.socket?.connected) {
139
+ console.log('\nDisconnecting...');
140
+ this.socket.disconnect();
141
+ }
142
+ process.exit(0);
103
143
  });
144
+ }
104
145
 
146
+ public async start(): Promise<void> {
147
+ const token = await this.getMindedToken();
148
+ await this.connect(token);
105
149
  }
106
- }
150
+ }
@@ -1,5 +1,4 @@
1
-
2
- export enum MindedConnectionSocketMessageType {
1
+ export enum MindedConnectionSocketMessageType {
3
2
  OnAppTrigger = 'on-app-trigger',
4
3
  }
5
4
 
@@ -7,9 +6,9 @@ export interface BaseMindedConnectionSocketMessage {
7
6
  type: MindedConnectionSocketMessageType;
8
7
  }
9
8
 
10
- export interface OnAppTrigger extends BaseMindedConnectionSocketMessage {
9
+ export interface OnAppTrigger extends BaseMindedConnectionSocketMessage {
11
10
  name: string;
11
+ agentId: string;
12
12
  body: Record<string, any>;
13
+ cnvId: string;
13
14
  }
14
-
15
-
@@ -1,5 +1,4 @@
1
1
  import axios from 'axios';
2
- const baseUrl = 'https://api.minded.com/sdk';
3
2
 
4
3
  type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
5
4
 
@@ -14,6 +13,8 @@ export const mindedRequest = async <Response, Request = object>({
14
13
  body: Request;
15
14
  token: string;
16
15
  }): Promise<Response> => {
16
+ const baseUrl = process.env.MINDED_SERVER || 'https://api.minded.com/sdk';
17
+
17
18
  const response = await axios({
18
19
  method,
19
20
  url: `${baseUrl}${path}`,