@minded-ai/mindedjs 1.0.102 → 1.0.103-beta-2
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.
- package/dist/agent.d.ts +4 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +68 -9
- package/dist/agent.js.map +1 -1
- package/dist/cli/index.js +14 -14
- package/dist/cli/index.js.map +1 -1
- package/dist/edges/edgeFactory.js +2 -2
- package/dist/edges/edgeFactory.js.map +1 -1
- package/dist/interrupts/BaseInterruptSessionManager.d.ts +51 -0
- package/dist/interrupts/BaseInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/BaseInterruptSessionManager.js +39 -0
- package/dist/interrupts/BaseInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/InterruptSessionManager.types.d.ts +36 -0
- package/dist/interrupts/InterruptSessionManager.types.d.ts.map +1 -0
- package/dist/interrupts/InterruptSessionManager.types.js +40 -0
- package/dist/interrupts/InterruptSessionManager.types.js.map +1 -0
- package/dist/interrupts/MemoryInterruptSessionManager.d.ts +14 -0
- package/dist/interrupts/MemoryInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/MemoryInterruptSessionManager.js +56 -0
- package/dist/interrupts/MemoryInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/MindedInterruptSessionManager.d.ts +13 -0
- package/dist/interrupts/MindedInterruptSessionManager.d.ts.map +1 -0
- package/dist/interrupts/MindedInterruptSessionManager.js +156 -0
- package/dist/interrupts/MindedInterruptSessionManager.js.map +1 -0
- package/dist/interrupts/interruptSessionManagerFactory.d.ts +3 -0
- package/dist/interrupts/interruptSessionManagerFactory.d.ts.map +1 -0
- package/dist/interrupts/interruptSessionManagerFactory.js +56 -0
- package/dist/interrupts/interruptSessionManagerFactory.js.map +1 -0
- package/dist/nodes/addAppToolNode.js +1 -1
- package/dist/nodes/addBrowserTaskNode.d.ts.map +1 -1
- package/dist/nodes/addBrowserTaskNode.js +2 -0
- package/dist/nodes/addBrowserTaskNode.js.map +1 -1
- package/dist/nodes/addBrowserTaskRunNode.d.ts.map +1 -1
- package/dist/nodes/addBrowserTaskRunNode.js +7 -3
- package/dist/nodes/addBrowserTaskRunNode.js.map +1 -1
- package/dist/nodes/addHumanInTheLoopNode.d.ts.map +1 -1
- package/dist/nodes/addHumanInTheLoopNode.js +2 -1
- package/dist/nodes/addHumanInTheLoopNode.js.map +1 -1
- package/dist/nodes/addJumpToNode.js +1 -1
- package/dist/nodes/addJumpToNode.js.map +1 -1
- package/dist/nodes/addPromptNode.d.ts.map +1 -1
- package/dist/nodes/addPromptNode.js +45 -1
- package/dist/nodes/addPromptNode.js.map +1 -1
- package/dist/nodes/addToolRunNode.d.ts.map +1 -1
- package/dist/nodes/addToolRunNode.js +1 -0
- package/dist/nodes/addToolRunNode.js.map +1 -1
- package/dist/platform/mindedChatOpenAI.d.ts +5 -0
- package/dist/platform/mindedChatOpenAI.d.ts.map +1 -0
- package/dist/platform/mindedChatOpenAI.js +23 -0
- package/dist/platform/mindedChatOpenAI.js.map +1 -0
- package/dist/platform/mindedConnection.d.ts.map +1 -1
- package/dist/platform/mindedConnection.js +12 -12
- package/dist/platform/mindedConnection.js.map +1 -1
- package/dist/platform/mindedConnectionTypes.d.ts +151 -1
- package/dist/platform/mindedConnectionTypes.d.ts.map +1 -1
- package/dist/platform/mindedConnectionTypes.js +9 -0
- package/dist/platform/mindedConnectionTypes.js.map +1 -1
- package/dist/playbooks/playbooks.js +6 -6
- package/dist/playbooks/playbooks.js.map +1 -1
- package/dist/types/Agent.types.d.ts +2 -0
- package/dist/types/Agent.types.d.ts.map +1 -1
- package/dist/types/Agent.types.js.map +1 -1
- package/dist/types/LangGraph.types.d.ts +2 -2
- package/dist/types/LangGraph.types.d.ts.map +1 -1
- package/dist/types/LangGraph.types.js +3 -1
- package/dist/types/LangGraph.types.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +1 -0
- package/dist/utils/logger.js.map +1 -1
- package/docs/getting-started/installation.md +0 -42
- package/package.json +2 -2
- package/src/agent.ts +86 -13
- package/src/cli/index.ts +14 -14
- package/src/edges/edgeFactory.ts +2 -2
- package/src/interrupts/BaseInterruptSessionManager.ts +94 -0
- package/src/interrupts/MemoryInterruptSessionManager.ts +57 -0
- package/src/interrupts/MindedInterruptSessionManager.ts +155 -0
- package/src/interrupts/interruptSessionManagerFactory.ts +20 -0
- package/src/nodes/addAppToolNode.ts +1 -1
- package/src/nodes/addBrowserTaskNode.ts +3 -1
- package/src/nodes/addBrowserTaskRunNode.ts +8 -6
- package/src/nodes/addHumanInTheLoopNode.ts +2 -1
- package/src/nodes/addJumpToNode.ts +1 -1
- package/src/nodes/addPromptNode.ts +50 -6
- package/src/nodes/addToolRunNode.ts +1 -1
- package/src/platform/mindedConnection.ts +15 -25
- package/src/platform/mindedConnectionTypes.ts +188 -1
- package/src/playbooks/playbooks.ts +6 -6
- package/src/types/Agent.types.ts +2 -0
- package/src/types/LangGraph.types.ts +3 -1
- package/src/utils/logger.ts +1 -0
|
@@ -5,7 +5,7 @@ export declare const createStateAnnotation: <Memory = any>() => import("@langcha
|
|
|
5
5
|
messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
|
|
6
6
|
memory: import("@langchain/langgraph").BinaryOperatorAggregate<Memory, Memory>;
|
|
7
7
|
history: import("@langchain/langgraph").BinaryOperatorAggregate<HistoryStep[], HistoryStep[]>;
|
|
8
|
-
sessionId: import("@langchain/langgraph").
|
|
8
|
+
sessionId: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
|
|
9
9
|
goto: import("@langchain/langgraph").BinaryOperatorAggregate<string | null | undefined, string | null | undefined>;
|
|
10
10
|
sessionType: import("@langchain/langgraph").BinaryOperatorAggregate<SessionType, SessionType>;
|
|
11
11
|
overrideStartFromNodeId: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
@@ -14,7 +14,7 @@ export declare const stateAnnotation: import("@langchain/langgraph").AnnotationR
|
|
|
14
14
|
messages: import("@langchain/langgraph").BinaryOperatorAggregate<BaseMessage[], BaseMessage[]>;
|
|
15
15
|
memory: import("@langchain/langgraph").BinaryOperatorAggregate<any, any>;
|
|
16
16
|
history: import("@langchain/langgraph").BinaryOperatorAggregate<HistoryStep[], HistoryStep[]>;
|
|
17
|
-
sessionId: import("@langchain/langgraph").
|
|
17
|
+
sessionId: import("@langchain/langgraph").BinaryOperatorAggregate<string, string>;
|
|
18
18
|
goto: import("@langchain/langgraph").BinaryOperatorAggregate<string | null | undefined, string | null | undefined>;
|
|
19
19
|
sessionType: import("@langchain/langgraph").BinaryOperatorAggregate<SessionType, SessionType>;
|
|
20
20
|
overrideStartFromNodeId: import("@langchain/langgraph").BinaryOperatorAggregate<string | null, string | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LangGraph.types.d.ts","sourceRoot":"","sources":["../../src/types/LangGraph.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAc,kBAAkB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAAI,MAAM,GAAG,GAAG;;;;;;;;
|
|
1
|
+
{"version":3,"file":"LangGraph.types.d.ts","sourceRoot":"","sources":["../../src/types/LangGraph.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAc,kBAAkB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAAI,MAAM,GAAG,GAAG;;;;;;;;EA2C9C,CAAC;AAGL,eAAO,MAAM,eAAe;;;;;;;;EAA0B,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AACjE,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AAC5D,MAAM,MAAM,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -32,7 +32,9 @@ const createStateAnnotation = () => langgraph_1.Annotation.Root({
|
|
|
32
32
|
default: () => [],
|
|
33
33
|
reducer: (a, b) => a.concat(b),
|
|
34
34
|
}),
|
|
35
|
-
sessionId: (0, langgraph_1.Annotation)(
|
|
35
|
+
sessionId: (0, langgraph_1.Annotation)({
|
|
36
|
+
reducer: (a, b) => b || a,
|
|
37
|
+
}),
|
|
36
38
|
goto: (0, langgraph_1.Annotation)({
|
|
37
39
|
default: () => null,
|
|
38
40
|
reducer: (a, b) => b,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LangGraph.types.js","sourceRoot":"","sources":["../../src/types/LangGraph.types.ts"],"names":[],"mappings":";;;AACA,oDAAkF;AAClF,+CAAyD;AAElD,MAAM,qBAAqB,GAAG,GAAiB,EAAE,CACtD,sBAAU,CAAC,IAAI,CAAC;IACd,QAAQ,EAAE,IAAA,sBAAU,EAAqB;QACvC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;QACjB,OAAO,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;;YACrC,MAAM,GAAG,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;YAC9B,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;gBAClC,IAAI,MAAA,OAAO,CAAC,iBAAiB,0CAAE,MAAM,EAAE,CAAC;oBACtC,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;oBAChE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;wBACjB,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;wBACrC,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;oBACnG,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;IACF,MAAM,EAAE,IAAA,sBAAU,EAAS;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAa,CAAA;QAC7B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;KACpC,CAAC;IACF,OAAO,EAAE,IAAA,sBAAU,EAAqB;QACtC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;KAC/B,CAAC;IACF,SAAS,EAAE,IAAA,sBAAU,
|
|
1
|
+
{"version":3,"file":"LangGraph.types.js","sourceRoot":"","sources":["../../src/types/LangGraph.types.ts"],"names":[],"mappings":";;;AACA,oDAAkF;AAClF,+CAAyD;AAElD,MAAM,qBAAqB,GAAG,GAAiB,EAAE,CACtD,sBAAU,CAAC,IAAI,CAAC;IACd,QAAQ,EAAE,IAAA,sBAAU,EAAqB;QACvC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;QACjB,OAAO,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;;YACrC,MAAM,GAAG,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;YAC9B,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;gBAClC,IAAI,MAAA,OAAO,CAAC,iBAAiB,0CAAE,MAAM,EAAE,CAAC;oBACtC,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,CAAC,CAAC;oBAChE,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;wBACjB,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;wBACrC,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,iBAAiB,EAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;oBACnG,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;IACF,MAAM,EAAE,IAAA,sBAAU,EAAS;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAa,CAAA;QAC7B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;KACpC,CAAC;IACF,OAAO,EAAE,IAAA,sBAAU,EAAqB;QACtC,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;QACjB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;KAC/B,CAAC;IACF,SAAS,EAAE,IAAA,sBAAU,EAAS;QAC5B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;KAC1B,CAAC;IACF,IAAI,EAAE,IAAA,sBAAU,EAA4B;QAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;QACnB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;KACrB,CAAC;IACF,WAAW,EAAE,IAAA,sBAAU,EAAc;QACnC,OAAO,EAAE,GAAG,EAAE,CAAC,yBAAW,CAAC,IAAI;QAC/B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC;KAC1B,CAAC;IACF,uBAAuB,EAAE,IAAA,sBAAU,EAAgB;QACjD,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI;QACnB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;KACrB,CAAC;CACH,CAAC,CAAC;AA3CQ,QAAA,qBAAqB,yBA2C7B;AAEL,gDAAgD;AACnC,QAAA,eAAe,GAAG,IAAA,6BAAqB,GAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,MAAM,uCAiBjB,CAAC"}
|
package/dist/utils/logger.js
CHANGED
package/dist/utils/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,oDAA4B;AAC5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,gDAAgD;AACnC,QAAA,MAAM,GAAG,IAAA,cAAI,EAAC;IACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO;IACvC,IAAI,EAAE,IAAI;IACV,SAAS,EAAE;QACT,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI;YACV,aAAa,EAAE,cAAc;
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,oDAA4B;AAC5B,gBAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,gDAAgD;AACnC,QAAA,MAAM,GAAG,IAAA,cAAI,EAAC;IACzB,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO;IACvC,IAAI,EAAE,IAAI;IACV,SAAS,EAAE;QACT,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI;YACV,aAAa,EAAE,cAAc;YAC7B,UAAU,EAAE,SAAS,EAAE,yCAAyC;SACjE;KACF;IACD,UAAU,EAAE;QACV,KAAK,CAAC,KAAK;YACT,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QAC1B,CAAC;KACF;CACF,CAAC,CAAC"}
|
|
@@ -35,48 +35,6 @@ pnpm add @minded-ai/mindedjs langchain
|
|
|
35
35
|
{% endtab %}
|
|
36
36
|
{% endtabs %}
|
|
37
37
|
|
|
38
|
-
## Python dependencies
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
### 1. Install uv
|
|
42
|
-
|
|
43
|
-
First, install `uv` which includes the `uvx` command:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### 2. Install browser-use cli with uv
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
uv tool install 'browser-use[cli]'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### 3. Install Playwright Chromium browser
|
|
56
|
-
|
|
57
|
-
After installing browser-use, you need to install the Chromium browser for Playwright:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
playwright install chromium
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
This downloads the Chromium browser that browser-use uses to automate web interactions.
|
|
64
|
-
|
|
65
|
-
### 4. Add uv to PATH
|
|
66
|
-
|
|
67
|
-
After installation, add uv to your PATH:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# For immediate use
|
|
71
|
-
source $HOME/.local/bin/env
|
|
72
|
-
|
|
73
|
-
# For permanent access, add to your shell config:
|
|
74
|
-
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # or ~/.bashrc
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
{% endtab %}
|
|
78
|
-
{% endtabs %}
|
|
79
|
-
|
|
80
38
|
## Next Steps
|
|
81
39
|
|
|
82
40
|
Now that MindedJS is installed:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@minded-ai/mindedjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.103-beta-2",
|
|
4
4
|
"description": "MindedJS is a TypeScript library for building agents.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -66,4 +66,4 @@
|
|
|
66
66
|
"uuid": "^11.1.0",
|
|
67
67
|
"ws": "^8.15.1"
|
|
68
68
|
}
|
|
69
|
-
}
|
|
69
|
+
}
|
package/src/agent.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
import { createLlmInstance } from './llm/createLlmInstance';
|
|
27
27
|
import { createCheckpointSaver } from './checkpointer/checkpointSaverFactory';
|
|
28
28
|
import { getConfig } from './platform/config';
|
|
29
|
+
import { InterruptSessionManager, InterruptType } from './interrupts/BaseInterruptSessionManager';
|
|
30
|
+
import { createInterruptSessionManager } from './interrupts/interruptSessionManagerFactory';
|
|
29
31
|
import { BaseMessage, HumanMessage } from '@langchain/core/messages';
|
|
30
32
|
import triggerTypeToDefaultMessage from './triggers/triggerTypeToDefaultMessage';
|
|
31
33
|
import appActionRunnerToolCreator from './internalTools/appActionRunnerTool';
|
|
@@ -43,6 +45,7 @@ type CreateAgentParams<Memory> = {
|
|
|
43
45
|
tools: Tool<any, Memory>[];
|
|
44
46
|
platformToken?: string;
|
|
45
47
|
memorySaver?: BaseCheckpointSaver;
|
|
48
|
+
interruptSessionManager?: InterruptSessionManager;
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
/**
|
|
@@ -75,6 +78,8 @@ export class Agent {
|
|
|
75
78
|
|
|
76
79
|
// Langgraph memory saver. In memory for local development, Custom for Platform
|
|
77
80
|
private checkpointer!: BaseCheckpointSaver;
|
|
81
|
+
// Interrupt session manager. In memory for local development, Custom for Platform
|
|
82
|
+
public interruptSessionManager!: InterruptSessionManager;
|
|
78
83
|
// Langgraph compiled graph
|
|
79
84
|
public compiledGraph!: CompiledGraph;
|
|
80
85
|
// Cache for secrets to avoid repeated API calls
|
|
@@ -145,7 +150,7 @@ export class Agent {
|
|
|
145
150
|
|
|
146
151
|
private async init(params: CreateAgentParams<z.infer<typeof this.memorySchema>>): Promise<void> {
|
|
147
152
|
try {
|
|
148
|
-
const { config, tools, memorySaver } = params;
|
|
153
|
+
const { config, tools, memorySaver, interruptSessionManager } = params;
|
|
149
154
|
const { runLocally } = getConfig();
|
|
150
155
|
if (!runLocally) {
|
|
151
156
|
await mindedConnection.start();
|
|
@@ -178,6 +183,7 @@ export class Agent {
|
|
|
178
183
|
const appActionsRunnerTools = this.initAppActionsRunnerTools();
|
|
179
184
|
this.tools = [...tools, ...appActionsRunnerTools];
|
|
180
185
|
this.checkpointer = memorySaver || createCheckpointSaver();
|
|
186
|
+
this.interruptSessionManager = interruptSessionManager || createInterruptSessionManager();
|
|
181
187
|
|
|
182
188
|
// call here methods that needs environment variables to be loaded
|
|
183
189
|
this.llm = createLlmInstance(config.llm);
|
|
@@ -416,10 +422,24 @@ export class Agent {
|
|
|
416
422
|
* });
|
|
417
423
|
* ```
|
|
418
424
|
*/
|
|
419
|
-
public async invoke({ triggerBody, triggerName, sessionId, appName }: AgentInvokeParams) {
|
|
425
|
+
public async invoke({ triggerBody, triggerName, sessionId, appName, bypassSessionCheck }: AgentInvokeParams): Promise<any> {
|
|
420
426
|
sessionId = sessionId ?? uuidv4();
|
|
421
427
|
try {
|
|
422
428
|
await this.waitForInitialization();
|
|
429
|
+
|
|
430
|
+
// Try to acquire lock atomically (unless bypassing session check)
|
|
431
|
+
if (!bypassSessionCheck && !(await this.interruptSessionManager.lock(sessionId))) {
|
|
432
|
+
// Could not acquire lock, session is being processed - enqueue the message
|
|
433
|
+
logger.info({ msg: 'Enqueuing message', sessionId, triggerBody, triggerName, appName });
|
|
434
|
+
await this.interruptSessionManager.enqueueMessage(sessionId, {
|
|
435
|
+
triggerBody,
|
|
436
|
+
triggerName,
|
|
437
|
+
appName,
|
|
438
|
+
});
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
// Session lock acquired, proceed with processing
|
|
442
|
+
|
|
423
443
|
let messages: Array<BaseMessage> = [];
|
|
424
444
|
let memoryUpdate = {};
|
|
425
445
|
let sessionType: SessionType = SessionType.TEXT;
|
|
@@ -447,7 +467,8 @@ export class Agent {
|
|
|
447
467
|
const handlerResult = results.find((r) => r !== undefined);
|
|
448
468
|
if (handlerResult) {
|
|
449
469
|
if (!handlerResult.isQualified) {
|
|
450
|
-
logger.
|
|
470
|
+
logger.info({ message: '[Trigger] Disqualified', triggerName, triggerBody, sessionId });
|
|
471
|
+
await this.interruptSessionManager.release(sessionId);
|
|
451
472
|
return;
|
|
452
473
|
}
|
|
453
474
|
memoryUpdate = handlerResult.memory || {};
|
|
@@ -466,7 +487,10 @@ export class Agent {
|
|
|
466
487
|
? state.values.overrideStartFromNodeId
|
|
467
488
|
? state.values.overrideStartFromNodeId
|
|
468
489
|
: state.next[0]
|
|
469
|
-
: this.startingNodeId
|
|
490
|
+
: this.startingNodeId;
|
|
491
|
+
if (!nodeToBeInvoked) {
|
|
492
|
+
throw new Error('No node to be invoked');
|
|
493
|
+
}
|
|
470
494
|
nodeToBeInvoked = nodeToBeInvoked.replace(new RegExp(suffixes.join('|'), 'g'), '');
|
|
471
495
|
const historyStep = this.createTriggerHistoryStep(
|
|
472
496
|
state.values.history,
|
|
@@ -479,13 +503,37 @@ export class Agent {
|
|
|
479
503
|
|
|
480
504
|
let res;
|
|
481
505
|
// Resume interruption
|
|
482
|
-
if (state.tasks?.[
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
506
|
+
if (state.tasks?.[state.tasks.length - 1]?.interrupts?.length > 0) {
|
|
507
|
+
const lastTask = state.tasks[state.tasks.length - 1];
|
|
508
|
+
const interrupt = lastTask.interrupts[0];
|
|
509
|
+
const interruptValue = (interrupt as any).value;
|
|
510
|
+
|
|
511
|
+
if (interruptValue?.type === InterruptType.HUMAN_IN_THE_LOOP) {
|
|
512
|
+
// For HUMAN_IN_THE_LOOP, use resume with the full object
|
|
513
|
+
res = await this.compiledGraph.invoke(
|
|
514
|
+
new Command({
|
|
515
|
+
resume: { memory: memoryUpdate, messages, history: historyStep, sessionId, sessionType, overrideStartFromNodeId: null },
|
|
516
|
+
}),
|
|
517
|
+
langraphConfig,
|
|
518
|
+
);
|
|
519
|
+
} else if (interruptValue?.type === InterruptType.NEW_TRIGGERS) {
|
|
520
|
+
// For NEW_TRIGGERS, check if there's an updateStateObject to apply first
|
|
521
|
+
const finalState = { memory: memoryUpdate, messages, history: [historyStep], sessionId, sessionType };
|
|
522
|
+
if (interruptValue.updateStateObject) {
|
|
523
|
+
finalState.messages = [...interruptValue.updateStateObject.messages, ...messages];
|
|
524
|
+
finalState.history = [...(interruptValue.updateStateObject.history || []), historyStep];
|
|
525
|
+
//add handlers for other state fields as needed
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Then use update with the full object and empty resume
|
|
529
|
+
res = await this.compiledGraph.invoke(
|
|
530
|
+
new Command({
|
|
531
|
+
update: finalState,
|
|
532
|
+
resume: '',
|
|
533
|
+
}),
|
|
534
|
+
langraphConfig,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
489
537
|
} else if (state.values.overrideStartFromNodeId) {
|
|
490
538
|
res = await this.compiledGraph.invoke(
|
|
491
539
|
new Command({
|
|
@@ -507,6 +555,26 @@ export class Agent {
|
|
|
507
555
|
langraphConfig,
|
|
508
556
|
);
|
|
509
557
|
}
|
|
558
|
+
const nextMessage = await this.interruptSessionManager.dequeue(sessionId);
|
|
559
|
+
if (nextMessage) {
|
|
560
|
+
// Dequeue the first message and process it recursively
|
|
561
|
+
// Recursively process the next message with bypass flag
|
|
562
|
+
const invokeParams: AgentInvokeParams = {
|
|
563
|
+
triggerBody: nextMessage.triggerBody,
|
|
564
|
+
triggerName: nextMessage.triggerName,
|
|
565
|
+
sessionId: sessionId,
|
|
566
|
+
bypassSessionCheck: true,
|
|
567
|
+
};
|
|
568
|
+
if (nextMessage.appName) {
|
|
569
|
+
invokeParams.appName = nextMessage.appName;
|
|
570
|
+
}
|
|
571
|
+
logger.info({ msg: 'Invoking next message in the queue', invokeParams });
|
|
572
|
+
return await this.invoke(invokeParams);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// Release the session lock
|
|
576
|
+
await this.interruptSessionManager.release(sessionId);
|
|
577
|
+
|
|
510
578
|
return res;
|
|
511
579
|
} catch (error: any) {
|
|
512
580
|
logger.error({
|
|
@@ -515,6 +583,10 @@ export class Agent {
|
|
|
515
583
|
stack: error.stack,
|
|
516
584
|
sessionId,
|
|
517
585
|
});
|
|
586
|
+
|
|
587
|
+
// Release the session lock on error
|
|
588
|
+
await this.interruptSessionManager.release(sessionId);
|
|
589
|
+
|
|
518
590
|
const state = await this.compiledGraph.getState(this.getLangraphConfig(sessionId));
|
|
519
591
|
this.emit(AgentEvents.ERROR, { error: error instanceof Error ? error : new Error(JSON.stringify(error)), state: state.values });
|
|
520
592
|
throw error;
|
|
@@ -823,7 +895,7 @@ export class Agent {
|
|
|
823
895
|
// Hangup / end session handler
|
|
824
896
|
connection.on(mindedConnectionSocketMessageType.DASHBOARD_VOICE_SESSION_END, (message) => {
|
|
825
897
|
const hangup = message as BaseVoiceMessage;
|
|
826
|
-
logger.debug({
|
|
898
|
+
logger.debug({ msg: '[Voice] Dashboard eneded voice session', sessionId: hangup.sessionId });
|
|
827
899
|
const voiceSession = this.voiceSessions.get(hangup.sessionId);
|
|
828
900
|
if (voiceSession) {
|
|
829
901
|
voiceSession.hangup();
|
|
@@ -856,7 +928,8 @@ export class Agent {
|
|
|
856
928
|
voiceId: voiceTrigger.voiceId,
|
|
857
929
|
});
|
|
858
930
|
await voiceSession.init();
|
|
859
|
-
logger.debug({
|
|
931
|
+
logger.debug({ msg: '[Voice] Voice session initialized', sessionId: params.sessionId });
|
|
932
|
+
|
|
860
933
|
this.voiceSessions.set(params.sessionId, voiceSession);
|
|
861
934
|
|
|
862
935
|
// Emit voice session start event
|
package/src/cli/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ function setToken(token: string): void {
|
|
|
19
19
|
if (!fs.existsSync(envPath)) {
|
|
20
20
|
// Create .env file with the token
|
|
21
21
|
fs.writeFileSync(envPath, tokenLine + '\n');
|
|
22
|
-
logger.info(`Created ${envPath} and added token`);
|
|
22
|
+
logger.info({ msg: `Created ${envPath} and added token` });
|
|
23
23
|
} else {
|
|
24
24
|
// Read existing .env file
|
|
25
25
|
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
@@ -29,12 +29,12 @@ function setToken(token: string): void {
|
|
|
29
29
|
// Replace existing token
|
|
30
30
|
const updatedContent = envContent.replace(/MINDED_CONNECTION_TOKEN=.*/, tokenLine);
|
|
31
31
|
fs.writeFileSync(envPath, updatedContent);
|
|
32
|
-
logger.info(`Updated MINDED_CONNECTION_TOKEN in ${envPath}`);
|
|
32
|
+
logger.info({ msg: `Updated MINDED_CONNECTION_TOKEN in ${envPath}` });
|
|
33
33
|
} else {
|
|
34
34
|
// Append token to existing file
|
|
35
35
|
const newContent = envContent.endsWith('\n') ? envContent + tokenLine + '\n' : envContent + '\n' + tokenLine + '\n';
|
|
36
36
|
fs.writeFileSync(envPath, newContent);
|
|
37
|
-
logger.info(`Added MINDED_CONNECTION_TOKEN to ${envPath}`);
|
|
37
|
+
logger.info({ msg: `Added MINDED_CONNECTION_TOKEN to ${envPath}` });
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -44,7 +44,7 @@ function generateLambdaHandler(): void {
|
|
|
44
44
|
|
|
45
45
|
// Check if minded.json exists
|
|
46
46
|
if (!fs.existsSync(mindedConfigPath)) {
|
|
47
|
-
logger.error('minded.json not found in the current directory');
|
|
47
|
+
logger.error({ msg: 'minded.json not found in the current directory' });
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -54,14 +54,14 @@ function generateLambdaHandler(): void {
|
|
|
54
54
|
const configContent = fs.readFileSync(mindedConfigPath, 'utf8');
|
|
55
55
|
mindedConfig = JSON.parse(configContent);
|
|
56
56
|
} catch (error) {
|
|
57
|
-
logger.error('Failed to read or parse minded.json:', error);
|
|
57
|
+
logger.error({ msg: 'Failed to read or parse minded.json:', error });
|
|
58
58
|
process.exit(1);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Get the agent path
|
|
62
62
|
const agentPath = mindedConfig.agent;
|
|
63
63
|
if (!agentPath) {
|
|
64
|
-
logger.error('No agent path found in minded.json');
|
|
64
|
+
logger.error({ msg: 'No agent path found in minded.json' });
|
|
65
65
|
process.exit(1);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -91,7 +91,7 @@ function generateLambdaHandler(): void {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (!templateContent) {
|
|
94
|
-
logger.error('Could not find Lambda handler template file');
|
|
94
|
+
logger.error({ msg: 'Could not find Lambda handler template file' });
|
|
95
95
|
process.exit(1);
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -102,10 +102,10 @@ function generateLambdaHandler(): void {
|
|
|
102
102
|
// Write the Lambda handler to index.ts at the root
|
|
103
103
|
const outputPath = path.join(process.cwd(), 'index.ts');
|
|
104
104
|
fs.writeFileSync(outputPath, templateContent);
|
|
105
|
-
logger.info(`Generated Lambda handler at ${outputPath}`);
|
|
105
|
+
logger.info({ msg: `Generated Lambda handler at ${outputPath}` });
|
|
106
106
|
|
|
107
107
|
// Compile the index.ts file using TypeScript
|
|
108
|
-
logger.info('Compiling the Lambda handler...');
|
|
108
|
+
logger.info({ msg: 'Compiling the Lambda handler...' });
|
|
109
109
|
|
|
110
110
|
try {
|
|
111
111
|
// Read tsconfig.json to get the outDir
|
|
@@ -138,12 +138,12 @@ function generateLambdaHandler(): void {
|
|
|
138
138
|
cwd: process.cwd(),
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
-
logger.info(`Successfully compiled Lambda handler to ${outDir}/index.js`);
|
|
141
|
+
logger.info({ msg: `Successfully compiled Lambda handler to ${outDir}/index.js` });
|
|
142
142
|
} catch (compileError) {
|
|
143
|
-
logger.error({
|
|
143
|
+
logger.error({ msg: 'Failed to compile Lambda handler', error: compileError });
|
|
144
144
|
}
|
|
145
145
|
} catch (error) {
|
|
146
|
-
logger.error({
|
|
146
|
+
logger.error({ msg: 'Failed to generate Lambda handler', error: error });
|
|
147
147
|
process.exit(1);
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -155,14 +155,14 @@ function main() {
|
|
|
155
155
|
if (command === 'token') {
|
|
156
156
|
const token = args[1];
|
|
157
157
|
if (!token) {
|
|
158
|
-
logger.error('Please provide a token');
|
|
158
|
+
logger.error({ msg: 'Please provide a token' });
|
|
159
159
|
process.exit(1);
|
|
160
160
|
}
|
|
161
161
|
setToken(token);
|
|
162
162
|
} else if (command === 'generate-lambda-ts-handler') {
|
|
163
163
|
generateLambdaHandler();
|
|
164
164
|
} else {
|
|
165
|
-
logger.error('Unknown command. Available commands: token, generate-lambda-ts-handler');
|
|
165
|
+
logger.error({ msg: 'Unknown command. Available commands: token, generate-lambda-ts-handler' });
|
|
166
166
|
process.exit(1);
|
|
167
167
|
}
|
|
168
168
|
}
|
package/src/edges/edgeFactory.ts
CHANGED
|
@@ -60,7 +60,7 @@ export const edgeFactory = ({
|
|
|
60
60
|
if (result) {
|
|
61
61
|
return result;
|
|
62
62
|
} else {
|
|
63
|
-
logger.debug('No logical conditions matched, continuing to prompt conditions');
|
|
63
|
+
logger.debug({ msg: 'No logical conditions matched, continuing to prompt conditions' });
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -80,7 +80,7 @@ export const edgeFactory = ({
|
|
|
80
80
|
|
|
81
81
|
// Fallback: stay at current source node
|
|
82
82
|
const source = originalNode?.name || sourceNode;
|
|
83
|
-
logger.info(`No conditions matched, returning to source: ${source}`);
|
|
83
|
+
logger.info({ msg: `No conditions matched, returning to source: ${source}` });
|
|
84
84
|
return source;
|
|
85
85
|
};
|
|
86
86
|
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { State } from '../types/LangGraph.types';
|
|
2
|
+
import { GraphInterrupt } from '@langchain/langgraph';
|
|
3
|
+
import { logger } from '../utils/logger';
|
|
4
|
+
|
|
5
|
+
export enum InterruptType {
|
|
6
|
+
NEW_TRIGGERS = 'NEW_TRIGGERS',
|
|
7
|
+
HUMAN_IN_THE_LOOP = 'HUMAN_IN_THE_LOOP',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface QueuedMessage {
|
|
11
|
+
triggerBody: any;
|
|
12
|
+
triggerName: string;
|
|
13
|
+
appName?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// export interface UpdateStateObject {
|
|
17
|
+
// memory: any;
|
|
18
|
+
// messages: any[];
|
|
19
|
+
// history: any[];
|
|
20
|
+
// sessionId: string;
|
|
21
|
+
// sessionType: SessionType;
|
|
22
|
+
// }
|
|
23
|
+
export interface InterruptPayload {
|
|
24
|
+
type: InterruptType.NEW_TRIGGERS;
|
|
25
|
+
updateStateObject?: Partial<State>;
|
|
26
|
+
id?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface InterruptSessionManager {
|
|
30
|
+
isProcessed(sessionId: string): boolean | Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Atomically attempts to acquire a lock for the given session.
|
|
33
|
+
* This method should only succeed if the session is not already being processed.
|
|
34
|
+
*
|
|
35
|
+
* @param sessionId - The session ID to lock
|
|
36
|
+
* @returns true if the lock was successfully acquired, false if the session is already locked
|
|
37
|
+
*/
|
|
38
|
+
lock(sessionId: string): boolean | Promise<boolean>;
|
|
39
|
+
release(sessionId: string): void | Promise<void>;
|
|
40
|
+
enqueueMessage(sessionId: string, message: QueuedMessage): void | Promise<void>;
|
|
41
|
+
dequeueAll(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
|
|
42
|
+
dequeue(sessionId: string): QueuedMessage | null | Promise<QueuedMessage | null>;
|
|
43
|
+
checkQueueAndInterrupt(sessionId: string, updateStateObject?: Partial<State>): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export abstract class BaseInterruptSessionManager implements InterruptSessionManager {
|
|
47
|
+
// Abstract methods that subclasses must implement for queue management
|
|
48
|
+
abstract isProcessed(sessionId: string): boolean | Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Atomically attempts to acquire a lock for the given session.
|
|
51
|
+
* This method should only succeed if the session is not already being processed.
|
|
52
|
+
* Implementations must ensure this operation is atomic to prevent race conditions.
|
|
53
|
+
*
|
|
54
|
+
* @param sessionId - The session ID to lock
|
|
55
|
+
* @returns true if the lock was successfully acquired, false if the session is already locked
|
|
56
|
+
*/
|
|
57
|
+
abstract lock(sessionId: string): boolean | Promise<boolean>;
|
|
58
|
+
abstract release(sessionId: string): void | Promise<void>;
|
|
59
|
+
abstract enqueueMessage(sessionId: string, message: QueuedMessage): void | Promise<void>;
|
|
60
|
+
abstract dequeueAll(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
|
|
61
|
+
abstract dequeue(sessionId: string): QueuedMessage | null | Promise<QueuedMessage | null>;
|
|
62
|
+
|
|
63
|
+
// Abstract method to check if queue has messages - this is the only queue-specific part
|
|
64
|
+
protected abstract hasQueuedMessages(sessionId: string): boolean | Promise<boolean>;
|
|
65
|
+
protected abstract getQueuedMessages(sessionId: string): QueuedMessage[] | Promise<QueuedMessage[]>;
|
|
66
|
+
|
|
67
|
+
// Common implementation of checkQueueAndInterrupt
|
|
68
|
+
async checkQueueAndInterrupt(sessionId: string, updateStateObject?: Partial<State>): Promise<boolean> {
|
|
69
|
+
if (await this.hasQueuedMessages(sessionId)) {
|
|
70
|
+
logger.trace({ msg: 'graph has queued messagess, interrupting graph', sessionId });
|
|
71
|
+
|
|
72
|
+
// Interrupt the graph with NEW_TRIGGERS flag and optional updateStateObject
|
|
73
|
+
const interruptPayload: InterruptPayload = { type: InterruptType.NEW_TRIGGERS };
|
|
74
|
+
if (updateStateObject) {
|
|
75
|
+
interruptPayload.updateStateObject = {
|
|
76
|
+
messages: updateStateObject.messages,
|
|
77
|
+
memory: updateStateObject.memory,
|
|
78
|
+
history: updateStateObject.history,
|
|
79
|
+
sessionId: updateStateObject.sessionId,
|
|
80
|
+
sessionType: updateStateObject.sessionType,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
throw new GraphInterrupt([
|
|
85
|
+
{
|
|
86
|
+
value: interruptPayload,
|
|
87
|
+
when: 'during',
|
|
88
|
+
resumable: true,
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BaseInterruptSessionManager, QueuedMessage } from './BaseInterruptSessionManager';
|
|
2
|
+
|
|
3
|
+
export class MemoryInterruptSessionManager extends BaseInterruptSessionManager {
|
|
4
|
+
private sessionProcessing: Map<string, boolean> = new Map();
|
|
5
|
+
private sessionMessageQueues: Map<string, QueuedMessage[]> = new Map();
|
|
6
|
+
|
|
7
|
+
isProcessed(sessionId: string): boolean {
|
|
8
|
+
return this.sessionProcessing.get(sessionId) || false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
lock(sessionId: string): boolean {
|
|
12
|
+
const isCurrentlyProcessed = this.sessionProcessing.get(sessionId) || false;
|
|
13
|
+
if (isCurrentlyProcessed) {
|
|
14
|
+
return false; // Could not acquire lock
|
|
15
|
+
}
|
|
16
|
+
this.sessionProcessing.set(sessionId, true);
|
|
17
|
+
return true; // Successfully acquired lock
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
release(sessionId: string): void {
|
|
21
|
+
this.sessionProcessing.delete(sessionId);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
enqueueMessage(sessionId: string, message: QueuedMessage): void {
|
|
25
|
+
if (!this.sessionMessageQueues.has(sessionId)) {
|
|
26
|
+
this.sessionMessageQueues.set(sessionId, []);
|
|
27
|
+
}
|
|
28
|
+
this.sessionMessageQueues.get(sessionId)!.push(message);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
dequeueAll(sessionId: string): QueuedMessage[] {
|
|
32
|
+
const messages = this.sessionMessageQueues.get(sessionId) || [];
|
|
33
|
+
const result = [...messages];
|
|
34
|
+
this.sessionMessageQueues.set(sessionId, []);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
dequeue(sessionId: string): QueuedMessage | null {
|
|
39
|
+
const messages = this.sessionMessageQueues.get(sessionId) || [];
|
|
40
|
+
if (messages.length === 0) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const firstMessage = messages.shift()!;
|
|
44
|
+
this.sessionMessageQueues.set(sessionId, messages);
|
|
45
|
+
return firstMessage;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Implementation of abstract methods from BaseInterruptSessionManager
|
|
49
|
+
protected hasQueuedMessages(sessionId: string): boolean {
|
|
50
|
+
const queue = this.sessionMessageQueues.get(sessionId) || [];
|
|
51
|
+
return queue.length > 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
protected getQueuedMessages(sessionId: string): QueuedMessage[] {
|
|
55
|
+
return this.sessionMessageQueues.get(sessionId) || [];
|
|
56
|
+
}
|
|
57
|
+
}
|