multi-ccp 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta name="ccp-ui-token" content="__CCP_UI_TOKEN__" />
7
+ <title>multi-ccp</title>
8
+ <link rel="stylesheet" href="/styles.css" />
9
+ </head>
10
+ <body>
11
+ <div class="grain" aria-hidden="true"></div>
12
+ <main class="shell">
13
+ <header class="topbar">
14
+ <section class="brand-block">
15
+ <div class="brand-mark">ccp</div>
16
+ <div>
17
+ <h1>multi-ccp</h1>
18
+ </div>
19
+ </section>
20
+ <section class="top-actions">
21
+ <button class="ghost icon-action icon-only" id="themeToggle" type="button" aria-label="切换深色" title="切换深色"><span class="ui-icon" data-icon="moon"></span></button>
22
+ <button class="ghost icon-action icon-only" id="refreshBtn" type="button" aria-label="刷新" title="刷新"><span class="ui-icon" data-icon="refresh"></span></button>
23
+ <button class="primary icon-action" id="newProfileBtn" type="button"><span class="ui-icon" data-icon="plus"></span><span>New</span></button>
24
+ </section>
25
+ </header>
26
+
27
+ <section class="summary-grid" id="summaryGrid" aria-live="polite"></section>
28
+
29
+ <section class="workspace" id="workspace">
30
+ <div class="board" id="profileBoard"></div>
31
+ <aside class="drawer" id="drawer" aria-live="polite" aria-hidden="true">
32
+ <div class="drawer-rail">
33
+ <button class="icon-btn" id="drawerClose" type="button" title="关闭">×</button>
34
+ </div>
35
+ <div class="empty-drawer">
36
+ <p class="eyebrow">profile details</p>
37
+ <h2>选择一个 Profile</h2>
38
+ <p>点击左侧卡片后,详情和编辑面板会从右侧展开。</p>
39
+ </div>
40
+ </aside>
41
+ </section>
42
+ </main>
43
+
44
+ <dialog id="newProfileDialog" class="modal">
45
+ <form method="dialog" class="modal-card" id="newProfileForm">
46
+ <div class="modal-head">
47
+ <div>
48
+ <p class="eyebrow">create profile</p>
49
+ <h2>New Profile</h2>
50
+ </div>
51
+ <button class="icon-btn" value="cancel" formnovalidate type="button" data-dialog-close="newProfileDialog">×</button>
52
+ </div>
53
+ <div class="preset-layout">
54
+ <aside class="preset-picker">
55
+ <div class="preset-search">
56
+ <span class="ui-icon" data-icon="search"></span>
57
+ <input id="presetSearch" type="search" placeholder="搜索预设..." autocomplete="off" />
58
+ </div>
59
+ <div class="preset-filters" id="presetFilters">
60
+ <button class="chip active" type="button" data-preset-filter="all">All</button>
61
+ <button class="chip" type="button" data-preset-filter="api">API</button>
62
+ <button class="chip" type="button" data-preset-filter="ccr">CCR</button>
63
+ <button class="chip" type="button" data-preset-filter="custom">Custom</button>
64
+ <button class="chip" type="button" data-preset-filter="login">Login</button>
65
+ </div>
66
+ <div class="preset-list" id="presetList"></div>
67
+ </aside>
68
+ <section class="preset-detail">
69
+ <input type="hidden" name="kind" id="newKind" value="api" />
70
+ <input type="hidden" name="presetId" id="presetId" value="custom-api" />
71
+ <div id="presetSummary" class="preset-summary"></div>
72
+ <label>Profile 名称 <input name="name" id="newProfileName" required autocomplete="off" /></label>
73
+ <div data-kind-fields="api">
74
+ <label>API Key <input name="token" id="newToken" type="password" placeholder="输入 key;留空则写入占位符" /></label>
75
+ </div>
76
+ <div data-kind-fields="custom-api" hidden>
77
+ <label>Base URL <input name="baseUrl" required placeholder="https://api.example.com/anthropic" /></label>
78
+ <label>Auth Token <input name="customToken" type="password" placeholder="留空则写入占位符" /></label>
79
+ <label>Model <input name="model" placeholder="留空使用 Claude Code 默认模型" /></label>
80
+ </div>
81
+ <div data-kind-fields="ccr" hidden>
82
+ <label>CCR Token <input name="ccrToken" type="password" placeholder="留空使用预设默认值" /></label>
83
+ <p class="hint">该模板会按预设模型路由生成 CCR preset。CCR provider/model 请在 CCR UI 中管理。</p>
84
+ </div>
85
+ <div data-kind-fields="manual-ccr" hidden>
86
+ <label>模型路由 <select name="route" id="manualCcrRoute" required><option value="">加载 CCR 路由中...</option></select></label>
87
+ <label>CCR Preset 名称 <input name="manualCcrPreset" placeholder="默认使用 Profile 名称" autocomplete="off" /></label>
88
+ <label>CCR Token <input name="manualCcrToken" type="password" placeholder="留空使用 ccr-local-secret" /></label>
89
+ <p class="hint">模型路由来自 Claude Code Router 的 provider/model 配置;如果没有想要的模型,请先打开 CCR UI 添加。</p>
90
+ </div>
91
+ <div data-kind-fields="login" hidden>
92
+ <p class="hint">Login Profile 不保存 Claude 账号密码,只隔离 Claude Code 的登录状态。</p>
93
+ </div>
94
+ </section>
95
+ </div>
96
+ <menu class="modal-actions">
97
+ <button class="ghost" value="cancel" formnovalidate type="button" data-dialog-close="newProfileDialog">取消</button>
98
+ <button class="primary" id="createProfileSubmit" value="default" type="button">创建</button>
99
+ </menu>
100
+ <div class="dialog-toast-region"></div>
101
+ </form>
102
+ </dialog>
103
+
104
+ <dialog id="ccrDialog" class="modal">
105
+ <div class="modal-card ccr-card" id="ccrPanel"></div>
106
+ </dialog>
107
+
108
+ <div class="toast-region" id="toastRegion"></div>
109
+ <script src="/app.js" type="module"></script>
110
+ </body>
111
+ </html>
@@ -0,0 +1 @@
1
+ :root{color-scheme:light;--bg:#f5f3ee;--panel:#fffdf8;--panel-2:#ffffff;--ink:#191815;--muted:#726d64;--faint:#a29a90;--line:#ded8cf;--accent:#9b5a36;--blue:#405f9f;--green:#2f7358;--orange:#a86722;--red:#ad4747;--chip:#efe8dd;--shadow:0 10px 30px rgba(40,34,26,.08);--radius:16px;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--sans:"Aptos","Segoe UI Variable","Segoe UI",system-ui,-apple-system,sans-serif}html[data-theme=dark]{color-scheme:dark;--bg:#141412;--panel:#1d1c19;--panel-2:#24231f;--ink:#eee8de;--muted:#aaa196;--faint:#7e766d;--line:#39352e;--accent:#d98b5d;--blue:#91aef0;--green:#73c49f;--orange:#dfb168;--red:#e07b77;--chip:#2c2822;--shadow:0 12px 34px rgba(0,0,0,.32)}*{box-sizing:border-box}html,body{height:100%}body{margin:0;overflow:hidden;background:var(--bg);color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased}body:before{content:"";position:fixed;inset:0;pointer-events:none;background:radial-gradient(circle at 8% -8%,rgba(155,90,54,.12),transparent 34%),radial-gradient(circle at 100% 0,rgba(64,95,159,.1),transparent 28%)}.grain{display:none}button,input,select{font:inherit}button{border:0;cursor:pointer}.shell{position:relative;width:min(1500px,100% - 24px);height:100vh;margin:0 auto;padding:12px 0;display:grid;grid-template-rows:auto auto minmax(0,1fr);gap:8px}.topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 10px;border:1px solid var(--line);border-radius:18px;background:color-mix(in srgb,var(--panel) 94%,transparent);box-shadow:var(--shadow)}.brand-block{display:flex;align-items:center;gap:10px}.brand-mark{width:34px;height:34px;display:grid;place-items:center;border-radius:11px;background:var(--ink);color:var(--bg);font-family:var(--mono);font-size:11px;font-weight:800;letter-spacing:-.04em}.eyebrow{margin:0 0 2px;color:var(--accent);text-transform:uppercase;letter-spacing:.16em;font-family:var(--mono);font-size:9.5px;font-weight:800}.topbar h1{margin:0;font-size:18px;line-height:1;letter-spacing:-.035em}.top-actions,.filters,.view-switch,.modal-actions{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.ui-icon,.icon-action>svg,.icon-action .ui-icon svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}.icon-action{white-space:nowrap}.icon-only{width:36px;min-width:36px;height:36px;padding:0}.icon-only svg{display:block;margin:auto}.primary,.ghost,.chip,.icon-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:31px;border-radius:999px;padding:7px 11px;color:var(--ink);background:var(--panel);border:1px solid var(--line);transition:background .16s,border-color .16s,transform .16s}.primary{background:var(--ink);color:var(--bg);border-color:var(--ink);font-weight:760}.ghost:hover,.chip:hover,.icon-btn:hover{background:var(--chip);border-color:color-mix(in srgb,var(--accent) 35%,var(--line))}.chip{min-height:27px;padding:5px 9px;font-size:11.5px;color:var(--muted)}.chip.active{background:var(--ink);border-color:var(--ink);color:var(--bg)}.summary-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:7px}.metric{height:48px;padding:8px 11px;border:1px solid var(--line);background:var(--panel);border-radius:14px;box-shadow:0 5px 14px rgba(40,34,26,.035);display:grid;grid-template-columns:1fr auto;align-items:center;gap:8px;position:relative;overflow:hidden}.metric:before{content:"";position:absolute;left:0;top:10px;bottom:10px;width:3px;border-radius:999px;background:var(--faint);opacity:.55}.metric.api:before{background:var(--blue)}.metric.login:before{background:var(--green)}.metric.ccr:before,.metric.ccr-status:before{background:var(--orange)}.metric.attention:before{background:var(--red)}.metric b{font-size:17px;line-height:1;letter-spacing:-.045em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metric span{color:var(--muted);font-family:var(--mono);font-size:9.5px;text-transform:uppercase;letter-spacing:.08em}#ccrMetric{cursor:pointer}#ccrMetric b{display:inline-block;border-bottom:1px solid var(--accent);padding-bottom:2px;line-height:1.05}.workspace{min-height:0;display:grid;grid-template-columns:minmax(0,1fr) 0;gap:0;transition:grid-template-columns .28s cubic-bezier(.2,.8,.2,1),gap .28s cubic-bezier(.2,.8,.2,1)}.workspace.drawer-open{grid-template-columns:minmax(0,1fr) 390px;gap:10px}.board,.drawer{min-height:0;scrollbar-width:thin;scrollbar-color:var(--line) transparent}.board{overflow:auto;padding:2px 2px 18px}.board-toolbar{position:sticky;top:0;z-index:4;display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 8px;padding:7px;border:1px solid var(--line);border-radius:16px;background:color-mix(in srgb,var(--panel) 96%,transparent);box-shadow:0 6px 18px rgba(40,34,26,.045)}.board-tools-left,.board-tools-right{display:flex;align-items:center;gap:7px;min-width:0}.board-tools-right{flex:0 0 auto}.search-wrap{width:min(340px,34vw);height:30px;display:flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--line);border-radius:999px;background:var(--panel-2)}.search-wrap span{color:var(--accent);font-family:var(--mono);font-size:13px}.search-wrap input{width:100%;border:0;outline:0;background:transparent;color:var(--ink);font-size:12.5px}.board-head{display:flex;align-items:center;justify-content:space-between;margin:2px 0 8px;padding:0 2px}.board-head h2{margin:0;font-size:15px;letter-spacing:-.03em}.board-head p{margin:0;color:var(--muted);font-size:11.5px;font-family:var(--mono)}.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(218px,1fr));gap:8px;contain:layout}.workspace.drawer-open .cards{grid-template-columns:repeat(auto-fill,minmax(212px,1fr))}.profile-card{cursor:pointer;position:relative;min-height:132px;padding:12px;border:1px solid var(--line);background:var(--panel);border-radius:16px;box-shadow:0 7px 18px rgba(40,34,26,.045);transition:transform .16s,border-color .16s,background .16s,box-shadow .16s}.profile-card:before{content:"";position:absolute;inset:0;border-radius:inherit;background:linear-gradient(135deg,color-mix(in srgb,var(--accent) 7%,transparent),transparent 42%);opacity:0;transition:opacity .16s;pointer-events:none}.profile-card:hover,.profile-card.selected{transform:translateY(-2px);border-color:var(--accent);background:var(--panel-2);box-shadow:0 12px 26px rgba(40,34,26,.08)}.profile-card:hover:before,.profile-card.selected:before{opacity:1}.profile-card.selected:after{content:"";position:absolute;inset:auto 10px 0;height:2px;border-radius:999px;background:var(--accent)}.card-top{display:flex;align-items:center;gap:9px;min-width:0}.profile-icon{width:32px;height:32px;flex:0 0 auto;display:grid;place-items:center;border-radius:11px;background:var(--chip);color:var(--accent);box-shadow:inset 0 0 0 1px color-mix(in srgb,currentColor 18%,transparent)}.profile-icon svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}.profile-icon.api{color:var(--blue)}.profile-icon.login{color:var(--green)}.profile-icon.ccr{color:var(--orange)}.profile-icon.main{color:var(--ink)}.card-title{min-width:0}.profile-card h3{margin:0;font-size:16px;line-height:1.1;letter-spacing:-.035em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.card-title p{margin:3px 0 0;color:var(--muted);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.tag-row{display:flex;gap:4px;flex-wrap:wrap;margin:8px 0}.tag{display:inline-flex;align-items:center;border-radius:999px;padding:2px 6px;font-size:10px;font-weight:760;background:var(--chip);color:var(--muted);border:1px solid var(--line);white-space:nowrap}.tag.ready{color:var(--green)}.tag.warn{color:var(--orange)}.tag.bad{color:var(--red)}.profile-meta{display:grid;gap:2px;margin:0 0 29px;color:var(--muted);font-size:11.2px;line-height:1.24}.profile-meta div{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.profile-meta strong{color:var(--ink);font-weight:760;margin-right:5px}.card-actions{position:absolute;left:11px;right:11px;bottom:10px;display:flex;gap:5px}.tiny{min-height:25px;padding:4px 8px;font-size:11px}.list-table{width:100%;border-collapse:separate;border-spacing:0 5px;font-size:12px}.list-table td,.list-table th{text-align:left;padding:9px 10px;background:var(--panel);border-top:1px solid var(--line);border-bottom:1px solid var(--line);transition:background .16s,border-color .16s,transform .16s}.list-table th{color:var(--muted);font-size:10px;text-transform:uppercase;letter-spacing:.12em;font-family:var(--mono);background:transparent;border-color:transparent}.list-table td:first-child{border-left:1px solid var(--line);border-radius:12px 0 0 12px}.list-table td:last-child{border-right:1px solid var(--line);border-radius:0 12px 12px 0}.list-table tbody tr{cursor:pointer}.list-table tbody tr:hover td,.list-table tbody tr.selected td{background:var(--panel-2);border-color:color-mix(in srgb,var(--accent) 42%,var(--line))}.list-table tbody tr.selected td:first-child{box-shadow:inset 3px 0 0 var(--accent)}.drawer{position:relative;min-height:0;overflow:hidden;display:flex;flex-direction:column;border:1px solid var(--line);background:var(--panel);border-radius:18px;box-shadow:var(--shadow);padding:14px;transform:translateX(16px);opacity:0;pointer-events:none;transition:transform .24s ease,opacity .18s ease}.workspace.drawer-open .drawer{transform:translateX(0);opacity:1;pointer-events:auto}.drawer-rail{display:flex;justify-content:flex-end;margin-bottom:4px}.empty-drawer{display:grid;place-content:center;min-height:70%;padding:22px;text-align:center;color:var(--muted)}.empty-state{min-height:280px;display:grid;place-content:center;text-align:center;color:var(--muted);border:1px dashed var(--line);border-radius:18px;background:var(--panel)}.drawer h2,.empty-state h2{margin:0 0 8px;font-size:24px;line-height:1.1;letter-spacing:-.045em;color:var(--ink);overflow-wrap:anywhere}.drawer-fixed{flex:0 0 auto}.launch-section{border-top:0;padding-top:0}.drawer-scroll{min-height:0;overflow:auto;flex:1 1 auto;padding-right:4px;border-top:1px solid var(--line);scrollbar-width:thin;scrollbar-color:var(--line) transparent}.drawer-scroll::-webkit-scrollbar{width:8px}.drawer-scroll::-webkit-scrollbar-track{background:transparent}.drawer-scroll::-webkit-scrollbar-thumb{background:var(--line);border:2px solid transparent;border-radius:999px;background-clip:padding-box}.drawer-scroll::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}.drawer-section{padding:12px 0;border-top:1px solid var(--line)}.drawer-scroll>.profile-summary>.drawer-section:first-child{border-top:0}.kv{display:grid;grid-template-columns:78px minmax(0,1fr);gap:6px;font-size:11.5px;line-height:1.35}.kv span{color:var(--muted)}.kv strong{overflow-wrap:anywhere}.command{display:flex;justify-content:space-between;gap:8px;align-items:center;padding:8px 9px;background:var(--chip);border-radius:11px;font-family:var(--mono);font-size:11px;overflow:hidden}.command code{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}label{display:grid;gap:4px;margin:8px 0;color:var(--muted);font-size:11.5px}input,select{width:100%;border:1px solid var(--line);border-radius:11px;padding:8px 34px 8px 9px;background:var(--panel-2);color:var(--ink);outline:0;font-size:12.5px}select{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);background-position:calc(100% - 16px) 52%,calc(100% - 11px) 52%;background-size:5px 5px,5px 5px;background-repeat:no-repeat}input:focus,select:focus{border-color:var(--accent)}.danger-actions{display:grid;gap:9px;margin-top:10px}.danger-actions .ghost{justify-self:start}.modal{border:0;background:transparent;opacity:0;transform:translateY(10px) scale(.985);transition:opacity .18s ease,transform .22s cubic-bezier(.2,.8,.2,1),overlay .22s allow-discrete,display .22s allow-discrete}.modal[open]{opacity:1;transform:translateY(0) scale(1)}@starting-style{.modal[open]{opacity:0;transform:translateY(10px) scale(.985)}}.modal::backdrop{background:rgba(28,24,20,.38);backdrop-filter:blur(8px);opacity:0;transition:opacity .22s ease,overlay .22s allow-discrete,display .22s allow-discrete}.modal[open]::backdrop{opacity:1}@starting-style{.modal[open]::backdrop{opacity:0}}.modal-card{width:min(820px,calc(100vw - 28px));max-height:min(76vh,720px);overflow:hidden;display:flex;flex-direction:column;padding:16px;border:1px solid var(--line);border-radius:22px;background:var(--panel-2);color:var(--ink);box-shadow:var(--shadow);scrollbar-width:thin;scrollbar-color:var(--line) transparent}.modal-card::-webkit-scrollbar{width:8px;height:8px}.modal-card::-webkit-scrollbar-track{background:transparent}.modal-card::-webkit-scrollbar-thumb{background:var(--line);border:2px solid transparent;border-radius:999px;background-clip:padding-box}.modal-card::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}.ccr-card{width:min(520px,calc(100vw - 28px));max-height:min(70vh,560px)}.modal-head{display:flex;justify-content:space-between;gap:16px;align-items:start}.modal-head h2{margin:0;font-size:18px;letter-spacing:-.035em}.icon-btn{width:30px;height:30px;padding:0}.hint{color:var(--muted);line-height:1.5;font-size:12px}.hint a{display:inline-flex;align-items:center;padding:1px 6px;border:1px solid color-mix(in srgb,var(--accent) 34%,var(--line));border-radius:999px;background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--accent);text-decoration:none;font-weight:650;line-height:1.35}.hint a:hover{background:var(--chip);border-color:var(--accent)}.preset-layout{display:grid;grid-template-columns:280px minmax(0,1fr);gap:14px;margin-top:12px;min-height:0;flex:1 1 auto;overflow:hidden}.preset-picker{min-height:0;display:grid;grid-template-rows:auto auto minmax(0,1fr);gap:8px;padding:8px;border:1px solid var(--line);border-radius:16px;background:var(--panel)}.preset-search{height:30px;display:flex;align-items:center;gap:7px;padding:0 10px;border:1px solid var(--line);border-radius:999px;background:var(--panel-2)}.preset-search svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;color:var(--accent)}.preset-search input{border:0;background:transparent;padding:0;width:100%;font-size:12px}.preset-filters{display:flex;gap:5px;overflow:auto;padding-bottom:2px}.preset-filters .chip{white-space:nowrap}.preset-list{min-height:0;overflow:auto;display:grid;gap:7px;align-content:start;padding-right:2px;scrollbar-width:thin;scrollbar-color:var(--line) transparent}.preset-list::-webkit-scrollbar{width:8px}.preset-list::-webkit-scrollbar-track{background:transparent}.preset-list::-webkit-scrollbar-thumb{background:var(--line);border:2px solid transparent;border-radius:999px;background-clip:padding-box}.preset-option{width:100%;display:grid;grid-template-columns:32px minmax(0,1fr);gap:9px;align-items:center;text-align:left;padding:9px;border:1px solid transparent;border-radius:13px;background:transparent;color:var(--ink);transition:background .16s ease,border-color .16s ease,box-shadow .16s ease}.preset-option:hover{background:var(--chip);border-color:var(--line)}.preset-option.active{background:var(--panel-2);border-color:var(--accent);box-shadow:inset 3px 0 0 var(--accent)}.preset-icon{width:32px;height:32px;display:grid;place-items:center;border-radius:10px;background:var(--chip);color:var(--accent)}.preset-icon svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}.preset-option strong{display:block;font-size:13px;line-height:1.15;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.preset-option small,.preset-option em{display:block;margin-top:3px;color:var(--muted);font-size:10.5px;font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.preset-option em{color:var(--faint)}.preset-empty{padding:18px 10px;text-align:center;color:var(--muted);font-size:12px;border:1px dashed var(--line);border-radius:12px}.preset-detail{min-width:0;overflow:auto;padding:8px 2px;scrollbar-width:thin;scrollbar-color:var(--line) transparent}.preset-detail::-webkit-scrollbar{width:8px;height:8px}.preset-detail::-webkit-scrollbar-track{background:transparent}.preset-detail::-webkit-scrollbar-thumb{background:var(--line);border:2px solid transparent;border-radius:999px;background-clip:padding-box}.preset-detail::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}.preset-summary{position:relative;padding:12px;border:1px solid var(--line);border-radius:16px;background:var(--panel);margin-bottom:12px}.preset-summary h3{margin:0 0 5px;font-size:18px;letter-spacing:-.035em}.preset-summary p{margin:0;color:var(--muted);font-size:12.5px;line-height:1.45}.preset-summary dl{display:grid;grid-template-columns:92px minmax(0,1fr);gap:6px;margin:12px 0 0;font-size:11.5px}.preset-summary dt{color:var(--muted)}.preset-summary dd{margin:0;overflow-wrap:anywhere}.preset-adjust{position:absolute;right:10px;top:10px;display:inline-flex;padding:4px 8px;border:1px solid var(--line);border-radius:999px;color:var(--accent);text-decoration:none;font-size:11px;font-weight:500;background:var(--panel-2)}.preset-adjust:hover{border-color:var(--accent);background:var(--chip)}.preset-config{margin-top:12px;border-top:1px solid var(--line);padding-top:10px}.preset-config summary{cursor:pointer;color:var(--accent);font-size:12px;font-weight:500}.preset-config pre{max-height:190px;overflow:auto;margin:9px 0 0;padding:10px;border-radius:12px;background:var(--chip);font-family:var(--mono);font-size:11px;line-height:1.45;white-space:pre-wrap;scrollbar-width:thin;scrollbar-color:var(--line-strong,var(--line)) transparent}.preset-config pre::-webkit-scrollbar{width:8px;height:8px}.preset-config pre::-webkit-scrollbar-track{background:transparent}.preset-config pre::-webkit-scrollbar-thumb{background:var(--line);border:2px solid transparent;border-radius:999px;background-clip:padding-box}.preset-config pre::-webkit-scrollbar-thumb:hover{background:var(--muted);background-clip:padding-box}.modal-actions{justify-content:flex-end;margin:14px 0 0;padding:0}.toast-region{position:fixed;right:18px;bottom:18px;display:grid;gap:8px;z-index:30}.dialog-toast-region{position:absolute;left:50%;top:14px;transform:translateX(-50%);width:min(420px,calc(100% - 32px));display:grid;justify-items:center;gap:8px;z-index:10000;pointer-events:none}.toast{padding:9px 12px;border:1px solid var(--line);border-radius:13px;background:var(--panel-2);box-shadow:var(--shadow);font-size:12.5px;animation:toast-in .22s ease both,toast-out .28s ease 3.25s forwards}.dialog-toast-region .toast{pointer-events:auto;animation:dialog-toast-in .22s ease both,dialog-toast-out .28s ease 3.25s forwards}@keyframes toast-in{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes dialog-toast-in{from{opacity:0;transform:translateY(-8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes toast-out{to{opacity:0;transform:translateY(6px) scale(.98)}}@keyframes dialog-toast-out{to{opacity:0;transform:translateY(6px) scale(.98)}}@media(max-width:1080px){body{overflow:auto}.shell{height:auto;min-height:100vh}.workspace,.workspace.drawer-open{grid-template-columns:1fr}.drawer{display:none}.workspace.drawer-open .drawer{display:flex;position:fixed;inset:10px;z-index:20;overflow:hidden}.board-toolbar{position:static;align-items:stretch;flex-direction:column}.board-tools-left,.board-tools-right{width:100%;overflow:auto}.search-wrap{width:100%}.summary-grid{grid-template-columns:repeat(3,1fr)}}@media(max-width:760px){.preset-layout{grid-template-columns:1fr}.preset-picker{max-height:330px}.preset-list{max-height:210px;overflow:auto}}@media(max-width:720px){.shell{width:calc(100% - 16px);padding:8px 0}.topbar{align-items:flex-start}.summary-grid{grid-template-columns:repeat(2,1fr)}.cards{grid-template-columns:1fr}.filters,.view-switch{overflow:auto;flex-wrap:nowrap}.chip{white-space:nowrap}.top-actions{justify-content:flex-end}.brand-mark{display:none}}
@@ -0,0 +1,6 @@
1
+ export interface UiServerOptions {
2
+ host?: string;
3
+ port?: number;
4
+ open?: boolean;
5
+ }
6
+ export declare function startUiServer(options?: UiServerOptions): Promise<void>;
@@ -0,0 +1,403 @@
1
+ import { createServer } from "node:http";
2
+ import { randomBytes } from "node:crypto";
3
+ import { readFile } from "node:fs/promises";
4
+ import { existsSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { spawn } from "node:child_process";
8
+ import { CcpError } from "../core/errors.js";
9
+ import { getMainClaudeDir } from "../core/paths.js";
10
+ import { createApiProfile, createCcrProfile, createLoginProfile, listProfiles, removeProfile, resolveConfigDir, summarizeProfile } from "../core/profiles.js";
11
+ import { ensureCcrPreset, getCcrRouteChoices, getCcrStatus, readCcrConfig, restartCcrService, startCcrService, stopCcrService } from "../core/ccr.js";
12
+ import { createApiProfileFromPreset, createCcrProfileFromPreset, listProfilePresets } from "../core/presets.js";
13
+ import { readMeta, readSettings, writeMeta, writeSettings } from "../core/settings.js";
14
+ const DEFAULT_HOST = "127.0.0.1";
15
+ const DEFAULT_PORT = 7821;
16
+ const JSON_HEADERS = { "content-type": "application/json; charset=utf-8" };
17
+ let nextActivityId = 1;
18
+ const activity = [];
19
+ function addActivity(type, message) {
20
+ activity.unshift({ id: nextActivityId++, time: new Date().toISOString(), type, message: redact(message) });
21
+ if (activity.length > 100)
22
+ activity.pop();
23
+ }
24
+ function redact(value) {
25
+ return value
26
+ .replace(/(ANTHROPIC_AUTH_TOKEN\s*[=:]\s*)[^\s,}]+/gi, "$1[redacted]")
27
+ .replace(/(authorization\s*[:=]\s*bearer\s+)[^\s,}]+/gi, "$1[redacted]")
28
+ .replace(/(api[_-]?key\s*[=:]\s*)[^\s,}]+/gi, "$1[redacted]")
29
+ .replace(/sk-[A-Za-z0-9._-]{8,}/g, "sk-****");
30
+ }
31
+ function json(res, status, data) {
32
+ res.writeHead(status, JSON_HEADERS);
33
+ res.end(JSON.stringify(data));
34
+ }
35
+ function notFound(res) {
36
+ json(res, 404, { error: "Not found" });
37
+ }
38
+ function methodNotAllowed(res) {
39
+ json(res, 405, { error: "Method not allowed" });
40
+ }
41
+ async function readJsonBody(req) {
42
+ const chunks = [];
43
+ for await (const chunk of req)
44
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
45
+ const raw = Buffer.concat(chunks).toString("utf8").trim();
46
+ if (!raw)
47
+ return {};
48
+ return JSON.parse(raw);
49
+ }
50
+ function requireToken(req, token) {
51
+ if (req.headers["x-ccp-ui-token"] !== token) {
52
+ throw new CcpError("Invalid UI token.");
53
+ }
54
+ }
55
+ function publicSettings(settings) {
56
+ if (!settings)
57
+ return undefined;
58
+ const cloned = JSON.parse(JSON.stringify(settings));
59
+ if (cloned.env?.ANTHROPIC_AUTH_TOKEN) {
60
+ cloned.env.ANTHROPIC_AUTH_TOKEN = maskToken(cloned.env.ANTHROPIC_AUTH_TOKEN);
61
+ }
62
+ return cloned;
63
+ }
64
+ function maskToken(token) {
65
+ if (!token || token === "REPLACE_WITH_FULL_TOKEN")
66
+ return "missing";
67
+ if (token.length <= 8)
68
+ return "configured";
69
+ return `${token.slice(0, 3)}****${token.slice(-4)}`;
70
+ }
71
+ function hostnameOf(url) {
72
+ try {
73
+ return new URL(url).hostname;
74
+ }
75
+ catch {
76
+ return url;
77
+ }
78
+ }
79
+ function tagsForProfile(profile, isMain, ccrRunning) {
80
+ const type = isMain ? "main" : profile.type;
81
+ const tags = [];
82
+ tags.push(type === "main" ? "Main" : type === "api" ? "API" : type === "login" ? "Login" : type === "ccr" ? "CCR" : "Unknown");
83
+ let status = "ready";
84
+ let statusText = "Ready";
85
+ if (profile.type === "api" && profile.tokenStatus === "missing") {
86
+ status = "needs_attention";
87
+ statusText = "Missing Token";
88
+ }
89
+ if (profile.type === "api" && !profile.baseUrl) {
90
+ status = "needs_attention";
91
+ statusText = "Missing Base URL";
92
+ }
93
+ if (profile.type === "ccr" && !ccrRunning) {
94
+ status = "needs_attention";
95
+ statusText = "CCR Offline";
96
+ }
97
+ if (profile.type === "unknown" && !isMain) {
98
+ status = "unknown";
99
+ statusText = "Unknown";
100
+ }
101
+ tags.push(status === "ready" ? "Ready" : statusText);
102
+ if (profile.type === "api") {
103
+ tags.push(profile.model ? "Custom Model" : "Default Model");
104
+ }
105
+ else if (profile.type === "login") {
106
+ tags.push("Login Profile");
107
+ }
108
+ else if (profile.type === "ccr") {
109
+ tags.push(profile.meta?.ccrRoute ? "Preset Bound" : "Endpoint Bound");
110
+ }
111
+ else if (isMain) {
112
+ tags.push("Main Config");
113
+ }
114
+ return { status, statusText, tags };
115
+ }
116
+ async function toWebProfile(profile, isMain, ccrRunning, includeSettings = false) {
117
+ const tagState = tagsForProfile(profile, isMain, ccrRunning);
118
+ const settings = includeSettings ? await readSettings(profile.dir) : undefined;
119
+ return {
120
+ ...profile,
121
+ type: isMain ? "main" : profile.type,
122
+ ...tagState,
123
+ startCommand: isMain ? "claude" : `ccp start ${profile.name}`,
124
+ settings: publicSettings(settings)
125
+ };
126
+ }
127
+ async function getAllProfiles(includeSettings = false) {
128
+ const ccr = await getCcrStatus();
129
+ const profiles = [];
130
+ const mainDir = getMainClaudeDir();
131
+ if (existsSync(mainDir)) {
132
+ const main = await summarizeProfile("main", mainDir);
133
+ profiles.push(await toWebProfile(main, true, ccr.running, includeSettings));
134
+ }
135
+ for (const profile of await listProfiles()) {
136
+ profiles.push(await toWebProfile(profile, false, ccr.running, includeSettings));
137
+ }
138
+ return profiles;
139
+ }
140
+ function dashboardFromProfiles(profiles, ccr) {
141
+ const count = (type) => profiles.filter((profile) => profile.type === type).length;
142
+ return {
143
+ profiles: {
144
+ total: profiles.length,
145
+ main: count("main"),
146
+ api: count("api"),
147
+ login: count("login"),
148
+ ccr: count("ccr"),
149
+ needsAttention: profiles.filter((profile) => profile.status !== "ready").length
150
+ },
151
+ ccr: {
152
+ installed: ccr.installed,
153
+ running: ccr.running,
154
+ endpoint: ccr.endpoint,
155
+ uiUrl: `${ccr.endpoint.replace(/\/$/, "")}/ui/`,
156
+ apiKeyStatus: ccr.apiKeyStatus
157
+ },
158
+ activity: activity.slice(0, 8)
159
+ };
160
+ }
161
+ async function updateApiSettings(name, body) {
162
+ const config = await resolveConfigDir(name, { allowMain: false });
163
+ const settings = (await readSettings(config.dir)) ?? { theme: "dark" };
164
+ settings.env ??= {};
165
+ const baseUrl = String(body.baseUrl ?? "").trim();
166
+ const token = String(body.token ?? "");
167
+ const model = String(body.model ?? "").trim();
168
+ const opusModel = String(body.opusModel ?? "").trim();
169
+ const sonnetModel = String(body.sonnetModel ?? "").trim();
170
+ const haikuModel = String(body.haikuModel ?? "").trim();
171
+ const subagentModel = String(body.subagentModel ?? "").trim();
172
+ if (baseUrl)
173
+ settings.env.ANTHROPIC_BASE_URL = baseUrl;
174
+ if (token.trim())
175
+ settings.env.ANTHROPIC_AUTH_TOKEN = token.trim();
176
+ setOptionalEnv(settings, "ANTHROPIC_MODEL", model);
177
+ setOptionalEnv(settings, "ANTHROPIC_DEFAULT_OPUS_MODEL", opusModel || model);
178
+ setOptionalEnv(settings, "ANTHROPIC_DEFAULT_SONNET_MODEL", sonnetModel || model);
179
+ setOptionalEnv(settings, "ANTHROPIC_DEFAULT_HAIKU_MODEL", haikuModel || model);
180
+ setOptionalEnv(settings, "CLAUDE_CODE_SUBAGENT_MODEL", subagentModel);
181
+ await writeSettings(config.dir, settings);
182
+ const summarized = await summarizeProfile(name, config.dir);
183
+ const ccr = await getCcrStatus();
184
+ addActivity("success", `Updated profile '${name}'.`);
185
+ return toWebProfile(summarized, false, ccr.running, true);
186
+ }
187
+ function setOptionalEnv(settings, key, value) {
188
+ settings.env ??= {};
189
+ if (value)
190
+ settings.env[key] = value;
191
+ else
192
+ delete settings.env[key];
193
+ }
194
+ async function updateCcrBinding(name, body) {
195
+ const config = await resolveConfigDir(name, { allowMain: false });
196
+ const route = String(body.route ?? "").trim();
197
+ if (!route)
198
+ throw new CcpError("CCR route is required.");
199
+ const meta = (await readMeta(config.dir));
200
+ if (!meta || meta.type !== "ccr")
201
+ throw new CcpError(`Profile '${name}' is not a CCR profile.`);
202
+ const preset = String(body.preset ?? meta.ccrPreset ?? name).trim() || name;
203
+ meta.ccrRoute = route;
204
+ meta.ccrPreset = preset;
205
+ await writeMeta(config.dir, meta);
206
+ await ensureCcrPreset(preset, route);
207
+ const summarized = await summarizeProfile(name, config.dir);
208
+ const ccr = await getCcrStatus();
209
+ addActivity("success", `Updated CCR route for '${name}'.`);
210
+ return toWebProfile(summarized, false, ccr.running, true);
211
+ }
212
+ function assetRoot() {
213
+ const here = path.dirname(fileURLToPath(import.meta.url));
214
+ const distAssets = path.join(here, "assets");
215
+ if (existsSync(distAssets))
216
+ return distAssets;
217
+ return path.resolve(here, "../../src/web/assets");
218
+ }
219
+ function contentType(filePath) {
220
+ if (filePath.endsWith(".html"))
221
+ return "text/html; charset=utf-8";
222
+ if (filePath.endsWith(".css"))
223
+ return "text/css; charset=utf-8";
224
+ if (filePath.endsWith(".js"))
225
+ return "text/javascript; charset=utf-8";
226
+ if (filePath.endsWith(".svg"))
227
+ return "image/svg+xml";
228
+ return "application/octet-stream";
229
+ }
230
+ async function serveStatic(res, pathname, token) {
231
+ const root = assetRoot();
232
+ const safePath = pathname === "/" ? "/index.html" : pathname;
233
+ const resolved = path.resolve(root, `.${safePath}`);
234
+ if (!resolved.startsWith(path.resolve(root)))
235
+ return notFound(res);
236
+ try {
237
+ let data = await readFile(resolved, "utf8");
238
+ if (resolved.endsWith("index.html")) {
239
+ data = data.replace("__CCP_UI_TOKEN__", token);
240
+ }
241
+ res.writeHead(200, { "content-type": contentType(resolved) });
242
+ res.end(data);
243
+ }
244
+ catch {
245
+ notFound(res);
246
+ }
247
+ }
248
+ function openBrowser(url) {
249
+ const command = process.platform === "win32" ? "cmd" : process.platform === "darwin" ? "open" : "xdg-open";
250
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
251
+ const child = spawn(command, args, { detached: true, stdio: "ignore" });
252
+ child.unref();
253
+ }
254
+ async function handleApi(req, res, pathname, token) {
255
+ try {
256
+ if (req.method !== "GET")
257
+ requireToken(req, token);
258
+ if (pathname === "/api/presets") {
259
+ if (req.method !== "GET")
260
+ return methodNotAllowed(res);
261
+ return json(res, 200, { presets: listProfilePresets() });
262
+ }
263
+ if (pathname === "/api/profiles/preset") {
264
+ if (req.method !== "POST")
265
+ return methodNotAllowed(res);
266
+ const body = await readJsonBody(req);
267
+ const presetId = body.presetId ?? "";
268
+ let created;
269
+ if (body.kind === "ccr") {
270
+ created = await createCcrProfileFromPreset({ presetId, name: body.name, token: body.token });
271
+ }
272
+ else {
273
+ created = await createApiProfileFromPreset({ presetId, name: body.name, token: body.token ?? "" });
274
+ }
275
+ addActivity("success", `Created profile '${created.name}' from preset '${presetId}'.`);
276
+ return json(res, 201, { profile: await toWebProfile(created, false, (await getCcrStatus()).running, true) });
277
+ }
278
+ if (pathname === "/api/dashboard") {
279
+ if (req.method !== "GET")
280
+ return methodNotAllowed(res);
281
+ const profiles = await getAllProfiles();
282
+ return json(res, 200, dashboardFromProfiles(profiles, await getCcrStatus()));
283
+ }
284
+ if (pathname === "/api/profiles") {
285
+ if (req.method !== "GET")
286
+ return methodNotAllowed(res);
287
+ return json(res, 200, { profiles: await getAllProfiles() });
288
+ }
289
+ if (pathname === "/api/activity") {
290
+ if (req.method !== "GET")
291
+ return methodNotAllowed(res);
292
+ return json(res, 200, { activity });
293
+ }
294
+ if (pathname === "/api/ccr/status") {
295
+ if (req.method !== "GET")
296
+ return methodNotAllowed(res);
297
+ const status = await getCcrStatus();
298
+ const profiles = await getAllProfiles();
299
+ return json(res, 200, { ...status, uiUrl: `${status.endpoint.replace(/\/$/, "")}/ui/`, profilesUsingCcr: profiles.filter((profile) => profile.type === "ccr").length });
300
+ }
301
+ if (pathname === "/api/ccr/routes") {
302
+ if (req.method !== "GET")
303
+ return methodNotAllowed(res);
304
+ return json(res, 200, { routes: getCcrRouteChoices(await readCcrConfig()) });
305
+ }
306
+ if (pathname === "/api/ccr/start") {
307
+ if (req.method !== "POST")
308
+ return methodNotAllowed(res);
309
+ await startCcrService();
310
+ addActivity("success", "CCR start command sent.");
311
+ return json(res, 200, { status: await getCcrStatus() });
312
+ }
313
+ if (pathname === "/api/ccr/restart") {
314
+ if (req.method !== "POST")
315
+ return methodNotAllowed(res);
316
+ await restartCcrService();
317
+ addActivity("success", "CCR restart command sent.");
318
+ return json(res, 200, { status: await getCcrStatus() });
319
+ }
320
+ if (pathname === "/api/ccr/stop") {
321
+ if (req.method !== "POST")
322
+ return methodNotAllowed(res);
323
+ await stopCcrService();
324
+ addActivity("success", "CCR stop command sent.");
325
+ return json(res, 200, { status: await getCcrStatus() });
326
+ }
327
+ if (pathname === "/api/profiles/api" && req.method === "POST") {
328
+ const body = await readJsonBody(req);
329
+ const created = await createApiProfile({ name: body.name ?? "", baseUrl: body.baseUrl ?? "", token: body.token ?? "", model: body.model ?? "" });
330
+ addActivity("success", `Created API profile '${created.name}'.`);
331
+ return json(res, 201, { profile: await toWebProfile(created, false, (await getCcrStatus()).running, true) });
332
+ }
333
+ if (pathname === "/api/profiles/login" && req.method === "POST") {
334
+ const body = await readJsonBody(req);
335
+ const created = await createLoginProfile({ name: body.name ?? "" });
336
+ addActivity("success", `Created login profile '${created.name}'.`);
337
+ return json(res, 201, { profile: await toWebProfile(created, false, (await getCcrStatus()).running, true) });
338
+ }
339
+ if (pathname === "/api/profiles/ccr" && req.method === "POST") {
340
+ const body = await readJsonBody(req);
341
+ const created = await createCcrProfile({ name: body.name ?? "", presetName: body.presetName, route: body.route ?? "", token: body.token ?? "" });
342
+ addActivity("success", `Created CCR profile '${created.name}'.`);
343
+ return json(res, 201, { profile: await toWebProfile(created, false, (await getCcrStatus()).running, true) });
344
+ }
345
+ const profileMatch = pathname.match(/^\/api\/profiles\/([^/]+)$/);
346
+ if (profileMatch) {
347
+ const name = decodeURIComponent(profileMatch[1]);
348
+ if (req.method === "GET") {
349
+ const config = await resolveConfigDir(name, { allowMain: true });
350
+ const profile = await summarizeProfile(config.name, config.dir);
351
+ return json(res, 200, { profile: await toWebProfile(profile, config.isMain, (await getCcrStatus()).running, true) });
352
+ }
353
+ if (req.method === "PUT") {
354
+ const body = await readJsonBody(req);
355
+ const kind = String(body.kind ?? "api");
356
+ const profile = kind === "ccr" ? await updateCcrBinding(name, body) : await updateApiSettings(name, body);
357
+ return json(res, 200, { profile });
358
+ }
359
+ if (req.method === "DELETE") {
360
+ const body = await readJsonBody(req);
361
+ if (body.confirmName !== name)
362
+ throw new CcpError("Profile name confirmation does not match.");
363
+ const removed = await removeProfile(name);
364
+ addActivity("success", `Deleted profile '${name}' at ${removed}.`);
365
+ return json(res, 200, { removed });
366
+ }
367
+ return methodNotAllowed(res);
368
+ }
369
+ notFound(res);
370
+ }
371
+ catch (error) {
372
+ const message = error instanceof Error ? error.message : String(error);
373
+ addActivity("error", message);
374
+ json(res, error instanceof CcpError ? 400 : 500, { error: redact(message) });
375
+ }
376
+ }
377
+ export async function startUiServer(options = {}) {
378
+ const host = options.host ?? DEFAULT_HOST;
379
+ const port = options.port ?? DEFAULT_PORT;
380
+ const token = randomBytes(24).toString("hex");
381
+ const server = createServer(async (req, res) => {
382
+ const url = new URL(req.url ?? "/", `http://${host}:${port}`);
383
+ if (url.pathname.startsWith("/api/")) {
384
+ await handleApi(req, res, url.pathname, token);
385
+ return;
386
+ }
387
+ await serveStatic(res, url.pathname, token);
388
+ });
389
+ await new Promise((resolve, reject) => {
390
+ server.once("error", reject);
391
+ server.listen(port, host, () => resolve());
392
+ });
393
+ const url = `http://${host}:${port}/`;
394
+ addActivity("info", `UI started at ${url}`);
395
+ console.log(`ccp ui running at ${url}`);
396
+ console.log("Press Ctrl+C to stop.");
397
+ if (host !== DEFAULT_HOST) {
398
+ console.log("Warning: ccp ui is not bound to 127.0.0.1. Use only on trusted networks.");
399
+ }
400
+ if (options.open)
401
+ openBrowser(url);
402
+ }
403
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/web/server.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multi-ccp",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Cross-platform Claude Code profile manager for API, login, and router workflows.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  "CHANGELOG.md"
15
15
  ],
16
16
  "scripts": {
17
- "build": "tsc -p tsconfig.json",
17
+ "build": "tsc -p tsconfig.json && node scripts/copy-web-assets.mjs",
18
18
  "dev": "tsx src/cli/index.ts",
19
19
  "test": "vitest run",
20
20
  "typecheck": "tsc -p tsconfig.json --noEmit",