@symerian/symi 2.1.5 → 2.1.7

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.
@@ -12,10 +12,10 @@ import "./accounts-8zZqL37v.js";
12
12
  import "./image-ops-ByaQt43P.js";
13
13
  import "./pi-model-discovery-j5tVLINv.js";
14
14
  import "./message-channel-BQINJQIT.js";
15
- import "./pi-embedded-helpers-B6ugLqkI.js";
15
+ import "./pi-embedded-helpers-SPJVuQfB.js";
16
16
  import "./config-diuFc3fL.js";
17
17
  import "./manifest-registry-D-mTF1cj.js";
18
- import "./chrome-DPHgzMPu.js";
18
+ import "./chrome-CqribT6Z.js";
19
19
  import "./skills-BNpGMnp-.js";
20
20
  import "./redact-1NGYV_8p.js";
21
21
  import "./errors-CPfngF0S.js";
@@ -25,10 +25,10 @@ import "./thinking-W85Rb32m.js";
25
25
  import "./accounts-DImOt9jX.js";
26
26
  import "./paths-DkMamAQ-.js";
27
27
  import "./tool-images-ChC2CXaN.js";
28
- import "./image-EKTeO3aa.js";
28
+ import "./image-CV4FUL4M.js";
29
29
  import "./gemini-auth-CrwifqcZ.js";
30
30
  import "./local-roots-CC8jiKDk.js";
31
- import { a as resolveMediaAttachmentLocalRoots, n as createMediaAttachmentCache, o as runCapability, r as normalizeMediaAttachments, t as buildProviderRegistry, u as isAudioAttachment } from "./runner-BlTur7kC.js";
31
+ import { a as resolveMediaAttachmentLocalRoots, n as createMediaAttachmentCache, o as runCapability, r as normalizeMediaAttachments, t as buildProviderRegistry, u as isAudioAttachment } from "./runner-Cx1wJumq.js";
32
32
 
33
33
  //#region src/media-understanding/audio-preflight.ts
34
34
  /**
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.1.5",
3
- "commit": "1d0607d2d61b8468c3c6a5d3867c574da83535a0",
4
- "builtAt": "2026-04-02T22:46:11.885Z"
2
+ "version": "2.1.7",
3
+ "commit": "236862b570794ff905bce9ae36d6385111b98492",
4
+ "builtAt": "2026-04-02T23:20:10.633Z"
5
5
  }
@@ -1 +1 @@
1
- 244228ec2c49d5b2b8729910500bb01f8e30cfe81c17e276404ff6056e0c5ce7
1
+ e6228164a7b3d4d917efbeca02e1b790a79300e805bd48e5dc29701f1217ed91
@@ -10,7 +10,7 @@ import fs$1 from "node:fs/promises";
10
10
  import { execFileSync, spawn } from "node:child_process";
11
11
  import net from "node:net";
12
12
  import { createServer } from "node:http";
13
- import WebSocket$1, { WebSocketServer } from "ws";
13
+ import WebSocket, { WebSocketServer } from "ws";
14
14
  import { Buffer as Buffer$1 } from "node:buffer";
15
15
 
16
16
  //#region src/browser/constants.ts
@@ -178,7 +178,7 @@ async function ensureChromeExtensionRelayServer(opts) {
178
178
  let nextExtensionId = 1;
179
179
  const sendToExtension = async (payload) => {
180
180
  const ws = extensionWs;
181
- if (!ws || ws.readyState !== WebSocket$1.OPEN) throw new Error("Chrome extension not connected");
181
+ if (!ws || ws.readyState !== WebSocket.OPEN) throw new Error("Chrome extension not connected");
182
182
  ws.send(JSON.stringify(payload));
183
183
  return await new Promise((resolve, reject) => {
184
184
  const timer = setTimeout(() => {
@@ -195,12 +195,12 @@ async function ensureChromeExtensionRelayServer(opts) {
195
195
  const broadcastToCdpClients = (evt) => {
196
196
  const msg = JSON.stringify(evt);
197
197
  for (const ws of cdpClients) {
198
- if (ws.readyState !== WebSocket$1.OPEN) continue;
198
+ if (ws.readyState !== WebSocket.OPEN) continue;
199
199
  ws.send(msg);
200
200
  }
201
201
  };
202
202
  const sendResponseToCdp = (ws, res) => {
203
- if (ws.readyState !== WebSocket$1.OPEN) return;
203
+ if (ws.readyState !== WebSocket.OPEN) return;
204
204
  ws.send(JSON.stringify(res));
205
205
  };
206
206
  const ensureTargetEventsForClient = (ws, mode) => {
@@ -425,7 +425,7 @@ async function ensureChromeExtensionRelayServer(opts) {
425
425
  wssExtension.on("connection", (ws) => {
426
426
  extensionWs = ws;
427
427
  const ping = setInterval(() => {
428
- if (ws.readyState !== WebSocket$1.OPEN) return;
428
+ if (ws.readyState !== WebSocket.OPEN) return;
429
429
  ws.send(JSON.stringify({ method: "ping" }));
430
430
  }, 5e3);
431
431
  ws.on("message", (data) => {
@@ -743,7 +743,7 @@ async function fetchOk(url, timeoutMs = 1500, init) {
743
743
  }
744
744
  async function withCdpSocket(wsUrl, fn, opts) {
745
745
  const headers = getHeadersWithAuth(wsUrl, opts?.headers ?? {});
746
- const ws = new WebSocket$1(wsUrl, {
746
+ const ws = new WebSocket(wsUrl, {
747
747
  handshakeTimeout: typeof opts?.handshakeTimeoutMs === "number" && Number.isFinite(opts.handshakeTimeoutMs) ? Math.max(1, Math.floor(opts.handshakeTimeoutMs)) : 5e3,
748
748
  ...Object.keys(headers).length ? { headers } : {}
749
749
  });
@@ -1637,7 +1637,7 @@ async function getChromeWebSocketUrl(cdpUrl, timeoutMs = 500) {
1637
1637
  async function canOpenWebSocket(wsUrl, timeoutMs = 800) {
1638
1638
  return await new Promise((resolve) => {
1639
1639
  const headers = getHeadersWithAuth(wsUrl);
1640
- const ws = new WebSocket$1(wsUrl, {
1640
+ const ws = new WebSocket(wsUrl, {
1641
1641
  handshakeTimeout: timeoutMs,
1642
1642
  ...Object.keys(headers).length ? { headers } : {}
1643
1643
  });
@@ -5,7 +5,7 @@ import { c as getActivePluginRegistry, v as createInternalHookEvent, y as trigge
5
5
  import { t as createSubsystemLogger } from "./subsystem-CZixfwU8.js";
6
6
  import { a as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-Cn6drXx2.js";
7
7
  import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-71oIavrF.js";
8
- import { B as resolveMirroredTranscriptText, i as isMessagingToolDuplicate, z as appendAssistantMessageToSessionTranscript } from "./pi-embedded-helpers-B6ugLqkI.js";
8
+ import { B as resolveMirroredTranscriptText, i as isMessagingToolDuplicate, z as appendAssistantMessageToSessionTranscript } from "./pi-embedded-helpers-SPJVuQfB.js";
9
9
  import { d as getChannelDock } from "./thinking-W85Rb32m.js";
10
10
  import { c as resolveChunkMode, f as parseFenceSpans, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, n as chunkByParagraph } from "./chunk-DTMTDXwE.js";
11
11
  import { n as resolveMarkdownTableMode } from "./markdown-tables-DawaaZEe.js";
@@ -7,13 +7,13 @@ import { a as resolveAgentIdentity } from "./reply-prefix-K_J_nfgx.js";
7
7
  import "./github-copilot-token-BbsJ0Qbo.js";
8
8
  import "./env-CQ_DQOwT.js";
9
9
  import "./tokens-Cn6drXx2.js";
10
- import { D as resolveAgentTimeoutMs, t as runEmbeddedPiAgent } from "./pi-embedded-02ObvVIR.js";
10
+ import { D as resolveAgentTimeoutMs, t as runEmbeddedPiAgent } from "./pi-embedded-DguKAKpR.js";
11
11
  import "./plugins-71oIavrF.js";
12
12
  import "./accounts-DDEyGwby.js";
13
13
  import "./bindings-DYVakimr.js";
14
14
  import "./send-BPW99hCM.js";
15
15
  import "./send-DFVqIDB9.js";
16
- import "./deliver-EKA6SdgU.js";
16
+ import "./deliver-vWWI-94q.js";
17
17
  import "./diagnostic-D0xmLpej.js";
18
18
  import "./diagnostic-session-state-C1vRJs5w.js";
19
19
  import "./accounts-8zZqL37v.js";
@@ -21,10 +21,10 @@ import "./send-Bz140PN8.js";
21
21
  import "./image-ops-ByaQt43P.js";
22
22
  import "./pi-model-discovery-j5tVLINv.js";
23
23
  import "./message-channel-BQINJQIT.js";
24
- import { G as saveSessionStore, H as loadSessionStore } from "./pi-embedded-helpers-B6ugLqkI.js";
24
+ import { G as saveSessionStore, H as loadSessionStore } from "./pi-embedded-helpers-SPJVuQfB.js";
25
25
  import "./config-diuFc3fL.js";
26
26
  import "./manifest-registry-D-mTF1cj.js";
27
- import "./chrome-DPHgzMPu.js";
27
+ import "./chrome-CqribT6Z.js";
28
28
  import "./skills-BNpGMnp-.js";
29
29
  import "./redact-1NGYV_8p.js";
30
30
  import "./errors-CPfngF0S.js";
@@ -34,7 +34,7 @@ import "./thinking-W85Rb32m.js";
34
34
  import "./accounts-DImOt9jX.js";
35
35
  import { n as resolveSessionFilePath, s as resolveStorePath } from "./paths-DkMamAQ-.js";
36
36
  import "./tool-images-ChC2CXaN.js";
37
- import "./image-EKTeO3aa.js";
37
+ import "./image-CV4FUL4M.js";
38
38
  import "./manager-CL7MzOkQ.js";
39
39
  import "./gemini-auth-CrwifqcZ.js";
40
40
  import "./sqlite-BNh23mUR.js";
@@ -47,7 +47,7 @@ import "./ir-F0moAwIl.js";
47
47
  import "./render-B1VqYyvo.js";
48
48
  import "./commands-registry-B_XO7lUV.js";
49
49
  import "./skill-commands-sj8KNio8.js";
50
- import "./runner-BlTur7kC.js";
50
+ import "./runner-Cx1wJumq.js";
51
51
  import "./fetch-DtLn7YU3.js";
52
52
  import "./channel-activity-D9q-fIPB.js";
53
53
  import "./tables-COnZ169v.js";
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
2
  import { D as isRecord, I as shortenHomeInString } from "./registry-BhoUuugi.js";
3
3
  import { G as resolveSymiAgentDir, S as getApiKeyForModel, Y as normalizeSecretInput, _ as resolveImplicitBedrockProvider, g as normalizeProviders, v as resolveImplicitCopilotProvider, w as requireApiKey, y as resolveImplicitProviders } from "./model-selection-DzqcLIsS.js";
4
4
  import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-j5tVLINv.js";
5
- import { N as sanitizeUserFacingText } from "./pi-embedded-helpers-B6ugLqkI.js";
5
+ import { N as sanitizeUserFacingText } from "./pi-embedded-helpers-SPJVuQfB.js";
6
6
  import { n as loadConfig } from "./config-diuFc3fL.js";
7
7
  import { n as redactToolDetail } from "./redact-1NGYV_8p.js";
8
8
  import path from "node:path";
@@ -14,7 +14,7 @@ import { a as logoutWeb, i as logWebSelfId, l as readWebSelfId, p as webAuthExis
14
14
  import { t as normalizeChatType } from "./chat-type-DFDuk3FY.js";
15
15
  import { a as resolveSlackWebClientOptions, c as buildSlackBlocksFallbackText, i as createSlackWebClient, l as parseSlackTarget, o as parseSlackBlocksInput, s as validateSlackBlocksArray, t as sendMessageSlack, u as resolveSlackChannelId } from "./send-BPW99hCM.js";
16
16
  import { $ as fetchChannelPermissionsDiscord, A as unpinMessageDiscord, B as listScheduledEventsDiscord, C as editMessageDiscord, Ct as resolveTimestampMs, D as pinMessageDiscord, Dt as normalizeChannelSlug, E as listThreadsDiscord, Et as buildChannelKeyCandidates, F as fetchMemberInfoDiscord, G as uploadStickerDiscord, H as timeoutMemberDiscord, I as fetchRoleInfoDiscord, J as editChannelDiscord, K as createChannelDiscord, L as fetchVoiceStatusDiscord, M as banMemberDiscord, N as createScheduledEventDiscord, O as readMessagesDiscord, Ot as resolveChannelEntryMatchWithFallback, P as fetchChannelInfoDiscord, Q as stripUndefinedFields, R as kickMemberDiscord, S as deleteMessageDiscord, St as resolveDiscordSystemLocation, T as listPinsDiscord, Tt as applyChannelMatchMeta, U as listGuildEmojisDiscord, V as removeRoleDiscord, W as uploadEmojiDiscord, X as removeChannelPermissionDiscord, Y as moveChannelDiscord, Z as setChannelPermissionDiscord, _ as sendPollDiscord, _t as resolveDiscordShouldRequireMention, a as removeReactionDiscord, at as resolveDiscordChannelId, b as sendWebhookMessageDiscord, bt as formatDiscordReactionEmoji, c as formatDiscordComponentEventText, ct as allowListMatches$1, d as parseDiscordModalCustomId, dt as normalizeDiscordSlug, et as hasAnyGuildPermissionDiscord, f as parseDiscordModalCustomIdForCarbon, ft as resolveDiscordAllowListMatch, g as sendMessageDiscord, gt as resolveDiscordOwnerAllowFrom, h as resolveDiscordModalEntry, ht as resolveDiscordMemberAccessState, i as removeOwnReactionsDiscord, it as parseDiscordTarget, j as addRoleDiscord, k as searchMessagesDiscord, l as parseDiscordComponentCustomId, lt as isDiscordGroupAllowedByPolicy, m as resolveDiscordComponentEntry, mt as resolveDiscordGuildEntry, n as fetchReactionsDiscord, nt as createDiscordClient, o as sendDiscordComponentMessage, ot as listDiscordDirectoryGroupsLive, p as readDiscordComponentSpec, pt as resolveDiscordChannelConfigWithFallback, q as deleteChannelDiscord, r as reactMessageDiscord, rt as createDiscordRestClient, s as createDiscordFormModal, st as listDiscordDirectoryPeersLive, tt as chunkDiscordTextWithMode, u as parseDiscordComponentCustomIdForCarbon, ut as normalizeDiscordAllowList, v as sendStickerDiscord, vt as resolveGroupDmAllow, w as fetchMessageDiscord, wt as fetchDiscord, x as createThreadDiscord, xt as formatDiscordUserTag, y as sendVoiceMessageDiscord, yt as shouldEmitDiscordReactionNotification, z as listGuildChannelsDiscord } from "./send-DFVqIDB9.js";
17
- import { C as getGlobalHookRunner, S as parseInlineDirectives$1, _ as normalizeTargetForProvider, a as normalizeOutboundPayloadsForJson, b as MEDIA_TOKEN_RE, c as applyReplyThreading, d as isRenderablePayload, f as shouldSuppressMessagingToolReplies, g as normalizeChannelTargetInput, h as buildTargetResolverSignature, i as normalizeOutboundPayloads, l as filterMessagingToolDuplicates, m as resolveReplyToMode, o as normalizeReplyPayloadsForDelivery, p as createReplyToModeFilterForChannel, r as formatOutboundPayloadLog, s as applyReplyTagsToPayload, t as deliverOutboundPayloads, u as filterMessagingToolMediaDuplicates, v as throwIfAborted, w as initializeGlobalHookRunner, x as splitMediaFromOutput, y as parseReplyDirectives } from "./deliver-EKA6SdgU.js";
17
+ import { C as getGlobalHookRunner, S as parseInlineDirectives$1, _ as normalizeTargetForProvider, a as normalizeOutboundPayloadsForJson, b as MEDIA_TOKEN_RE, c as applyReplyThreading, d as isRenderablePayload, f as shouldSuppressMessagingToolReplies, g as normalizeChannelTargetInput, h as buildTargetResolverSignature, i as normalizeOutboundPayloads, l as filterMessagingToolDuplicates, m as resolveReplyToMode, o as normalizeReplyPayloadsForDelivery, p as createReplyToModeFilterForChannel, r as formatOutboundPayloadLog, s as applyReplyTagsToPayload, t as deliverOutboundPayloads, u as filterMessagingToolMediaDuplicates, v as throwIfAborted, w as initializeGlobalHookRunner, x as splitMediaFromOutput, y as parseReplyDirectives } from "./deliver-vWWI-94q.js";
18
18
  import { a as logMessageProcessed, c as logWebhookError, d as startDiagnosticHeartbeat, f as stopDiagnosticHeartbeat, i as logLaneEnqueue, l as logWebhookProcessed, m as isDiagnosticsEnabled, o as logMessageQueued, p as emitDiagnosticEvent, r as logLaneDequeue, s as logSessionStateChange, t as diag, u as logWebhookReceived } from "./diagnostic-D0xmLpej.js";
19
19
  import { r as getDiagnosticSessionState } from "./diagnostic-session-state-C1vRJs5w.js";
20
20
  import { n as resolveSignalAccount, t as listEnabledSignalAccounts } from "./accounts-8zZqL37v.js";
@@ -22,10 +22,10 @@ import { $ as isVoiceCompatibleAudio, A as extractTelegramLocation, B as normali
22
22
  import { d as detectMime, f as extensionForMime, g as isGifMedia, h as isAudioFileName, i as getImageMetadata, m as imageMimeFromFormat, s as resizeToJpeg, x as mediaKindFromMime, y as MAX_IMAGE_BYTES } from "./image-ops-ByaQt43P.js";
23
23
  import { n as discoverModels, t as discoverAuthStorage } from "./pi-model-discovery-j5tVLINv.js";
24
24
  import { a as isMarkdownCapableMessageChannel, c as resolveGatewayMessageChannel, d as GATEWAY_CLIENT_MODES, f as GATEWAY_CLIENT_NAMES, i as isInternalMessageChannel, l as resolveMessageChannel, n as isDeliverableMessageChannel, o as listDeliverableMessageChannels, r as isGatewayMessageChannel, s as normalizeMessageChannel, t as INTERNAL_MESSAGE_CHANNEL, u as GATEWAY_CLIENT_IDS } from "./message-channel-BQINJQIT.js";
25
- import { $ as mergeDeliveryContext, A as isTransientHttpError, At as DEFAULT_UPLOAD_DIR, Bt as expandToolGroups, C as isContextOverflowError, Ct as resolveGroupSessionKey, D as isRateLimitAssistantError, Dt as registerBrowserRoutes, E as isLikelyContextOverflowError, Et as createBrowserRouteContext, F as resolveSandboxContext, Ft as resolveSandboxConfigForAgent, Gt as compileGlobPatterns, H as loadSessionStore, Ht as normalizeToolName, I as resolveSandboxRuntimeStatus, It as applyOwnerOnlyToolPolicy, J as updateSessionStoreEntry, Jt as ensureSessionHeader, K as updateLastRoute, Kt as matchesAnyGlobPattern, L as extractDeliveryInfo, Lt as buildPluginToolGroups, M as parseImageSizeError, Mt as getBridgeAuthForPort, N as sanitizeUserFacingText, Nt as ensureBrowserControlAuth, O as isRawApiErrorPayload, Ot as resolveBrowserConfig, P as ensureSandboxWorkspaceForSession, Pt as resolveBrowserControlAuth, Q as deliveryContextKey, R as parseSessionThreadInfo, Rt as collectExplicitAllowlist, S as isCompactionFailureError, St as deriveSessionMetaPatch, T as isFailoverErrorMessage, Tt as resolveSessionLockMaxHoldFromTimeout, U as readSessionUpdatedAt, Ut as resolveToolProfilePolicy, V as resolveAndPersistSessionFile, Vt as mergeAlsoAllowPolicy, W as recordSessionMetaFromInbound, Wt as stripPluginOnlyAllowlist, X as resolveCacheTtlMs$1, Xt as resolveBootstrapTotalMaxChars, Y as isCacheEnabled, Yt as resolveBootstrapMaxChars, Z as deliveryContextFromSession, Zt as sanitizeGoogleTurnOrdering, _ as formatRawAssistantErrorForUi, _t as DEFAULT_RESET_TRIGGERS, a as isMessagingToolDuplicateNormalized, at as countToolResults, b as isBillingAssistantError, bt as resolveExplicitAgentSessionKey, c as extractToolCallsFromAssistant, ct as applyInputProvenanceToUserMessage, d as isAntigravityClaude, dt as resolveSessionKey, et as normalizeDeliveryContext, f as isGoogleModelApi, ft as evaluateSessionFreshness, g as formatBillingErrorMessage, gt as resolveThreadFlag, h as formatAssistantErrorText, ht as resolveSessionResetType, it as capArrayByJsonBytes, j as parseImageDimensionError, jt as resolveExistingPathsWithinRoot, k as isTimeoutErrorMessage, kt as resolveProfile, l as extractToolResultId, lt as hasInterSessionUserProvenance, m as classifyFailoverReason, mt as resolveSessionResetPolicy, n as validateGeminiTurns, nt as normalizeAccountId$3, o as normalizeTextForComparison, ot as extractToolCallNames, p as BILLING_ERROR_USER_MESSAGE, pt as resolveChannelResetConfig, q as updateSessionStore, qt as buildBootstrapContextFiles, r as pickFallbackThinkingLevel, rt as archiveSessionTranscripts, s as sanitizeSessionMessagesImages, st as INPUT_PROVENANCE_KIND_VALUES, t as validateAnthropicTurns, tt as normalizeSessionDeliveryFields, u as downgradeOpenAIReasoningBlocks, ut as normalizeInputProvenance, v as getApiErrorPayloadFingerprint, vt as resolveFreshSessionTotalTokens, w as isFailoverAssistantError, wt as acquireSessionWriteLock, x as isCloudCodeAssistFormatError, xt as resolveMainSessionKey, y as isAuthAssistantError, yt as canonicalizeMainSessionAlias, z as appendAssistantMessageToSessionTranscript, zt as expandPolicyWithPluginGroups } from "./pi-embedded-helpers-B6ugLqkI.js";
25
+ import { $ as mergeDeliveryContext, A as isTransientHttpError, At as DEFAULT_UPLOAD_DIR, Bt as expandToolGroups, C as isContextOverflowError, Ct as resolveGroupSessionKey, D as isRateLimitAssistantError, Dt as registerBrowserRoutes, E as isLikelyContextOverflowError, Et as createBrowserRouteContext, F as resolveSandboxContext, Ft as resolveSandboxConfigForAgent, Gt as compileGlobPatterns, H as loadSessionStore, Ht as normalizeToolName, I as resolveSandboxRuntimeStatus, It as applyOwnerOnlyToolPolicy, J as updateSessionStoreEntry, Jt as ensureSessionHeader, K as updateLastRoute, Kt as matchesAnyGlobPattern, L as extractDeliveryInfo, Lt as buildPluginToolGroups, M as parseImageSizeError, Mt as getBridgeAuthForPort, N as sanitizeUserFacingText, Nt as ensureBrowserControlAuth, O as isRawApiErrorPayload, Ot as resolveBrowserConfig, P as ensureSandboxWorkspaceForSession, Pt as resolveBrowserControlAuth, Q as deliveryContextKey, R as parseSessionThreadInfo, Rt as collectExplicitAllowlist, S as isCompactionFailureError, St as deriveSessionMetaPatch, T as isFailoverErrorMessage, Tt as resolveSessionLockMaxHoldFromTimeout, U as readSessionUpdatedAt, Ut as resolveToolProfilePolicy, V as resolveAndPersistSessionFile, Vt as mergeAlsoAllowPolicy, W as recordSessionMetaFromInbound, Wt as stripPluginOnlyAllowlist, X as resolveCacheTtlMs$1, Xt as resolveBootstrapTotalMaxChars, Y as isCacheEnabled, Yt as resolveBootstrapMaxChars, Z as deliveryContextFromSession, Zt as sanitizeGoogleTurnOrdering, _ as formatRawAssistantErrorForUi, _t as DEFAULT_RESET_TRIGGERS, a as isMessagingToolDuplicateNormalized, at as countToolResults, b as isBillingAssistantError, bt as resolveExplicitAgentSessionKey, c as extractToolCallsFromAssistant, ct as applyInputProvenanceToUserMessage, d as isAntigravityClaude, dt as resolveSessionKey, et as normalizeDeliveryContext, f as isGoogleModelApi, ft as evaluateSessionFreshness, g as formatBillingErrorMessage, gt as resolveThreadFlag, h as formatAssistantErrorText, ht as resolveSessionResetType, it as capArrayByJsonBytes, j as parseImageDimensionError, jt as resolveExistingPathsWithinRoot, k as isTimeoutErrorMessage, kt as resolveProfile, l as extractToolResultId, lt as hasInterSessionUserProvenance, m as classifyFailoverReason, mt as resolveSessionResetPolicy, n as validateGeminiTurns, nt as normalizeAccountId$3, o as normalizeTextForComparison, ot as extractToolCallNames, p as BILLING_ERROR_USER_MESSAGE, pt as resolveChannelResetConfig, q as updateSessionStore, qt as buildBootstrapContextFiles, r as pickFallbackThinkingLevel, rt as archiveSessionTranscripts, s as sanitizeSessionMessagesImages, st as INPUT_PROVENANCE_KIND_VALUES, t as validateAnthropicTurns, tt as normalizeSessionDeliveryFields, u as downgradeOpenAIReasoningBlocks, ut as normalizeInputProvenance, v as getApiErrorPayloadFingerprint, vt as resolveFreshSessionTotalTokens, w as isFailoverAssistantError, wt as acquireSessionWriteLock, x as isCloudCodeAssistFormatError, xt as resolveMainSessionKey, y as isAuthAssistantError, yt as canonicalizeMainSessionAlias, z as appendAssistantMessageToSessionTranscript, zt as expandPolicyWithPluginGroups } from "./pi-embedded-helpers-SPJVuQfB.js";
26
26
  import { A as VERSION, C as getConfigValueAtPath, D as isSafeExecutableValue, E as unsetConfigValueAtPath, O as DEFAULT_SUBAGENT_MAX_SPAWN_DEPTH, S as unsetConfigOverride, T as setConfigValueAtPath, _ as parseDurationMs, a as writeConfigFile, b as resetConfigOverrides, c as TELEGRAM_COMMAND_NAME_PATTERN, f as isInboundPathAllowed, g as normalizeScpRemoteHost, h as resolveIMessageRemoteAttachmentRoots, i as resolveConfigSnapshotHash, k as resolveAgentMaxConcurrent, l as normalizeTelegramCommandName, m as resolveIMessageAttachmentRoots, n as loadConfig, o as validateConfigObjectWithPlugins, r as readConfigFileSnapshot, u as resolveTelegramCustomCommands, v as validateJsonSchemaValue, w as parseConfigPath, x as setConfigOverride, y as getConfigOverrides } from "./config-diuFc3fL.js";
27
27
  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-D-mTF1cj.js";
28
- import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-DPHgzMPu.js";
28
+ import { C as rawDataToString, O as DEFAULT_AI_SNAPSHOT_MAX_CHARS, T as isSecureWebSocketUrl, x as ensureChromeExtensionRelayServer } from "./chrome-CqribT6Z.js";
29
29
  import { c as assertSandboxPath, d as resolveSandboxedMediaSource, f as applySkillEnvOverrides, i as resolveSkillsPromptForRun, l as resolveSandboxInputPath, n as buildWorkspaceSkillSnapshot, p as applySkillEnvOverridesFromSnapshot, r as loadWorkspaceSkillEntries, s as assertMediaNotDataUrl } from "./skills-BNpGMnp-.js";
30
30
  import { n as formatErrorMessage, r as formatUncaughtError } from "./errors-CPfngF0S.js";
31
31
  import { i as isBlockedHostnameOrIp, o as normalizeHostname, t as SsrFBlockedError } from "./ssrf-CxfFyMRZ.js";
@@ -36,7 +36,7 @@ import { t as resolveIMessageAccount } from "./accounts-DImOt9jX.js";
36
36
  import { i as resolveSessionTranscriptPath, n as resolveSessionFilePath, o as resolveSessionTranscriptsDirForAgent, r as resolveSessionFilePathOptions, s as resolveStorePath, t as resolveDefaultSessionStorePath } from "./paths-DkMamAQ-.js";
37
37
  import { t as emitSessionTranscriptUpdate } from "./transcript-events-C8Tqw4td.js";
38
38
  import { i as resolveImageSanitizationLimits, n as sanitizeImageBlocks, r as sanitizeToolResultImages } from "./tool-images-ChC2CXaN.js";
39
- import { S as ensureSymiModelsJson, _ as stripMinimaxToolCallXml, a as decodeDataUrl, b as stripReasoningTagsFromText, c as extractAssistantText$1, d as extractThinkingFromTaggedText, f as formatReasoningMessage, g as stripDowngradedToolCallText, h as promoteThinkingTagsToBlocks, i as coerceImageModelConfig, l as extractAssistantThinking, m as isAssistantMessage, o as resolveProviderVisionModelFromConfig, p as inferToolMetaFromArgs, r as coerceImageAssistantText, s as minimaxUnderstandImage, u as extractThinkingFromTaggedStream, v as stripThinkingTagsFromText, x as extractTextFromChatContent, y as resolveToolDisplay } from "./image-EKTeO3aa.js";
39
+ import { S as ensureSymiModelsJson, _ as stripMinimaxToolCallXml, a as decodeDataUrl, b as stripReasoningTagsFromText, c as extractAssistantText$1, d as extractThinkingFromTaggedText, f as formatReasoningMessage, g as stripDowngradedToolCallText, h as promoteThinkingTagsToBlocks, i as coerceImageModelConfig, l as extractAssistantThinking, m as isAssistantMessage, o as resolveProviderVisionModelFromConfig, p as inferToolMetaFromArgs, r as coerceImageAssistantText, s as minimaxUnderstandImage, u as extractThinkingFromTaggedStream, v as stripThinkingTagsFromText, x as extractTextFromChatContent, y as resolveToolDisplay } from "./image-CV4FUL4M.js";
40
40
  import { i as resolveMemorySearchConfig, n as probeOllamaEmbeddingModels, r as resolveOllamaBaseUrl } from "./manager-CL7MzOkQ.js";
41
41
  import { d as listMemoryFiles, f as normalizeExtraMemoryPaths, g as runTasksWithConcurrency } from "./sqlite-BNh23mUR.js";
42
42
  import { n as retryAsync } from "./retry-QGp0jvVi.js";
@@ -49,7 +49,7 @@ import { a as loadWebMedia, i as getDefaultLocalRoots } from "./ir-F0moAwIl.js";
49
49
  import { _ as resolveNativeCommandsEnabled, a as listChatCommandsForConfig, c as normalizeCommandBody, d as resolveCommandArgMenu, f as serializeCommandArgs, g as isRestartEnabled, h as isNativeCommandsExplicitlyDisabled, i as listChatCommands, l as parseCommandArgs, m as isCommandFlagEnabled, o as listNativeCommandSpecs, p as shouldHandleTextCommands, r as findCommandByNativeName, s as listNativeCommandSpecsForConfig, t as buildCommandTextFromArgs, u as resolveCommandArgChoices, v as resolveNativeSkillsEnabled } from "./commands-registry-B_XO7lUV.js";
50
50
  import { c as getSkillsSnapshotVersion, d as createAsyncLock, f as readJsonFile, i as resolveSkillCommandInvocation, l as pruneExpiredPending, n as listSkillCommandsForAgents, o as getRemoteSkillEligibility, p as writeJsonAtomic, r as listSkillCommandsForWorkspace, s as ensureSkillsWatcher, t as listReservedChatSlashCommandNames, u as resolvePairingPaths } from "./skill-commands-sj8KNio8.js";
51
51
  import { r as normalizeInboundTextNewlines, t as finalizeInboundContext } from "./inbound-context-QOi5vzUt.js";
52
- import { _ as resolveMediaUnderstandingScope, a as resolveMediaAttachmentLocalRoots, c as loadModelCatalog, d as resolveAttachmentKind, f as buildRandomTempFilePath, g as normalizeMediaUnderstandingChatType, h as resolveTimeoutMs$1, i as resolveAutoImageModel, l as modelSupportsVision, m as resolveConcurrency, n as createMediaAttachmentCache, o as runCapability, p as registerUnhandledRejectionHandler, r as normalizeMediaAttachments, s as findModelInCatalog, t as buildProviderRegistry, v as CLI_OUTPUT_MAX_BUFFER, y as applyTemplate } from "./runner-BlTur7kC.js";
52
+ import { _ as resolveMediaUnderstandingScope, a as resolveMediaAttachmentLocalRoots, c as loadModelCatalog, d as resolveAttachmentKind, f as buildRandomTempFilePath, g as normalizeMediaUnderstandingChatType, h as resolveTimeoutMs$1, i as resolveAutoImageModel, l as modelSupportsVision, m as resolveConcurrency, n as createMediaAttachmentCache, o as runCapability, p as registerUnhandledRejectionHandler, r as normalizeMediaAttachments, s as findModelInCatalog, t as buildProviderRegistry, v as CLI_OUTPUT_MAX_BUFFER, y as applyTemplate } from "./runner-Cx1wJumq.js";
53
53
  import { n as wrapFetchWithAbortSignal, t as resolveFetch } from "./fetch-DtLn7YU3.js";
54
54
  import { n as recordCommandPoll, r as resetCommandPollCount } from "./command-poll-backoff-DtXYsHEc.js";
55
55
  import { n as recordChannelActivity, r as createDiscordRetryRunner, t as getChannelActivity } from "./channel-activity-D9q-fIPB.js";
@@ -79,7 +79,7 @@ import { EdgeTTS } from "node-edge-tts";
79
79
  import AjvPkg from "ajv";
80
80
  import { createServer } from "node:http";
81
81
  import { ProxyAgent, fetch as fetch$1 } from "undici";
82
- import WebSocket$1, { WebSocket } from "ws";
82
+ import WebSocket, { WebSocket as WebSocket$1 } from "ws";
83
83
  import { Buffer as Buffer$1 } from "node:buffer";
84
84
  import { createJiti } from "jiti";
85
85
  import { Type } from "@sinclair/typebox";
@@ -5714,7 +5714,7 @@ var GatewayClient = class {
5714
5714
  if (fingerprint !== expected) return /* @__PURE__ */ new Error("gateway tls fingerprint mismatch");
5715
5715
  });
5716
5716
  }
5717
- this.ws = new WebSocket(url, wsOptions);
5717
+ this.ws = new WebSocket$1(url, wsOptions);
5718
5718
  this.ws.on("open", () => {
5719
5719
  if (url.startsWith("wss://") && this.opts.tlsFingerprint) {
5720
5720
  const tlsError = this.validateTlsFingerprint();
@@ -5933,7 +5933,7 @@ var GatewayClient = class {
5933
5933
  return null;
5934
5934
  }
5935
5935
  async request(method, params, opts) {
5936
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("gateway not connected");
5936
+ if (!this.ws || this.ws.readyState !== WebSocket$1.OPEN) throw new Error("gateway not connected");
5937
5937
  const id = randomUUID();
5938
5938
  const frame = {
5939
5939
  type: "req",
@@ -7199,7 +7199,7 @@ async function routeReply(params) {
7199
7199
  const resolvedReplyToId = replyToId ?? (channelId === "slack" && threadId != null && threadId !== "" ? String(threadId) : void 0);
7200
7200
  const resolvedThreadId = channelId === "slack" ? null : threadId ?? null;
7201
7201
  try {
7202
- const { deliverOutboundPayloads } = await import("./deliver-EKA6SdgU.js").then((n) => n.n);
7202
+ const { deliverOutboundPayloads } = await import("./deliver-vWWI-94q.js").then((n) => n.n);
7203
7203
  return {
7204
7204
  ok: true,
7205
7205
  messageId: (await deliverOutboundPayloads({
@@ -41655,7 +41655,7 @@ async function deliverSessionMaintenanceWarning(params) {
41655
41655
  return;
41656
41656
  }
41657
41657
  try {
41658
- const { deliverOutboundPayloads } = await import("./deliver-EKA6SdgU.js").then((n) => n.n);
41658
+ const { deliverOutboundPayloads } = await import("./deliver-vWWI-94q.js").then((n) => n.n);
41659
41659
  await deliverOutboundPayloads({
41660
41660
  cfg: params.cfg,
41661
41661
  channel,
@@ -45101,7 +45101,7 @@ async function describeStickerImage(params) {
45101
45101
  logVerbose(`telegram: describing sticker with ${provider}/${model}`);
45102
45102
  try {
45103
45103
  const buffer = await fs$1.readFile(imagePath);
45104
- const { describeImageWithModel } = await import("./image-EKTeO3aa.js").then((n) => n.n);
45104
+ const { describeImageWithModel } = await import("./image-CV4FUL4M.js").then((n) => n.n);
45105
45105
  return (await describeImageWithModel({
45106
45106
  buffer,
45107
45107
  fileName: "sticker.webp",
@@ -47763,7 +47763,7 @@ async function preflightDiscordMessage(params) {
47763
47763
  let preflightTranscript;
47764
47764
  const hasAudioAttachment = message.attachments?.some((att) => att.contentType?.startsWith("audio/"));
47765
47765
  if (!isDirectMessage && shouldRequireMention && hasAudioAttachment && !baseText && mentionRegexes.length > 0) try {
47766
- const { transcribeFirstAudio } = await import("./audio-preflight-BnwAAlLw.js");
47766
+ const { transcribeFirstAudio } = await import("./audio-preflight-IRs02MgH.js");
47767
47767
  const audioPaths = message.attachments?.filter((att) => att.contentType?.startsWith("audio/")).map((att) => att.url) ?? [];
47768
47768
  if (audioPaths.length > 0) preflightTranscript = await transcribeFirstAudio({
47769
47769
  ctx: {
@@ -51769,7 +51769,7 @@ function isVoiceChannelType(type) {
51769
51769
  function createDefaultDeps() {
51770
51770
  return {
51771
51771
  sendMessageWhatsApp: async (...args) => {
51772
- const { sendMessageWhatsApp } = await import("./web-CMl4g_Bl.js");
51772
+ const { sendMessageWhatsApp } = await import("./web-cSkprx6P.js");
51773
51773
  return await sendMessageWhatsApp(...args);
51774
51774
  },
51775
51775
  sendMessageTelegram: async (...args) => {
@@ -54676,7 +54676,7 @@ function createDiscordGatewayPlugin(params) {
54676
54676
  super(options);
54677
54677
  }
54678
54678
  createWebSocket(url) {
54679
- return new WebSocket$1(url, { agent });
54679
+ return new WebSocket(url, { agent });
54680
54680
  }
54681
54681
  }
54682
54682
  return new ProxyGatewayPlugin();
@@ -64894,7 +64894,7 @@ const buildTelegramMessageContext = async ({ primaryCtx, allMedia, storeAllowFro
64894
64894
  const hasAudio = allMedia.some((media) => media.contentType?.startsWith("audio/"));
64895
64895
  let preflightTranscript;
64896
64896
  if (isGroup && requireMention && hasAudio && !hasUserText && mentionRegexes.length > 0) try {
64897
- const { transcribeFirstAudio } = await import("./audio-preflight-BnwAAlLw.js");
64897
+ const { transcribeFirstAudio } = await import("./audio-preflight-IRs02MgH.js");
64898
64898
  preflightTranscript = await transcribeFirstAudio({
64899
64899
  ctx: {
64900
64900
  MediaPaths: allMedia.length > 0 ? allMedia.map((m) => m.path) : void 0,
@@ -67051,7 +67051,7 @@ function loadWebLoginQr() {
67051
67051
  return webLoginQrPromise;
67052
67052
  }
67053
67053
  function loadWebChannel() {
67054
- webChannelPromise ??= import("./web-CMl4g_Bl.js");
67054
+ webChannelPromise ??= import("./web-cSkprx6P.js");
67055
67055
  return webChannelPromise;
67056
67056
  }
67057
67057
  function loadWhatsAppActions() {
@@ -10,7 +10,7 @@ import { t as normalizeChatType } from "./chat-type-DFDuk3FY.js";
10
10
  import { c as SafeOpenError, i as getImageMetadata, l as openFileWithinRoot, n as buildImageResizeSideGrid, s as resizeToJpeg, t as IMAGE_REDUCE_QUALITY_STEPS } from "./image-ops-ByaQt43P.js";
11
11
  import { o as listDeliverableMessageChannels, s as normalizeMessageChannel } from "./message-channel-BQINJQIT.js";
12
12
  import { _ as parseDurationMs, a as writeConfigFile, n as loadConfig, s as parseByteSize, t as createConfigIO } from "./config-diuFc3fL.js";
13
- 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-DPHgzMPu.js";
13
+ 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-CqribT6Z.js";
14
14
  import { a as syncSkillsToWorkspace, l as resolveSandboxInputPath, m as sanitizeEnvVars, u as resolveSandboxPath } from "./skills-BNpGMnp-.js";
15
15
  import { n as formatErrorMessage, t as extractErrorCode } from "./errors-CPfngF0S.js";
16
16
  import { t as SsrFBlockedError } from "./ssrf-CxfFyMRZ.js";
@@ -931,7 +931,7 @@ function isModuleNotFoundError(err) {
931
931
  }
932
932
  async function loadPwAiModule(mode) {
933
933
  try {
934
- return await import("./pw-ai-CD2xT-vT.js");
934
+ return await import("./pw-ai-DnN0T7wd.js");
935
935
  } catch (err) {
936
936
  if (mode === "soft") return null;
937
937
  if (isModuleNotFoundError(err)) return null;
@@ -3471,11 +3471,11 @@ function createProfileContext(opts, profile) {
3471
3471
  const userDataDir = resolveSymiUserDataDir(profile.name);
3472
3472
  const profileState = getProfileState();
3473
3473
  if (await isHttpReachable(300) && !profileState.running) try {
3474
- await (await import("./pw-ai-CD2xT-vT.js")).closePlaywrightBrowserConnection();
3474
+ await (await import("./pw-ai-DnN0T7wd.js")).closePlaywrightBrowserConnection();
3475
3475
  } catch {}
3476
3476
  if (profileState.running) await stopRunningBrowser();
3477
3477
  try {
3478
- await (await import("./pw-ai-CD2xT-vT.js")).closePlaywrightBrowserConnection();
3478
+ await (await import("./pw-ai-DnN0T7wd.js")).closePlaywrightBrowserConnection();
3479
3479
  } catch {}
3480
3480
  if (!fs.existsSync(userDataDir)) return {
3481
3481
  moved: false,
@@ -7,7 +7,7 @@ import "./github-copilot-token-BbsJ0Qbo.js";
7
7
  import { r as formatCliCommand } from "./env-CQ_DQOwT.js";
8
8
  import "./config-diuFc3fL.js";
9
9
  import "./manifest-registry-D-mTF1cj.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-DPHgzMPu.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-CqribT6Z.js";
11
11
  import "./redact-1NGYV_8p.js";
12
12
  import { n as formatErrorMessage } from "./errors-CPfngF0S.js";
13
13
  import "./ssrf-CxfFyMRZ.js";
@@ -4,7 +4,7 @@ import { G as resolveSymiAgentDir, T as resolveApiKeyForProvider, c as normalize
4
4
  import { t as normalizeChatType } from "./chat-type-DFDuk3FY.js";
5
5
  import { _ as kindFromMime, d as detectMime, h as isAudioFileName, p as getFileExtension } from "./image-ops-ByaQt43P.js";
6
6
  import { d as DEFAULT_IMESSAGE_ATTACHMENT_ROOTS, f as isInboundPathAllowed, m as resolveIMessageAttachmentRoots, n as loadConfig, p as mergeInboundPathRoots } from "./config-diuFc3fL.js";
7
- import { S as ensureSymiModelsJson, t as describeImageWithModel } from "./image-EKTeO3aa.js";
7
+ import { S as ensureSymiModelsJson, t as describeImageWithModel } from "./image-CV4FUL4M.js";
8
8
  import { n as collectProviderApiKeysForExecution, r as executeWithApiKeyRotation, t as parseGeminiAuth } from "./gemini-auth-CrwifqcZ.js";
9
9
  import { n as fetchWithTimeout } from "./fetch-timeout-BheTNyes.js";
10
10
  import { i as fetchRemoteMedia, n as getDefaultMediaLocalRoots, o as fetchWithSsrFGuard, r as MediaFetchError } from "./local-roots-CC8jiKDk.js";
@@ -8,13 +8,13 @@ import { c as resolveIdentityNamePrefix, l as resolveMessagePrefix, t as createR
8
8
  import "./github-copilot-token-BbsJ0Qbo.js";
9
9
  import { r as formatCliCommand } from "./env-CQ_DQOwT.js";
10
10
  import "./tokens-Cn6drXx2.js";
11
- import { C as shouldComputeCommandAuthorized, S as hasControlCommand, T as normalizeMentionText, _ as enqueueSystemEvent, a as resolveMentionGating, b as formatInboundEnvelope, c as recordPendingHistoryEntryIfEnabled, f as createDedupeCache, g as formatDurationPrecise, h as parseActivationCommand, i as buildPairingReply, l as shouldAckReactionForWhatsApp, m as normalizeGroupActivation, n as computeBackoff, o as DEFAULT_GROUP_HISTORY_LIMIT, p as getReplyFromConfig, r as sleepWithAbort, s as buildHistoryContextFromEntries, u as dispatchReplyWithBufferedBlockDispatcher, v as createInboundDebouncer, w as buildMentionRegexes, x as resolveEnvelopeFormatOptions, y as resolveInboundDebounceMs } from "./pi-embedded-02ObvVIR.js";
11
+ import { C as shouldComputeCommandAuthorized, S as hasControlCommand, T as normalizeMentionText, _ as enqueueSystemEvent, a as resolveMentionGating, b as formatInboundEnvelope, c as recordPendingHistoryEntryIfEnabled, f as createDedupeCache, g as formatDurationPrecise, h as parseActivationCommand, i as buildPairingReply, l as shouldAckReactionForWhatsApp, m as normalizeGroupActivation, n as computeBackoff, o as DEFAULT_GROUP_HISTORY_LIMIT, p as getReplyFromConfig, r as sleepWithAbort, s as buildHistoryContextFromEntries, u as dispatchReplyWithBufferedBlockDispatcher, v as createInboundDebouncer, w as buildMentionRegexes, x as resolveEnvelopeFormatOptions, y as resolveInboundDebounceMs } from "./pi-embedded-DguKAKpR.js";
12
12
  import "./plugins-71oIavrF.js";
13
13
  import { i as logWebSelfId, l as readWebSelfId, n as WA_WEB_AUTH_DIR, p as webAuthExists, r as getWebAuthAgeMs, s as pickWebChannel, t as resolveWhatsAppAccount } from "./accounts-DDEyGwby.js";
14
14
  import "./bindings-DYVakimr.js";
15
15
  import "./send-BPW99hCM.js";
16
16
  import "./send-DFVqIDB9.js";
17
- import "./deliver-EKA6SdgU.js";
17
+ import "./deliver-vWWI-94q.js";
18
18
  import "./diagnostic-D0xmLpej.js";
19
19
  import "./diagnostic-session-state-C1vRJs5w.js";
20
20
  import "./accounts-8zZqL37v.js";
@@ -22,10 +22,10 @@ import { G as formatLocationText, J as readChannelAllowFromStore, K as toLocatio
22
22
  import "./image-ops-ByaQt43P.js";
23
23
  import "./pi-model-discovery-j5tVLINv.js";
24
24
  import "./message-channel-BQINJQIT.js";
25
- import { Ct as resolveGroupSessionKey, H as loadSessionStore, K as updateLastRoute, U as readSessionUpdatedAt, W as recordSessionMetaFromInbound } from "./pi-embedded-helpers-B6ugLqkI.js";
25
+ import { Ct as resolveGroupSessionKey, H as loadSessionStore, K as updateLastRoute, U as readSessionUpdatedAt, W as recordSessionMetaFromInbound } from "./pi-embedded-helpers-SPJVuQfB.js";
26
26
  import { n as loadConfig } from "./config-diuFc3fL.js";
27
27
  import "./manifest-registry-D-mTF1cj.js";
28
- import "./chrome-DPHgzMPu.js";
28
+ import "./chrome-CqribT6Z.js";
29
29
  import "./skills-BNpGMnp-.js";
30
30
  import "./redact-1NGYV_8p.js";
31
31
  import "./errors-CPfngF0S.js";
@@ -35,7 +35,7 @@ import { h as resolveChannelGroupRequireMention, m as resolveChannelGroupPolicy
35
35
  import "./accounts-DImOt9jX.js";
36
36
  import { s as resolveStorePath } from "./paths-DkMamAQ-.js";
37
37
  import "./tool-images-ChC2CXaN.js";
38
- import "./image-EKTeO3aa.js";
38
+ import "./image-CV4FUL4M.js";
39
39
  import "./manager-CL7MzOkQ.js";
40
40
  import "./gemini-auth-CrwifqcZ.js";
41
41
  import "./sqlite-BNh23mUR.js";
@@ -49,7 +49,7 @@ import "./render-B1VqYyvo.js";
49
49
  import "./commands-registry-B_XO7lUV.js";
50
50
  import "./skill-commands-sj8KNio8.js";
51
51
  import { t as finalizeInboundContext } from "./inbound-context-QOi5vzUt.js";
52
- import { p as registerUnhandledRejectionHandler } from "./runner-BlTur7kC.js";
52
+ import { p as registerUnhandledRejectionHandler } from "./runner-Cx1wJumq.js";
53
53
  import "./fetch-DtLn7YU3.js";
54
54
  import { n as recordChannelActivity } from "./channel-activity-D9q-fIPB.js";
55
55
  import { t as convertMarkdownTables } from "./tables-COnZ169v.js";
@@ -1,6 +1,11 @@
1
1
  import { buildOauthProviderAuthResult, emptyPluginConfigSchema } from "symi/plugin-sdk";
2
2
  import type { AnyAgentTool, SymiPluginApi, ProviderAuthContext } from "../../src/plugins/types.js";
3
- import { loginOutlook } from "./src/auth.js";
3
+ import {
4
+ loginOutlook,
5
+ requestDeviceCode,
6
+ pollForDeviceCodeToken,
7
+ fetchUserProfile,
8
+ } from "./src/auth.js";
4
9
  import { saveCredentials, loadCredentials, deleteCredentials } from "./src/store.js";
5
10
  import {
6
11
  createOutlookListTool,
@@ -108,21 +113,30 @@ const outlookPlugin = {
108
113
  .description("Sign in with your Microsoft account")
109
114
  .action(async () => {
110
115
  const { loginOutlook: login } = await import("./src/auth.js");
111
- const open = (await import("node:child_process")).execSync;
116
+
117
+ const isHeadless =
118
+ process.platform === "linux" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY;
112
119
 
113
120
  const result = await login({
114
- isRemote: false,
121
+ isRemote: isHeadless,
115
122
  openUrl: async (url) => {
123
+ if (isHeadless) {
124
+ console.log("\nOpen this URL in your browser:\n");
125
+ console.log(url);
126
+ console.log("");
127
+ return;
128
+ }
129
+ const { execSync } = await import("node:child_process");
116
130
  const cmd =
117
131
  process.platform === "darwin"
118
132
  ? `open "${url}"`
119
133
  : process.platform === "win32"
120
134
  ? `start "" "${url}"`
121
- : `xdg-open "${url}" 2>/dev/null || echo "Open this URL: ${url}"`;
135
+ : `xdg-open "${url}" 2>/dev/null`;
122
136
  try {
123
- open(cmd, { stdio: "ignore" });
137
+ execSync(cmd, { stdio: "ignore" });
124
138
  } catch {
125
- console.log(`Open this URL in your browser:\n${url}`);
139
+ console.log(`\nOpen this URL in your browser:\n${url}\n`);
126
140
  }
127
141
  },
128
142
  prompt: async (message) => {
@@ -193,6 +207,105 @@ const outlookPlugin = {
193
207
  },
194
208
  { commands: ["outlook"] },
195
209
  );
210
+
211
+ // -------------------------------------------------------------------------
212
+ // Chat commands — /outlook login, /outlook logout, /outlook status
213
+ // Accessible from Telegram, Discord, WhatsApp, etc.
214
+ // -------------------------------------------------------------------------
215
+ api.registerCommand({
216
+ name: "outlook",
217
+ description: "Outlook 365 email — login, logout, status",
218
+ acceptsArgs: true,
219
+ handler: async (ctx) => {
220
+ const subcommand = ctx.args?.trim().split(/\s+/)[0]?.toLowerCase() ?? "";
221
+
222
+ if (subcommand === "login") {
223
+ const creds = loadCredentials();
224
+ if (creds && Date.now() < creds.expires) {
225
+ return {
226
+ text: `Already connected as ${creds.email ?? "unknown"}. Use /outlook logout to disconnect first.`,
227
+ };
228
+ }
229
+
230
+ try {
231
+ const deviceCode = await requestDeviceCode();
232
+
233
+ // Start polling in the background
234
+ const pollPromise = pollForDeviceCodeToken({
235
+ deviceCode: deviceCode.device_code,
236
+ intervalMs: (deviceCode.interval ?? 5) * 1000,
237
+ expiresInMs: (deviceCode.expires_in ?? 900) * 1000,
238
+ });
239
+
240
+ // Don't await — let it poll while user signs in
241
+ pollPromise
242
+ .then(async (tokens) => {
243
+ const profile = await fetchUserProfile(tokens.access);
244
+ saveCredentials({
245
+ access: tokens.access,
246
+ refresh: tokens.refresh,
247
+ expires: tokens.expires,
248
+ email: profile.email,
249
+ displayName: profile.displayName,
250
+ });
251
+ // The completion message will be picked up by the next interaction
252
+ api.logger.info(
253
+ `Outlook connected as ${profile.displayName ?? profile.email ?? "unknown"}`,
254
+ );
255
+ })
256
+ .catch((err) => {
257
+ api.logger.error(`Outlook login failed: ${String(err)}`);
258
+ });
259
+
260
+ return {
261
+ text: [
262
+ "Sign in to your Microsoft account:",
263
+ "",
264
+ `1. Go to: ${deviceCode.verification_uri}`,
265
+ `2. Enter code: **${deviceCode.user_code}**`,
266
+ "",
267
+ `Code expires in ${Math.floor(deviceCode.expires_in / 60)} minutes.`,
268
+ "I'll confirm once you've signed in.",
269
+ ].join("\n"),
270
+ };
271
+ } catch (err) {
272
+ return {
273
+ text: `Outlook login failed: ${err instanceof Error ? err.message : String(err)}`,
274
+ };
275
+ }
276
+ }
277
+
278
+ if (subcommand === "logout") {
279
+ const removed = deleteCredentials();
280
+ return { text: removed ? "Outlook disconnected." : "Outlook was not connected." };
281
+ }
282
+
283
+ if (subcommand === "status") {
284
+ const creds = loadCredentials();
285
+ if (!creds) {
286
+ return { text: "Outlook not connected. Send /outlook login to sign in." };
287
+ }
288
+ const expired = Date.now() >= creds.expires;
289
+ return {
290
+ text: [
291
+ `Account: ${creds.email ?? "unknown"}`,
292
+ `Name: ${creds.displayName ?? "unknown"}`,
293
+ `Token: ${expired ? "expired (will auto-refresh)" : "valid"}`,
294
+ ].join("\n"),
295
+ };
296
+ }
297
+
298
+ return {
299
+ text: [
300
+ "Outlook 365 commands:",
301
+ "",
302
+ "/outlook login — Sign in with Microsoft",
303
+ "/outlook logout — Disconnect",
304
+ "/outlook status — Show connection info",
305
+ ].join("\n"),
306
+ };
307
+ },
308
+ });
196
309
  },
197
310
  };
198
311
 
@@ -52,7 +52,14 @@ export function generatePkce(): { verifier: string; challenge: string } {
52
52
  }
53
53
 
54
54
  export function shouldUseManualOAuthFlow(isRemote: boolean): boolean {
55
- return isRemote || isWSL2Sync();
55
+ if (isRemote || isWSL2Sync()) {
56
+ return true;
57
+ }
58
+ // Headless Linux (no display server) — can't open a browser
59
+ if (process.platform === "linux" && !process.env.DISPLAY && !process.env.WAYLAND_DISPLAY) {
60
+ return true;
61
+ }
62
+ return false;
56
63
  }
57
64
 
58
65
  export function buildAuthUrl(params: { challenge: string; state: string }): string {
@@ -247,6 +254,97 @@ export async function refreshAccessToken(refreshToken: string): Promise<{
247
254
  return { access, refresh, expires };
248
255
  }
249
256
 
257
+ // =========================================================================
258
+ // Device Code Flow — for chat-based login (no browser on this device)
259
+ // =========================================================================
260
+
261
+ const DEVICE_CODE_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode";
262
+
263
+ export type DeviceCodeResponse = {
264
+ device_code: string;
265
+ user_code: string;
266
+ verification_uri: string;
267
+ expires_in: number;
268
+ interval: number;
269
+ };
270
+
271
+ export async function requestDeviceCode(): Promise<DeviceCodeResponse> {
272
+ const clientId = resolveClientId();
273
+ const response = await fetch(DEVICE_CODE_URL, {
274
+ method: "POST",
275
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
276
+ body: new URLSearchParams({
277
+ client_id: clientId,
278
+ scope: SCOPES.join(" "),
279
+ }),
280
+ });
281
+
282
+ if (!response.ok) {
283
+ const text = await response.text();
284
+ throw new Error(`Device code request failed: ${text}`);
285
+ }
286
+
287
+ return (await response.json()) as DeviceCodeResponse;
288
+ }
289
+
290
+ export async function pollForDeviceCodeToken(params: {
291
+ deviceCode: string;
292
+ intervalMs: number;
293
+ expiresInMs: number;
294
+ }): Promise<{ access: string; refresh: string; expires: number }> {
295
+ const clientId = resolveClientId();
296
+ const deadline = Date.now() + params.expiresInMs;
297
+
298
+ while (Date.now() < deadline) {
299
+ await new Promise((resolve) => setTimeout(resolve, params.intervalMs));
300
+
301
+ const response = await fetch(TOKEN_URL, {
302
+ method: "POST",
303
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
304
+ body: new URLSearchParams({
305
+ client_id: clientId,
306
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code",
307
+ device_code: params.deviceCode,
308
+ }),
309
+ });
310
+
311
+ const data = (await response.json()) as {
312
+ access_token?: string;
313
+ refresh_token?: string;
314
+ expires_in?: number;
315
+ error?: string;
316
+ };
317
+
318
+ if (data.error === "authorization_pending") {
319
+ continue;
320
+ }
321
+ if (data.error === "slow_down") {
322
+ // Back off by adding 5 seconds
323
+ params.intervalMs += 5000;
324
+ continue;
325
+ }
326
+ if (data.error) {
327
+ throw new Error(`Device code auth failed: ${data.error}`);
328
+ }
329
+
330
+ const access = data.access_token?.trim();
331
+ const refresh = data.refresh_token?.trim();
332
+ const expiresIn = data.expires_in ?? 0;
333
+
334
+ if (!access) {
335
+ throw new Error("Token exchange returned no access_token");
336
+ }
337
+ if (!refresh) {
338
+ throw new Error("Token exchange returned no refresh_token");
339
+ }
340
+
341
+ const expires = Date.now() + expiresIn * 1000 - 5 * 60 * 1000;
342
+ return { access, refresh, expires };
343
+ }
344
+
345
+ throw new Error("Device code expired. Please try again.");
346
+ }
347
+
250
348
  export async function fetchUserProfile(accessToken: string): Promise<{
251
349
  email?: string;
252
350
  displayName?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@symerian/symi",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "description": "Multi-channel AI gateway with extensible messaging integrations",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/jaysteelmind/symi#readme",