aibroker 0.1.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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/adapters/iterm/core.d.ts +28 -0
  4. package/dist/adapters/iterm/core.d.ts.map +1 -0
  5. package/dist/adapters/iterm/core.js +191 -0
  6. package/dist/adapters/iterm/core.js.map +1 -0
  7. package/dist/adapters/iterm/dictation.d.ts +26 -0
  8. package/dist/adapters/iterm/dictation.d.ts.map +1 -0
  9. package/dist/adapters/iterm/dictation.js +99 -0
  10. package/dist/adapters/iterm/dictation.js.map +1 -0
  11. package/dist/adapters/iterm/sessions.d.ts +31 -0
  12. package/dist/adapters/iterm/sessions.d.ts.map +1 -0
  13. package/dist/adapters/iterm/sessions.js +156 -0
  14. package/dist/adapters/iterm/sessions.js.map +1 -0
  15. package/dist/adapters/kokoro/media.d.ts +32 -0
  16. package/dist/adapters/kokoro/media.d.ts.map +1 -0
  17. package/dist/adapters/kokoro/media.js +157 -0
  18. package/dist/adapters/kokoro/media.js.map +1 -0
  19. package/dist/adapters/kokoro/tts.d.ts +19 -0
  20. package/dist/adapters/kokoro/tts.d.ts.map +1 -0
  21. package/dist/adapters/kokoro/tts.js +157 -0
  22. package/dist/adapters/kokoro/tts.js.map +1 -0
  23. package/dist/adapters/session/backend.d.ts +22 -0
  24. package/dist/adapters/session/backend.d.ts.map +1 -0
  25. package/dist/adapters/session/backend.js +43 -0
  26. package/dist/adapters/session/backend.js.map +1 -0
  27. package/dist/backend/api.d.ts +20 -0
  28. package/dist/backend/api.d.ts.map +1 -0
  29. package/dist/backend/api.js +26 -0
  30. package/dist/backend/api.js.map +1 -0
  31. package/dist/core/log.d.ts +7 -0
  32. package/dist/core/log.d.ts.map +1 -0
  33. package/dist/core/log.js +14 -0
  34. package/dist/core/log.js.map +1 -0
  35. package/dist/core/markdown.d.ts +32 -0
  36. package/dist/core/markdown.d.ts.map +1 -0
  37. package/dist/core/markdown.js +71 -0
  38. package/dist/core/markdown.js.map +1 -0
  39. package/dist/core/mime.d.ts +11 -0
  40. package/dist/core/mime.d.ts.map +1 -0
  41. package/dist/core/mime.js +46 -0
  42. package/dist/core/mime.js.map +1 -0
  43. package/dist/core/persistence.d.ts +20 -0
  44. package/dist/core/persistence.d.ts.map +1 -0
  45. package/dist/core/persistence.js +108 -0
  46. package/dist/core/persistence.js.map +1 -0
  47. package/dist/core/router.d.ts +24 -0
  48. package/dist/core/router.d.ts.map +1 -0
  49. package/dist/core/router.js +38 -0
  50. package/dist/core/router.js.map +1 -0
  51. package/dist/core/state.d.ts +45 -0
  52. package/dist/core/state.d.ts.map +1 -0
  53. package/dist/core/state.js +82 -0
  54. package/dist/core/state.js.map +1 -0
  55. package/dist/index.d.ts +35 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +38 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/ipc/client.d.ts +45 -0
  60. package/dist/ipc/client.d.ts.map +1 -0
  61. package/dist/ipc/client.js +199 -0
  62. package/dist/ipc/client.js.map +1 -0
  63. package/dist/ipc/server.d.ts +34 -0
  64. package/dist/ipc/server.d.ts.map +1 -0
  65. package/dist/ipc/server.js +123 -0
  66. package/dist/ipc/server.js.map +1 -0
  67. package/dist/types/backend.d.ts +25 -0
  68. package/dist/types/backend.d.ts.map +1 -0
  69. package/dist/types/backend.js +9 -0
  70. package/dist/types/backend.js.map +1 -0
  71. package/dist/types/index.d.ts +6 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/index.js +6 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/types/ipc.d.ts +18 -0
  76. package/dist/types/ipc.d.ts.map +1 -0
  77. package/dist/types/ipc.js +6 -0
  78. package/dist/types/ipc.js.map +1 -0
  79. package/dist/types/session.d.ts +29 -0
  80. package/dist/types/session.d.ts.map +1 -0
  81. package/dist/types/session.js +5 -0
  82. package/dist/types/session.js.map +1 -0
  83. package/dist/types/transport.d.ts +43 -0
  84. package/dist/types/transport.d.ts.map +1 -0
  85. package/dist/types/transport.js +8 -0
  86. package/dist/types/transport.js.map +1 -0
  87. package/dist/types/voice.d.ts +17 -0
  88. package/dist/types/voice.d.ts.map +1 -0
  89. package/dist/types/voice.js +5 -0
  90. package/dist/types/voice.js.map +1 -0
  91. package/package.json +35 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Matthias Nott
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,40 @@
1
+ # aibroker
2
+
3
+ Platform-agnostic AI message broker — shared infrastructure for messaging
4
+ bridges that connect WhatsApp, Telegram, and other channels to Claude Code.
5
+
6
+ ## Family
7
+
8
+ | Package | Channel | Repo |
9
+ |---------|---------|------|
10
+ | **aibroker** | Shared core | [github.com/mnott/AIBroker](https://github.com/mnott/AIBroker) |
11
+ | **whazaa** | WhatsApp | [github.com/mnott/Whazaa](https://github.com/mnott/Whazaa) |
12
+ | **telex** | Telegram | [github.com/mnott/Telex](https://github.com/mnott/Telex) |
13
+
14
+ ## What's Inside
15
+
16
+ - Logging with configurable prefix (`setLogPrefix`)
17
+ - Session state management and message queuing
18
+ - File persistence with configurable data dir (`setAppDir`)
19
+ - Unix Domain Socket IPC (server + client)
20
+ - macOS iTerm2 adapter (AppleScript session management)
21
+ - Kokoro TTS (local speech synthesis + Whisper transcription)
22
+
23
+ ## Usage
24
+
25
+ ```typescript
26
+ import { setLogPrefix, setAppDir } from "aibroker";
27
+
28
+ setLogPrefix("my-app");
29
+ setAppDir("/path/to/data");
30
+ ```
31
+
32
+ ## Hard Rule
33
+
34
+ aibroker never imports `@whiskeysockets/baileys`, `telegram`/`gramjs`,
35
+ `better-sqlite3`, `qrcode`, or any transport SDK. Those belong in
36
+ the per-channel packages.
37
+
38
+ ## License
39
+
40
+ MIT — Matthias Nott
@@ -0,0 +1,28 @@
1
+ /**
2
+ * adapters/iterm/core.ts — Low-level iTerm2 AppleScript primitives.
3
+ *
4
+ * Foundation of all iTerm2 communication. Wraps `osascript` and `spawnSync`
5
+ * with zero transport-specific imports.
6
+ */
7
+ export declare function runAppleScript(script: string): string | null;
8
+ export declare function stripItermPrefix(id: string | undefined): string | undefined;
9
+ export declare function withSessionAppleScript(sessionId: string, body: string, fallback?: string): string;
10
+ export declare function sendKeystrokeToSession(sessionId: string, asciiCode: number): boolean;
11
+ export declare function sendEscapeSequenceToSession(sessionId: string, dirChar: string): boolean;
12
+ export declare function typeIntoSession(sessionId: string, text: string): boolean;
13
+ export declare function pasteTextIntoSession(sessionId: string, text: string): boolean;
14
+ export declare function findClaudeSession(): string | null;
15
+ export declare function isClaudeRunningInSession(sessionId: string): boolean;
16
+ export declare function isItermRunning(): boolean;
17
+ export declare function isItermSessionAlive(sessionId: string): boolean;
18
+ export declare function isScreenLocked(): boolean;
19
+ export declare function writeToTty(ttyPath: string, text: string): boolean;
20
+ export interface SessionSnapshot {
21
+ id: string;
22
+ name: string;
23
+ tty: string;
24
+ atPrompt: boolean;
25
+ paiName: string | null;
26
+ }
27
+ export declare function snapshotAllSessions(): SessionSnapshot[];
28
+ //# sourceMappingURL=core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../src/adapters/iterm/core.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5D;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,MAAM,CActG;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAQpF;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQvF;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxE;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ7E;AAED,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CA+BjD;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAcnE;AAED,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAO9D;AAED,wBAAgB,cAAc,IAAI,OAAO,CAWxC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CA8BjE;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,wBAAgB,mBAAmB,IAAI,eAAe,EAAE,CAyCvD"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * adapters/iterm/core.ts — Low-level iTerm2 AppleScript primitives.
3
+ *
4
+ * Foundation of all iTerm2 communication. Wraps `osascript` and `spawnSync`
5
+ * with zero transport-specific imports.
6
+ */
7
+ import { spawnSync } from "node:child_process";
8
+ import { log } from "../../core/log.js";
9
+ export function runAppleScript(script) {
10
+ const result = spawnSync("osascript", [], {
11
+ input: script,
12
+ stdio: ["pipe", "pipe", "pipe"],
13
+ timeout: 4_000,
14
+ });
15
+ if (result.status !== 0)
16
+ return null;
17
+ return result.stdout?.toString().trim() ?? null;
18
+ }
19
+ export function stripItermPrefix(id) {
20
+ if (!id)
21
+ return id;
22
+ const colonIdx = id.lastIndexOf(":");
23
+ return colonIdx >= 0 ? id.slice(colonIdx + 1) : id;
24
+ }
25
+ export function withSessionAppleScript(sessionId, body, fallback = 'return ""') {
26
+ const escaped = sessionId.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
27
+ return `tell application "iTerm2"
28
+ repeat with aWindow in windows
29
+ repeat with aTab in tabs of aWindow
30
+ repeat with aSession in sessions of aTab
31
+ if id of aSession is "${escaped}" then
32
+ ${body}
33
+ end if
34
+ end repeat
35
+ end repeat
36
+ end repeat
37
+ ${fallback}
38
+ end tell`;
39
+ }
40
+ export function sendKeystrokeToSession(sessionId, asciiCode) {
41
+ const script = withSessionAppleScript(sessionId, ` tell aSession to write text (ASCII character ${asciiCode}) newline no\n return "ok"`, 'return "not_found"');
42
+ const result = runAppleScript(script);
43
+ return result === "ok";
44
+ }
45
+ export function sendEscapeSequenceToSession(sessionId, dirChar) {
46
+ const script = withSessionAppleScript(sessionId, ` tell aSession to write text (ASCII character 27) & "[${dirChar}" newline no\n return "ok"`, 'return "not_found"');
47
+ const result = runAppleScript(script);
48
+ return result === "ok";
49
+ }
50
+ export function typeIntoSession(sessionId, text) {
51
+ if (!pasteTextIntoSession(sessionId, text))
52
+ return false;
53
+ sendKeystrokeToSession(sessionId, 13);
54
+ return true;
55
+ }
56
+ export function pasteTextIntoSession(sessionId, text) {
57
+ const escaped = text.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
58
+ const textScript = withSessionAppleScript(sessionId, ` tell aSession to write text "${escaped}" newline no\n return "ok"`, 'return "not_found"');
59
+ return runAppleScript(textScript) === "ok";
60
+ }
61
+ export function findClaudeSession() {
62
+ const script = `
63
+ tell application "iTerm2"
64
+ set output to ""
65
+ repeat with aWindow in windows
66
+ repeat with aTab in tabs of aWindow
67
+ repeat with aSession in sessions of aTab
68
+ set sessionId to id of aSession
69
+ set sessionName to name of aSession
70
+ set output to output & sessionId & (ASCII character 9) & sessionName & linefeed
71
+ end repeat
72
+ end repeat
73
+ end repeat
74
+ return output
75
+ end tell`;
76
+ const result = runAppleScript(script);
77
+ if (!result)
78
+ return null;
79
+ const lines = result.split("\n").filter(Boolean);
80
+ for (const line of lines) {
81
+ const tabIdx = line.indexOf("\t");
82
+ if (tabIdx < 0)
83
+ continue;
84
+ const id = line.substring(0, tabIdx);
85
+ const name = line.substring(tabIdx + 1).toLowerCase();
86
+ if (name.includes("claude")) {
87
+ log(`Found claude session: ${id} ("${line.substring(tabIdx + 1)}")`);
88
+ return id;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+ export function isClaudeRunningInSession(sessionId) {
94
+ const script = withSessionAppleScript(sessionId, ` if (is at shell prompt of aSession) then\n return "shell"\n else\n return "running"\n end if`, 'return "not_found"');
95
+ const result = runAppleScript(script);
96
+ if (result === "running")
97
+ return true;
98
+ if (result === "shell") {
99
+ log(`Session ${sessionId} is at shell prompt — Claude has exited.`);
100
+ }
101
+ else {
102
+ log(`Session ${sessionId} not found in iTerm2.`);
103
+ }
104
+ return false;
105
+ }
106
+ export function isItermRunning() {
107
+ const result = spawnSync("pgrep", ["-x", "iTerm2"], {
108
+ stdio: ["pipe", "pipe", "pipe"],
109
+ timeout: 3_000,
110
+ });
111
+ return result.status === 0;
112
+ }
113
+ export function isItermSessionAlive(sessionId) {
114
+ const script = withSessionAppleScript(sessionId, ` return "alive"`, 'return "gone"');
115
+ return runAppleScript(script) === "alive";
116
+ }
117
+ export function isScreenLocked() {
118
+ try {
119
+ const result = spawnSync("sh", ["-c", "ioreg -n Root -d1 -a | grep -c CGSSessionScreenIsLocked"], { timeout: 3_000, encoding: "utf8" });
120
+ return parseInt((result.stdout ?? "0").trim(), 10) > 0;
121
+ }
122
+ catch {
123
+ return false;
124
+ }
125
+ }
126
+ export function writeToTty(ttyPath, text) {
127
+ if (!ttyPath || !ttyPath.startsWith("/dev/ttys")) {
128
+ log(`writeToTty: invalid tty path "${ttyPath}"`);
129
+ return false;
130
+ }
131
+ const statResult = spawnSync("test", ["-c", ttyPath], {
132
+ stdio: ["pipe", "pipe", "pipe"],
133
+ timeout: 1_000,
134
+ });
135
+ if (statResult.status !== 0) {
136
+ log(`writeToTty: device not found: ${ttyPath}`);
137
+ return false;
138
+ }
139
+ const safeText = text.replace(/'/g, "'\\''");
140
+ const writeResult = spawnSync("sh", ["-c", `printf '%s\\n' '${safeText}' > ${ttyPath}`], { stdio: ["pipe", "pipe", "pipe"], timeout: 2_000 });
141
+ if (writeResult.status !== 0) {
142
+ const stderr = writeResult.stderr?.toString().trim() ?? "";
143
+ log(`writeToTty: failed for ${ttyPath} — ${stderr || "exit " + writeResult.status}`);
144
+ return false;
145
+ }
146
+ log(`writeToTty: delivered ${text.length} chars to ${ttyPath}`);
147
+ return true;
148
+ }
149
+ export function snapshotAllSessions() {
150
+ const script = `
151
+ tell application "iTerm2"
152
+ set output to ""
153
+ repeat with aWindow in windows
154
+ repeat with aTab in tabs of aWindow
155
+ repeat with aSession in sessions of aTab
156
+ set sessionId to id of aSession
157
+ set sessionName to name of aSession
158
+ set sessionTty to tty of aSession
159
+ set isAtPrompt to (is at shell prompt of aSession)
160
+ tell aSession
161
+ try
162
+ set paiName to (variable named "user.paiName")
163
+ on error
164
+ set paiName to ""
165
+ end try
166
+ end tell
167
+ set output to output & sessionId & (ASCII character 9) & sessionName & (ASCII character 9) & sessionTty & (ASCII character 9) & (isAtPrompt as text) & (ASCII character 9) & paiName & linefeed
168
+ end repeat
169
+ end repeat
170
+ end repeat
171
+ return output
172
+ end tell`;
173
+ const result = runAppleScript(script);
174
+ if (!result)
175
+ return [];
176
+ const sessions = [];
177
+ for (const line of result.split("\n").filter(Boolean)) {
178
+ const parts = line.split("\t");
179
+ if (parts.length < 4)
180
+ continue;
181
+ sessions.push({
182
+ id: parts[0],
183
+ name: parts[1],
184
+ tty: parts[2],
185
+ atPrompt: parts[3] === "true",
186
+ paiName: (parts[4] && parts[4] !== "missing value" && parts[4] !== "") ? parts[4] : null,
187
+ });
188
+ }
189
+ return sessions;
190
+ }
191
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/adapters/iterm/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * adapters/iterm/dictation.ts — Local mic recording and Whisper transcription.
3
+ *
4
+ * Provides recordFromMic() and transcribeLocalAudio() for desk dictation.
5
+ * Both functions use sox for recording and the Whisper CLI for transcription.
6
+ */
7
+ /** Absolute path to the Whisper CLI binary. */
8
+ export declare const WHISPER_BIN: string;
9
+ /** Whisper model name (overridable via AIBROKER_WHISPER_MODEL env). */
10
+ export declare const WHISPER_MODEL: string;
11
+ /**
12
+ * Record audio from the default Mac microphone using sox.
13
+ * Stops automatically after ~2 seconds of silence.
14
+ *
15
+ * @param maxDurationSec - Maximum recording duration (default 60s).
16
+ * @returns Absolute path to the recorded WAV file.
17
+ */
18
+ export declare function recordFromMic(maxDurationSec?: number): Promise<string>;
19
+ /**
20
+ * Transcribe a local audio file using the Whisper CLI.
21
+ *
22
+ * @param audioPath - Absolute path to the audio file.
23
+ * @returns The raw transcript text.
24
+ */
25
+ export declare function transcribeLocalAudio(audioPath: string): Promise<string>;
26
+ //# sourceMappingURL=dictation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dictation.d.ts","sourceRoot":"","sources":["../../../src/adapters/iterm/dictation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,+CAA+C;AAC/C,eAAO,MAAM,WAAW,QAGR,CAAC;AAEjB,uEAAuE;AACvE,eAAO,MAAM,aAAa,QAA2H,CAAC;AAQtJ;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,cAAc,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAoCxE;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAyC7E"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * adapters/iterm/dictation.ts — Local mic recording and Whisper transcription.
3
+ *
4
+ * Provides recordFromMic() and transcribeLocalAudio() for desk dictation.
5
+ * Both functions use sox for recording and the Whisper CLI for transcription.
6
+ */
7
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
8
+ import { promisify } from "node:util";
9
+ import { tmpdir } from "node:os";
10
+ import { join } from "node:path";
11
+ import { execFile } from "node:child_process";
12
+ import { log } from "../../core/log.js";
13
+ const execFileAsync = promisify(execFile);
14
+ /** Absolute path to the Whisper CLI binary. */
15
+ export const WHISPER_BIN = ["/opt/homebrew/bin/whisper", "/usr/local/bin/whisper", "whisper"].find((p) => p === "whisper" || existsSync(p)) ?? "whisper";
16
+ /** Whisper model name (overridable via AIBROKER_WHISPER_MODEL env). */
17
+ export const WHISPER_MODEL = process.env.AIBROKER_WHISPER_MODEL ?? process.env.MSGBRIDGE_WHISPER_MODEL ?? process.env.WHAZAA_WHISPER_MODEL ?? "small";
18
+ /** Absolute path to the sox binary. */
19
+ const SOX_BIN = ["/opt/homebrew/bin/sox", "/usr/local/bin/sox", "sox"].find((p) => p === "sox" || existsSync(p)) ?? "sox";
20
+ /**
21
+ * Record audio from the default Mac microphone using sox.
22
+ * Stops automatically after ~2 seconds of silence.
23
+ *
24
+ * @param maxDurationSec - Maximum recording duration (default 60s).
25
+ * @returns Absolute path to the recorded WAV file.
26
+ */
27
+ export async function recordFromMic(maxDurationSec = 60) {
28
+ const wavPath = join(tmpdir(), `aibroker-dictation-${Date.now()}.wav`);
29
+ // Audible start indicator
30
+ execFile("afplay", ["/System/Library/Sounds/Tink.aiff"], () => { });
31
+ log(`Dictation: recording to ${wavPath} (max ${maxDurationSec}s)...`);
32
+ try {
33
+ await execFileAsync(SOX_BIN, [
34
+ "-d", "-r", "16000", "-c", "1", "-b", "16",
35
+ wavPath,
36
+ "silence", "1", "0.2", "1%", "1", "2.0", "1%",
37
+ ], {
38
+ timeout: maxDurationSec * 1000,
39
+ env: {
40
+ ...process.env,
41
+ PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH || "/usr/bin:/bin"}`,
42
+ },
43
+ });
44
+ }
45
+ catch (err) {
46
+ if (!existsSync(wavPath)) {
47
+ throw new Error(`Recording failed: ${err instanceof Error ? err.message : String(err)}`);
48
+ }
49
+ log("Dictation: sox exited (likely timeout/silence stop) — file exists, continuing.");
50
+ }
51
+ // Audible stop indicator
52
+ execFile("afplay", ["/System/Library/Sounds/Pop.aiff"], () => { });
53
+ log(`Dictation: recorded ${wavPath}`);
54
+ return wavPath;
55
+ }
56
+ /**
57
+ * Transcribe a local audio file using the Whisper CLI.
58
+ *
59
+ * @param audioPath - Absolute path to the audio file.
60
+ * @returns The raw transcript text.
61
+ */
62
+ export async function transcribeLocalAudio(audioPath) {
63
+ const base = audioPath.replace(/\.[^.]+$/, "");
64
+ const baseName = base.split("/").pop();
65
+ const outDir = tmpdir();
66
+ const filesToClean = [
67
+ join(outDir, `${baseName}.txt`),
68
+ join(outDir, `${baseName}.json`),
69
+ join(outDir, `${baseName}.vtt`),
70
+ join(outDir, `${baseName}.srt`),
71
+ join(outDir, `${baseName}.tsv`),
72
+ ];
73
+ try {
74
+ log(`Dictation: transcribing ${audioPath} (model=${WHISPER_MODEL})...`);
75
+ await execFileAsync(WHISPER_BIN, [audioPath, "--model", WHISPER_MODEL, "--output_format", "txt", "--output_dir", outDir, "--verbose", "False"], {
76
+ timeout: 120_000,
77
+ env: {
78
+ ...process.env,
79
+ PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH || "/usr/bin:/bin"}`,
80
+ },
81
+ });
82
+ const txtPath = join(outDir, `${baseName}.txt`);
83
+ if (!existsSync(txtPath)) {
84
+ throw new Error(`Whisper did not produce output at ${txtPath}`);
85
+ }
86
+ const transcript = readFileSync(txtPath, "utf-8").trim();
87
+ log(`Dictation: transcript (${transcript.length} chars): ${transcript.slice(0, 80)}`);
88
+ return transcript;
89
+ }
90
+ finally {
91
+ for (const f of filesToClean) {
92
+ try {
93
+ unlinkSync(f);
94
+ }
95
+ catch { /* ignore */ }
96
+ }
97
+ }
98
+ }
99
+ //# sourceMappingURL=dictation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dictation.js","sourceRoot":"","sources":["../../../src/adapters/iterm/dictation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * adapters/iterm/sessions.ts — Higher-level iTerm2 session management.
3
+ *
4
+ * Session variables, tab naming, discovery, creation, and lifecycle.
5
+ * Does NOT import any transport send functions — callers handle message delivery.
6
+ */
7
+ export declare function setItermSessionVar(itermSessionId: string, name: string): void;
8
+ export declare function setItermTabName(itermSessionId: string, name: string): void;
9
+ export declare function getItermSessionVar(itermSessionId: string): string | null;
10
+ export declare function findItermSessionForTermId(termSessionId: string, itermSessionIdHint?: string): string | null;
11
+ export declare function listClaudeSessions(): Array<{
12
+ id: string;
13
+ name: string;
14
+ }>;
15
+ /**
16
+ * Build a full session list with type classification and PAI name resolution.
17
+ * Returns the data used by /s command.
18
+ */
19
+ export declare function getSessionList(): Array<{
20
+ id: string;
21
+ name: string;
22
+ path: string;
23
+ type: "claude" | "terminal";
24
+ paiName: string | null;
25
+ atPrompt: boolean;
26
+ }>;
27
+ export declare function createClaudeSession(command?: string): string | null;
28
+ export declare function createTerminalTab(command?: string): string | null;
29
+ export declare function restartSession(itermSessionId: string, command?: string): Promise<void>;
30
+ export declare function killSession(itermSessionId: string): void;
31
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/adapters/iterm/sessions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6CH,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAG7E;AAED,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAG1E;AAED,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBxE;AAID,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,kBAAkB,CAAC,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CA0Bf;AAID,wBAAgB,kBAAkB,IAAI,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAKxE;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC,CAoBD;AAID,wBAAgB,mBAAmB,CAAC,OAAO,SAAW,GAAG,MAAM,GAAG,IAAI,CAkBrE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAqBjE;AAID,wBAAsB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,SAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9F;AAED,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAMxD"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * adapters/iterm/sessions.ts — Higher-level iTerm2 session management.
3
+ *
4
+ * Session variables, tab naming, discovery, creation, and lifecycle.
5
+ * Does NOT import any transport send functions — callers handle message delivery.
6
+ */
7
+ import { execSync } from "node:child_process";
8
+ import { runAppleScript, typeIntoSession, sendKeystrokeToSession, stripItermPrefix, withSessionAppleScript, snapshotAllSessions, } from "./core.js";
9
+ import { log } from "../../core/log.js";
10
+ import { managedSessions, updateSessionTtyCache, } from "../../core/state.js";
11
+ // ── Session Variable Helpers ──
12
+ function setItermSessionProperty(itermSessionId, body) {
13
+ try {
14
+ const script = withSessionAppleScript(itermSessionId, ` tell aSession\n ${body}\n end tell\n return`, "");
15
+ execSync(`osascript <<'APPLESCRIPT'\n${script}\nAPPLESCRIPT`, {
16
+ timeout: 5000,
17
+ shell: "/bin/bash",
18
+ });
19
+ }
20
+ catch {
21
+ // silently ignore
22
+ }
23
+ }
24
+ export function setItermSessionVar(itermSessionId, name) {
25
+ const escaped = name.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\n\r]/g, " ");
26
+ setItermSessionProperty(itermSessionId, `set variable named "user.paiName" to "${escaped}"`);
27
+ }
28
+ export function setItermTabName(itermSessionId, name) {
29
+ const escaped = name.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/[\n\r]/g, " ");
30
+ setItermSessionProperty(itermSessionId, `set name to "${escaped}"`);
31
+ }
32
+ export function getItermSessionVar(itermSessionId) {
33
+ try {
34
+ const script = withSessionAppleScript(itermSessionId, ` tell aSession\n try\n return (variable named "user.paiName")\n on error\n return ""\n end try\n end tell`, 'return ""');
35
+ const result = execSync(`osascript <<'APPLESCRIPT'\n${script}\nAPPLESCRIPT`, {
36
+ timeout: 5000,
37
+ encoding: "utf8",
38
+ shell: "/bin/bash",
39
+ }).trim();
40
+ return (result && result !== "missing value") ? result : null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ // ── Session Resolution ──
47
+ export function findItermSessionForTermId(termSessionId, itermSessionIdHint) {
48
+ if (itermSessionIdHint) {
49
+ return stripItermPrefix(itermSessionIdHint) ?? itermSessionIdHint;
50
+ }
51
+ const script = `
52
+ tell application "iTerm2"
53
+ set output to ""
54
+ repeat with aWindow in windows
55
+ repeat with aTab in tabs of aWindow
56
+ repeat with aSession in sessions of aTab
57
+ set envVal to ""
58
+ try
59
+ tell aSession to set envVal to (variable named "TERM_SESSION_ID")
60
+ end try
61
+ if envVal is "${termSessionId.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}" then
62
+ return id of aSession
63
+ end if
64
+ end repeat
65
+ end repeat
66
+ end repeat
67
+ return ""
68
+ end tell`;
69
+ const result = runAppleScript(script);
70
+ return (result && result.length > 0) ? result : null;
71
+ }
72
+ // ── Session Listing ──
73
+ export function listClaudeSessions() {
74
+ const sessions = snapshotAllSessions();
75
+ return sessions
76
+ .filter((s) => s.name.toLowerCase().includes("claude") || s.paiName)
77
+ .map((s) => ({ id: s.id, name: s.paiName ?? s.name }));
78
+ }
79
+ /**
80
+ * Build a full session list with type classification and PAI name resolution.
81
+ * Returns the data used by /s command.
82
+ */
83
+ export function getSessionList() {
84
+ const snapshots = snapshotAllSessions();
85
+ // Update TTY cache
86
+ updateSessionTtyCache(snapshots.map((s) => ({ id: s.id, tty: s.tty })));
87
+ // Prune dead managed sessions
88
+ const aliveIds = new Set(snapshots.map((s) => s.id));
89
+ for (const [id] of managedSessions) {
90
+ if (!aliveIds.has(id))
91
+ managedSessions.delete(id);
92
+ }
93
+ return snapshots.map((s) => ({
94
+ id: s.id,
95
+ name: s.paiName ?? s.name,
96
+ path: "",
97
+ type: (s.name.toLowerCase().includes("claude") || !s.atPrompt) ? "claude" : "terminal",
98
+ paiName: s.paiName,
99
+ atPrompt: s.atPrompt,
100
+ }));
101
+ }
102
+ // ── Session Creation ──
103
+ export function createClaudeSession(command = "claude") {
104
+ try {
105
+ const script = `tell application "iTerm2"
106
+ tell current window
107
+ set newTab to (create tab with default profile)
108
+ tell newTab
109
+ tell current session
110
+ write text "${command.replace(/"/g, '\\"')}"
111
+ return id
112
+ end tell
113
+ end tell
114
+ end tell
115
+ end tell`;
116
+ return runAppleScript(script) ?? null;
117
+ }
118
+ catch (err) {
119
+ log("Failed to create session:", String(err));
120
+ return null;
121
+ }
122
+ }
123
+ export function createTerminalTab(command) {
124
+ try {
125
+ const writeCmd = command
126
+ ? `write text "${command.replace(/"/g, '\\"')}"`
127
+ : "";
128
+ const script = `tell application "iTerm2"
129
+ tell current window
130
+ set newTab to (create tab with default profile)
131
+ tell newTab
132
+ tell current session
133
+ ${writeCmd}
134
+ return id
135
+ end tell
136
+ end tell
137
+ end tell
138
+ end tell`;
139
+ return runAppleScript(script) ?? null;
140
+ }
141
+ catch (err) {
142
+ log("Failed to create terminal tab:", String(err));
143
+ return null;
144
+ }
145
+ }
146
+ // ── Session Lifecycle ──
147
+ export async function restartSession(itermSessionId, command = "claude") {
148
+ sendKeystrokeToSession(itermSessionId, 3); // Ctrl+C
149
+ await new Promise((r) => setTimeout(r, 500));
150
+ typeIntoSession(itermSessionId, command);
151
+ }
152
+ export function killSession(itermSessionId) {
153
+ const script = withSessionAppleScript(itermSessionId, ` close aSession\n return "ok"`);
154
+ runAppleScript(script);
155
+ }
156
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../../src/adapters/iterm/sessions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,OAAO,EACL,cAAc,EAId,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAEL,eAAe,EAIf,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAG7B,iCAAiC;AAEjC,SAAS,uBAAuB,CAAC,cAAsB,EAAE,IAAY;IACnE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,sBAAsB,CACnC,cAAc,EACd,wCAAwC,IAAI,wCAAwC,EACpF,EAAE,CACH,CAAC;QACF,QAAQ,CAAC,8BAA8B,MAAM,eAAe,EAAE;YAC5D,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,cAAsB,EAAE,IAAY;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACzF,uBAAuB,CAAC,cAAc,EAAE,yCAAyC,OAAO,GAAG,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,cAAsB,EAAE,IAAY;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACzF,uBAAuB,CAAC,cAAc,EAAE,gBAAgB,OAAO,GAAG,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,cAAsB;IACvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,sBAAsB,CACnC,cAAc,EACd,wLAAwL,EACxL,WAAW,CACZ,CAAC;QACF,MAAM,MAAM,GAAG,QAAQ,CAAC,8BAA8B,MAAM,eAAe,EAAE;YAC3E,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,MAAM,IAAI,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,2BAA2B;AAE3B,MAAM,UAAU,yBAAyB,CACvC,aAAqB,EACrB,kBAA2B;IAE3B,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,kBAAkB,CAAC;IACpE,CAAC;IAED,MAAM,MAAM,GAAG;;;;;;;;;;wBAUO,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;;;;;;;SAOxE,CAAC;IAER,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,wBAAwB;AAExB,MAAM,UAAU,kBAAkB;IAChC,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,OAAO,QAAQ;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;SACnE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAQ5B,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IAExC,mBAAmB;IACnB,qBAAqB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAExE,8BAA8B;IAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI;QACzB,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAiB,CAAC,CAAC,CAAC,UAAmB;QACxG,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,CAAC,CAAC,QAAQ;KACrB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,yBAAyB;AAEzB,MAAM,UAAU,mBAAmB,CAAC,OAAO,GAAG,QAAQ;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG;;;;;sBAKG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;;;;;SAKzC,CAAC;QACN,OAAO,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,OAAO;YACtB,CAAC,CAAC,eAAe,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG;YAChD,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,MAAM,GAAG;;;;;UAKT,QAAQ;;;;;SAKT,CAAC;QACN,OAAO,cAAc,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,gCAAgC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,0BAA0B;AAE1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,cAAsB,EAAE,OAAO,GAAG,QAAQ;IAC7E,sBAAsB,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;IACpD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7C,eAAe,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,cAAsB;IAChD,MAAM,MAAM,GAAG,sBAAsB,CACnC,cAAc,EACd,iDAAiD,CAClD,CAAC;IACF,cAAc,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC"}