jinzd-ai-cli 0.4.273 → 0.4.276
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +610 -610
- package/README.zh-CN.md +559 -559
- package/dist/agent-client-6GX6QQDU.js +0 -0
- package/dist/auth-PE3Z5OHS.js +0 -0
- package/dist/{batch-LOW3GM26.js → batch-F7SKIBI3.js} +2 -2
- package/dist/chat-index-2D5GK2DB.js +0 -0
- package/dist/chunk-23SJVOQD.js +0 -0
- package/dist/chunk-3FEZSLGI.js +0 -0
- package/dist/chunk-4BKXL7SM.js +0 -0
- package/dist/{chunk-AUEX6RNY.js → chunk-4KTK2OYU.js} +54 -21
- package/dist/{chunk-M3NXF4GD.js → chunk-4NH4Q7QK.js} +1 -1
- package/dist/chunk-5C76XDDF.js +0 -0
- package/dist/chunk-6YZEZFX5.js +0 -0
- package/dist/{chunk-FHXLAJJG.js → chunk-AOISQVXS.js} +1 -1
- package/dist/{chunk-FNLWPYP5.js → chunk-ATD2Y3PB.js} +1 -1
- package/dist/chunk-BXP6YZ2P.js +0 -0
- package/dist/chunk-CGDYO52A.js +0 -0
- package/dist/chunk-CKH4KQ4E.js +0 -0
- package/dist/{chunk-JT6UN5C6.js → chunk-DPTEC6AQ.js} +3 -0
- package/dist/{chunk-EDAUDILT.js → chunk-FLDYAXJR.js} +1 -1
- package/dist/chunk-GHWZVPUV.js +0 -0
- package/dist/chunk-GLSR2NR3.js +0 -0
- package/dist/chunk-HLWUDRBO.js +0 -0
- package/dist/chunk-HOSJZMQS.js +0 -0
- package/dist/chunk-IW3Q7AE5.js +0 -0
- package/dist/chunk-KHYD3WXE.js +0 -0
- package/dist/{chunk-Z3UXZ5EI.js → chunk-KWSGSSWN.js} +1 -1
- package/dist/{chunk-4FIDMC2K.js → chunk-MCKUGWOY.js} +69 -4
- package/dist/chunk-MX75TNE5.js +0 -0
- package/dist/{chunk-FN7DE4HA.js → chunk-MXPUOF5K.js} +4 -4
- package/dist/chunk-NR5U6LVG.js +0 -0
- package/dist/{chunk-ZWCQQZT5.js → chunk-NXAHXWPF.js} +1 -1
- package/dist/{chunk-R4YGDJPL.js → chunk-NXNXWM6H.js} +5 -5
- package/dist/chunk-NYNSYLFY.js +0 -0
- package/dist/{chunk-WSCZRQDR.js → chunk-OMBKLWLJ.js} +1 -1
- package/dist/chunk-RYQBBEMM.js +0 -0
- package/dist/{chunk-3OBY7WSS.js → chunk-TEXT4DAT.js} +7 -1
- package/dist/chunk-TU3L3PW7.js +0 -0
- package/dist/{chunk-LEK5WGKV.js → chunk-UNL7NR55.js} +1 -1
- package/dist/chunk-UUSRWSSX.js +0 -0
- package/dist/{chunk-T65VFCID.js → chunk-VF7DMSKF.js} +1 -1
- package/dist/chunk-VOIOUJXI.js +0 -0
- package/dist/{chunk-MTQBSOZW.js → chunk-WYDP2WEQ.js} +4 -4
- package/dist/chunk-XNFIYS7G.js +0 -0
- package/dist/{ci-C5YMQXCS.js → ci-VURFRMWQ.js} +6 -6
- package/dist/{ci-format-R6EMNOGZ.js → ci-format-AFJJIURF.js} +2 -2
- package/dist/config-command-E5DHADEV.js +0 -0
- package/dist/{constants-QJCNMBPJ.js → constants-WO7ERENL.js} +1 -1
- package/dist/{doctor-cli-5CM2I6OF.js → doctor-cli-BGGILTHE.js} +6 -6
- package/dist/electron-server.js +167 -57
- package/dist/file-checkpoint-NKBHGC7L.js +0 -0
- package/dist/git-context-EXOEHQSF.js +0 -0
- package/dist/{hub-7JBSZOSD.js → hub-Z73RLNJI.js} +1 -1
- package/dist/hub-server-RF6LURXY.js +0 -0
- package/dist/index.js +57 -43
- package/dist/indexer-VZETNE4H.js +0 -0
- package/dist/persist-PQM4BRI4.js +0 -0
- package/dist/{persistent-memory-4E53HW3U.js → persistent-memory-5QMARQJF.js} +2 -2
- package/dist/{persistent-memory-KYRY56PG.js → persistent-memory-CI544RLT.js} +2 -2
- package/dist/{pr-NPUGZSXB.js → pr-24REDMGV.js} +6 -6
- package/dist/project-trust-NKYHL3VZ.js +0 -0
- package/dist/{run-tests-5FHQ5IBX.js → run-tests-72VNZXNT.js} +2 -2
- package/dist/{run-tests-SU5CDQKF.js → run-tests-JJ3KOY5E.js} +2 -2
- package/dist/semantic-HLAE2O4F.js +0 -0
- package/dist/{server-ER36M7TR.js → server-JMXC2N3F.js} +40 -29
- package/dist/{server-77YS5NNN.js → server-QJHCJDA7.js} +6 -6
- package/dist/setup-wizard-S55ICNHH.js +0 -0
- package/dist/store-MWNHVGJT.js +0 -0
- package/dist/{task-orchestrator-56PQ7LGV.js → task-orchestrator-DJN36HP5.js} +6 -6
- package/dist/{usage-3YATXRFZ.js → usage-HXJVDETY.js} +3 -3
- package/dist/vector-store-BBDXB5IQ.js +0 -0
- package/dist/wasm/web-tree-sitter.wasm +0 -0
- package/dist/web/client/actions.js +104 -104
- package/dist/web/client/actions.js.br +0 -0
- package/dist/web/client/actions.js.gz +0 -0
- package/dist/web/client/api.js.gz +0 -0
- package/dist/web/client/app.js.gz +0 -0
- package/dist/web/client/dom.js.gz +0 -0
- package/dist/web/client/icon.svg +22 -22
- package/dist/web/client/icon.svg.br +0 -0
- package/dist/web/client/icon.svg.gz +0 -0
- package/dist/web/client/index.html +388 -388
- package/dist/web/client/index.html.br +0 -0
- package/dist/web/client/index.html.gz +0 -0
- package/dist/web/client/manifest.json +15 -15
- package/dist/web/client/sidebar-tabs.js.gz +0 -0
- package/dist/web/client/state.js.gz +0 -0
- package/dist/web/client/style.css +991 -991
- package/dist/web/client/style.css.br +0 -0
- package/dist/web/client/style.css.gz +0 -0
- package/dist/web/client/sw.js +85 -85
- package/dist/web/client/sw.js.br +0 -0
- package/dist/web/client/sw.js.gz +0 -0
- package/dist/web/client/templates.js.gz +0 -0
- package/dist/web/client/util.js.gz +0 -0
- package/dist/web/client/vendor/daisyui-full.min.css.gz +0 -0
- package/dist/web/client/vendor/github-dark.min.css.gz +0 -0
- package/dist/web/client/vendor/github.min.css.gz +0 -0
- package/dist/web/client/vendor/highlight.min.js.gz +0 -0
- package/dist/web/client/vendor/marked.min.js.gz +0 -0
- package/dist/web/client/vendor/tailwind.js.gz +0 -0
- package/package.json +178 -178
|
@@ -1,388 +1,388 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en" data-theme="dark">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
6
|
-
<title>ai-cli Web UI</title>
|
|
7
|
-
<!-- PWA -->
|
|
8
|
-
<link rel="manifest" href="manifest.json">
|
|
9
|
-
<meta name="theme-color" content="#6419e6">
|
|
10
|
-
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
11
|
-
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
12
|
-
<link rel="apple-touch-icon" href="icon-192.png">
|
|
13
|
-
<link rel="icon" type="image/svg+xml" href="icon.svg">
|
|
14
|
-
<link rel="icon" type="image/png" sizes="192x192" href="icon-192.png">
|
|
15
|
-
<!-- Tailwind CSS + DaisyUI (vendored locally — v0.4.153). These were on
|
|
16
|
-
cdn.tailwindcss.com / cdn.jsdelivr.net, which GFW blocks in CN; when the
|
|
17
|
-
CDN failed the whole UI rendered unstyled AND the `.hidden` login overlay
|
|
18
|
-
became visible (no users → "can't log in"). Serving locally makes the UI
|
|
19
|
-
work offline / behind GFW with zero behavior change. -->
|
|
20
|
-
<link href="vendor/daisyui-full.min.css" rel="stylesheet"
|
|
21
|
-
integrity="sha384-Qn1dWOhPHD8ZitIQRnpquZJZmyWs+sq1SKENTuBIc3+Yg16SG2u3RqsC8LVbkZre" crossorigin="anonymous">
|
|
22
|
-
<script src="vendor/tailwind.js"
|
|
23
|
-
integrity="sha384-igm5BeiBt36UU4gqwWS7imYmelpTsZlQ45FZf+XBn9MuJbn4nQr7yx1yFydocC/K" crossorigin="anonymous"></script>
|
|
24
|
-
<!-- Markdown + Code highlighting -->
|
|
25
|
-
<script src="vendor/marked.min.js"
|
|
26
|
-
integrity="sha384-948ahk4ZmxYVYOc+rxN1H2gM1EJ2Duhp7uHtZ4WSLkV4Vtx5MUqnV+l7u9B+jFv+" crossorigin="anonymous"></script>
|
|
27
|
-
<!-- P2-SEC-01: SRI integrity for both hljs themes — toggle disabled instead of changing href -->
|
|
28
|
-
<link id="hljs-theme-dark" rel="stylesheet" href="vendor/github-dark.min.css"
|
|
29
|
-
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH" crossorigin="anonymous">
|
|
30
|
-
<link id="hljs-theme-light" rel="stylesheet" href="vendor/github.min.css" disabled
|
|
31
|
-
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L" crossorigin="anonymous">
|
|
32
|
-
<script src="vendor/highlight.min.js"
|
|
33
|
-
integrity="sha384-F/bZzf7p3Joyp5psL90p/p89AZJsndkSoGwRpXcZhleCWhd8SnRuoYo4d0yirjJp" crossorigin="anonymous"></script>
|
|
34
|
-
<link rel="stylesheet" href="style.css">
|
|
35
|
-
</head>
|
|
36
|
-
<body class="bg-base-300 h-screen overflow-hidden">
|
|
37
|
-
|
|
38
|
-
<!-- ── Login / Register Screen (shown when auth required) ──── -->
|
|
39
|
-
<div id="auth-screen" class="auth-screen hidden">
|
|
40
|
-
<div class="auth-card">
|
|
41
|
-
<div class="text-center mb-6">
|
|
42
|
-
<div class="text-4xl mb-2">🤖</div>
|
|
43
|
-
<h1 class="text-2xl font-bold text-primary">ai-cli</h1>
|
|
44
|
-
<p id="auth-subtitle" class="text-sm text-base-content/60 mt-1">Sign in to continue</p>
|
|
45
|
-
</div>
|
|
46
|
-
<div id="auth-error" class="alert alert-error text-sm mb-4 hidden" role="alert" aria-live="assertive"></div>
|
|
47
|
-
<form id="auth-form" >
|
|
48
|
-
<div class="form-control mb-3">
|
|
49
|
-
<label class="label" for="auth-username"><span class="label-text">Username</span></label>
|
|
50
|
-
<input id="auth-username" type="text" class="input input-bordered w-full" placeholder="username" autocomplete="username" required minlength="2" maxlength="32">
|
|
51
|
-
</div>
|
|
52
|
-
<div class="form-control mb-4">
|
|
53
|
-
<label class="label" for="auth-password"><span class="label-text">Password</span></label>
|
|
54
|
-
<input id="auth-password" type="password" class="input input-bordered w-full" placeholder="password" autocomplete="current-password" required minlength="4">
|
|
55
|
-
</div>
|
|
56
|
-
<button id="auth-submit" type="submit" class="btn btn-primary w-full">Sign In</button>
|
|
57
|
-
</form>
|
|
58
|
-
<div class="text-center mt-4">
|
|
59
|
-
<button id="auth-toggle" class="btn btn-ghost btn-sm" data-action="toggle-auth-mode" type="button">
|
|
60
|
-
Don't have an account? <span class="text-primary">Register</span>
|
|
61
|
-
</button>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<div id="app" class="flex flex-col h-screen">
|
|
67
|
-
|
|
68
|
-
<!-- ── Navbar ─────────────────────────────────────── -->
|
|
69
|
-
<div class="navbar bg-base-200 border-b border-base-content/10 px-4 min-h-[3.5rem] flex-shrink-0">
|
|
70
|
-
<div class="navbar-start gap-2">
|
|
71
|
-
<button id="btn-sidebar-toggle" class="btn btn-sm btn-ghost sidebar-toggle-btn" title="Toggle sidebar" aria-label="Toggle sidebar">
|
|
72
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
|
|
73
|
-
</button>
|
|
74
|
-
<span class="text-lg font-bold text-primary brand-text">🤖 ai-cli</span>
|
|
75
|
-
<select id="provider-select" class="select select-sm select-bordered navbar-select" title="Provider" aria-label="Provider"></select>
|
|
76
|
-
<select id="model-select" class="select select-sm select-bordered navbar-select" title="Model" aria-label="Model"></select>
|
|
77
|
-
</div>
|
|
78
|
-
<div class="navbar-end gap-1">
|
|
79
|
-
<button id="btn-think" class="btn btn-sm btn-ghost" title="Toggle thinking mode" aria-label="Toggle thinking mode">💭 Think</button>
|
|
80
|
-
<button id="btn-plan" class="btn btn-sm btn-ghost" title="Toggle plan mode" aria-label="Toggle plan mode">📋 Plan</button>
|
|
81
|
-
<div class="divider divider-horizontal mx-0"></div>
|
|
82
|
-
<button id="btn-clear" class="btn btn-sm btn-ghost" title="Clear conversation" aria-label="Clear conversation">🗑️</button>
|
|
83
|
-
<button id="btn-compact" class="btn btn-sm btn-ghost" title="Compact conversation" aria-label="Compact conversation">📦</button>
|
|
84
|
-
<div class="dropdown dropdown-end">
|
|
85
|
-
<button type="button" class="btn btn-sm btn-ghost" aria-label="Choose theme" aria-haspopup="menu">🎨</button>
|
|
86
|
-
<ul tabindex="0" class="dropdown-content menu bg-base-200 rounded-box z-10 w-40 p-2 shadow-lg border border-base-content/10">
|
|
87
|
-
<li><a data-theme-choice="dark">🌙 Dark</a></li>
|
|
88
|
-
<li><a data-theme-choice="night">🌃 Night</a></li>
|
|
89
|
-
<li><a data-theme-choice="dim">🌑 Dim</a></li>
|
|
90
|
-
<li><a data-theme-choice="synthwave">🎵 Synthwave</a></li>
|
|
91
|
-
<li><a data-theme-choice="cyberpunk">🤖 Cyberpunk</a></li>
|
|
92
|
-
<li><a data-theme-choice="light">☀️ Light</a></li>
|
|
93
|
-
<li><a data-theme-choice="cupcake">🧁 Cupcake</a></li>
|
|
94
|
-
<li><a data-theme-choice="nord">❄️ Nord</a></li>
|
|
95
|
-
</ul>
|
|
96
|
-
</div>
|
|
97
|
-
<!-- Enable Auth button (shown when no users registered) -->
|
|
98
|
-
<button id="btn-enable-auth" class="btn btn-sm btn-ghost hidden" title="Enable multi-user auth" data-action="show-enable-auth" aria-label="Enable multi-user auth">👤 Enable Auth</button>
|
|
99
|
-
<!-- User menu (shown when authenticated) -->
|
|
100
|
-
<div id="user-menu" class="dropdown dropdown-end hidden">
|
|
101
|
-
<button type="button" class="btn btn-sm btn-ghost gap-1" aria-label="User menu" aria-haspopup="menu">
|
|
102
|
-
<span id="user-display">👤</span>
|
|
103
|
-
</button>
|
|
104
|
-
<ul tabindex="0" class="dropdown-content menu bg-base-200 rounded-box z-10 w-40 p-2 shadow-lg border border-base-content/10">
|
|
105
|
-
<li><a id="user-label" class="text-sm font-semibold pointer-events-none"></a></li>
|
|
106
|
-
<li><a data-action="logout">🚪 Logout</a></li>
|
|
107
|
-
</ul>
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
|
|
112
|
-
<!-- ── Main content: sidebar + chat ──────────────── -->
|
|
113
|
-
<div class="flex flex-1 overflow-hidden">
|
|
114
|
-
|
|
115
|
-
<!-- Sidebar -->
|
|
116
|
-
<aside id="sidebar" class="sidebar bg-base-200 border-r border-base-content/10 flex flex-col flex-shrink-0 overflow-hidden">
|
|
117
|
-
<!-- Sidebar tabs -->
|
|
118
|
-
<div class="flex border-b border-base-content/10 flex-shrink-0" role="tablist" aria-label="Sidebar sections">
|
|
119
|
-
<button id="sidebar-tab-dashboard" class="sidebar-tab active flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="dashboard" role="tab" aria-controls="tab-dashboard" aria-selected="true" title="Agent control dashboard" aria-label="Agent control dashboard">⌘ Dash</button>
|
|
120
|
-
<button id="sidebar-tab-sessions" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="sessions" role="tab" aria-controls="tab-sessions" aria-selected="false" tabindex="-1">📋 Sessions</button>
|
|
121
|
-
<button id="sidebar-tab-branches" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="branches" role="tab" aria-controls="tab-branches" aria-selected="false" tabindex="-1" title="Conversation branches (B2)" aria-label="Conversation branches (B2)">🌿 Branches</button>
|
|
122
|
-
<button id="sidebar-tab-tools" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="tools" role="tab" aria-controls="tab-tools" aria-selected="false" tabindex="-1">🔧 Tools</button>
|
|
123
|
-
<button id="sidebar-tab-files" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="files" role="tab" aria-controls="tab-files" aria-selected="false" tabindex="-1">📁 Files</button>
|
|
124
|
-
<button id="sidebar-tab-memory" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="memory" role="tab" aria-controls="tab-memory" aria-selected="false" tabindex="-1" title="Chat memory semantic recall (B4, v0.4.90)" aria-label="Chat memory semantic recall (B4, v0.4.90)">🧠 Memory</button>
|
|
125
|
-
<button id="sidebar-tab-hub" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="hub" role="tab" aria-controls="tab-hub" aria-selected="false" tabindex="-1" title="Multi-agent brainstorm room (P4)" aria-label="Multi-agent brainstorm room (P4)">🏛 Hub</button>
|
|
126
|
-
</div>
|
|
127
|
-
<!-- Dashboard tab (Phase 6) -->
|
|
128
|
-
<div id="tab-dashboard" role="tabpanel" aria-labelledby="sidebar-tab-dashboard" aria-hidden="false" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden">
|
|
129
|
-
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
130
|
-
<span class="text-xs font-semibold flex-1">Agent Console</span>
|
|
131
|
-
<button id="btn-dashboard-refresh" class="btn btn-xs btn-ghost" title="Refresh dashboard" aria-label="Refresh dashboard">↻</button>
|
|
132
|
-
</div>
|
|
133
|
-
<div id="dashboard-panel" class="dashboard-panel flex-1 overflow-y-auto p-2 text-sm">
|
|
134
|
-
<div class="text-xs opacity-40 text-center py-4">Waiting for status…</div>
|
|
135
|
-
</div>
|
|
136
|
-
</div>
|
|
137
|
-
<!-- Sessions tab -->
|
|
138
|
-
<div id="tab-sessions" role="tabpanel" aria-labelledby="sidebar-tab-sessions" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
139
|
-
<div class="p-2 border-b border-base-content/10 flex items-center justify-between gap-1">
|
|
140
|
-
<input id="session-search" type="text" aria-label="Search sessions" class="input input-xs input-bordered flex-1 min-w-0" placeholder="Search...">
|
|
141
|
-
<button id="btn-batch-select" class="btn btn-xs btn-ghost flex-shrink-0" title="Select multiple" data-action="toggle-batch-select" aria-label="Select multiple">☑</button>
|
|
142
|
-
<button id="btn-new-session" class="btn btn-xs btn-primary btn-outline flex-shrink-0 whitespace-nowrap" title="New session" aria-label="New session">+ New</button>
|
|
143
|
-
</div>
|
|
144
|
-
<!-- Batch action bar (hidden by default) -->
|
|
145
|
-
<div id="batch-bar" class="hidden px-2 py-1 border-b border-base-content/10 flex items-center gap-1 bg-base-300 text-xs">
|
|
146
|
-
<span class="batch-count opacity-60">0 selected</span>
|
|
147
|
-
<span class="flex-1"></span>
|
|
148
|
-
<button class="btn btn-xs btn-ghost" data-action="select-all-sessions">All</button>
|
|
149
|
-
<button class="btn btn-xs btn-error btn-outline" data-action="batch-delete-selected">🗑 Delete</button>
|
|
150
|
-
<button class="btn btn-xs btn-ghost" data-action="toggle-batch-select">Cancel</button>
|
|
151
|
-
</div>
|
|
152
|
-
<div id="session-list" class="flex-1 overflow-y-auto p-2 flex flex-col gap-1 text-sm">
|
|
153
|
-
<div class="text-xs opacity-40 text-center py-4">No sessions yet</div>
|
|
154
|
-
</div>
|
|
155
|
-
</div>
|
|
156
|
-
<!-- Branches tab (B2) -->
|
|
157
|
-
<div id="tab-branches" role="tabpanel" aria-labelledby="sidebar-tab-branches" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
158
|
-
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
159
|
-
<span class="text-xs opacity-60 flex-1 truncate" id="branches-header">No session</span>
|
|
160
|
-
<button id="btn-branch-new" class="btn btn-xs btn-primary btn-outline flex-shrink-0 whitespace-nowrap" title="Fork at current tip" aria-label="Fork at current tip">+ Fork</button>
|
|
161
|
-
</div>
|
|
162
|
-
<div id="branch-list" class="flex-1 overflow-y-auto p-2 flex flex-col gap-1 text-sm">
|
|
163
|
-
<div class="text-xs opacity-40 text-center py-4">Load a session to see branches</div>
|
|
164
|
-
</div>
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
<!-- Tools tab -->
|
|
168
|
-
<div id="tab-tools" role="tabpanel" aria-labelledby="sidebar-tab-tools" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
169
|
-
<div class="p-2 border-b border-base-content/10">
|
|
170
|
-
<input id="tools-search" type="text" aria-label="Search tools" class="input input-xs input-bordered w-full" placeholder="Search tools...">
|
|
171
|
-
</div>
|
|
172
|
-
<div id="tools-list" class="flex-1 overflow-y-auto p-2 text-sm">
|
|
173
|
-
<div class="text-xs opacity-40 text-center py-4">Type /tools to load</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
<!-- Files tab -->
|
|
177
|
-
<div id="tab-files" role="tabpanel" aria-labelledby="sidebar-tab-files" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
178
|
-
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
179
|
-
<span class="text-xs opacity-40 flex-1 truncate" id="file-tree-cwd" title="">cwd</span>
|
|
180
|
-
<button id="btn-file-tree-refresh" aria-label="Refresh file tree" class="btn btn-xs btn-ghost opacity-50 hover:opacity-100 flex-shrink-0" title="Refresh file tree">↺</button>
|
|
181
|
-
</div>
|
|
182
|
-
<div id="file-tree" class="flex-1 overflow-y-auto py-1 text-sm">
|
|
183
|
-
<div class="text-xs opacity-40 text-center py-4">Click tab to load</div>
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
<!-- Memory tab (B4, v0.4.90+) -->
|
|
188
|
-
<div id="tab-memory" role="tabpanel" aria-labelledby="sidebar-tab-memory" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
189
|
-
<div class="p-2 border-b border-base-content/10 flex flex-col gap-1">
|
|
190
|
-
<div class="flex items-center gap-1">
|
|
191
|
-
<input id="memory-search-input" type="text" aria-label="Search past chats" class="input input-xs input-bordered flex-1 min-w-0" placeholder="Search past chats (semantic)…">
|
|
192
|
-
<button id="btn-memory-search" aria-label="Search memory" class="btn btn-xs btn-primary btn-outline flex-shrink-0" title="Search">🔍</button>
|
|
193
|
-
</div>
|
|
194
|
-
<div class="flex items-center gap-1 text-xs">
|
|
195
|
-
<label class="flex items-center gap-1 opacity-70 cursor-pointer">
|
|
196
|
-
<input id="memory-exclude-current" type="checkbox" class="checkbox checkbox-xs">
|
|
197
|
-
<span>exclude current</span>
|
|
198
|
-
</label>
|
|
199
|
-
<span class="flex-1"></span>
|
|
200
|
-
<button id="btn-memory-refresh" class="btn btn-xs btn-ghost" title="Incremental refresh" aria-label="Incremental refresh">↻</button>
|
|
201
|
-
<button id="btn-memory-rebuild" class="btn btn-xs btn-ghost" title="Full rebuild (slow first run)" aria-label="Full rebuild (slow first run)">⟳ Rebuild</button>
|
|
202
|
-
</div>
|
|
203
|
-
<div id="memory-status" class="text-xs opacity-50 truncate">Loading index status…</div>
|
|
204
|
-
<div id="memory-governance" class="border-t border-base-content/10 pt-2 mt-1">
|
|
205
|
-
<div class="flex items-center gap-1 mb-1">
|
|
206
|
-
<span class="text-xs font-semibold flex-1">Persistent memory</span>
|
|
207
|
-
<button id="btn-memory-managed-refresh" class="btn btn-xs btn-ghost" title="Refresh persistent memory" aria-label="Refresh persistent memory">↻</button>
|
|
208
|
-
<button id="btn-memory-managed-export" class="btn btn-xs btn-ghost" title="Export persistent memory" aria-label="Export persistent memory">Export</button>
|
|
209
|
-
</div>
|
|
210
|
-
<div id="memory-managed-list" class="flex flex-col gap-1 max-h-48 overflow-y-auto text-xs">
|
|
211
|
-
<div class="opacity-40 py-1">Loading persistent memory…</div>
|
|
212
|
-
</div>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
<div id="memory-hits" class="flex-1 overflow-y-auto p-2 flex flex-col gap-2 text-sm">
|
|
216
|
-
<div class="text-xs opacity-40 text-center py-4">Type a query above to recall past chats.</div>
|
|
217
|
-
</div>
|
|
218
|
-
</div>
|
|
219
|
-
|
|
220
|
-
<!-- Hub tab (P4) — multi-agent brainstorm room -->
|
|
221
|
-
<div id="tab-hub" role="tabpanel" aria-labelledby="sidebar-tab-hub" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
222
|
-
<div class="p-2 flex flex-col gap-2 overflow-y-auto">
|
|
223
|
-
<p class="text-xs opacity-60 leading-snug">Several AI agents discuss a topic in the chat area, then a structured summary is saved to history (open it and hit 🎬 to replay).</p>
|
|
224
|
-
<textarea id="hub-topic" aria-label="Discussion topic" class="textarea textarea-bordered textarea-sm w-full" rows="2" placeholder="Discussion topic…"></textarea>
|
|
225
|
-
<label class="text-xs opacity-70">Preset
|
|
226
|
-
<select id="hub-preset" class="select select-bordered select-xs w-full mt-1">
|
|
227
|
-
<option value="brainstorm">brainstorm — 创意者·分析师·执行者</option>
|
|
228
|
-
<option value="tech-review">tech-review — 架构师·开发者·安全</option>
|
|
229
|
-
<option value="code-review">code-review — 质量·性能·测试</option>
|
|
230
|
-
<option value="debate">debate — 正方·反方·主持人</option>
|
|
231
|
-
</select>
|
|
232
|
-
</label>
|
|
233
|
-
<label class="text-xs opacity-70">Max rounds
|
|
234
|
-
<input id="hub-rounds" type="number" min="1" max="20" value="6" class="input input-bordered input-xs w-full mt-1">
|
|
235
|
-
</label>
|
|
236
|
-
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
237
|
-
<input id="hub-mix" type="checkbox" class="checkbox checkbox-xs"> Mix providers (Claude vs GPT vs DeepSeek…)
|
|
238
|
-
</label>
|
|
239
|
-
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
240
|
-
<input id="hub-vote" type="checkbox" class="checkbox checkbox-xs" checked> Convergence voting (2/3 ends early)
|
|
241
|
-
</label>
|
|
242
|
-
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
243
|
-
<input id="hub-steer" type="checkbox" class="checkbox checkbox-xs"> Human steering (pause each round to guide/stop)
|
|
244
|
-
</label>
|
|
245
|
-
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
246
|
-
<input id="hub-lanes" type="checkbox" class="checkbox checkbox-xs"> Lanes view (one column per agent)
|
|
247
|
-
</label>
|
|
248
|
-
<button id="hub-start-btn" class="btn btn-primary btn-sm w-full" data-action="start-hub">🏛 Start discussion</button>
|
|
249
|
-
<button id="hub-abort-btn" class="btn btn-error btn-outline btn-xs w-full hidden" data-action="abort-hub">⏹ Stop</button>
|
|
250
|
-
<div id="hub-status" class="text-xs opacity-60"></div>
|
|
251
|
-
</div>
|
|
252
|
-
</div>
|
|
253
|
-
</aside>
|
|
254
|
-
<!-- Sidebar resize handle -->
|
|
255
|
-
<div id="sidebar-resize" class="sidebar-resize-handle" title="Drag to resize sidebar"></div>
|
|
256
|
-
<!-- Sidebar backdrop (mobile overlay) -->
|
|
257
|
-
<div id="sidebar-backdrop" class="sidebar-backdrop hidden" data-action="close-sidebar"></div>
|
|
258
|
-
|
|
259
|
-
<!-- Chat Area -->
|
|
260
|
-
<div class="flex-1 flex flex-col overflow-hidden">
|
|
261
|
-
<!-- Session Tab Bar -->
|
|
262
|
-
<div id="session-tabs" class="session-tab-bar bg-base-200 border-b border-base-content/10 flex-shrink-0">
|
|
263
|
-
<div id="session-tabs-list" class="session-tabs-scroll"></div>
|
|
264
|
-
<button id="btn-add-tab" class="session-tab-add" title="New tab" aria-label="New tab">+</button>
|
|
265
|
-
</div>
|
|
266
|
-
<main id="chat-area" aria-label="Conversation" class="flex-1 overflow-y-auto px-4 py-4 relative">
|
|
267
|
-
<!-- Round progress bar (sticky top, hidden by default) -->
|
|
268
|
-
<div id="round-progress" class="round-progress-bar hidden">
|
|
269
|
-
<div class="round-progress-inner">
|
|
270
|
-
<span id="round-progress-label" class="round-progress-label">Round 1/25</span>
|
|
271
|
-
<progress id="round-progress-bar" class="progress progress-primary progress-sm flex-1" value="0" max="100"></progress>
|
|
272
|
-
</div>
|
|
273
|
-
</div>
|
|
274
|
-
<div id="messages" class="max-w-4xl mx-auto flex flex-col gap-3">
|
|
275
|
-
<!-- Welcome message -->
|
|
276
|
-
<div class="chat chat-start">
|
|
277
|
-
<div class="chat-bubble chat-bubble-primary">
|
|
278
|
-
Welcome to <strong>ai-cli Web UI</strong>! Select a provider & model above, then start chatting.
|
|
279
|
-
<br><span class="text-xs opacity-70">Type <code>/command</code> for REPL commands. Shift+Enter for newline. Type <code>@</code> to reference files.</span>
|
|
280
|
-
</div>
|
|
281
|
-
</div>
|
|
282
|
-
</div>
|
|
283
|
-
</main>
|
|
284
|
-
</div><!-- end chat column (tab bar + chat area) -->
|
|
285
|
-
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<!-- ── Input Area ─────────────────────────────────── -->
|
|
289
|
-
<footer class="bg-base-200 border-t border-base-content/10 px-4 py-3 flex-shrink-0 input-footer">
|
|
290
|
-
<div class="max-w-4xl mx-auto flex gap-2 items-end">
|
|
291
|
-
<button id="btn-templates" class="btn btn-ghost btn-square btn-sm self-center" title="Prompt templates" aria-label="Prompt templates">
|
|
292
|
-
<span class="text-lg">📝</span>
|
|
293
|
-
</button>
|
|
294
|
-
<textarea id="user-input" aria-label="Message"
|
|
295
|
-
class="textarea textarea-bordered flex-1 min-h-[2.75rem] max-h-[200px] resize-none leading-relaxed"
|
|
296
|
-
placeholder="Type a message... (Shift+Enter for newline)"
|
|
297
|
-
rows="1"></textarea>
|
|
298
|
-
<button id="btn-send" class="btn btn-primary btn-square" title="Send" aria-label="Send message">
|
|
299
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor">
|
|
300
|
-
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
|
|
301
|
-
</svg>
|
|
302
|
-
</button>
|
|
303
|
-
<button id="btn-stop" class="btn btn-error btn-square hidden" title="Stop" aria-label="Stop response">
|
|
304
|
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor">
|
|
305
|
-
<rect x="6" y="6" width="12" height="12" rx="1"/>
|
|
306
|
-
</svg>
|
|
307
|
-
</button>
|
|
308
|
-
</div>
|
|
309
|
-
<!-- Status bar -->
|
|
310
|
-
<div class="max-w-4xl mx-auto flex gap-4 mt-2 text-xs opacity-50" role="status" aria-live="polite">
|
|
311
|
-
<span id="status-session"></span>
|
|
312
|
-
<span id="status-tokens"></span>
|
|
313
|
-
<span id="connection-status">⚪ Connecting...</span>
|
|
314
|
-
</div>
|
|
315
|
-
</footer>
|
|
316
|
-
|
|
317
|
-
</div>
|
|
318
|
-
|
|
319
|
-
<!-- ── Prompt Templates Modal ───────────────────────── -->
|
|
320
|
-
<dialog id="templates-modal" class="modal" aria-labelledby="templates-modal-title">
|
|
321
|
-
<div class="modal-box max-w-2xl bg-base-200">
|
|
322
|
-
<div class="flex items-center justify-between mb-3">
|
|
323
|
-
<h3 id="templates-modal-title" class="font-bold text-lg">📝 Prompt Templates</h3>
|
|
324
|
-
<div class="flex gap-1">
|
|
325
|
-
<button class="btn btn-xs btn-ghost" data-action="import-templates" title="Import" aria-label="Import">📥 Import</button>
|
|
326
|
-
<button class="btn btn-xs btn-ghost" data-action="export-templates" title="Export" aria-label="Export">📤 Export</button>
|
|
327
|
-
<button class="btn btn-xs btn-ghost" data-action="show-add-template" title="New template" aria-label="New template">+ New</button>
|
|
328
|
-
</div>
|
|
329
|
-
</div>
|
|
330
|
-
|
|
331
|
-
<!-- Add/Edit form (hidden by default) -->
|
|
332
|
-
<div id="template-form" class="hidden mb-3 p-3 bg-base-300 rounded-lg">
|
|
333
|
-
<input id="tpl-name" type="text" class="input input-sm input-bordered w-full mb-2" placeholder="Template name">
|
|
334
|
-
<textarea id="tpl-content" class="textarea textarea-bordered w-full text-sm mb-2" rows="4" placeholder="Prompt content..."></textarea>
|
|
335
|
-
<input id="tpl-tags" type="text" class="input input-sm input-bordered w-full mb-2" placeholder="Tags (comma-separated, optional)">
|
|
336
|
-
<div class="flex gap-2 justify-end">
|
|
337
|
-
<button class="btn btn-sm btn-ghost" data-action="cancel-template-form">Cancel</button>
|
|
338
|
-
<button class="btn btn-sm btn-primary" data-action="save-template-form">Save</button>
|
|
339
|
-
</div>
|
|
340
|
-
<input type="hidden" id="tpl-edit-id">
|
|
341
|
-
</div>
|
|
342
|
-
|
|
343
|
-
<!-- Search -->
|
|
344
|
-
<input id="template-search" type="text" class="input input-sm input-bordered w-full mb-3" placeholder="Search templates...">
|
|
345
|
-
|
|
346
|
-
<!-- Template list -->
|
|
347
|
-
<div id="template-list" class="flex flex-col gap-1 max-h-[50vh] overflow-y-auto"></div>
|
|
348
|
-
|
|
349
|
-
<div class="modal-action mt-3">
|
|
350
|
-
<form method="dialog"><button class="btn btn-sm">Close</button></form>
|
|
351
|
-
</div>
|
|
352
|
-
</div>
|
|
353
|
-
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
|
354
|
-
</dialog>
|
|
355
|
-
|
|
356
|
-
<!-- ── Session Replay Modal (B1) ───────────────────────── -->
|
|
357
|
-
<dialog id="replay-modal" class="modal" aria-labelledby="replay-modal-title">
|
|
358
|
-
<div class="modal-box max-w-5xl bg-base-200 w-11/12">
|
|
359
|
-
<div class="flex items-center justify-between mb-3">
|
|
360
|
-
<h3 id="replay-modal-title" class="font-bold text-lg">🎬 Session Replay</h3>
|
|
361
|
-
<form method="dialog"><button class="btn btn-sm btn-ghost">✕</button></form>
|
|
362
|
-
</div>
|
|
363
|
-
<div id="replay-meta" class="text-xs opacity-70 mb-2"></div>
|
|
364
|
-
<div id="replay-usage" class="text-xs mb-2"></div>
|
|
365
|
-
<div id="replay-filters" class="replay-filters flex flex-wrap gap-1 mb-3">
|
|
366
|
-
<button class="btn btn-xs btn-primary btn-outline" data-replay-filter="all">All</button>
|
|
367
|
-
<button class="btn btn-xs btn-ghost" data-replay-filter="tools">Tools</button>
|
|
368
|
-
<button class="btn btn-xs btn-ghost" data-replay-filter="agents">Agents</button>
|
|
369
|
-
<button class="btn btn-xs btn-ghost" data-replay-filter="errors">Errors</button>
|
|
370
|
-
<button class="btn btn-xs btn-ghost" data-replay-filter="cost">Cost</button>
|
|
371
|
-
</div>
|
|
372
|
-
<div id="replay-timeline" class="flex flex-col gap-2 max-h-[70vh] overflow-y-auto pr-2"></div>
|
|
373
|
-
</div>
|
|
374
|
-
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
|
375
|
-
</dialog>
|
|
376
|
-
|
|
377
|
-
<!-- state.js stays a classic script (NOT a module): its top-level `let`
|
|
378
|
-
globals live in the shared global lexical environment so the ES modules
|
|
379
|
-
below can read AND reassign them as free variables. Must load first. -->
|
|
380
|
-
<script src="state.js"></script>
|
|
381
|
-
<!-- ES modules (P0-4 Phase 2). Ordered so top-level side effects run
|
|
382
|
-
app → templates → actions, matching the previous classic-script order.
|
|
383
|
-
util.js loads via `import` from app.js (no tag needed). -->
|
|
384
|
-
<script type="module" src="app.js"></script>
|
|
385
|
-
<script type="module" src="templates.js"></script>
|
|
386
|
-
<script type="module" src="actions.js"></script>
|
|
387
|
-
</body>
|
|
388
|
-
</html>
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" data-theme="dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
6
|
+
<title>ai-cli Web UI</title>
|
|
7
|
+
<!-- PWA -->
|
|
8
|
+
<link rel="manifest" href="manifest.json">
|
|
9
|
+
<meta name="theme-color" content="#6419e6">
|
|
10
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
11
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
12
|
+
<link rel="apple-touch-icon" href="icon-192.png">
|
|
13
|
+
<link rel="icon" type="image/svg+xml" href="icon.svg">
|
|
14
|
+
<link rel="icon" type="image/png" sizes="192x192" href="icon-192.png">
|
|
15
|
+
<!-- Tailwind CSS + DaisyUI (vendored locally — v0.4.153). These were on
|
|
16
|
+
cdn.tailwindcss.com / cdn.jsdelivr.net, which GFW blocks in CN; when the
|
|
17
|
+
CDN failed the whole UI rendered unstyled AND the `.hidden` login overlay
|
|
18
|
+
became visible (no users → "can't log in"). Serving locally makes the UI
|
|
19
|
+
work offline / behind GFW with zero behavior change. -->
|
|
20
|
+
<link href="vendor/daisyui-full.min.css" rel="stylesheet"
|
|
21
|
+
integrity="sha384-Qn1dWOhPHD8ZitIQRnpquZJZmyWs+sq1SKENTuBIc3+Yg16SG2u3RqsC8LVbkZre" crossorigin="anonymous">
|
|
22
|
+
<script src="vendor/tailwind.js"
|
|
23
|
+
integrity="sha384-igm5BeiBt36UU4gqwWS7imYmelpTsZlQ45FZf+XBn9MuJbn4nQr7yx1yFydocC/K" crossorigin="anonymous"></script>
|
|
24
|
+
<!-- Markdown + Code highlighting -->
|
|
25
|
+
<script src="vendor/marked.min.js"
|
|
26
|
+
integrity="sha384-948ahk4ZmxYVYOc+rxN1H2gM1EJ2Duhp7uHtZ4WSLkV4Vtx5MUqnV+l7u9B+jFv+" crossorigin="anonymous"></script>
|
|
27
|
+
<!-- P2-SEC-01: SRI integrity for both hljs themes — toggle disabled instead of changing href -->
|
|
28
|
+
<link id="hljs-theme-dark" rel="stylesheet" href="vendor/github-dark.min.css"
|
|
29
|
+
integrity="sha384-wH75j6z1lH97ZOpMOInqhgKzFkAInZPPSPlZpYKYTOqsaizPvhQZmAtLcPKXpLyH" crossorigin="anonymous">
|
|
30
|
+
<link id="hljs-theme-light" rel="stylesheet" href="vendor/github.min.css" disabled
|
|
31
|
+
integrity="sha384-eFTL69TLRZTkNfYZOLM+G04821K1qZao/4QLJbet1pP4tcF+fdXq/9CdqAbWRl/L" crossorigin="anonymous">
|
|
32
|
+
<script src="vendor/highlight.min.js"
|
|
33
|
+
integrity="sha384-F/bZzf7p3Joyp5psL90p/p89AZJsndkSoGwRpXcZhleCWhd8SnRuoYo4d0yirjJp" crossorigin="anonymous"></script>
|
|
34
|
+
<link rel="stylesheet" href="style.css">
|
|
35
|
+
</head>
|
|
36
|
+
<body class="bg-base-300 h-screen overflow-hidden">
|
|
37
|
+
|
|
38
|
+
<!-- ── Login / Register Screen (shown when auth required) ──── -->
|
|
39
|
+
<div id="auth-screen" class="auth-screen hidden">
|
|
40
|
+
<div class="auth-card">
|
|
41
|
+
<div class="text-center mb-6">
|
|
42
|
+
<div class="text-4xl mb-2">🤖</div>
|
|
43
|
+
<h1 class="text-2xl font-bold text-primary">ai-cli</h1>
|
|
44
|
+
<p id="auth-subtitle" class="text-sm text-base-content/60 mt-1">Sign in to continue</p>
|
|
45
|
+
</div>
|
|
46
|
+
<div id="auth-error" class="alert alert-error text-sm mb-4 hidden" role="alert" aria-live="assertive"></div>
|
|
47
|
+
<form id="auth-form" >
|
|
48
|
+
<div class="form-control mb-3">
|
|
49
|
+
<label class="label" for="auth-username"><span class="label-text">Username</span></label>
|
|
50
|
+
<input id="auth-username" type="text" class="input input-bordered w-full" placeholder="username" autocomplete="username" required minlength="2" maxlength="32">
|
|
51
|
+
</div>
|
|
52
|
+
<div class="form-control mb-4">
|
|
53
|
+
<label class="label" for="auth-password"><span class="label-text">Password</span></label>
|
|
54
|
+
<input id="auth-password" type="password" class="input input-bordered w-full" placeholder="password" autocomplete="current-password" required minlength="4">
|
|
55
|
+
</div>
|
|
56
|
+
<button id="auth-submit" type="submit" class="btn btn-primary w-full">Sign In</button>
|
|
57
|
+
</form>
|
|
58
|
+
<div class="text-center mt-4">
|
|
59
|
+
<button id="auth-toggle" class="btn btn-ghost btn-sm" data-action="toggle-auth-mode" type="button">
|
|
60
|
+
Don't have an account? <span class="text-primary">Register</span>
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div id="app" class="flex flex-col h-screen">
|
|
67
|
+
|
|
68
|
+
<!-- ── Navbar ─────────────────────────────────────── -->
|
|
69
|
+
<div class="navbar bg-base-200 border-b border-base-content/10 px-4 min-h-[3.5rem] flex-shrink-0">
|
|
70
|
+
<div class="navbar-start gap-2">
|
|
71
|
+
<button id="btn-sidebar-toggle" class="btn btn-sm btn-ghost sidebar-toggle-btn" title="Toggle sidebar" aria-label="Toggle sidebar">
|
|
72
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/></svg>
|
|
73
|
+
</button>
|
|
74
|
+
<span class="text-lg font-bold text-primary brand-text">🤖 ai-cli</span>
|
|
75
|
+
<select id="provider-select" class="select select-sm select-bordered navbar-select" title="Provider" aria-label="Provider"></select>
|
|
76
|
+
<select id="model-select" class="select select-sm select-bordered navbar-select" title="Model" aria-label="Model"></select>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="navbar-end gap-1">
|
|
79
|
+
<button id="btn-think" class="btn btn-sm btn-ghost" title="Toggle thinking mode" aria-label="Toggle thinking mode">💭 Think</button>
|
|
80
|
+
<button id="btn-plan" class="btn btn-sm btn-ghost" title="Toggle plan mode" aria-label="Toggle plan mode">📋 Plan</button>
|
|
81
|
+
<div class="divider divider-horizontal mx-0"></div>
|
|
82
|
+
<button id="btn-clear" class="btn btn-sm btn-ghost" title="Clear conversation" aria-label="Clear conversation">🗑️</button>
|
|
83
|
+
<button id="btn-compact" class="btn btn-sm btn-ghost" title="Compact conversation" aria-label="Compact conversation">📦</button>
|
|
84
|
+
<div class="dropdown dropdown-end">
|
|
85
|
+
<button type="button" class="btn btn-sm btn-ghost" aria-label="Choose theme" aria-haspopup="menu">🎨</button>
|
|
86
|
+
<ul tabindex="0" class="dropdown-content menu bg-base-200 rounded-box z-10 w-40 p-2 shadow-lg border border-base-content/10">
|
|
87
|
+
<li><a data-theme-choice="dark">🌙 Dark</a></li>
|
|
88
|
+
<li><a data-theme-choice="night">🌃 Night</a></li>
|
|
89
|
+
<li><a data-theme-choice="dim">🌑 Dim</a></li>
|
|
90
|
+
<li><a data-theme-choice="synthwave">🎵 Synthwave</a></li>
|
|
91
|
+
<li><a data-theme-choice="cyberpunk">🤖 Cyberpunk</a></li>
|
|
92
|
+
<li><a data-theme-choice="light">☀️ Light</a></li>
|
|
93
|
+
<li><a data-theme-choice="cupcake">🧁 Cupcake</a></li>
|
|
94
|
+
<li><a data-theme-choice="nord">❄️ Nord</a></li>
|
|
95
|
+
</ul>
|
|
96
|
+
</div>
|
|
97
|
+
<!-- Enable Auth button (shown when no users registered) -->
|
|
98
|
+
<button id="btn-enable-auth" class="btn btn-sm btn-ghost hidden" title="Enable multi-user auth" data-action="show-enable-auth" aria-label="Enable multi-user auth">👤 Enable Auth</button>
|
|
99
|
+
<!-- User menu (shown when authenticated) -->
|
|
100
|
+
<div id="user-menu" class="dropdown dropdown-end hidden">
|
|
101
|
+
<button type="button" class="btn btn-sm btn-ghost gap-1" aria-label="User menu" aria-haspopup="menu">
|
|
102
|
+
<span id="user-display">👤</span>
|
|
103
|
+
</button>
|
|
104
|
+
<ul tabindex="0" class="dropdown-content menu bg-base-200 rounded-box z-10 w-40 p-2 shadow-lg border border-base-content/10">
|
|
105
|
+
<li><a id="user-label" class="text-sm font-semibold pointer-events-none"></a></li>
|
|
106
|
+
<li><a data-action="logout">🚪 Logout</a></li>
|
|
107
|
+
</ul>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<!-- ── Main content: sidebar + chat ──────────────── -->
|
|
113
|
+
<div class="flex flex-1 overflow-hidden">
|
|
114
|
+
|
|
115
|
+
<!-- Sidebar -->
|
|
116
|
+
<aside id="sidebar" class="sidebar bg-base-200 border-r border-base-content/10 flex flex-col flex-shrink-0 overflow-hidden">
|
|
117
|
+
<!-- Sidebar tabs -->
|
|
118
|
+
<div class="flex border-b border-base-content/10 flex-shrink-0" role="tablist" aria-label="Sidebar sections">
|
|
119
|
+
<button id="sidebar-tab-dashboard" class="sidebar-tab active flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="dashboard" role="tab" aria-controls="tab-dashboard" aria-selected="true" title="Agent control dashboard" aria-label="Agent control dashboard">⌘ Dash</button>
|
|
120
|
+
<button id="sidebar-tab-sessions" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="sessions" role="tab" aria-controls="tab-sessions" aria-selected="false" tabindex="-1">📋 Sessions</button>
|
|
121
|
+
<button id="sidebar-tab-branches" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="branches" role="tab" aria-controls="tab-branches" aria-selected="false" tabindex="-1" title="Conversation branches (B2)" aria-label="Conversation branches (B2)">🌿 Branches</button>
|
|
122
|
+
<button id="sidebar-tab-tools" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="tools" role="tab" aria-controls="tab-tools" aria-selected="false" tabindex="-1">🔧 Tools</button>
|
|
123
|
+
<button id="sidebar-tab-files" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="files" role="tab" aria-controls="tab-files" aria-selected="false" tabindex="-1">📁 Files</button>
|
|
124
|
+
<button id="sidebar-tab-memory" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="memory" role="tab" aria-controls="tab-memory" aria-selected="false" tabindex="-1" title="Chat memory semantic recall (B4, v0.4.90)" aria-label="Chat memory semantic recall (B4, v0.4.90)">🧠 Memory</button>
|
|
125
|
+
<button id="sidebar-tab-hub" class="sidebar-tab flex-1 text-xs font-semibold py-2 px-1 text-center" data-tab="hub" role="tab" aria-controls="tab-hub" aria-selected="false" tabindex="-1" title="Multi-agent brainstorm room (P4)" aria-label="Multi-agent brainstorm room (P4)">🏛 Hub</button>
|
|
126
|
+
</div>
|
|
127
|
+
<!-- Dashboard tab (Phase 6) -->
|
|
128
|
+
<div id="tab-dashboard" role="tabpanel" aria-labelledby="sidebar-tab-dashboard" aria-hidden="false" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden">
|
|
129
|
+
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
130
|
+
<span class="text-xs font-semibold flex-1">Agent Console</span>
|
|
131
|
+
<button id="btn-dashboard-refresh" class="btn btn-xs btn-ghost" title="Refresh dashboard" aria-label="Refresh dashboard">↻</button>
|
|
132
|
+
</div>
|
|
133
|
+
<div id="dashboard-panel" class="dashboard-panel flex-1 overflow-y-auto p-2 text-sm">
|
|
134
|
+
<div class="text-xs opacity-40 text-center py-4">Waiting for status…</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
<!-- Sessions tab -->
|
|
138
|
+
<div id="tab-sessions" role="tabpanel" aria-labelledby="sidebar-tab-sessions" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
139
|
+
<div class="p-2 border-b border-base-content/10 flex items-center justify-between gap-1">
|
|
140
|
+
<input id="session-search" type="text" aria-label="Search sessions" class="input input-xs input-bordered flex-1 min-w-0" placeholder="Search...">
|
|
141
|
+
<button id="btn-batch-select" class="btn btn-xs btn-ghost flex-shrink-0" title="Select multiple" data-action="toggle-batch-select" aria-label="Select multiple">☑</button>
|
|
142
|
+
<button id="btn-new-session" class="btn btn-xs btn-primary btn-outline flex-shrink-0 whitespace-nowrap" title="New session" aria-label="New session">+ New</button>
|
|
143
|
+
</div>
|
|
144
|
+
<!-- Batch action bar (hidden by default) -->
|
|
145
|
+
<div id="batch-bar" class="hidden px-2 py-1 border-b border-base-content/10 flex items-center gap-1 bg-base-300 text-xs">
|
|
146
|
+
<span class="batch-count opacity-60">0 selected</span>
|
|
147
|
+
<span class="flex-1"></span>
|
|
148
|
+
<button class="btn btn-xs btn-ghost" data-action="select-all-sessions">All</button>
|
|
149
|
+
<button class="btn btn-xs btn-error btn-outline" data-action="batch-delete-selected">🗑 Delete</button>
|
|
150
|
+
<button class="btn btn-xs btn-ghost" data-action="toggle-batch-select">Cancel</button>
|
|
151
|
+
</div>
|
|
152
|
+
<div id="session-list" class="flex-1 overflow-y-auto p-2 flex flex-col gap-1 text-sm">
|
|
153
|
+
<div class="text-xs opacity-40 text-center py-4">No sessions yet</div>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
<!-- Branches tab (B2) -->
|
|
157
|
+
<div id="tab-branches" role="tabpanel" aria-labelledby="sidebar-tab-branches" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
158
|
+
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
159
|
+
<span class="text-xs opacity-60 flex-1 truncate" id="branches-header">No session</span>
|
|
160
|
+
<button id="btn-branch-new" class="btn btn-xs btn-primary btn-outline flex-shrink-0 whitespace-nowrap" title="Fork at current tip" aria-label="Fork at current tip">+ Fork</button>
|
|
161
|
+
</div>
|
|
162
|
+
<div id="branch-list" class="flex-1 overflow-y-auto p-2 flex flex-col gap-1 text-sm">
|
|
163
|
+
<div class="text-xs opacity-40 text-center py-4">Load a session to see branches</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
<!-- Tools tab -->
|
|
168
|
+
<div id="tab-tools" role="tabpanel" aria-labelledby="sidebar-tab-tools" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
169
|
+
<div class="p-2 border-b border-base-content/10">
|
|
170
|
+
<input id="tools-search" type="text" aria-label="Search tools" class="input input-xs input-bordered w-full" placeholder="Search tools...">
|
|
171
|
+
</div>
|
|
172
|
+
<div id="tools-list" class="flex-1 overflow-y-auto p-2 text-sm">
|
|
173
|
+
<div class="text-xs opacity-40 text-center py-4">Type /tools to load</div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
<!-- Files tab -->
|
|
177
|
+
<div id="tab-files" role="tabpanel" aria-labelledby="sidebar-tab-files" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
178
|
+
<div class="p-2 border-b border-base-content/10 flex items-center gap-1">
|
|
179
|
+
<span class="text-xs opacity-40 flex-1 truncate" id="file-tree-cwd" title="">cwd</span>
|
|
180
|
+
<button id="btn-file-tree-refresh" aria-label="Refresh file tree" class="btn btn-xs btn-ghost opacity-50 hover:opacity-100 flex-shrink-0" title="Refresh file tree">↺</button>
|
|
181
|
+
</div>
|
|
182
|
+
<div id="file-tree" class="flex-1 overflow-y-auto py-1 text-sm">
|
|
183
|
+
<div class="text-xs opacity-40 text-center py-4">Click tab to load</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<!-- Memory tab (B4, v0.4.90+) -->
|
|
188
|
+
<div id="tab-memory" role="tabpanel" aria-labelledby="sidebar-tab-memory" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
189
|
+
<div class="p-2 border-b border-base-content/10 flex flex-col gap-1">
|
|
190
|
+
<div class="flex items-center gap-1">
|
|
191
|
+
<input id="memory-search-input" type="text" aria-label="Search past chats" class="input input-xs input-bordered flex-1 min-w-0" placeholder="Search past chats (semantic)…">
|
|
192
|
+
<button id="btn-memory-search" aria-label="Search memory" class="btn btn-xs btn-primary btn-outline flex-shrink-0" title="Search">🔍</button>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="flex items-center gap-1 text-xs">
|
|
195
|
+
<label class="flex items-center gap-1 opacity-70 cursor-pointer">
|
|
196
|
+
<input id="memory-exclude-current" type="checkbox" class="checkbox checkbox-xs">
|
|
197
|
+
<span>exclude current</span>
|
|
198
|
+
</label>
|
|
199
|
+
<span class="flex-1"></span>
|
|
200
|
+
<button id="btn-memory-refresh" class="btn btn-xs btn-ghost" title="Incremental refresh" aria-label="Incremental refresh">↻</button>
|
|
201
|
+
<button id="btn-memory-rebuild" class="btn btn-xs btn-ghost" title="Full rebuild (slow first run)" aria-label="Full rebuild (slow first run)">⟳ Rebuild</button>
|
|
202
|
+
</div>
|
|
203
|
+
<div id="memory-status" class="text-xs opacity-50 truncate">Loading index status…</div>
|
|
204
|
+
<div id="memory-governance" class="border-t border-base-content/10 pt-2 mt-1">
|
|
205
|
+
<div class="flex items-center gap-1 mb-1">
|
|
206
|
+
<span class="text-xs font-semibold flex-1">Persistent memory</span>
|
|
207
|
+
<button id="btn-memory-managed-refresh" class="btn btn-xs btn-ghost" title="Refresh persistent memory" aria-label="Refresh persistent memory">↻</button>
|
|
208
|
+
<button id="btn-memory-managed-export" class="btn btn-xs btn-ghost" title="Export persistent memory" aria-label="Export persistent memory">Export</button>
|
|
209
|
+
</div>
|
|
210
|
+
<div id="memory-managed-list" class="flex flex-col gap-1 max-h-48 overflow-y-auto text-xs">
|
|
211
|
+
<div class="opacity-40 py-1">Loading persistent memory…</div>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
<div id="memory-hits" class="flex-1 overflow-y-auto p-2 flex flex-col gap-2 text-sm">
|
|
216
|
+
<div class="text-xs opacity-40 text-center py-4">Type a query above to recall past chats.</div>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<!-- Hub tab (P4) — multi-agent brainstorm room -->
|
|
221
|
+
<div id="tab-hub" role="tabpanel" aria-labelledby="sidebar-tab-hub" aria-hidden="true" class="sidebar-tab-content flex flex-col flex-1 overflow-hidden hidden">
|
|
222
|
+
<div class="p-2 flex flex-col gap-2 overflow-y-auto">
|
|
223
|
+
<p class="text-xs opacity-60 leading-snug">Several AI agents discuss a topic in the chat area, then a structured summary is saved to history (open it and hit 🎬 to replay).</p>
|
|
224
|
+
<textarea id="hub-topic" aria-label="Discussion topic" class="textarea textarea-bordered textarea-sm w-full" rows="2" placeholder="Discussion topic…"></textarea>
|
|
225
|
+
<label class="text-xs opacity-70">Preset
|
|
226
|
+
<select id="hub-preset" class="select select-bordered select-xs w-full mt-1">
|
|
227
|
+
<option value="brainstorm">brainstorm — 创意者·分析师·执行者</option>
|
|
228
|
+
<option value="tech-review">tech-review — 架构师·开发者·安全</option>
|
|
229
|
+
<option value="code-review">code-review — 质量·性能·测试</option>
|
|
230
|
+
<option value="debate">debate — 正方·反方·主持人</option>
|
|
231
|
+
</select>
|
|
232
|
+
</label>
|
|
233
|
+
<label class="text-xs opacity-70">Max rounds
|
|
234
|
+
<input id="hub-rounds" type="number" min="1" max="20" value="6" class="input input-bordered input-xs w-full mt-1">
|
|
235
|
+
</label>
|
|
236
|
+
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
237
|
+
<input id="hub-mix" type="checkbox" class="checkbox checkbox-xs"> Mix providers (Claude vs GPT vs DeepSeek…)
|
|
238
|
+
</label>
|
|
239
|
+
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
240
|
+
<input id="hub-vote" type="checkbox" class="checkbox checkbox-xs" checked> Convergence voting (2/3 ends early)
|
|
241
|
+
</label>
|
|
242
|
+
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
243
|
+
<input id="hub-steer" type="checkbox" class="checkbox checkbox-xs"> Human steering (pause each round to guide/stop)
|
|
244
|
+
</label>
|
|
245
|
+
<label class="flex items-center gap-2 text-xs cursor-pointer">
|
|
246
|
+
<input id="hub-lanes" type="checkbox" class="checkbox checkbox-xs"> Lanes view (one column per agent)
|
|
247
|
+
</label>
|
|
248
|
+
<button id="hub-start-btn" class="btn btn-primary btn-sm w-full" data-action="start-hub">🏛 Start discussion</button>
|
|
249
|
+
<button id="hub-abort-btn" class="btn btn-error btn-outline btn-xs w-full hidden" data-action="abort-hub">⏹ Stop</button>
|
|
250
|
+
<div id="hub-status" class="text-xs opacity-60"></div>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
</aside>
|
|
254
|
+
<!-- Sidebar resize handle -->
|
|
255
|
+
<div id="sidebar-resize" class="sidebar-resize-handle" title="Drag to resize sidebar"></div>
|
|
256
|
+
<!-- Sidebar backdrop (mobile overlay) -->
|
|
257
|
+
<div id="sidebar-backdrop" class="sidebar-backdrop hidden" data-action="close-sidebar"></div>
|
|
258
|
+
|
|
259
|
+
<!-- Chat Area -->
|
|
260
|
+
<div class="flex-1 flex flex-col overflow-hidden">
|
|
261
|
+
<!-- Session Tab Bar -->
|
|
262
|
+
<div id="session-tabs" class="session-tab-bar bg-base-200 border-b border-base-content/10 flex-shrink-0">
|
|
263
|
+
<div id="session-tabs-list" class="session-tabs-scroll"></div>
|
|
264
|
+
<button id="btn-add-tab" class="session-tab-add" title="New tab" aria-label="New tab">+</button>
|
|
265
|
+
</div>
|
|
266
|
+
<main id="chat-area" aria-label="Conversation" class="flex-1 overflow-y-auto px-4 py-4 relative">
|
|
267
|
+
<!-- Round progress bar (sticky top, hidden by default) -->
|
|
268
|
+
<div id="round-progress" class="round-progress-bar hidden">
|
|
269
|
+
<div class="round-progress-inner">
|
|
270
|
+
<span id="round-progress-label" class="round-progress-label">Round 1/25</span>
|
|
271
|
+
<progress id="round-progress-bar" class="progress progress-primary progress-sm flex-1" value="0" max="100"></progress>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
<div id="messages" class="max-w-4xl mx-auto flex flex-col gap-3">
|
|
275
|
+
<!-- Welcome message -->
|
|
276
|
+
<div class="chat chat-start">
|
|
277
|
+
<div class="chat-bubble chat-bubble-primary">
|
|
278
|
+
Welcome to <strong>ai-cli Web UI</strong>! Select a provider & model above, then start chatting.
|
|
279
|
+
<br><span class="text-xs opacity-70">Type <code>/command</code> for REPL commands. Shift+Enter for newline. Type <code>@</code> to reference files.</span>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</main>
|
|
284
|
+
</div><!-- end chat column (tab bar + chat area) -->
|
|
285
|
+
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<!-- ── Input Area ─────────────────────────────────── -->
|
|
289
|
+
<footer class="bg-base-200 border-t border-base-content/10 px-4 py-3 flex-shrink-0 input-footer">
|
|
290
|
+
<div class="max-w-4xl mx-auto flex gap-2 items-end">
|
|
291
|
+
<button id="btn-templates" class="btn btn-ghost btn-square btn-sm self-center" title="Prompt templates" aria-label="Prompt templates">
|
|
292
|
+
<span class="text-lg">📝</span>
|
|
293
|
+
</button>
|
|
294
|
+
<textarea id="user-input" aria-label="Message"
|
|
295
|
+
class="textarea textarea-bordered flex-1 min-h-[2.75rem] max-h-[200px] resize-none leading-relaxed"
|
|
296
|
+
placeholder="Type a message... (Shift+Enter for newline)"
|
|
297
|
+
rows="1"></textarea>
|
|
298
|
+
<button id="btn-send" class="btn btn-primary btn-square" title="Send" aria-label="Send message">
|
|
299
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor">
|
|
300
|
+
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
|
|
301
|
+
</svg>
|
|
302
|
+
</button>
|
|
303
|
+
<button id="btn-stop" class="btn btn-error btn-square hidden" title="Stop" aria-label="Stop response">
|
|
304
|
+
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="currentColor">
|
|
305
|
+
<rect x="6" y="6" width="12" height="12" rx="1"/>
|
|
306
|
+
</svg>
|
|
307
|
+
</button>
|
|
308
|
+
</div>
|
|
309
|
+
<!-- Status bar -->
|
|
310
|
+
<div class="max-w-4xl mx-auto flex gap-4 mt-2 text-xs opacity-50" role="status" aria-live="polite">
|
|
311
|
+
<span id="status-session"></span>
|
|
312
|
+
<span id="status-tokens"></span>
|
|
313
|
+
<span id="connection-status">⚪ Connecting...</span>
|
|
314
|
+
</div>
|
|
315
|
+
</footer>
|
|
316
|
+
|
|
317
|
+
</div>
|
|
318
|
+
|
|
319
|
+
<!-- ── Prompt Templates Modal ───────────────────────── -->
|
|
320
|
+
<dialog id="templates-modal" class="modal" aria-labelledby="templates-modal-title">
|
|
321
|
+
<div class="modal-box max-w-2xl bg-base-200">
|
|
322
|
+
<div class="flex items-center justify-between mb-3">
|
|
323
|
+
<h3 id="templates-modal-title" class="font-bold text-lg">📝 Prompt Templates</h3>
|
|
324
|
+
<div class="flex gap-1">
|
|
325
|
+
<button class="btn btn-xs btn-ghost" data-action="import-templates" title="Import" aria-label="Import">📥 Import</button>
|
|
326
|
+
<button class="btn btn-xs btn-ghost" data-action="export-templates" title="Export" aria-label="Export">📤 Export</button>
|
|
327
|
+
<button class="btn btn-xs btn-ghost" data-action="show-add-template" title="New template" aria-label="New template">+ New</button>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
<!-- Add/Edit form (hidden by default) -->
|
|
332
|
+
<div id="template-form" class="hidden mb-3 p-3 bg-base-300 rounded-lg">
|
|
333
|
+
<input id="tpl-name" type="text" class="input input-sm input-bordered w-full mb-2" placeholder="Template name">
|
|
334
|
+
<textarea id="tpl-content" class="textarea textarea-bordered w-full text-sm mb-2" rows="4" placeholder="Prompt content..."></textarea>
|
|
335
|
+
<input id="tpl-tags" type="text" class="input input-sm input-bordered w-full mb-2" placeholder="Tags (comma-separated, optional)">
|
|
336
|
+
<div class="flex gap-2 justify-end">
|
|
337
|
+
<button class="btn btn-sm btn-ghost" data-action="cancel-template-form">Cancel</button>
|
|
338
|
+
<button class="btn btn-sm btn-primary" data-action="save-template-form">Save</button>
|
|
339
|
+
</div>
|
|
340
|
+
<input type="hidden" id="tpl-edit-id">
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
<!-- Search -->
|
|
344
|
+
<input id="template-search" type="text" class="input input-sm input-bordered w-full mb-3" placeholder="Search templates...">
|
|
345
|
+
|
|
346
|
+
<!-- Template list -->
|
|
347
|
+
<div id="template-list" class="flex flex-col gap-1 max-h-[50vh] overflow-y-auto"></div>
|
|
348
|
+
|
|
349
|
+
<div class="modal-action mt-3">
|
|
350
|
+
<form method="dialog"><button class="btn btn-sm">Close</button></form>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
|
354
|
+
</dialog>
|
|
355
|
+
|
|
356
|
+
<!-- ── Session Replay Modal (B1) ───────────────────────── -->
|
|
357
|
+
<dialog id="replay-modal" class="modal" aria-labelledby="replay-modal-title">
|
|
358
|
+
<div class="modal-box max-w-5xl bg-base-200 w-11/12">
|
|
359
|
+
<div class="flex items-center justify-between mb-3">
|
|
360
|
+
<h3 id="replay-modal-title" class="font-bold text-lg">🎬 Session Replay</h3>
|
|
361
|
+
<form method="dialog"><button class="btn btn-sm btn-ghost">✕</button></form>
|
|
362
|
+
</div>
|
|
363
|
+
<div id="replay-meta" class="text-xs opacity-70 mb-2"></div>
|
|
364
|
+
<div id="replay-usage" class="text-xs mb-2"></div>
|
|
365
|
+
<div id="replay-filters" class="replay-filters flex flex-wrap gap-1 mb-3">
|
|
366
|
+
<button class="btn btn-xs btn-primary btn-outline" data-replay-filter="all">All</button>
|
|
367
|
+
<button class="btn btn-xs btn-ghost" data-replay-filter="tools">Tools</button>
|
|
368
|
+
<button class="btn btn-xs btn-ghost" data-replay-filter="agents">Agents</button>
|
|
369
|
+
<button class="btn btn-xs btn-ghost" data-replay-filter="errors">Errors</button>
|
|
370
|
+
<button class="btn btn-xs btn-ghost" data-replay-filter="cost">Cost</button>
|
|
371
|
+
</div>
|
|
372
|
+
<div id="replay-timeline" class="flex flex-col gap-2 max-h-[70vh] overflow-y-auto pr-2"></div>
|
|
373
|
+
</div>
|
|
374
|
+
<form method="dialog" class="modal-backdrop"><button>close</button></form>
|
|
375
|
+
</dialog>
|
|
376
|
+
|
|
377
|
+
<!-- state.js stays a classic script (NOT a module): its top-level `let`
|
|
378
|
+
globals live in the shared global lexical environment so the ES modules
|
|
379
|
+
below can read AND reassign them as free variables. Must load first. -->
|
|
380
|
+
<script src="state.js"></script>
|
|
381
|
+
<!-- ES modules (P0-4 Phase 2). Ordered so top-level side effects run
|
|
382
|
+
app → templates → actions, matching the previous classic-script order.
|
|
383
|
+
util.js loads via `import` from app.js (no tag needed). -->
|
|
384
|
+
<script type="module" src="app.js"></script>
|
|
385
|
+
<script type="module" src="templates.js"></script>
|
|
386
|
+
<script type="module" src="actions.js"></script>
|
|
387
|
+
</body>
|
|
388
|
+
</html>
|