@minicor/mcp-server 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/README.md +169 -0
  2. package/dist/__tests__/diff.test.d.ts +2 -0
  3. package/dist/__tests__/diff.test.d.ts.map +1 -0
  4. package/dist/__tests__/diff.test.js +23 -0
  5. package/dist/__tests__/diff.test.js.map +1 -0
  6. package/dist/__tests__/helpers.test.d.ts +2 -0
  7. package/dist/__tests__/helpers.test.d.ts.map +1 -0
  8. package/dist/__tests__/helpers.test.js +70 -0
  9. package/dist/__tests__/helpers.test.js.map +1 -0
  10. package/dist/__tests__/inspect-scripts.test.d.ts +2 -0
  11. package/dist/__tests__/inspect-scripts.test.d.ts.map +1 -0
  12. package/dist/__tests__/inspect-scripts.test.js +66 -0
  13. package/dist/__tests__/inspect-scripts.test.js.map +1 -0
  14. package/dist/browser-client.d.ts +42 -0
  15. package/dist/browser-client.d.ts.map +1 -0
  16. package/dist/browser-client.js +66 -0
  17. package/dist/browser-client.js.map +1 -0
  18. package/dist/cli.d.ts +14 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +256 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/config.d.ts +21 -0
  23. package/dist/config.d.ts.map +1 -0
  24. package/dist/config.js +57 -0
  25. package/dist/config.js.map +1 -0
  26. package/dist/diff.d.ts +7 -0
  27. package/dist/diff.d.ts.map +1 -0
  28. package/dist/diff.js +97 -0
  29. package/dist/diff.js.map +1 -0
  30. package/dist/helpers.d.ts +28 -0
  31. package/dist/helpers.d.ts.map +1 -0
  32. package/dist/helpers.js +91 -0
  33. package/dist/helpers.js.map +1 -0
  34. package/dist/index.d.ts +9 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +193 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/inspect-scripts.d.ts +18 -0
  39. package/dist/inspect-scripts.d.ts.map +1 -0
  40. package/dist/inspect-scripts.js +572 -0
  41. package/dist/inspect-scripts.js.map +1 -0
  42. package/dist/laminar-client.d.ts +160 -0
  43. package/dist/laminar-client.d.ts.map +1 -0
  44. package/dist/laminar-client.js +237 -0
  45. package/dist/laminar-client.js.map +1 -0
  46. package/dist/lds-client.d.ts +107 -0
  47. package/dist/lds-client.d.ts.map +1 -0
  48. package/dist/lds-client.js +81 -0
  49. package/dist/lds-client.js.map +1 -0
  50. package/dist/paths.d.ts +17 -0
  51. package/dist/paths.d.ts.map +1 -0
  52. package/dist/paths.js +46 -0
  53. package/dist/paths.js.map +1 -0
  54. package/dist/prompts/build-browser-rpa.d.ts +3 -0
  55. package/dist/prompts/build-browser-rpa.d.ts.map +1 -0
  56. package/dist/prompts/build-browser-rpa.js +90 -0
  57. package/dist/prompts/build-browser-rpa.js.map +1 -0
  58. package/dist/prompts/build-rpa.d.ts +3 -0
  59. package/dist/prompts/build-rpa.d.ts.map +1 -0
  60. package/dist/prompts/build-rpa.js +168 -0
  61. package/dist/prompts/build-rpa.js.map +1 -0
  62. package/dist/prompts/debug-execution.d.ts +3 -0
  63. package/dist/prompts/debug-execution.d.ts.map +1 -0
  64. package/dist/prompts/debug-execution.js +50 -0
  65. package/dist/prompts/debug-execution.js.map +1 -0
  66. package/dist/prompts/workflow-guide.d.ts +3 -0
  67. package/dist/prompts/workflow-guide.d.ts.map +1 -0
  68. package/dist/prompts/workflow-guide.js +175 -0
  69. package/dist/prompts/workflow-guide.js.map +1 -0
  70. package/dist/services.d.ts +61 -0
  71. package/dist/services.d.ts.map +1 -0
  72. package/dist/services.js +249 -0
  73. package/dist/services.js.map +1 -0
  74. package/dist/setup.d.ts +11 -0
  75. package/dist/setup.d.ts.map +1 -0
  76. package/dist/setup.js +790 -0
  77. package/dist/setup.js.map +1 -0
  78. package/dist/state.d.ts +23 -0
  79. package/dist/state.d.ts.map +1 -0
  80. package/dist/state.js +24 -0
  81. package/dist/state.js.map +1 -0
  82. package/dist/sync.d.ts +86 -0
  83. package/dist/sync.d.ts.map +1 -0
  84. package/dist/sync.js +394 -0
  85. package/dist/sync.js.map +1 -0
  86. package/dist/tools/browser.d.ts +3 -0
  87. package/dist/tools/browser.d.ts.map +1 -0
  88. package/dist/tools/browser.js +254 -0
  89. package/dist/tools/browser.js.map +1 -0
  90. package/dist/tools/config-stores.d.ts +3 -0
  91. package/dist/tools/config-stores.d.ts.map +1 -0
  92. package/dist/tools/config-stores.js +54 -0
  93. package/dist/tools/config-stores.js.map +1 -0
  94. package/dist/tools/core.d.ts +3 -0
  95. package/dist/tools/core.d.ts.map +1 -0
  96. package/dist/tools/core.js +202 -0
  97. package/dist/tools/core.js.map +1 -0
  98. package/dist/tools/cron.d.ts +3 -0
  99. package/dist/tools/cron.d.ts.map +1 -0
  100. package/dist/tools/cron.js +168 -0
  101. package/dist/tools/cron.js.map +1 -0
  102. package/dist/tools/elasticsearch.d.ts +3 -0
  103. package/dist/tools/elasticsearch.d.ts.map +1 -0
  104. package/dist/tools/elasticsearch.js +248 -0
  105. package/dist/tools/elasticsearch.js.map +1 -0
  106. package/dist/tools/issues.d.ts +3 -0
  107. package/dist/tools/issues.d.ts.map +1 -0
  108. package/dist/tools/issues.js +39 -0
  109. package/dist/tools/issues.js.map +1 -0
  110. package/dist/tools/stats.d.ts +3 -0
  111. package/dist/tools/stats.d.ts.map +1 -0
  112. package/dist/tools/stats.js +18 -0
  113. package/dist/tools/stats.js.map +1 -0
  114. package/dist/tools/sync-tools.d.ts +3 -0
  115. package/dist/tools/sync-tools.d.ts.map +1 -0
  116. package/dist/tools/sync-tools.js +121 -0
  117. package/dist/tools/sync-tools.js.map +1 -0
  118. package/dist/tools/vm-rpa.d.ts +3 -0
  119. package/dist/tools/vm-rpa.d.ts.map +1 -0
  120. package/dist/tools/vm-rpa.js +281 -0
  121. package/dist/tools/vm-rpa.js.map +1 -0
  122. package/dist/tools/vm.d.ts +3 -0
  123. package/dist/tools/vm.d.ts.map +1 -0
  124. package/dist/tools/vm.js +280 -0
  125. package/dist/tools/vm.js.map +1 -0
  126. package/dist/tools/workflow-ops.d.ts +3 -0
  127. package/dist/tools/workflow-ops.d.ts.map +1 -0
  128. package/dist/tools/workflow-ops.js +313 -0
  129. package/dist/tools/workflow-ops.js.map +1 -0
  130. package/dist/types.d.ts +14 -0
  131. package/dist/types.d.ts.map +1 -0
  132. package/dist/types.js +5 -0
  133. package/dist/types.js.map +1 -0
  134. package/package.json +58 -0
package/dist/paths.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Shared path resolution for token and config storage.
3
+ *
4
+ * New installs write to ~/.minicor/. Existing ~/.laminar/ installs
5
+ * keep working via fallback reads. Once a user re-auths, tokens
6
+ * silently migrate to ~/.minicor/.
7
+ */
8
+ import fs from "node:fs";
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ const MINICOR_DIR = path.join(os.homedir(), ".minicor");
12
+ const LEGACY_DIR = path.join(os.homedir(), ".laminar");
13
+ export { MINICOR_DIR };
14
+ export function getTokenPath() {
15
+ const minicorPath = path.join(MINICOR_DIR, "tokens.json");
16
+ if (fs.existsSync(minicorPath))
17
+ return minicorPath;
18
+ const legacyPath = path.join(LEGACY_DIR, "tokens.json");
19
+ if (fs.existsSync(legacyPath))
20
+ return legacyPath;
21
+ return minicorPath;
22
+ }
23
+ export function getWriteTokenPath() {
24
+ return path.join(MINICOR_DIR, "tokens.json");
25
+ }
26
+ export function getConfigPath() {
27
+ const minicorPath = path.join(MINICOR_DIR, "config.json");
28
+ if (fs.existsSync(minicorPath))
29
+ return minicorPath;
30
+ const legacyPath = path.join(LEGACY_DIR, "config.json");
31
+ if (fs.existsSync(legacyPath))
32
+ return legacyPath;
33
+ return minicorPath;
34
+ }
35
+ export function getWriteConfigPath() {
36
+ return path.join(MINICOR_DIR, "config.json");
37
+ }
38
+ export function regionToApiBase(region) {
39
+ return region === "ca"
40
+ ? "https://ca.api.laminar.run"
41
+ : "https://api.laminar.run";
42
+ }
43
+ export function apiBaseToRegion(apiBase) {
44
+ return apiBase.includes("ca.api") ? "ca" : "us";
45
+ }
46
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACxD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAEvD,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,MAAM,UAAU,YAAY;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAC1D,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IACjD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAC1D,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,WAAW,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IACjD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAC/C,CAAC;AAID,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM,KAAK,IAAI;QACpB,CAAC,CAAC,4BAA4B;QAC9B,CAAC,CAAC,yBAAyB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDeps } from "../types.js";
2
+ export declare function register({ server }: ToolDeps): void;
3
+ //# sourceMappingURL=build-browser-rpa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-browser-rpa.d.ts","sourceRoot":"","sources":["../../src/prompts/build-browser-rpa.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,QA8F5C"}
@@ -0,0 +1,90 @@
1
+ import { z } from "zod";
2
+ export function register({ server }) {
3
+ server.prompt("build-browser-rpa-workflow", "Iteratively build a browser-based RPA workflow using the Laminar Browser RPA service. Guides you through creating a browser session, performing actions, extracting data, and saving each step as a Laminar workflow flow.", {
4
+ workspaceId: z.string().describe("Laminar workspace ID"),
5
+ task: z
6
+ .string()
7
+ .describe("Description of what to automate (e.g. 'Log into athenaHealth, navigate to patient chart, extract insurance info')"),
8
+ targetUrl: z
9
+ .string()
10
+ .describe("Starting URL for the web application"),
11
+ workflowId: z
12
+ .string()
13
+ .optional()
14
+ .describe("Existing workflow ID to add steps to (omit to create a new workflow)"),
15
+ }, async ({ workspaceId, task, targetUrl, workflowId }) => ({
16
+ messages: [
17
+ {
18
+ role: "user",
19
+ content: {
20
+ type: "text",
21
+ text: `You are building a browser-based RPA workflow on the Laminar platform. Your goal is to automate web application interactions using the Browser RPA session API.
22
+
23
+ ## Task
24
+ ${task}
25
+
26
+ ## Target URL
27
+ ${targetUrl}
28
+
29
+ ## Workspace
30
+ ID: ${workspaceId}${workflowId ? `\nExisting workflow ID: ${workflowId} (add steps to this workflow)` : "\nCreate a new workflow for this automation."}
31
+
32
+ ## How Browser RPA Works
33
+
34
+ The Browser RPA service provides a session-based API:
35
+ 1. **Create Session** — starts a browser instance, returns a sessionId
36
+ 2. **Act** — sends natural-language actions (e.g. "click the login button", "type hello@example.com in the email field")
37
+ 3. **Extract** — extracts data from the current page via natural-language instructions
38
+ 4. **Screenshot** — captures the current browser state
39
+ 5. **Close Session** — cleans up
40
+
41
+ ## Procedure
42
+
43
+ ### 1. Connect to Browser RPA Service
44
+ Call \`browser_connect\` with the service base URL and bearer token. Ask the user if not known.
45
+
46
+ ### 2. Create a Browser Session
47
+ Call \`browser_create_session\` to get a sessionId.
48
+
49
+ ### 3. Iterative Build Loop — For EACH step:
50
+
51
+ **a. ACT — Perform the browser action**
52
+ - Call \`browser_act\` with a natural-language description of what to do
53
+ - Be specific: "navigate to ${targetUrl}", "click the Submit button", "type 'john@example.com' into the email input field"
54
+
55
+ **b. VERIFY — Confirm the action worked**
56
+ - Call \`browser_screenshot\` to see the current state
57
+ - If the action didn't produce the expected result, retry with a more specific instruction
58
+
59
+ **c. EXTRACT — Get data if needed**
60
+ - Call \`browser_extract\` with instructions like "extract the patient name and date of birth"
61
+ - This returns structured data from the page
62
+
63
+ **d. SAVE — Persist as a workflow step**
64
+ - Call \`create_browser_rpa_flow\` with the action type and payload
65
+ - For the first step, use actionType "create_session"
66
+ - For navigation/interaction steps, use actionType "act"
67
+ - For data extraction steps, use actionType "extract"
68
+ - For cleanup, use actionType "close_session"
69
+
70
+ ### 4. End-to-End Validation
71
+ - Run the full workflow via \`execute_workflow\`
72
+ - Verify the final state
73
+
74
+ ### 5. Iterate with the User
75
+ - Present the completed workflow
76
+ - Make adjustments as needed
77
+
78
+ ## Important Rules
79
+ - **Always verify actions with screenshots** before saving
80
+ - **Use \`create_browser_rpa_flow\`** to save steps — it generates the correct \`lam.httpRequest\` wrapper
81
+ - **Use \`{{config.variables}}\`** for credentials (bearerToken, baseUrl, etc.)
82
+ - **Be specific in actions** — natural language should be unambiguous
83
+ - **Handle 2FA/MFA** — if login requires verification codes, use waitForInput patterns
84
+ - **One action per step** — keep steps focused and debuggable`,
85
+ },
86
+ },
87
+ ],
88
+ }));
89
+ }
90
+ //# sourceMappingURL=build-browser-rpa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-browser-rpa.js","sourceRoot":"","sources":["../../src/prompts/build-browser-rpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAY;IAC3C,MAAM,CAAC,MAAM,CACX,4BAA4B,EAC5B,4NAA4N,EAC5N;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,mHAAmH,CACpH;QACH,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,CAAC,sCAAsC,CAAC;QACnD,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sEAAsE,CAAC;KACpF,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACvD,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;EAGhB,IAAI;;;EAGJ,SAAS;;;MAGL,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,2BAA2B,UAAU,+BAA+B,CAAC,CAAC,CAAC,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;8BAuBxH,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DA+BuB;iBACnD;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDeps } from "../types.js";
2
+ export declare function register({ server }: ToolDeps): void;
3
+ //# sourceMappingURL=build-rpa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-rpa.d.ts","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,QAgL5C"}
@@ -0,0 +1,168 @@
1
+ import { z } from "zod";
2
+ export function register({ server }) {
3
+ server.prompt("build-rpa-workflow", "Iteratively build an RPA workflow on a VM using the Laminar Desktop Service. Guides you through connecting to the VM, researching the target app's UI framework, taking screenshots, inspecting UI elements, writing and testing RPA scripts, and saving each working step as a Laminar workflow flow.", {
4
+ workspaceId: z.string().describe("Laminar workspace ID"),
5
+ task: z
6
+ .string()
7
+ .describe("Description of what to automate (e.g. 'Log into Centricity, navigate to Documents, download the latest report')"),
8
+ appName: z
9
+ .string()
10
+ .describe("Name of the application to automate (e.g. 'Centricity', 'SAP GUI', 'Epic Hyperspace')"),
11
+ workflowId: z
12
+ .string()
13
+ .optional()
14
+ .describe("Existing workflow ID to add steps to (omit to create a new workflow)"),
15
+ }, async ({ workspaceId, task, appName, workflowId }) => ({
16
+ messages: [
17
+ {
18
+ role: "user",
19
+ content: {
20
+ type: "text",
21
+ text: `You are building an RPA workflow on the Laminar platform. Your goal is to iteratively create automation steps that run on a VM via the Laminar Desktop Service (LDS).
22
+
23
+ ## Task
24
+ ${task}
25
+
26
+ ## Target Application
27
+ ${appName}
28
+
29
+ ## Workspace
30
+ ID: ${workspaceId}${workflowId ? `\nExisting workflow ID: ${workflowId} (add steps to this workflow)` : "\nCreate a new workflow for this automation."}
31
+
32
+ ## CRITICAL RULES
33
+
34
+ ### Rule 1 — MANDATORY VALIDATION
35
+ **NEVER save a step without first validating it on the VM.** Every RPA script MUST pass this sequence:
36
+ 1. \`vm_execute_script\` — run on the VM
37
+ 2. \`vm_screenshot\` — visually confirm it worked
38
+ 3. Only then → save via \`create_rpa_flow\`
39
+
40
+ ### Rule 2 — USE \`create_rpa_flow\` TO SAVE (NOT \`create_flow\`)
41
+ When saving an RPA step, call **\`create_rpa_flow\`** — it automatically wraps your Python script in the correct Laminar JS format. You only pass the Python script; the tool handles the \`lam.httpRequest\` / \`lam.rpa\` wrapper.
42
+
43
+ **NEVER** call \`create_flow\` with raw Python for an RPA step. **NEVER** try to construct the JS wrapper yourself.
44
+
45
+ ### Rule 3 — COMBINE ui_inspect + screenshots + clipboard
46
+ Screenshots alone are unreliable for reading data (resolution issues, misreads). ALWAYS combine multiple methods. See the Data Extraction Strategy section below.
47
+
48
+ ## Procedure
49
+
50
+ ### 1. Connect to the VM
51
+ If no VM is connected, ask for the **Cloudflare Tunnel URL** and call \`vm_connect\`.
52
+
53
+ ### 2. Research the Target Application
54
+ Based on "${appName}", pick the UI automation framework:
55
+ - **.NET / WPF / WinForms** → \`uiautomation\` (default) or \`pywinauto\`
56
+ - **Java / Swing** → \`jab\` (Java Access Bridge)
57
+ - **Electron / web-based desktop** → \`pywinauto\` or pyautogui
58
+ - **Legacy Win32** → \`uiautomation\`
59
+
60
+ Start with \`uiautomation\` if unsure.
61
+
62
+ ### 3. Initial Survey (ALWAYS do this first)
63
+ Before writing any automation:
64
+ 1. \`vm_screenshot\` — see the desktop state
65
+ 2. \`vm_inspect_ui\` mode \`screen_info\` — get resolution
66
+ 3. \`vm_inspect_ui\` mode \`window_list\` — list windows
67
+ 4. Verify the target app is running
68
+
69
+ ### 4. Iterative Build Loop — For EACH step:
70
+
71
+ **a. OBSERVE — Understand the current state (REQUIRED)**
72
+ - \`vm_screenshot\` to see the screen
73
+ - \`vm_inspect_ui\` with \`element_tree\` to map UI elements
74
+ - \`vm_inspect_ui\` with \`element_at_point\` for specific elements
75
+
76
+ **b. WRITE — Create the Python RPA script**
77
+ - Use the appropriate framework (pyautogui for mouse/keyboard, uiautomation/pywinauto for element-based)
78
+ - Include error handling and waits
79
+ - Explain what it does before executing
80
+
81
+ **c. VALIDATE — Test on the VM (REQUIRED)**
82
+ - \`vm_execute_script\` — run the script
83
+ - Or use \`debug_rpa_step\` for full before/after screenshots + diagnostics
84
+ - Fix and re-run if errors occur
85
+
86
+ **d. VERIFY — Confirm visually (REQUIRED)**
87
+ - \`vm_screenshot\` immediately after
88
+ - If result is wrong, go back to (b)
89
+
90
+ **e. SAVE — Call \`create_rpa_flow\` (only after c + d pass)**
91
+ - Pass the validated Python script, step name, description, flowId, and executionOrder
92
+ - The tool handles all JS wrapping automatically
93
+ - Default dispatch: \`cloudflare_tunnel\` (uses \`lam.httpRequest\`)
94
+
95
+ ### 5. End-to-End Validation
96
+ After all steps are built:
97
+ - \`execute_workflow\` to run the full sequence
98
+ - \`vm_screenshot\` to verify final state
99
+ - \`diagnose_execution\` if anything fails
100
+
101
+ ### 6. Iterate with the User
102
+ - Present completed workflow summary
103
+ - Make adjustments, re-validate changed steps
104
+
105
+ ## Data Extraction Strategy
106
+
107
+ When you need to READ data from the screen (not just click/type), follow this priority order. **Do NOT rely solely on screenshots for data reading.**
108
+
109
+ ### Priority 1: Accessibility Tree (most reliable)
110
+ - \`vm_inspect_ui\` with \`element_tree\` on the target window
111
+ - If the tree exposes text values, this is the most reliable method
112
+ - Use \`element_at_point\` for specific fields
113
+ - Use \`focused_element\` to read the current field
114
+
115
+ ### Priority 2: Open Accessible Dialogs
116
+ - Many apps expose more data when you open edit/detail dialogs
117
+ - Double-click on a row or click "Edit" to open a modal — the modal often has better accessibility support
118
+ - Then use \`element_tree\` on the modal
119
+
120
+ ### Priority 3: Clipboard Extraction
121
+ - Use \`vm_execute_script\` to click a field, then Ctrl+A, Ctrl+C
122
+ - Call \`vm_read_clipboard\` to get the copied text
123
+ - Works for individual fields, text areas, and some grid cells
124
+
125
+ ### Priority 4: Keyboard Navigation
126
+ - Tab through fields, reading each via \`vm_inspect_ui\` \`focused_element\`
127
+ - Useful when the accessibility tree returns element structure but not values
128
+
129
+ ### Priority 5: Zoomed Screenshot
130
+ - Use \`vm_screenshot_region\` to crop a specific area for better resolution
131
+ - Only for small text that can't be accessed any other way
132
+
133
+ ### Priority 6: Alternative Application Paths
134
+ - Think creatively! Look for:
135
+ - Reports or Print menus that export data
136
+ - List/Search views with better accessibility
137
+ - CLI tools or command-line interfaces the app provides
138
+ - Export to CSV/clipboard options
139
+ - Alternative windows/dialogs that show the same data more accessibly
140
+ - Use \`vm_execute_script\` to run Python code that queries the app's data directly if a CLI or API exists
141
+
142
+ ### Priority 7: Full Screenshot (VERIFICATION ONLY)
143
+ - Full desktop screenshots are for **verifying actions worked**, NOT for reading data
144
+ - If you must use a screenshot to read data, acknowledge it's unreliable and suggest a better approach to the user
145
+
146
+ ## Debugging Tools
147
+
148
+ - **\`debug_rpa_step\`** — runs a script with before/after screenshots and full diagnostics (stdout, stderr, exit code). Use during development.
149
+ - **\`vm_reset_state\`** — Smart Launch: close dialogs, reset app to known state. Use before testing.
150
+ - **\`vm_read_clipboard\`** — read clipboard after a copy operation.
151
+ - **\`vm_screenshot_region\`** — crop/zoom a region for better text reading.
152
+ - **\`batch_test_rpa\`** — run the workflow with multiple test inputs.
153
+
154
+ ## Important Rules
155
+ - **VALIDATE BEFORE SAVING** — no exceptions unless user explicitly opts out
156
+ - **Use \`create_rpa_flow\`** — never construct JS wrappers manually
157
+ - **Use \`{{config.variables}}\` for secrets** — never hardcode credentials
158
+ - **Combine extraction methods** — accessibility tree + clipboard + screenshots
159
+ - **Start simple** — get basic automation working before adding sophistication
160
+ - **Add waits** — use \`time.sleep()\` or element-wait patterns between actions
161
+ - **Handle errors** — try/except with meaningful messages
162
+ - **Keep scripts focused** — one logical action per step`,
163
+ },
164
+ },
165
+ ],
166
+ }));
167
+ }
168
+ //# sourceMappingURL=build-rpa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-rpa.js","sourceRoot":"","sources":["../../src/prompts/build-rpa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAY;IAC3C,MAAM,CAAC,MAAM,CACX,oBAAoB,EACpB,wSAAwS,EACxS;QACE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxD,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,CACP,iHAAiH,CAClH;QACH,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,CACP,uFAAuF,CACxF;QACH,UAAU,EAAE,CAAC;aACV,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sEAAsE,CACvE;KACJ,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;QACrD,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;EAGhB,IAAI;;;EAGJ,OAAO;;;MAGH,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,2BAA2B,UAAU,+BAA+B,CAAC,CAAC,CAAC,8CAA8C;;;;;;;;;;;;;;;;;;;;;;;;YAwB1I,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yDA4GsC;iBAC9C;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDeps } from "../types.js";
2
+ export declare function register({ server, client }: ToolDeps): void;
3
+ //# sourceMappingURL=debug-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-execution.d.ts","sourceRoot":"","sources":["../../src/prompts/debug-execution.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,QAoDpD"}
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { json } from "../helpers.js";
3
+ export function register({ server, client }) {
4
+ server.prompt("debug-workflow-execution", "Analyze a failed workflow execution and suggest fixes", {
5
+ workflowId: z.string().describe("Workflow ID to debug"),
6
+ executionId: z.string().describe("Failed execution ID"),
7
+ }, async ({ workflowId, executionId }) => {
8
+ const wId = parseInt(workflowId);
9
+ const eId = parseInt(executionId);
10
+ let executionData;
11
+ let flowsData;
12
+ try {
13
+ executionData = await client().getExecution(wId, eId);
14
+ flowsData = await client().getWorkflowFlows(wId);
15
+ }
16
+ catch (e) {
17
+ return {
18
+ messages: [
19
+ {
20
+ role: "user",
21
+ content: {
22
+ type: "text",
23
+ text: `Failed to fetch execution data: ${e.message}`,
24
+ },
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ return {
30
+ messages: [
31
+ {
32
+ role: "user",
33
+ content: {
34
+ type: "text",
35
+ text: `Please debug this Laminar workflow execution.
36
+
37
+ ## Workflow Flows (Steps):
38
+ ${json(flowsData)}
39
+
40
+ ## Execution Details:
41
+ ${json(executionData)}
42
+
43
+ Analyze the execution, identify failures, explain root causes, and suggest specific code fixes for the failing steps. Use the Laminar workflow specification (available via the laminar-workflow-guide prompt) for correct syntax.`,
44
+ },
45
+ },
46
+ ],
47
+ };
48
+ });
49
+ }
50
+ //# sourceMappingURL=debug-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-execution.js","sourceRoot":"","sources":["../../src/prompts/debug-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,EAAY;IACnD,MAAM,CAAC,MAAM,CACX,0BAA0B,EAC1B,uDAAuD,EACvD;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACvD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qBAAqB,CAAC;KACxD,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,EAAE;QACpC,MAAM,GAAG,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QAClC,IAAI,aAAkB,CAAC;QACvB,IAAI,SAAc,CAAC;QAEnB,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,MAAM,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtD,SAAS,GAAG,MAAM,MAAM,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,IAAI,EAAE,MAAe;wBACrB,OAAO,EAAE;4BACP,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,mCAAmC,CAAC,CAAC,OAAO,EAAE;yBACrD;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,IAAI,EAAE,MAAe;oBACrB,OAAO,EAAE;wBACP,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;;;EAGlB,IAAI,CAAC,SAAS,CAAC;;;EAGf,IAAI,CAAC,aAAa,CAAC;;mOAE8M;qBACtN;iBACF;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDeps } from "../types.js";
2
+ export declare function register({ server }: ToolDeps): void;
3
+ //# sourceMappingURL=workflow-guide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-guide.d.ts","sourceRoot":"","sources":["../../src/prompts/workflow-guide.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,QAkL5C"}
@@ -0,0 +1,175 @@
1
+ export function register({ server }) {
2
+ server.prompt("laminar-workflow-guide", "Comprehensive guide for creating and editing Laminar workflows — step types, data access patterns, available libraries, and best practices", {}, async () => ({
3
+ messages: [
4
+ {
5
+ role: "user",
6
+ content: {
7
+ type: "text",
8
+ text: `Please use this Laminar platform specification when creating or editing workflows:
9
+
10
+ # Laminar Workflow Specification
11
+
12
+ ## Step Structure
13
+ Every step is a JSON object with these fields:
14
+ - \`name\`: (string) Descriptive name
15
+ - \`description\`: (string) Detailed explanation
16
+ - \`program\`: (string) Code to execute (JS or Python)
17
+ - \`executionOrder\`: (integer) Position in workflow (starts at 1)
18
+ - \`flowType\`: (string) "HTTP_REQUEST", "GENERAL_FUNCTION", "SHELL_SCRIPT", "RPA"
19
+ - \`language\`: (string) "js" or "py" (NOTE: RPA flows must ALWAYS use "js")
20
+
21
+ ## Program Signatures
22
+ **Python (py):**
23
+ \`\`\`python
24
+ def transform(data):
25
+ # Your logic here
26
+ return {}
27
+ \`\`\`
28
+
29
+ **JavaScript (js):**
30
+ \`\`\`javascript
31
+ (data) => {
32
+ // Your code here
33
+ return {};
34
+ }
35
+ \`\`\`
36
+
37
+ ## Return Values by flowType
38
+
39
+ ### HTTP_REQUEST
40
+ \`\`\`json
41
+ {
42
+ "lam.httpRequest": {
43
+ "method": "GET|POST|PUT|DELETE|PATCH",
44
+ "url": "String",
45
+ "headers": "Object (optional)",
46
+ "pathParams": "Object (optional)",
47
+ "queryParams": "Object (optional)",
48
+ "body": "Object (optional)",
49
+ "authentication": {
50
+ "type": "basic|bearer|oauth2|apikey",
51
+ "token": "{{config.token}}"
52
+ },
53
+ "retry": { "maxAttempts": "Number" },
54
+ "pagination": {
55
+ "next": { "queryParams": {}, "headers": {}, "body": {} },
56
+ "stopCondition": "JS function receiving ctx",
57
+ "maxPages": 10
58
+ },
59
+ "loopUntil": {
60
+ "condition": "(ctx) => ctx.response.status === 'completed'",
61
+ "maxAttempts": 20,
62
+ "strategy": "exponential",
63
+ "initialDelay": "2s",
64
+ "maxDelay": "60s",
65
+ "multiplier": 2
66
+ }
67
+ }
68
+ }
69
+ \`\`\`
70
+
71
+ Multiple requests: use \`"lam.httpRequests"\` (plural) with an array.
72
+
73
+ ### SHELL_SCRIPT
74
+ \`\`\`json
75
+ {
76
+ "lam.shell": {
77
+ "script": "Bash script as string",
78
+ "environment": {},
79
+ "timeout": 300,
80
+ "binaryDataIds": []
81
+ }
82
+ }
83
+ \`\`\`
84
+
85
+ ### RPA (Desktop Automation)
86
+ **IMPORTANT: Use the \`create_rpa_flow\` tool to save RPA steps.** It accepts your validated Python script and automatically wraps it in the correct JS format. You do NOT need to construct the wrapper yourself.
87
+
88
+ RPA flows internally use \`language: "js"\` with the Python embedded in a JS arrow function. Two dispatch patterns exist:
89
+ - **\`lam.httpRequest\`** (Cloudflare Tunnel — default) — sends the script to the VM via HTTP
90
+ - **\`lam.rpa\`** (channelId) — sends via pub/sub channel
91
+
92
+ The \`create_rpa_flow\` tool handles both patterns via the \`dispatchPattern\` parameter (default: \`cloudflare_tunnel\`).
93
+
94
+ **NEVER** save raw Python as the program for an RPA flow. **NEVER** manually construct the JS wrapper — use \`create_rpa_flow\`.
95
+
96
+ ### Configuration Updates
97
+ \`\`\`json
98
+ {
99
+ "lam.updateConfig": {
100
+ "configurationId": "my-config",
101
+ "properties": [{ "key": "k", "value": "v" }],
102
+ "createIfNotExists": true,
103
+ "configurationName": "Auto-generated Config"
104
+ }
105
+ }
106
+ \`\`\`
107
+
108
+ ### Redis Key-Value Store
109
+ \`\`\`json
110
+ {
111
+ "lam.kvStore": {
112
+ "operation": "set|get|delete|exists|list|increment|decrement|transaction",
113
+ "key": "user:session:token",
114
+ "value": {},
115
+ "ttl": 3600,
116
+ "redisUrl": "{{config.redisUrl}}"
117
+ }
118
+ }
119
+ \`\`\`
120
+
121
+ ### Cron Job Management
122
+ \`\`\`json
123
+ {
124
+ "lam.cron": {
125
+ "operation": "create|update|delete",
126
+ "name": "Daily Report",
127
+ "schedule": "0 0 9 * * *",
128
+ "url": "https://api.laminar.run/workflow/execute/external/{id}?api_key=key",
129
+ "body": {}
130
+ }
131
+ }
132
+ \`\`\`
133
+
134
+ ### Custom Response (lam.response)
135
+ \`\`\`json
136
+ {
137
+ "lam.response": {
138
+ "statusCode": 200,
139
+ "message": "Success",
140
+ "data": {},
141
+ "error": { "code": "ERROR_CODE", "message": "Error description" }
142
+ }
143
+ }
144
+ \`\`\`
145
+ Note: Workflow exits immediately when lam.response is encountered.
146
+
147
+ ## Data Access Patterns
148
+ - \`data.input\`: Original workflow input
149
+ - \`data.step_N.response\`: HTTP request output from step N
150
+ - \`data.step_N.data\`: General function output from step N
151
+ - \`data.step_N.stdout\`: Shell output from step N
152
+ - \`data.step_N.stderr\`: Shell error from step N
153
+ - \`data.step_N.cronJobId\`: Cron job ID from step N
154
+ - \`data.step_N.response["lam.kvStore.value"]\`: KV store value
155
+ - \`data.step_N.response["lam.binaryDataId"]\`: File download reference
156
+
157
+ ## Available Libraries
158
+ - **Python:** json, datetime, math, statistics, collections, itertools, functools, re, copy, decimal, csv, io, dataclasses, typing, enum
159
+ - **JavaScript:** lodash (as _), date-fns (format, parseISO)
160
+
161
+ ## Security
162
+ Use \`{{config.variableName}}\` for sensitive values (API keys, tokens, passwords). These reference configuration store properties.
163
+
164
+ ## Best Practices
165
+ 1. **Minimize steps** — combine operations when logical, fewer steps = faster execution
166
+ 2. **Don't JSON.stringify request bodies** — pass objects directly
167
+ 3. **File downloads** auto-create \`lam.binaryDataId\` — don't process as text
168
+ 4. **Use {{config.variables}}** for sensitive data, not hardcoded values
169
+ 5. **Access errors** via \`data.step_N.response.error\` and \`data.step_N.response.statusCode\``,
170
+ },
171
+ },
172
+ ],
173
+ }));
174
+ }
175
+ //# sourceMappingURL=workflow-guide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-guide.js","sourceRoot":"","sources":["../../src/prompts/workflow-guide.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAC,EAAE,MAAM,EAAY;IAC3C,MAAM,CAAC,MAAM,CACX,wBAAwB,EACxB,4IAA4I,EAC5I,EAAE,EACF,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gGAiK8E;iBACrF;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Optional service clients: Elasticsearch + CRON.
3
+ * Only instantiated when configured — otherwise tools degrade gracefully.
4
+ */
5
+ import type { ElasticsearchConfig, CronConfig } from "./config.js";
6
+ export interface ESSearchParams {
7
+ workspaceId: string;
8
+ workflowId?: string;
9
+ workflowIds?: string[];
10
+ query?: string;
11
+ startDate?: string;
12
+ endDate?: string;
13
+ status?: string;
14
+ includeGlobalObject?: boolean;
15
+ rawQuery?: string;
16
+ fuzzy?: boolean;
17
+ size?: number;
18
+ from?: number;
19
+ }
20
+ export declare class ElasticsearchService {
21
+ private endpoint;
22
+ private apiKey;
23
+ private indexName;
24
+ constructor(config: ElasticsearchConfig);
25
+ private esRequest;
26
+ search(params: ESSearchParams): Promise<{
27
+ warning?: string | undefined;
28
+ hits: any;
29
+ total: any;
30
+ took: any;
31
+ }>;
32
+ private formatResults;
33
+ }
34
+ export declare class CronService {
35
+ private apiBase;
36
+ private apiKey;
37
+ constructor(config: CronConfig);
38
+ private request;
39
+ listJobs(workflowId?: string): Promise<any[]>;
40
+ getJob(jobId: string): Promise<any>;
41
+ createJob(job: {
42
+ name: string;
43
+ schedule: string;
44
+ url: string;
45
+ body?: Record<string, any>;
46
+ enabled?: boolean;
47
+ max_runs?: number | null;
48
+ is_temporary?: boolean;
49
+ }): Promise<any>;
50
+ updateJob(jobId: string, updates: {
51
+ name?: string;
52
+ schedule?: string;
53
+ url?: string;
54
+ body?: Record<string, any>;
55
+ enabled?: boolean;
56
+ }): Promise<any>;
57
+ toggleJob(jobId: string): Promise<any>;
58
+ deleteJob(jobId: string): Promise<void>;
59
+ triggerJob(jobId: string): Promise<void>;
60
+ }
61
+ //# sourceMappingURL=services.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAOnE,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,mBAAmB;YAMzB,SAAS;IAmBjB,MAAM,CAAC,MAAM,EAAE,cAAc;;;;;;IAmJnC,OAAO,CAAC,aAAa;CAyBtB;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,UAAU;YAKhB,OAAO;IA+Bf,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM;IAY5B,MAAM,CAAC,KAAK,EAAE,MAAM;IAKpB,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB;IASK,SAAS,CACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB;IAUG,SAAS,CAAC,KAAK,EAAE,MAAM;IAKvB,SAAS,CAAC,KAAK,EAAE,MAAM;IAIvB,UAAU,CAAC,KAAK,EAAE,MAAM;CAG/B"}