@optimuslabs/runtime 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +198 -0
  3. package/dist/capture-prompt.d.ts +14 -0
  4. package/dist/capture-prompt.d.ts.map +1 -0
  5. package/dist/capture-prompt.js +173 -0
  6. package/dist/capture-prompt.js.map +1 -0
  7. package/dist/index.d.ts +9 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +203 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/client-event.d.ts +12 -0
  12. package/dist/lib/client-event.d.ts.map +1 -0
  13. package/dist/lib/client-event.js +140 -0
  14. package/dist/lib/client-event.js.map +1 -0
  15. package/dist/lib/endpoint-config.d.ts +2 -0
  16. package/dist/lib/endpoint-config.d.ts.map +1 -0
  17. package/dist/lib/endpoint-config.js +2 -0
  18. package/dist/lib/endpoint-config.js.map +1 -0
  19. package/dist/lib/hardware-uuid.d.ts +7 -0
  20. package/dist/lib/hardware-uuid.d.ts.map +1 -0
  21. package/dist/lib/hardware-uuid.js +52 -0
  22. package/dist/lib/hardware-uuid.js.map +1 -0
  23. package/dist/lib/machine-auth.d.ts +11 -0
  24. package/dist/lib/machine-auth.d.ts.map +1 -0
  25. package/dist/lib/machine-auth.js +46 -0
  26. package/dist/lib/machine-auth.js.map +1 -0
  27. package/dist/lib/pending-events.d.ts +49 -0
  28. package/dist/lib/pending-events.d.ts.map +1 -0
  29. package/dist/lib/pending-events.js +135 -0
  30. package/dist/lib/pending-events.js.map +1 -0
  31. package/dist/lib/startup-sync.d.ts +13 -0
  32. package/dist/lib/startup-sync.d.ts.map +1 -0
  33. package/dist/lib/startup-sync.js +164 -0
  34. package/dist/lib/startup-sync.js.map +1 -0
  35. package/dist/lib/streaming.d.ts +35 -0
  36. package/dist/lib/streaming.d.ts.map +1 -0
  37. package/dist/lib/streaming.js +326 -0
  38. package/dist/lib/streaming.js.map +1 -0
  39. package/dist/lib/telemetry/build-event.d.ts +10 -0
  40. package/dist/lib/telemetry/build-event.d.ts.map +1 -0
  41. package/dist/lib/telemetry/build-event.js +34 -0
  42. package/dist/lib/telemetry/build-event.js.map +1 -0
  43. package/dist/lib/telemetry/canonical.d.ts +26 -0
  44. package/dist/lib/telemetry/canonical.d.ts.map +1 -0
  45. package/dist/lib/telemetry/canonical.js +153 -0
  46. package/dist/lib/telemetry/canonical.js.map +1 -0
  47. package/dist/lib/telemetry/index.d.ts +9 -0
  48. package/dist/lib/telemetry/index.d.ts.map +1 -0
  49. package/dist/lib/telemetry/index.js +9 -0
  50. package/dist/lib/telemetry/index.js.map +1 -0
  51. package/dist/lib/telemetry/serialize.d.ts +3 -0
  52. package/dist/lib/telemetry/serialize.d.ts.map +1 -0
  53. package/dist/lib/telemetry/serialize.js +15 -0
  54. package/dist/lib/telemetry/serialize.js.map +1 -0
  55. package/dist/lib/telemetry/types.d.ts +35 -0
  56. package/dist/lib/telemetry/types.d.ts.map +1 -0
  57. package/dist/lib/telemetry/types.js +14 -0
  58. package/dist/lib/telemetry/types.js.map +1 -0
  59. package/dist/lib/telemetry/wire-metadata.d.ts +10 -0
  60. package/dist/lib/telemetry/wire-metadata.d.ts.map +1 -0
  61. package/dist/lib/telemetry/wire-metadata.js +28 -0
  62. package/dist/lib/telemetry/wire-metadata.js.map +1 -0
  63. package/dist/lib/telemetry.d.ts +2 -0
  64. package/dist/lib/telemetry.d.ts.map +1 -0
  65. package/dist/lib/telemetry.js +2 -0
  66. package/dist/lib/telemetry.js.map +1 -0
  67. package/dist/lib/tofu.d.ts +16 -0
  68. package/dist/lib/tofu.d.ts.map +1 -0
  69. package/dist/lib/tofu.js +44 -0
  70. package/dist/lib/tofu.js.map +1 -0
  71. package/dist/lib/user-profile.d.ts +17 -0
  72. package/dist/lib/user-profile.d.ts.map +1 -0
  73. package/dist/lib/user-profile.js +187 -0
  74. package/dist/lib/user-profile.js.map +1 -0
  75. package/dist/test/canonical.test.d.ts +2 -0
  76. package/dist/test/canonical.test.d.ts.map +1 -0
  77. package/dist/test/canonical.test.js +138 -0
  78. package/dist/test/canonical.test.js.map +1 -0
  79. package/dist/test/endpoint-config.test.d.ts +2 -0
  80. package/dist/test/endpoint-config.test.d.ts.map +1 -0
  81. package/dist/test/endpoint-config.test.js +73 -0
  82. package/dist/test/endpoint-config.test.js.map +1 -0
  83. package/dist/test/index.test.d.ts +2 -0
  84. package/dist/test/index.test.d.ts.map +1 -0
  85. package/dist/test/index.test.js +376 -0
  86. package/dist/test/index.test.js.map +1 -0
  87. package/dist/test/integration-canonical.test.d.ts +2 -0
  88. package/dist/test/integration-canonical.test.d.ts.map +1 -0
  89. package/dist/test/integration-canonical.test.js +176 -0
  90. package/dist/test/integration-canonical.test.js.map +1 -0
  91. package/dist/test/pending-events.test.d.ts +13 -0
  92. package/dist/test/pending-events.test.d.ts.map +1 -0
  93. package/dist/test/pending-events.test.js +265 -0
  94. package/dist/test/pending-events.test.js.map +1 -0
  95. package/dist/test/startup-sync.test.d.ts +2 -0
  96. package/dist/test/startup-sync.test.d.ts.map +1 -0
  97. package/dist/test/startup-sync.test.js +57 -0
  98. package/dist/test/startup-sync.test.js.map +1 -0
  99. package/dist/test/streaming-http.test.d.ts +11 -0
  100. package/dist/test/streaming-http.test.d.ts.map +1 -0
  101. package/dist/test/streaming-http.test.js +181 -0
  102. package/dist/test/streaming-http.test.js.map +1 -0
  103. package/dist/test/streaming.test.d.ts +2 -0
  104. package/dist/test/streaming.test.d.ts.map +1 -0
  105. package/dist/test/streaming.test.js +223 -0
  106. package/dist/test/streaming.test.js.map +1 -0
  107. package/dist/test/telemetry.test.d.ts +2 -0
  108. package/dist/test/telemetry.test.d.ts.map +1 -0
  109. package/dist/test/telemetry.test.js +201 -0
  110. package/dist/test/telemetry.test.js.map +1 -0
  111. package/package.json +54 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Optimus Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # optimus-tool-call
2
+
3
+ Passive, non-blocking audit sensor for tool calls from coding agents (Claude Code, Cursor, GitHub Copilot, etc.).
4
+
5
+ ## Features
6
+
7
+ - **50+ command classifiers** - Full nah taxonomy coverage
8
+ - **40+ action types** - Comprehensive security categorization
9
+ - **Real-time telemetry** - Async event streaming to backend
10
+ - **Zero developer friction** - <50ms p99 latency, never blocks execution
11
+ - **Smart parsing** - Handles pipes, redirects, command chains, shell builtins
12
+ - **Flag-based detection** - Context-aware classification (sed -i, curl -X POST, make --dry-run, etc.)
13
+
14
+ ## How It Works
15
+
16
+ 1. **Hook Integration**: Integrates with Claude Code PreToolUse hooks
17
+ 2. **Command Classification**: Parses and classifies each tool call into an action type
18
+ 3. **Telemetry Event**: Creates event with classified action, file paths, session info
19
+ 4. **Async Streaming**: Non-blocking queue sends events to backend in batches
20
+ 5. **Backend Severity**: Django backend assigns severity (critical/high/medium/low/info)
21
+ 6. **Frontend Dashboard**: Real-time audit log with 2-second polling
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install @optimus/tool-call
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ Via PreToolUse hook (automatic in Claude Code):
32
+
33
+ ```json
34
+ {
35
+ "preToolUse": {
36
+ "matcher": "*",
37
+ "command": "node path/to/optimus-tool-call/dist/index.js"
38
+ }
39
+ }
40
+ ```
41
+
42
+ The hook:
43
+ - Classifies the tool call
44
+ - Extracts relevant metadata (files, commands, patterns)
45
+ - Queues telemetry event
46
+ - Returns `{"continue": true, "permission": "allow"}` (never blocks)
47
+
48
+ ## Command Coverage
49
+
50
+ See [COMMAND_COVERAGE.md](./COMMAND_COVERAGE.md) for complete list of 50+ supported commands and their classifications.
51
+
52
+ ### Quick Examples
53
+
54
+ ```
55
+ Filesystem:
56
+ read: cat, grep, ls, find, head, tail, which
57
+ write: echo, touch, mkdir, cp, mv, chmod
58
+ delete: rm
59
+
60
+ Git:
61
+ safe: log, status, diff, branch
62
+ write: add, commit, checkout, pull
63
+ history_rewrite: push --force, reset --hard, rebase
64
+
65
+ Network:
66
+ outbound: curl, wget, ssh
67
+ write: curl --data, scp, rsync
68
+
69
+ Language Execution:
70
+ python, node, ruby, bash, source, gdb
71
+
72
+ Text Processing:
73
+ sed -i → filesystem_write
74
+ awk with system() → lang_exec
75
+
76
+ And 30+ more...
77
+ ```
78
+
79
+ ## Action Types
80
+
81
+ | Type | Examples | Severity |
82
+ |------|----------|----------|
83
+ | `filesystem_read` | cat, grep, ls, find, head | low |
84
+ | `filesystem_write` | echo, touch, mkdir, cp, mv | medium |
85
+ | `filesystem_delete` | rm | medium |
86
+ | `git_safe` | git log, git status | low |
87
+ | `git_write` | git add, git commit | medium |
88
+ | `git_remote_write` | git push | medium |
89
+ | `git_discard` | git branch -d | medium |
90
+ | `git_history_rewrite` | git push --force, git rebase | critical |
91
+ | `network_outbound` | curl GET, wget | low |
92
+ | `network_write` | curl POST, scp, rsync | high |
93
+ | `network_diagnostic` | ping, traceroute | low |
94
+ | `package_install` | npm install, pip install | high |
95
+ | `package_run` | npm run | medium |
96
+ | `lang_exec` | python, node, bash, gdb | high |
97
+ | `process_signal` | kill, pkill | high |
98
+ | `container_read` | docker ps, docker logs | low |
99
+ | `container_write` | docker build, docker create | medium |
100
+ | `container_exec` | docker run, docker exec | medium |
101
+ | `container_destructive` | docker rm, docker stop | high |
102
+ | `service_write` | systemctl start, service restart | high |
103
+ | `agent_exec_bypass` | (reserved for future) | critical |
104
+ | `obfuscated` | (reserved for future) | critical |
105
+
106
+ ## Configuration
107
+
108
+ Environment variables (optional):
109
+
110
+ ```bash
111
+ OPTIMUS_API_URL=https://your-host/ # Backend base URL (same as log-llm-config; see optimus-tofu)
112
+ OPTIMUS_ENDPOINT=... # Alternative to OPTIMUS_API_URL
113
+ OPTIMUS_HARDWARE_UUID=... # Override when no stable hardware UUID (e.g. Linux CI)
114
+ OPTIMUS_BATCH_SIZE=50 # Batch size before flush (default: 1 for testing, 50 for prod)
115
+ OPTIMUS_DEBUG=1 # Verbose stderr (payload preview, endpoint, HTTP details)
116
+ OPTIMUS_TOOL_CALL_LOG=1 # One line per successful batch on stderr: host, path, status, count
117
+ ```
118
+
119
+ Hook wrappers append stderr to `~/.cursor/hook-errors.log` or `~/.claude/hook-errors.log`, so enable `OPTIMUS_TOOL_CALL_LOG` or `OPTIMUS_DEBUG` in `~/.optimuslabs/management/optimus_dev.env` (the hook exports these from that file).
120
+
121
+ Ingestion uses the same machine auth as `log-llm-config`: keys under `~/.optimuslabs/management/auth_key.txt`, handshake against `/endpoint_security/auth/`, and HMAC signatures on each batch (see backend `batch_create`).
122
+
123
+ ## Architecture
124
+
125
+ ```
126
+ ┌─────────────────────────────────────────────┐
127
+ │ Coding Agent (Claude Code, Cursor, etc.) │
128
+ └────────────────────┬────────────────────────┘
129
+ │ PreToolUse hook
130
+ ▼
131
+ ┌─────────────────────────────────────────────┐
132
+ │ optimus-tool-call (TypeScript) │
133
+ │ ├─ Classify command into action type │
134
+ │ ├─ Extract file paths, patterns, etc. │
135
+ │ ├─ Create telemetry event │
136
+ │ └─ Queue for async streaming │
137
+ └────────────────────┬────────────────────────┘
138
+ │ Non-blocking async
139
+ ▼
140
+ ┌─────────────────────────────────────────────┐
141
+ │ Django Backend (optimus_security) │
142
+ │ ├─ Receive batched events │
143
+ │ ├─ Calculate severity │
144
+ │ ├─ Store in SQLite │
145
+ │ └─ Expose via REST API │
146
+ └────────────────────┬────────────────────────┘
147
+ │ /api/tool-calls/events/recent/
148
+ ▼
149
+ ┌─────────────────────────────────────────────┐
150
+ │ Frontend Dashboard (React) │
151
+ │ ├─ Real-time audit log (2s polling) │
152
+ │ ├─ Color-coded severity/agent │
153
+ │ └─ Expandable command details │
154
+ └─────────────────────────────────────────────┘
155
+ ```
156
+
157
+ ## Development
158
+
159
+ ```bash
160
+ npm install
161
+ npm run build
162
+ npm run test
163
+ ```
164
+
165
+ ## Testing
166
+
167
+ E2E test with various commands:
168
+
169
+ ```bash
170
+ ./test-e2e.sh
171
+ ```
172
+
173
+ This will:
174
+ 1. Clear the audit log
175
+ 2. Run 50+ diverse commands (filesystem, git, network, package, etc.)
176
+ 3. Verify correct classification for each
177
+ 4. Display coverage summary
178
+
179
+ ## Performance
180
+
181
+ - **Classification latency**: <1ms per command
182
+ - **Telemetry overhead**: <50ms p99 (async, non-blocking)
183
+ - **Memory**: ~10MB resident (minimal buffering)
184
+ - **CPU**: Negligible (event-driven)
185
+
186
+ ## Safety
187
+
188
+ - ✅ Never blocks agent execution
189
+ - ✅ Always returns `permission: "allow"`
190
+ - ✅ Errors logged but never thrown
191
+ - ✅ Graceful degradation if backend unavailable
192
+ - ✅ Batch timeout ensures events flush (5s default)
193
+
194
+ ## References
195
+
196
+ - Based on nah taxonomy: https://github.com/manuelschipper/nah
197
+ - Integrated with Optimus Labs security platform
198
+ - Part of agent compliance and audit infrastructure
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * optimus-capture-prompt — Cursor hook to capture and store prompt text
4
+ *
5
+ * Runs on beforeSubmitPrompt hook. Reads the prompt from stdin (if available),
6
+ * stores it in a temp file keyed by session ID, so that the tool-call hook
7
+ * can retrieve it when processing tool invocations.
8
+ *
9
+ * Cursor hook protocol for beforeSubmitPrompt:
10
+ * - stdin: JSON with prompt text (format varies by Cursor version)
11
+ * - stdout: {"continue": true|false} JSON
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=capture-prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-prompt.d.ts","sourceRoot":"","sources":["../src/capture-prompt.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG"}
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * optimus-capture-prompt — Cursor hook to capture and store prompt text
4
+ *
5
+ * Runs on beforeSubmitPrompt hook. Reads the prompt from stdin (if available),
6
+ * stores it in a temp file keyed by session ID, so that the tool-call hook
7
+ * can retrieve it when processing tool invocations.
8
+ *
9
+ * Cursor hook protocol for beforeSubmitPrompt:
10
+ * - stdin: JSON with prompt text (format varies by Cursor version)
11
+ * - stdout: {"continue": true|false} JSON
12
+ */
13
+ import fs from "fs";
14
+ import os from "os";
15
+ import path from "path";
16
+ const dbg = (...args) => { if (process.env.OPTIMUS_DEBUG)
17
+ console.error(...args); };
18
+ async function main() {
19
+ const stdinData = await readStdin();
20
+ dbg("[optimus-capture-prompt] ===== HOOK STARTED =====");
21
+ dbg("[optimus-capture-prompt] stdin length:", stdinData.length);
22
+ dbg("[optimus-capture-prompt] stdin preview:", stdinData.slice(0, 200));
23
+ let promptText = null;
24
+ let payloadSessionId = null;
25
+ try {
26
+ const raw = JSON.parse(stdinData);
27
+ dbg("[optimus-capture-prompt] Parsed JSON successfully");
28
+ dbg("[optimus-capture-prompt] Raw keys:", Object.keys(raw));
29
+ dbg("[optimus-capture-prompt] Raw payload:", JSON.stringify(raw, null, 2).slice(0, 500));
30
+ // Extract session ID for Cursor (from conversation_id or session_id in payload)
31
+ payloadSessionId =
32
+ (typeof raw.conversation_id === "string" && raw.conversation_id) ||
33
+ (typeof raw.session_id === "string" && raw.session_id) ||
34
+ null;
35
+ // Extract prompt from various possible locations in the hook payload
36
+ promptText =
37
+ extractValue(raw, ["prompt"]) ||
38
+ extractValue(raw, ["text"]) ||
39
+ extractValue(raw, ["message"]) ||
40
+ extractValue(raw, ["input"]) ||
41
+ null;
42
+ // Try to extract from nested message structure
43
+ if (!promptText) {
44
+ const msg = raw.message;
45
+ if (msg && typeof msg === "object") {
46
+ promptText =
47
+ extractValue(msg, ["content"]) ||
48
+ extractValue(msg, ["text"]) ||
49
+ extractValue(msg, ["prompt"]) ||
50
+ null;
51
+ }
52
+ }
53
+ dbg("[optimus-capture-prompt] Extracted prompt text:", promptText ? `"${promptText.slice(0, 100)}..."` : "null");
54
+ }
55
+ catch (error) {
56
+ // Not valid JSON — might not have prompt in this hook payload
57
+ console.error("[optimus-capture-prompt] Failed to parse JSON:", error);
58
+ }
59
+ // If we have a prompt, store it in a temp file keyed by session ID
60
+ if (promptText) {
61
+ dbg("[optimus-capture-prompt] Storing prompt...");
62
+ try {
63
+ const sessionId = payloadSessionId ||
64
+ process.env.CURSOR_SESSION_ID ||
65
+ process.env.CURSOR_CODE_SESSION_ID ||
66
+ process.env.CLAUDE_CODE_SESSION_ID ||
67
+ "unknown";
68
+ const promptCacheDir = path.join(os.tmpdir(), "optimus-prompt-cache");
69
+ dbg("[optimus-capture-prompt] Session ID:", sessionId);
70
+ dbg("[optimus-capture-prompt] Cache dir:", promptCacheDir);
71
+ // Create cache directory if it doesn't exist
72
+ if (!fs.existsSync(promptCacheDir)) {
73
+ dbg("[optimus-capture-prompt] Creating cache directory...");
74
+ fs.mkdirSync(promptCacheDir, { recursive: true });
75
+ }
76
+ // Write prompt to temp file (with short TTL via filename timestamp)
77
+ const timestamp = Date.now();
78
+ const promptFile = path.join(promptCacheDir, `prompt-${sessionId}-${timestamp}.txt`);
79
+ fs.writeFileSync(promptFile, promptText, "utf-8");
80
+ dbg(`[optimus-capture-prompt] Wrote prompt file: ${promptFile}`);
81
+ // Also write a "latest" symlink for easy access
82
+ const latestFile = path.join(promptCacheDir, `prompt-${sessionId}.txt`);
83
+ try {
84
+ fs.unlinkSync(latestFile);
85
+ }
86
+ catch {
87
+ // File might not exist
88
+ }
89
+ try {
90
+ fs.symlinkSync(promptFile, latestFile);
91
+ dbg(`[optimus-capture-prompt] Created symlink: ${latestFile}`);
92
+ }
93
+ catch (e) {
94
+ dbg(`[optimus-capture-prompt] Symlink creation failed (non-fatal):`, e);
95
+ }
96
+ dbg(`[optimus-capture-prompt] SUCCESS: Stored prompt at ${promptFile}`);
97
+ // Clean up old prompt files (older than 5 minutes)
98
+ cleanupOldPromptFiles(promptCacheDir, sessionId);
99
+ }
100
+ catch (error) {
101
+ // Non-fatal — if we can't cache the prompt, the tool-call hook just won't have it
102
+ console.error("[optimus-capture-prompt] ERROR: Failed to store prompt:", error);
103
+ }
104
+ }
105
+ else {
106
+ dbg("[optimus-capture-prompt] No prompt text found in hook payload");
107
+ }
108
+ // Always allow — never block on prompt capture
109
+ const response = { continue: true };
110
+ dbg("[optimus-capture-prompt] Returning response:", JSON.stringify(response));
111
+ console.log(JSON.stringify(response));
112
+ }
113
+ async function readStdin() {
114
+ return new Promise((resolve) => {
115
+ let data = "";
116
+ process.stdin.setEncoding("utf8");
117
+ process.stdin.on("readable", () => {
118
+ let chunk;
119
+ while ((chunk = process.stdin.read()) !== null) {
120
+ data += chunk;
121
+ }
122
+ });
123
+ process.stdin.on("end", () => {
124
+ resolve(data);
125
+ });
126
+ process.stdin.on("error", () => {
127
+ resolve("");
128
+ });
129
+ });
130
+ }
131
+ function extractValue(obj, keys) {
132
+ for (const key of keys) {
133
+ const value = obj[key];
134
+ if (value !== undefined && value !== null && typeof value === "string") {
135
+ return value;
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ function cleanupOldPromptFiles(dir, sessionId) {
141
+ try {
142
+ const files = fs.readdirSync(dir);
143
+ const now = Date.now();
144
+ const maxAge = 5 * 60 * 1000; // 5 minutes
145
+ for (const file of files) {
146
+ // Only clean up files for this session
147
+ if (!file.startsWith(`prompt-${sessionId}-`))
148
+ continue;
149
+ const filePath = path.join(dir, file);
150
+ try {
151
+ const stat = fs.statSync(filePath);
152
+ if (now - stat.mtimeMs > maxAge) {
153
+ fs.unlinkSync(filePath);
154
+ }
155
+ }
156
+ catch {
157
+ // Ignore errors during cleanup
158
+ }
159
+ }
160
+ }
161
+ catch {
162
+ // Ignore errors during cleanup
163
+ }
164
+ }
165
+ main().catch((err) => {
166
+ if (process.env.OPTIMUS_DEBUG) {
167
+ console.error("[optimus-capture-prompt] Fatal error:", err);
168
+ }
169
+ const response = { continue: true };
170
+ console.log(JSON.stringify(response));
171
+ process.exit(0);
172
+ });
173
+ //# sourceMappingURL=capture-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-prompt.js","sourceRoot":"","sources":["../src/capture-prompt.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,GAAG,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;IAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,MAAM,SAAS,EAAE,CAAC;IAEpC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACzD,GAAG,CAAC,wCAAwC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAChE,GAAG,CAAC,yCAAyC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAExE,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,gBAAgB,GAAkB,IAAI,CAAC;IAE3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAElC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACzD,GAAG,CAAC,oCAAoC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,GAAG,CAAC,uCAAuC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAEzF,gFAAgF;QAChF,gBAAgB;YACd,CAAC,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,IAAI,GAAG,CAAC,eAAe,CAAC;gBAChE,CAAC,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC;gBACtD,IAAI,CAAC;QAEP,qEAAqE;QACrE,UAAU;YACR,YAAY,CAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;gBACrC,YAAY,CAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;gBACnC,YAAY,CAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBACtC,YAAY,CAAS,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC;gBACpC,IAAI,CAAC;QAEP,+CAA+C;QAC/C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC;YACxB,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACnC,UAAU;oBACR,YAAY,CAAS,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;wBACtC,YAAY,CAAS,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;wBACnC,YAAY,CAAS,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;wBACrC,IAAI,CAAC;YACT,CAAC;QACH,CAAC;QAED,GAAG,CAAC,iDAAiD,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACnH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8DAA8D;QAC9D,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;IAED,mEAAmE;IACnE,IAAI,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAClD,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,gBAAgB;gBAChC,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAC7B,OAAO,CAAC,GAAG,CAAC,sBAAsB;gBAClC,OAAO,CAAC,GAAG,CAAC,sBAAsB;gBAClC,SAAS,CAAC;YAEZ,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;YAEtE,GAAG,CAAC,sCAAsC,EAAE,SAAS,CAAC,CAAC;YACvD,GAAG,CAAC,qCAAqC,EAAE,cAAc,CAAC,CAAC;YAE3D,6CAA6C;YAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnC,GAAG,CAAC,sDAAsD,CAAC,CAAC;gBAC5D,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,CAAC;YAED,oEAAoE;YACpE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,SAAS,IAAI,SAAS,MAAM,CAAC,CAAC;YACrF,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YAClD,GAAG,CAAC,+CAA+C,UAAU,EAAE,CAAC,CAAC;YAEjE,gDAAgD;YAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,SAAS,MAAM,CAAC,CAAC;YACxE,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,uBAAuB;YACzB,CAAC;YACD,IAAI,CAAC;gBACH,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;gBACvC,GAAG,CAAC,6CAA6C,UAAU,EAAE,CAAC,CAAC;YACjE,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,CAAC,+DAA+D,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,GAAG,CAAC,sDAAsD,UAAU,EAAE,CAAC,CAAC;YAExE,mDAAmD;YACnD,qBAAqB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kFAAkF;YAClF,OAAO,CAAC,KAAK,CAAC,yDAAyD,EAAE,KAAK,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,+DAA+D,CAAC,CAAC;IACvE,CAAC;IAED,+CAA+C;IAC/C,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACpC,GAAG,CAAC,8CAA8C,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAChC,IAAI,KAAoB,CAAC;YACzB,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC/C,IAAI,IAAI,KAAK,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC7B,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,YAAY,CAAI,GAA4B,EAAE,IAAc;IACnE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvE,OAAO,KAAU,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW,EAAE,SAAiB;IAC3D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;QAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,uCAAuC;YACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,SAAS,GAAG,CAAC;gBAAE,SAAS;YAEvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBACnC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC;oBAChC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;IAC9D,CAAC;IACD,MAAM,QAAQ,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * optimus-tool-call — agentic audit sensor entry point
4
+ *
5
+ * Reads hook JSON from stdin, builds a raw telemetry event, streams it to the
6
+ * backend (server classifies), returns allow response.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
package/dist/index.js ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * optimus-tool-call — agentic audit sensor entry point
4
+ *
5
+ * Reads hook JSON from stdin, builds a raw telemetry event, streams it to the
6
+ * backend (server classifies), returns allow response.
7
+ */
8
+ import fs from "fs";
9
+ import { buildTelemetryEvent, eventToDict } from "./lib/telemetry.js";
10
+ import { queueEvent, ensureShutdown } from "./lib/streaming.js";
11
+ import { normalizeToCanonical } from "./lib/telemetry/canonical.js";
12
+ const dbg = (...args) => { if (process.env.OPTIMUS_DEBUG)
13
+ console.error(...args); };
14
+ /** FunctionalRun.command — tool name plus primary path/target when present. */
15
+ function clientEventCommand(canonical) {
16
+ const name = (canonical.tool_name || "tool_call").trim() || "tool_call";
17
+ const input = canonical.tool_input || {};
18
+ for (const key of ["path", "target_file", "file", "uri"]) {
19
+ const v = input[key];
20
+ if (typeof v === "string" && v.trim()) {
21
+ return `${name} ${v.trim()}`;
22
+ }
23
+ }
24
+ const cmd = input.command;
25
+ if (typeof cmd === "string" && cmd.trim()) {
26
+ return `${name} ${cmd.trim()}`;
27
+ }
28
+ return name;
29
+ }
30
+ function reportClientEventOk(canonical) {
31
+ void import("./lib/client-event.js")
32
+ .then(({ reportToolCallRun }) => reportToolCallRun({
33
+ outcome: "ok",
34
+ command: clientEventCommand(canonical),
35
+ message: canonical.tool_name || "",
36
+ agent: canonical.agent,
37
+ }))
38
+ .catch(() => { });
39
+ }
40
+ async function main() {
41
+ dbg("[optimus-tool-call] ===== HOOK STARTED =====");
42
+ dbg("[optimus-tool-call] NODE_ENV:", process.env.NODE_ENV);
43
+ dbg("[optimus-tool-call] CURSOR:", process.env.CURSOR);
44
+ dbg("[optimus-tool-call] CURSOR_SESSION_ID:", process.env.CURSOR_SESSION_ID);
45
+ dbg("[optimus-tool-call] CLAUDE_CODE_SESSION_ID:", process.env.CLAUDE_CODE_SESSION_ID);
46
+ // Setup shutdown handling
47
+ ensureShutdown();
48
+ // Read stdin
49
+ const stdinData = await readStdin();
50
+ dbg("[optimus-tool-call] stdin length:", stdinData.length);
51
+ dbg("[optimus-tool-call] stdin preview:", stdinData.slice(0, 300));
52
+ // Parse and normalize to canonical format
53
+ let canonical;
54
+ try {
55
+ const raw = JSON.parse(stdinData);
56
+ dbg("[optimus-tool-call] Parsed JSON successfully");
57
+ dbg("[optimus-tool-call] Raw keys:", Object.keys(raw));
58
+ // Normalize to canonical format (works for both Claude and Cursor)
59
+ canonical = normalizeToCanonical(raw);
60
+ dbg("[optimus-tool-call] Detected agent:", canonical.agent);
61
+ dbg("[optimus-tool-call] Hook event name:", canonical.hook_event_name);
62
+ dbg("[optimus-tool-call] Tool name:", canonical.tool_name);
63
+ // Try to extract user prompt from transcript file (works for both Claude and Cursor)
64
+ if (!canonical.user_prompt) {
65
+ const transcriptPath = typeof raw.transcript_path === "string" ? raw.transcript_path : null;
66
+ if (transcriptPath) {
67
+ const userPrompt = readLastUserPrompt(transcriptPath);
68
+ if (userPrompt) {
69
+ canonical = { ...canonical, user_prompt: userPrompt };
70
+ }
71
+ }
72
+ }
73
+ dbg("[optimus-tool-call] Canonical event:", {
74
+ agent: canonical.agent,
75
+ hook_event_name: canonical.hook_event_name,
76
+ tool_name: canonical.tool_name,
77
+ user_prompt_preview: canonical.user_prompt?.slice(0, 100),
78
+ });
79
+ }
80
+ catch (error) {
81
+ // Invalid JSON or parse error — allow and return
82
+ console.error("[optimus-tool-call] ERROR: Failed to parse:", error);
83
+ const response = { continue: true, permission: "allow" };
84
+ console.log(JSON.stringify(response));
85
+ return;
86
+ }
87
+ // Convert canonical to ToolInvocation (for backward compatibility with existing code)
88
+ const invocation = {
89
+ tool_name: canonical.tool_name,
90
+ tool_input: canonical.tool_input,
91
+ tool_use_id: canonical.tool_use_id,
92
+ session_id: canonical.session_id,
93
+ cwd: canonical.cwd,
94
+ hook_event_name: canonical.hook_event_name,
95
+ model: canonical.model,
96
+ user_prompt: canonical.user_prompt,
97
+ raw_event: canonical.raw_event,
98
+ };
99
+ // Build telemetry event
100
+ const event = buildTelemetryEvent(invocation, canonical.agent, canonical.session_id);
101
+ if (event) {
102
+ // Server classifies `action_type`; queue raw invocation for all non-null events.
103
+ await queueEvent(event);
104
+ reportClientEventOk(canonical);
105
+ if (process.env.OPTIMUS_DEBUG) {
106
+ const eventDict = eventToDict(event);
107
+ console.error(`[optimus-tool-call] Queued event: ${JSON.stringify(eventDict)}`);
108
+ }
109
+ }
110
+ // Always return allow (never block)
111
+ const response = { continue: true, permission: "allow" };
112
+ console.log(JSON.stringify(response));
113
+ }
114
+ async function readStdin() {
115
+ /**
116
+ * Read all of stdin until EOF.
117
+ */
118
+ return new Promise((resolve, reject) => {
119
+ let data = "";
120
+ process.stdin.setEncoding("utf8");
121
+ process.stdin.on("readable", () => {
122
+ let chunk;
123
+ while ((chunk = process.stdin.read()) !== null) {
124
+ data += chunk;
125
+ }
126
+ });
127
+ process.stdin.on("end", () => {
128
+ resolve(data);
129
+ });
130
+ process.stdin.on("error", (err) => {
131
+ reject(err);
132
+ });
133
+ });
134
+ }
135
+ /**
136
+ * Read the Claude Code session transcript (JSONL) and return the text of the
137
+ * last user-typed message. Each line is a JSON object; user turns look like:
138
+ * {"type":"user","message":{"role":"user","content":"<text>"},...}
139
+ * Failures are non-fatal — returns null if the file is missing or unreadable.
140
+ */
141
+ function readLastUserPrompt(transcriptPath) {
142
+ try {
143
+ const raw = fs.readFileSync(transcriptPath, "utf-8");
144
+ const lines = raw.split("\n");
145
+ for (let i = lines.length - 1; i >= 0; i--) {
146
+ const line = lines[i].trim();
147
+ if (!line)
148
+ continue;
149
+ try {
150
+ const entry = JSON.parse(line);
151
+ if (entry.type !== "user")
152
+ continue;
153
+ const msg = entry.message;
154
+ if (!msg || msg.role !== "user")
155
+ continue;
156
+ const content = msg.content;
157
+ if (typeof content === "string" && content.trim()) {
158
+ return content.trim();
159
+ }
160
+ if (Array.isArray(content)) {
161
+ const blocks = content;
162
+ // Skip tool_result turns — those are API feedback, not user-typed messages
163
+ if (blocks.some((c) => c.type === "tool_result"))
164
+ continue;
165
+ const text = blocks
166
+ .filter((c) => c.type === "text" && typeof c.text === "string")
167
+ .map((c) => c.text)
168
+ .join("\n")
169
+ .trim();
170
+ if (text)
171
+ return text;
172
+ }
173
+ }
174
+ catch {
175
+ // skip malformed lines
176
+ }
177
+ }
178
+ }
179
+ catch {
180
+ // file missing or unreadable — non-fatal
181
+ }
182
+ return null;
183
+ }
184
+ // Run
185
+ main().catch(async (err) => {
186
+ console.error("[optimus-tool-call] Fatal error:", err);
187
+ // Report the tool_call failure (awaited so it lands before exit), then always allow.
188
+ try {
189
+ const { reportToolCallRun } = await import("./lib/client-event.js");
190
+ await reportToolCallRun({
191
+ outcome: "failed",
192
+ message: err instanceof Error ? `${err.name}: ${err.message}` : String(err),
193
+ detail: err instanceof Error && err.stack ? err.stack : String(err),
194
+ });
195
+ }
196
+ catch {
197
+ // never let telemetry mask the allow response
198
+ }
199
+ const response = { continue: true, permission: "allow" };
200
+ console.log(JSON.stringify(response));
201
+ process.exit(0); // Never exit non-zero (never block)
202
+ });
203
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ type ToolCallRunFields = {
2
+ outcome: "started" | "ok" | "failed";
3
+ command?: string;
4
+ message?: string;
5
+ detail?: string;
6
+ exit_code?: number | null;
7
+ /** From normalizeToCanonical when shell env is missing. */
8
+ agent?: string;
9
+ };
10
+ export declare function reportToolCallRun(fields: ToolCallRunFields): Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=client-event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-event.d.ts","sourceRoot":"","sources":["../../src/lib/client-event.ts"],"names":[],"mappings":"AAgEA,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,SAAS,GAAG,IAAI,GAAG,QAAQ,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAuBF,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8ChF"}