@symerian/symi 3.5.12 → 3.5.14

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.5.12",
3
- "commit": "ba937470adc8cb729ea183e67afa9e9b23fa2245",
4
- "builtAt": "2026-05-06T02:37:25.750Z"
2
+ "version": "3.5.14",
3
+ "commit": "717a47dd4ed3d79cd51e0392bdb0234271d8b354",
4
+ "builtAt": "2026-05-06T17:04:48.417Z"
5
5
  }
@@ -1 +1 @@
1
- 74ed545b32825cef7fb4fa2f000acd88a717aaea0e2acf93d7d7c1b8ed2be576
1
+ b79723675878faef939375c6e1c5aeba4af2beba5b4fed5b057a23b9321ec6dd
@@ -9,7 +9,7 @@ import fs$1 from "node:fs/promises";
9
9
  import { execFileSync, spawn } from "node:child_process";
10
10
  import net from "node:net";
11
11
  import { createServer } from "node:http";
12
- import WebSocket$1, { WebSocketServer } from "ws";
12
+ import WebSocket, { WebSocketServer } from "ws";
13
13
  import { Buffer as Buffer$1 } from "node:buffer";
14
14
 
15
15
  //#region src/browser/constants.ts
@@ -177,7 +177,7 @@ async function ensureChromeExtensionRelayServer(opts) {
177
177
  let nextExtensionId = 1;
178
178
  const sendToExtension = async (payload) => {
179
179
  const ws = extensionWs;
180
- if (!ws || ws.readyState !== WebSocket$1.OPEN) throw new Error("Chrome extension not connected");
180
+ if (!ws || ws.readyState !== WebSocket.OPEN) throw new Error("Chrome extension not connected");
181
181
  ws.send(JSON.stringify(payload));
182
182
  return await new Promise((resolve, reject) => {
183
183
  const timer = setTimeout(() => {
@@ -194,12 +194,12 @@ async function ensureChromeExtensionRelayServer(opts) {
194
194
  const broadcastToCdpClients = (evt) => {
195
195
  const msg = JSON.stringify(evt);
196
196
  for (const ws of cdpClients) {
197
- if (ws.readyState !== WebSocket$1.OPEN) continue;
197
+ if (ws.readyState !== WebSocket.OPEN) continue;
198
198
  ws.send(msg);
199
199
  }
200
200
  };
201
201
  const sendResponseToCdp = (ws, res) => {
202
- if (ws.readyState !== WebSocket$1.OPEN) return;
202
+ if (ws.readyState !== WebSocket.OPEN) return;
203
203
  ws.send(JSON.stringify(res));
204
204
  };
205
205
  const ensureTargetEventsForClient = (ws, mode) => {
@@ -424,7 +424,7 @@ async function ensureChromeExtensionRelayServer(opts) {
424
424
  wssExtension.on("connection", (ws) => {
425
425
  extensionWs = ws;
426
426
  const ping = setInterval(() => {
427
- if (ws.readyState !== WebSocket$1.OPEN) return;
427
+ if (ws.readyState !== WebSocket.OPEN) return;
428
428
  ws.send(JSON.stringify({ method: "ping" }));
429
429
  }, 5e3);
430
430
  ws.on("message", (data) => {
@@ -742,7 +742,7 @@ async function fetchOk(url, timeoutMs = 1500, init) {
742
742
  }
743
743
  async function withCdpSocket(wsUrl, fn, opts) {
744
744
  const headers = getHeadersWithAuth(wsUrl, opts?.headers ?? {});
745
- const ws = new WebSocket$1(wsUrl, {
745
+ const ws = new WebSocket(wsUrl, {
746
746
  handshakeTimeout: typeof opts?.handshakeTimeoutMs === "number" && Number.isFinite(opts.handshakeTimeoutMs) ? Math.max(1, Math.floor(opts.handshakeTimeoutMs)) : 5e3,
747
747
  ...Object.keys(headers).length ? { headers } : {}
748
748
  });
@@ -1636,7 +1636,7 @@ async function getChromeWebSocketUrl(cdpUrl, timeoutMs = 500) {
1636
1636
  async function canOpenWebSocket(wsUrl, timeoutMs = 800) {
1637
1637
  return await new Promise((resolve) => {
1638
1638
  const headers = getHeadersWithAuth(wsUrl);
1639
- const ws = new WebSocket$1(wsUrl, {
1639
+ const ws = new WebSocket(wsUrl, {
1640
1640
  handshakeTimeout: timeoutMs,
1641
1641
  ...Object.keys(headers).length ? { headers } : {}
1642
1642
  });
@@ -397,57 +397,59 @@ body {
397
397
  letter-spacing: 0.05em;
398
398
  }
399
399
 
400
- /* ── Model Routing list ────────────────────────────────────────────── */
401
- .model-routing-list {
402
- display: flex;
403
- flex-direction: column;
404
- gap: 10px;
405
- margin-bottom: 8px;
406
- }
407
- .model-section {
408
- display: flex;
409
- flex-direction: column;
410
- gap: 3px;
411
- }
412
- .model-section-header {
413
- font-family: var(--font-mono);
414
- font-size: 9px;
415
- letter-spacing: 0.08em;
416
- text-transform: uppercase;
417
- color: var(--text-dim);
418
- opacity: 0.6;
419
- padding: 0 2px 2px;
420
- border-bottom: 1px solid rgba(255, 255, 255, 0.06);
421
- margin-bottom: 2px;
422
- }
423
- .model-item {
400
+ /* ── Model Routing select ──────────────────────────────────────────── */
401
+ .model-routing-select {
424
402
  width: 100%;
425
403
  display: block;
426
- text-align: left;
427
- padding: 6px 8px;
404
+ padding: 8px 22px 8px 8px;
405
+ margin-bottom: 6px;
428
406
  border: 1px solid var(--glass-border);
429
- border-radius: 5px;
407
+ border-radius: 6px;
430
408
  background: rgba(255, 255, 255, 0.03);
431
- color: var(--text-dim);
409
+ color: var(--text);
432
410
  font-family: var(--font-mono);
433
411
  font-size: 10px;
434
- letter-spacing: 0.03em;
435
- line-height: 1.3;
412
+ letter-spacing: 0.04em;
436
413
  cursor: pointer;
437
- transition: all 0.15s ease;
438
- white-space: normal;
439
- word-break: break-word;
414
+ transition: all 0.2s ease;
415
+ appearance: none;
416
+ -webkit-appearance: none;
417
+ background-image:
418
+ linear-gradient(45deg, transparent 50%, currentColor 50%),
419
+ linear-gradient(135deg, currentColor 50%, transparent 50%);
420
+ background-position:
421
+ calc(100% - 10px) 50%,
422
+ calc(100% - 6px) 50%;
423
+ background-size:
424
+ 4px 4px,
425
+ 4px 4px;
426
+ background-repeat: no-repeat;
427
+ text-overflow: ellipsis;
428
+ overflow: hidden;
440
429
  }
441
- .model-item:hover {
430
+ .model-routing-select:hover {
442
431
  border-color: var(--accent-cyan);
443
432
  color: var(--text);
444
433
  }
445
- .model-item.active {
446
- background: rgba(0, 212, 255, 0.08);
434
+ .model-routing-select:focus {
435
+ outline: none;
447
436
  border-color: var(--accent-cyan);
448
- color: var(--accent-cyan);
449
437
  box-shadow: 0 0 8px rgba(0, 212, 255, 0.12);
450
438
  }
439
+ .model-routing-select option {
440
+ background: #0a0a0a;
441
+ color: var(--text);
442
+ padding: 4px 0;
443
+ }
444
+ .model-routing-select optgroup {
445
+ background: #0a0a0a;
446
+ color: var(--accent-cyan);
447
+ font-style: normal;
448
+ font-weight: 600;
449
+ letter-spacing: 0.08em;
450
+ text-transform: uppercase;
451
+ font-size: 10px;
452
+ }
451
453
  .model-status {
452
454
  font-size: 10px;
453
455
  color: var(--text-dim);
@@ -832,6 +834,79 @@ body {
832
834
  right: calc(50% - 370px - 16px - 360px);
833
835
  }
834
836
 
837
+ /* ── Symframe (right-column dynamic display) ──────────────────────── */
838
+ /* Phase 1: shell + the 3 existing panels reframed as cards. The aside
839
+ itself stays positioned by .metrics-right; symframe just adds a
840
+ header band on top and unified card chrome around each child panel.
841
+ No JS plumbing yet — Phase 2 introduces the registry + dynamic
842
+ add/update/remove semantics. */
843
+ .symframe {
844
+ display: flex;
845
+ flex-direction: column;
846
+ gap: 8px;
847
+ }
848
+ .symframe-header {
849
+ padding: 8px 10px 10px;
850
+ border-bottom: 1px solid rgba(0, 212, 255, 0.12);
851
+ margin-bottom: 4px;
852
+ }
853
+ .symframe-header-row {
854
+ display: flex;
855
+ align-items: baseline;
856
+ justify-content: space-between;
857
+ gap: 10px;
858
+ }
859
+ .symframe-title {
860
+ font-family: var(--font-mono);
861
+ font-size: 12px;
862
+ font-weight: 600;
863
+ letter-spacing: 0.14em;
864
+ color: var(--accent-cyan);
865
+ }
866
+ .symframe-count {
867
+ font-family: var(--font-mono);
868
+ font-size: 9px;
869
+ letter-spacing: 0.06em;
870
+ color: var(--text-dim);
871
+ opacity: 0.7;
872
+ text-transform: uppercase;
873
+ }
874
+ .symframe-sub {
875
+ font-family: var(--font-mono);
876
+ font-size: 9px;
877
+ letter-spacing: 0.04em;
878
+ color: var(--text-dim);
879
+ opacity: 0.55;
880
+ margin-top: 4px;
881
+ line-height: 1.4;
882
+ }
883
+ .symframe-cards {
884
+ display: flex;
885
+ flex-direction: column;
886
+ gap: 10px;
887
+ }
888
+ /* Card chrome — overrides the per-panel transparent treatment from the
889
+ floating-panels arc (3.4.10/11/12/13) for the panels that now live
890
+ inside the symframe. Higher specificity (`.symframe .symframe-card`)
891
+ wins over the panel-specific class selectors. */
892
+ .symframe .symframe-card {
893
+ position: relative;
894
+ background: rgba(255, 255, 255, 0.02);
895
+ border: 1px solid rgba(0, 212, 255, 0.1);
896
+ border-radius: 10px;
897
+ padding: 10px 12px;
898
+ box-shadow:
899
+ inset 0 1px 0 rgba(255, 255, 255, 0.03),
900
+ 0 2px 8px rgba(0, 0, 0, 0.15);
901
+ }
902
+ .symframe .symframe-card::before,
903
+ .symframe .symframe-card::after {
904
+ display: none;
905
+ }
906
+ .symframe .symframe-card:hover {
907
+ border-color: rgba(0, 212, 255, 0.18);
908
+ }
909
+
835
910
  /* ── Response Area ────────────────────────────────────────────────── */
836
911
  .response-area {
837
912
  position: fixed;
@@ -120,41 +120,23 @@
120
120
 
121
121
  <div class="glass-panel" id="model-routing-panel">
122
122
  <div class="panel-label">MODEL ROUTING</div>
123
- <div class="model-routing-list" id="model-toggle">
124
- <div class="model-section">
125
- <div class="model-section-header">SPIDER</div>
126
- <button class="model-item" data-group="spider" data-value="spider-gemma4">
127
- Gemma 4 31B Uncensored
128
- </button>
129
- <button class="model-item" data-group="spider" data-value="spider-qwen35">
130
- Qwen 3.5 35B
131
- </button>
132
- <button class="model-item" data-group="spider" data-value="spider-qwen35-uncen">
133
- Qwen 3.5 Uncensored
134
- </button>
135
- <button class="model-item" data-group="spider" data-value="spider-qwen36">
136
- Qwen 3.6 35B
137
- </button>
138
- </div>
139
- <div class="model-section">
140
- <div class="model-section-header">COREWEAVE</div>
141
- <button class="model-item" data-group="coreweave" data-value="coreweave1">
142
- CoreWeave 1 (Qwen 3.5 35B)
143
- </button>
144
- <button class="model-item" data-group="coreweave" data-value="coreweave2">
145
- CoreWeave 2 (Qwen 3.6 35B)
146
- </button>
147
- <button class="model-item" data-group="coreweave" data-value="coreweave3">
148
- CoreWeave 3 (Qwen 3.6 27B)
149
- </button>
150
- </div>
151
- <div class="model-section">
152
- <div class="model-section-header">API</div>
153
- <button class="model-item" data-group="api" data-value="api">
154
- Anthropic Claude Sonnet 4.6
155
- </button>
156
- </div>
157
- </div>
123
+ <select class="model-routing-select" id="model-toggle">
124
+ <option value="" disabled selected>Select model…</option>
125
+ <optgroup label="SPIDER">
126
+ <option value="spider-gemma4">Gemma 4 31B Uncensored</option>
127
+ <option value="spider-qwen35">Qwen 3.5 35B</option>
128
+ <option value="spider-qwen35-uncen">Qwen 3.5 Uncensored</option>
129
+ <option value="spider-qwen36">Qwen 3.6 35B</option>
130
+ </optgroup>
131
+ <optgroup label="COREWEAVE">
132
+ <option value="coreweave1">CoreWeave 1 (Qwen 3.5 35B)</option>
133
+ <option value="coreweave2">CoreWeave 2 (Qwen 3.6 35B)</option>
134
+ <option value="coreweave3">CoreWeave 3 (Qwen 3.6 27B)</option>
135
+ </optgroup>
136
+ <optgroup label="API">
137
+ <option value="api">Anthropic Claude Sonnet 4.6</option>
138
+ </optgroup>
139
+ </select>
158
140
  <div class="model-status" id="model-status">loading…</div>
159
141
  </div>
160
142
 
@@ -209,10 +191,18 @@
209
191
  </div>
210
192
  </aside>
211
193
 
212
- <!-- MetricsRight column -->
213
- <aside class="metrics-col metrics-right">
194
+ <!-- Symframedynamic display panel ("window into the agent's mind") -->
195
+ <aside class="metrics-col metrics-right symframe" id="symframe">
196
+ <div class="symframe-header">
197
+ <div class="symframe-header-row">
198
+ <span class="symframe-title">SYMFRAME</span>
199
+ <span class="symframe-count" id="symframe-count">3 cards</span>
200
+ </div>
201
+ <div class="symframe-sub">window into the agent's mind</div>
202
+ </div>
203
+ <div class="symframe-cards" id="symframe-cards">
214
204
  <!-- Subagents Panel -->
215
- <div class="glass-panel subagents-panel" id="subagents-panel">
205
+ <div class="glass-panel symframe-card subagents-panel" id="subagents-panel">
216
206
  <div class="panel-label">
217
207
  SUBAGENTS
218
208
  <span class="subagents-count" id="subagents-count"></span>
@@ -294,7 +284,7 @@
294
284
  </div>
295
285
 
296
286
  <!-- Reasoning Panel -->
297
- <div class="glass-panel reasoning-panel" id="reasoning-panel">
287
+ <div class="glass-panel symframe-card reasoning-panel" id="reasoning-panel">
298
288
  <div class="panel-label">
299
289
  REASONING
300
290
  <span class="reasoning-live-dot" id="reasoning-live-dot"></span>
@@ -315,7 +305,7 @@
315
305
  </div>
316
306
 
317
307
  <!-- Scheduling Panel -->
318
- <div class="glass-panel scheduling-panel" id="scheduling-panel">
308
+ <div class="glass-panel symframe-card scheduling-panel" id="scheduling-panel">
319
309
  <div class="panel-label">
320
310
  SCHEDULING
321
311
  <span class="schedule-count" id="schedule-count"></span>
@@ -339,6 +329,7 @@
339
329
  <span>Add Schedule</span>
340
330
  </button>
341
331
  </div>
332
+ </div>
342
333
 
343
334
  </aside>
344
335
 
@@ -1,15 +1,13 @@
1
- // ── Model Routing list ───────────────────────────────────────────────
2
- // Vertical sectioned list (SPIDER / COREWEAVE / API) — each .model-item
3
- // row is a click target that switches `agents.defaults.model.primary`
4
- // via config.patch. Replaced the side-by-side dropdowns + button design
5
- // in 3.5.12 because the three controls were forcing horizontal scroll
6
- // inside the panel; sectioned vertical layout has no width constraint
7
- // and lets long model names wrap naturally.
1
+ // ── Model Routing select ─────────────────────────────────────────────
2
+ // Single <select> with three <optgroup>s (SPIDER / COREWEAVE / API).
3
+ // Picking an option switches `agents.defaults.model.primary` via
4
+ // config.patch. Compact one-row presentation no horizontal scroll,
5
+ // no vertical bloat from listing every option in the panel.
8
6
 
9
7
  (function () {
10
- // data-value (per-item) → fully-qualified model id understood by the
11
- // gateway (provider/model split on first "/"; later slashes survive
12
- // and are part of the model id, e.g. for HuggingFace paths).
8
+ // <option value> → fully-qualified model id understood by the gateway
9
+ // (provider/model split on first "/"; later slashes survive and are
10
+ // part of the model id, e.g. for HuggingFace paths).
13
11
  const MODEL_IDS = {
14
12
  // SPIDER
15
13
  "spider-gemma4": "spider-gemma4/TrevorJS/gemma-4-31B-it-uncensored",
@@ -25,27 +23,29 @@
25
23
  api: "anthropic/claude-sonnet-4-6",
26
24
  };
27
25
 
28
- // Reverse: model id → data-value (for setActive lookup).
26
+ // Reverse: model id → option value (for setActive lookup).
29
27
  const idToValue = {};
30
28
  for (const [value, id] of Object.entries(MODEL_IDS)) {
31
29
  idToValue[id] = value;
32
30
  }
33
31
 
34
- const list = document.getElementById("model-toggle");
35
- const items = list ? list.querySelectorAll(".model-item") : [];
32
+ const select = document.getElementById("model-toggle");
36
33
  const statusEl = document.getElementById("model-status");
37
34
 
38
- if (!list || items.length === 0) {
35
+ if (!select) {
39
36
  return;
40
37
  }
41
38
 
42
39
  let currentHash = null;
43
40
 
44
41
  function setActive(primaryId) {
45
- const activeValue = idToValue[primaryId];
46
- items.forEach((item) => {
47
- item.classList.toggle("active", item.dataset.value === activeValue);
48
- });
42
+ const value = idToValue[primaryId];
43
+ if (value) {
44
+ select.value = value;
45
+ } else {
46
+ // Unknown model id — leave the placeholder visible.
47
+ select.value = "";
48
+ }
49
49
  }
50
50
 
51
51
  async function init() {
@@ -104,14 +104,8 @@
104
104
  }
105
105
  });
106
106
 
107
- // Single delegated click on the list → look up data-value → switch.
108
- list.addEventListener("click", (e) => {
109
- const item = e.target.closest(".model-item");
110
- if (!item) {
111
- return;
112
- }
113
- const value = item.dataset.value;
114
- const id = MODEL_IDS[value];
107
+ select.addEventListener("change", () => {
108
+ const id = MODEL_IDS[select.value];
115
109
  if (id) {
116
110
  void switchToModelId(id);
117
111
  }
@@ -9,7 +9,7 @@ import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-CZ_mYw
9
9
  import { _ as listDeliverableMessageChannels, c as resolveChunkMode, f as parseFenceSpans, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, n as chunkByParagraph, v as normalizeMessageChannel } from "./chunk-CAZujdOi.js";
10
10
  import { c as loadConfig, d as writeConfigFile, m as parseByteSize, p as parseDurationMs, s as createConfigIO, t as SsrFBlockedError } from "./ssrf-BCSnhba8.js";
11
11
  import { t as parseBooleanValue } from "./boolean-BW6OTjPi.js";
12
- import { A as DEFAULT_BROWSER_EVALUATE_ENABLED, D as DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS, E as DEFAULT_AI_SNAPSHOT_EFFICIENT_DEPTH, M as DEFAULT_SYMI_BROWSER_ENABLED, N as DEFAULT_SYMI_BROWSER_PROFILE_NAME, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, S as stopChromeExtensionRelayServer, _ as fetchJson, a as resolveSymiUserDataDir, c as captureScreenshot, d as normalizeCdpWsUrl, f as snapshotAria, g as appendCdpPath, h as withBrowserNavigationPolicy, i as launchSymiChrome, j as DEFAULT_SYMI_BROWSER_COLOR, k as DEFAULT_BROWSER_DEFAULT_PROFILE_NAME, l as createTargetViaCdp, m as assertBrowserNavigationAllowed, n as isChromeCdpReady, o as stopSymiChrome, p as InvalidBrowserNavigationUrlError, r as isChromeReachable, s as resolveBrowserExecutableForPlatform, v as fetchOk, w as isLoopbackHost, x as ensureChromeExtensionRelayServer } from "./chrome-DNssqQJs.js";
12
+ import { A as DEFAULT_BROWSER_EVALUATE_ENABLED, D as DEFAULT_AI_SNAPSHOT_EFFICIENT_MAX_CHARS, E as DEFAULT_AI_SNAPSHOT_EFFICIENT_DEPTH, M as DEFAULT_SYMI_BROWSER_ENABLED, N as DEFAULT_SYMI_BROWSER_PROFILE_NAME, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, S as stopChromeExtensionRelayServer, _ as fetchJson, a as resolveSymiUserDataDir, c as captureScreenshot, d as normalizeCdpWsUrl, f as snapshotAria, g as appendCdpPath, h as withBrowserNavigationPolicy, i as launchSymiChrome, j as DEFAULT_SYMI_BROWSER_COLOR, k as DEFAULT_BROWSER_DEFAULT_PROFILE_NAME, l as createTargetViaCdp, m as assertBrowserNavigationAllowed, n as isChromeCdpReady, o as stopSymiChrome, p as InvalidBrowserNavigationUrlError, r as isChromeReachable, s as resolveBrowserExecutableForPlatform, v as fetchOk, w as isLoopbackHost, x as ensureChromeExtensionRelayServer } from "./chrome-3jl2ulOE.js";
13
13
  import { t as formatCliCommand } from "./command-format-DPd9RN2g.js";
14
14
  import { a as syncSkillsToWorkspace, l as resolveSandboxInputPath, m as sanitizeEnvVars, u as resolveSandboxPath } from "./skills-DO7WNsVJ.js";
15
15
  import { n as formatErrorMessage, t as extractErrorCode } from "./errors-BEU7IHU6.js";
@@ -1331,7 +1331,7 @@ function isModuleNotFoundError(err) {
1331
1331
  }
1332
1332
  async function loadPwAiModule(mode) {
1333
1333
  try {
1334
- return await import("./pw-ai-v__CyAlM.js");
1334
+ return await import("./pw-ai-DOAsQ5NX.js");
1335
1335
  } catch (err) {
1336
1336
  if (mode === "soft") return null;
1337
1337
  if (isModuleNotFoundError(err)) return null;
@@ -3928,11 +3928,11 @@ function createProfileContext(opts, profile) {
3928
3928
  const userDataDir = resolveSymiUserDataDir(profile.name);
3929
3929
  const profileState = getProfileState();
3930
3930
  if (await isHttpReachable(300) && !profileState.running) try {
3931
- await (await import("./pw-ai-v__CyAlM.js")).closePlaywrightBrowserConnection();
3931
+ await (await import("./pw-ai-DOAsQ5NX.js")).closePlaywrightBrowserConnection();
3932
3932
  } catch {}
3933
3933
  if (profileState.running) await stopRunningBrowser();
3934
3934
  try {
3935
- await (await import("./pw-ai-v__CyAlM.js")).closePlaywrightBrowserConnection();
3935
+ await (await import("./pw-ai-DOAsQ5NX.js")).closePlaywrightBrowserConnection();
3936
3936
  } catch {}
3937
3937
  if (!fs.existsSync(userDataDir)) return {
3938
3938
  moved: false,
@@ -6,8 +6,8 @@ import { _ as DEFAULT_PROVIDER, g as DEFAULT_MODEL, p as resolveThinkingDefault
6
6
  import { a as resolveAgentIdentity } from "./reply-prefix-i-FPYcoQ.js";
7
7
  import "./plugins-CZ_mYwXq.js";
8
8
  import "./replies-0nzkXt6o.js";
9
- import { a as resolveAgentTimeoutMs, r as runEmbeddedPiAgent } from "./pi-embedded-DP8324Ib.js";
10
- import { $ as loadSessionStore, nt as saveSessionStore } from "./deliver-q23ar_Pm.js";
9
+ import { a as resolveAgentTimeoutMs, r as runEmbeddedPiAgent } from "./pi-embedded-BxKs-STI.js";
10
+ import { $ as loadSessionStore, nt as saveSessionStore } from "./deliver-f3cIWxXT.js";
11
11
  import "./diagnostic-BdRnGknC.js";
12
12
  import "./diagnostic-session-state-DpxCUzoM.js";
13
13
  import "./chunk-CAZujdOi.js";
@@ -16,14 +16,14 @@ import "./ssrf-BCSnhba8.js";
16
16
  import "./boolean-BW6OTjPi.js";
17
17
  import "./shell-env-DgjeObDZ.js";
18
18
  import "./manifest-registry-CAWGTwb5.js";
19
- import "./chrome-DNssqQJs.js";
19
+ import "./chrome-3jl2ulOE.js";
20
20
  import "./skills-DO7WNsVJ.js";
21
21
  import "./redact-DSOAcWMe.js";
22
22
  import "./errors-BEU7IHU6.js";
23
23
  import "./tokens-yWO1wD7Z.js";
24
24
  import "./thinking-DgjGxdSP.js";
25
25
  import { n as resolveSessionFilePath, s as resolveStorePath } from "./paths-BsT3BvfH.js";
26
- import "./manager-BWWH1lYn.js";
26
+ import "./manager-Ct4kRT7n.js";
27
27
  import "./github-copilot-token-dYUr1mDQ.js";
28
28
  import "./sqlite-D8iYC_CU.js";
29
29
  import "./markdown-tables-jQzXAsf3.js";
@@ -4449,7 +4449,7 @@ var MemoryIndexManager = class MemoryIndexManager extends MemoryManagerEmbedding
4449
4449
  * to bypass the min-interval guard (CLI use).
4450
4450
  */
4451
4451
  async runL3CycleIfDue(params) {
4452
- const [{ runL3Cycle, runL3CycleIfDue }, { createSynthesizer }] = await Promise.all([import("./consolidate-CwJCvaOH.js"), import("./synthesis-qt5bxUcn.js")]);
4452
+ const [{ runL3Cycle, runL3CycleIfDue }, { createSynthesizer }] = await Promise.all([import("./consolidate-CwJCvaOH.js"), import("./synthesis-CxR-cX-4.js")]);
4453
4453
  const synthesize = createSynthesizer({
4454
4454
  cfg: this.cfg,
4455
4455
  agentId: this.agentId,
@@ -9,7 +9,7 @@ import { i as resolveAckReaction, o as resolveEffectiveMessagesConfig, r as reso
9
9
  import { t as normalizeChatType } from "./chat-type-Acj2OK2p.js";
10
10
  import { i as resolveSlackAccount, n as listChannelPlugins, o as resolveSlackAppToken, r as normalizeChannelId$1, s as resolveSlackBotToken, t as getChannelPlugin } from "./plugins-CZ_mYwXq.js";
11
11
  import { S as resolveSlackChannelId, _ as resolveSlackWebClientOptions, a as sendMessageSlack, b as buildSlackBlocksFallbackText, c as getDefaultLocalRoots, d as fetchRemoteMedia, f as readResponseWithLimit, g as createSlackWebClient, h as fetchWithTimeout, i as resolveSlackThreadTs, l as loadWebMedia, m as bindAbortRelay, n as deliverReplies, o as renderMarkdownWithMarkers, p as fetchWithSsrFGuard, s as markdownToIRWithMeta, t as createSlackReplyDeliveryPlan, u as MediaFetchError, v as parseSlackBlocksInput, x as parseSlackTarget, y as validateSlackBlocksArray } from "./replies-0nzkXt6o.js";
12
- import { $ as loadSessionStore, $t as resolveToolProfilePolicy, A as formatRawAssistantErrorForUi, At as resolveMainSessionKey, B as isRateLimitAssistantError, Bt as saveMediaBuffer, C as downgradeOpenAIReasoningBlocks, Ct as resolveChannelResetConfig, D as classifyFailoverReason, Dt as DEFAULT_RESET_TRIGGERS, E as BILLING_ERROR_USER_MESSAGE, Et as resolveThreadFlag, F as isCompactionFailureError, Ft as createBrowserRouteContext, G as parseImageSizeError, Gt as resolveBrowserControlAuth, H as isTimeoutErrorMessage, Ht as resolveExistingPathsWithinRoot, I as isContextOverflowError, It as registerBrowserRoutes, J as resolveSandboxContext, Jt as collectExplicitAllowlist, K as sanitizeUserFacingText, Kt as applyOwnerOnlyToolPolicy, L as isFailoverAssistantError, Lt as resolveBrowserConfig, M as isAuthAssistantError, Mt as resolveGroupSessionKey, N as isBillingAssistantError, Nt as acquireSessionWriteLock, O as formatAssistantErrorText, Ot as resolveFreshSessionTotalTokens, P as isCloudCodeAssistFormatError, Pt as resolveSessionLockMaxHoldFromTimeout, Q as resolveAndPersistSessionFile, Qt as normalizeToolName$1, R as isFailoverErrorMessage, Rt as resolveProfile, S as extractToolResultId, St as evaluateSessionFreshness, T as isGoogleModelApi, Tt as resolveSessionResetType, U as isTransientHttpError, Ut as getBridgeAuthForPort, V as isRawApiErrorPayload, Vt as DEFAULT_UPLOAD_DIR, W as parseImageDimensionError, Wt as ensureBrowserControlAuth, X as extractDeliveryInfo, Xt as expandToolGroups, Y as resolveSandboxRuntimeStatus, Yt as expandPolicyWithPluginGroups, Z as appendAssistantMessageToSessionTranscript, Zt as mergeAlsoAllowPolicy, _ as sanitizeSessionMessagesImages, _t as INPUT_PROVENANCE_KIND_VALUES, a as normalizeChannelTargetInput, an as resolveBootstrapMaxChars, at as updateSessionStoreEntry, b as resolveImageSanitizationLimits, bt as normalizeInputProvenance, c as parseReplyDirectives, cn as getGlobalHookRunner, ct as deliveryContextFromSession, d as parseInlineDirectives$1, dt as normalizeDeliveryContext, en as stripPluginOnlyAllowlist, et as readSessionUpdatedAt, f as validateAnthropicTurns, ft as normalizeSessionDeliveryFields, g as normalizeTextForComparison, gt as extractToolCallNames, h as isMessagingToolDuplicateNormalized, ht as countToolResults, i as buildTargetResolverSignature, in as ensureSessionHeader, it as updateSessionStore, j as getApiErrorPayloadFingerprint, jt as deriveSessionMetaPatch, k as formatBillingErrorMessage, kt as canonicalizeMainSessionAlias, l as MEDIA_TOKEN_RE, ln as initializeGlobalHookRunner, lt as deliveryContextKey, m as pickFallbackThinkingLevel, mt as capArrayByJsonBytes, nn as matchesAnyGlobPattern, o as normalizeTargetForProvider, on as resolveBootstrapTotalMaxChars, ot as isCacheEnabled, p as validateGeminiTurns, pt as archiveSessionTranscripts, q as ensureSandboxWorkspaceForSession, qt as buildPluginToolGroups, r as normalizeReplyPayloadsForDelivery, rn as buildBootstrapContextFiles, rt as updateLastRoute, s as throwIfAborted, sn as sanitizeGoogleTurnOrdering, st as resolveCacheTtlMs$1, t as deliverOutboundPayloads, tn as compileGlobPatterns, tt as recordSessionMetaFromInbound, u as splitMediaFromOutput, ut as mergeDeliveryContext, v as sanitizeImageBlocks, vt as applyInputProvenanceToUserMessage, w as isAntigravityClaude, wt as resolveSessionResetPolicy, x as extractToolCallsFromAssistant, xt as resolveSessionKey, y as sanitizeToolResultImages, yt as hasInterSessionUserProvenance, z as isLikelyContextOverflowError, zt as getMediaDir } from "./deliver-q23ar_Pm.js";
12
+ import { $ as loadSessionStore, $t as resolveToolProfilePolicy, A as formatRawAssistantErrorForUi, At as resolveMainSessionKey, B as isRateLimitAssistantError, Bt as saveMediaBuffer, C as downgradeOpenAIReasoningBlocks, Ct as resolveChannelResetConfig, D as classifyFailoverReason, Dt as DEFAULT_RESET_TRIGGERS, E as BILLING_ERROR_USER_MESSAGE, Et as resolveThreadFlag, F as isCompactionFailureError, Ft as createBrowserRouteContext, G as parseImageSizeError, Gt as resolveBrowserControlAuth, H as isTimeoutErrorMessage, Ht as resolveExistingPathsWithinRoot, I as isContextOverflowError, It as registerBrowserRoutes, J as resolveSandboxContext, Jt as collectExplicitAllowlist, K as sanitizeUserFacingText, Kt as applyOwnerOnlyToolPolicy, L as isFailoverAssistantError, Lt as resolveBrowserConfig, M as isAuthAssistantError, Mt as resolveGroupSessionKey, N as isBillingAssistantError, Nt as acquireSessionWriteLock, O as formatAssistantErrorText, Ot as resolveFreshSessionTotalTokens, P as isCloudCodeAssistFormatError, Pt as resolveSessionLockMaxHoldFromTimeout, Q as resolveAndPersistSessionFile, Qt as normalizeToolName$1, R as isFailoverErrorMessage, Rt as resolveProfile, S as extractToolResultId, St as evaluateSessionFreshness, T as isGoogleModelApi, Tt as resolveSessionResetType, U as isTransientHttpError, Ut as getBridgeAuthForPort, V as isRawApiErrorPayload, Vt as DEFAULT_UPLOAD_DIR, W as parseImageDimensionError, Wt as ensureBrowserControlAuth, X as extractDeliveryInfo, Xt as expandToolGroups, Y as resolveSandboxRuntimeStatus, Yt as expandPolicyWithPluginGroups, Z as appendAssistantMessageToSessionTranscript, Zt as mergeAlsoAllowPolicy, _ as sanitizeSessionMessagesImages, _t as INPUT_PROVENANCE_KIND_VALUES, a as normalizeChannelTargetInput, an as resolveBootstrapMaxChars, at as updateSessionStoreEntry, b as resolveImageSanitizationLimits, bt as normalizeInputProvenance, c as parseReplyDirectives, cn as getGlobalHookRunner, ct as deliveryContextFromSession, d as parseInlineDirectives$1, dt as normalizeDeliveryContext, en as stripPluginOnlyAllowlist, et as readSessionUpdatedAt, f as validateAnthropicTurns, ft as normalizeSessionDeliveryFields, g as normalizeTextForComparison, gt as extractToolCallNames, h as isMessagingToolDuplicateNormalized, ht as countToolResults, i as buildTargetResolverSignature, in as ensureSessionHeader, it as updateSessionStore, j as getApiErrorPayloadFingerprint, jt as deriveSessionMetaPatch, k as formatBillingErrorMessage, kt as canonicalizeMainSessionAlias, l as MEDIA_TOKEN_RE, ln as initializeGlobalHookRunner, lt as deliveryContextKey, m as pickFallbackThinkingLevel, mt as capArrayByJsonBytes, nn as matchesAnyGlobPattern, o as normalizeTargetForProvider, on as resolveBootstrapTotalMaxChars, ot as isCacheEnabled, p as validateGeminiTurns, pt as archiveSessionTranscripts, q as ensureSandboxWorkspaceForSession, qt as buildPluginToolGroups, r as normalizeReplyPayloadsForDelivery, rn as buildBootstrapContextFiles, rt as updateLastRoute, s as throwIfAborted, sn as sanitizeGoogleTurnOrdering, st as resolveCacheTtlMs$1, t as deliverOutboundPayloads, tn as compileGlobPatterns, tt as recordSessionMetaFromInbound, u as splitMediaFromOutput, ut as mergeDeliveryContext, v as sanitizeImageBlocks, vt as applyInputProvenanceToUserMessage, w as isAntigravityClaude, wt as resolveSessionResetPolicy, x as extractToolCallsFromAssistant, xt as resolveSessionKey, y as sanitizeToolResultImages, yt as hasInterSessionUserProvenance, z as isLikelyContextOverflowError, zt as getMediaDir } from "./deliver-f3cIWxXT.js";
13
13
  import { a as logMessageProcessed, i as logLaneEnqueue, o as logMessageQueued, r as logLaneDequeue, s as logSessionStateChange, t as diag } from "./diagnostic-BdRnGknC.js";
14
14
  import { n as getDiagnosticSessionState } from "./diagnostic-session-state-DpxCUzoM.js";
15
15
  import { S as GATEWAY_CLIENT_NAMES, _ as listDeliverableMessageChannels, a as chunkText, b as GATEWAY_CLIENT_IDS, c as resolveChunkMode, d as isSafeFenceBreak, f as parseFenceSpans, g as isMarkdownCapableMessageChannel, h as isInternalMessageChannel, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, m as isDeliverableMessageChannel, o as chunkTextWithMode, p as INTERNAL_MESSAGE_CHANNEL, r as chunkMarkdownText, t as chunkByNewline, u as findFenceSpanAt, v as normalizeMessageChannel, x as GATEWAY_CLIENT_MODES, y as resolveGatewayMessageChannel } from "./chunk-CAZujdOi.js";
@@ -18,7 +18,7 @@ import { C as unsetConfigValueAtPath, S as setConfigValueAtPath, T as VERSION, _
18
18
  import { t as parseBooleanValue } from "./boolean-BW6OTjPi.js";
19
19
  import { i as resolveShellEnvFallbackTimeoutMs, n as getShellPathFromLoginShell, s as isTruthyEnvValue } from "./shell-env-DgjeObDZ.js";
20
20
  import { c as normalizePluginsConfig, f as isPathInsideWithRealpath, i as safeStatSync, l as resolveEnableState, n as discoverSymiPlugins, p as isDangerousHostEnvVarName, r as isPathInside, s as applyTestPluginDefaults, t as loadPluginManifestRegistry, u as resolveMemorySlotDecision } from "./manifest-registry-CAWGTwb5.js";
21
- import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-DNssqQJs.js";
21
+ import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-3jl2ulOE.js";
22
22
  import { n as resolveCliName, t as formatCliCommand } from "./command-format-DPd9RN2g.js";
23
23
  import { c as assertSandboxPath, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, h as parseFrontmatterBlock, i as resolveSkillsPromptForRun, l as resolveSandboxInputPath, n as buildWorkspaceSkillSnapshot, p as applySkillEnvOverridesFromSnapshot, r as loadWorkspaceSkillEntries, s as assertMediaNotDataUrl } from "./skills-DO7WNsVJ.js";
24
24
  import { n as redactToolDetail } from "./redact-DSOAcWMe.js";
@@ -29,7 +29,7 @@ import { n as resolveConversationLabel } from "./conversation-label-DTTqF8gH.js"
29
29
  import { i as resolveSessionTranscriptPath, n as resolveSessionFilePath, o as resolveSessionTranscriptsDirForAgent, r as resolveSessionFilePathOptions, s as resolveStorePath, t as resolveDefaultSessionStorePath } from "./paths-BsT3BvfH.js";
30
30
  import { t as emitSessionTranscriptUpdate } from "./transcript-events-ChU6IQwp.js";
31
31
  import { n as saveJsonFile, t as loadJsonFile } from "./json-file-B7D44OOV.js";
32
- import { a as parseGeminiAuth, c as resolveMemorySearchConfig, d as requireApiKey, f as resolveApiKeyForProvider, h as resolveModelAuthMode, i as resolveOllamaBaseUrl, l as getApiKeyForModel, m as resolveEnvApiKey, n as retryAsync, o as collectProviderApiKeysForExecution, p as resolveAwsSdkEnvVarName, r as probeOllamaEmbeddingModels, s as executeWithApiKeyRotation, u as getCustomProviderApiKey } from "./manager-BWWH1lYn.js";
32
+ import { a as parseGeminiAuth, c as resolveMemorySearchConfig, d as requireApiKey, f as resolveApiKeyForProvider, h as resolveModelAuthMode, i as resolveOllamaBaseUrl, l as getApiKeyForModel, m as resolveEnvApiKey, n as retryAsync, o as collectProviderApiKeysForExecution, p as resolveAwsSdkEnvVarName, r as probeOllamaEmbeddingModels, s as executeWithApiKeyRotation, u as getCustomProviderApiKey } from "./manager-Ct4kRT7n.js";
33
33
  import { r as resolveCopilotApiToken, t as DEFAULT_COPILOT_API_BASE_URL } from "./github-copilot-token-dYUr1mDQ.js";
34
34
  import { c as normalizeExtraMemoryPaths, f as runTasksWithConcurrency, s as listMemoryFiles } from "./internal-Ce-sg7EN.js";
35
35
  import { n as resolveMarkdownTableMode } from "./markdown-tables-jQzXAsf3.js";
@@ -53,7 +53,7 @@ import { fileURLToPath } from "node:url";
53
53
  import { CURRENT_SESSION_VERSION, DefaultResourceLoader, SessionManager, SettingsManager, codingTools, createAgentSession, createEditTool, createReadTool, createWriteTool, estimateTokens, generateSummary, readTool } from "@mariozechner/pi-coding-agent";
54
54
  import crypto, { X509Certificate, createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
55
55
  import AjvPkg from "ajv";
56
- import { WebSocket } from "ws";
56
+ import { WebSocket as WebSocket$1 } from "ws";
57
57
  import { Buffer as Buffer$1 } from "node:buffer";
58
58
  import { complete, createAssistantMessageEventStream, streamSimple } from "@mariozechner/pi-ai";
59
59
  import { BedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";
@@ -3390,7 +3390,7 @@ async function getMemorySearchManager(params) {
3390
3390
  const wrapper = new FallbackMemoryManager({
3391
3391
  primary,
3392
3392
  fallbackFactory: async () => {
3393
- const { MemoryIndexManager } = await import("./manager-BWWH1lYn.js").then((n) => n.t);
3393
+ const { MemoryIndexManager } = await import("./manager-Ct4kRT7n.js").then((n) => n.t);
3394
3394
  return await MemoryIndexManager.get(params);
3395
3395
  }
3396
3396
  }, () => QMD_MANAGER_CACHE.delete(cacheKey));
@@ -3403,7 +3403,7 @@ async function getMemorySearchManager(params) {
3403
3403
  }
3404
3404
  }
3405
3405
  try {
3406
- const { MemoryIndexManager } = await import("./manager-BWWH1lYn.js").then((n) => n.t);
3406
+ const { MemoryIndexManager } = await import("./manager-Ct4kRT7n.js").then((n) => n.t);
3407
3407
  return { manager: await MemoryIndexManager.get(params) };
3408
3408
  } catch (err) {
3409
3409
  return {
@@ -5922,7 +5922,7 @@ var GatewayClient = class {
5922
5922
  if (fingerprint !== expected) return /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
5923
5923
  });
5924
5924
  }
5925
- this.ws = new WebSocket(url, wsOptions);
5925
+ this.ws = new WebSocket$1(url, wsOptions);
5926
5926
  this.ws.on("open", () => {
5927
5927
  if (url.startsWith("wss://") && this.opts.tlsFingerprint) {
5928
5928
  const tlsError = this.validateTlsFingerprint();
@@ -6141,7 +6141,7 @@ var GatewayClient = class {
6141
6141
  return null;
6142
6142
  }
6143
6143
  async request(method, params, opts) {
6144
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("gateway not connected");
6144
+ if (!this.ws || this.ws.readyState !== WebSocket$1.OPEN) throw new Error("gateway not connected");
6145
6145
  const id = randomUUID();
6146
6146
  const frame = {
6147
6147
  type: "req",
@@ -7090,7 +7090,7 @@ async function routeReply(params) {
7090
7090
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
7091
7091
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
7092
7092
  try {
7093
- const { deliverOutboundPayloads } = await import("./deliver-q23ar_Pm.js").then((n) => n.n);
7093
+ const { deliverOutboundPayloads } = await import("./deliver-f3cIWxXT.js").then((n) => n.n);
7094
7094
  return {
7095
7095
  ok: true,
7096
7096
  messageId: (await deliverOutboundPayloads({
@@ -42079,7 +42079,7 @@ async function deliverSessionMaintenanceWarning(params) {
42079
42079
  return;
42080
42080
  }
42081
42081
  try {
42082
- const { deliverOutboundPayloads } = await import("./deliver-q23ar_Pm.js").then((n) => n.n);
42082
+ const { deliverOutboundPayloads } = await import("./deliver-f3cIWxXT.js").then((n) => n.n);
42083
42083
  await deliverOutboundPayloads({
42084
42084
  cfg: params.cfg,
42085
42085
  channel,
@@ -7,7 +7,7 @@ import "./ssrf-BCSnhba8.js";
7
7
  import "./boolean-BW6OTjPi.js";
8
8
  import "./shell-env-DgjeObDZ.js";
9
9
  import "./manifest-registry-CAWGTwb5.js";
10
- import { _ as fetchJson, b as withCdpSocket, d as normalizeCdpWsUrl, g as appendCdpPath, h as withBrowserNavigationPolicy, m as assertBrowserNavigationAllowed, t as getChromeWebSocketUrl, u as formatAriaSnapshot, y as getHeadersWithAuth } from "./chrome-DNssqQJs.js";
10
+ import { _ as fetchJson, b as withCdpSocket, d as normalizeCdpWsUrl, g as appendCdpPath, h as withBrowserNavigationPolicy, m as assertBrowserNavigationAllowed, t as getChromeWebSocketUrl, u as formatAriaSnapshot, y as getHeadersWithAuth } from "./chrome-3jl2ulOE.js";
11
11
  import { t as formatCliCommand } from "./command-format-DPd9RN2g.js";
12
12
  import "./redact-DSOAcWMe.js";
13
13
  import { n as formatErrorMessage } from "./errors-BEU7IHU6.js";
@@ -6,8 +6,8 @@ import "./model-selection-BisYvTBb.js";
6
6
  import "./reply-prefix-i-FPYcoQ.js";
7
7
  import "./plugins-CZ_mYwXq.js";
8
8
  import "./replies-0nzkXt6o.js";
9
- import { n as runAgentTurn } from "./pi-embedded-DP8324Ib.js";
10
- import "./deliver-q23ar_Pm.js";
9
+ import { n as runAgentTurn } from "./pi-embedded-BxKs-STI.js";
10
+ import "./deliver-f3cIWxXT.js";
11
11
  import "./diagnostic-BdRnGknC.js";
12
12
  import "./diagnostic-session-state-DpxCUzoM.js";
13
13
  import "./chunk-CAZujdOi.js";
@@ -16,14 +16,14 @@ import "./ssrf-BCSnhba8.js";
16
16
  import "./boolean-BW6OTjPi.js";
17
17
  import "./shell-env-DgjeObDZ.js";
18
18
  import "./manifest-registry-CAWGTwb5.js";
19
- import "./chrome-DNssqQJs.js";
19
+ import "./chrome-3jl2ulOE.js";
20
20
  import "./skills-DO7WNsVJ.js";
21
21
  import "./redact-DSOAcWMe.js";
22
22
  import "./errors-BEU7IHU6.js";
23
23
  import "./tokens-yWO1wD7Z.js";
24
24
  import "./thinking-DgjGxdSP.js";
25
25
  import "./paths-BsT3BvfH.js";
26
- import "./manager-BWWH1lYn.js";
26
+ import "./manager-Ct4kRT7n.js";
27
27
  import "./github-copilot-token-dYUr1mDQ.js";
28
28
  import "./sqlite-D8iYC_CU.js";
29
29
  import "./markdown-tables-jQzXAsf3.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symerian/symi",
3
- "version": "3.5.12",
3
+ "version": "3.5.14",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/jaysteelmind/symi#readme",