@agentdeck/shared 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/adapter.d.ts +16 -3
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +38 -0
- package/dist/adapter.js.map +1 -1
- package/dist/command-builders.d.ts +30 -0
- package/dist/command-builders.d.ts.map +1 -0
- package/dist/command-builders.js +60 -0
- package/dist/command-builders.js.map +1 -0
- package/dist/eval-schema.d.ts +211 -0
- package/dist/eval-schema.d.ts.map +1 -0
- package/dist/eval-schema.js +23 -0
- package/dist/eval-schema.js.map +1 -0
- package/dist/format-utils.d.ts +27 -0
- package/dist/format-utils.d.ts.map +1 -0
- package/dist/format-utils.js +120 -0
- package/dist/format-utils.js.map +1 -0
- package/dist/gateway-protocol.d.ts +391 -0
- package/dist/gateway-protocol.d.ts.map +1 -0
- package/dist/gateway-protocol.js +19 -0
- package/dist/gateway-protocol.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/llm-settings.d.ts +52 -0
- package/dist/llm-settings.d.ts.map +1 -0
- package/dist/llm-settings.js +118 -0
- package/dist/llm-settings.js.map +1 -0
- package/dist/protocol.d.ts +326 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +19 -0
- package/dist/protocol.js.map +1 -1
- package/dist/session-utils.d.ts +62 -0
- package/dist/session-utils.d.ts.map +1 -0
- package/dist/session-utils.js +109 -0
- package/dist/session-utils.js.map +1 -0
- package/dist/state-colors.d.ts +16 -0
- package/dist/state-colors.d.ts.map +1 -0
- package/dist/state-colors.js +46 -0
- package/dist/state-colors.js.map +1 -0
- package/dist/states.d.ts +1 -0
- package/dist/states.d.ts.map +1 -1
- package/dist/svg-renderers/agent-logos.d.ts +33 -0
- package/dist/svg-renderers/agent-logos.d.ts.map +1 -0
- package/dist/svg-renderers/agent-logos.js +100 -0
- package/dist/svg-renderers/agent-logos.js.map +1 -0
- package/dist/svg-renderers/index.d.ts +4 -0
- package/dist/svg-renderers/index.d.ts.map +1 -0
- package/dist/svg-renderers/index.js +4 -0
- package/dist/svg-renderers/index.js.map +1 -0
- package/dist/svg-renderers/session-slot-renderer.d.ts +25 -0
- package/dist/svg-renderers/session-slot-renderer.d.ts.map +1 -0
- package/dist/svg-renderers/session-slot-renderer.js +317 -0
- package/dist/svg-renderers/session-slot-renderer.js.map +1 -0
- package/dist/svg-renderers/text-utils.d.ts +15 -0
- package/dist/svg-renderers/text-utils.d.ts.map +1 -0
- package/dist/svg-renderers/text-utils.js +88 -0
- package/dist/svg-renderers/text-utils.js.map +1 -0
- package/dist/telemetry-envelope.d.ts +108 -0
- package/dist/telemetry-envelope.d.ts.map +1 -0
- package/dist/telemetry-envelope.js +34 -0
- package/dist/telemetry-envelope.js.map +1 -0
- package/dist/timeline-summarizer.d.ts +13 -0
- package/dist/timeline-summarizer.d.ts.map +1 -0
- package/dist/timeline-summarizer.js +83 -0
- package/dist/timeline-summarizer.js.map +1 -0
- package/dist/timeline.d.ts +65 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +456 -0
- package/dist/timeline.js.map +1 -0
- package/dist/voice-paths.d.ts +4 -0
- package/dist/voice-paths.d.ts.map +1 -1
- package/dist/voice-paths.js +5 -0
- package/dist/voice-paths.js.map +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical state color palette — single source of truth for all platforms.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript consumers import directly.
|
|
5
|
+
* Native platforms (Android/Apple/ESP32) reference these hex values in comments.
|
|
6
|
+
*/
|
|
7
|
+
import { State } from './states.js';
|
|
8
|
+
// ===== State Colors =====
|
|
9
|
+
export const STATE_COLORS = {
|
|
10
|
+
[State.IDLE]: '#22c55e', // green
|
|
11
|
+
[State.PROCESSING]: '#3b82f6', // blue
|
|
12
|
+
[State.AWAITING_PERMISSION]: '#f59e0b', // amber
|
|
13
|
+
[State.AWAITING_OPTION]: '#f59e0b', // amber
|
|
14
|
+
[State.AWAITING_DIFF]: '#f59e0b', // amber
|
|
15
|
+
[State.DISCONNECTED]: '#6b7280', // gray
|
|
16
|
+
};
|
|
17
|
+
/** Look up state color by string key. No agent-type overrides — purely semantic. */
|
|
18
|
+
export function stateColor(state) {
|
|
19
|
+
if (!state)
|
|
20
|
+
return STATE_COLORS[State.DISCONNECTED];
|
|
21
|
+
return STATE_COLORS[state] ?? STATE_COLORS[State.IDLE];
|
|
22
|
+
}
|
|
23
|
+
// ===== Agent Brand Colors (for icons, not states) =====
|
|
24
|
+
export const AGENT_BRAND_COLORS = {
|
|
25
|
+
'claude-code': '#C07058', // terracotta
|
|
26
|
+
'openclaw': '#ff4d4d', // red
|
|
27
|
+
'codex-cli': '#6366f1', // indigo
|
|
28
|
+
'opencode': '#F1ECEC', // cream
|
|
29
|
+
'monitor': '#94a3b8', // slate
|
|
30
|
+
};
|
|
31
|
+
/** Get agent brand color. Falls back to slate for unknown types. */
|
|
32
|
+
export function agentBrandColor(agentType) {
|
|
33
|
+
return AGENT_BRAND_COLORS[agentType ?? ''] ?? '#94a3b8';
|
|
34
|
+
}
|
|
35
|
+
// ===== Color Utilities =====
|
|
36
|
+
/** Mix a hex color toward black by ratio (0=original, 1=black). */
|
|
37
|
+
export function dimColor(hex, ratio) {
|
|
38
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
39
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
40
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
41
|
+
const dr = Math.round(r * (1 - ratio));
|
|
42
|
+
const dg = Math.round(g * (1 - ratio));
|
|
43
|
+
const db = Math.round(b * (1 - ratio));
|
|
44
|
+
return `#${dr.toString(16).padStart(2, '0')}${dg.toString(16).padStart(2, '0')}${db.toString(16).padStart(2, '0')}`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=state-colors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-colors.js","sourceRoot":"","sources":["../src/state-colors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,2BAA2B;AAE3B,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,CAAC,KAAK,CAAC,IAAI,CAAC,EAAiB,SAAS,EAAG,QAAQ;IACjD,CAAC,KAAK,CAAC,UAAU,CAAC,EAAW,SAAS,EAAG,OAAO;IAChD,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,SAAS,EAAG,QAAQ;IACjD,CAAC,KAAK,CAAC,eAAe,CAAC,EAAM,SAAS,EAAG,QAAQ;IACjD,CAAC,KAAK,CAAC,aAAa,CAAC,EAAQ,SAAS,EAAG,QAAQ;IACjD,CAAC,KAAK,CAAC,YAAY,CAAC,EAAS,SAAS,EAAG,OAAO;CACjD,CAAC;AAEF,oFAAoF;AACpF,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACpD,OAAQ,YAAuC,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACrF,CAAC;AAED,yDAAyD;AAEzD,MAAM,CAAC,MAAM,kBAAkB,GAA2B;IACxD,aAAa,EAAE,SAAS,EAAG,aAAa;IACxC,UAAU,EAAK,SAAS,EAAG,MAAM;IACjC,WAAW,EAAI,SAAS,EAAG,SAAS;IACpC,UAAU,EAAK,SAAS,EAAG,QAAQ;IACnC,SAAS,EAAM,SAAS,EAAG,QAAQ;CACpC,CAAC;AAEF,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,SAA6B;IAC3D,OAAO,kBAAkB,CAAC,SAAS,IAAI,EAAE,CAAC,IAAI,SAAS,CAAC;AAC1D,CAAC;AAED,8BAA8B;AAE9B,mEAAmE;AACnE,MAAM,UAAU,QAAQ,CAAC,GAAW,EAAE,KAAa;IACjD,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACvC,OAAO,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AACtH,CAAC"}
|
package/dist/states.d.ts
CHANGED
package/dist/states.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../src/states.ts"],"names":[],"mappings":"AAAA,oBAAY,KAAK;IACf,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,mBAAmB,wBAAwB;IAC3C,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;CAChC;AAED,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,YAAY,gBAAgB;IAC5B,QAAQ,YAAY;IACpB,kBAAkB,sBAAsB;CACzC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC;IAClB,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,eAAe,EA4BxC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,eAAe,EAAE,WAAW,CAAC;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
|
|
1
|
+
{"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../src/states.ts"],"names":[],"mappings":"AAAA,oBAAY,KAAK;IACf,YAAY,iBAAiB;IAC7B,IAAI,SAAS;IACb,UAAU,eAAe;IACzB,mBAAmB,wBAAwB;IAC3C,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;CAChC;AAED,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,IAAI,SAAS;IACb,YAAY,gBAAgB;IAC5B,QAAQ,YAAY;IACpB,kBAAkB,sBAAsB;CACzC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,KAAK,GAAG,GAAG,CAAC;IAClB,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,EAAE,eAAe,EA4BxC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,OAAO,eAAe,EAAE,WAAW,CAAC;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent logo SVG paths for icon and watermark rendering on session buttons.
|
|
3
|
+
*
|
|
4
|
+
* Each logo is a centered path designed for a 144x144 button canvas.
|
|
5
|
+
* Two rendering modes:
|
|
6
|
+
* agentLogoIcon() — prominent icon at top of button (primary identification)
|
|
7
|
+
* agentLogoWatermark() — low-opacity background mark
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentType } from '../adapter.js';
|
|
10
|
+
/** Claude Code creature asset: assets/logos/claude.svg. viewBox 0 0 24 24. */
|
|
11
|
+
export declare const CLAUDE_LOGO_PATH = "M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z";
|
|
12
|
+
/** Legacy OpenClaw paths kept for the Gateway preset mini-browser icon. */
|
|
13
|
+
export declare const OC_BODY = "M60 10 C30 10 15 35 15 55 C15 75 30 95 45 100 L45 110 L55 110 L55 100 C55 100 60 102 65 100 L65 110 L75 110 L75 100 C90 95 105 75 105 55 C105 35 90 10 60 10Z";
|
|
14
|
+
export declare const OC_CLAW_L = "M20 45 C5 40 0 50 5 60 C10 70 20 65 25 55 C28 48 25 45 20 45Z";
|
|
15
|
+
export declare const OC_CLAW_R = "M100 45 C115 40 120 50 115 60 C110 70 100 65 95 55 C92 48 95 45 100 45Z";
|
|
16
|
+
/** Codex CLI knot/clover — official SVG from codex brand assets. viewBox 0 0 24 24. */
|
|
17
|
+
export declare const CODEX_LOGO_PATH = "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z";
|
|
18
|
+
/** OpenClaw creature asset: assets/logos/openclaw.svg. viewBox 0 0 24 24. */
|
|
19
|
+
export declare const OPENCLAW_LOGO_PATHS: string[];
|
|
20
|
+
/**
|
|
21
|
+
* Render agent logo as a visible icon at top-center of button.
|
|
22
|
+
* Uses agent brand color (not state color) for consistent identification.
|
|
23
|
+
* @param agent Agent type
|
|
24
|
+
* @param size Target size in px (default 48)
|
|
25
|
+
* @param opacity Icon opacity (default 0.7)
|
|
26
|
+
*/
|
|
27
|
+
export declare function agentLogoIcon(agent: AgentType, size?: number, opacity?: number, cx?: number, cy?: number): string;
|
|
28
|
+
/**
|
|
29
|
+
* Render agent logo as a background watermark.
|
|
30
|
+
* Uses brand color dimmed for subtle identification.
|
|
31
|
+
*/
|
|
32
|
+
export declare function agentLogoWatermark(agent: AgentType, _color?: string, opacity?: number): string;
|
|
33
|
+
//# sourceMappingURL=agent-logos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-logos.d.ts","sourceRoot":"","sources":["../../src/svg-renderers/agent-logos.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG/C,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,g+CACk8C,CAAC;AAEh+C,2EAA2E;AAC3E,eAAO,MAAM,OAAO,kKAC6I,CAAC;AAClK,eAAO,MAAM,SAAS,kEAC2C,CAAC;AAClE,eAAO,MAAM,SAAS,4EACqD,CAAC;AAE5E,uFAAuF;AACvF,eAAO,MAAM,eAAe,goCACmmC,CAAC;AAEhoC,6EAA6E;AAC7E,eAAO,MAAM,mBAAmB,UAM/B,CAAC;AAkBF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,EAChB,IAAI,SAAK,EACT,OAAO,SAAM,EACb,EAAE,SAAK,EACP,EAAE,SAAgB,GACjB,MAAM,CAwBR;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,SAAO,GACb,MAAM,CAyBR"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent logo SVG paths for icon and watermark rendering on session buttons.
|
|
3
|
+
*
|
|
4
|
+
* Each logo is a centered path designed for a 144x144 button canvas.
|
|
5
|
+
* Two rendering modes:
|
|
6
|
+
* agentLogoIcon() — prominent icon at top of button (primary identification)
|
|
7
|
+
* agentLogoWatermark() — low-opacity background mark
|
|
8
|
+
*/
|
|
9
|
+
import { dimColor, agentBrandColor } from '../state-colors.js';
|
|
10
|
+
/** Claude Code creature asset: assets/logos/claude.svg. viewBox 0 0 24 24. */
|
|
11
|
+
export const CLAUDE_LOGO_PATH = 'M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z';
|
|
12
|
+
/** Legacy OpenClaw paths kept for the Gateway preset mini-browser icon. */
|
|
13
|
+
export const OC_BODY = 'M60 10 C30 10 15 35 15 55 C15 75 30 95 45 100 L45 110 L55 110 L55 100 C55 100 60 102 65 100 L65 110 L75 110 L75 100 C90 95 105 75 105 55 C105 35 90 10 60 10Z';
|
|
14
|
+
export const OC_CLAW_L = 'M20 45 C5 40 0 50 5 60 C10 70 20 65 25 55 C28 48 25 45 20 45Z';
|
|
15
|
+
export const OC_CLAW_R = 'M100 45 C115 40 120 50 115 60 C110 70 100 65 95 55 C92 48 95 45 100 45Z';
|
|
16
|
+
/** Codex CLI knot/clover — official SVG from codex brand assets. viewBox 0 0 24 24. */
|
|
17
|
+
export const CODEX_LOGO_PATH = 'M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z';
|
|
18
|
+
/** OpenClaw creature asset: assets/logos/openclaw.svg. viewBox 0 0 24 24. */
|
|
19
|
+
export const OPENCLAW_LOGO_PATHS = [
|
|
20
|
+
'M9.046 7.104a.527.527 0 110 1.055.527.527 0 010-1.055z',
|
|
21
|
+
'M15.376 7.104a.528.528 0 110 1.056.528.528 0 010-1.056z',
|
|
22
|
+
'M16.877 1.912c.58-.27 1.14-.323 1.616-.037a.317.317 0 01-.326.542c-.227-.136-.547-.153-1.022.068-.352.165-.765.45-1.234.866 2.683 1.17 4.4 3.5 5.148 5.921a6.421 6.421 0 00-.704.184c-.578.016-1.174.204-1.502.735-.338.55-.268 1.276.072 2.069l.005.012.007.014c.523 1.045 1.318 1.91 2.2 2.284-.912 3.274-3.44 6.144-5.972 6.988v2.109h-2.11v-2.11c-1.043.417-2.086.01-2.11 0v2.11h-2.11v-2.11c-2.531-.843-5.061-3.713-5.973-6.987.882-.373 1.678-1.238 2.2-2.284l.007-.014.006-.012c.34-.793.41-1.518.071-2.069-.327-.531-.923-.719-1.503-.735a6.409 6.409 0 00-.704-.183c.749-2.421 2.466-4.751 5.149-5.922-.47-.416-.88-.701-1.234-.866-.474-.221-.794-.204-1.021-.068a.318.318 0 01-.435-.109.317.317 0 01.109-.433c.476-.286 1.036-.233 1.615.037.49.229 1.031.628 1.621 1.182A9.924 9.924 0 0112 2.568c1.199 0 2.284.19 3.256.526.59-.554 1.13-.953 1.62-1.182zM8.835 6.577a1.266 1.266 0 100 2.532 1.266 1.266 0 000-2.532zm6.33 0a1.267 1.267 0 100 2.533 1.267 1.267 0 000-2.533z',
|
|
23
|
+
'M.395 13.118c-.966-1.932-.163-3.863 2.41-3.365v-.001l.05.01c.084.018.17.038.26.06.033.009.067.017.1.027.084.022.168.048.255.076l.09.027c.528 0 .95.158 1.16.501.212.343.212.87-.105 1.61-.085.17-.178.333-.276.489l-.01.017a4.967 4.967 0 01-.62.791l-.019.02c-1.092 1.117-2.496 1.336-3.295-.262z',
|
|
24
|
+
'M21.193 9.753c2.574-.5 3.378 1.433 2.411 3.365-.58 1.159-1.476 1.361-2.342.96l-.011-.005a2.419 2.419 0 01-.114-.056l-.019-.01a2.751 2.751 0 01-.115-.067l-.023-.014c-.035-.022-.071-.044-.106-.068l-.05-.035c-.55-.388-1.062-1.007-1.44-1.76-.276-.647-.311-1.132-.174-1.472.176-.439.636-.639 1.23-.639.032-.011.066-.02.099-.03.08-.026.16-.05.238-.072l.117-.03a5.502 5.502 0 01.3-.067z',
|
|
25
|
+
];
|
|
26
|
+
function officialPathIcon(path, fill, size, opacity, cx, cy) {
|
|
27
|
+
const s = size / 24;
|
|
28
|
+
return `<g transform="translate(${cx},${cy}) scale(${s.toFixed(3)}) translate(-12,-12)" opacity="${opacity}"><path d="${path}" fill="${fill}" fill-rule="evenodd" clip-rule="evenodd"/></g>`;
|
|
29
|
+
}
|
|
30
|
+
function officialMultiPathIcon(paths, fill, size, opacity, cx, cy) {
|
|
31
|
+
const s = size / 24;
|
|
32
|
+
return [
|
|
33
|
+
`<g transform="translate(${cx},${cy}) scale(${s.toFixed(3)}) translate(-12,-12)" opacity="${opacity}" fill="${fill}" fill-rule="evenodd" clip-rule="evenodd">`,
|
|
34
|
+
...paths.map((p) => `<path d="${p}"/>`),
|
|
35
|
+
`</g>`,
|
|
36
|
+
].join('');
|
|
37
|
+
}
|
|
38
|
+
// ===== Prominent agent icon (top of button, primary identification) =====
|
|
39
|
+
/**
|
|
40
|
+
* Render agent logo as a visible icon at top-center of button.
|
|
41
|
+
* Uses agent brand color (not state color) for consistent identification.
|
|
42
|
+
* @param agent Agent type
|
|
43
|
+
* @param size Target size in px (default 48)
|
|
44
|
+
* @param opacity Icon opacity (default 0.7)
|
|
45
|
+
*/
|
|
46
|
+
export function agentLogoIcon(agent, size = 48, opacity = 0.7, cx = 72, cy = size / 2 + 12) {
|
|
47
|
+
const brandColor = agentBrandColor(agent);
|
|
48
|
+
if (agent === 'claude-code') {
|
|
49
|
+
return officialPathIcon(CLAUDE_LOGO_PATH, brandColor, size, opacity, cx, cy);
|
|
50
|
+
}
|
|
51
|
+
if (agent === 'codex-cli') {
|
|
52
|
+
return officialPathIcon(CODEX_LOGO_PATH, brandColor, size, opacity, cx, cy);
|
|
53
|
+
}
|
|
54
|
+
if (agent === 'opencode') {
|
|
55
|
+
// Smaller icon for OpenCode (geometric squares are visually heavier)
|
|
56
|
+
const ocSize = Math.round(size * 0.75);
|
|
57
|
+
const half = ocSize / 2;
|
|
58
|
+
const ring = ocSize * 0.18;
|
|
59
|
+
const inner = ocSize * 0.5;
|
|
60
|
+
return [
|
|
61
|
+
`<g opacity="${opacity}">`,
|
|
62
|
+
`<rect x="${cx - half}" y="${cy - half}" width="${ocSize}" height="${ocSize}" rx="4" fill="${dimColor(brandColor, 0.3)}"/>`,
|
|
63
|
+
`<rect x="${cx - half + ring}" y="${cy - half + ring}" width="${ocSize - ring * 2}" height="${ocSize - ring * 2}" rx="2" fill="${dimColor('#4B4646', 0.2)}"/>`,
|
|
64
|
+
`<rect x="${cx - inner / 2}" y="${cy - inner / 2}" width="${inner}" height="${inner}" rx="2" fill="${dimColor('#4B4646', 0.2)}"/>`,
|
|
65
|
+
`</g>`,
|
|
66
|
+
].join('');
|
|
67
|
+
}
|
|
68
|
+
return officialMultiPathIcon(OPENCLAW_LOGO_PATHS, brandColor, size, opacity, cx, cy);
|
|
69
|
+
}
|
|
70
|
+
// ===== Low-opacity watermark (background mark) =====
|
|
71
|
+
/**
|
|
72
|
+
* Render agent logo as a background watermark.
|
|
73
|
+
* Uses brand color dimmed for subtle identification.
|
|
74
|
+
*/
|
|
75
|
+
export function agentLogoWatermark(agent, _color, opacity = 0.12) {
|
|
76
|
+
const brandColor = agentBrandColor(agent);
|
|
77
|
+
const markOpacity = Math.min(opacity * 4, 0.9);
|
|
78
|
+
const fill = dimColor(brandColor, 0.5);
|
|
79
|
+
if (agent === 'claude-code') {
|
|
80
|
+
return officialPathIcon(CLAUDE_LOGO_PATH, fill, 72, markOpacity, 72, 72);
|
|
81
|
+
}
|
|
82
|
+
if (agent === 'codex-cli') {
|
|
83
|
+
return officialPathIcon(CODEX_LOGO_PATH, fill, 72, markOpacity, 72, 72);
|
|
84
|
+
}
|
|
85
|
+
if (agent === 'opencode') {
|
|
86
|
+
const s = 72;
|
|
87
|
+
const half = s / 2;
|
|
88
|
+
const ring = s * 0.18;
|
|
89
|
+
const inner = s * 0.5;
|
|
90
|
+
return [
|
|
91
|
+
`<g opacity="${markOpacity}">`,
|
|
92
|
+
`<rect x="${72 - half}" y="${72 - half}" width="${s}" height="${s}" fill="${dimColor('#F1ECEC', 0.6)}"/>`,
|
|
93
|
+
`<rect x="${72 - half + ring}" y="${72 - half + ring}" width="${s - ring * 2}" height="${s - ring * 2}" fill="${dimColor('#4B4646', 0.5)}"/>`,
|
|
94
|
+
`<rect x="${72 - inner / 2}" y="${72 - inner / 2}" width="${inner}" height="${inner}" fill="${dimColor('#4B4646', 0.5)}"/>`,
|
|
95
|
+
`</g>`,
|
|
96
|
+
].join('');
|
|
97
|
+
}
|
|
98
|
+
return officialMultiPathIcon(OPENCLAW_LOGO_PATHS, fill, 72, markOpacity, 72, 72);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=agent-logos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-logos.js","sourceRoot":"","sources":["../../src/svg-renderers/agent-logos.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svg-renderers/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/svg-renderers/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SessionInfo } from '../protocol.js';
|
|
2
|
+
import type { PromptOption } from '../states.js';
|
|
3
|
+
import { State } from '../states.js';
|
|
4
|
+
/**
|
|
5
|
+
* Format "Model · effort" suffix for session tile / detail view.
|
|
6
|
+
* Skips neutral efforts ("medium" legacy, "default" is Claude Code 2.1+
|
|
7
|
+
* per-model default) so they don't clutter the tile. Truncates the model
|
|
8
|
+
* name preferentially so the effort label survives in tight pixel budgets.
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatModelEffort(modelName?: string, effortLevel?: string, maxLen?: number): string;
|
|
11
|
+
export declare function renderSessionSlot(session: SessionInfo, isActive: boolean, animFrame: number, displayName?: string, options?: {
|
|
12
|
+
animated?: boolean;
|
|
13
|
+
}): string;
|
|
14
|
+
export declare function renderEmptySlot(): string;
|
|
15
|
+
export declare function renderNoDaemonSlot(slot: number): string;
|
|
16
|
+
export declare function renderBackButton(): string;
|
|
17
|
+
export declare function renderNextPageButton(pageLabel: string): string;
|
|
18
|
+
export declare function renderEscButton(active?: boolean): string;
|
|
19
|
+
export declare function renderStopButton(active?: boolean): string;
|
|
20
|
+
export declare function renderDetailInfo(session: SessionInfo | undefined, state: State, tool?: string, modelName?: string, mode?: string, displayName?: string, effortLevel?: string): string;
|
|
21
|
+
export declare function renderOptionButton(option: PromptOption, index: number): string;
|
|
22
|
+
export declare function renderPresetButton(label: string, iconSvg: string, color: string, textColor: string, subtitle?: string, loading?: boolean): string;
|
|
23
|
+
export declare function renderInfoSlot(label: string, subtitle?: string): string;
|
|
24
|
+
export declare function svgFrame(bgColor: string, innerElements: string): string;
|
|
25
|
+
//# sourceMappingURL=session-slot-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-slot-renderer.d.ts","sourceRoot":"","sources":["../../src/svg-renderers/session-slot-renderer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAwCrC;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAS/F;AAID,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/B,MAAM,CA8HR;AAID,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUvD;AAID,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED,wBAAgB,eAAe,CAAC,MAAM,UAAO,GAAG,MAAM,CASrD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,UAAO,GAAG,MAAM,CAStD;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAiDrL;AAID,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkB9E;AAID,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CASjJ;AAID,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAMvE;AAID,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAkBvE"}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { stateColor } from '../state-colors.js';
|
|
2
|
+
import { agentLogoIcon } from './agent-logos.js';
|
|
3
|
+
import { wrapTextByWidth } from './text-utils.js';
|
|
4
|
+
const SIZE = 144;
|
|
5
|
+
const MAX_TEXT_PX = 124; // 144 - 10px padding each side
|
|
6
|
+
function stateLabel(state, agentType) {
|
|
7
|
+
if (!state)
|
|
8
|
+
return 'OFFLINE';
|
|
9
|
+
// OpenClaw-specific labels
|
|
10
|
+
if (agentType === 'openclaw') {
|
|
11
|
+
if (state === 'idle')
|
|
12
|
+
return 'STANDBY';
|
|
13
|
+
if (state === 'processing')
|
|
14
|
+
return 'ROUTING';
|
|
15
|
+
}
|
|
16
|
+
switch (state) {
|
|
17
|
+
case 'idle': return 'IDLE';
|
|
18
|
+
case 'processing': return 'WORKING';
|
|
19
|
+
case 'awaiting_option':
|
|
20
|
+
case 'awaiting_permission':
|
|
21
|
+
case 'awaiting_diff':
|
|
22
|
+
return 'AWAITING';
|
|
23
|
+
default: return state.toUpperCase();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function escXml(s) {
|
|
27
|
+
return s
|
|
28
|
+
.replace(/&/g, '&')
|
|
29
|
+
.replace(/</g, '<')
|
|
30
|
+
.replace(/>/g, '>')
|
|
31
|
+
.replace(/"/g, '"')
|
|
32
|
+
.replace(/'/g, ''');
|
|
33
|
+
}
|
|
34
|
+
function truncate(s, max) {
|
|
35
|
+
if (s.length <= max)
|
|
36
|
+
return s;
|
|
37
|
+
return s.slice(0, max - 1) + '\u2026';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Format "Model · effort" suffix for session tile / detail view.
|
|
41
|
+
* Skips neutral efforts ("medium" legacy, "default" is Claude Code 2.1+
|
|
42
|
+
* per-model default) so they don't clutter the tile. Truncates the model
|
|
43
|
+
* name preferentially so the effort label survives in tight pixel budgets.
|
|
44
|
+
*/
|
|
45
|
+
export function formatModelEffort(modelName, effortLevel, maxLen = 14) {
|
|
46
|
+
if (!modelName)
|
|
47
|
+
return '';
|
|
48
|
+
const showEffort = effortLevel && effortLevel !== 'medium' && effortLevel !== 'default';
|
|
49
|
+
if (!showEffort)
|
|
50
|
+
return truncate(modelName, maxLen);
|
|
51
|
+
const combined = `${modelName} · ${effortLevel}`;
|
|
52
|
+
if (combined.length <= maxLen)
|
|
53
|
+
return combined;
|
|
54
|
+
const effortSuffix = ` · ${effortLevel}`;
|
|
55
|
+
const modelBudget = Math.max(4, maxLen - effortSuffix.length);
|
|
56
|
+
return truncate(modelName, modelBudget) + effortSuffix;
|
|
57
|
+
}
|
|
58
|
+
// ---- Session List Button ----
|
|
59
|
+
export function renderSessionSlot(session, isActive, animFrame, displayName, options) {
|
|
60
|
+
const isWorking = session.state === 'processing';
|
|
61
|
+
const isAsking = session.state?.startsWith('awaiting') ?? false;
|
|
62
|
+
const isIdle = !isWorking && !isAsking;
|
|
63
|
+
// Stream Deck / SD+ run a 150ms tick — animated. D200H's TypeScript image
|
|
64
|
+
// pipeline (bridge/src/d200h/image-renderer.ts) has no such loop: passing
|
|
65
|
+
// animFrame=0 every time freezes dashed strokes and leaves the sin-based
|
|
66
|
+
// pulse at a dim phase. Callers without a loop should pass animated:false
|
|
67
|
+
// so we emit a motion-free visual (solid borders + badges) that still
|
|
68
|
+
// clearly distinguishes working vs awaiting vs idle.
|
|
69
|
+
const animated = options?.animated ?? true;
|
|
70
|
+
const agent = session.agentType || 'claude-code';
|
|
71
|
+
const nameForDisplay = displayName ?? session.projectName;
|
|
72
|
+
// Bottom line budget: tile width ~124px at 14px font ≈ 16 chars. Leave a
|
|
73
|
+
// little headroom so "Opus 4.7 · max" fits without running into the
|
|
74
|
+
// watermark on the right.
|
|
75
|
+
const modelText = formatModelEffort(session.modelName, session.effortLevel, 15);
|
|
76
|
+
// Custom palette mimicking the premium demo
|
|
77
|
+
const p1 = agent === 'claude-code' ? '#D97757' : agent === 'codex-cli' ? '#8BA4FF' : agent === 'openclaw' ? '#FF6B6B' : '#F1ECEC';
|
|
78
|
+
const p2 = agent === 'claude-code' ? '#BE6D52' : agent === 'codex-cli' ? '#5981FF' : agent === 'openclaw' ? '#CC3333' : '#AFAFAF';
|
|
79
|
+
const sColor = stateColor(session.state);
|
|
80
|
+
const fontFam = 'Inter, -apple-system, system-ui, Helvetica Neue, sans-serif';
|
|
81
|
+
const stateLbl = isWorking ? 'RUNNING' : isAsking ? 'PERMIT?' : 'IDLE';
|
|
82
|
+
const colorText = isWorking ? '#FDE68A' : isAsking ? '#FECACA' : p1;
|
|
83
|
+
const gradId = `sd-bg-${agent}-${session.state || 'idle'}`;
|
|
84
|
+
let defs = `
|
|
85
|
+
<linearGradient id="${gradId}" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
86
|
+
<stop offset="0%" stop-color="#1C1C1E"/>
|
|
87
|
+
<stop offset="100%" stop-color="#0C0C0E"/>
|
|
88
|
+
</linearGradient>
|
|
89
|
+
`;
|
|
90
|
+
let glowBorder = '';
|
|
91
|
+
let askDot = '';
|
|
92
|
+
let runBadge = '';
|
|
93
|
+
const filterId = `pg-${animFrame}`;
|
|
94
|
+
const blurDef = `
|
|
95
|
+
<filter id="${filterId}" x="-10%" y="-10%" width="120%" height="120%">
|
|
96
|
+
<feGaussianBlur in="SourceGraphic" stdDeviation="2.4"/>
|
|
97
|
+
</filter>
|
|
98
|
+
`;
|
|
99
|
+
if (isAsking) {
|
|
100
|
+
// Animated callers pulse the opacity (0.55…1.0 over a sin wave). Static
|
|
101
|
+
// callers (D200H) pin to a near-peak value so the frozen snapshot reads
|
|
102
|
+
// as bright and attention-grabbing instead of dim.
|
|
103
|
+
const pulseOpacity = animated
|
|
104
|
+
? 0.55 + 0.45 * Math.abs(Math.sin(animFrame * 0.15))
|
|
105
|
+
: 0.95;
|
|
106
|
+
defs += blurDef;
|
|
107
|
+
// Thick outer glow + crisp inner ring — distinct "breathing" solid border.
|
|
108
|
+
glowBorder =
|
|
109
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="4.5" opacity="${pulseOpacity.toFixed(2)}" filter="url(#${filterId})"/>` +
|
|
110
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="1.5" opacity="${(pulseOpacity * 0.9).toFixed(2)}"/>`;
|
|
111
|
+
askDot = `
|
|
112
|
+
<circle cx="114" cy="24" r="5" fill="#F5B942" filter="url(#${filterId})"/>
|
|
113
|
+
<circle cx="114" cy="24" r="3" fill="#ffffff" />
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
else if (isWorking) {
|
|
117
|
+
if (animated) {
|
|
118
|
+
// Flowing-light dashed border — SD/SD+ 150ms tick advances animFrame
|
|
119
|
+
// → dashoffset drifts → chasing light.
|
|
120
|
+
const perimeter = 128 * 4;
|
|
121
|
+
const dashOffset = ((animFrame * 4) % perimeter).toFixed(0);
|
|
122
|
+
defs += blurDef;
|
|
123
|
+
glowBorder =
|
|
124
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="4.5" stroke-dasharray="22 14" stroke-dashoffset="-${dashOffset}" opacity="0.85" filter="url(#${filterId})"/>` +
|
|
125
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="1.5" stroke-dasharray="22 14" stroke-dashoffset="-${dashOffset}" opacity="0.95"/>`;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Non-animated callers (D200H still-image pipeline): render a solid
|
|
129
|
+
// glowing border + a play-chevron badge so WORKING is obvious without
|
|
130
|
+
// motion. The amber border is still the primary signal; the ▶ badge
|
|
131
|
+
// distinguishes this from the red awaiting state at a glance.
|
|
132
|
+
defs += blurDef;
|
|
133
|
+
glowBorder =
|
|
134
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="4.5" opacity="0.9" filter="url(#${filterId})"/>` +
|
|
135
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="none" stroke="${sColor}" stroke-width="1.5" opacity="0.95"/>`;
|
|
136
|
+
runBadge = `
|
|
137
|
+
<rect x="100" y="14" width="28" height="16" rx="8" fill="${sColor}" opacity="0.9" />
|
|
138
|
+
<text x="114" y="26" font-size="11" font-weight="800" text-anchor="middle" fill="#0C0C0E" font-family="${fontFam}">▶ RUN</text>
|
|
139
|
+
`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Simplified Agent watermark at bottom-right
|
|
143
|
+
// agentLogoIcon renders at x,y with given width/height
|
|
144
|
+
const watermark = `<g transform="translate(90, 86)" opacity="${isIdle ? '0.46' : '0.34'}">
|
|
145
|
+
${agentLogoIcon(agent, 40, 1, 0, 0)}
|
|
146
|
+
</g>`;
|
|
147
|
+
// Left Edge Color Strip
|
|
148
|
+
const leftStrip = `<rect x="8" y="8" width="4" height="128" rx="2" fill="${isWorking ? '#F5B942' : isAsking ? '#F87171' : p1}"/>`;
|
|
149
|
+
// Border is now the primary working/awaiting signal — no tiny spinner glyph.
|
|
150
|
+
const spinner = '';
|
|
151
|
+
// ACT badge only on IDLE — WORKING has the flowing border, AWAITING has the pulse.
|
|
152
|
+
const badgeObj = isIdle ? `
|
|
153
|
+
<rect x="100" y="14" width="28" height="16" rx="8" fill="#ffffff" opacity="0.1" />
|
|
154
|
+
<text x="114" y="25" font-size="10" font-weight="700" text-anchor="middle" fill="#A1A1AA" font-family="${fontFam}">ACT</text>
|
|
155
|
+
` : '';
|
|
156
|
+
const toolStr = isWorking ? 'Running task' : modelText;
|
|
157
|
+
const elements = [
|
|
158
|
+
`<defs>${defs}</defs>`,
|
|
159
|
+
`<rect width="${SIZE}" height="${SIZE}" rx="16" fill="url(#${gradId})"/>`,
|
|
160
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="#2C2C2E" opacity="0.8"/>`,
|
|
161
|
+
glowBorder,
|
|
162
|
+
leftStrip,
|
|
163
|
+
watermark,
|
|
164
|
+
spinner,
|
|
165
|
+
askDot,
|
|
166
|
+
runBadge,
|
|
167
|
+
badgeObj,
|
|
168
|
+
`<text x="20" y="32" font-size="17" font-weight="800" text-anchor="start" fill="${colorText}" font-family="${fontFam}">${escXml(stateLbl)}</text>`,
|
|
169
|
+
`<text x="20" y="52" font-size="13" font-weight="600" text-anchor="start" fill="#E2E8F0" font-family="${fontFam}">${escXml(truncate(nameForDisplay, 13))}</text>`,
|
|
170
|
+
`<text x="20" y="120" font-size="${isWorking ? '13' : '14'}" font-weight="500" text-anchor="start" fill="${colorText}" opacity="0.8" font-family="${fontFam}">${escXml(toolStr)}</text>`
|
|
171
|
+
].join('');
|
|
172
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">${elements}</svg>`;
|
|
173
|
+
}
|
|
174
|
+
// ---- Empty Slot ----
|
|
175
|
+
export function renderEmptySlot() {
|
|
176
|
+
const label = `<text x="72" y="76" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#333333">Empty</text>`;
|
|
177
|
+
return svgFrame('#111111', label);
|
|
178
|
+
}
|
|
179
|
+
export function renderNoDaemonSlot(slot) {
|
|
180
|
+
if (slot === 0) {
|
|
181
|
+
// START button — launches macOS app
|
|
182
|
+
const elements = [
|
|
183
|
+
`<text x="72" y="56" text-anchor="middle" font-family="Arial,sans-serif" font-size="14" fill="#94a3b8">AgentDeck</text>`,
|
|
184
|
+
`<text x="72" y="96" text-anchor="middle" font-family="Arial,sans-serif" font-size="28" font-weight="bold" fill="#22c55e">\u25B6 START</text>`,
|
|
185
|
+
].join('');
|
|
186
|
+
return svgFrame('#0f1a0f', elements);
|
|
187
|
+
}
|
|
188
|
+
return svgFrame('#111111', '');
|
|
189
|
+
}
|
|
190
|
+
// ---- Navigation Buttons ----
|
|
191
|
+
export function renderBackButton() {
|
|
192
|
+
const arrow = `<text x="72" y="76" text-anchor="middle" font-family="Arial,sans-serif" font-size="32" fill="#94a3b8">\u2190</text>`;
|
|
193
|
+
const label = `<text x="72" y="108" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="600" fill="#94a3b8">BACK</text>`;
|
|
194
|
+
return svgFrame('#1a1a1a', arrow + label);
|
|
195
|
+
}
|
|
196
|
+
export function renderNextPageButton(pageLabel) {
|
|
197
|
+
const arrow = `<text x="72" y="64" text-anchor="middle" font-family="Arial,sans-serif" font-size="28" fill="#60a5fa">\u25B6</text>`;
|
|
198
|
+
const label = `<text x="72" y="92" text-anchor="middle" font-family="Arial,sans-serif" font-size="14" font-weight="600" fill="#60a5fa">NEXT</text>`;
|
|
199
|
+
const page = `<text x="72" y="114" text-anchor="middle" font-family="Arial,sans-serif" font-size="11" fill="#64748b">${escXml(pageLabel)}</text>`;
|
|
200
|
+
return svgFrame('#1a1a2e', arrow + label + page);
|
|
201
|
+
}
|
|
202
|
+
export function renderEscButton(active = true) {
|
|
203
|
+
const c = active ? '#f97316' : '#a0855a';
|
|
204
|
+
const bg = active ? '#2d1810' : '#1a1308';
|
|
205
|
+
const op = active ? '' : ' opacity="0.45"';
|
|
206
|
+
const elements = [
|
|
207
|
+
`<text x="72" y="62" text-anchor="middle" font-family="Arial,sans-serif" font-size="32" fill="${c}"${op}>\u2716</text>`,
|
|
208
|
+
`<text x="72" y="100" text-anchor="middle" font-family="Arial,sans-serif" font-size="28" font-weight="bold" fill="${c}"${op}>ESC</text>`,
|
|
209
|
+
].join('');
|
|
210
|
+
return svgFrame(bg, elements);
|
|
211
|
+
}
|
|
212
|
+
export function renderStopButton(active = true) {
|
|
213
|
+
const c = active ? '#ef4444' : '#666666';
|
|
214
|
+
const bg = active ? '#2d1010' : '#1a0a0a';
|
|
215
|
+
const op = active ? '' : ' opacity="0.4"';
|
|
216
|
+
const elements = [
|
|
217
|
+
`<text x="72" y="62" text-anchor="middle" font-family="Arial,sans-serif" font-size="32" fill="${c}"${op}>\u25A0</text>`,
|
|
218
|
+
`<text x="72" y="100" text-anchor="middle" font-family="Arial,sans-serif" font-size="28" font-weight="bold" fill="${c}"${op}>STOP</text>`,
|
|
219
|
+
].join('');
|
|
220
|
+
return svgFrame(bg, elements);
|
|
221
|
+
}
|
|
222
|
+
// ---- Detail View: Session Info ----
|
|
223
|
+
export function renderDetailInfo(session, state, tool, modelName, mode, displayName, effortLevel) {
|
|
224
|
+
if (!session)
|
|
225
|
+
return renderEmptySlot();
|
|
226
|
+
const agent = session.agentType || 'claude-code';
|
|
227
|
+
const nameForDisplay = displayName ?? session.projectName;
|
|
228
|
+
const fontFam = 'Inter, -apple-system, system-ui, Helvetica Neue, sans-serif';
|
|
229
|
+
const sColor = stateColor(session.state);
|
|
230
|
+
const stateLbl = stateLabel(session.state, agent);
|
|
231
|
+
const gradId = `sd-bg-detail-${agent}`;
|
|
232
|
+
const defs = `
|
|
233
|
+
<linearGradient id="${gradId}" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
234
|
+
<stop offset="0%" stop-color="#151720"/>
|
|
235
|
+
<stop offset="100%" stop-color="#0A0B10"/>
|
|
236
|
+
</linearGradient>
|
|
237
|
+
`;
|
|
238
|
+
const watermark = `<g transform="translate(90, 86)" opacity="0.36">
|
|
239
|
+
${agentLogoIcon(agent, 40, 1, 0, 0)}
|
|
240
|
+
</g>`;
|
|
241
|
+
const leftStrip = `<rect x="8" y="8" width="4" height="128" rx="2" fill="${sColor}"/>`;
|
|
242
|
+
const badgeObj = `
|
|
243
|
+
<rect x="100" y="14" width="28" height="16" rx="8" fill="#ffffff" opacity="0.1" />
|
|
244
|
+
<text x="114" y="25" font-size="10" font-weight="700" text-anchor="middle" fill="#A1A1AA" font-family="${fontFam}">INFO</text>
|
|
245
|
+
`;
|
|
246
|
+
const toolDisplay = tool ? `\u25B6 ${truncate(tool, 18)}` : stateLbl;
|
|
247
|
+
const elements = [
|
|
248
|
+
`<defs>${defs}</defs>`,
|
|
249
|
+
`<rect width="${SIZE}" height="${SIZE}" rx="16" fill="url(#${gradId})"/>`,
|
|
250
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="#1C1F2E" opacity="0.8"/>`,
|
|
251
|
+
leftStrip,
|
|
252
|
+
watermark,
|
|
253
|
+
badgeObj,
|
|
254
|
+
// Title
|
|
255
|
+
`<text x="20" y="34" font-size="18" font-weight="800" text-anchor="start" fill="#ffffff" font-family="${fontFam}">${escXml(truncate(nameForDisplay, 10))}</text>`,
|
|
256
|
+
// Model/Mode — effort renders inline with model (e.g. "Opus 4.7 · max")
|
|
257
|
+
// so the permission-mode chip below keeps its y=74 slot.
|
|
258
|
+
(modelName && agent !== 'openclaw') ? `<text x="20" y="56" font-size="12" font-weight="600" text-anchor="start" fill="#94a3b8" font-family="${fontFam}">${escXml(formatModelEffort(modelName, effortLevel, 17))}</text>` : '',
|
|
259
|
+
(mode && mode !== 'default' && agent !== 'openclaw') ? `<text x="20" y="74" font-size="11" font-weight="700" text-anchor="start" fill="#a78bfa" font-family="${fontFam}">${escXml(mode.toUpperCase())}</text>` : '',
|
|
260
|
+
// Tool/State
|
|
261
|
+
`<text x="20" y="120" font-size="12" font-weight="700" text-anchor="start" fill="${tool ? '#fbbf24' : sColor}" font-family="${fontFam}">${escXml(toolDisplay)}</text>`,
|
|
262
|
+
].join('');
|
|
263
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">${elements}</svg>`;
|
|
264
|
+
}
|
|
265
|
+
// ---- Detail View: Option Button ----
|
|
266
|
+
export function renderOptionButton(option, index) {
|
|
267
|
+
const label = option.label || `Option ${index + 1}`;
|
|
268
|
+
const lines = wrapTextByWidth(label, MAX_TEXT_PX, 16);
|
|
269
|
+
const lineHeight = 20;
|
|
270
|
+
const startY = lines.length === 1 ? 76 : 76 - ((lines.length - 1) * lineHeight) / 2;
|
|
271
|
+
// Slot number (top-right)
|
|
272
|
+
const slotNum = `<text x="${SIZE - 10}" y="18" text-anchor="end" font-family="Arial,sans-serif" font-size="13" fill="#ffffff" opacity="0.25">${index + 1}</text>`;
|
|
273
|
+
const textEls = lines.slice(0, 3).map((line, i) => `<text x="72" y="${startY + i * lineHeight}" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="bold" fill="#ffffff">${escXml(line)}</text>`).join('');
|
|
274
|
+
// Use different bg colors for visual distinction
|
|
275
|
+
const colors = ['#1e3a5f', '#1e3a4a', '#2a1e4a', '#1e4a3a', '#3a1e2a'];
|
|
276
|
+
const bgColor = colors[index % colors.length];
|
|
277
|
+
return svgFrame(bgColor, slotNum + textEls);
|
|
278
|
+
}
|
|
279
|
+
// ---- Detail View: Preset Action Button ----
|
|
280
|
+
export function renderPresetButton(label, iconSvg, color, textColor, subtitle, loading) {
|
|
281
|
+
if (loading) {
|
|
282
|
+
return svgFrame(color, iconSvg);
|
|
283
|
+
}
|
|
284
|
+
const labelEl = `<text x="72" y="100" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="bold" fill="${textColor}">${escXml(label)}</text>`;
|
|
285
|
+
const subEl = subtitle
|
|
286
|
+
? `<text x="72" y="118" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="${textColor}" opacity="0.7">${escXml(truncate(subtitle, 14))}</text>`
|
|
287
|
+
: '';
|
|
288
|
+
return svgFrame(color, iconSvg + labelEl + subEl);
|
|
289
|
+
}
|
|
290
|
+
// ---- Detail View: Info slot (tool, model/mode) ----
|
|
291
|
+
export function renderInfoSlot(label, subtitle) {
|
|
292
|
+
const mainEl = `<text x="72" y="${subtitle ? 68 : 76}" text-anchor="middle" font-family="Arial,sans-serif" font-size="16" font-weight="bold" fill="#94a3b8">${escXml(truncate(label, 18))}</text>`;
|
|
293
|
+
const subEl = subtitle
|
|
294
|
+
? `<text x="72" y="92" text-anchor="middle" font-family="Arial,sans-serif" font-size="12" fill="#64748b">${escXml(truncate(subtitle, 22))}</text>`
|
|
295
|
+
: '';
|
|
296
|
+
return svgFrame('#1a1a1a', mainEl + subEl);
|
|
297
|
+
}
|
|
298
|
+
// ---- SVG Frame ----
|
|
299
|
+
export function svgFrame(bgColor, innerElements) {
|
|
300
|
+
// Use a random ID to prevent SVG constraint clashes
|
|
301
|
+
const gradId = 'frame-bg-' + Math.floor(Math.random() * 1000000);
|
|
302
|
+
const defs = `
|
|
303
|
+
<linearGradient id="${gradId}" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
304
|
+
<stop offset="0%" stop-color="${bgColor}"/>
|
|
305
|
+
<stop offset="100%" stop-color="#0A0A0E"/>
|
|
306
|
+
</linearGradient>
|
|
307
|
+
`;
|
|
308
|
+
return [
|
|
309
|
+
`<svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">`,
|
|
310
|
+
`<defs>${defs}</defs>`,
|
|
311
|
+
`<rect width="${SIZE}" height="${SIZE}" rx="16" fill="url(#${gradId})"/>`,
|
|
312
|
+
`<rect x="8" y="8" width="128" height="128" rx="12" fill="#2C2C2E" opacity="0.6"/>`,
|
|
313
|
+
innerElements,
|
|
314
|
+
`</svg>`,
|
|
315
|
+
].join('');
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=session-slot-renderer.js.map
|