@xingjisoft/neutrino 0.3.0 → 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.
- package/README.md +312 -464
- package/assets/pro/backend_output_model.txt +5 -0
- package/assets/pro/claude-module-prompt.txt +65 -0
- package/assets/pro/common.txt +9 -0
- package/assets/pro/confirm_model.txt +5 -0
- package/assets/pro/front_output_model.txt +9 -0
- package/assets/pro/genimage_model.txt +1 -0
- package/assets/pro/main_model.txt +5 -0
- package/assets/pro/model-template.json +376 -0
- package/assets/pro/modeling_model.txt +5 -0
- package/assets/pro/plan_model.txt +8 -0
- package/assets/pro/thinking_model.txt +3 -0
- package/dist/app.js +43 -7
- package/dist/bin.js +5 -2
- package/dist/browser.js +57 -0
- package/dist/config.js +170 -26
- package/dist/index.js +1 -1
- package/dist/llm/approval.js +6 -2
- package/dist/llm/client.js +197 -28
- package/dist/llm/subagent.js +37 -1
- package/dist/pro/agents.js +104 -0
- package/dist/pro/config.js +88 -0
- package/dist/pro/preflight.js +172 -0
- package/dist/screens/chat.js +14 -8
- package/dist/screens/modelSelect.js +15 -4
- package/dist/screens/settings.js +9 -7
- package/dist/screens/start.js +48 -15
- package/dist/ui.js +58 -0
- package/dist/web/hub.js +22 -4
- package/dist/web/server.js +279 -66
- package/dist/web/session.js +258 -22
- package/dist/web/settings.js +91 -24
- package/package.json +37 -37
- package/web/README.md +87 -13
- package/web/app.js +304 -14
- package/web/i18n.js +382 -345
- package/web/index.html +90 -14
- package/web/neutrino-pro.gif +0 -0
- package/web/neutrino.png +0 -0
- package/web/pro.js +184 -0
- package/web/settings.js +322 -247
- package/web/style.css +297 -0
package/web/style.css
CHANGED
|
@@ -137,6 +137,10 @@ svg {
|
|
|
137
137
|
display: none !important;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
.pro-only { display: none; }
|
|
141
|
+
.pro-mode .pro-only { display: block; }
|
|
142
|
+
.pro-mode .standard-only { display: none !important; }
|
|
143
|
+
|
|
140
144
|
#app {
|
|
141
145
|
display: flex;
|
|
142
146
|
width: 100%;
|
|
@@ -240,6 +244,120 @@ svg {
|
|
|
240
244
|
flex: none;
|
|
241
245
|
}
|
|
242
246
|
|
|
247
|
+
/* The orbit badge doubles as the switch to the Pro workspace. */
|
|
248
|
+
.brand-logo {
|
|
249
|
+
appearance: none;
|
|
250
|
+
padding: 0;
|
|
251
|
+
cursor: pointer;
|
|
252
|
+
transition: background var(--fast), border-color var(--fast), transform var(--fast);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.brand-logo:hover {
|
|
256
|
+
background: var(--surface-2);
|
|
257
|
+
border-color: var(--border-strong);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.brand-logo:active {
|
|
261
|
+
transform: scale(0.96);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.brand-logo:focus-visible {
|
|
265
|
+
outline: 2px solid var(--accent);
|
|
266
|
+
outline-offset: 2px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Pro mode replaces the orbit with the static Neutrino wordmark and drops the
|
|
270
|
+
button cue. The PNG is transparent, so it sits directly on the sidebar. */
|
|
271
|
+
.brand-logo.pro-logo {
|
|
272
|
+
/* Narrower than the animated mark was: the brand name grows to "Neutrino
|
|
273
|
+
Pro" in this workspace, and the extra 30px keeps the name on one line at
|
|
274
|
+
the default sidebar width without touching the action buttons. */
|
|
275
|
+
width: 86px;
|
|
276
|
+
height: 25.8px;
|
|
277
|
+
cursor: default;
|
|
278
|
+
overflow: hidden;
|
|
279
|
+
background: transparent;
|
|
280
|
+
border-color: transparent;
|
|
281
|
+
border-radius: 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.brand-logo.pro-logo:hover {
|
|
285
|
+
background: transparent;
|
|
286
|
+
border-color: transparent;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.brand-logo.pro-logo:active {
|
|
290
|
+
transform: none;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.brand-logo.pro-logo img {
|
|
294
|
+
display: block;
|
|
295
|
+
width: 100%;
|
|
296
|
+
height: 100%;
|
|
297
|
+
object-fit: contain;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* A dismissible hint under the brand; it never renders in Pro mode. It takes
|
|
301
|
+
its own row so it never covers the New conversation button, with the
|
|
302
|
+
triangle pointing back up at the badge. */
|
|
303
|
+
.pro-tip {
|
|
304
|
+
position: relative;
|
|
305
|
+
z-index: 20;
|
|
306
|
+
display: flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: 6px;
|
|
309
|
+
flex: none;
|
|
310
|
+
margin: 10px 12px 0;
|
|
311
|
+
padding: 8px 8px 8px 12px;
|
|
312
|
+
background: #2563eb;
|
|
313
|
+
color: #ffffff;
|
|
314
|
+
border-radius: 10px;
|
|
315
|
+
box-shadow: 0 10px 26px rgba(0, 0, 0, 0.42);
|
|
316
|
+
font-size: 12px;
|
|
317
|
+
line-height: 1.4;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.pro-tip::before {
|
|
321
|
+
content: "";
|
|
322
|
+
position: absolute;
|
|
323
|
+
top: -6px;
|
|
324
|
+
left: 16px;
|
|
325
|
+
width: 0;
|
|
326
|
+
height: 0;
|
|
327
|
+
border-right: 6px solid transparent;
|
|
328
|
+
border-bottom: 6px solid #2563eb;
|
|
329
|
+
border-left: 6px solid transparent;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.pro-tip span {
|
|
333
|
+
flex: 1;
|
|
334
|
+
min-width: 0;
|
|
335
|
+
overflow-wrap: anywhere;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.pro-tip-close {
|
|
339
|
+
display: grid;
|
|
340
|
+
place-items: center;
|
|
341
|
+
flex: none;
|
|
342
|
+
width: 20px;
|
|
343
|
+
height: 20px;
|
|
344
|
+
padding: 0;
|
|
345
|
+
background: transparent;
|
|
346
|
+
border: 0;
|
|
347
|
+
border-radius: 6px;
|
|
348
|
+
color: rgba(255, 255, 255, 0.82);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.pro-tip-close:hover {
|
|
352
|
+
background: rgba(255, 255, 255, 0.16);
|
|
353
|
+
color: #ffffff;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.pro-tip-close svg {
|
|
357
|
+
width: 12px;
|
|
358
|
+
height: 12px;
|
|
359
|
+
}
|
|
360
|
+
|
|
243
361
|
.icon-btn {
|
|
244
362
|
display: grid;
|
|
245
363
|
place-items: center;
|
|
@@ -516,6 +634,29 @@ svg {
|
|
|
516
634
|
gap: 6px;
|
|
517
635
|
}
|
|
518
636
|
|
|
637
|
+
/* Pro workspace only: a persistent way back to the regular console, pinned to
|
|
638
|
+
the far right of the main header. */
|
|
639
|
+
.pro-exit {
|
|
640
|
+
flex: none;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.pro-exit svg {
|
|
644
|
+
flex: none;
|
|
645
|
+
width: 14px;
|
|
646
|
+
height: 14px;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
@media (max-width: 560px) {
|
|
650
|
+
.pro-exit {
|
|
651
|
+
width: 30px;
|
|
652
|
+
padding: 0;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.pro-exit span {
|
|
656
|
+
display: none;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
519
660
|
.badge {
|
|
520
661
|
display: inline-flex;
|
|
521
662
|
align-items: center;
|
|
@@ -1287,6 +1428,113 @@ svg {
|
|
|
1287
1428
|
outline: none;
|
|
1288
1429
|
}
|
|
1289
1430
|
|
|
1431
|
+
.pro-mode .composer-card { flex-wrap: wrap; }
|
|
1432
|
+
.pro-mode .composer textarea { flex: 1 0 100%; }
|
|
1433
|
+
.pro-preset-control { position: relative; margin-left: auto; align-self: center; }
|
|
1434
|
+
.pro-preset-control > summary {
|
|
1435
|
+
display: flex; align-items: center; gap: 10px; padding: 7px 10px;
|
|
1436
|
+
border-radius: var(--radius-sm); color: var(--text-secondary); cursor: pointer;
|
|
1437
|
+
font-size: 12px; list-style: none; user-select: none;
|
|
1438
|
+
}
|
|
1439
|
+
.pro-preset-control > summary::-webkit-details-marker { display: none; }
|
|
1440
|
+
.pro-preset-chevron { width: 14px; height: 14px; flex: none; transition: transform var(--fast); }
|
|
1441
|
+
.pro-preset-control[open] .pro-preset-chevron { transform: rotate(180deg); }
|
|
1442
|
+
.pro-preset-control > summary:hover, .pro-preset-control[open] > summary { background: var(--surface-3); }
|
|
1443
|
+
.pro-preset-card {
|
|
1444
|
+
position: absolute; z-index: 30; right: 0; bottom: calc(100% + 12px);
|
|
1445
|
+
width: min(390px, calc(100vw - 48px)); max-height: min(560px, 65dvh); overflow-y: auto;
|
|
1446
|
+
padding: 18px; border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
|
|
1447
|
+
background: var(--surface-1); box-shadow: var(--shadow-strong);
|
|
1448
|
+
}
|
|
1449
|
+
.pro-preset-heading { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; font-size: 13px; }
|
|
1450
|
+
.pro-preset-heading strong { color: var(--accent); font-size: 14px; font-weight: 500; }
|
|
1451
|
+
.pro-slider-label { display: block; color: var(--text-tertiary); font-size: 11px; margin-bottom: 8px; }
|
|
1452
|
+
.pro-preset-slider { position: relative; height: 40px; --pro-slider-position: 0; }
|
|
1453
|
+
.pro-preset-slider.is-disabled { opacity: .5; }
|
|
1454
|
+
.pro-slider-track {
|
|
1455
|
+
position: absolute; top: 8px; right: 2px; left: 2px; height: 24px;
|
|
1456
|
+
border-radius: 999px; background: #454547; overflow: hidden; pointer-events: none;
|
|
1457
|
+
}
|
|
1458
|
+
.pro-slider-fill {
|
|
1459
|
+
width: calc(12px + (100% - 24px) * var(--pro-slider-position)); height: 100%; background: #347ff6;
|
|
1460
|
+
}
|
|
1461
|
+
.pro-slider-stops {
|
|
1462
|
+
position: absolute; top: 18px; right: 14px; left: 14px; height: 4px; pointer-events: none;
|
|
1463
|
+
}
|
|
1464
|
+
.pro-slider-stop {
|
|
1465
|
+
position: absolute; width: 4px; height: 4px; transform: translateX(-50%);
|
|
1466
|
+
border-radius: 50%; background: rgba(255, 255, 255, .18);
|
|
1467
|
+
}
|
|
1468
|
+
.pro-slider-stop.is-filled { background: rgba(255, 255, 255, .35); }
|
|
1469
|
+
#pro-preset-range {
|
|
1470
|
+
position: relative; display: block; width: 100%; height: 40px; margin: 0; padding: 0;
|
|
1471
|
+
-webkit-appearance: none; appearance: none; border: 0; border-radius: 999px; background: transparent; cursor: pointer;
|
|
1472
|
+
}
|
|
1473
|
+
#pro-preset-range::-webkit-slider-runnable-track { height: 24px; border: 0; background: transparent; }
|
|
1474
|
+
#pro-preset-range::-webkit-slider-thumb {
|
|
1475
|
+
-webkit-appearance: none; appearance: none; width: 28px; height: 28px; margin-top: -2px;
|
|
1476
|
+
border: 0; border-radius: 50%; background: #fff;
|
|
1477
|
+
}
|
|
1478
|
+
#pro-preset-range::-moz-range-track { height: 24px; border: 0; background: transparent; }
|
|
1479
|
+
#pro-preset-range::-moz-range-progress { background: transparent; }
|
|
1480
|
+
#pro-preset-range::-moz-range-thumb { width: 28px; height: 28px; border: 0; border-radius: 50%; background: #fff; }
|
|
1481
|
+
#pro-preset-range:focus-visible { outline-offset: 2px; }
|
|
1482
|
+
#pro-preset-range:disabled { cursor: default; }
|
|
1483
|
+
.pro-preset-ticks { position: relative; height: 24px; margin: 6px 14px 16px; }
|
|
1484
|
+
.pro-preset-ticks button {
|
|
1485
|
+
position: absolute; transform: translateX(-50%); border: 0; background: transparent;
|
|
1486
|
+
color: var(--text-caption); font-size: 11px; line-height: 16px; padding: 4px; white-space: nowrap; cursor: pointer;
|
|
1487
|
+
}
|
|
1488
|
+
.pro-preset-ticks button[aria-pressed="true"] { color: var(--accent); }
|
|
1489
|
+
.pro-preset-ticks button:disabled { cursor: default; }
|
|
1490
|
+
.pro-slider-meteors { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
|
|
1491
|
+
.pro-slider-meteor {
|
|
1492
|
+
position: absolute; top: 4px; left: -52px; width: 46px; height: 1.5px; opacity: 0;
|
|
1493
|
+
border-radius: 999px; background: linear-gradient(90deg, transparent, rgba(224, 222, 255, .7) 75%, #fff);
|
|
1494
|
+
animation: pro-slider-meteor 2.8s linear infinite; animation-play-state: paused;
|
|
1495
|
+
}
|
|
1496
|
+
.pro-slider-meteor::after {
|
|
1497
|
+
content: ""; position: absolute; top: 50%; right: -1px; width: 3px; height: 3px;
|
|
1498
|
+
transform: translateY(-50%); border-radius: 50%; background: #fff; box-shadow: 0 0 5px rgba(242, 232, 255, .8);
|
|
1499
|
+
}
|
|
1500
|
+
.pro-slider-meteor:nth-child(2) { top: 15px; width: 34px; animation-duration: 3.4s; animation-delay: -1.1s; }
|
|
1501
|
+
.pro-slider-meteor:nth-child(3) { top: 22px; width: 26px; animation-duration: 2.5s; animation-delay: -.45s; }
|
|
1502
|
+
.pro-slider-meteor:nth-child(4) { top: 8px; width: 20px; animation-duration: 4.2s; animation-delay: -2.3s; }
|
|
1503
|
+
.pro-preset-control.is-max .pro-slider-fill { background: linear-gradient(100deg, #347ff6 5%, #6075ff 50%, #a45af8); }
|
|
1504
|
+
.pro-preset-control.is-max .pro-slider-track { box-shadow: 0 0 14px rgba(132, 99, 255, .22); }
|
|
1505
|
+
.pro-preset-control.is-max .pro-slider-meteors { opacity: 1; }
|
|
1506
|
+
.pro-preset-control[open].is-max .pro-slider-meteor { animation-play-state: running; }
|
|
1507
|
+
.pro-preset-control.is-max .pro-preset-heading strong,
|
|
1508
|
+
.pro-preset-control.is-max .pro-preset-ticks button[aria-pressed="true"] { color: #bda8ff; }
|
|
1509
|
+
@keyframes pro-slider-meteor {
|
|
1510
|
+
0% { transform: translate3d(0, 8px, 0) rotate(-14deg); opacity: 0; }
|
|
1511
|
+
8% { opacity: .9; }
|
|
1512
|
+
55% { opacity: .65; }
|
|
1513
|
+
72%, 100% { transform: translate3d(450px, -8px, 0) rotate(-14deg); opacity: 0; }
|
|
1514
|
+
}
|
|
1515
|
+
.pro-model-details { border-top: 1px solid var(--border-soft); }
|
|
1516
|
+
.pro-model-details > summary {
|
|
1517
|
+
display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 0;
|
|
1518
|
+
color: var(--text-tertiary); font-size: 11.5px; list-style: none; cursor: pointer; user-select: none;
|
|
1519
|
+
}
|
|
1520
|
+
.pro-model-details > summary::-webkit-details-marker { display: none; }
|
|
1521
|
+
.pro-model-details > summary:hover { color: var(--text); }
|
|
1522
|
+
.pro-model-details-chevron { width: 14px; height: 14px; flex: none; color: var(--text-caption); transition: transform var(--fast); }
|
|
1523
|
+
.pro-model-details[open] .pro-model-details-chevron { transform: rotate(180deg); }
|
|
1524
|
+
.pro-preset-models { display: grid; gap: 9px; padding: 2px 0 12px; }
|
|
1525
|
+
.pro-model-row { display: grid; grid-template-columns: minmax(90px, .8fr) minmax(0, 1.6fr); gap: 12px; font-size: 11.5px; line-height: 1.5; }
|
|
1526
|
+
.pro-model-row > span:first-child { color: var(--text-tertiary); }
|
|
1527
|
+
.pro-model-row > span:last-child { overflow-wrap: anywhere; text-align: right; }
|
|
1528
|
+
.pro-model-row .pro-model-fallback { color: var(--amber); }
|
|
1529
|
+
.pro-preset-card .settings-note { margin-top: 15px; font-size: 11px; }
|
|
1530
|
+
.pro-preset-card .form-feedback:empty { display: none; }
|
|
1531
|
+
.pro-fallback-rows { display: grid; gap: 14px; margin-top: 18px; }
|
|
1532
|
+
.pro-fallback-row { display: grid; gap: 5px; padding-bottom: 14px; border-bottom: 1px solid var(--border-soft); overflow-wrap: anywhere; }
|
|
1533
|
+
.pro-fallback-row strong { font-size: 13px; font-weight: 500; }
|
|
1534
|
+
.pro-fallback-row > span { color: var(--amber); font-size: 12px; }
|
|
1535
|
+
.pro-fallback-row small { color: var(--text-tertiary); font-size: 11px; }
|
|
1536
|
+
.pro-fallback-dialog { max-width: 540px; }
|
|
1537
|
+
|
|
1290
1538
|
#send {
|
|
1291
1539
|
display: grid;
|
|
1292
1540
|
place-items: center;
|
|
@@ -2743,6 +2991,45 @@ select option {
|
|
|
2743
2991
|
background: transparent;
|
|
2744
2992
|
}
|
|
2745
2993
|
|
|
2994
|
+
/* --------------------------------------------------------------- pro curtain */
|
|
2995
|
+
|
|
2996
|
+
/* Set by the inline head bootstrap when a just-started switch is recorded. It
|
|
2997
|
+
covers /pro before the module runs, so there is no flash of the new page
|
|
2998
|
+
while the curtain is being rebuilt. The module removes it immediately. */
|
|
2999
|
+
html.pro-transitioning body::before {
|
|
3000
|
+
content: "";
|
|
3001
|
+
position: fixed;
|
|
3002
|
+
inset: 0;
|
|
3003
|
+
z-index: 299;
|
|
3004
|
+
background: #151515;
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
/* Full-screen cover used while switching to /pro. #151515 matches the GIF's
|
|
3008
|
+
own background, so the wordmark blends into the cover on first paint. */
|
|
3009
|
+
.pro-curtain {
|
|
3010
|
+
position: fixed;
|
|
3011
|
+
inset: 0;
|
|
3012
|
+
z-index: 300;
|
|
3013
|
+
display: flex;
|
|
3014
|
+
align-items: center;
|
|
3015
|
+
justify-content: center;
|
|
3016
|
+
background: #151515;
|
|
3017
|
+
opacity: 0;
|
|
3018
|
+
transition: opacity 0.35s ease;
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
.pro-curtain.pro-curtain-visible {
|
|
3022
|
+
opacity: 1;
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
.pro-curtain img {
|
|
3026
|
+
display: block;
|
|
3027
|
+
width: min(82vw, 900px);
|
|
3028
|
+
max-height: 60vh;
|
|
3029
|
+
height: auto;
|
|
3030
|
+
object-fit: contain;
|
|
3031
|
+
}
|
|
3032
|
+
|
|
2746
3033
|
/* -------------------------------------------------------------- animations */
|
|
2747
3034
|
|
|
2748
3035
|
@keyframes blink {
|
|
@@ -2781,6 +3068,7 @@ select option {
|
|
|
2781
3068
|
}
|
|
2782
3069
|
|
|
2783
3070
|
@media (prefers-reduced-motion: reduce) {
|
|
3071
|
+
.pro-slider-meteors { display: none; }
|
|
2784
3072
|
*,
|
|
2785
3073
|
*::before,
|
|
2786
3074
|
*::after {
|
|
@@ -2804,6 +3092,15 @@ select option {
|
|
|
2804
3092
|
}
|
|
2805
3093
|
}
|
|
2806
3094
|
|
|
3095
|
+
/* Pro's brand name is longer ("Neutrino Pro"). Keep the regular 288px sidebar
|
|
3096
|
+
down to phone width so the name stays on one line next to the narrower logo;
|
|
3097
|
+
the regular workspace keeps its more compact 264px pane. */
|
|
3098
|
+
@media (min-width: 761px) and (max-width: 1080px) {
|
|
3099
|
+
body.pro-mode #sidebar {
|
|
3100
|
+
width: 288px;
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
|
|
2807
3104
|
/* Phones use one full-width pane: the conversation list opens first. */
|
|
2808
3105
|
@media (max-width: 760px) {
|
|
2809
3106
|
#sidebar {
|