@xingjisoft/neutrino 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +312 -436
  2. package/assets/pro/backend_output_model.txt +5 -0
  3. package/assets/pro/claude-module-prompt.txt +65 -0
  4. package/assets/pro/common.txt +9 -0
  5. package/assets/pro/confirm_model.txt +5 -0
  6. package/assets/pro/front_output_model.txt +9 -0
  7. package/assets/pro/genimage_model.txt +1 -0
  8. package/assets/pro/main_model.txt +5 -0
  9. package/assets/pro/model-template.json +376 -0
  10. package/assets/pro/modeling_model.txt +5 -0
  11. package/assets/pro/plan_model.txt +8 -0
  12. package/assets/pro/thinking_model.txt +3 -0
  13. package/dist/app.js +43 -7
  14. package/dist/bin.js +5 -2
  15. package/dist/browser.js +57 -0
  16. package/dist/config.js +179 -26
  17. package/dist/index.js +1 -1
  18. package/dist/llm/approval.js +6 -2
  19. package/dist/llm/client.js +197 -28
  20. package/dist/llm/subagent.js +37 -1
  21. package/dist/pro/agents.js +104 -0
  22. package/dist/pro/config.js +88 -0
  23. package/dist/pro/preflight.js +172 -0
  24. package/dist/screens/chat.js +54 -38
  25. package/dist/screens/modelSelect.js +15 -4
  26. package/dist/screens/settings.js +9 -7
  27. package/dist/screens/start.js +48 -15
  28. package/dist/ui.js +58 -0
  29. package/dist/web/hub.js +31 -4
  30. package/dist/web/server.js +611 -50
  31. package/dist/web/session.js +320 -20
  32. package/dist/web/settings.js +117 -24
  33. package/package.json +37 -37
  34. package/web/README.md +158 -16
  35. package/web/app.js +1603 -128
  36. package/web/i18n.js +382 -0
  37. package/web/index.html +289 -37
  38. package/web/markdown.js +710 -0
  39. package/web/neutrino-pro.gif +0 -0
  40. package/web/neutrino.png +0 -0
  41. package/web/pro.js +184 -0
  42. package/web/settings.js +322 -193
  43. package/web/style.css +1378 -42
package/web/index.html CHANGED
@@ -5,6 +5,23 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, interactive-widget=resizes-content" />
6
6
  <meta name="color-scheme" content="dark" />
7
7
  <meta name="theme-color" content="#151517" />
8
+ <script>
9
+ // Switching to the Pro workspace navigates only once the #151515 curtain
10
+ // is opaque. Cover the page here, before the first paint, so a slow
11
+ // module load cannot flash the freshly loaded /pro page before app.js
12
+ // takes the curtain over. app.js removes the class; the timer is a
13
+ // safety net for when the module cannot run at all.
14
+ try {
15
+ var proPath = location.pathname === "/pro" || location.pathname.startsWith("/pro/");
16
+ var proStart = Number(sessionStorage.getItem("neutrino.pro.transition")) || 0;
17
+ if (proPath && proStart && Date.now() - proStart < 8000) {
18
+ document.documentElement.classList.add("pro-transitioning");
19
+ setTimeout(function () {
20
+ document.documentElement.classList.remove("pro-transitioning");
21
+ }, 8000);
22
+ }
23
+ } catch (error) { /* Storage may be blocked; the page still works. */ }
24
+ </script>
8
25
  <title>Neutrino</title>
9
26
  <link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f9fafb' stroke-width='1.7'%3E%3Cellipse cx='12' cy='12' rx='9.4' ry='3.8' transform='rotate(-30 12 12)'/%3E%3Ccircle cx='12' cy='12' r='3.1'/%3E%3C/svg%3E" />
10
27
  <link rel="stylesheet" href="style.css" />
@@ -13,51 +30,88 @@
13
30
  <div id="app">
14
31
  <aside id="sidebar">
15
32
  <header class="brand">
16
- <div class="logo" aria-hidden="true">
33
+ <button id="brand-logo" class="logo brand-logo" type="button" title="Switch to Pro mode" aria-label="Switch to Pro mode" data-i18n-title="Switch to Pro mode" data-i18n-aria-label="Switch to Pro mode">
17
34
  <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
18
35
  <ellipse cx="12" cy="12" rx="9.4" ry="3.8" transform="rotate(-30 12 12)" stroke="currentColor" stroke-width="1.7" />
19
36
  <circle cx="12" cy="12" r="3.1" stroke="currentColor" stroke-width="1.7" />
20
37
  </svg>
21
- </div>
38
+ </button>
22
39
  <div class="brand-text">
23
- <strong>Neutrino</strong>
40
+ <strong id="brand-name">Neutrino</strong>
24
41
  <span id="status" class="status">connecting…</span>
25
42
  </div>
26
43
  <div class="brand-actions">
27
- <button id="refresh" class="icon-btn" type="button" title="Refresh conversations" aria-label="Refresh conversations">
44
+ <button id="refresh" class="icon-btn" type="button" title="Refresh conversations" aria-label="Refresh conversations" data-i18n-title="Refresh conversations" data-i18n-aria-label="Refresh conversations">
28
45
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a9 9 0 1 1-2.64-6.36" /><path d="M21 3v6h-6" /></svg>
29
46
  </button>
30
- <button id="settings-open" class="icon-btn" type="button" title="Settings" aria-label="Settings">
47
+ <button id="settings-open" class="icon-btn" type="button" title="Settings" aria-label="Settings" data-i18n-title="Settings" data-i18n-aria-label="Settings">
31
48
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" /><circle cx="12" cy="12" r="3" /></svg>
32
49
  </button>
33
50
  </div>
34
51
  </header>
52
+ <div id="pro-tip" class="pro-tip hidden" role="note">
53
+ <span data-i18n="Click the badge to switch to Pro mode">Click the badge to switch to Pro mode</span>
54
+ <button id="pro-tip-close" class="pro-tip-close" type="button" title="Dismiss" aria-label="Dismiss" data-i18n-title="Dismiss" data-i18n-aria-label="Dismiss">
55
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
56
+ </button>
57
+ </div>
58
+
59
+ <div class="sidebar-tools">
60
+ <button id="new-chat" class="new-chat" type="button" title="New conversation" data-i18n-title="New conversation">
61
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14" /></svg>
62
+ <span data-i18n="New conversation">New conversation</span>
63
+ </button>
64
+ <button id="workspace-button" class="workspace-button" type="button" title="Working directory" data-i18n-title="Working directory">
65
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7.5A2.5 2.5 0 0 1 5.5 5H9l2 2.5h7.5A2.5 2.5 0 0 1 21 10v7a2.5 2.5 0 0 1-2.5 2.5h-13A2.5 2.5 0 0 1 3 17z" /></svg>
66
+ <span id="workspace-label" class="workspace-label" data-i18n="All directories">All directories</span>
67
+ <svg class="workspace-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 18 6-6-6-6" /></svg>
68
+ </button>
69
+ <button id="agents-open" class="workspace-button" type="button" title="Other agents" data-i18n-title="Other agents">
70
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 12a9 9 0 1 0 3-6.7" /><path d="M3 4v5h5" /><path d="M12 7v5l3 2" /></svg>
71
+ <span class="workspace-label" data-i18n="Other agents">Other agents</span>
72
+ <svg class="workspace-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 18 6-6-6-6" /></svg>
73
+ </button>
74
+ </div>
75
+
35
76
  <div id="sessions" class="sessions"></div>
36
77
  <footer class="sidebar-foot">
37
- <span>Local agent console</span>
78
+ <span class="foot-note" data-i18n="Local agent console">Local agent console</span>
79
+ <label class="language-picker" title="Interface language" data-i18n-title="Interface language">
80
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3c2.5 2.6 3.8 5.6 3.8 9S14.5 18.4 12 21c-2.5-2.6-3.8-5.6-3.8-9S9.5 5.6 12 3z" /></svg>
81
+ <select id="language-select" aria-label="Interface language" data-i18n-aria-label="Interface language">
82
+ <option value="en">English</option>
83
+ <option value="zh">简体中文</option>
84
+ </select>
85
+ </label>
38
86
  </footer>
39
87
  </aside>
40
88
 
41
89
  <main id="main">
42
90
  <header id="main-header" class="main-header">
43
- <button id="back-to-menu" class="icon-btn back-to-menu" type="button" title="Back to conversations" aria-label="Back to conversations" aria-controls="sidebar">
91
+ <button id="back-to-menu" class="icon-btn back-to-menu" type="button" title="Back to conversations" aria-label="Back to conversations" data-i18n-title="Back to conversations" data-i18n-aria-label="Back to conversations" aria-controls="sidebar">
44
92
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 5-7 7 7 7M5 12h14" /></svg>
45
93
  </button>
46
94
  <div class="main-title">
47
- <h1 id="session-title">Select a conversation</h1>
95
+ <h1 id="session-title" data-i18n="Select a conversation">Select a conversation</h1>
48
96
  <div id="session-sub" class="sub"></div>
49
97
  </div>
50
98
  <div id="controls" class="controls"></div>
99
+ <button id="pro-exit" class="control pro-exit hidden" type="button" title="Exit Pro mode" aria-label="Exit Pro mode" data-i18n-title="Exit Pro mode" data-i18n-aria-label="Exit Pro mode">
100
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 5-7 7 7 7M5 12h14" /></svg>
101
+ <span data-i18n="Exit Pro mode">Exit Pro mode</span>
102
+ </button>
51
103
  </header>
52
104
 
53
105
  <form id="model-picker" class="model-picker hidden" aria-label="Conversation model">
54
- <label>Provider<select id="model-provider"></select></label>
55
- <label>Model<select id="model-name"></select></label>
56
- <label>Thinking<select id="model-intensity"></select></label>
57
- <button id="model-apply" class="control" type="submit">Apply</button>
106
+ <label><span data-i18n="Provider">Provider</span><select id="model-provider"></select></label>
107
+ <label><span data-i18n="Model">Model</span><select id="model-name"></select></label>
108
+ <label><span data-i18n="Thinking">Thinking</span><select id="model-intensity"></select></label>
109
+ <button id="model-apply" class="control" type="submit" data-i18n="Apply">Apply</button>
58
110
  <p id="model-feedback" class="form-feedback" role="status" aria-live="polite"></p>
59
111
  </form>
60
112
 
113
+ <aside id="plan-card" class="plan-card hidden" aria-live="polite"></aside>
114
+
61
115
  <section id="messages" class="messages">
62
116
  <div class="empty">
63
117
  <span class="empty-mark" aria-hidden="true">
@@ -66,8 +120,9 @@
66
120
  <circle cx="12" cy="12" r="3.1" stroke="currentColor" stroke-width="1.7" />
67
121
  </svg>
68
122
  </span>
69
- <strong>No conversation open</strong>
70
- <span>Choose a conversation from the sidebar to view it.</span>
123
+ <strong data-i18n="No conversation open">No conversation open</strong>
124
+ <span data-i18n="Choose a conversation from the sidebar to view it.">Choose a conversation from the sidebar to view it.</span>
125
+ <button id="empty-new-chat" class="control primary" type="button" data-i18n="New conversation">New conversation</button>
71
126
  </div>
72
127
  </section>
73
128
 
@@ -76,12 +131,40 @@
76
131
  <footer id="composer" class="composer hidden">
77
132
  <div class="composer-inner">
78
133
  <div class="composer-card">
79
- <textarea id="input" rows="1" placeholder="Message Neutrino…" aria-label="Message"></textarea>
80
- <button id="send" class="primary" type="button" title="Send message" aria-label="Send message">
134
+ <textarea id="input" rows="1" placeholder="Message Neutrino…" aria-label="Message" data-i18n-placeholder="Message Neutrino…"></textarea>
135
+ <details id="pro-preset-control" class="pro-preset-control hidden">
136
+ <summary aria-label="Pro preset" data-i18n-aria-label="Pro preset"><span id="pro-preset-label">Pro</span><svg class="pro-preset-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m7 10 5 5 5-5" /></svg></summary>
137
+ <div class="pro-preset-card">
138
+ <div class="pro-preset-heading"><span data-i18n="Neutrino Pro">Neutrino Pro</span><strong id="pro-preset-name"></strong></div>
139
+ <label class="pro-slider-label" for="pro-preset-range" data-i18n="Preset">Preset</label>
140
+ <div id="pro-preset-slider" class="pro-preset-slider">
141
+ <div class="pro-slider-track" aria-hidden="true">
142
+ <div class="pro-slider-fill"></div>
143
+ <div class="pro-slider-meteors">
144
+ <span class="pro-slider-meteor"></span><span class="pro-slider-meteor"></span><span class="pro-slider-meteor"></span><span class="pro-slider-meteor"></span>
145
+ </div>
146
+ </div>
147
+ <div id="pro-slider-stops" class="pro-slider-stops" aria-hidden="true"></div>
148
+ <input id="pro-preset-range" type="range" min="0" max="0" step="1" value="0" aria-label="Pro preset" data-i18n-aria-label="Pro preset" />
149
+ </div>
150
+ <div id="pro-preset-ticks" class="pro-preset-ticks"></div>
151
+ <details class="pro-model-details" id="pro-model-details">
152
+ <summary><span data-i18n="Model details">Model details</span><svg class="pro-model-details-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m7 10 5 5 5-5" /></svg></summary>
153
+ <div id="pro-preset-models" class="pro-preset-models"></div>
154
+ </details>
155
+ <p id="pro-preset-note" class="settings-note"></p>
156
+ <p id="pro-preset-feedback" class="form-feedback error" role="status" aria-live="polite"></p>
157
+ </div>
158
+ </details>
159
+ <button id="send" class="primary" type="button" title="Send message" aria-label="Send message" data-i18n-title="Send message" data-i18n-aria-label="Send message">
81
160
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7" /></svg>
82
161
  </button>
83
162
  </div>
84
- <div class="composer-hint"><kbd>Enter</kbd> to send · <kbd>Shift</kbd> + <kbd>Enter</kbd> for a new line</div>
163
+ <div class="composer-hint">
164
+ <span><kbd>Enter</kbd> <span data-i18n="to send">to send</span></span>
165
+ <span class="hint-sep">·</span>
166
+ <span><kbd>Shift</kbd> + <kbd>Enter</kbd> <span data-i18n="for a new line">for a new line</span></span>
167
+ </div>
85
168
  </div>
86
169
  </footer>
87
170
  </main>
@@ -91,38 +174,207 @@
91
174
  <form id="settings-form">
92
175
  <header class="settings-header">
93
176
  <div>
94
- <h2 id="settings-title">Settings</h2>
95
- <p class="settings-sub">Models, approvals, and console access.</p>
177
+ <h2 id="settings-title" data-i18n="Settings">Settings</h2>
178
+ <p class="settings-sub" data-i18n="Models, approvals, and console access.">Models, approvals, and console access.</p>
96
179
  </div>
97
- <button id="settings-close" class="icon-btn" type="button" aria-label="Close settings">
180
+ <button id="settings-close" class="icon-btn" type="button" aria-label="Close settings" data-i18n-aria-label="Close settings">
98
181
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
99
182
  </button>
100
183
  </header>
101
184
  <div class="settings-fields">
102
- <h3>Defaults for new conversations</h3>
103
- <label>Provider<select id="default-provider"></select></label>
104
- <label>Model<select id="default-model"></select></label>
105
- <label>Thinking intensity<select id="default-intensity"></select></label>
106
- <h3>Conversation and approvals</h3>
107
- <label>Model context window (tokens)<input id="settings-context" type="number" min="1" max="9007199254740991" step="1" required /></label>
108
- <p id="settings-compress-note" class="settings-note">Auto-compress at 80% of this model's context window. Default: 1,000,000 tokens.</p>
109
- <label>Approval reviewer model<select id="settings-reviewer"></select></label>
110
- <label class="checkbox-label"><input id="settings-extreme" type="checkbox" /> Extreme-risk auto-approval (del class, 3 separate review rounds)</label>
111
- <label class="checkbox-label"><input id="settings-sound" type="checkbox" /> Sound alerts (turn finished, approval waiting)</label>
112
- <p class="settings-note">Safety determines automatic approval; task relevance only blocks unanimously confirmed, extreme mismatches. Delete-class automatic approval also requires this setting.</p>
113
- <h3>Web access</h3>
114
- <label>New Web password<input id="settings-password" type="password" autocomplete="new-password" maxlength="256" placeholder="Leave blank to keep current password" /></label>
115
- <label>Confirm password<input id="settings-password-confirm" type="password" autocomplete="new-password" maxlength="256" placeholder="Repeat new password" /></label>
116
- <p class="settings-note">The password is permanent and survives restarts. Default: 114514. Saving a new password signs out other browsers.</p>
185
+ <h3 data-i18n="Interface">Interface</h3>
186
+ <div class="settings-grid">
187
+ <label><span data-i18n="Language">Language</span>
188
+ <select id="settings-language">
189
+ <option value="en">English</option>
190
+ <option value="zh">简体中文</option>
191
+ </select>
192
+ </label>
193
+ <label><span data-i18n="Default approval mode">Default approval mode</span>
194
+ <select id="settings-approval">
195
+ <option value="request" data-i18n="Request Approval">Request Approval</option>
196
+ <option value="auto" data-i18n="Auto Approval">Auto Approval</option>
197
+ </select>
198
+ </label>
199
+ </div>
200
+ <label class="checkbox-label standard-only"><input id="settings-plan" type="checkbox" /> <span data-i18n="Plan-first turns">Plan-first turns</span></label>
201
+ <p class="settings-note standard-only" data-i18n="Split multi-step requests into a plan before answering.">Split multi-step requests into a plan before answering.</p>
202
+ <h3 class="standard-only" data-i18n="Defaults for new conversations">Defaults for new conversations</h3>
203
+ <div class="settings-grid standard-only">
204
+ <label><span data-i18n="Provider">Provider</span><select id="default-provider"></select></label>
205
+ <label><span data-i18n="Model">Model</span><select id="default-model"></select></label>
206
+ <label><span data-i18n="Thinking intensity">Thinking intensity</span><select id="default-intensity"></select></label>
207
+ </div>
208
+ <section id="settings-pro" class="hidden">
209
+ <h3 data-i18n="Pro orchestration">Pro orchestration</h3>
210
+ <div class="settings-grid">
211
+ <label><span data-i18n="Default Pro preset">Default Pro preset</span><select id="settings-pro-preset"></select></label>
212
+ <label><span data-i18n="Maximum delegation depth">Maximum delegation depth</span><input id="settings-pro-depth" type="number" min="1" max="100" step="1" value="10" /></label>
213
+ </div>
214
+ <p class="settings-note" data-i18n="Every Pro task is planned first. All roles share the regular provider configuration. Image generation is reserved.">Every Pro task is planned first. All roles share the regular provider configuration. Image generation is reserved.</p>
215
+ <p class="settings-note" data-i18n="Edit role models, intensity and context windows in ~/.neutrino/pro/model.json. Default delegation depth: 10.">Edit role models, intensity and context windows in ~/.neutrino/pro/model.json. Default delegation depth: 10.</p>
216
+ </section>
217
+ <h3 data-i18n="Conversation and approvals">Conversation and approvals</h3>
218
+ <label class="standard-only"><span data-i18n="Model context window (tokens)">Model context window (tokens)</span><input id="settings-context" type="number" min="1" max="9007199254740991" step="1" required /></label>
219
+ <p id="settings-compress-note" class="settings-note standard-only" data-i18n="Auto-compress at 80% of this model's context window. Default: 1,000,000 tokens.">Auto-compress at 80% of this model's context window. Default: 1,000,000 tokens.</p>
220
+ <label class="standard-only"><span data-i18n="Approval reviewer model">Approval reviewer model</span><select id="settings-reviewer"></select></label>
221
+ <label class="checkbox-label"><input id="settings-extreme" type="checkbox" /> <span data-i18n="Extreme-risk auto-approval (del class, 3 separate review rounds)">Extreme-risk auto-approval (del class, 3 separate review rounds)</span></label>
222
+ <label class="checkbox-label"><input id="settings-sound" type="checkbox" /> <span data-i18n="Sound alerts (turn finished, approval waiting)">Sound alerts (turn finished, approval waiting)</span></label>
223
+ <label class="checkbox-label"><input id="settings-web-console" type="checkbox" /> <span data-i18n="Start the Web console with the terminal">Start the Web console with the terminal</span></label>
224
+ <p class="settings-note" data-i18n="Safety determines automatic approval; task relevance only blocks unanimously confirmed, extreme mismatches. Delete-class automatic approval also requires this setting.">Safety determines automatic approval; task relevance only blocks unanimously confirmed, extreme mismatches. Delete-class automatic approval also requires this setting.</p>
225
+ <h3 data-i18n="Web access">Web access</h3>
226
+ <label class="checkbox-label"><input id="settings-web-lan" type="checkbox" /> <span data-i18n="Allow access from other devices (LAN, 0.0.0.0)">Allow access from other devices (LAN, 0.0.0.0)</span></label>
227
+ <p class="settings-note" data-i18n="Binds the Web console to 0.0.0.0 so other devices on your network can open it, like --lan. Takes effect immediately; turning it off returns the console to 127.0.0.1. Keep the Web password on: anyone who can reach this port can drive the agent.">Binds the Web console to 0.0.0.0 so other devices on your network can open it, like --lan. Takes effect immediately; turning it off returns the console to 127.0.0.1. Keep the Web password on: anyone who can reach this port can drive the agent.</p>
228
+ <div class="settings-grid">
229
+ <label><span data-i18n="New Web password">New Web password</span><input id="settings-password" type="password" autocomplete="new-password" maxlength="256" placeholder="Leave blank to keep current password" data-i18n-placeholder="Leave blank to keep current password" /></label>
230
+ <label><span data-i18n="Confirm password">Confirm password</span><input id="settings-password-confirm" type="password" autocomplete="new-password" maxlength="256" placeholder="Repeat new password" data-i18n-placeholder="Repeat new password" /></label>
231
+ </div>
232
+ <p class="settings-note" data-i18n="The password is permanent and survives restarts. Default: 114514. Saving a new password signs out other browsers.">The password is permanent and survives restarts. Default: 114514. Saving a new password signs out other browsers.</p>
117
233
  <p id="settings-feedback" class="form-feedback" role="status" aria-live="polite"></p>
118
234
  </div>
119
235
  <footer class="settings-actions">
120
- <button id="settings-cancel" class="control" type="button">Cancel</button>
121
- <button id="settings-save" class="primary" type="submit">Save changes</button>
236
+ <button id="settings-cancel" class="control" type="button" data-i18n="Cancel">Cancel</button>
237
+ <button id="settings-save" class="primary" type="submit" data-i18n="Save changes">Save changes</button>
238
+ </footer>
239
+ </form>
240
+ </dialog>
241
+
242
+ <dialog id="new-chat-dialog" class="sheet-dialog" aria-labelledby="new-chat-title">
243
+ <form id="new-chat-form" class="sheet">
244
+ <header class="sheet-header">
245
+ <div>
246
+ <h2 id="new-chat-title" data-i18n="New conversation">New conversation</h2>
247
+ <p class="sheet-sub standard-only" data-i18n="Choose a working directory and a model.">Choose a working directory and a model.</p>
248
+ <p class="sheet-sub pro-only" data-i18n="Choose a working directory and a professional team preset.">Choose a working directory and a professional team preset.</p>
249
+ </div>
250
+ <button id="new-chat-close" class="icon-btn" type="button" aria-label="Close" data-i18n-aria-label="Close">
251
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
252
+ </button>
253
+ </header>
254
+ <div class="sheet-body">
255
+ <section class="field-group">
256
+ <h3 data-i18n="Working directory">Working directory</h3>
257
+ <div class="path-row">
258
+ <input id="new-chat-cwd" class="path-input" type="text" spellcheck="false" autocomplete="off" placeholder="C:\path\to\project" aria-label="Working directory" data-i18n-aria-label="Working directory" />
259
+ <button id="new-chat-browse" class="control" type="button" data-i18n="Browse…">Browse…</button>
260
+ </div>
261
+ <p class="settings-note" data-i18n="This working directory is used for the conversation's tools.">This working directory is used for the conversation's tools.</p>
262
+ <h4 class="recent-title" data-i18n="Recent folders">Recent folders</h4>
263
+ <div id="new-chat-recents" class="workspace-recents"></div>
264
+ </section>
265
+ <section class="field-group">
266
+ <h3 class="standard-only" data-i18n="Model">Model</h3>
267
+ <div class="settings-grid standard-only">
268
+ <label><span data-i18n="Provider">Provider</span><select id="new-chat-provider"></select></label>
269
+ <label><span data-i18n="Model">Model</span><select id="new-chat-model"></select></label>
270
+ <label><span data-i18n="Thinking">Thinking</span><select id="new-chat-intensity"></select></label>
271
+ </div>
272
+ <label class="pro-only"><span data-i18n="Pro preset">Pro preset</span><select id="new-chat-pro-preset"></select></label>
273
+ <label><span data-i18n="Default approval mode">Default approval mode</span>
274
+ <select id="new-chat-approval">
275
+ <option value="request" data-i18n="Request Approval">Request Approval</option>
276
+ <option value="auto" data-i18n="Auto Approval">Auto Approval</option>
277
+ </select>
278
+ </label>
279
+ <p id="new-chat-note" class="settings-note standard-only"></p>
280
+ </section>
281
+ <p id="new-chat-feedback" class="form-feedback" role="status" aria-live="polite"></p>
282
+ </div>
283
+ <footer class="sheet-actions">
284
+ <button id="new-chat-cancel" class="control" type="button" data-i18n="Cancel">Cancel</button>
285
+ <button id="new-chat-start" class="primary" type="submit" data-i18n="Start conversation">Start conversation</button>
122
286
  </footer>
123
287
  </form>
124
288
  </dialog>
125
289
 
290
+ <dialog id="folder-dialog" class="sheet-dialog" aria-labelledby="folder-title">
291
+ <div class="sheet folder-sheet">
292
+ <header class="sheet-header">
293
+ <div>
294
+ <h2 id="folder-title" data-i18n="Open working directory">Open working directory</h2>
295
+ <p class="sheet-sub" data-i18n="Choose a folder to open as the working directory.">Choose a folder to open as the working directory.</p>
296
+ </div>
297
+ <button id="folder-close" class="icon-btn" type="button" aria-label="Close" data-i18n-aria-label="Close">
298
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
299
+ </button>
300
+ </header>
301
+ <div class="folder-toolbar">
302
+ <button id="folder-up" class="icon-btn" type="button" title="Up" aria-label="Up" data-i18n-title="Up" data-i18n-aria-label="Up">
303
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m18 15-6-6-6 6" /></svg>
304
+ </button>
305
+ <input id="folder-path" class="path-input" type="text" spellcheck="false" autocomplete="off" aria-label="Working directory" data-i18n-aria-label="Working directory" />
306
+ <button id="folder-go" class="control" type="button" data-i18n="Open">Open</button>
307
+ </div>
308
+ <div id="folder-roots" class="folder-roots"></div>
309
+ <div id="folder-list" class="folder-list" role="listbox" aria-label="Folders"></div>
310
+ <div id="folder-new" class="folder-new hidden">
311
+ <input id="folder-new-name" class="path-input" type="text" maxlength="255" placeholder="Folder name" aria-label="Folder name" data-i18n-placeholder="Folder name" data-i18n-aria-label="Folder name" />
312
+ <button id="folder-new-create" class="primary" type="button" data-i18n="Create">Create</button>
313
+ <button id="folder-new-cancel" class="control" type="button" data-i18n="Cancel">Cancel</button>
314
+ </div>
315
+ <p id="folder-feedback" class="form-feedback" role="status" aria-live="polite"></p>
316
+ <footer class="sheet-actions folder-actions">
317
+ <button id="folder-mkdir" class="control" type="button" data-i18n="New folder">New folder</button>
318
+ <span class="sheet-spacer"></span>
319
+ <button id="folder-cancel" class="control" type="button" data-i18n="Cancel">Cancel</button>
320
+ <button id="folder-use" class="primary" type="button" data-i18n="Use this folder">Use this folder</button>
321
+ </footer>
322
+ </div>
323
+ </dialog>
324
+
325
+ <dialog id="agents-dialog" class="sheet-dialog" aria-labelledby="agents-title">
326
+ <div class="sheet">
327
+ <header class="sheet-header">
328
+ <div>
329
+ <h2 id="agents-title" data-i18n="Other agents">Other agents</h2>
330
+ <p class="sheet-sub" data-i18n="Read-only sessions recorded by other coding agents in this working directory.">Read-only sessions recorded by other coding agents in this working directory.</p>
331
+ </div>
332
+ <button id="agents-close" class="icon-btn" type="button" aria-label="Close" data-i18n-aria-label="Close">
333
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
334
+ </button>
335
+ </header>
336
+ <div id="agents-list" class="agents-list"></div>
337
+ <p id="agents-feedback" class="form-feedback" role="status" aria-live="polite"></p>
338
+ <footer class="sheet-actions">
339
+ <span id="agents-cwd" class="agents-cwd"></span>
340
+ <span class="sheet-spacer"></span>
341
+ </footer>
342
+ </div>
343
+ </dialog>
344
+
345
+ <dialog id="workspace-dialog" class="sheet-dialog" aria-labelledby="workspace-title">
346
+ <div class="sheet">
347
+ <header class="sheet-header">
348
+ <div>
349
+ <h2 id="workspace-title" data-i18n="Working directories">Working directories</h2>
350
+ <p class="sheet-sub" data-i18n="Choose a working directory to browse and start conversations in.">Choose a working directory to browse and start conversations in.</p>
351
+ </div>
352
+ <button id="workspace-close" class="icon-btn" type="button" aria-label="Close" data-i18n-aria-label="Close">
353
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" /></svg>
354
+ </button>
355
+ </header>
356
+ <div id="workspace-list" class="workspace-list"></div>
357
+ <p id="workspace-feedback" class="form-feedback" role="status" aria-live="polite"></p>
358
+ <footer class="sheet-actions">
359
+ <button id="workspace-all" class="control" type="button" data-i18n="All directories">All directories</button>
360
+ <span class="sheet-spacer"></span>
361
+ <button id="workspace-add" class="primary" type="button" data-i18n="Open folder…">Open folder…</button>
362
+ </footer>
363
+ </div>
364
+ </dialog>
365
+
366
+ <dialog id="pro-fallback-dialog" class="sheet-dialog pro-fallback-dialog" aria-labelledby="pro-fallback-title">
367
+ <div class="sheet">
368
+ <header class="sheet-header"><h2 id="pro-fallback-title" data-i18n="Professional model availability">Professional model availability</h2></header>
369
+ <div class="sheet-body">
370
+ <p class="settings-note" data-i18n="These model substitutions apply only to this task in this conversation. Your preset configuration is unchanged.">These model substitutions apply only to this task in this conversation. Your preset configuration is unchanged.</p>
371
+ <div id="pro-fallback-rows" class="pro-fallback-rows"></div>
372
+ <p id="pro-fallback-error" class="form-feedback error hidden" role="alert"></p>
373
+ </div>
374
+ <footer class="sheet-actions"><button id="pro-fallback-close" class="primary" type="button" data-i18n="Got it">Got it</button></footer>
375
+ </div>
376
+ </dialog>
377
+
126
378
  <script src="app.js" type="module"></script>
127
379
  </body>
128
380
  </html>