@symerian/symi 3.5.16 → 3.5.17
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.
- package/dist/build-info.json +3 -3
- package/dist/bundled/boot-md/handler.js +4 -4
- package/dist/bundled/session-memory/handler.js +4 -4
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/{chrome-OTJg3QKn.js → chrome-CmQwGAuL.js} +7 -7
- package/dist/{command-registry-2hfSOaGL.js → command-registry-Bmzf59Qv.js} +4 -4
- package/dist/{completion-cli-TYU7Y_XZ.js → completion-cli-BM4kZs0m.js} +2 -2
- package/dist/{completion-cli-BEO2AB41.js → completion-cli-CtUZzw-P.js} +1 -1
- package/dist/control-ui/css/style.css +166 -0
- package/dist/control-ui/js/symframe.js +246 -20
- package/dist/{deliver-BiWlR84Y.js → deliver-B04yNX82.js} +4 -4
- package/dist/{doctor-completion-CvaSyxyp.js → doctor-completion-Df7Hv_IA.js} +1 -1
- package/dist/{doctor-completion-DgNgQFQQ.js → doctor-completion-Do20Q4ZM.js} +1 -1
- package/dist/entry.js +1 -1
- package/dist/{gateway-cli-DCTPCoQx.js → gateway-cli-CKlpsjYJ.js} +1 -1
- package/dist/{gateway-cli-BNhURE6O.js → gateway-cli-CwuURJSh.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/llm-slug-generator.js +4 -4
- package/dist/{manager-DjhE8yLr.js → manager-B-wPs7cb.js} +1 -1
- package/dist/{onboard-DRn6pFfO.js → onboard-3FdfkbGm.js} +1 -1
- package/dist/{onboard-fBxK2Bky.js → onboard-DFbgAa-t.js} +1 -1
- package/dist/{onboarding-CLOZkMhc.js → onboarding-BigIUHoh.js} +1 -1
- package/dist/{onboarding-i1rA1XGe.js → onboarding-fq_-89Jc.js} +1 -1
- package/dist/{onboarding.finalize-BV76YUaD.js → onboarding.finalize-BGDBP9G7.js} +4 -4
- package/dist/{onboarding.finalize-gk9ot6lb.js → onboarding.finalize-C2Dt95Rn.js} +3 -3
- package/dist/plugin-sdk/index.js +6 -6
- package/dist/{program-Qug3oi2C.js → program-FBDhJLrg.js} +2 -2
- package/dist/{program-context-CCIGjsQL.js → program-context-CZYb4zB2.js} +7 -7
- package/dist/{prompt-select-styled-ARnCLf3Q.js → prompt-select-styled-C3LUG3Be.js} +1 -1
- package/dist/{prompt-select-styled-BdNTADj2.js → prompt-select-styled-DQyZ6VHH.js} +1 -1
- package/dist/{pw-ai-DY_6l11g.js → pw-ai-DLsdzdgc.js} +1 -1
- package/dist/{register.maintenance-CTF70v5h.js → register.maintenance-81d4KKmA.js} +5 -5
- package/dist/{register.maintenance-BncnnneX.js → register.maintenance-FWHasNw7.js} +4 -4
- package/dist/{register.onboard-O0P6rCuX.js → register.onboard-BjPPudfS.js} +2 -2
- package/dist/{register.onboard-DhcpKFgU.js → register.onboard-COyX1xSR.js} +2 -2
- package/dist/{register.setup-CZfWa9-Z.js → register.setup-C_ds_5fl.js} +2 -2
- package/dist/{register.setup-D3XQyELS.js → register.setup-DDMtRxcF.js} +2 -2
- package/dist/{register.subclis-Dv8bf2ox.js → register.subclis-B16w8wxz.js} +4 -4
- package/dist/{run-main-BsVhPYM4.js → run-main-CUMiBvgm.js} +3 -3
- package/dist/{symframe-cli-CsA_x7U9.js → symframe-cli-DLbhzXNU.js} +16 -2
- package/dist/{symframe-cli-BKrtoG8H.js → symframe-cli-OqTUw6Mt.js} +16 -2
- package/dist/{synthesis-Dv6bJWYX.js → synthesis-CG0rRaLA.js} +4 -4
- package/dist/{unified-runner-ByJSAveb.js → unified-runner-ChkYfsxy.js} +10 -10
- package/dist/{update-cli-y4Q__h4E.js → update-cli-BhI88CVk.js} +5 -5
- package/dist/{update-cli-CrP5Kvo4.js → update-cli-jxM3sFLP.js} +4 -4
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -4,16 +4,16 @@ import { E as shouldLogVerbose, G as isRecord, r as DEFAULT_CHAT_CHANNEL, v as i
|
|
|
4
4
|
import { a as resolveAgentSkillsFilter, c as resolveEffectiveModelFallbacks, i as resolveAgentModelPrimary, l as resolveSessionAgentId, o as resolveAgentWorkspaceDir, r as resolveAgentDir, t as listAgentIds, u as resolveSessionAgentIds } from "../../agent-scope-B1Ina6jV.js";
|
|
5
5
|
import { r as defaultRuntime, t as createSubsystemLogger } from "../../subsystem-DzRUKS9f.js";
|
|
6
6
|
import { l as ensureAgentWorkspace } from "../../workspace-CsaDUuDn.js";
|
|
7
|
-
import { A as runWithModelFallback, C as resolveSymiDocsPath, D as resolveRunWorkspaceDir, E as redactRunIdentifier, M as resolveFailoverStatus, O as deriveSessionTotalTokens, S as buildAgentSystemPrompt, T as resolveBootstrapContextForRun, _ as AGENT_LANE_NESTED, a as resolveSessionDeliveryTarget, b as emitAgentEvent, c as detectRuntimeShell, d as applyModelOverrideToSessionEntry, f as applyVerboseOverride, g as resolveAgentTimeoutMs, i as resolveOutboundTarget, j as FailoverError, k as hasNonzeroUsage, l as resolveSendPolicy, m as clearSessionAuthProfileOverride, n as buildModelAliasLines, o as buildSystemPromptParams, p as loadModelCatalog, s as getProcessSupervisor, t as runAgentTurn, u as lookupContextTokens, v as AGENT_LANE_SUBAGENT, w as makeBootstrapWarn, x as registerAgentRunContext, y as clearAgentRunContext } from "../../unified-runner-
|
|
7
|
+
import { A as runWithModelFallback, C as resolveSymiDocsPath, D as resolveRunWorkspaceDir, E as redactRunIdentifier, M as resolveFailoverStatus, O as deriveSessionTotalTokens, S as buildAgentSystemPrompt, T as resolveBootstrapContextForRun, _ as AGENT_LANE_NESTED, a as resolveSessionDeliveryTarget, b as emitAgentEvent, c as detectRuntimeShell, d as applyModelOverrideToSessionEntry, f as applyVerboseOverride, g as resolveAgentTimeoutMs, i as resolveOutboundTarget, j as FailoverError, k as hasNonzeroUsage, l as resolveSendPolicy, m as clearSessionAuthProfileOverride, n as buildModelAliasLines, o as buildSystemPromptParams, p as loadModelCatalog, s as getProcessSupervisor, t as runAgentTurn, u as lookupContextTokens, v as AGENT_LANE_SUBAGENT, w as makeBootstrapWarn, x as registerAgentRunContext, y as clearAgentRunContext } from "../../unified-runner-ChkYfsxy.js";
|
|
8
8
|
import { d as ensureAuthProfileStore } from "../../auth-profiles-BSw0aQND.js";
|
|
9
9
|
import { t as formatCliCommand } from "../../command-format-BrrHNE8r.js";
|
|
10
10
|
import { _ as DEFAULT_MODEL, a as isCliProvider, c as normalizeProviderId, d as resolveDefaultModelForAgent, g as DEFAULT_CONTEXT_TOKENS, m as resolveThinkingDefault, o as modelKey, s as normalizeModelRef, t as buildAllowedModelSet, u as resolveConfiguredModelRef, v as DEFAULT_PROVIDER } from "../../model-selection-BqshlIZc.js";
|
|
11
|
-
import { At as resolveSessionResetPolicy, Dt as resolveSessionKey, It as resolveAgentMainSessionKey, Lt as resolveExplicitAgentSessionKey, M as classifyFailoverReason, Ot as evaluateSessionFreshness, Rt as resolveMainSessionKey, U as isFailoverErrorMessage, a as normalizeOutboundPayloadsForJson, at as loadSessionStore, i as normalizeOutboundPayloads, it as resolveAndPersistSessionFile, jt as resolveSessionResetType, kt as resolveChannelResetConfig, lt as updateSessionStore, nt as parseSessionThreadInfo, r as formatOutboundPayloadLog, t as deliverOutboundPayloads, vt as normalizeAccountId } from "../../deliver-
|
|
11
|
+
import { At as resolveSessionResetPolicy, Dt as resolveSessionKey, It as resolveAgentMainSessionKey, Lt as resolveExplicitAgentSessionKey, M as classifyFailoverReason, Ot as evaluateSessionFreshness, Rt as resolveMainSessionKey, U as isFailoverErrorMessage, a as normalizeOutboundPayloadsForJson, at as loadSessionStore, i as normalizeOutboundPayloads, it as resolveAndPersistSessionFile, jt as resolveSessionResetType, kt as resolveChannelResetConfig, lt as updateSessionStore, nt as parseSessionThreadInfo, r as formatOutboundPayloadLog, t as deliverOutboundPayloads, vt as normalizeAccountId } from "../../deliver-B04yNX82.js";
|
|
12
12
|
import { c as loadConfig } from "../../ssrf-DNhyFMRW.js";
|
|
13
13
|
import "../../boolean-BsqeuxE6.js";
|
|
14
14
|
import { s as isTruthyEnvValue } from "../../shell-env-B1lDWz4t.js";
|
|
15
15
|
import "../../manifest-registry-BGJu2aC-.js";
|
|
16
|
-
import "../../chrome-
|
|
16
|
+
import "../../chrome-CmQwGAuL.js";
|
|
17
17
|
import "../../frontmatter-CJEX1BrH.js";
|
|
18
18
|
import { n as buildWorkspaceSkillSnapshot } from "../../skills-Dm4gX4Tl.js";
|
|
19
19
|
import "../../redact-CSGZUFxa.js";
|
|
@@ -27,7 +27,7 @@ import { i as resolveSessionTranscriptPath, n as resolveSessionFilePath, s as re
|
|
|
27
27
|
import { t as SILENT_REPLY_TOKEN } from "../../tokens-D_vCJSzF.js";
|
|
28
28
|
import "../../diagnostic-BALvP9wI.js";
|
|
29
29
|
import "../../diagnostic-session-state-BDfanaOY.js";
|
|
30
|
-
import "../../manager-
|
|
30
|
+
import "../../manager-B-wPs7cb.js";
|
|
31
31
|
import "../../github-copilot-token-uhEBNQfj.js";
|
|
32
32
|
import "../../pi-auth-json-DCGR3yfh.js";
|
|
33
33
|
import "../../reply-prefix-D0NzzC4I.js";
|
|
@@ -4,15 +4,15 @@ import "../../registry-C-JddWwo.js";
|
|
|
4
4
|
import { o as resolveAgentWorkspaceDir } from "../../agent-scope-B1Ina6jV.js";
|
|
5
5
|
import { t as createSubsystemLogger } from "../../subsystem-DzRUKS9f.js";
|
|
6
6
|
import "../../workspace-CsaDUuDn.js";
|
|
7
|
-
import "../../unified-runner-
|
|
7
|
+
import "../../unified-runner-ChkYfsxy.js";
|
|
8
8
|
import "../../auth-profiles-BSw0aQND.js";
|
|
9
9
|
import "../../model-selection-BqshlIZc.js";
|
|
10
|
-
import { Tt as hasInterSessionUserProvenance } from "../../deliver-
|
|
10
|
+
import { Tt as hasInterSessionUserProvenance } from "../../deliver-B04yNX82.js";
|
|
11
11
|
import "../../ssrf-DNhyFMRW.js";
|
|
12
12
|
import "../../boolean-BsqeuxE6.js";
|
|
13
13
|
import "../../shell-env-B1lDWz4t.js";
|
|
14
14
|
import "../../manifest-registry-BGJu2aC-.js";
|
|
15
|
-
import "../../chrome-
|
|
15
|
+
import "../../chrome-CmQwGAuL.js";
|
|
16
16
|
import "../../frontmatter-CJEX1BrH.js";
|
|
17
17
|
import "../../skills-Dm4gX4Tl.js";
|
|
18
18
|
import "../../redact-CSGZUFxa.js";
|
|
@@ -26,7 +26,7 @@ import "../../paths-BsT3BvfH.js";
|
|
|
26
26
|
import "../../tokens-D_vCJSzF.js";
|
|
27
27
|
import "../../diagnostic-BALvP9wI.js";
|
|
28
28
|
import "../../diagnostic-session-state-BDfanaOY.js";
|
|
29
|
-
import "../../manager-
|
|
29
|
+
import "../../manager-B-wPs7cb.js";
|
|
30
30
|
import "../../github-copilot-token-uhEBNQfj.js";
|
|
31
31
|
import "../../pi-auth-json-DCGR3yfh.js";
|
|
32
32
|
import "../../reply-prefix-D0NzzC4I.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c9d3271c9b49843128f1170d40c1f7e0a23bd45b3480f9a6f294ffd294c04151
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1639
|
+
const ws = new WebSocket(wsUrl, {
|
|
1640
1640
|
handshakeTimeout: timeoutMs,
|
|
1641
1641
|
...Object.keys(headers).length ? { headers } : {}
|
|
1642
1642
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
|
|
2
2
|
import { Qt as getPrimaryCommand, tn as hasHelpOrVersion } from "./entry.js";
|
|
3
|
-
import { i as registerSubCliCommands, o as reparseProgramFromActionArgs } from "./register.subclis-
|
|
3
|
+
import { i as registerSubCliCommands, o as reparseProgramFromActionArgs } from "./register.subclis-B16w8wxz.js";
|
|
4
4
|
|
|
5
5
|
//#region src/cli/program/command-registry.ts
|
|
6
6
|
var command_registry_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -22,7 +22,7 @@ const coreEntries = [
|
|
|
22
22
|
hasSubcommands: false
|
|
23
23
|
}],
|
|
24
24
|
register: async ({ program }) => {
|
|
25
|
-
(await import("./register.setup-
|
|
25
|
+
(await import("./register.setup-DDMtRxcF.js")).registerSetupCommand(program);
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
{
|
|
@@ -32,7 +32,7 @@ const coreEntries = [
|
|
|
32
32
|
hasSubcommands: false
|
|
33
33
|
}],
|
|
34
34
|
register: async ({ program }) => {
|
|
35
|
-
(await import("./register.onboard-
|
|
35
|
+
(await import("./register.onboard-BjPPudfS.js")).registerOnboardCommand(program);
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
{
|
|
@@ -79,7 +79,7 @@ const coreEntries = [
|
|
|
79
79
|
}
|
|
80
80
|
],
|
|
81
81
|
register: async ({ program }) => {
|
|
82
|
-
(await import("./register.maintenance-
|
|
82
|
+
(await import("./register.maintenance-81d4KKmA.js")).registerMaintenanceCommands(program);
|
|
83
83
|
}
|
|
84
84
|
},
|
|
85
85
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
|
|
2
2
|
import { Mt as pathExists, l as routeLogsToStderr, yt as resolveStateDir } from "./entry.js";
|
|
3
|
-
import { n as getSubCliEntries, r as registerSubCliByName } from "./register.subclis-
|
|
4
|
-
import { i as registerCoreCliByName, n as getCoreCliCommandNames } from "./command-registry-
|
|
3
|
+
import { n as getSubCliEntries, r as registerSubCliByName } from "./register.subclis-B16w8wxz.js";
|
|
4
|
+
import { i as registerCoreCliByName, n as getCoreCliCommandNames } from "./command-registry-Bmzf59Qv.js";
|
|
5
5
|
import { t as getProgramContext } from "./program-context-CGKRxOBU.js";
|
|
6
6
|
import os from "node:os";
|
|
7
7
|
import path from "node:path";
|
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
|
|
|
2
2
|
import { _ as resolveStateDir } from "./paths-By0XjHBk.js";
|
|
3
3
|
import { f as pathExists } from "./utils-CTPsqyE_.js";
|
|
4
4
|
import { i as routeLogsToStderr } from "./subsystem-CHbO_DkH.js";
|
|
5
|
-
import { a as registerCoreCliByName, c as getSubCliEntries, l as registerSubCliByName, r as getCoreCliCommandNames, t as getProgramContext } from "./program-context-
|
|
5
|
+
import { a as registerCoreCliByName, c as getSubCliEntries, l as registerSubCliByName, r as getCoreCliCommandNames, t as getProgramContext } from "./program-context-CZYb4zB2.js";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import os from "node:os";
|
|
8
8
|
import fs from "node:fs/promises";
|
|
@@ -987,6 +987,172 @@ body {
|
|
|
987
987
|
box-shadow: 0 0 8px rgba(0, 212, 255, 0.18);
|
|
988
988
|
}
|
|
989
989
|
|
|
990
|
+
/* ── Phase 4: type-specific body renderers ───────────────────────── */
|
|
991
|
+
|
|
992
|
+
/* Text + markdown: inherit from .symframe-card-body. Add minimal
|
|
993
|
+
markdown rules — most users will want headings and code blocks
|
|
994
|
+
readable but compact. */
|
|
995
|
+
.symframe-body-markdown h1,
|
|
996
|
+
.symframe-body-markdown h2,
|
|
997
|
+
.symframe-body-markdown h3,
|
|
998
|
+
.symframe-body-markdown h4 {
|
|
999
|
+
font-size: 12px;
|
|
1000
|
+
font-weight: 600;
|
|
1001
|
+
margin: 8px 0 4px;
|
|
1002
|
+
color: var(--text);
|
|
1003
|
+
}
|
|
1004
|
+
.symframe-body-markdown p {
|
|
1005
|
+
margin: 4px 0;
|
|
1006
|
+
}
|
|
1007
|
+
.symframe-body-markdown ul,
|
|
1008
|
+
.symframe-body-markdown ol {
|
|
1009
|
+
padding-left: 18px;
|
|
1010
|
+
margin: 4px 0;
|
|
1011
|
+
}
|
|
1012
|
+
.symframe-body-markdown code {
|
|
1013
|
+
font-family: var(--font-mono);
|
|
1014
|
+
font-size: 10px;
|
|
1015
|
+
padding: 1px 4px;
|
|
1016
|
+
background: rgba(255, 255, 255, 0.04);
|
|
1017
|
+
border-radius: 3px;
|
|
1018
|
+
}
|
|
1019
|
+
.symframe-body-markdown pre {
|
|
1020
|
+
background: rgba(0, 0, 0, 0.25);
|
|
1021
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
1022
|
+
border-radius: 5px;
|
|
1023
|
+
padding: 8px;
|
|
1024
|
+
overflow-x: auto;
|
|
1025
|
+
margin: 6px 0;
|
|
1026
|
+
}
|
|
1027
|
+
.symframe-body-markdown pre code {
|
|
1028
|
+
background: transparent;
|
|
1029
|
+
padding: 0;
|
|
1030
|
+
font-size: 10px;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
/* Code body — pre/code wrapper with hljs theme-friendly chrome. */
|
|
1034
|
+
.symframe-body-code {
|
|
1035
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1036
|
+
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
1037
|
+
border-radius: 5px;
|
|
1038
|
+
padding: 8px 10px;
|
|
1039
|
+
margin: 0;
|
|
1040
|
+
overflow-x: auto;
|
|
1041
|
+
max-height: 320px;
|
|
1042
|
+
overflow-y: auto;
|
|
1043
|
+
}
|
|
1044
|
+
.symframe-body-code code {
|
|
1045
|
+
font-family: var(--font-mono);
|
|
1046
|
+
font-size: 10px;
|
|
1047
|
+
line-height: 1.45;
|
|
1048
|
+
color: var(--text);
|
|
1049
|
+
background: transparent;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/* Email-draft — From/To/Subject header rows + body. */
|
|
1053
|
+
.symframe-body-email {
|
|
1054
|
+
display: flex;
|
|
1055
|
+
flex-direction: column;
|
|
1056
|
+
gap: 4px;
|
|
1057
|
+
}
|
|
1058
|
+
.symframe-email-row {
|
|
1059
|
+
display: flex;
|
|
1060
|
+
gap: 6px;
|
|
1061
|
+
font-family: var(--font-mono);
|
|
1062
|
+
font-size: 10px;
|
|
1063
|
+
letter-spacing: 0.02em;
|
|
1064
|
+
padding: 2px 0;
|
|
1065
|
+
border-bottom: 1px dashed rgba(255, 255, 255, 0.05);
|
|
1066
|
+
}
|
|
1067
|
+
.symframe-email-row:last-of-type {
|
|
1068
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
1069
|
+
margin-bottom: 4px;
|
|
1070
|
+
padding-bottom: 4px;
|
|
1071
|
+
}
|
|
1072
|
+
.symframe-email-label {
|
|
1073
|
+
flex: 0 0 auto;
|
|
1074
|
+
color: var(--text-dim);
|
|
1075
|
+
text-transform: uppercase;
|
|
1076
|
+
letter-spacing: 0.06em;
|
|
1077
|
+
font-size: 9px;
|
|
1078
|
+
min-width: 48px;
|
|
1079
|
+
opacity: 0.7;
|
|
1080
|
+
}
|
|
1081
|
+
.symframe-email-value {
|
|
1082
|
+
color: var(--text);
|
|
1083
|
+
word-break: break-word;
|
|
1084
|
+
}
|
|
1085
|
+
.symframe-email-body {
|
|
1086
|
+
font-family: var(--font-mono);
|
|
1087
|
+
font-size: 11px;
|
|
1088
|
+
line-height: 1.5;
|
|
1089
|
+
color: var(--text);
|
|
1090
|
+
white-space: pre-wrap;
|
|
1091
|
+
word-break: break-word;
|
|
1092
|
+
margin-top: 4px;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/* PDF embed */
|
|
1096
|
+
.symframe-body-pdf {
|
|
1097
|
+
display: flex;
|
|
1098
|
+
flex-direction: column;
|
|
1099
|
+
gap: 6px;
|
|
1100
|
+
}
|
|
1101
|
+
.symframe-pdf-iframe {
|
|
1102
|
+
width: 100%;
|
|
1103
|
+
height: 280px;
|
|
1104
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
1105
|
+
border-radius: 5px;
|
|
1106
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/* Audio + video shared chrome */
|
|
1110
|
+
.symframe-body-audio,
|
|
1111
|
+
.symframe-body-video {
|
|
1112
|
+
display: flex;
|
|
1113
|
+
flex-direction: column;
|
|
1114
|
+
gap: 6px;
|
|
1115
|
+
}
|
|
1116
|
+
.symframe-audio,
|
|
1117
|
+
.symframe-video {
|
|
1118
|
+
width: 100%;
|
|
1119
|
+
border-radius: 5px;
|
|
1120
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1121
|
+
}
|
|
1122
|
+
.symframe-video {
|
|
1123
|
+
max-height: 280px;
|
|
1124
|
+
object-fit: contain;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
/* Empty-media placeholder when url is missing */
|
|
1128
|
+
.symframe-body-empty {
|
|
1129
|
+
font-family: var(--font-mono);
|
|
1130
|
+
font-size: 10px;
|
|
1131
|
+
color: var(--text-dim);
|
|
1132
|
+
opacity: 0.6;
|
|
1133
|
+
font-style: italic;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/* Download link — used by pdf/audio/video renderers */
|
|
1137
|
+
.symframe-download {
|
|
1138
|
+
display: inline-block;
|
|
1139
|
+
padding: 4px 8px;
|
|
1140
|
+
border: 1px solid var(--glass-border);
|
|
1141
|
+
border-radius: 4px;
|
|
1142
|
+
font-family: var(--font-mono);
|
|
1143
|
+
font-size: 10px;
|
|
1144
|
+
letter-spacing: 0.04em;
|
|
1145
|
+
color: var(--text-dim);
|
|
1146
|
+
text-decoration: none;
|
|
1147
|
+
transition: all 0.15s ease;
|
|
1148
|
+
align-self: flex-start;
|
|
1149
|
+
}
|
|
1150
|
+
.symframe-download:hover {
|
|
1151
|
+
border-color: var(--accent-cyan);
|
|
1152
|
+
color: var(--accent-cyan);
|
|
1153
|
+
background: rgba(0, 212, 255, 0.06);
|
|
1154
|
+
}
|
|
1155
|
+
|
|
990
1156
|
/* ── Response Area ────────────────────────────────────────────────── */
|
|
991
1157
|
.response-area {
|
|
992
1158
|
position: fixed;
|
|
@@ -57,33 +57,261 @@
|
|
|
57
57
|
countEl.textContent = total === 1 ? "1 card" : `${total} cards`;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// Per-type renderers
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
// in
|
|
60
|
+
// ── Per-type body renderers ──
|
|
61
|
+
// Each renderer takes a card and returns an HTMLElement (or
|
|
62
|
+
// DocumentFragment) that gets appended to the body slot. New types
|
|
63
|
+
// plug in by adding to the renderers map below — no other code path
|
|
64
|
+
// changes required.
|
|
65
|
+
|
|
66
|
+
function renderTextBody(card) {
|
|
67
|
+
const div = document.createElement("div");
|
|
68
|
+
div.className = "symframe-body-text";
|
|
69
|
+
if (card.bodyHtml) {
|
|
70
|
+
div.innerHTML = card.bodyHtml;
|
|
71
|
+
} else {
|
|
72
|
+
div.textContent = card.body || "";
|
|
73
|
+
}
|
|
74
|
+
return div;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function renderMarkdownBody(card) {
|
|
78
|
+
const div = document.createElement("div");
|
|
79
|
+
div.className = "symframe-body-markdown";
|
|
80
|
+
if (typeof window.marked?.parse === "function") {
|
|
81
|
+
div.innerHTML = window.marked.parse(card.body || "");
|
|
82
|
+
} else {
|
|
83
|
+
div.textContent = card.body || "";
|
|
84
|
+
}
|
|
85
|
+
return div;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function renderCodeBody(card) {
|
|
89
|
+
const pre = document.createElement("pre");
|
|
90
|
+
pre.className = "symframe-body-code";
|
|
91
|
+
const code = document.createElement("code");
|
|
92
|
+
if (card.language) {
|
|
93
|
+
code.classList.add(`language-${card.language}`);
|
|
94
|
+
}
|
|
95
|
+
code.textContent = card.body || "";
|
|
96
|
+
pre.appendChild(code);
|
|
97
|
+
// hljs is bundled as window.hljs via vendor/highlight.min.js. Best-effort
|
|
98
|
+
// highlight; if hljs throws (unknown language, etc.) the plain pre/code
|
|
99
|
+
// already renders fine.
|
|
100
|
+
if (typeof window.hljs?.highlightElement === "function") {
|
|
101
|
+
try {
|
|
102
|
+
window.hljs.highlightElement(code);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
console.warn("[symframe] hljs.highlightElement failed:", err);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return pre;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function renderEmailDraftBody(card) {
|
|
111
|
+
const wrap = document.createElement("div");
|
|
112
|
+
wrap.className = "symframe-body-email";
|
|
113
|
+
const email = card.email || {};
|
|
114
|
+
const headerRows = [
|
|
115
|
+
["From", email.from],
|
|
116
|
+
["To", email.to],
|
|
117
|
+
["Cc", email.cc],
|
|
118
|
+
["Bcc", email.bcc],
|
|
119
|
+
["Subject", email.subject],
|
|
120
|
+
];
|
|
121
|
+
for (const [label, value] of headerRows) {
|
|
122
|
+
if (!value) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const row = document.createElement("div");
|
|
126
|
+
row.className = "symframe-email-row";
|
|
127
|
+
const lbl = document.createElement("span");
|
|
128
|
+
lbl.className = "symframe-email-label";
|
|
129
|
+
lbl.textContent = `${label}:`;
|
|
130
|
+
const val = document.createElement("span");
|
|
131
|
+
val.className = "symframe-email-value";
|
|
132
|
+
val.textContent = String(value);
|
|
133
|
+
row.appendChild(lbl);
|
|
134
|
+
row.appendChild(val);
|
|
135
|
+
wrap.appendChild(row);
|
|
136
|
+
}
|
|
137
|
+
if (email.body) {
|
|
138
|
+
const body = document.createElement("div");
|
|
139
|
+
body.className = "symframe-email-body";
|
|
140
|
+
body.textContent = email.body;
|
|
141
|
+
wrap.appendChild(body);
|
|
142
|
+
}
|
|
143
|
+
return wrap;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function renderEmptyMedia(reason) {
|
|
147
|
+
const div = document.createElement("div");
|
|
148
|
+
div.className = "symframe-body-empty";
|
|
149
|
+
div.textContent = reason;
|
|
150
|
+
return div;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function renderPdfBody(card) {
|
|
154
|
+
if (!card.url) {
|
|
155
|
+
return renderEmptyMedia("(no url provided)");
|
|
156
|
+
}
|
|
157
|
+
const wrap = document.createElement("div");
|
|
158
|
+
wrap.className = "symframe-body-pdf";
|
|
159
|
+
const frame = document.createElement("iframe");
|
|
160
|
+
frame.src = card.url;
|
|
161
|
+
frame.className = "symframe-pdf-iframe";
|
|
162
|
+
frame.setAttribute("title", card.title || "PDF document");
|
|
163
|
+
wrap.appendChild(frame);
|
|
164
|
+
wrap.appendChild(buildDownloadLink(card.url, card.downloadName, "Download PDF"));
|
|
165
|
+
return wrap;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function renderAudioBody(card) {
|
|
169
|
+
if (!card.url) {
|
|
170
|
+
return renderEmptyMedia("(no url provided)");
|
|
171
|
+
}
|
|
172
|
+
const wrap = document.createElement("div");
|
|
173
|
+
wrap.className = "symframe-body-audio";
|
|
174
|
+
const audio = document.createElement("audio");
|
|
175
|
+
audio.controls = true;
|
|
176
|
+
audio.preload = "metadata";
|
|
177
|
+
audio.className = "symframe-audio";
|
|
178
|
+
if (card.mimeType) {
|
|
179
|
+
const source = document.createElement("source");
|
|
180
|
+
source.src = card.url;
|
|
181
|
+
source.type = card.mimeType;
|
|
182
|
+
audio.appendChild(source);
|
|
183
|
+
} else {
|
|
184
|
+
audio.src = card.url;
|
|
185
|
+
}
|
|
186
|
+
wrap.appendChild(audio);
|
|
187
|
+
wrap.appendChild(buildDownloadLink(card.url, card.downloadName, "Download"));
|
|
188
|
+
return wrap;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function renderVideoBody(card) {
|
|
192
|
+
if (!card.url) {
|
|
193
|
+
return renderEmptyMedia("(no url provided)");
|
|
194
|
+
}
|
|
195
|
+
const wrap = document.createElement("div");
|
|
196
|
+
wrap.className = "symframe-body-video";
|
|
197
|
+
const video = document.createElement("video");
|
|
198
|
+
video.controls = true;
|
|
199
|
+
video.preload = "metadata";
|
|
200
|
+
video.className = "symframe-video";
|
|
201
|
+
video.playsInline = true;
|
|
202
|
+
if (card.poster) {
|
|
203
|
+
video.poster = card.poster;
|
|
204
|
+
}
|
|
205
|
+
if (card.mimeType) {
|
|
206
|
+
const source = document.createElement("source");
|
|
207
|
+
source.src = card.url;
|
|
208
|
+
source.type = card.mimeType;
|
|
209
|
+
video.appendChild(source);
|
|
210
|
+
} else {
|
|
211
|
+
video.src = card.url;
|
|
212
|
+
}
|
|
213
|
+
wrap.appendChild(video);
|
|
214
|
+
wrap.appendChild(buildDownloadLink(card.url, card.downloadName, "Download"));
|
|
215
|
+
return wrap;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function buildDownloadLink(url, downloadName, label) {
|
|
219
|
+
const a = document.createElement("a");
|
|
220
|
+
a.href = url;
|
|
221
|
+
if (downloadName) {
|
|
222
|
+
a.download = downloadName;
|
|
223
|
+
} else {
|
|
224
|
+
a.setAttribute("download", "");
|
|
225
|
+
}
|
|
226
|
+
a.target = "_blank";
|
|
227
|
+
a.rel = "noopener noreferrer";
|
|
228
|
+
a.className = "symframe-download";
|
|
229
|
+
a.textContent = `⬇ ${label}`;
|
|
230
|
+
return a;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const renderers = {
|
|
234
|
+
text: renderTextBody,
|
|
235
|
+
markdown: renderMarkdownBody,
|
|
236
|
+
code: renderCodeBody,
|
|
237
|
+
"email-draft": renderEmailDraftBody,
|
|
238
|
+
pdf: renderPdfBody,
|
|
239
|
+
audio: renderAudioBody,
|
|
240
|
+
video: renderVideoBody,
|
|
241
|
+
};
|
|
242
|
+
|
|
64
243
|
function renderBodyForType(card) {
|
|
65
244
|
const type = card.type || "text";
|
|
66
|
-
|
|
67
|
-
|
|
245
|
+
const renderer = renderers[type] || renderers.text;
|
|
246
|
+
return renderer(card);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// True iff the card has any body-shaped data — body, bodyHtml, or
|
|
250
|
+
// type-specific structured fields. Used to decide whether to render
|
|
251
|
+
// the body slot at all.
|
|
252
|
+
function hasBodyContent(card) {
|
|
253
|
+
if (card.body || card.bodyHtml) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
if (card.url) {
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
if (card.email && typeof card.email === "object") {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Choose what `Copy` would copy for this card. Honors body/bodyHtml first,
|
|
266
|
+
// then type-specific shapes (email-draft renders a plain-text email;
|
|
267
|
+
// url-based media types copy the URL).
|
|
268
|
+
function resolveCopyTarget(card) {
|
|
269
|
+
if (card.body) {
|
|
270
|
+
return card.body;
|
|
68
271
|
}
|
|
69
|
-
// Fallback: text body (escaped via textContent in caller) or trusted HTML.
|
|
70
272
|
if (card.bodyHtml) {
|
|
71
|
-
return
|
|
273
|
+
return card.bodyHtml;
|
|
274
|
+
}
|
|
275
|
+
if (card.email && typeof card.email === "object") {
|
|
276
|
+
const lines = [];
|
|
277
|
+
if (card.email.from) {
|
|
278
|
+
lines.push(`From: ${card.email.from}`);
|
|
279
|
+
}
|
|
280
|
+
if (card.email.to) {
|
|
281
|
+
lines.push(`To: ${card.email.to}`);
|
|
282
|
+
}
|
|
283
|
+
if (card.email.cc) {
|
|
284
|
+
lines.push(`Cc: ${card.email.cc}`);
|
|
285
|
+
}
|
|
286
|
+
if (card.email.bcc) {
|
|
287
|
+
lines.push(`Bcc: ${card.email.bcc}`);
|
|
288
|
+
}
|
|
289
|
+
if (card.email.subject) {
|
|
290
|
+
lines.push(`Subject: ${card.email.subject}`);
|
|
291
|
+
}
|
|
292
|
+
if (card.email.body) {
|
|
293
|
+
lines.push("");
|
|
294
|
+
lines.push(card.email.body);
|
|
295
|
+
}
|
|
296
|
+
return lines.join("\n");
|
|
297
|
+
}
|
|
298
|
+
if (card.url) {
|
|
299
|
+
return card.url;
|
|
72
300
|
}
|
|
73
|
-
return
|
|
301
|
+
return "";
|
|
74
302
|
}
|
|
75
303
|
|
|
76
|
-
// Default Copy action when the card has
|
|
77
|
-
//
|
|
78
|
-
//
|
|
304
|
+
// Default Copy action when the card has copyable content and no explicit
|
|
305
|
+
// actions. Custom actions take precedence — server-pushed cards or
|
|
306
|
+
// tool-pushed cards with their own buttons get those instead.
|
|
79
307
|
function buildDefaultActions(card) {
|
|
80
308
|
if (Array.isArray(card.actions) && card.actions.length > 0) {
|
|
81
309
|
return card.actions;
|
|
82
310
|
}
|
|
83
|
-
|
|
311
|
+
const copyTarget = resolveCopyTarget(card);
|
|
312
|
+
if (!copyTarget) {
|
|
84
313
|
return [];
|
|
85
314
|
}
|
|
86
|
-
const copyTarget = card.body ?? card.bodyHtml ?? "";
|
|
87
315
|
return [
|
|
88
316
|
{
|
|
89
317
|
label: "Copy",
|
|
@@ -133,15 +361,13 @@
|
|
|
133
361
|
}
|
|
134
362
|
el.appendChild(header);
|
|
135
363
|
|
|
136
|
-
// Body via type-specific renderer
|
|
137
|
-
if (card
|
|
364
|
+
// Body via type-specific renderer (returns an Element)
|
|
365
|
+
if (hasBodyContent(card)) {
|
|
138
366
|
const body = document.createElement("div");
|
|
139
367
|
body.className = "symframe-card-body";
|
|
140
368
|
const rendered = renderBodyForType(card);
|
|
141
|
-
if (rendered
|
|
142
|
-
body.
|
|
143
|
-
} else {
|
|
144
|
-
body.textContent = rendered.text;
|
|
369
|
+
if (rendered) {
|
|
370
|
+
body.appendChild(rendered);
|
|
145
371
|
}
|
|
146
372
|
el.appendChild(body);
|
|
147
373
|
}
|