A side pane, In this chat, that lists the to-do list, connectors, context files and skills this chat used

Current publication inventory — 2026-10-24: 135 bilingual posts across10 series (7 Tutorials /96 articles,3 Thoughts /39 essays),147 HTML files (146 enumerated), 466 images,135 feed items and146 sitemap URLs. AI-Core Functional Workflows adds twelve lessons paired with Anirach/ai-core-functional-tutorial,108 offline tests and twelve exercises. Earlier dated measurements below retain their historical context.
The personal site of Dr. Anirach Mingkhwan — Associate Professor at King Mongkut's University of Technology North Bangkok (KMUTNB), PhD (Liverpool John Moores University, UK), researcher in Agentic AI, computer networks, and big data analytics.
🌐 Live: anirach.com
A hand-written static site — seven top-level pages, four per-book detail pages, and 135 self-contained blog posts catalogued on two pages: Tutorials (/blog/, seven technical series) and Thoughts (/thoughts/, thirty-nine essays on living well and working well). No build system, no package manager, no dependencies, no JavaScript framework. Push to main and GitHub Pages publishes it.
| Pages | Home · Tutorials (/blog/) · Thoughts (/thoughts/) · Publications · Books · Projects & Apps · News & Updates |
| Posts | 135, in 10 series across two catalogs, every one bilingual Thai/English |
| Files | 147 HTML files on disk (146 enumerated by the linter; 404.html is deliberately excluded) |
| Stack | Plain HTML5 + CSS3, zero JavaScript. Google Fonts is the only external dependency |
| Hosting | GitHub Pages (classic Jekyll build) on the custom domain anirach.com, fronted by Cloudflare |
| Build step | None |
| Tests | Four scripts, run before every push — check_site.py alone carries 62 cross-file integrity checks. This is the test suite |
| Page | What it holds |
|---|---|
index.html | Single-scroll consultant profile: hero, at-a-glance stats, six services, engagement approach, selected work, about and career, research, free resources, latest news with the featured book, contact |
blog/ | The Tutorials catalog — 96 cards in seven technical series, plus all 135 post files |
thoughts/ | The Thoughts catalog — 39 essay cards in three series, each linking ../blog/<slug>.html |
publications/ | The academic record: the Springer book Libraries in Transformation, 8 book chapters, and a selected-publications table |
books/ | Books & writing: four works — One Day of Light (the free last-lecture event book, EN/TH editions with free PDF downloads served from books/), the published novel Three Old Men: The Last Conversation, and two complete bilingual manuscripts — each with its own detail page |
projects/ | Live apps (each verified working before it ships) and research-code repositories |
news/ | Reverse-chronological timeline of publications, talks and appointments, plus a career timeline |
The posts never move. Every post is blog/<slug>.html, including the 39 essays that /thoughts/ catalogues — the 2026-09-08 split separated the two catalogs, not the files.
books/ was one "Books & Writing" page until 2026-08-23, when it split: academic content moved to the new publications/, and books/ became the fiction section with one detail page per book. On 2026-08-24 it gained a fourth work, the Last Lecture companion book One Day of Light, whose EN/TH PDFs are downloadable for free from books/.
script.js is gone — deleted 2026-08-26. The site loads no executable JavaScript at all, and check_site.py INV-38 fails the build on any <script> that is not application/ld+json (schema.org metadata, which the browser parses as data and never executes — 128 pages carry one). Each of the script's four jobs has a CSS replacement in style.css: the scroll-reveal and the nav scroll state are scroll-driven CSS animations (animation-timeline: view() / scroll(root)), the landing page's mobile menu is .nav__links:target, and anchor scrolling is native scroll-behavior: smooth. The other pages' mobile menu is a pure-CSS checkbox toggle — a second mechanism, also without JavaScript.
Both are static, zero-JavaScript and generated by scripts/reindex_blog.py — re-run it rather than hand-ordering cards. Each is a hero, a sticky chip strip, a "Start here" feature, a row of series tiles, then one numbered-row-card section per series. There is no filtering, sorting or search UI.
Tutorials — /blog/, hero reads 7 Series · 96 Articles
| Series | Posts | Navigation |
|---|---|---|
| ⧉ AI-Core Functional Workflows | 12 | generated12-chip strip · GitHub code, tests and exercises |
| 🛡️ Engineering AI-Core Systems | 10 | chip strip · generated |
| 💻 Hermes Desktop Hands-On | 7 | chip strip · generated |
| 🧭 AI Transformation for Organizations | 20 | grouped chip strip (Reframe · Redesign · Engineer · Lead) · generated |
| ⚡ Hermes Agent in Practice | 10 | chip strip |
| 🤖 OpenClaw for Organizations | 13 | seven are a numbered chip-strip series; six stand alone with no nav |
| 🔧 DevOps & Vibe Coding | 24 | a single prev/next chain |
Thoughts — /thoughts/, hero reads 3 Series · 39 Essays
| Series | Essays | Navigation |
|---|---|---|
| 🌱 Wisdom for a Good Life | 20 | grouped chip strip, four arcs of five (Self · Mind · Work · Others) · generated |
| 🧭 Working Philosophies | 10 | chip strip, one working week Monday to Friday · generated |
| 🌅 Life Thought & Philosophy | 9 | chip strip, one day in three parts (Morning · Noon · Twilight) |
Five of the nine series are generated from a manifest plus per-post content sheets: python3 scripts/build_series.py --series <name>, with manifests in scripts/series/ (ai-core, ai-transformation, good-life, hermes-desktop, working). For those, the manifest and the sheets are the edit surface — never the emitted post.
Every post is bilingual. All 123 carry a pure-CSS Thai ⇄ English switch: a ไทย · English pill in the hero swaps between two complete tracks of the same article. Thai is the default, there is no JavaScript, and the page-level <html lang="th"> never changes — the English track is lang="en" inside it. The seven top-level pages and the four book detail pages are lang="en" chrome and wrap their Thai passages in <span lang="th">.
The Thoughts essays are written in a different register from the tutorials — literary Thai in the author's own voice, not code-switched technical prose. The brief, with ten rules and worked before/after pairs, is .claude/skills/blog-post/references/thai-essay-voice.md.
.
├── index.html # Landing page — the ONLY file that loads style.css
├── style.css # Landing-page styles; carries the canonical :root token block
├── _config.yml # Jekyll: keeps internal working docs out of the published site
├── CNAME # anirach.com
├── sitemap.xml # 134 URLs, generated · feed.xml — 123 items, generated · llms.txt · robots.txt
├── blog/ # index.html (the Tutorials catalog, 96 cards) + all 123 self-contained posts
├── thoughts/ # index.html (the Thoughts catalog — 39 essay cards linking ../blog/)
├── books/ # index.html + 4 per-book detail pages + 3 free PDFs, all self-contained
├── publications/ projects/ news/ # one self-contained index.html each
├── images/ # 431 files — 124 covers (800×800) + 8 book faces, 123 card thumbs (144×144),
│ # 130 share cards (1200×630), diagrams, series figures, posters, profile photo
├── scripts/ # 13 generators and sweeps (build_series, reindex_blog, gen_feed, gen_sitemap,
│ # make_cover, make_figure, bilingualize, check_visibility, …)
├── docs/ # design spec, implementation plan, OpenClaw runbook (not published)
└── .claude/skills/ # the four maintenance skills (not published)
The single most important fact before editing:
index.html ──▶ style.css (the ONLY consumer of it)
blog/index.html ──▶ its own <style> block, no JS
blog/<post>.html ──▶ its own <style> block, no JS × 123
thoughts/ books/ (index + 4 detail) publications/ projects/ news/ 404.html ──▶ same × 10
Every page embeds its complete stylesheet. There is no shared partial, template engine or token file, so a "global" change means editing N files by hand — and nothing tells you when file 23 of 135 got missed. That is what the linter is for. The compensating upside: blast radius is exactly one file.
No install, no build. Serve the repository root:
python3 -m http.server 8000 # → http://localhost:8000
Serve the root, not
blog/. Every blog page references images as../images/….
Known local-dev trap. The eight chip-strip series — 93 posts in all — link to each other with root-absolute, extensionless URLs (
/blog/openclaw-101). GitHub Pages resolves those;http.serverdoes not and returns 404. That is not a regression.
Run all four from the repo root before pushing. All must pass:
python3 .claude/skills/site-check/scripts/check_site.py # 62 cross-file integrity checks
python3 scripts/check_visibility.py --strict # search/AI-visibility, JSON-LD, metadata
python3 docs/openclaw/check-news-sync.py # news↔homepage sync, provenance, 4 counters
python3 .claude/skills/blog-post/assets/verify-wiring.py # blog post wiring
check_site.py runs 62 checks — 43 fail-severity, 17 warn, 2 info — and exits 0 when no fail-severity violation appears. Its baseline of pre-existing debt is empty since 2026-08-26 — the tree is clean (0 new, 0 known), so any violation it prints is new and any fail-severity one blocks the push. INV-25 fails the build if a baseline entry is ever added and goes stale, so the safety net cannot silently rot. INV-26 (added with the books split) ties every section-directory detail page to its own index.html: an orphan detail page, or an index card linking a file that does not exist, fails the build.
check-news-sync.py verifies the homepage strip mirrors the three newest news items, that every news item carries a <!-- source: … --> provenance comment, and that all four hand-typed counters match reality: news/index.html "7 updates", publications/index.html "8 chapters", and books/index.html "1 novel" and "2 complete" (it strips HTML comments first, so a commented-out card cannot satisfy a counter).
feed.xml and sitemap.xml are generated, not hand-written — scripts/gen_feed.py and scripts/gen_sitemap.py. INV-31 and INV-32 fail the build when either drifts from the catalogs. Run the sitemap in the commit after a content change, so the git lastmod dates exist.
git push origin main
That is the whole pipeline; GitHub Pages rebuilds in 1–3 minutes. _config.yml excludes docs/ and CLAUDE.md from the published output — they stay in the repository but are not served. Anything beginning with . or _ (including .claude/) is omitted by Jekyll automatically.
Cloudflare caches HTML for 10 minutes and assets for 4 hours. After a deploy, append
?cb=$RANDOMto check the real state before diagnosing a problem that is not there — and remember your own browser holds its copy for the same 10 minutes, so a stale tab needs a hard reload rather than a bug report.
Two measured costs were paid down on 2026-09-10, and both are easy to reintroduce:
Inter:wght@300..900 gets one variable file; the semicolon form Inter:wght@300;400;…;900 makes the API serve one static file per weight — 7 files and 331 KB for the latin subset against 1 file and 47 KB. Switching saved 189 KB per page, 56% of the font bytes. Sarabun keeps the semicolon form**: it has no variable version, a range request returns HTTP 400, and all five of its static weights are used.srcset. The row card renders its cover in a 72px box, so an 800×800 source was ~11× oversampled. /blog/ went from 3.63 MB to 0.42 MB, /thoughts/ from 2.11 MB to 0.38 MB.Both are documented with their measurements in the a11y-perf skill (R8b and R1b).
A post is not one file — it is a file plus a cover plus a share card plus a card plus counters plus its neighbours' nav links plus a feed item, a sitemap entry and an llms.txt line, in two language tracks, with no build step to catch a miss. The full recipe, including which of the four navigation patterns applies, is in .claude/skills/blog-post/SKILL.md. Start from .claude/skills/page-design/assets/post-template.html — the repo's single canonical template. For one of the five generated series, add a manifest row and run build_series.py instead; never hand-edit those posts.
Four skills in .claude/skills/ carry the verified detail:
| Skill | Covers |
|---|---|
| page-design | The house visual system — canonical tokens, type scale, component vocabulary, approved hero gradients, and the anti-patterns this repo has been burned by |
| blog-post | Adding, editing or removing a post without breaking the hand-wired navigation; plus the Thai essay voice brief |
| a11y-perf | Accessibility and performance rules with this site's real measured numbers |
| site-check | The linter, what every check means, and how to repair each failure |
Every number in those skills is load-bearing: a change that invalidates one must update it in the same commit. A confidently wrong measurement is worse than none, because it gets acted on.
News updates have their own runbook at docs/openclaw/latest-updates-runbook.md, written for an autonomous agent. Its gate enforces that every news item carries a verified source — no structural check can tell a true item from an invented one, so instead an item cannot exist without a stated source.
Open to research collaborations, speaking engagements, and academic partnerships.
No LICENSE file is present. Content and code are © Anirach Mingkhwan; all rights reserved by default.
Twelve bilingual lessons and the matching code are maintained together: Anirach/ai-core-functional-tutorial. The offline lab ZIP is downloads/ai-core-functional-lab.zip. The series manifest is scripts/series/ai-core-functional.json; article source links pin the reviewed companion commit. Default fixtures require no SDK install, API key or paid calls. Run the companion tests/advertised commands and the four website checks when revising. No additional reuse license is granted by the companion's public availability.
hooks/register.tsx 903 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register, SessionMessage } from 'claude-code'
3
4import type { CallRow, ConnectorRow, FileRow, Inventory, Plan, PlanStep, SkillRow } from '../types'
5import { CONNECTOR_NAMES, connectorName as nameOf, splitTool } from './connectors'
6import { LOGOS } from './logos'
7
8const PLUGIN = 'chat-inventory'
9const NAME = 'chat-inventory'
10const PANE = 'chat-inventory'
11const TITLE = 'In this chat'
12const MAX_ROWS = 40
13const MAX_CALLS = 60
14// Context files show in a window this many rows tall; Up and Down move it.
15const FILE_WINDOW = 10
16const FILE_STEP = 5
17const SECTIONS = ['todo', 'connectors', 'files', 'skills'] as const
18const OFF_LINE = 'Turned off. Open /mods to turn it on.'
19const NO_PLAN = 'No to-do list yet. Claude makes one for jobs with 3 or more steps.'
20// The plan tool helper-desk registers, and Claude's built-in list tools, all feed the To-do section.
21const PLAN_TOOL = 'mcp__helper-desk__plan'
22const PLAN_TOOLS = new Set([PLAN_TOOL, 'TodoWrite', 'TaskCreate', 'TaskUpdate'])
23
24const ACCENT = '#d97757'
25const INFO = '#2563eb'
26const GOOD = '#16a34a'
27
28const EMPTY: Inventory = { connectors: [], files: [], skills: [] }
29const inv = atom({ plugin: 'chat-inventory', key: 'inv' } as const, EMPTY)
30const NO_STEPS: Plan = { title: '', steps: [], updatedAt: 0 }
31const planAtom = atom({ plugin: 'chat-inventory', key: 'plan' } as const, NO_STEPS)
32const openKey = atom({ plugin: 'chat-inventory', key: 'open' } as const, '')
33const offAtom = atom({ plugin: 'chat-inventory', key: 'off' } as const, false)
34// Sections the person closed, and the first context file row shown. Kept per chat in $.state.
35const foldedAtom = atom({ plugin: 'chat-inventory', key: 'folded' } as const, [] as string[])
36const fileTopAtom = atom({ plugin: 'chat-inventory', key: 'fileTop' } as const, 0)
37
38// Logo keys whose slug differs from the name.
39const ALIAS: Record<string, string> = { googleworkspace: 'google', metaads: 'meta' }
40
41// CLI tools in Bash that count as connectors. Matched as a command word.
42const CLI_RE = /(?:^|[;&|(\n`]|\bdo\b|\bthen\b|\$\()\s*(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(gws|firecrawl|youtube-pp-cli|browser-harness|agent-browser)\b([^;&|\n`)]*)/g
43const GWS: Record<string, string> = {
44 gmail: 'Gmail',
45 calendar: 'Google Calendar',
46 drive: 'Google Drive',
47 sheets: 'Google Sheets',
48 docs: 'Google Docs',
49}
50const CLI_NAME: Record<string, string> = {
51 firecrawl: 'Firecrawl',
52 'youtube-pp-cli': 'YouTube',
53 'browser-harness': 'Browser',
54 'agent-browser': 'Browser',
55}
56
57// Input keys worth showing, best first.
58const ARG_KEYS = [
59 'query', 'q', 'search', 'searchQuery', 'keyword', 'keywords', 'url', 'file_path', 'path', 'filename', 'fileName',
60 'name', 'title', 'subject', 'transcriptId', 'threadId', 'messageId', 'documentId', 'spreadsheetId', 'fileId',
61 'pageId', 'eventId', 'calendarId', 'id', 'email', 'channel', 'prompt', 'skill', 'command',
62]
63const NOT_ARGS = new Set(['tool', 'tool_use_id', 'agentId', 'hook_event_name', 'session_id', 'transcript_path', 'cwd', 'permission_mode', 'surface'])
64
65// Module variables reset on a reload; the lists live in $.state.
66let home = ''
67let seq = 0
68let autoOpened = false
69let off = false
70// "chat-inventory:hidden": true in switches.json closes the pane and stops it opening by itself.
71let hidden = false
72let switchTimer: unknown
73const seen = new Set<string>()
74let skillNames = new Set<string>()
75
76const slug = (name: string) => {
77 const s = name.toLowerCase().replace(/[^a-z0-9]/g, '')
78 return ALIAS[s] ?? s
79}
80
81const clip = (s: string, n = 60) => {
82 const flat = s.replace(/\s+/g, ' ').trim()
83 return flat.length > n ? `${flat.slice(0, n - 1)}…` : flat
84}
85
86const base = (p: string) => (/^[~/.]/.test(p) && p.includes('/') ? p.slice(p.replace(/\/+$/, '').lastIndexOf('/') + 1) : p)
87
88/** The friendly connector name for an MCP tool, or '' when the tool is not a connector's. */
89function connectorName(tool: string): string {
90 if (!tool.startsWith('mcp__')) return ''
91 const { server, name } = splitTool(tool)
92 if (!server || server.startsWith('ccd_')) return ''
93 return nameOf(server, name)
94}
95
96/** "fireflies_get_transcripts" for Fireflies becomes "get transcripts". */
97function humanTool(tool: string, name: string): string {
98 const raw = tool.split('__').slice(2).join('__') || tool
99 const words = raw.split(/[-_\s]+/).filter(Boolean).map(w => w.toLowerCase())
100 const own = new Set([slug(name), ...name.toLowerCase().split(/\s+/)])
101 while (words.length > 1 && (own.has(words[0]!) || /^s\d+$/.test(words[0]!))) words.shift()
102 return words.join(' ')
103}
104
105/** The main argument of a call, short. */
106function summaryOf(input: Record<string, unknown>): string {
107 for (const k of ARG_KEYS) {
108 const v = input[k]
109 if (typeof v === 'string' && v.trim()) return clip(base(v))
110 if (typeof v === 'number') return String(v)
111 }
112 for (const [k, v] of Object.entries(input)) {
113 if (NOT_ARGS.has(k)) continue
114 if (typeof v === 'string' && v.trim()) return clip(base(v))
115 }
116 for (const [k, v] of Object.entries(input)) {
117 if (NOT_ARGS.has(k)) continue
118 if (typeof v === 'number' || typeof v === 'boolean') return clip(`${k} ${v}`)
119 }
120 return ''
121}
122
123/** The main argument of a CLI line: a query or id in --params, else the rest of the line. */
124function cliSummary(rest: string): string {
125 const m = /\\?"(q|query|id|fileId|spreadsheetId|documentId|calendarId|url)\\?"\s*:\s*\\?"([^"\\]+)/.exec(rest)
126 if (m) return clip(m[2]!)
127 const url = /https?:\/\/\S+/.exec(rest)
128 if (url) return clip(url[0])
129 return clip(rest.replace(/<<-?\s*'?\w+'?/, '').replace(/^\s*(?:[a-z][a-zA-Z-]*\s*)+/, ''))
130}
131
132type CallHit = { kind: 'connector'; name: string; call: Omit<CallRow, 'at'> }
133type Hit = CallHit | { kind: 'file' | 'skill'; name: string; always?: boolean }
134
135/** Connector calls inside one Bash command line. */
136function cliHits(command: string): CallHit[] {
137 const out: CallHit[] = []
138 const done = new Set<string>()
139 for (const m of command.matchAll(CLI_RE)) {
140 const cmd = m[1]!
141 const rest = m[2] ?? ''
142 let name = CLI_NAME[cmd] ?? ''
143 let tool = ''
144 if (cmd === 'gws') {
145 const svc = /^\s*([a-z]+)/.exec(rest)?.[1] ?? ''
146 name = GWS[svc] ?? 'Google Workspace'
147 const words = rest
148 .trim()
149 .split(/\s+/)
150 .filter(w => /^[a-z][a-zA-Z]*$/.test(w))
151 tool = (GWS[svc] ? words.slice(1) : words).slice(0, 3).join(' ') || svc || 'run'
152 } else if (cmd === 'firecrawl' || cmd === 'youtube-pp-cli') {
153 tool = /^\s*([a-z][a-z-]*)/.exec(rest)?.[1]?.replace(/-/g, ' ') ?? 'run'
154 } else {
155 tool = 'run script'
156 }
157 const summary = cmd === 'browser-harness' || cmd === 'agent-browser' ? '' : cliSummary(rest)
158 const id = `${name}|${tool}|${summary}`
159 if (done.has(id)) continue
160 done.add(id)
161 out.push({ kind: 'connector', name, call: { tool, summary, cli: true } })
162 }
163 return out
164}
165
166/** What one tool call adds to the lists. */
167function hitsOf(tool: string, input: Record<string, unknown>): Hit[] {
168 // The plan tool is the To-do section, not a connector.
169 if (tool === PLAN_TOOL) return []
170 const connector = connectorName(tool)
171 if (connector) return [{ kind: 'connector', name: connector, call: { tool: humanTool(tool, connector), summary: summaryOf(input), cli: false } }]
172 if (tool === 'Bash' && typeof input.command === 'string') return cliHits(input.command)
173 if (tool === 'Read' && typeof input.file_path === 'string') {
174 const fp = input.file_path
175 // A skill file read on purpose is a skill, named for its folder.
176 const skill = /\/([^/]+)\/SKILL\.md$/.exec(fp)
177 if (skill) return [{ kind: 'skill', name: skill[1]! }]
178 // Claude's own spill files (big tool results, temp copies) are not context the person gave it.
179 if (/\/tool-results\/|^\/private\/tmp\/|^\/tmp\/|\/\.claude\/projects\/[^/]+\/[0-9a-f-]{36}\//.test(fp)) return []
180 return [{ kind: 'file', name: fp }]
181 }
182 if (tool === 'Skill' && typeof input.skill === 'string' && input.skill) return [{ kind: 'skill', name: input.skill.replace(/^\//, '') }]
183 return []
184}
185
186const tilde = (p: string) => (home && p.startsWith(home) ? `~${p.slice(home.length)}` : p)
187const plural = (n: number, word: string) => `${n} ${word}${n === 1 ? '' : 's'}`
188const pad = (n: number) => String(n).padStart(2, '0')
189const clockTime = (ms: number) => {
190 if (!ms) return ''
191 const d = new Date(ms)
192 return `${pad(d.getHours())}:${pad(d.getMinutes())}`
193}
194
195async function logError($: EngineInterface, where: string, err: unknown) {
196 try {
197 const path = `${home}/.claude/mods-logs/${PLUGIN}.log`
198 let old = ''
199 try {
200 old = String(await $.fs.read(path))
201 } catch {
202 await $.process.run(['mkdir', '-p', `${home}/.claude/mods-logs`])
203 }
204 const line = `${new Date(await $.clock.now()).toISOString()} ${where}: ${String(err instanceof Error ? err.message : err)}\n`
205 await $.fs.write(path, old + line)
206 } catch {
207 // Nowhere left to report it.
208 }
209}
210
211function bumpConnector(rows: ConnectorRow[], hit: CallHit, at: number, time: number): ConnectorRow[] {
212 const key = slug(hit.name)
213 const old = rows.find(r => r.key === key)
214 const rest = rows.filter(r => r.key !== key)
215 const calls = [...(old?.calls ?? []), { ...hit.call, at: time }].slice(-MAX_CALLS)
216 return [
217 ...rest,
218 {
219 key,
220 name: hit.name,
221 count: (old?.count ?? 0) + 1,
222 seq: at,
223 cli: (old?.cli ?? false) || hit.call.cli,
224 mcp: (old?.mcp ?? false) || !hit.call.cli,
225 calls,
226 },
227 ]
228}
229
230function bumpSkill(rows: SkillRow[], name: string, at: number, always: boolean): SkillRow[] {
231 const old = rows.find(r => r.name === name)
232 const rest = rows.filter(r => r.name !== name)
233 if (always) return [...rest, { name, count: old?.count ?? 0, seq: old?.seq ?? at, always: true }]
234 return [...rest, { name, count: (old?.count ?? 0) + 1, seq: at, always: old?.always ?? false }]
235}
236
237type Stamped = { hit: Hit; at: number; time: number }
238
239function apply(list: Inventory, hits: Stamped[]): Inventory {
240 let { connectors, files, skills } = list
241 for (const { hit, at, time } of hits) {
242 if (hit.kind === 'connector') connectors = bumpConnector(connectors, hit as CallHit, at, time)
243 else if (hit.kind === 'skill') skills = bumpSkill(skills, hit.name, at, hit.always === true)
244 else files = [...files.filter(f => f.path !== hit.name), { path: hit.name, auto: false, seq: at }]
245 }
246 return { connectors, files, skills }
247}
248
249const STATUSES = new Set(['pending', 'in_progress', 'completed'])
250const statusOf = (v: unknown): PlanStep['status'] => (typeof v === 'string' && STATUSES.has(v) ? (v as PlanStep['status']) : 'pending')
251const str = (v: unknown) => (typeof v === 'string' ? v.trim() : '')
252
253/** Steps from a list of objects, reading the text from the first key that has it. */
254function stepsOf(raw: unknown, textKeys: string[]): PlanStep[] {
255 if (!Array.isArray(raw)) return []
256 const out: PlanStep[] = []
257 for (const item of raw) {
258 if (!item || typeof item !== 'object') continue
259 const o = item as Record<string, unknown>
260 const text = textKeys.map(k => str(o[k])).find(Boolean) ?? ''
261 if (!text) continue
262 const active = str(o.activeForm)
263 out.push({ text, status: statusOf(o.status), ...(active ? { active } : {}) })
264 }
265 return out
266}
267
268/** The plan after one main-chat call to a plan tool, or null when the call changes nothing. */
269function planAfter(cur: Plan, tool: string, input: Record<string, unknown>, result: unknown, time: number): Plan | null {
270 if (tool === 'TodoWrite') return { title: cur.title, steps: stepsOf(input.todos, ['content']), updatedAt: time }
271 if (tool === PLAN_TOOL) {
272 const title = typeof input.title === 'string' ? input.title.trim() : cur.title
273 return { title, steps: stepsOf(input.steps, ['text']), updatedAt: time }
274 }
275 if (tool === 'TaskCreate') {
276 const text = str(input.subject)
277 if (!text) return null
278 const made = (result as { task?: { id?: unknown } } | undefined)?.task?.id
279 const id = typeof made === 'string' || typeof made === 'number' ? String(made) : String(cur.steps.length + 1)
280 const active = str(input.activeForm)
281 return { ...cur, steps: [...cur.steps, { text, status: 'pending', id, ...(active ? { active } : {}) }], updatedAt: time }
282 }
283 if (tool === 'TaskUpdate') {
284 const id = str(input.taskId) || (typeof input.taskId === 'number' ? String(input.taskId) : '')
285 let at = cur.steps.findIndex(st => st.id === id)
286 if (at < 0 && /^\d+$/.test(id) && !cur.steps.some(st => st.id)) at = Number(id) - 1
287 const old = cur.steps[at]
288 if (!old) return null
289 if (input.status === 'deleted') return { ...cur, steps: cur.steps.filter((_, i) => i !== at), updatedAt: time }
290 const text = str(input.subject) || old.text
291 const active = str(input.activeForm) || old.active
292 const status = input.status === undefined ? old.status : statusOf(input.status)
293 const steps = cur.steps.map((st, i) => (i === at ? { ...st, text, status, ...(active ? { active } : {}) } : st))
294 return { ...cur, steps, updatedAt: time }
295 }
296 return null
297}
298
299/** Watches a plan tool call in the main chat, so the list works with helper-desk off. */
300async function watchPlan($: EngineInterface, call: Record<string, unknown> & { tool: string }, result: unknown, time: number) {
301 if (!PLAN_TOOLS.has(call.tool) || call.agentId) return false
302 let changed = false
303 await update($, planAtom, cur => {
304 const nextPlan = planAfter(cur, call.tool, call, result, Math.max(time, cur.updatedAt + 1))
305 if (!nextPlan) return cur
306 changed = true
307 return nextPlan
308 })
309 return changed
310}
311
312const planPath = (sid: string) => `${home}/.claude/mods-state/plan-${sid}.json`
313
314/** Reads the shared plan file for this chat; it wins when it is newer than what the pane has. Never throws. */
315async function readPlan($: EngineInterface) {
316 try {
317 const path = planPath(await $.session.id())
318 if (!(await $.fs.exists(path))) return
319 const json = JSON.parse(String(await $.fs.read(path))) as Record<string, unknown>
320 const at = typeof json.updatedAt === 'string' ? Date.parse(json.updatedAt) : typeof json.updatedAt === 'number' ? json.updatedAt : NaN
321 if (!Number.isFinite(at)) return
322 const cur = await read($, planAtom)
323 if (at <= cur.updatedAt) return
324 // Keep TodoWrite's present-tense text and TaskCreate's ids for steps the file also has.
325 const steps = stepsOf(json.steps, ['text']).map(st => {
326 const was = cur.steps.find(o => o.text === st.text)
327 return { ...st, ...(was?.active && !st.active ? { active: was.active } : {}), ...(was?.id ? { id: was.id } : {}) }
328 })
329 const title = typeof json.title === 'string' ? json.title.trim() : ''
330 await update($, planAtom, () => ({ title, steps, updatedAt: at }))
331 } catch (err) {
332 await logError($, 'plan', err)
333 }
334}
335
336/** Splits text into lines no wider than `width` columns, breaking at spaces. */
337function wrapLines(text: string, width: number): string[] {
338 const w = Math.max(8, width)
339 const lines: string[] = []
340 let cur = ''
341 for (const word of text.replace(/\s+/g, ' ').trim().split(' ')) {
342 let rest = word
343 while (rest.length > w) {
344 if (cur) lines.push(cur)
345 cur = ''
346 lines.push(rest.slice(0, w))
347 rest = rest.slice(w)
348 }
349 if (!rest) continue
350 if (!cur) cur = rest
351 else if (cur.length + 1 + rest.length <= w) cur += ` ${rest}`
352 else {
353 lines.push(cur)
354 cur = rest
355 }
356 }
357 if (cur || !lines.length) lines.push(cur)
358 return lines
359}
360
361async function openPane($: EngineInterface) {
362 await $.ui.open({ id: PANE, title: TITLE })
363}
364
365async function record($: EngineInterface, id: string, hits: Hit[]) {
366 if (!hits.length) return
367 if (id) {
368 if (seen.has(id)) return
369 seen.add(id)
370 }
371 const time = await $.clock.now()
372 const stamped = hits.map(hit => {
373 seq += 1
374 return { hit, at: seq, time }
375 })
376 await update($, inv, list => apply(list, stamped))
377 autoOpen($)
378}
379
380/** Opens the pane the first time the chat uses something, unless it is hidden. */
381function autoOpen($: EngineInterface) {
382 if (autoOpened || hidden) return
383 autoOpened = true
384 void openPane($).catch(err => logError($, 'open', err))
385}
386
387async function loadSkillNames($: EngineInterface) {
388 const names = new Set<string>()
389 try {
390 const usage = await $.session.usage({ breakdown: 'summary' })
391 for (const s of usage.context.breakdown?.skills?.skillFrontmatter ?? []) names.add(s.name)
392 } catch {
393 // No breakdown: fall back to the command list below.
394 }
395 if (names.size) skillNames = names
396 return names
397}
398
399/** True when a typed slash command is a skill. */
400async function isSkill($: EngineInterface, name: string) {
401 if (!skillNames.size) await loadSkillNames($)
402 if (skillNames.has(name)) return true
403 if (skillNames.size) return false
404 const cmds = await $.command.list()
405 return cmds.some(c => c.name === name && c.source === 'user')
406}
407
408const skillOfPath = (p: string) => /\/([^/]+)\/SKILL\.md$/.exec(p)?.[1] ?? ''
409
410/** Memory files the chat loaded at start. A SKILL.md among them is a skill, always loaded. */
411async function loadMemoryFiles($: EngineInterface) {
412 const usage = await $.session.usage({ breakdown: 'summary' })
413 const b = usage.context.breakdown
414 if (!b) return
415 for (const s of b.skills?.skillFrontmatter ?? []) skillNames.add(s.name)
416 const all = b.memoryFiles.map(m => m.path).filter(Boolean)
417 const skills = all.map(skillOfPath).filter(Boolean)
418 const paths = all.filter(p => !skillOfPath(p))
419 if (!paths.length && !skills.length) return
420 await update($, inv, list => {
421 const have = new Set(list.files.map(f => f.path))
422 const added: FileRow[] = paths.filter(p => !have.has(p)).map((p, i) => ({ path: p, auto: true, seq: -1000 + i }))
423 const files = list.files.filter(f => !skillOfPath(f.path)).map(f => (paths.includes(f.path) ? { ...f, auto: true } : f))
424 let rows = list.skills
425 skills.forEach((name, i) => {
426 rows = bumpSkill(rows, name, -2000 + i, true)
427 })
428 return { ...list, files: [...files, ...added], skills: rows }
429 })
430}
431
432/** tool_use id to the time it was written, from this chat's transcript file. */
433async function callTimes($: EngineInterface): Promise<Map<string, number>> {
434 const times = new Map<string, number>()
435 try {
436 const sid = await $.session.id()
437 const cwd = await $.session.cwd()
438 const path = `${home}/.claude/projects/${cwd.replace(/[^a-zA-Z0-9]/g, '-')}/${sid}.jsonl`
439 if (!(await $.fs.exists(path))) return times
440 const text = String(await $.fs.read(path))
441 for (const line of text.split('\n')) {
442 if (!line.includes('"tool_use"')) continue
443 const ts = /"timestamp":"([^"]+)"/.exec(line)?.[1]
444 const ms = ts ? Date.parse(ts) : NaN
445 if (!Number.isFinite(ms)) continue
446 for (const m of line.matchAll(/"type":"tool_use","id":"([^"]+)"/g)) times.set(m[1]!, ms)
447 }
448 } catch {
449 // Times stay blank for older calls.
450 }
451 return times
452}
453
454const SLASH_RE = /<command-name>\/?([\w:.-]+)<\/command-name>|^\/([\w:.-]+)/
455
456async function seed($: EngineInterface) {
457 const main = await $.session.messages()
458 const all: SessionMessage[] = [...main]
459 for (const m of main) {
460 for (const u of m.toolUses) {
461 if (!u.agentId) continue
462 const child = await $.session.messages({ agentId: u.agentId })
463 if (Array.isArray(child)) all.push(...child)
464 }
465 }
466 // Plan calls already in the chat, oldest first, stamped old so a newer plan file still wins.
467 let plan = await read($, planAtom)
468 let planChanged = false
469 for (const m of main) {
470 for (const u of m.toolUses) {
471 if (u.agentId || !PLAN_TOOLS.has(u.tool)) continue
472 const nextPlan = planAfter(plan, u.tool, u.input, undefined, plan.updatedAt + 1)
473 if (nextPlan) {
474 plan = nextPlan
475 planChanged = true
476 }
477 }
478 }
479 if (planChanged) await update($, planAtom, cur => (cur.updatedAt >= plan.updatedAt ? cur : plan))
480 const times = all.some(m => m.toolUses.length) ? await callTimes($) : new Map<string, number>()
481 const hits: Stamped[] = []
482 for (const m of all) {
483 if (m.role === 'user' && typeof m.text === 'string') {
484 const found = SLASH_RE.exec(m.text.trim())
485 const name = found?.[1] ?? found?.[2]
486 if (name && (await isSkill($, name))) {
487 seq += 1
488 hits.push({ hit: { kind: 'skill', name }, at: seq, time: 0 })
489 }
490 }
491 for (const u of m.toolUses) {
492 if (seen.has(u.tool_use_id)) continue
493 const found = hitsOf(u.tool, u.input)
494 if (!found.length) continue
495 seen.add(u.tool_use_id)
496 for (const hit of found) {
497 seq += 1
498 hits.push({ hit, at: seq, time: times.get(u.tool_use_id) ?? 0 })
499 }
500 }
501 }
502 // A reload of a chat that already used things does not pop the pane open again.
503 if (hits.length) autoOpened = true
504 if (hits.length) await update($, inv, list => apply(list, hits))
505}
506
507const HIDE_KEY = `${NAME}:hidden`
508const switchesPath = () => `${home}/.claude/mods/switches.json`
509
510async function readSwitches($: EngineInterface): Promise<Record<string, unknown>> {
511 if (!(await $.fs.exists(switchesPath()))) return {}
512 const json = JSON.parse(String(await $.fs.read(switchesPath()))) as unknown
513 return json && typeof json === 'object' && !Array.isArray(json) ? (json as Record<string, unknown>) : {}
514}
515
516/** Reads the shared switch file and the open request for this chat. Never throws. */
517async function readSwitch($: EngineInterface) {
518 try {
519 let next = false
520 let nowHidden = false
521 try {
522 const json = await readSwitches($)
523 next = json[NAME] === false
524 nowHidden = json[HIDE_KEY] === true
525 } catch {
526 next = false
527 nowHidden = hidden
528 }
529 if (nowHidden && !hidden) await $.ui.close({ id: PANE }).catch(() => undefined)
530 hidden = nowHidden
531 if (next !== off) {
532 off = next
533 await update($, offAtom, () => next)
534 $.ui.invalidate('ui.render')
535 }
536 const sid = await $.session.id()
537 const req = `${home}/.claude/mods/.open-${NAME}-${sid}`
538 if (await $.fs.exists(req)) {
539 await $.process.run(['rm', '-f', req])
540 if (!off) await openPane($)
541 }
542 } catch (err) {
543 await logError($, 'switch', err)
544 }
545}
546
547// Read, change, write the whole file, so every chat sees the choice within 3 s.
548async function setHidden($: EngineInterface, value: boolean) {
549 try {
550 const json = await readSwitches($)
551 if (value) json[HIDE_KEY] = true
552 else delete json[HIDE_KEY]
553 await $.process.run(['mkdir', '-p', `${home}/.claude/mods`])
554 await $.fs.write(switchesPath(), `${JSON.stringify(json, null, 2)}\n`)
555 } catch (err) {
556 await logError($, 'save hidden', err)
557 }
558 hidden = value
559 if (value) await $.ui.close({ id: PANE }).catch(() => undefined)
560}
561
562const newest = <T extends { seq: number }>(rows: T[]) => [...rows].sort((a, b) => b.seq - a.seq)
563
564/** A logo tile with its call count in a corner badge. */
565function badgeSvg(key: string, name: string, count: number): string {
566 const logo = LOGOS[key]
567 const tile =
568 logo?.svg ??
569 `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32"><rect width="32" height="32" rx="8" fill="${ACCENT}"/><text x="16" y="21.5" text-anchor="middle" font-family="-apple-system, Helvetica, Arial, sans-serif" font-size="16" font-weight="700" fill="#ffffff">${(name[0] ?? '?').toUpperCase()}</text></svg>`
570 const inner = tile.replace('<svg ', '<svg x="1" y="7" ')
571 const label = count > 99 ? '99+' : String(count)
572 const w = label.length > 1 ? 9 + label.length * 4 : 15
573 return (
574 '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 44 40" width="44" height="40">' +
575 inner +
576 `<rect x="${42 - w}" y="1" width="${w}" height="15" rx="7.5" fill="${ACCENT}" stroke="#ffffff" stroke-width="1.5"/>` +
577 `<text x="${42 - w / 2}" y="12" text-anchor="middle" font-family="-apple-system, Helvetica, Arial, sans-serif" font-size="10" font-weight="700" fill="#ffffff">${label}</text>` +
578 '</svg>'
579 )
580}
581
582async function togglePress($: EngineInterface, element: string) {
583 if (!element.startsWith('c:')) return
584 const key = element.slice(2)
585 await update($, openKey, cur => (cur === key ? '' : key))
586}
587
588async function toggleSection($: EngineInterface, id: string) {
589 await update($, foldedAtom, cur => (cur.includes(id) ? cur.filter(x => x !== id) : [...cur, id]))
590}
591
592async function moveFiles($: EngineInterface, by: number) {
593 const total = (await read($, inv)).files.length
594 const last = Math.max(0, total - FILE_WINDOW)
595 await update($, fileTopAtom, cur => Math.min(last, Math.max(0, Math.min(cur, last) + by)))
596}
597
598// Every key a connector can carry, so each press has its own handler.
599const KNOWN_KEYS = [...new Set([...Object.keys(LOGOS), ...[...CONNECTOR_NAMES, ...Object.values(GWS), ...Object.values(CLI_NAME), 'Google Workspace'].map(slug)])]
600
601export const register: Register = on => {
602 on('session.start', async ($, e, next) => {
603 home = $.plugin.root.split('/.claude/')[0] ?? ''
604 await $.command.register({ name: 'inventory', description: 'Show the connectors, files and skills this chat used', immediate: true })
605 await readSwitch($)
606 if (!switchTimer)
607 switchTimer = $.clock.every(3000, () => {
608 void readSwitch($)
609 if (!off) void readPlan($)
610 })
611 void seed($)
612 .then(() => readPlan($))
613 .catch(err => logError($, 'seed', err))
614 void loadMemoryFiles($).catch(err => logError($, 'memory', err))
615 return next(e)
616 })
617
618 on('command.run', { command: 'inventory' }, async $ => {
619 if (off) return { text: 'Chat Inventory is off. Turn it on with /mods.' }
620 if (hidden) await setHidden($, false)
621 await openPane($)
622 void loadMemoryFiles($).catch(err => logError($, 'memory', err))
623 return { text: 'Opened the In this chat pane.' }
624 })
625
626 // A skill the person typed as a slash command.
627 on('command.run', async ($, e, next) => {
628 const ran = await next(e)
629 if (off) return ran
630 try {
631 if (e.command !== 'inventory' && (await isSkill($, e.command))) await record($, '', [{ kind: 'skill', name: e.command }])
632 } catch (err) {
633 await logError($, 'command', err)
634 }
635 return ran
636 }).catch(($, e, next) => next(e))
637
638 // Every tool call, in the main chat and in helpers: the call runs first, then it is counted.
639 on('tool.call', async ($, e, next) => {
640 if (off) return next(e)
641 const ran = await next(e)
642 try {
643 if ((ran as { deny?: unknown }).deny === undefined) {
644 const call = e as unknown as Record<string, unknown> & { tool: string; tool_use_id: string }
645 await record($, call.tool_use_id, hitsOf(call.tool, call))
646 if (await watchPlan($, call, (ran as { result?: unknown }).result, await $.clock.now())) autoOpen($)
647 }
648 } catch (err) {
649 await logError($, 'tool.call', err)
650 }
651 return ran
652 }).catch(($, e, next) => next(e))
653
654 // A press on a connector logo opens its call list; a second press closes it.
655 for (const key of KNOWN_KEYS) {
656 on('ui.press', { plugin: 'chat-inventory', element: `c:${key}` }, async ($, e) => {
657 await togglePress($, e.element)
658 return { element: e.element }
659 })
660 }
661 // The arrow on each section header opens or closes it.
662 for (const id of SECTIONS) {
663 on('ui.press', { plugin: 'chat-inventory', element: `sec-${id}` }, async ($, e) => {
664 await toggleSection($, id)
665 return { element: e.element }
666 })
667 }
668 on('ui.press', { plugin: 'chat-inventory', element: 'files-up' }, async ($, e) => {
669 await moveFiles($, -FILE_STEP)
670 return { element: e.element }
671 })
672 on('ui.press', { plugin: 'chat-inventory', element: 'files-down' }, async ($, e) => {
673 await moveFiles($, FILE_STEP)
674 return { element: e.element }
675 })
676
677 on('ui.press', { plugin: 'chat-inventory', element: 'hide' }, async ($, e) => {
678 await setHidden($, true)
679 try {
680 $.ui.toast('Chat Inventory hidden. Type /inventory or open /mods to show it.')
681 } catch {
682 // The toast is only a hint.
683 }
684 return { element: e.element }
685 })
686
687 // Connectors with no known key (an unmapped server).
688 on('ui.press', { plugin: 'chat-inventory' }, async ($, e, next) => {
689 const key = e.element.slice(2)
690 if (!e.element.startsWith('c:') || KNOWN_KEYS.includes(key)) return next(e)
691 await togglePress($, e.element)
692 return { element: e.element }
693 })
694
695 on('ui.render', { component: 'Pane', requestId: PANE }, async ($, e) => {
696 const els = $.ui.resolve(e)
697 const { Box, Text, Button } = els
698 const width = Math.max(20, e.props.bodyColumns)
699 const inner = width - 4
700 if (await read($, offAtom)) return <Text dimColor>{OFF_LINE}</Text>
701 const list = await read($, inv)
702 const open = await read($, openKey)
703 const folded = await read($, foldedAtom)
704 const Svg = e.surface !== 'terminal' && 'Svg' in els ? els.Svg : undefined
705
706 // The header is the toggle: an arrow, the title, and the count on the right.
707 const header = (key: string, title: string, right: string, isOpen: boolean) => (
708 <Box key="h" flexDirection="row" justifyContent="space-between" width={inner}>
709 <Button key={`sec-${key}`} plain onPress={() => undefined}>
710 <Text color={ACCENT}>{isOpen ? '▾ ' : '▸ '}</Text>
711 <Text bold>{title}</Text>
712 </Button>
713 {right ? <Text dimColor>{right}</Text> : null}
714 </Box>
715 )
716 const none = <Text dimColor>None used yet</Text>
717 const section = (key: string, title: string, right: string, body: unknown) => {
718 const isOpen = !folded.includes(key)
719 return (
720 <Box key={key} flexDirection="column" borderStyle="round" paddingX={1} width={width} flexShrink={0}>
721 {header(key, title, right, isOpen)}
722 {isOpen ? (body as never) : null}
723 </Box>
724 )
725 }
726 const row = (key: string, left: unknown, right: unknown) => (
727 <Box key={key} flexDirection="row" justifyContent="space-between" width={inner} height={1} gap={1}>
728 <Box flexShrink={1} flexGrow={1} height={1} overflow="hidden">
729 {left as never}
730 </Box>
731 {right ? <Box flexShrink={0}>{right as never}</Box> : null}
732 </Box>
733 )
734 const capped = <T,>(rows: T[], draw: (r: T) => unknown) => {
735 const shown = rows.slice(0, MAX_ROWS)
736 const more = rows.length - shown.length
737 return [...shown.map(draw), more > 0 ? <Text key="more" dimColor>{`+${more} more`}</Text> : null] as never
738 }
739
740 // Connectors: a grid of logos, then the open one's calls.
741 const conns = newest(list.connectors)
742 const callList = (c: ConnectorRow) => {
743 const calls = [...c.calls].reverse()
744 return (
745 <Box key={`calls:${c.key}`} flexDirection="column" width={inner} marginTop={1}>
746 <Text dimColor wrap="truncate-end">{`${c.name} calls, newest first`}</Text>
747 {capped(calls, call => {
748 const i = calls.indexOf(call)
749 return row(
750 `call:${c.key}:${i}`,
751 <Text wrap="truncate-end">
752 {call.tool}
753 {call.summary ? <Text dimColor>{` ${call.summary}`}</Text> : null}
754 </Text>,
755 <Text dimColor>{`${call.cli ? 'CLI ' : ''}${clockTime(call.at)}`.trim() || ' '}</Text>,
756 )
757 })}
758 </Box>
759 )
760 }
761 let connectorBody: unknown = none
762 if (conns.length && Svg) {
763 const tileCols = 12
764 const perRow = Math.max(1, Math.floor(inner / tileCols))
765 const rows: ConnectorRow[][] = []
766 for (let i = 0; i < conns.length; i += perRow) rows.push(conns.slice(i, i + perRow))
767 connectorBody = rows.map((r, ri) => (
768 <Box key={`row${ri}`} flexDirection="column" width={inner}>
769 <Box flexDirection="row" width={inner}>
770 {r.map(c => (
771 <Box key={`t:${c.key}`} flexDirection="column" alignItems="center" width={tileCols} flexShrink={0}>
772 <Svg source={badgeSvg(c.key, c.name, c.count)} alt={`${c.name}, ${plural(c.count, 'call')}`} width={44} height={40} />
773 <Button key={`c:${c.key}`} plain dimColor={open !== c.key} onPress={() => undefined}>
774 {c.name}
775 </Button>
776 <Text dimColor wrap="truncate-end">{c.cli && !c.mcp ? 'via CLI' : c.cli ? 'MCP + CLI' : ' '}</Text>
777 </Box>
778 ))}
779 </Box>
780 {r.some(c => c.key === open) ? callList(r.find(c => c.key === open)!) : null}
781 </Box>
782 ))
783 } else if (conns.length) {
784 // Terminal: one row per connector, the name pressable.
785 connectorBody = conns.map(c => (
786 <Box key={`r:${c.key}`} flexDirection="column" width={inner}>
787 {row(
788 `l:${c.key}`,
789 <Button key={`c:${c.key}`} plain onPress={() => undefined}>
790 {`${open === c.key ? '▾' : '▸'} ${c.name}`}
791 {c.cli && !c.mcp ? <Text dimColor> via CLI</Text> : c.cli ? <Text dimColor> MCP + CLI</Text> : null}
792 </Button>,
793 <Text color={ACCENT}>{plural(c.count, 'call')}</Text>,
794 )}
795 {open === c.key ? callList(c) : null}
796 </Box>
797 ))
798 }
799
800 const files = newest(list.files)
801 const fileRow = (f: FileRow) => {
802 const cut = f.path.lastIndexOf('/')
803 const name = f.path.slice(cut + 1)
804 const full = tilde(cut > 0 ? f.path.slice(0, cut) : '/')
805 // One line per file: long folders wrapped and drew over the row above on desktop.
806 const parts = full.split('/').filter(Boolean)
807 const folder = full.length > 28 && parts.length > 1 ? `…/${parts[parts.length - 1]}` : full
808 return row(
809 `f:${f.path}`,
810 <Text wrap="truncate-end">
811 {name}
812 <Text dimColor>{` ${folder}`}</Text>
813 </Text>,
814 f.auto ? <Text color={INFO}>auto</Text> : null,
815 )
816 }
817 // A fixed window of rows: a Box cannot scroll inside a pane, so Up and Down move it.
818 const top = Math.min(await read($, fileTopAtom), Math.max(0, files.length - FILE_WINDOW))
819 const windowed = files.slice(top, top + FILE_WINDOW)
820 const atTop = top === 0
821 const atEnd = top + FILE_WINDOW >= files.length
822 const readCount = files.filter(f => !f.auto).length
823 const readLine = row('fread', <Text dimColor>Files read</Text>, <Text dimColor>{String(readCount)}</Text>)
824 const fileBody = !files.length
825 ? none
826 : files.length <= FILE_WINDOW
827 ? [readLine, ...files.map(fileRow)]
828 : [
829 readLine,
830 <Box key="fwin" flexDirection="column" width={inner} height={FILE_WINDOW} overflow="hidden" flexShrink={0}>
831 {windowed.map(fileRow)}
832 </Box>,
833 <Box key="fnav" flexDirection="row" justifyContent="space-between" width={inner} gap={1}>
834 <Text dimColor wrap="truncate-end">{`${top + 1} to ${top + windowed.length} of ${files.length}`}</Text>
835 <Box flexDirection="row" gap={1} flexShrink={0}>
836 {atTop ? <Text dimColor>▴ Up</Text> : <Button key="files-up" plain onPress={() => undefined}>▴ Up</Button>}
837 {atEnd ? <Text dimColor>▾ Down</Text> : <Button key="files-down" plain onPress={() => undefined}>▾ Down</Button>}
838 </Box>
839 </Box>,
840 ]
841
842 const skills = newest(list.skills)
843 const skillBody = skills.length
844 ? capped(skills, s =>
845 row(
846 `s:${s.name}`,
847 <Text wrap="truncate-end">
848 <Text color={ACCENT}>/</Text>
849 {s.name}
850 </Text>,
851 <Text>
852 {s.always ? <Text color={INFO}>always loaded</Text> : null}
853 {s.always && s.count ? <Text dimColor>{' '}</Text> : null}
854 {s.count ? <Text dimColor>{plural(s.count, 'use')}</Text> : null}
855 </Text>,
856 ),
857 )
858 : none
859
860 // To-do: one row per step, the mark in a fixed column and the text wrapped beside it.
861 const plan = await read($, planAtom)
862 const textCols = inner - 2
863 const todoRow = (st: PlanStep, i: number) => {
864 const done = st.status === 'completed'
865 const now = st.status === 'in_progress'
866 const lines = wrapLines(now && st.active ? st.active : st.text, textCols)
867 return (
868 <Box key={`todo:${i}`} flexDirection="row" width={inner} flexShrink={0}>
869 <Box width={2} flexShrink={0}>
870 {done ? <Text color={GOOD}>✓</Text> : now ? <Text color={ACCENT}>●</Text> : <Text dimColor>○</Text>}
871 </Box>
872 <Box flexDirection="column" width={textCols} flexShrink={0}>
873 {lines.map((line, j) => (
874 <Text key={`l${j}`} wrap="truncate-end" dimColor={done} strikethrough={done} bold={now}>
875 {line}
876 </Text>
877 ))}
878 </Box>
879 </Box>
880 )
881 }
882 const doneCount = plan.steps.filter(st => st.status === 'completed').length
883 const todoBody = plan.steps.length
884 ? [
885 ...(plan.title ? wrapLines(plan.title, inner).map((line, j) => <Text key={`pt${j}`} dimColor wrap="truncate-end">{line}</Text>) : []),
886 ...plan.steps.map(todoRow),
887 ]
888 : wrapLines(NO_PLAN, inner).map((line, j) => <Text key={`np${j}`} dimColor wrap="truncate-end">{line}</Text>)
889
890 return (
891 <Box flexDirection="column" width={width}>
892 <Box key="top" flexDirection="row" justifyContent="flex-end" width={width}>
893 <Button key="hide" label="Hide" dimColor onPress={() => undefined} />
894 </Box>
895 {section('todo', 'To-do', plan.steps.length ? `${doneCount} of ${plan.steps.length}` : '', todoBody)}
896 {section('connectors', 'Connectors', String(conns.length), connectorBody)}
897 {section('files', 'Context files', String(files.length), fileBody)}
898 {section('skills', 'Skills', String(skills.length), skillBody)}
899 </Box>
900 )
901 })
902}
903hooks/connectors.ts 117 lines1// Names an MCP connector the same way on every account.
2// A server with a readable name (mcp__notion__..., mcp__plugin_x_fireflies__...) is named for it.
3// A claude.ai connector shows a random id as its server (mcp__<random id>__<tool>), and that id differs per
4// account, so it is named by its tool names instead. Anything else gets a tidy label, never the raw id.
5
6/** Readable server names, keyed in lower case. */
7const NAMED: Record<string, string> = {
8 'google-workspace': 'Google Workspace',
9 gmail: 'Gmail',
10 'google-calendar': 'Google Calendar',
11 'google-drive': 'Google Drive',
12 'chat-relay': 'Chat Relay',
13 handoff: 'Handoff',
14 vidiq: 'vidIQ',
15 apify: 'Apify',
16 'claude-in-chrome': 'Chrome',
17 claude_browser: 'Browser',
18 fireflies: 'Fireflies',
19 posthog: 'PostHog',
20 pipedrive: 'Pipedrive',
21 pandadoc: 'PandaDoc',
22 firecrawl: 'Firecrawl',
23 attio: 'Attio',
24 composio: 'Composio',
25 figma: 'Figma',
26 stripe: 'Stripe',
27 shopify: 'Shopify',
28 notion: 'Notion',
29 slack: 'Slack',
30 calendly: 'Calendly',
31 youtube: 'YouTube',
32 kit: 'Kit',
33 circle: 'Circle',
34 'circle-community': 'Circle',
35 supabase: 'Supabase',
36 vercel: 'Vercel',
37 make: 'Make',
38 higgsfield: 'Higgsfield',
39 github: 'GitHub',
40 linear: 'Linear',
41 hubspot: 'HubSpot',
42 reddit: 'Reddit',
43}
44
45/** Tool name patterns, first match wins. Prefixed families first, then the exact names one app uses. */
46const BY_TOOL: [RegExp, string][] = [
47 [/^fireflies_/i, 'Fireflies'],
48 [/^notion-/i, 'Notion'],
49 [/^vidiq_/i, 'vidIQ'],
50 [/^slack_/i, 'Slack'],
51 [/^composio_/i, 'Composio'],
52 [/^(ads_studio|ai_influencer|scene_builder_3d|shorts_studio|tiktok)_/i, 'Higgsfield'],
53 [/^ads_/i, 'Meta Ads'],
54 [/^(availability|event_types|meetings|routing_forms|scheduling_links|shares|locations|users|organizations)-|calendly/i, 'Calendly'],
55 [
56 /^(search_threads|get_thread|get_message|list_drafts|get_draft|create_draft|update_draft|delete_draft|list_labels|create_label|update_label|delete_label|(un)?label_(thread|message)|(un)?trash_(thread|message)|(un)?mark_(thread|message)_spam|apply_sensitive_(thread|message)_label|update_message_labels|forward|reply)$/i,
57 'Gmail',
58 ],
59 [/^(list_calendars|respond_to_event|suggest_time|search_events)$/i, 'Google Calendar'],
60 [
61 /^(list_recent_files|search_files|read_file_content|download_file_content|get_file_metadata|get_file_permissions|share_file|trash_file|copy_file)$/i,
62 'Google Drive',
63 ],
64 [/^(get_spreadsheet|get_values|update_values|append_values|batch_clear_values|update_formulas|insert_dimension|update_spreadsheet|copy_sheet_to_another_spreadsheet)$/i, 'Google Sheets'],
65 [/(subscriber|broadcast|sequence|landing_page|snippet|growth_stats|email_template|creator_profile|email_stats)/i, 'Kit'],
66 [/(community_member|space_group|(^|_)spaces?(_|$)|space_member|course_(lesson|section)|access_group|member_tag|tagged_member|live_room|gamification|paywall|flagged_content|filter_kit|post_summary|advanced_search)/i, 'Circle'],
67 [/(^|-)actors?(-|$)|apify|(^|-)dataset(-|$)|key-value-store/i, 'Apify'],
68 [/-records?(-|$)|^semantic-search-|call-recording|^run-basic-report$|-workspace-(members|teams)$|-list-entry-|attribute-definitions$/i, 'Attio'],
69 [/^(scenarios?|scenario-[a-z-]+|data-stores?|data-store-records|data-structures?|hooks|hook-[a-z-]+|executions|credential-requests|app-modules?|connections|connection-[a-z-]+)_/i, 'Make'],
70 [/^(apply_migration|execute_sql|list_migrations|list_tables|list_extensions|generate_typescript_types|get_advisors|get_publishable_keys|get_project_url|deploy_edge_function|list_edge_functions|get_edge_function|create_edge_function_secret)$/i, 'Supabase'],
71 [/deployment|vercel|edge_config|project_domain|sandboxes|named_sandbox|toolbar_|rolling_release|_drains?$|kms_/i, 'Vercel'],
72 [/^(get_design_context|get_figjam|use_figma|get_figma_skill|get_variable_defs|create_design_system_rules|search_design_system|send_code_to_figma|add_code_connect_map|get_motion_context)$|code_connect|shader|generative_plugin|^weave_/i, 'Figma'],
73 [/^(find_(person|company|decision_maker)_emails?|verify_email|report_bad_email)$/i, 'AnyMailFinder'],
74 [/^(match|enrich)-(business|prospects)$|^fetch-(entities|businesses-events|prospects-events|entities-statistics)$/i, 'Vibe Prospecting'],
75 [/^(getTranscripts|getVideoDetails|searchVideos|getChannelStatistics|getVideoComments|getTrendingVideos|getChannelTopVideos|getVideoCategories)$/, 'YouTube'],
76]
77
78/** The label for a connector whose name cannot be told from its server or its tools. */
79export const OTHER = 'Connector'
80
81/** Every name this file can give, so a caller can set up one handler per name. */
82export const CONNECTOR_NAMES: readonly string[] = [...new Set([...Object.values(NAMED), ...BY_TOOL.map(r => r[1]), OTHER])]
83
84const titleCase = (s: string) =>
85 s
86 .split(/[-_\s]+/)
87 .filter(Boolean)
88 .map(w => w[0]!.toUpperCase() + w.slice(1))
89 .join(' ')
90
91/** A random id rather than a name: 8 hex characters, a dash, then more hex and dashes. */
92export const isIdServer = (server: string) => /^[0-9a-f]{8}-[0-9a-f-]*$/i.test(server)
93
94// Servers already named by one of their tools, so a tool that fits no pattern still gets the name.
95const known = new Map<string, string>()
96
97/** The server and tool parts of an MCP tool name: mcp__<server>__<tool>. */
98export function splitTool(tool: string): { server: string; name: string } {
99 const [, server = '', ...rest] = tool.split('__')
100 return { server, name: rest.join('__') }
101}
102
103/** The friendly name for an MCP server, given one of its tool names. */
104export function connectorName(server: string, toolName: string): string {
105 if (!isIdServer(server)) {
106 let name = server.replace(/^plugin_[^_]+_/, '').replace(/^claude_ai_/i, '')
107 if (!name) name = server
108 return NAMED[name.toLowerCase()] ?? titleCase(name)
109 }
110 const hit = BY_TOOL.find(([re]) => re.test(toolName))
111 if (hit) {
112 known.set(server, hit[1])
113 return hit[1]
114 }
115 return known.get(server) ?? OTHER
116}
117hooks/logos.ts 4 lines1// Generated by assets/build-logos.py. Do not edit by hand.
2export type Logo = { svg: string; color: string; real: boolean }
3export const LOGOS: Record<string, Logo> = {"gmail": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 49.4 512 399.42\" preserveAspectRatio=\"xMidYMid meet\"><g fill=\"none\" fill-rule=\"evenodd\"><g fill-rule=\"nonzero\"><path fill=\"#4285f4\" d=\"M34.91 448.818h81.454V251L0 163.727V413.91c0 19.287 15.622 34.91 34.91 34.91z\"/><path fill=\"#34a853\" d=\"M395.636 448.818h81.455c19.287 0 34.909-15.622 34.909-34.909V163.727L395.636 251z\"/><path fill=\"#fbbc04\" d=\"M395.636 99.727V251L512 163.727v-46.545c0-43.142-49.25-67.782-83.782-41.891z\"/></g><path fill=\"#ea4335\" d=\"M116.364 251V99.727L256 204.455 395.636 99.727V251L256 355.727z\"/><path fill=\"#c5221f\" fill-rule=\"nonzero\" d=\"M0 117.182v46.545L116.364 251V99.727L83.782 75.291C49.25 49.4 0 74.04 0 117.18z\"/></g></svg></svg>", "color": "#EA4335", "real": true}, "googlecalendar": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 256\" preserveAspectRatio=\"xMidYMid meet\"><g><polygon fill=\"#FFFFFF\" points=\"195.368421 60.6315789 60.6315789 60.6315789 60.6315789 195.368421 195.368421 195.368421\"></polygon><polygon fill=\"#EA4335\" points=\"195.368421 256 256 195.368421 225.684211 190.196005 195.368421 195.368421 189.835162 223.098002\"></polygon><path d=\"M1.42108547e-14,195.368421 L1.42108547e-14,235.789474 C1.42108547e-14,246.955789 9.04421053,256 20.2105263,256 L60.6315789,256 L66.8568645,225.684211 L60.6315789,195.368421 L27.5991874,190.196005 L1.42108547e-14,195.368421 Z\" fill=\"#188038\"></path><path d=\"M256,60.6315789 L256,20.2105263 C256,9.04421053 246.955789,1.42108547e-14 235.789474,1.42108547e-14 L195.368421,1.42108547e-14 C191.679582,15.0358547 189.835162,26.1010948 189.835162,33.1957202 C189.835162,40.2903456 191.679582,49.4356319 195.368421,60.6315789 C208.777986,64.4714866 218.883249,66.3914404 225.684211,66.3914404 C232.485172,66.3914404 242.590435,64.4714866 256,60.6315789 Z\" fill=\"#1967D2\"></path><polygon fill=\"#FBBC04\" points=\"256 60.6315789 195.368421 60.6315789 195.368421 195.368421 256 195.368421\"></polygon><polygon fill=\"#34A853\" points=\"195.368421 195.368421 60.6315789 195.368421 60.6315789 256 195.368421 256\"></polygon><path d=\"M195.368421,0 L20.2105263,0 C9.04421053,0 0,9.04421053 0,20.2105263 L0,195.368421 L60.6315789,195.368421 L60.6315789,60.6315789 L195.368421,60.6315789 L195.368421,0 Z\" fill=\"#4285F4\"></path><path d=\"M88.2694737,165.153684 C83.2336842,161.751579 79.7473684,156.783158 77.8442105,150.214737 L89.5326316,145.397895 C90.5936842,149.44 92.4463158,152.572632 95.0905263,154.795789 C97.7178947,157.018947 100.917895,158.113684 104.656842,158.113684 C108.48,158.113684 111.764211,156.951579 114.509474,154.627368 C117.254737,152.303158 118.635789,149.338947 118.635789,145.751579 C118.635789,142.08 117.187368,139.082105 114.290526,136.757895 C111.393684,134.433684 107.755789,133.271579 103.410526,133.271579 L96.6568421,133.271579 L96.6568421,121.701053 L102.72,121.701053 C106.458947,121.701053 109.608421,120.690526 112.168421,118.669474 C114.728421,116.648421 116.008421,113.886316 116.008421,110.366316 C116.008421,107.233684 114.863158,104.741053 112.572632,102.871579 C110.282105,101.002105 107.385263,100.058947 103.865263,100.058947 C100.429474,100.058947 97.7010526,100.968421 95.68,102.804211 C93.6602819,104.644885 92.1418208,106.968942 91.2673684,109.557895 L79.6968421,104.741053 C81.2294737,100.395789 84.0421053,96.5557895 88.1684211,93.2378947 C92.2947368,89.92 97.5663158,88.2526316 103.966316,88.2526316 C108.698947,88.2526316 112.96,89.1621053 116.732632,90.9978947 C120.505263,92.8336842 123.469474,95.3768421 125.608421,98.6105263 C127.747368,101.861053 128.808421,105.498947 128.808421,109.541053 C128.808421,113.667368 127.814737,117.153684 125.827368,120.016842 C123.84,122.88 121.397895,125.069474 118.501053,126.602105 L118.501053,127.292632 C122.241568,128.834789 125.490747,131.367752 127.898947,134.618947 C130.341053,137.903158 131.570526,141.827368 131.570526,146.408421 C131.570526,150.989474 130.408421,155.082105 128.084211,158.669474 C125.76,162.256842 122.543158,165.086316 118.467368,167.141053 C114.374737,169.195789 109.776842,170.240124 104.673684,170.240124 C98.7621053,170.256842 93.3052632,168.555789 88.2694737,165.153684 L88.2694737,165.153684 Z M160.067368,107.149474 L147.233684,116.429474 L140.816842,106.694737 L163.84,90.0884211 L172.665263,90.0884211 L172.665263,168.421053 L160.067368,168.421053 L160.067368,107.149474 Z\" fill=\"#4285F4\"></path></g></svg></svg>", "color": "#4285F4", "real": true}, "googledrive": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 229\" preserveAspectRatio=\"xMidYMid meet\"><g><path d=\"M19.3542312,196.033928 L30.644172,215.534816 C32.9900287,219.64014 36.3622164,222.86588 40.3210929,225.211737 C51.6602421,210.818376 59.5534225,199.772864 64.000634,192.075201 C68.5137119,184.263529 74.0609657,172.045039 80.6423954,155.41973 C62.9064315,153.085282 49.4659974,151.918058 40.3210929,151.918058 C31.545465,151.918058 18.1051007,153.085282 0,155.41973 C0,159.964996 1.17298825,164.510261 3.51893479,168.615586 L19.3542312,196.033928 Z\" fill=\"#0066DA\"></path><path d=\"M215.681443,225.211737 C219.64032,222.86588 223.012507,219.64014 225.358364,215.534816 L230.050377,207.470615 L252.483511,168.615586 C254.829368,164.510261 256.002446,159.964996 256.002446,155.41973 C237.79254,153.085282 224.376613,151.918058 215.754667,151.918058 C206.488712,151.918058 193.072785,153.085282 175.506888,155.41973 C182.010479,172.136093 187.484394,184.354584 191.928633,192.075201 C196.412073,199.863919 204.329677,210.909431 215.681443,225.211737 Z\" fill=\"#EA4335\"></path><path d=\"M128.001268,73.3111515 C141.121182,57.4655263 150.162898,45.2470011 155.126415,36.6555757 C159.123121,29.7376196 163.521739,18.6920726 168.322271,3.51893479 C164.363395,1.1729583 159.818129,0 155.126415,0 L100.876121,0 C96.1841079,0 91.638842,1.31958557 87.6799655,3.51893479 C93.7861943,20.9210065 98.9675428,33.3058067 103.224011,40.6733354 C107.927832,48.8151881 116.186918,59.6944602 128.001268,73.3111515 Z\" fill=\"#00832D\"></path><path d=\"M175.360141,155.41973 L80.6420959,155.41973 L40.3210929,225.211737 C44.2799694,227.557893 48.8252352,228.730672 53.5172481,228.730672 L202.485288,228.730672 C207.177301,228.730672 211.722567,227.411146 215.681443,225.211737 L175.360141,155.41973 Z\" fill=\"#2684FC\"></path><path d=\"M128.001268,73.3111515 L87.680265,3.51893479 C83.7213885,5.86488134 80.3489013,9.09044179 78.0030446,13.1960654 L3.51893479,142.223575 C1.17298825,146.329198 0,150.874464 0,155.41973 L80.6423954,155.41973 L128.001268,73.3111515 Z\" fill=\"#00AC47\"></path><path d=\"M215.241501,77.7099697 L177.999492,13.1960654 C175.653635,9.09044179 172.281148,5.86488134 168.322271,3.51893479 L128.001268,73.3111515 L175.360141,155.41973 L255.855999,155.41973 C255.855999,150.874464 254.682921,146.329198 252.337064,142.223575 L215.241501,77.7099697 Z\" fill=\"#FFBA00\"></path></g></svg></svg>", "color": "#0F9D58", "real": true}, "googlesheets": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 74 100\" preserveAspectRatio=\"xMidYMid meet\"><mask id=\"googlesheets-mask0_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask0_1:52)\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L56.4365 16.8843L45.398 1.43036Z\" fill=\"#0F9D58\"/></g><mask id=\"googlesheets-mask1_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask1_1:52)\"><path d=\"M18.9054 48.8962V80.908H54.2288V48.8962H18.9054ZM34.3594 76.4926H23.3209V70.9733H34.3594V76.4926ZM34.3594 67.6617H23.3209V62.1424H34.3594V67.6617ZM34.3594 58.8309H23.3209V53.3116H34.3594V58.8309ZM49.8134 76.4926H38.7748V70.9733H49.8134V76.4926ZM49.8134 67.6617H38.7748V62.1424H49.8134V67.6617ZM49.8134 58.8309H38.7748V53.3116H49.8134V58.8309Z\" fill=\"#F1F1F1\"/></g><mask id=\"googlesheets-mask2_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask2_1:52)\"><path d=\"M47.3352 25.9856L71.8905 50.5354V27.9229L47.3352 25.9856Z\" fill=\"url(#googlesheets-paint0_linear_1:52)\"/></g><mask id=\"googlesheets-mask3_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask3_1:52)\"><path d=\"M45.398 1.43036V21.2998C45.398 24.959 48.3618 27.9229 52.0211 27.9229H71.8905L45.398 1.43036Z\" fill=\"#87CEAC\"/></g><mask id=\"googlesheets-mask4_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask4_1:52)\"><path d=\"M7.86688 1.43036C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V8.60542C1.24374 4.9627 4.22415 1.98229 7.86688 1.98229H45.398V1.43036H7.86688Z\" fill=\"white\" fill-opacity=\"0.2\"/></g><mask id=\"googlesheets-mask5_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask5_1:52)\"><path d=\"M65.2674 98.0177H7.86688C4.22415 98.0177 1.24374 95.0373 1.24374 91.3946V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V91.3946C71.8905 95.0373 68.9101 98.0177 65.2674 98.0177Z\" fill=\"#263238\" fill-opacity=\"0.2\"/></g><mask id=\"googlesheets-mask6_1:52\" style=\"mask-type:alpha\" maskUnits=\"userSpaceOnUse\" x=\"1\" y=\"1\" width=\"71\" height=\"98\"><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"white\"/></mask><g mask=\"url(#googlesheets-mask6_1:52)\"><path d=\"M52.0211 27.9229C48.3618 27.9229 45.398 24.959 45.398 21.2998V21.8517C45.398 25.511 48.3618 28.4748 52.0211 28.4748H71.8905V27.9229H52.0211Z\" fill=\"#263238\" fill-opacity=\"0.1\"/></g><path d=\"M45.398 1.43036H7.86688C4.22415 1.43036 1.24374 4.41077 1.24374 8.0535V91.9465C1.24374 95.5893 4.22415 98.5697 7.86688 98.5697H65.2674C68.9101 98.5697 71.8905 95.5893 71.8905 91.9465V27.9229L45.398 1.43036Z\" fill=\"url(#googlesheets-paint1_radial_1:52)\"/><defs><linearGradient id=\"googlesheets-paint0_linear_1:52\" x1=\"59.6142\" y1=\"28.0935\" x2=\"59.6142\" y2=\"50.5388\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#263238\" stop-opacity=\"0.2\"/><stop offset=\"1\" stop-color=\"#263238\" stop-opacity=\"0.02\"/></linearGradient><radialGradient id=\"googlesheets-paint1_radial_1:52\" cx=\"0\" cy=\"0\" r=\"1\" gradientUnits=\"userSpaceOnUse\" gradientTransform=\"translate(3.48187 3.36121) scale(113.917)\"><stop stop-color=\"white\" stop-opacity=\"0.1\"/><stop offset=\"1\" stop-color=\"white\" stop-opacity=\"0\"/></radialGradient></defs></svg></svg>", "color": "#34A853", "real": true}, "googledocs": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" preserveAspectRatio=\"xMidYMid meet\"><path fill=\"#4285F4\" d=\"M14.727 6.727H14V0H4.91c-.905 0-1.637.732-1.637 1.636v20.728c0 .904.732 1.636 1.636 1.636h14.182c.904 0 1.636-.732 1.636-1.636V6.727h-6zm-.545 10.455H7.09v-1.364h7.09v1.364zm2.727-3.273H7.091v-1.364h9.818v1.364zm0-3.273H7.091V9.273h9.818v1.363zM14.727 6h6l-6-6v6z\"/></svg></svg>", "color": "#4285F4", "real": true}, "google": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 268.152 273.883\" preserveAspectRatio=\"xMidYMid meet\"><defs><linearGradient id=\"google-a\"><stop offset=\"0\" stop-color=\"#0fbc5c\"/><stop offset=\"1\" stop-color=\"#0cba65\"/></linearGradient><linearGradient id=\"google-g\"><stop offset=\".231\" stop-color=\"#0fbc5f\"/><stop offset=\".312\" stop-color=\"#0fbc5f\"/><stop offset=\".366\" stop-color=\"#0fbc5e\"/><stop offset=\".458\" stop-color=\"#0fbc5d\"/><stop offset=\".54\" stop-color=\"#12bc58\"/><stop offset=\".699\" stop-color=\"#28bf3c\"/><stop offset=\".771\" stop-color=\"#38c02b\"/><stop offset=\".861\" stop-color=\"#52c218\"/><stop offset=\".915\" stop-color=\"#67c30f\"/><stop offset=\"1\" stop-color=\"#86c504\"/></linearGradient><linearGradient id=\"google-h\"><stop offset=\".142\" stop-color=\"#1abd4d\"/><stop offset=\".248\" stop-color=\"#6ec30d\"/><stop offset=\".312\" stop-color=\"#8ac502\"/><stop offset=\".366\" stop-color=\"#a2c600\"/><stop offset=\".446\" stop-color=\"#c8c903\"/><stop offset=\".54\" stop-color=\"#ebcb03\"/><stop offset=\".616\" stop-color=\"#f7cd07\"/><stop offset=\".699\" stop-color=\"#fdcd04\"/><stop offset=\".771\" stop-color=\"#fdce05\"/><stop offset=\".861\" stop-color=\"#ffce0a\"/></linearGradient><linearGradient id=\"google-f\"><stop offset=\".316\" stop-color=\"#ff4c3c\"/><stop offset=\".604\" stop-color=\"#ff692c\"/><stop offset=\".727\" stop-color=\"#ff7825\"/><stop offset=\".885\" stop-color=\"#ff8d1b\"/><stop offset=\"1\" stop-color=\"#ff9f13\"/></linearGradient><linearGradient id=\"google-b\"><stop offset=\".231\" stop-color=\"#ff4541\"/><stop offset=\".312\" stop-color=\"#ff4540\"/><stop offset=\".458\" stop-color=\"#ff4640\"/><stop offset=\".54\" stop-color=\"#ff473f\"/><stop offset=\".699\" stop-color=\"#ff5138\"/><stop offset=\".771\" stop-color=\"#ff5b33\"/><stop offset=\".861\" stop-color=\"#ff6c29\"/><stop offset=\"1\" stop-color=\"#ff8c18\"/></linearGradient><linearGradient id=\"google-d\"><stop offset=\".408\" stop-color=\"#fb4e5a\"/><stop offset=\"1\" stop-color=\"#ff4540\"/></linearGradient><linearGradient id=\"google-c\"><stop offset=\".132\" stop-color=\"#0cba65\"/><stop offset=\".21\" stop-color=\"#0bb86d\"/><stop offset=\".297\" stop-color=\"#09b479\"/><stop offset=\".396\" stop-color=\"#08ad93\"/><stop offset=\".477\" stop-color=\"#0aa6a9\"/><stop offset=\".568\" stop-color=\"#0d9cc6\"/><stop offset=\".667\" stop-color=\"#1893dd\"/><stop offset=\".769\" stop-color=\"#258bf1\"/><stop offset=\".859\" stop-color=\"#3086ff\"/></linearGradient><linearGradient id=\"google-e\"><stop offset=\".366\" stop-color=\"#ff4e3a\"/><stop offset=\".458\" stop-color=\"#ff8a1b\"/><stop offset=\".54\" stop-color=\"#ffa312\"/><stop offset=\".616\" stop-color=\"#ffb60c\"/><stop offset=\".771\" stop-color=\"#ffcd0a\"/><stop offset=\".861\" stop-color=\"#fecf0a\"/><stop offset=\".915\" stop-color=\"#fecf08\"/><stop offset=\"1\" stop-color=\"#fdcd01\"/></linearGradient><linearGradient xlink:href=\"#google-a\" id=\"google-s\" x1=\"219.7\" x2=\"254.467\" y1=\"329.535\" y2=\"329.535\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-b\" id=\"google-m\" cx=\"109.627\" cy=\"135.862\" r=\"71.46\" fx=\"109.627\" fy=\"135.862\" gradientTransform=\"matrix(-1.93688 1.043 1.45573 2.55542 290.525 -400.634)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-c\" id=\"google-n\" cx=\"45.259\" cy=\"279.274\" r=\"71.46\" fx=\"45.259\" fy=\"279.274\" gradientTransform=\"matrix(-3.5126 -4.45809 -1.69255 1.26062 870.8 191.554)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-d\" id=\"google-l\" cx=\"304.017\" cy=\"118.009\" r=\"47.854\" fx=\"304.017\" fy=\"118.009\" gradientTransform=\"matrix(2.06435 0 0 2.59204 -297.679 -151.747)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-e\" id=\"google-o\" cx=\"181.001\" cy=\"177.201\" r=\"71.46\" fx=\"181.001\" fy=\"177.201\" gradientTransform=\"matrix(-.24858 2.08314 2.96249 .33417 -255.146 -331.164)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-f\" id=\"google-p\" cx=\"207.673\" cy=\"108.097\" r=\"41.102\" fx=\"207.673\" fy=\"108.097\" gradientTransform=\"matrix(-1.2492 1.34326 -3.89684 -3.4257 880.501 194.905)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-g\" id=\"google-r\" cx=\"109.627\" cy=\"135.862\" r=\"71.46\" fx=\"109.627\" fy=\"135.862\" gradientTransform=\"matrix(-1.93688 -1.043 1.45573 -2.55542 290.525 838.683)\" gradientUnits=\"userSpaceOnUse\"/><radialGradient xlink:href=\"#google-h\" id=\"google-j\" cx=\"154.87\" cy=\"145.969\" r=\"71.46\" fx=\"154.87\" fy=\"145.969\" gradientTransform=\"matrix(-.0814 -1.93722 2.92674 -.11625 -215.135 632.86)\" gradientUnits=\"userSpaceOnUse\"/><filter id=\"google-q\" width=\"1.097\" height=\"1.116\" x=\"-.048\" y=\"-.058\" color-interpolation-filters=\"sRGB\"><feGaussianBlur stdDeviation=\"1.701\"/></filter><filter id=\"google-k\" width=\"1.033\" height=\"1.02\" x=\"-.017\" y=\"-.01\" color-interpolation-filters=\"sRGB\"><feGaussianBlur stdDeviation=\".242\"/></filter><clipPath id=\"google-i\" clipPathUnits=\"userSpaceOnUse\"><path d=\"M371.378 193.24H237.083v53.438h77.167c-1.241 7.563-4.026 15.003-8.105 21.786-4.674 7.773-10.451 13.69-16.373 18.196-17.74 13.498-38.42 16.258-52.783 16.258-36.283 0-67.283-23.286-79.285-54.928-.484-1.149-.805-2.335-1.197-3.507a81.115 81.115 0 0 1-4.101-25.448c0-9.226 1.569-18.057 4.43-26.398 11.285-32.897 42.985-57.467 80.179-57.467 7.481 0 14.685.884 21.517 2.648a77.668 77.668 0 0 1 33.425 18.25l40.834-39.712c-24.839-22.616-57.219-36.32-95.844-36.32-30.878 0-59.386 9.553-82.748 25.7-18.945 13.093-34.483 30.625-44.97 50.985-9.753 18.879-15.094 39.8-15.094 62.294 0 22.495 5.35 43.633 15.103 62.337v.126c10.302 19.857 25.368 36.954 43.678 49.988 15.997 11.386 44.68 26.551 84.031 26.551 22.63 0 42.687-4.051 60.375-11.644 12.76-5.478 24.065-12.622 34.301-21.804 13.525-12.132 24.117-27.139 31.347-44.404 7.23-17.265 11.097-36.79 11.097-57.957 0-9.858-.998-19.87-2.689-28.968Z\"/></clipPath></defs><g clip-path=\"url(#google-i)\" transform=\"matrix(.95792 0 0 .98525 -90.174 -78.856)\"><path fill=\"url(#google-j)\" d=\"M92.076 219.958c.148 22.14 6.501 44.983 16.117 63.424v.127c6.949 13.392 16.445 23.97 27.26 34.452l65.327-23.67c-12.36-6.235-14.246-10.055-23.105-17.026-9.054-9.066-15.802-19.473-20.004-31.677h-.17l.17-.127c-2.765-8.058-3.037-16.613-3.14-25.503Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-l)\" d=\"M237.083 79.025c-6.456 22.526-3.988 44.421 0 57.161 7.457.006 14.64.888 21.45 2.647a77.662 77.662 0 0 1 33.424 18.25l41.88-40.726c-24.81-22.59-54.667-37.297-96.754-37.332Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-m)\" d=\"M236.943 78.847c-31.67 0-60.91 9.798-84.871 26.359a145.533 145.533 0 0 0-24.332 21.15c-1.904 17.744 14.257 39.551 46.262 39.37 15.528-17.936 38.495-29.542 64.056-29.542l.07.002-1.044-57.335c-.048 0-.093-.004-.14-.004Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-n)\" d=\"m341.475 226.379-28.268 19.285c-1.24 7.562-4.028 15.002-8.107 21.786-4.674 7.772-10.45 13.69-16.373 18.196-17.702 13.47-38.328 16.244-52.687 16.255-14.842 25.102-17.444 37.675 1.043 57.934 22.877-.016 43.157-4.117 61.046-11.796 12.931-5.551 24.388-12.792 34.761-22.097 13.706-12.295 24.442-27.503 31.769-45 7.327-17.497 11.245-37.282 11.245-58.734Z\" filter=\"url(#google-k)\"/><path fill=\"#3086ff\" d=\"M234.996 191.21v57.498h136.006c1.196-7.874 5.152-18.064 5.152-26.5 0-9.858-.996-21.899-2.687-30.998Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-o)\" d=\"M128.39 124.327c-8.394 9.119-15.564 19.326-21.249 30.364-9.753 18.879-15.094 41.83-15.094 64.324 0 .317.026.627.029.944 4.32 8.224 59.666 6.649 62.456 0-.004-.31-.039-.613-.039-.924 0-9.226 1.57-16.026 4.43-24.367 3.53-10.289 9.056-19.763 16.123-27.926 1.602-2.031 5.875-6.397 7.121-9.016.475-.997-.862-1.557-.937-1.908-.083-.393-1.876-.077-2.277-.37-1.275-.929-3.8-1.414-5.334-1.845-3.277-.921-8.708-2.953-11.725-5.06-9.536-6.658-24.417-14.612-33.505-24.216Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-p)\" d=\"M162.099 155.857c22.112 13.301 28.471-6.714 43.173-12.977l-25.574-52.664a144.74 144.74 0 0 0-26.543 14.504c-12.316 8.512-23.192 18.9-32.176 30.72Z\" filter=\"url(#google-q)\"/><path fill=\"url(#google-r)\" d=\"M171.099 290.222c-29.683 10.641-34.33 11.023-37.062 29.29a144.806 144.806 0 0 0 16.792 13.984c15.996 11.386 46.766 26.551 86.118 26.551.046 0 .09-.004.137-.004v-59.157l-.094.002c-14.736 0-26.512-3.843-38.585-10.527-2.977-1.648-8.378 2.777-11.123.799-3.786-2.729-12.9 2.35-16.183-.938Z\" filter=\"url(#google-k)\"/><path fill=\"url(#google-s)\" d=\"M219.7 299.023v59.996c5.506.64 11.236 1.028 17.247 1.028 6.026 0 11.855-.307 17.52-.872v-59.748a105.119 105.119 0 0 1-17.477 1.461c-5.932 0-11.7-.686-17.29-1.865Z\" filter=\"url(#google-k)\" opacity=\".5\"/></g></svg></svg>", "color": "#4285F4", "real": true}, "notion": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 268\" preserveAspectRatio=\"xMidYMid meet\"><g><path d=\"M16.0924984,11.5384656 L164.089991,0.608048392 C182.268719,-0.952166138 186.940447,0.0998642306 198.370133,8.40912104 L245.613429,41.6907258 C253.405586,47.4144843 256,48.9746988 256,55.2066414 L256,237.73391 C256,249.172512 251.845372,255.939385 237.304172,256.973584 L65.4398551,267.377986 C54.5272689,267.895086 49.3295257,266.334872 43.6146827,259.050899 L8.82635648,213.813593 C2.58549836,205.486505 0,199.254562 0,191.970589 L0,29.7261093 C0,20.3737376 4.1546284,12.572665 16.0924984,11.5384656 Z\" fill=\"#FFFFFF\"></path><path d=\"M164.089991,0.608048392 L16.0924984,11.5384656 C4.1546284,12.572665 0,20.3737376 0,29.7261093 L0,191.970589 C0,199.254562 2.58549836,205.486505 8.82635648,213.813593 L43.6146827,259.050899 C49.3295257,266.334872 54.5272689,267.895086 65.4398551,267.377986 L237.304172,256.973584 C251.836456,255.939385 256,249.172512 256,237.73391 L256,55.2066414 C256,49.2956572 253.664136,47.5927945 246.790277,42.5466149 C246.394749,42.2616979 245.999494,41.9764014 245.604513,41.6907258 L198.370133,8.40912104 C186.940447,0.0998642306 182.268719,-0.952166138 164.089991,0.608048392 Z M69.3270182,52.219945 C55.2940029,53.1649893 52.1111653,53.3789615 44.1406979,46.8973846 L23.8757401,30.7781396 C21.8162569,28.6919099 22.8504562,26.0885805 28.039284,25.5714809 L170.313018,15.1759943 C182.259804,14.1328795 188.482831,18.2964234 193.154559,21.9339521 L217.556314,39.6134116 C218.599429,40.1394268 221.193843,43.2509404 218.073414,43.2509404 L71.1457825,52.0951279 L69.3270182,52.219945 Z M52.9670544,236.173696 L52.9670544,81.2221043 C52.9670544,74.455231 55.0443686,71.3348019 61.2673957,70.8087867 L230.020199,60.9303999 C235.743958,60.4133002 238.329456,64.0508289 238.329456,70.8087867 L238.329456,224.726179 C238.329456,231.493052 237.286341,237.216811 227.942885,237.73391 L66.4562234,247.095198 C57.1127673,247.612297 52.9670544,244.500784 52.9670544,236.173696 Z M212.376402,89.5313611 C213.410601,94.2120046 212.376402,98.8926482 207.695758,99.4275789 L199.912517,100.969962 L199.912517,215.373807 C193.154559,219.011336 186.931532,221.08865 181.733788,221.08865 C173.424532,221.08865 171.347217,218.485321 165.12419,210.693164 L114.225535,130.614039 L114.225535,208.089834 L130.326949,211.736279 C130.326949,211.736279 130.326949,221.097566 117.337048,221.097566 L81.523438,223.17488 C80.4803232,221.08865 81.523438,215.890907 85.1520513,214.856708 L94.5044229,212.262294 L94.5044229,109.823065 L81.523438,108.771035 C80.4803232,104.090391 83.0747371,97.3324337 90.3497945,96.8064185 L128.77565,94.2209202 L181.733788,175.334245 L181.733788,103.573292 L168.235704,102.021993 C167.192589,96.2893189 171.347217,92.1257749 176.536045,91.6175908 L212.376402,89.5313611 L212.376402,89.5313611 Z\" fill=\"#000000\"></path></g></svg></svg>", "color": "#000000", "real": true}, "slack": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 256\" preserveAspectRatio=\"xMidYMid meet\"><g><path d=\"M53.8412698,161.320635 C53.8412698,176.152381 41.8539683,188.139683 27.0222222,188.139683 C12.1904762,188.139683 0.203174603,176.152381 0.203174603,161.320635 C0.203174603,146.488889 12.1904762,134.501587 27.0222222,134.501587 L53.8412698,134.501587 L53.8412698,161.320635 Z M67.2507937,161.320635 C67.2507937,146.488889 79.2380952,134.501587 94.0698413,134.501587 C108.901587,134.501587 120.888889,146.488889 120.888889,161.320635 L120.888889,228.368254 C120.888889,243.2 108.901587,255.187302 94.0698413,255.187302 C79.2380952,255.187302 67.2507937,243.2 67.2507937,228.368254 L67.2507937,161.320635 Z\" fill=\"#E01E5A\"></path><path d=\"M94.0698413,53.6380952 C79.2380952,53.6380952 67.2507937,41.6507937 67.2507937,26.8190476 C67.2507937,11.9873016 79.2380952,-7.10542736e-15 94.0698413,-7.10542736e-15 C108.901587,-7.10542736e-15 120.888889,11.9873016 120.888889,26.8190476 L120.888889,53.6380952 L94.0698413,53.6380952 Z M94.0698413,67.2507937 C108.901587,67.2507937 120.888889,79.2380952 120.888889,94.0698413 C120.888889,108.901587 108.901587,120.888889 94.0698413,120.888889 L26.8190476,120.888889 C11.9873016,120.888889 0,108.901587 0,94.0698413 C0,79.2380952 11.9873016,67.2507937 26.8190476,67.2507937 L94.0698413,67.2507937 Z\" fill=\"#36C5F0\"></path><path d=\"M201.549206,94.0698413 C201.549206,79.2380952 213.536508,67.2507937 228.368254,67.2507937 C243.2,67.2507937 255.187302,79.2380952 255.187302,94.0698413 C255.187302,108.901587 243.2,120.888889 228.368254,120.888889 L201.549206,120.888889 L201.549206,94.0698413 Z M188.139683,94.0698413 C188.139683,108.901587 176.152381,120.888889 161.320635,120.888889 C146.488889,120.888889 134.501587,108.901587 134.501587,94.0698413 L134.501587,26.8190476 C134.501587,11.9873016 146.488889,-1.42108547e-14 161.320635,-1.42108547e-14 C176.152381,-1.42108547e-14 188.139683,11.9873016 188.139683,26.8190476 L188.139683,94.0698413 Z\" fill=\"#2EB67D\"></path><path d=\"M161.320635,201.549206 C176.152381,201.549206 188.139683,213.536508 188.139683,228.368254 C188.139683,243.2 176.152381,255.187302 161.320635,255.187302 C146.488889,255.187302 134.501587,243.2 134.501587,228.368254 L134.501587,201.549206 L161.320635,201.549206 Z M161.320635,188.139683 C146.488889,188.139683 134.501587,176.152381 134.501587,161.320635 C134.501587,146.488889 146.488889,134.501587 161.320635,134.501587 L228.571429,134.501587 C243.403175,134.501587 255.390476,146.488889 255.390476,161.320635 C255.390476,176.152381 243.403175,188.139683 228.571429,188.139683 L161.320635,188.139683 Z\" fill=\"#ECB22E\"></path></g></svg></svg>", "color": "#4A154B", "real": true}, "stripe": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" preserveAspectRatio=\"xMidYMid meet\"><path fill=\"#635BFF\" d=\"M13.976 9.15c-2.172-.806-3.356-1.426-3.356-2.409 0-.831.683-1.305 1.901-1.305 2.227 0 4.515.858 6.09 1.631l.89-5.494C18.252.975 15.697 0 12.165 0 9.667 0 7.589.654 6.104 1.872 4.56 3.147 3.757 4.992 3.757 7.218c0 4.039 2.467 5.76 6.476 7.219 2.585.92 3.445 1.574 3.445 2.583 0 .98-.84 1.545-2.354 1.545-1.875 0-4.965-.921-6.99-2.109l-.9 5.555C5.175 22.99 8.385 24 11.714 24c2.641 0 4.843-.624 6.328-1.813 1.664-1.305 2.525-3.236 2.525-5.732 0-4.128-2.524-5.851-6.594-7.305h.003z\"/></svg></svg>", "color": "#635BFF", "real": true}, "calendly": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 841.89 595.28\" preserveAspectRatio=\"xMidYMid meet\"><style type=\"text/css\"> .st0{fill:#3664AE;} .st1{fill:#5FC2D6;} </style><path class=\"st0\" d=\"M505.27,365.28c-14.79,12.86-33.19,28.86-66.71,28.86h-20.01c-24.22,0-46.25-8.62-62.01-24.28 c-15.39-15.3-23.89-36.22-23.89-58.94v-26.87c0-22.72,8.48-43.66,23.89-58.94c15.77-15.66,37.79-24.28,62.01-24.28h20.01 c33.51,0,51.92,16,66.71,28.86c15.34,13.34,28.59,24.86,63.89,24.86c5.48,0,10.86-0.43,16.09-1.26c-0.04-0.11-0.08-0.2-0.12-0.3 c-2.1-5.1-4.57-10.12-7.42-14.96l-23.6-40.1c-21.65-36.8-61.68-59.46-104.98-59.46h-47.21c-43.3,0-83.33,22.67-104.98,59.46 l-23.6,40.1c-21.65,36.8-21.65,82.12,0,118.91l23.6,40.1c21.65,36.8,61.68,59.45,104.98,59.45h47.21 c43.3,0,83.33-22.67,104.98-59.45l23.6-40.1c2.85-4.85,5.32-9.85,7.42-14.95c0.04-0.11,0.08-0.2,0.12-0.3 c-5.23-0.83-10.59-1.26-16.09-1.26C533.87,340.42,520.61,351.94,505.27,365.28z\"/><path class=\"st0\" d=\"M438.57,225.16h-20.01c-36.86,0-61.09,25.83-61.09,58.89v26.87c0,33.06,24.22,58.89,61.09,58.89h20.01 c53.71,0,49.49-53.72,130.59-53.72c7.77,0,15.45,0.7,22.92,2.06c2.46-13.66,2.46-27.64,0-41.31c-7.48,1.36-15.15,2.06-22.92,2.06 C488.06,278.89,492.28,225.16,438.57,225.16z\"/><path class=\"st0\" d=\"M638.66,337.76c-13.85-10.02-29.74-16.56-46.59-19.64c-0.03,0.13-0.04,0.26-0.07,0.39 c-1.44,7.87-3.69,15.62-6.77,23.14c14.22,2.26,27.32,7.5,38.52,15.55c-0.04,0.12-0.07,0.24-0.11,0.37 c-6.46,20.57-16.2,39.96-28.93,57.6c-12.58,17.42-27.79,32.76-45.22,45.57c-36.18,26.62-79.27,40.68-124.63,40.68 c-28.08,0-55.31-5.39-80.94-16.02c-24.75-10.27-46.99-24.98-66.11-43.73c-19.11-18.75-34.1-40.56-44.57-64.85 c-10.83-25.14-16.33-51.85-16.33-79.4c0-27.55,5.5-54.26,16.33-79.4c10.47-24.28,25.46-46.1,44.57-64.85 c19.11-18.75,41.35-33.45,66.11-43.73c25.62-10.63,52.85-16.02,80.94-16.02c45.36,0,88.45,14.06,124.63,40.68 c17.43,12.82,32.63,28.15,45.22,45.57c12.73,17.65,22.47,37.04,28.93,57.6c0.04,0.13,0.08,0.25,0.11,0.37 c-11.19,8.04-24.3,13.3-38.52,15.55c3.08,7.53,5.34,15.3,6.77,23.17c0.03,0.13,0.04,0.25,0.07,0.38 c16.85-3.08,32.73-9.62,46.59-19.64c13.28-9.64,10.71-20.53,8.69-26.99C618.08,136.9,529.55,69.12,424.87,69.12 c-128.55,0-232.75,102.22-232.75,228.32c0,126.1,104.21,228.32,232.75,228.32c104.68,0,193.21-67.79,222.48-161.05 C649.38,358.29,651.96,347.41,638.66,337.76z\"/><path class=\"st1\" d=\"M585.25,253.26c-5.23,0.83-10.59,1.26-16.09,1.26c-35.29,0-48.55-11.52-63.89-24.86 c-14.79-12.86-33.19-28.86-66.71-28.86h-20.01c-24.22,0-46.25,8.62-62.01,24.28c-15.39,15.3-23.89,36.22-23.89,58.94v26.87 c0,22.72,8.48,43.66,23.89,58.94c15.77,15.66,37.79,24.28,62.01,24.28h20.01c33.51,0,51.92-16.01,66.71-28.86 c15.34-13.34,28.59-24.86,63.89-24.86c5.48,0,10.86,0.43,16.09,1.26c3.08-7.52,5.32-15.28,6.77-23.14c0.03-0.13,0.04-0.26,0.07-0.39 c-7.48-1.36-15.15-2.06-22.92-2.06c-81.1,0-76.88,53.72-130.59,53.72h-20.01c-36.86,0-61.09-25.83-61.09-58.89v-26.87 c0-33.06,24.22-58.89,61.09-58.89h20.01c53.71,0,49.5,53.72,130.59,53.72c7.77,0,15.45-0.7,22.92-2.06 c-0.03-0.13-0.04-0.25-0.07-0.38C590.59,268.56,588.33,260.8,585.25,253.26z\"/><path class=\"st1\" d=\"M585.25,253.26c-5.23,0.83-10.59,1.26-16.09,1.26c-35.29,0-48.55-11.52-63.89-24.86 c-14.79-12.86-33.19-28.86-66.71-28.86h-20.01c-24.22,0-46.25,8.62-62.01,24.28c-15.39,15.3-23.89,36.22-23.89,58.94v26.87 c0,22.72,8.48,43.66,23.89,58.94c15.77,15.66,37.79,24.28,62.01,24.28h20.01c33.51,0,51.92-16.01,66.71-28.86 c15.34-13.34,28.59-24.86,63.89-24.86c5.48,0,10.86,0.43,16.09,1.26c3.08-7.52,5.32-15.28,6.77-23.14c0.03-0.13,0.04-0.26,0.07-0.39 c-7.48-1.36-15.15-2.06-22.92-2.06c-81.1,0-76.88,53.72-130.59,53.72h-20.01c-36.86,0-61.09-25.83-61.09-58.89v-26.87 c0-33.06,24.22-58.89,61.09-58.89h20.01c53.71,0,49.5,53.72,130.59,53.72c7.77,0,15.45-0.7,22.92-2.06 c-0.03-0.13-0.04-0.25-0.07-0.38C590.59,268.56,588.33,260.8,585.25,253.26z\"/></svg></svg>", "color": "#006BFF", "real": true}, "figma": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 54 80\" preserveAspectRatio=\"xMidYMid meet\"><g clip-path=\"url(#figma-clip0_912_3)\"><path d=\"M13.3333 80.0002C20.6933 80.0002 26.6667 74.0268 26.6667 66.6668V53.3335H13.3333C5.97333 53.3335 0 59.3068 0 66.6668C0 74.0268 5.97333 80.0002 13.3333 80.0002Z\" fill=\"#0ACF83\"/><path d=\"M0 39.9998C0 32.6398 5.97333 26.6665 13.3333 26.6665H26.6667V53.3332H13.3333C5.97333 53.3332 0 47.3598 0 39.9998Z\" fill=\"#A259FF\"/><path d=\"M0 13.3333C0 5.97333 5.97333 0 13.3333 0H26.6667V26.6667H13.3333C5.97333 26.6667 0 20.6933 0 13.3333Z\" fill=\"#F24E1E\"/><path d=\"M26.6667 0H40.0001C47.3601 0 53.3334 5.97333 53.3334 13.3333C53.3334 20.6933 47.3601 26.6667 40.0001 26.6667H26.6667V0Z\" fill=\"#FF7262\"/><path d=\"M53.3334 39.9998C53.3334 47.3598 47.3601 53.3332 40.0001 53.3332C32.6401 53.3332 26.6667 47.3598 26.6667 39.9998C26.6667 32.6398 32.6401 26.6665 40.0001 26.6665C47.3601 26.6665 53.3334 32.6398 53.3334 39.9998Z\" fill=\"#1ABCFE\"/></g><defs><clipPath id=\"figma-clip0_912_3\"><rect width=\"53.3333\" height=\"80\" fill=\"white\"/></clipPath></defs></svg></svg>", "color": "#F24E1E", "real": true}, "vercel": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 222\" preserveAspectRatio=\"xMidYMid meet\"><g><polygon fill=\"#000000\" points=\"127.999778 0 256 221.704527 0 221.704527\"></polygon></g></svg></svg>", "color": "#000000", "real": true}, "supabase": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 263\" preserveAspectRatio=\"xMidYMid meet\"><defs><linearGradient x1=\"20.8617445%\" y1=\"20.6868812%\" x2=\"63.4256086%\" y2=\"44.0710077%\" id=\"supabase-supabase-linearGradient-1\"><stop stop-color=\"#249361\" offset=\"0%\"></stop><stop stop-color=\"#3ECF8E\" offset=\"100%\"></stop></linearGradient><linearGradient x1=\"1.99116498%\" y1=\"-13.1584008%\" x2=\"21.4025077%\" y2=\"34.708062%\" id=\"supabase-supabase-linearGradient-2\"><stop stop-color=\"#000000\" offset=\"0%\"></stop><stop stop-color=\"#000000\" stop-opacity=\"0\" offset=\"100%\"></stop></linearGradient></defs><g><path d=\"M149.601512,258.578826 C142.884085,267.038157 129.263882,262.403261 129.102024,251.601817 L126.735244,93.6176533 L232.963622,93.6176533 C252.204429,93.6176533 262.935398,115.840956 250.971119,130.909887 L149.601512,258.578826 Z\" fill=\"url(#supabase-supabase-linearGradient-1)\"></path><path d=\"M149.601512,258.578826 C142.884085,267.038157 129.263882,262.403261 129.102024,251.601817 L126.735244,93.6176533 L232.963622,93.6176533 C252.204429,93.6176533 262.935398,115.840956 250.971119,130.909887 L149.601512,258.578826 Z\" fill-opacity=\"0.2\" fill=\"url(#supabase-supabase-linearGradient-2)\"></path><path d=\"M106.399023,4.36908575 C113.11645,-4.09118439 126.736889,0.544432392 126.898746,11.3460249 L127.935901,169.329953 L23.0369844,169.329953 C3.79559007,169.329953 -6.93568494,147.106651 5.02918175,132.037719 L106.399023,4.36908575 Z\" fill=\"#3ECF8E\"></path></g></svg></svg>", "color": "#3FCF8E", "real": true}, "make": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" preserveAspectRatio=\"xMidYMid meet\"><path fill=\"#6D00CC\" d=\"M13.38 3.498c-.27 0-.511.19-.566.465L9.85 18.986a.578.578 0 0 0 .453.678l4.095.826a.58.58 0 0 0 .682-.455l2.963-15.021a.578.578 0 0 0-.453-.678l-4.096-.826a.589.589 0 0 0-.113-.012zm-5.876.098a.576.576 0 0 0-.516.318L.062 17.697a.575.575 0 0 0 .256.774l3.733 1.877a.578.578 0 0 0 .775-.258l6.926-13.781a.577.577 0 0 0-.256-.776L7.762 3.658a.571.571 0 0 0-.258-.062zm11.74.115a.576.576 0 0 0-.576.576v15.426c0 .318.258.578.576.578h4.178a.58.58 0 0 0 .578-.578V4.287a.578.578 0 0 0-.578-.576Z\"/></svg></svg>", "color": "#6D00CC", "real": true}, "youtube": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 180\" preserveAspectRatio=\"xMidYMid meet\"><g><path d=\"M250.346231,28.0746923 C247.358133,17.0320558 238.732098,8.40602109 227.689461,5.41792308 C207.823743,0 127.868333,0 127.868333,0 C127.868333,0 47.9129229,0.164179487 28.0472049,5.58210256 C17.0045684,8.57020058 8.37853373,17.1962353 5.39043571,28.2388718 C-0.618533519,63.5374615 -2.94988224,117.322662 5.5546152,151.209308 C8.54271322,162.251944 17.1687479,170.877979 28.2113844,173.866077 C48.0771024,179.284 128.032513,179.284 128.032513,179.284 C128.032513,179.284 207.987923,179.284 227.853641,173.866077 C238.896277,170.877979 247.522312,162.251944 250.51041,151.209308 C256.847738,115.861464 258.801474,62.1091 250.346231,28.0746923 Z\" fill=\"#FF0000\"></path><polygon fill=\"#FFFFFF\" points=\"102.420513 128.06 168.749025 89.642 102.420513 51.224\"></polygon></g></svg></svg>", "color": "#FF0000", "real": true}, "shopify": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 292\" preserveAspectRatio=\"xMidYMid meet\"><g><path d=\"M223.773626,57.3402078 C223.572932,55.8793405 222.29409,55.0718963 221.236945,54.9832175 C220.182133,54.8945386 197.853734,53.2399781 197.853734,53.2399781 C197.853734,53.2399781 182.346604,37.8448639 180.64537,36.1412966 C178.941803,34.4377293 175.616346,34.9558004 174.325836,35.336186 C174.134476,35.3921937 170.937371,36.3793293 165.646977,38.0152206 C160.466266,23.1101737 151.325344,9.41162582 135.241802,9.41162582 C134.798408,9.41162582 134.341011,9.43029505 133.883615,9.45596525 C129.309654,3.40713457 123.643542,0.779440373 118.74987,0.779440373 C81.285392,0.779440373 63.3862673,47.6135387 57.7738299,71.414474 C43.2164974,75.9254268 32.8737437,79.1318671 31.5528956,79.5472575 C23.4271131,82.0956074 23.1704111,82.3523094 22.1039313,90.0090275 C21.2988208,95.8058236 0.0369009009,260.235071 0.0369009009,260.235071 L165.714653,291.277334 L255.485648,271.856667 C255.485648,271.856667 223.971987,58.8010751 223.773626,57.3402078 L223.773626,57.3402078 Z M156.48972,40.8482763 C152.328815,42.1364532 147.598499,43.5996542 142.471461,45.1865388 C142.476129,44.1994032 142.480796,43.2262696 142.480796,42.1644571 C142.480796,32.8998514 141.194953,25.4414939 139.132003,19.5280151 C147.418807,20.5688247 152.937899,29.9967861 156.48972,40.8482763 L156.48972,40.8482763 Z M128.852258,21.3646006 C131.155574,27.1380602 132.65378,35.4225312 132.65378,46.6030666 C132.65378,47.1748118 132.649112,47.6975503 132.644445,48.2272897 C123.52686,51.0510108 113.620499,54.1174319 103.690802,57.1931876 C109.265901,35.6768995 119.716003,25.2851391 128.852258,21.3646006 L128.852258,21.3646006 Z M117.720729,10.8281537 C119.337951,10.8281537 120.966841,11.3765623 122.525722,12.4500431 C110.519073,18.099819 97.6489725,32.3304399 92.2138928,60.7473424 C84.2701352,63.2070135 76.506069,65.6106769 69.3277499,67.834649 C75.6939575,46.1596724 90.8113669,10.8281537 117.720729,10.8281537 L117.720729,10.8281537 Z\" fill=\"#95BF46\"></path><path d=\"M221.236945,54.9832175 C220.182133,54.8945386 197.853734,53.2399781 197.853734,53.2399781 C197.853734,53.2399781 182.346604,37.8448639 180.64537,36.1412966 C180.008283,35.5065427 179.149498,35.1821649 178.251042,35.0421456 L165.723988,291.275001 L255.485648,271.856667 C255.485648,271.856667 223.971987,58.8010751 223.773626,57.3402078 C223.572932,55.8793405 222.29409,55.0718963 221.236945,54.9832175\" fill=\"#5E8E3E\"></path><path d=\"M135.241802,104.585029 L124.173282,137.510551 C124.173282,137.510551 114.474617,132.334507 102.586984,132.334507 C85.1592573,132.334507 84.2818035,143.272342 84.2818035,146.028387 C84.2818035,161.066452 123.48252,166.828244 123.48252,202.052414 C123.48252,229.764553 105.90544,247.610004 82.2048516,247.610004 C53.7646126,247.610004 39.2212821,229.90924 39.2212821,229.90924 L46.8359944,204.750118 C46.8359944,204.750118 61.7853808,217.585214 74.4011133,217.585214 C82.6435785,217.585214 85.9970391,211.095323 85.9970391,206.353338 C85.9970391,186.736644 53.8369559,185.861524 53.8369559,153.629098 C53.8369559,126.500372 73.3089633,100.246767 112.614694,100.246767 C127.760108,100.246767 135.241802,104.585029 135.241802,104.585029\" fill=\"#FFFFFF\"></path></g></svg></svg>", "color": "#7AB55C", "real": true}, "meta": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 256 171\" preserveAspectRatio=\"xMidYMid meet\"><defs><linearGradient id=\"meta-a\" x1=\"13.878%\" x2=\"89.144%\" y1=\"55.934%\" y2=\"58.694%\"><stop offset=\"0%\" stop-color=\"#0064E1\"/><stop offset=\"40%\" stop-color=\"#0064E1\"/><stop offset=\"83%\" stop-color=\"#0073EE\"/><stop offset=\"100%\" stop-color=\"#0082FB\"/></linearGradient><linearGradient id=\"meta-b\" x1=\"54.315%\" x2=\"54.315%\" y1=\"82.782%\" y2=\"39.307%\"><stop offset=\"0%\" stop-color=\"#0082FB\"/><stop offset=\"100%\" stop-color=\"#0064E0\"/></linearGradient></defs><path fill=\"#0081FB\" d=\"M27.651 112.136c0 9.775 2.146 17.28 4.95 21.82 3.677 5.947 9.16 8.466 14.751 8.466 7.211 0 13.808-1.79 26.52-19.372 10.185-14.092 22.186-33.874 30.26-46.275l13.675-21.01c9.499-14.591 20.493-30.811 33.1-41.806C161.196 4.985 172.298 0 183.47 0c18.758 0 36.625 10.87 50.3 31.257C248.735 53.584 256 81.707 256 110.729c0 17.253-3.4 29.93-9.187 39.946-5.591 9.686-16.488 19.363-34.818 19.363v-27.616c15.695 0 19.612-14.422 19.612-30.927 0-23.52-5.484-49.623-17.564-68.273-8.574-13.23-19.684-21.313-31.907-21.313-13.22 0-23.859 9.97-35.815 27.75-6.356 9.445-12.882 20.956-20.208 33.944l-8.066 14.289c-16.203 28.728-20.307 35.271-28.408 46.07-14.2 18.91-26.324 26.076-42.287 26.076-18.935 0-30.91-8.2-38.325-20.556C2.973 139.413 0 126.202 0 111.148l27.651.988Z\"/><path fill=\"url(#meta-a)\" d=\"M21.802 33.206C34.48 13.666 52.774 0 73.757 0 85.91 0 97.99 3.597 110.605 13.897c13.798 11.261 28.505 29.805 46.853 60.368l6.58 10.967c15.881 26.459 24.917 40.07 30.205 46.49 6.802 8.243 11.565 10.7 17.752 10.7 15.695 0 19.612-14.422 19.612-30.927l24.393-.766c0 17.253-3.4 29.93-9.187 39.946-5.591 9.686-16.488 19.363-34.818 19.363-11.395 0-21.49-2.475-32.654-13.007-8.582-8.083-18.615-22.443-26.334-35.352l-22.96-38.352C118.528 64.08 107.96 49.73 101.845 43.23c-6.578-6.988-15.036-15.428-28.532-15.428-10.923 0-20.2 7.666-27.963 19.39L21.802 33.206Z\"/><path fill=\"url(#meta-b)\" d=\"M73.312 27.802c-10.923 0-20.2 7.666-27.963 19.39-10.976 16.568-17.698 41.245-17.698 64.944 0 9.775 2.146 17.28 4.95 21.82L9.027 149.482C2.973 139.413 0 126.202 0 111.148 0 83.772 7.514 55.24 21.802 33.206 34.48 13.666 52.774 0 73.757 0l-.445 27.802Z\"/></svg></svg>", "color": "#0467DF", "real": true}, "attio": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 103 26\" preserveAspectRatio=\"xMidYMid meet\"><path d=\"M84.2267 1.03809H79.9922V5.27257H84.2267V1.03809Z\" fill=\"#000000\"></path><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M67.7423 11.9094H64.0236V18.7905C64.0236 19.364 64.1661 19.7836 64.4529 20.0473C64.7396 20.3129 65.1592 20.4669 65.7097 20.5112C66.2602 20.5324 66.9454 20.5227 67.7615 20.4785V24.3492C64.8725 24.6802 62.811 24.4146 61.5753 23.5562C60.3627 22.6746 59.7564 21.0867 59.7564 18.7924V11.9113H56.8789V7.80774H59.7564V4.46635L64.0236 3.17676V7.80967H70.6198V4.46828L74.887 3.17868V7.81159H78.6249V11.9152H74.887V18.7962C74.887 19.3698 75.0294 19.7894 75.3162 20.0531C75.603 20.3187 76.0226 20.4727 76.5731 20.517C77.1236 20.5381 77.8088 20.5285 78.623 20.4842V24.3549C75.7339 24.686 73.6725 24.4204 72.4368 23.5619C71.2242 22.6804 70.6179 21.0925 70.6179 18.7981V11.9171H67.7404L67.7423 11.9094Z\" fill=\"#000000\"></path><path d=\"M84.2477 7.80371H79.9805V24.3471H84.2477V7.80371Z\" fill=\"#000000\"></path><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M94.3015 7.375C89.4973 7.375 85.6016 11.2707 85.6016 16.0769C85.6016 20.883 89.4973 24.7787 94.3015 24.7787C99.1057 24.7787 103.001 20.883 103.001 16.0769C103.001 11.2707 99.1076 7.375 94.3015 7.375V7.375ZM94.2861 20.6771C91.7377 20.6771 89.6705 18.6099 89.6705 16.0615C89.6705 13.5131 91.7377 11.4459 94.2861 11.4459C96.8345 11.4459 98.8998 13.5111 98.8998 16.0615C98.8998 18.6118 96.8345 20.6771 94.2861 20.6771V20.6771Z\" fill=\"#000000\"></path><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M51.2865 7.7715V8.68961C49.9526 7.85812 48.3782 7.375 46.6902 7.375C41.886 7.375 37.9902 11.2707 37.9902 16.0769C37.9902 20.883 41.886 24.7787 46.6902 24.7787C48.3782 24.7787 49.9526 24.2975 51.2865 23.4641V24.3822H55.521V7.7715H51.2865ZM46.6748 20.6771C44.1264 20.6771 42.0592 18.6099 42.0592 16.0615C42.0592 13.5131 44.1264 11.4459 46.6748 11.4459C49.2232 11.4459 51.2461 13.4707 51.2865 15.9845V16.1365C51.2461 18.6503 49.1981 20.6751 46.6748 20.6751V20.6771Z\" fill=\"#000000\"></path><path d=\"M30.6468 17.7823L28.0599 13.6422C28.0599 13.6422 28.0503 13.6248 28.0445 13.6172L27.8405 13.2919C27.4555 12.674 26.7895 12.3045 26.062 12.3025L21.8949 12.2891L21.6042 12.7549L16.6249 20.7234L16.3496 21.1642L18.4361 24.4978C18.821 25.1176 19.487 25.4872 20.2203 25.4872H26.06C26.7799 25.4872 27.4613 25.108 27.8424 24.4998L28.0483 24.1706C28.0483 24.1706 28.056 24.161 28.058 24.1572L30.6487 20.0112C31.0741 19.3337 31.0741 18.4579 30.6487 17.7823H30.6468ZM29.8576 19.5166L27.2669 23.6625C27.2553 23.6817 27.2419 23.6971 27.2303 23.7125C27.1398 23.8146 27.0224 23.828 26.9705 23.828C26.9108 23.828 26.7645 23.8107 26.6702 23.6606L24.0795 19.5146C24.0506 19.4684 24.0256 19.4203 24.0025 19.3683C23.9794 19.3183 23.9621 19.2683 23.9467 19.2163C23.8889 19.0084 23.8889 18.7851 23.9467 18.5773C23.9755 18.4753 24.0198 18.3732 24.0775 18.2809L26.6644 14.1388C26.6644 14.1388 26.6683 14.133 26.6702 14.1291C26.7318 14.0367 26.8088 13.9944 26.8762 13.9809C26.9031 13.9732 26.9262 13.9713 26.9454 13.9675C26.9551 13.9675 26.9647 13.9675 26.9743 13.9675C27.034 13.9675 27.1822 13.9867 27.2746 14.1368L29.8615 18.277C30.0982 18.6543 30.0982 19.1393 29.8615 19.5166H29.8576Z\" fill=\"#000000\"></path><path d=\"M22.9913 7.7644C23.4148 7.08496 23.4148 6.21112 22.9913 5.53553L20.4044 1.39536L20.1889 1.04697C19.802 0.429125 19.136 0.0595703 18.4046 0.0595703H12.5649C11.8354 0.0595703 11.1694 0.429125 10.7806 1.0489L0.323361 17.7847C0.113561 18.1196 0 18.5065 0 18.8992C0 19.2918 0.111636 19.6787 0.321436 20.0117L3.12582 24.5022C3.5127 25.1219 4.17866 25.4896 4.90815 25.4896H10.7479C11.4812 25.4896 12.1472 25.12 12.5321 24.5002L12.7458 24.1615C12.7458 24.1615 12.7458 24.1615 12.7458 24.1576C12.7458 24.1576 12.7496 24.1519 12.7496 24.1499L14.8342 20.8162L21.0127 10.9287L22.9875 7.76633L22.9913 7.7644ZM22.3812 6.64996C22.3812 6.86361 22.3215 7.07919 22.2002 7.26974L11.9566 23.6649C11.8643 23.8131 11.716 23.8304 11.6564 23.8304C11.5967 23.8304 11.4504 23.8131 11.3561 23.6649L8.7673 19.517C8.53248 19.1417 8.53248 18.6586 8.7673 18.2794L19.0109 1.8881C19.1033 1.73797 19.2515 1.72064 19.3112 1.72064C19.3708 1.72064 19.519 1.73797 19.6134 1.89002L22.2002 6.03019C22.3215 6.22074 22.3812 6.43632 22.3812 6.64996V6.64996Z\" fill=\"#000000\"></path></svg></svg>", "color": "#000000", "real": true}, "fireflies": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 1 22 22\" preserveAspectRatio=\"xMidYMid meet\"><path fill=\"url(#logo-with-text_svg__a)\" d=\"M7.36 2H.787v6.527H7.36z\"></path><path fill=\"url(#logo-with-text_svg__b)\" d=\"M15.149 9.88H8.574v6.526h6.575z\"></path><path fill=\"url(#logo-with-text_svg__c)\" d=\"M15.149 2H8.574v6.527h12.212v-.933a5.57 5.57 0 0 0-1.651-3.956A5.66 5.66 0 0 0 15.15 2z\"></path><path fill=\"url(#logo-with-text_svg__d)\" d=\"M.786 9.88v6.526c0 1.484.594 2.907 1.65 3.956A5.66 5.66 0 0 0 6.423 22h.939V9.88z\"></path><path fill=\"url(#logo-with-text_svg__e)\" d=\"M.786 2 7.36 8.527H.786z\" opacity=\"0.18\"></path><path fill=\"url(#logo-with-text_svg__f)\" d=\"m8.574 9.88 6.575 6.526H8.574z\" opacity=\"0.18\"></path><path fill=\"url(#logo-with-text_svg__g)\" d=\"M.786 16.406c0 1.484.594 2.907 1.65 3.956A5.66 5.66 0 0 0 6.423 22h.939V9.88z\" opacity=\"0.18\"></path><path fill=\"url(#logo-with-text_svg__h)\" d=\"M15.15 2c1.494 0 2.928.59 3.985 1.638a5.57 5.57 0 0 1 1.65 3.956v.933H8.576z\" opacity=\"0.18\"></path><defs><linearGradient id=\"logo-with-text_svg__a\" x1=\"16.868\" x2=\"-10.77\" y1=\"18.512\" y2=\"-10.526\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.113\" stop-color=\"#DE2D7A\"></stop><stop offset=\"0.3\" stop-color=\"#C5388F\"></stop><stop offset=\"0.54\" stop-color=\"#9B4AB0\"></stop><stop offset=\"0.818\" stop-color=\"#6262DE\"></stop><stop offset=\"0.994\" stop-color=\"#3B73FF\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__b\" x1=\"16.964\" x2=\"-10.674\" y1=\"18.423\" y2=\"-10.616\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#FF3C82\"></stop><stop offset=\"0.103\" stop-color=\"#F53E88\"></stop><stop offset=\"0.274\" stop-color=\"#DC4598\"></stop><stop offset=\"0.492\" stop-color=\"#B251B2\"></stop><stop offset=\"0.745\" stop-color=\"#7961D7\"></stop><stop offset=\"0.994\" stop-color=\"#3B73FF\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__c\" x1=\"21.555\" x2=\"12.19\" y1=\"14.055\" y2=\"-19.882\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.113\" stop-color=\"#DE2D7A\"></stop><stop offset=\"0.3\" stop-color=\"#C5388F\"></stop><stop offset=\"0.54\" stop-color=\"#9B4AB0\"></stop><stop offset=\"0.818\" stop-color=\"#6262DE\"></stop><stop offset=\"0.994\" stop-color=\"#3B73FF\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__d\" x1=\"12.338\" x2=\"-21.187\" y1=\"22.824\" y2=\"12.611\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.113\" stop-color=\"#DE2D7A\"></stop><stop offset=\"0.3\" stop-color=\"#C5388F\"></stop><stop offset=\"0.54\" stop-color=\"#9B4AB0\"></stop><stop offset=\"0.818\" stop-color=\"#6262DE\"></stop><stop offset=\"0.994\" stop-color=\"#3B73FF\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__e\" x1=\"-2.429\" x2=\"6.961\" y1=\"-6.152\" y2=\"15.365\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.114\" stop-color=\"#DE286E\"></stop><stop offset=\"0.303\" stop-color=\"#C52361\"></stop><stop offset=\"0.544\" stop-color=\"#9B1A4D\"></stop><stop offset=\"0.825\" stop-color=\"#620F30\"></stop><stop offset=\"0.994\" stop-color=\"#3D081E\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__f\" x1=\"5.359\" x2=\"14.749\" y1=\"1.727\" y2=\"23.245\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.114\" stop-color=\"#DE286E\"></stop><stop offset=\"0.303\" stop-color=\"#C52361\"></stop><stop offset=\"0.544\" stop-color=\"#9B1A4D\"></stop><stop offset=\"0.825\" stop-color=\"#620F30\"></stop><stop offset=\"0.994\" stop-color=\"#3D081E\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__g\" x1=\"-1.397\" x2=\"19.87\" y1=\"1.383\" y2=\"15.511\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.114\" stop-color=\"#DE286E\"></stop><stop offset=\"0.303\" stop-color=\"#C52361\"></stop><stop offset=\"0.544\" stop-color=\"#9B1A4D\"></stop><stop offset=\"0.825\" stop-color=\"#620F30\"></stop><stop offset=\"0.994\" stop-color=\"#3D081E\"></stop></linearGradient><linearGradient id=\"logo-with-text_svg__h\" x1=\"-464.769\" x2=\"-461.125\" y1=\"461.172\" y2=\"489.944\" gradientUnits=\"userSpaceOnUse\"><stop stop-color=\"#E82A73\"></stop><stop offset=\"0.114\" stop-color=\"#DE286E\"></stop><stop offset=\"0.303\" stop-color=\"#C52361\"></stop><stop offset=\"0.544\" stop-color=\"#9B1A4D\"></stop><stop offset=\"0.825\" stop-color=\"#620F30\"></stop><stop offset=\"0.994\" stop-color=\"#3D081E\"></stop></linearGradient><clipPath id=\"logo-with-text_svg__i\"><path fill=\"#fff\" d=\"M28.786 0h69.429v24h-69.43z\"></path></clipPath></defs></svg></svg>", "color": "#6262DE", "real": true}, "kit": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 400 181\" preserveAspectRatio=\"xMidYMid meet\"><path d=\"M109.562 75.1422c49.21 9.535 64.488 55.0968 64.903 100.9298 0 1.03-.831 1.878-1.86 1.878h-61.959c-1.03 0-1.86-.83-1.86-1.842-.181-35.557-5.942-66.925-41.1743-68.28-1.0474-.036-1.9322.795-1.9322 1.86v66.42c0 1.03-.8307 1.86-1.8601 1.86H1.86a1.857 1.857 0 0 1-1.86-1.86V6.8262c0-1.0294.8307-1.86 1.86-1.86h61.9775c1.0293 0 1.86.8306 1.86 1.86v63.4041c0 .939.7585 1.6975 1.6975 1.6975.7404 0 1.4086-.4876 1.6253-1.1919C84.9661 18.4379 114.781 5.2912 163.196 4.9842c1.03 0 1.86.8307 1.86 1.86v63.2416c0 1.0293-.83 1.86-1.86 1.86h-53.327c-.903 0-1.625.7224-1.625 1.6253 0 .7585.56 1.4266 1.318 1.5711Zm169.661 39.6388V73.7878c0-1.0293.831-1.86 1.861-1.86h45.598c.903 0 1.625-.7224 1.625-1.6253 0-.7765-.56-1.4447-1.318-1.5892-35.684-7.079-52.154-27.6117-52.714-61.8871-.018-1.0113.795-1.86 1.824-1.86h66.962c1.029 0 1.86.8306 1.86 1.86V35.702c0 1.0294.831 1.8601 1.86 1.8601h38.393c1.029 0 1.86.8307 1.86 1.86v30.6817c0 1.0294-.831 1.8601-1.86 1.8601h-38.393c-1.029 0-1.86.8307-1.86 1.86v33.0651c0 11.684 7.169 15.531 16.686 15.531 14.917 0 29.653-6.718 35.558-9.77 1.228-.632 2.709.253 2.709 1.643v51.468c0 1.372-.759 2.636-1.969 3.286-5.833 3.07-23.855 11.576-44.46 11.576-42.456-.036-74.222-17.318-74.222-65.842Zm-87.169 61.309V73.7878c0-1.0293.831-1.86 1.86-1.86h61.978c1.029 0 1.86.8307 1.86 1.86V176.09c0 1.03-.831 1.86-1.86 1.86h-61.978c-1.029-.018-1.86-.848-1.86-1.86Zm-3.521-144.5595c0 17.4086 12.298 31.5305 35.918 31.5305 23.621 0 35.919-14.1219 35.919-31.5305S248.09 0 224.451 0c-23.62 0-35.918 14.1219-35.918 31.5305Z\" fill=\"#1e1e1e\"/></svg></svg>", "color": "#1E1E1E", "real": true}, "circle": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 200 58\" preserveAspectRatio=\"xMidYMid meet\"><path d=\"M26.5583 57.3672C22.8697 57.3672 19.4023 56.6783 16.1563 55.3006C12.9103 53.8737 10.0823 51.9056 7.6724 49.3962C5.26248 46.8376 3.36897 43.8854 1.99187 40.5395C0.663958 37.1937 0 33.5772 0 29.6901C0 25.803 0.663958 22.2111 1.99187 18.9145C3.36897 15.5686 5.26248 12.641 7.6724 10.1316C10.0823 7.62225 12.9103 5.67871 16.1563 4.301C19.4023 2.8741 22.8697 2.16064 26.5583 2.16064C31.2306 2.16064 35.4603 3.12012 39.2473 5.03906C43.0835 6.958 46.2311 9.6396 48.6902 13.0839C51.1493 16.5281 52.674 20.5136 53.2642 25.0404H41.3867C40.9933 22.4818 40.0834 20.243 38.6571 18.3241C37.28 16.4051 35.5586 14.9044 33.493 13.8219C31.4765 12.7394 29.2141 12.1982 26.7059 12.1982C24.3943 12.1982 22.3041 12.6164 20.4351 13.4529C18.6154 14.2894 17.017 15.4948 15.6399 17.0694C14.312 18.6439 13.2792 20.5136 12.5414 22.6786C11.8529 24.7943 11.5086 27.1315 11.5086 29.6901C11.5086 32.2979 11.8529 34.6843 12.5414 36.8492C13.2792 38.965 14.312 40.8101 15.6399 42.3847C17.017 43.9592 18.6154 45.1893 20.4351 46.0749C22.3041 46.9114 24.3943 47.3296 26.7059 47.3296C29.2141 47.3296 31.5011 46.7884 33.5668 45.7059C35.6324 44.5742 37.3292 43.0489 38.6571 41.13C40.0342 39.1618 40.9441 36.923 41.3867 34.4137H53.2642C52.6248 38.9896 51.0756 42.9997 48.6165 46.444C46.1574 49.8882 43.0343 52.5698 39.2473 54.4888C35.4603 56.4077 31.2306 57.3672 26.5583 57.3672Z\" fill=\"#191B1F\"/><path d=\"M68.9876 56.2601H58.7332V16.8479H68.9876V56.2601Z\" fill=\"#191B1F\"/><path d=\"M86.892 37.1445V56.2601H76.6376V16.8479H86.0805V24.4499C87.556 21.9405 89.6954 19.9724 92.4988 18.5455C95.3022 17.1186 98.2777 16.4051 101.425 16.4051V27.0331C98.5728 26.8363 96.0399 26.9839 93.8267 27.4759C91.6627 27.9188 89.9659 28.9274 88.7364 30.502C87.5068 32.0273 86.892 34.2414 86.892 37.1445Z\" fill=\"#191B1F\"/><path d=\"M121.587 56.9981C117.8 56.9981 114.456 56.1371 111.554 54.415C108.702 52.6928 106.464 50.2818 104.841 47.182C103.218 44.0822 102.406 40.5395 102.406 36.554C102.406 32.6177 103.218 29.1243 104.841 26.0736C106.513 22.9738 108.8 20.5382 111.702 18.7669C114.603 16.9956 117.899 16.1099 121.587 16.1099C124.981 16.1099 128.055 16.8479 130.809 18.3241C133.563 19.751 135.801 21.7929 137.522 24.4499C139.244 27.0577 140.301 30.1329 140.695 33.6756H129.924C129.678 31.0678 128.792 29.0013 127.268 27.4759C125.792 25.9506 123.899 25.188 121.587 25.188C119.817 25.188 118.267 25.6554 116.94 26.5903C115.661 27.5251 114.653 28.829 113.915 30.502C113.226 32.1749 112.882 34.1922 112.882 36.554C112.882 38.8666 113.226 40.8839 113.915 42.6061C114.653 44.3282 115.661 45.6567 116.94 46.5916C118.267 47.4772 119.817 47.9201 121.587 47.9201C123.948 47.9201 125.842 47.182 127.268 45.7059C128.743 44.1806 129.629 42.0894 129.924 39.4324H140.695C140.35 43.0243 139.317 46.1487 137.596 48.8057C135.875 51.4135 133.661 53.4309 130.956 54.8578C128.251 56.2847 125.128 56.9981 121.587 56.9981Z\" fill=\"#191B1F\"/><path d=\"M156.131 56.2601H145.803V3.26773L156.131 3.26773V56.2601Z\" fill=\"#191B1F\"/><path d=\"M180.967 56.9243C177.032 56.9243 173.565 56.0879 170.565 54.415C167.614 52.6928 165.327 50.2818 163.704 47.182C162.081 44.0822 161.269 40.4903 161.269 36.4064C161.269 32.4701 162.105 28.9767 163.777 25.926C165.45 22.8754 167.761 20.489 170.712 18.7669C173.663 16.9956 177.032 16.1099 180.819 16.1099C183.917 16.1099 186.721 16.7003 189.229 17.8812C191.787 19.0129 193.926 20.6366 195.647 22.7524C197.369 24.8681 198.598 27.3283 199.336 30.1329C200.074 32.8883 200.197 35.8652 199.705 39.0634H167.319V32.5685H188.86C188.762 29.8131 187.95 27.6482 186.426 26.0736C184.95 24.4499 183.008 23.6381 180.598 23.6381C178.68 23.6381 177.057 24.1301 175.729 25.1142C174.401 26.0982 173.368 27.5497 172.63 29.4687C171.942 31.3384 171.597 33.651 171.597 36.4064C171.597 39.1126 171.942 41.4006 172.63 43.2703C173.319 45.1401 174.352 46.567 175.729 47.551C177.106 48.5351 178.778 49.0272 180.745 49.0272C183.008 49.0272 184.877 48.4859 186.352 47.4034C187.827 46.3209 188.86 44.8202 189.45 42.9013H199.631C198.5 47.3296 196.311 50.7739 193.065 53.2341C189.819 55.6943 185.786 56.9243 180.967 56.9243Z\" fill=\"#191B1F\"/><path d=\"M70.5386 7.01152C70.5386 9.02888 69.8992 10.7018 68.6205 12.0303C67.3418 13.3096 65.6942 13.9492 63.6777 13.9492C61.6613 13.9492 59.9891 13.3096 58.6611 12.0303C57.3824 10.7018 56.743 9.02888 56.743 7.01152C56.743 4.94497 57.3824 3.27205 58.6611 1.99275C59.9891 0.664252 61.6613 0 63.6777 0C65.6942 0 67.3418 0.664252 68.6205 1.99275C69.8992 3.27205 70.5386 4.94497 70.5386 7.01152Z\" fill=\"#506CF0\"/></svg></svg>", "color": "#506CF0", "real": true}, "vidiq": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 16 16\" preserveAspectRatio=\"xMidYMid meet\"><g clip-path=\"url(#a)\"><path fill=\"#2574F5\" d=\"M0 0h16v16H0z\"/><path fill=\"#0A0D15\" d=\"m3 3 12 5-12 5V3Z\"/><g filter=\"url(#b)\"><path fill=\"#F7F7F7\" fill-rule=\"evenodd\" d=\"m11.506 9.708 1.122 1.094-.857.873-1.158-1.129c-.43.205-.989.31-1.706.31-2.01 0-2.939-.882-2.939-2.901 0-1.96 1.009-2.9 2.94-2.9 1.854 0 2.942.94 2.944 2.9 0 .711-.101 1.299-.346 1.753ZM8.907 6.555c-.857 0-1.396.507-1.396 1.4 0 .892.533 1.411 1.396 1.4.845-.009 1.388-.437 1.396-1.4.009-.895-.538-1.4-1.396-1.4ZM5.59 5.107H3.965v5.644H5.59V5.107Z\" clip-rule=\"evenodd\"/></g></g><defs><clipPath id=\"a\"><path fill=\"#fff\" d=\"M0 0h16v16H0z\"/></clipPath><filter id=\"b\" width=\"19.927\" height=\"27.442\" x=\"-1.667\" y=\"3.945\" color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"/><feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/><feOffset dy=\".853\"/><feGaussianBlur stdDeviation=\".981\"/><feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0\"/><feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow_9_207\"/><feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/><feOffset dy=\"3.499\"/><feGaussianBlur stdDeviation=\"1.749\"/><feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0\"/><feBlend in2=\"effect1_dropShadow_9_207\" result=\"effect2_dropShadow_9_207\"/><feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/><feOffset dy=\"7.936\"/><feGaussianBlur stdDeviation=\"2.389\"/><feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0\"/><feBlend in2=\"effect2_dropShadow_9_207\" result=\"effect3_dropShadow_9_207\"/><feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/><feOffset dy=\"14.08\"/><feGaussianBlur stdDeviation=\"2.816\"/><feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0\"/><feBlend in2=\"effect3_dropShadow_9_207\" result=\"effect4_dropShadow_9_207\"/><feBlend in=\"SourceGraphic\" in2=\"effect4_dropShadow_9_207\" result=\"shape\"/></filter></defs></svg></svg>", "color": "#2574F5", "real": true}, "posthog": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 300 300\" preserveAspectRatio=\"xMidYMid meet\"><rect width=\"300\" height=\"300\" fill=\"#000\"/><path fill=\"#fff\" d=\"M33 179.379L72.0038 218.33H33V179.379ZM33 169.641L81.7548 218.33H120.759L33 130.689V169.641ZM33 120.951L130.51 218.33H169.513L33 82V120.951ZM81.7548 120.951L179.264 218.33V179.379L81.7548 82V120.951ZM130.51 82V120.951L179.264 169.641V130.689L130.51 82Z\"/><path fill=\"#fff\" d=\"M266.863 203.174C256.87 203.174 247.291 199.208 240.231 192.158L186 138V218.754H266.863V203.174Z\"/><path fill=\"#000\" d=\"M209.563 202.75C213.871 202.75 217.363 199.262 217.363 194.959C217.363 190.657 213.871 187.169 209.563 187.169C205.254 187.169 201.762 190.657 201.762 194.959C201.762 199.262 205.254 202.75 209.563 202.75Z\"/><path fill=\"#fff\" d=\"M33 218.33H72.0038L33 179.379V218.33Z\"/><path fill=\"#fff\" d=\"M81.7548 130.689L33 82V120.951L81.7548 169.641V130.689Z\"/><path fill=\"#fff\" d=\"M33 130.689V169.641L81.7548 218.33V179.379L33 130.689Z\"/><path fill=\"#fff\" d=\"M130.51 130.689L81.7548 82V120.951L130.51 169.641V130.689Z\"/><path fill=\"#fff\" d=\"M81.7548 218.33H120.759L81.7548 179.379V218.33Z\"/><path fill=\"#fff\" d=\"M81.7548 130.689V169.641L130.51 218.33V179.379L81.7548 130.689Z\"/></svg></svg>", "color": "#000000", "real": true}, "apify": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 1080 1080\" preserveAspectRatio=\"xMidYMid meet\"><path d=\"M607.859 78.2218H987.785C995.513 78.2218 1001.78 84.4868 1001.78 92.2151V672.834C1001.78 686.742 983.69 692.134 976.075 680.496L596.15 99.877C590.06 90.5703 596.737 78.2218 607.859 78.2218Z\" fill=\"#246DFF\"/><path d=\"M472.141 78.2218H92.215C84.4867 78.2218 78.2217 84.4868 78.2217 92.2151V672.834C78.2217 686.742 96.3094 692.134 103.924 680.496L483.85 99.877C489.94 90.5703 483.263 78.2218 472.141 78.2218Z\" fill=\"#20A34E\"/><path d=\"M533.491 543.086L101.895 977.927C93.1302 986.758 99.3849 1001.78 111.826 1001.78H968.529C980.919 1001.78 987.197 986.863 978.535 978.003L553.429 543.161C547.969 537.576 538.993 537.542 533.491 543.086Z\" fill=\"#F86606\"/></svg></svg>", "color": "#246DFF", "real": true}, "higgsfield": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 20 20\" preserveAspectRatio=\"xMidYMid meet\"><path d=\"M18.3498 9.83713L18.3339 9.65759C18.1831 7.93447 17.0963 4.69261 14.0816 4.69261C11.8445 4.69261 10.1545 6.97097 8.66311 8.97967C7.47302 10.5883 6.4419 11.9683 5.3073 11.9683C5.00574 11.9357 4.61708 11.7805 4.3792 11.4294C4.16497 11.1108 4.10948 10.7026 4.22046 10.2126C4.39489 9.43684 5.39463 8.7182 6.44963 7.95063C7.02864 7.54238 7.6238 7.10955 8.03634 6.69311C9.22643 5.5091 9.82932 4.65164 9.82932 3.2717C9.82932 1.89176 9.09157 1.20565 8.47276 0.911636C7.23514 0.323844 5.41851 0.666781 4.26026 1.69583C4.08583 1.85922 3.91117 2.01418 3.75243 2.16119C2.58622 3.23097 1.80094 3.95781 0 3.40232V5.63972C2.38791 6.72588 4.39512 4.65164 5.15675 3.69633C5.74372 3.06758 6.36253 2.70006 6.82283 2.70006H6.84671C7.05298 2.70825 7.22741 2.78995 7.35454 2.93696C7.56081 3.18204 7.64018 3.46786 7.60038 3.78622C7.51305 4.45594 6.83875 5.23967 5.60113 6.09713C4.14928 7.10159 1.7218 8.78374 1.53122 10.8987C1.3884 12.4177 2.15003 13.9365 3.34012 14.5243C6.11669 15.8798 7.80665 13.5444 9.5994 11.0783C10.9719 9.1756 12.273 7.37103 14.0818 7.37103C15.7081 7.37103 16.311 8.75916 16.311 9.63301V9.80459L16.1523 9.83713C12.2095 10.5558 10.0595 14.3611 10.0595 16.1167C10.0595 17.8724 11.5034 19.375 13.2804 19.375C15.359 19.375 17.9293 17.5458 18.3419 12.4013L18.3578 12.2136H20V9.83737H18.3498V9.83713ZM16.1998 12.4746C15.8826 15.5531 14.3513 16.9904 13.4232 16.9904C13.0027 16.9904 12.4158 16.631 12.4158 15.9615C12.4158 15.2104 13.5026 12.932 15.946 12.2543L16.2316 12.1808L16.1998 12.4748V12.4746Z\" fill=\"#030304\"></path></svg></svg>", "color": "#030304", "real": true}, "anymailfinder": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 38 38\" preserveAspectRatio=\"xMidYMid meet\"><g fill=\"#0073e6\"><path clip-rule=\"evenodd\" d=\"M0.914602 12.1473C0.914602 12.1473 13.8811 21.2685 19.0491 22.5118C16.5611 25.4521 9.66107 31.2255 9.75306 31.167C17.1059 26.8151 32.5413 13.7506 32.5413 13.7506C33.02 13.4454 33.5147 13.6719 33.6455 14.2523L37.3308 30.6191C37.4615 31.1995 37.0496 31.7654 36.4095 31.8833L6.78525 37.3397C6.1457 37.4575 5.47651 36.8836 5.29052 36.0576L0.0463848 12.7683C-0.13958 11.9425 0.250498 11.6686 0.914602 12.1473ZM2.52542 9.77466C2.52542 9.77466 19.3996 -0.381419 21.4381 0.011091C23.428 0.394256 31.1593 11.1758 31.5264 11.689L31.5399 11.7079C31.8475 12.0512 31.6451 12.3014 31.0874 12.2682L2.42364 10.571C1.86514 10.5381 1.91192 10.1802 2.52542 9.77466Z\" fill-rule=\"evenodd\"></path></g></svg></svg>", "color": "#0073E6", "real": true}, "composio": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 64 64\" preserveAspectRatio=\"xMidYMid meet\"><g clip-path=\"url(#clip0_2129_471)\"><g clip-path=\"url(#clip1_2129_471)\"><path\n\t\t\t\td=\"M58.5409 18.0442L22.4819 10.6695C20.1176 10.1841 17.8943 12.0003 17.8943 14.4116V31.4939V32.402V49.4842C17.8943 51.8955 20.1176 53.712 22.4819 53.2265L58.5409 45.8518\"\n\t\t\t\tstroke=\"black\"\n\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\tstroke-miterlimit=\"10\"\n\t\t\t\tstroke-width=\"1.82758\"\n\t\t\t/><path\n\t\t\t\td=\"M30.6983 4.73539C30.6984 1.34782 34.161 -0.917709 37.2617 0.379183L37.4093 0.443562L37.4126 0.445442L56.7025 9.35428C58.3954 10.1174 59.4565 11.8082 59.4569 13.6442V21.1912C59.4569 23.9444 57.112 26.1189 54.3726 25.9069L32.5258 24.2763V39.6193L54.3692 37.9887L54.6252 37.9755C57.2487 37.9116 59.456 40.0302 59.4406 42.6889V50.2358C59.4406 52.086 58.3516 53.7519 56.6895 54.5248L56.6867 54.5257L37.413 63.4183L37.4135 63.4188C34.2705 64.8735 30.6983 62.5825 30.6983 59.1294V51.9373C30.5567 51.9931 30.405 52.0302 30.2458 52.0417L19.585 52.8093C18.6942 52.8733 17.9362 52.1673 17.9361 51.2742V43.3595C17.9361 43.0526 18.0277 42.7648 18.1851 42.5225L9.41491 43.1776H9.41164C6.67967 43.3713 4.33082 41.2037 4.33081 38.4614V25.4342C4.33101 22.6801 6.67776 20.5047 9.41823 20.7185H9.41775L17.9939 21.3585C17.9567 21.2261 17.9361 21.0869 17.9361 20.9431V12.6057C17.9361 11.3884 19.025 10.4599 20.227 10.6522L30.3783 12.2763C30.4899 12.2941 30.5967 12.3247 30.6983 12.3646V4.73539ZM54.5116 39.8111H54.5083L32.5258 41.452V50.9913L57.6135 45.7476V42.6823L57.6106 42.5272C57.5355 40.9328 56.1381 39.6842 54.5116 39.8111ZM17.5836 23.1607C17.7369 23.4005 17.8261 23.6847 17.8261 23.9882V40.1889C17.8261 40.3767 17.7909 40.5566 17.7289 40.7236L30.6983 39.7556V24.1395L17.5836 23.1607ZM32.5258 22.4436L54.5083 24.0845L54.5116 24.085L54.6675 24.093C56.2752 24.1322 57.6293 22.8309 57.6293 21.1912V18.0187L32.5258 12.7711V22.4436Z\"\n\t\t\t\tfill=\"black\"\n\t\t\t/></g></g><defs><clipPath id=\"clip0_2129_471\"><rect fill=\"white\" height=\"64\" width=\"64\" /></clipPath><clipPath id=\"clip1_2129_471\"><rect\n\t\t\t\tfill=\"white\"\n\t\t\t\theight=\"64\"\n\t\t\t\ttransform=\"translate(4.33081 0.00878906)\"\n\t\t\t\twidth=\"55.3383\"\n\t\t\t/></clipPath></defs></svg></svg>", "color": "#000000", "real": true}, "firecrawl": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"8 44 570 570\" preserveAspectRatio=\"xMidYMid meet\"><g><g transform=\" translate(293.035, 553.013) scale(0.97724, 0.97724) translate(-533.035, -800.013)\"><path d=\" M603.36 416.33 C581,433 586.63,450.25 583.86,466.55 C583.19,470.47 577.75,469.25 576.54,465.71 C559.5,447 549.55,423.61 559.33,394.37 C577.25,340.75 614.25,311.25 594.16,288.45 C590.97,284.83 591.83,284.26 590.22,288.82 C572.5,339 363,338 427.98,536 C430.85,544.77 430.25,555.25 429.51,565.8 C429.28,568.95 427.08,571.32 424.17,570.12 C401.5,560.75 395.38,525.75 390.42,516.28 C389,513.58 387.5,514.5 385.67,517.95 C381.03,524.07 377.94,532.3 374.2,538.54 C336.92,600.69 343.58,664.33 368.03,714.96 C368.94,716.86 369.89,718.74 370.85,720.6 C371.93,722.68 373.05,724.75 374.19,726.79 C391.8,758.26 416.04,783.76 439.75,799.32 C442.6,801.19 446.26,798.52 445.29,795.24 C437.07,767.62 642.75,744.75 634.67,795.2 C634.12,798.62 637.29,801.28 640.2,799.38 C659.88,786.47 680.25,766.82 695.21,741.99 C696.41,740.01 697.57,737.99 698.7,735.93 C699.47,734.52 700.23,733.09 700.97,731.65 C711.2,711.65 717.8,688.75 718.09,663.65 C718.33,643.75 714.58,622.45 705.52,600.11 C703.78,595.83 700.25,616.5 684.38,613.26 C682.86,612.95 691.25,586.13 692.06,570.64 C692.44,563.26 690.67,544.7 683.23,524.06 C667.77,481.12 615.5,466.25 609.58,417.31 C609.25,414.61 605.53,414.71 603.36,416.33z \" fill=\"#FA5D19\" fill-opacity=\"1\" fill-rule=\"nonzero\"></path></g><g transform=\" translate(300, 470.504) scale(0.9650799999999999, 0.9650799999999999) translate(-510.283, -685.815)\"><path d=\" M410.06 771.87 C412.91,773.74 416.57,771.07 415.6,767.79 C407.38,740.17 411.54,708.64 427.68,684.63 C455.29,643.16 510.65,603.1 501.81,548.71 C501.24,545.26 505.31,542.99 507.87,545.36 C546.86,581 554.59,628.95 548.18,671.96 C547.63,675.7 552.32,677.69 554.68,674.76 C560.64,667.29 567.92,660.74 575.85,655.81 C577.82,654.59 580.46,655.52 581.21,657.72 C594.24,695.64 617.69,725.57 604.98,767.75 C603.97,771.07 607.6,773.83 610.51,771.93 C610.51,771.93 610.51,827.25 610.51,827.25 C610.51,827.25 410.06,827.25 410.06,827.25 C410.06,827.25 410.06,771.87 410.06,771.87z \" fill=\"#FA5D19\" fill-opacity=\"1\" fill-rule=\"nonzero\"></path></g></g></svg></svg>", "color": "#FA5D19", "real": true}, "pipedrive": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect x=\"0.5\" y=\"0.5\" width=\"31\" height=\"31\" rx=\"8\" fill=\"#ffffff\" stroke=\"#d9d9d9\"/><svg x=\"5\" y=\"5\" width=\"22\" height=\"22\" viewBox=\"0 0 32 32\" preserveAspectRatio=\"xMidYMid meet\"><g fill=\"#FFFFFF\"><g clip-path=\"url(#clip0_503_588)\"><path fill=\"#017737\" d=\"M32 16C32 24.8366 24.8366 32 16 32C7.16344 32 0 24.8366 0 16C0 7.16344 7.16344 0 16 0C24.8366 0 32 7.16344 32 16Z\"></path><path d=\"M24.9842 13.4564C24.9842 17.8851 22.1247 20.914 18.036 20.914C16.0923 20.914 14.4903 20.1136 13.8906 19.1134L13.9189 20.142V26.4847H9.74512V10.0846C9.74512 9.85644 9.68836 9.79843 9.4304 9.79843H8V6.31321H11.4889C13.0896 6.31321 13.4907 7.68461 13.6042 8.28525C14.2337 7.22834 15.8911 6 18.2359 6C22.2679 5.99871 24.9842 8.99802 24.9842 13.4564ZM20.724 13.4847C20.724 11.1131 19.1801 9.48523 17.2351 9.48523C15.6344 9.48523 13.8325 10.5421 13.8325 13.5144C13.8325 15.4568 14.9186 17.4855 17.1783 17.4855C18.837 17.4842 20.724 16.2843 20.724 13.4847Z\" fill=\"#FFFFFF\"></path></g></g></svg></svg>", "color": "#017737", "real": true}, "pandadoc": {"svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\" width=\"32\" height=\"32\"><rect width=\"32\" height=\"32\" rx=\"8\" fill=\"#248567\"/><text x=\"16\" y=\"21.5\" text-anchor=\"middle\" font-family=\"-apple-system, Helvetica, Arial, sans-serif\" font-size=\"16\" font-weight=\"700\" fill=\"#ffffff\">P</text></svg>", "color": "#248567", "real": false}}
4types/index.d.ts 88 lines1/** One call a connector made in this chat. */
2export type CallRow = {
3 /** Humanised tool name: "search threads". */
4 tool: string
5 /** The main argument, short: a query, an id, a file name. */
6 summary: string
7 /** Milliseconds since the epoch; 0 when unknown. */
8 at: number
9 /** True for a CLI call made through Bash. */
10 cli: boolean
11}
12
13/** One connector, with every call it made. */
14export type ConnectorRow = {
15 /** Logo key and press address: "gmail", "fireflies". */
16 key: string
17 name: string
18 count: number
19 /** Order of last use: higher is newer. */
20 seq: number
21 /** Used through a CLI in Bash. */
22 cli: boolean
23 /** Used through an MCP tool. */
24 mcp: boolean
25 /** Newest last; capped. */
26 calls: CallRow[]
27}
28
29/** One skill, with how many times this chat used it. */
30export type SkillRow = {
31 name: string
32 count: number
33 seq: number
34 /** Loaded at start through a memory file (CLAUDE.md import). */
35 always: boolean
36}
37
38/** One file in the chat's context. */
39export type FileRow = {
40 /** Absolute path. */
41 path: string
42 /** True for a memory file the chat loaded at start (CLAUDE.md, AGENTS.md, MEMORY.md). */
43 auto: boolean
44 seq: number
45}
46
47export type Inventory = {
48 connectors: ConnectorRow[]
49 files: FileRow[]
50 skills: SkillRow[]
51}
52
53/** One step of this chat's to-do list. */
54export type PlanStep = {
55 text: string
56 status: 'pending' | 'in_progress' | 'completed'
57 /** TodoWrite's present-tense form, shown while the step is in progress. */
58 active?: string
59 /** TaskCreate's id, so TaskUpdate finds the step. */
60 id?: string
61}
62
63/** The to-do list: from the shared plan file, or from Claude's own plan tool calls. Newest wins. */
64export type Plan = {
65 title: string
66 steps: PlanStep[]
67 /** Milliseconds since the epoch of the last change; 0 for none. */
68 updatedAt: number
69}
70
71declare module 'claude-code' {
72 interface PluginState {
73 'chat-inventory': {
74 inv: Inventory
75 /** The to-do list shown at the top of the pane. */
76 plan: Plan
77 /** Key of the connector whose call list is open; '' for none. */
78 open: string
79 /** True when switches.json turns the mod off. */
80 off: boolean
81 /** Sections the person closed with the header arrow: todo, connectors, files, skills. */
82 folded: string[]
83 /** First context file row shown in the 10-row window. */
84 fileTop: number
85 }
86 }
87}
88