@runcore-sh/runcore 0.4.0 → 0.5.1
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/dictionary.json +2 -2
- package/dist/activity/log.js +2 -2
- package/dist/activity/log.js.map +1 -1
- package/dist/agents/governed-spawn.d.ts.map +1 -1
- package/dist/cli.js +101 -11
- package/dist/cli.js.map +1 -1
- package/dist/extensions/cache.d.ts +57 -0
- package/dist/extensions/cache.d.ts.map +1 -0
- package/dist/extensions/cache.js +173 -0
- package/dist/extensions/cache.js.map +1 -0
- package/dist/extensions/client.d.ts +55 -0
- package/dist/extensions/client.d.ts.map +1 -0
- package/dist/extensions/client.js +120 -0
- package/dist/extensions/client.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +50 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +166 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/manifest.d.ts +38 -0
- package/dist/extensions/manifest.d.ts.map +1 -0
- package/dist/extensions/manifest.js +17 -0
- package/dist/extensions/manifest.js.map +1 -0
- package/dist/extensions/stubs.d.ts +27 -0
- package/dist/extensions/stubs.d.ts.map +1 -0
- package/dist/extensions/stubs.js +45 -0
- package/dist/extensions/stubs.js.map +1 -0
- package/dist/lib/audit.js +2 -2
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/brain-migrate.d.ts +21 -0
- package/dist/lib/brain-migrate.d.ts.map +1 -0
- package/dist/lib/brain-migrate.js +137 -0
- package/dist/lib/brain-migrate.js.map +1 -0
- package/dist/lib/paths.d.ts +27 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +65 -0
- package/dist/lib/paths.js.map +1 -1
- package/dist/llm/call-log.d.ts +40 -0
- package/dist/llm/call-log.d.ts.map +1 -0
- package/dist/llm/call-log.js +35 -0
- package/dist/llm/call-log.js.map +1 -0
- package/dist/llm/complete.d.ts +6 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +27 -0
- package/dist/llm/complete.js.map +1 -1
- package/dist/mcp-server.js +118 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/memory/file-backed.d.ts +4 -0
- package/dist/memory/file-backed.d.ts.map +1 -1
- package/dist/memory/file-backed.js +4 -0
- package/dist/memory/file-backed.js.map +1 -1
- package/dist/memory/vector-index.d.ts +4 -12
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +11 -93
- package/dist/memory/vector-index.js.map +1 -1
- package/dist/search/brain-docs.d.ts +17 -7
- package/dist/search/brain-docs.d.ts.map +1 -1
- package/dist/search/brain-docs.js +170 -52
- package/dist/search/brain-docs.js.map +1 -1
- package/dist/search/brain-rag.d.ts +45 -0
- package/dist/search/brain-rag.d.ts.map +1 -0
- package/dist/search/brain-rag.js +275 -0
- package/dist/search/brain-rag.js.map +1 -0
- package/dist/search/chunker.d.ts +24 -0
- package/dist/search/chunker.d.ts.map +1 -0
- package/dist/search/chunker.js +95 -0
- package/dist/search/chunker.js.map +1 -0
- package/dist/search/embedder.d.ts +16 -0
- package/dist/search/embedder.d.ts.map +1 -0
- package/dist/search/embedder.js +108 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/file-watcher.d.ts +11 -0
- package/dist/search/file-watcher.d.ts.map +1 -0
- package/dist/search/file-watcher.js +86 -0
- package/dist/search/file-watcher.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +814 -472
- package/dist/server.js.map +1 -1
- package/dist/sessions/store.d.ts +9 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +78 -2
- package/dist/settings.js.map +1 -1
- package/dist/tracing/init.d.ts +1 -1
- package/dist/tracing/init.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/module-tiers.json +164 -0
- package/package.json +9 -13
- package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
- package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
- package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
- package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
- package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
- package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
- package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
- package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
- package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
- package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
- package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
- package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
- package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
- package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
- package/public/index.html +379 -59
- package/dist/agents/autonomous.js +0 -749
- package/dist/agents/autonomous.js.map +0 -1
- package/dist/agents/commit.js +0 -113
- package/dist/agents/commit.js.map +0 -1
- package/dist/agents/continue.js +0 -158
- package/dist/agents/continue.js.map +0 -1
- package/dist/agents/cooldown.js +0 -397
- package/dist/agents/cooldown.js.map +0 -1
- package/dist/agents/dedup-guard.js +0 -131
- package/dist/agents/dedup-guard.js.map +0 -1
- package/dist/agents/feed.js +0 -176
- package/dist/agents/feed.js.map +0 -1
- package/dist/agents/governance.js +0 -292
- package/dist/agents/governance.js.map +0 -1
- package/dist/agents/governed-spawn.js +0 -192
- package/dist/agents/governed-spawn.js.map +0 -1
- package/dist/agents/heartbeat.js +0 -324
- package/dist/agents/heartbeat.js.map +0 -1
- package/dist/agents/instance-manager.js +0 -850
- package/dist/agents/instance-manager.js.map +0 -1
- package/dist/agents/issue-reporter.js +0 -123
- package/dist/agents/issue-reporter.js.map +0 -1
- package/dist/agents/issues.js +0 -141
- package/dist/agents/issues.js.map +0 -1
- package/dist/agents/locks.js +0 -234
- package/dist/agents/locks.js.map +0 -1
- package/dist/agents/memory.js +0 -93
- package/dist/agents/memory.js.map +0 -1
- package/dist/agents/monitor.js +0 -235
- package/dist/agents/monitor.js.map +0 -1
- package/dist/agents/orchestration.js +0 -715
- package/dist/agents/orchestration.js.map +0 -1
- package/dist/agents/recover.js +0 -166
- package/dist/agents/recover.js.map +0 -1
- package/dist/agents/reflection.js +0 -199
- package/dist/agents/reflection.js.map +0 -1
- package/dist/agents/runtime/bus.js +0 -174
- package/dist/agents/runtime/bus.js.map +0 -1
- package/dist/agents/runtime/config.js +0 -101
- package/dist/agents/runtime/config.js.map +0 -1
- package/dist/agents/runtime/driver.js +0 -214
- package/dist/agents/runtime/driver.js.map +0 -1
- package/dist/agents/runtime/errors.js +0 -40
- package/dist/agents/runtime/errors.js.map +0 -1
- package/dist/agents/runtime/index.js +0 -54
- package/dist/agents/runtime/index.js.map +0 -1
- package/dist/agents/runtime/lifecycle.js +0 -116
- package/dist/agents/runtime/lifecycle.js.map +0 -1
- package/dist/agents/runtime/manager.js +0 -948
- package/dist/agents/runtime/manager.js.map +0 -1
- package/dist/agents/runtime/registry.js +0 -195
- package/dist/agents/runtime/registry.js.map +0 -1
- package/dist/agents/runtime/resources.js +0 -146
- package/dist/agents/runtime/resources.js.map +0 -1
- package/dist/agents/runtime/types.js +0 -24
- package/dist/agents/runtime/types.js.map +0 -1
- package/dist/agents/spawn-policy.js +0 -202
- package/dist/agents/spawn-policy.js.map +0 -1
- package/dist/agents/spawn.js +0 -970
- package/dist/agents/spawn.js.map +0 -1
- package/dist/agents/triage.js +0 -81
- package/dist/agents/triage.js.map +0 -1
- package/dist/agents/workflow.js +0 -543
- package/dist/agents/workflow.js.map +0 -1
- package/dist/avatar/client.js +0 -172
- package/dist/avatar/client.js.map +0 -1
- package/dist/avatar/sidecar.js +0 -125
- package/dist/avatar/sidecar.js.map +0 -1
- package/dist/browser/sessions.js +0 -122
- package/dist/browser/sessions.js.map +0 -1
- package/dist/capabilities/definitions/browser.js +0 -242
- package/dist/capabilities/definitions/browser.js.map +0 -1
- package/dist/channels/whatsapp.js +0 -200
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/credentials/store.js +0 -189
- package/dist/credentials/store.js.map +0 -1
- package/dist/files/deep-index.js +0 -337
- package/dist/files/deep-index.js.map +0 -1
- package/dist/files/extract.js +0 -33
- package/dist/files/extract.js.map +0 -1
- package/dist/files/gdrive.js +0 -246
- package/dist/files/gdrive.js.map +0 -1
- package/dist/github/client.js +0 -408
- package/dist/github/client.js.map +0 -1
- package/dist/github/commit-analysis.js +0 -276
- package/dist/github/commit-analysis.js.map +0 -1
- package/dist/github/contributor-stats.js +0 -119
- package/dist/github/contributor-stats.js.map +0 -1
- package/dist/github/issue-sla.js +0 -220
- package/dist/github/issue-sla.js.map +0 -1
- package/dist/github/issue-triage.js +0 -286
- package/dist/github/issue-triage.js.map +0 -1
- package/dist/github/pr-readiness.js +0 -197
- package/dist/github/pr-readiness.js.map +0 -1
- package/dist/github/pr-review.js +0 -410
- package/dist/github/pr-review.js.map +0 -1
- package/dist/github/release-notes.js +0 -227
- package/dist/github/release-notes.js.map +0 -1
- package/dist/github/repo-health.js +0 -303
- package/dist/github/repo-health.js.map +0 -1
- package/dist/github/retry.js +0 -117
- package/dist/github/retry.js.map +0 -1
- package/dist/github/types.js +0 -8
- package/dist/github/types.js.map +0 -1
- package/dist/github/webhooks.js +0 -153
- package/dist/github/webhooks.js.map +0 -1
- package/dist/google/auth.js +0 -325
- package/dist/google/auth.js.map +0 -1
- package/dist/google/calendar-timer.js +0 -91
- package/dist/google/calendar-timer.js.map +0 -1
- package/dist/google/calendar.js +0 -270
- package/dist/google/calendar.js.map +0 -1
- package/dist/google/docs.js +0 -309
- package/dist/google/docs.js.map +0 -1
- package/dist/google/gmail-send.js +0 -219
- package/dist/google/gmail-send.js.map +0 -1
- package/dist/google/gmail-timer.js +0 -223
- package/dist/google/gmail-timer.js.map +0 -1
- package/dist/google/gmail.js +0 -470
- package/dist/google/gmail.js.map +0 -1
- package/dist/google/plugin.js +0 -169
- package/dist/google/plugin.js.map +0 -1
- package/dist/google/tasks-timer.js +0 -107
- package/dist/google/tasks-timer.js.map +0 -1
- package/dist/google/tasks.js +0 -331
- package/dist/google/tasks.js.map +0 -1
- package/dist/google/temporal.js +0 -176
- package/dist/google/temporal.js.map +0 -1
- package/dist/integrations/gate.js +0 -100
- package/dist/integrations/gate.js.map +0 -1
- package/dist/integrations/github.js +0 -331
- package/dist/integrations/github.js.map +0 -1
- package/dist/integrations/google-tasks.js +0 -432
- package/dist/integrations/google-tasks.js.map +0 -1
- package/dist/mdns.js +0 -110
- package/dist/mdns.js.map +0 -1
- package/dist/notifications/channel.js +0 -83
- package/dist/notifications/channel.js.map +0 -1
- package/dist/notifications/channels/adapter.js +0 -55
- package/dist/notifications/channels/adapter.js.map +0 -1
- package/dist/notifications/channels/index.js +0 -6
- package/dist/notifications/channels/index.js.map +0 -1
- package/dist/notifications/channels/log.js +0 -29
- package/dist/notifications/channels/log.js.map +0 -1
- package/dist/notifications/email.js +0 -72
- package/dist/notifications/email.js.map +0 -1
- package/dist/notifications/engine.js +0 -198
- package/dist/notifications/engine.js.map +0 -1
- package/dist/notifications/index.js +0 -24
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/phone.js +0 -48
- package/dist/notifications/phone.js.map +0 -1
- package/dist/notifications/sms.js +0 -65
- package/dist/notifications/sms.js.map +0 -1
- package/dist/notifications/types.js +0 -14
- package/dist/notifications/types.js.map +0 -1
- package/dist/notifications/webhook.js +0 -65
- package/dist/notifications/webhook.js.map +0 -1
- package/dist/resend/inbox.js +0 -199
- package/dist/resend/inbox.js.map +0 -1
- package/dist/resend/webhooks.js +0 -244
- package/dist/resend/webhooks.js.map +0 -1
- package/dist/search/browse.js +0 -225
- package/dist/search/browse.js.map +0 -1
- package/dist/search/perplexity.js +0 -41
- package/dist/search/perplexity.js.map +0 -1
- package/dist/slack/channels.js +0 -277
- package/dist/slack/channels.js.map +0 -1
- package/dist/slack/client.js +0 -468
- package/dist/slack/client.js.map +0 -1
- package/dist/slack/retry.js +0 -100
- package/dist/slack/retry.js.map +0 -1
- package/dist/slack/types.js +0 -52
- package/dist/slack/types.js.map +0 -1
- package/dist/slack/webhooks.js +0 -285
- package/dist/slack/webhooks.js.map +0 -1
- package/dist/stt/client.js +0 -66
- package/dist/stt/client.js.map +0 -1
- package/dist/stt/sidecar.js +0 -115
- package/dist/stt/sidecar.js.map +0 -1
- package/dist/tracing/bridge.js +0 -70
- package/dist/tracing/bridge.js.map +0 -1
- package/dist/tracing/correlation.js +0 -49
- package/dist/tracing/correlation.js.map +0 -1
- package/dist/tracing/index.js +0 -18
- package/dist/tracing/index.js.map +0 -1
- package/dist/tracing/init.js +0 -81
- package/dist/tracing/init.js.map +0 -1
- package/dist/tracing/instrument.js +0 -145
- package/dist/tracing/instrument.js.map +0 -1
- package/dist/tracing/middleware.js +0 -69
- package/dist/tracing/middleware.js.map +0 -1
- package/dist/tracing/tracer.js +0 -327
- package/dist/tracing/tracer.js.map +0 -1
- package/dist/tts/client.js +0 -48
- package/dist/tts/client.js.map +0 -1
- package/dist/tts/sidecar.js +0 -148
- package/dist/tts/sidecar.js.map +0 -1
- package/dist/twilio/call.js +0 -79
- package/dist/twilio/call.js.map +0 -1
- package/dist/vault/matcher.js +0 -197
- package/dist/vault/matcher.js.map +0 -1
- package/dist/vault/personal.js +0 -163
- package/dist/vault/personal.js.map +0 -1
- package/dist/vault/policy.js +0 -159
- package/dist/vault/policy.js.map +0 -1
- package/dist/vault/store.js +0 -122
- package/dist/vault/store.js.map +0 -1
- package/dist/vault/transfer.js +0 -188
- package/dist/vault/transfer.js.map +0 -1
- package/dist/volumes/index.js +0 -2
- package/dist/volumes/index.js.map +0 -1
- package/dist/volumes/manager.js +0 -462
- package/dist/volumes/manager.js.map +0 -1
- package/dist/volumes/types.js +0 -8
- package/dist/volumes/types.js.map +0 -1
- package/dist/webhooks/config.js +0 -214
- package/dist/webhooks/config.js.map +0 -1
- package/dist/webhooks/event-log.js +0 -132
- package/dist/webhooks/event-log.js.map +0 -1
- package/dist/webhooks/handler.js +0 -103
- package/dist/webhooks/handler.js.map +0 -1
- package/dist/webhooks/handlers.js +0 -231
- package/dist/webhooks/handlers.js.map +0 -1
- package/dist/webhooks/index.js +0 -33
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/mount.js +0 -400
- package/dist/webhooks/mount.js.map +0 -1
- package/dist/webhooks/registry.js +0 -143
- package/dist/webhooks/registry.js.map +0 -1
- package/dist/webhooks/relay.js +0 -53
- package/dist/webhooks/relay.js.map +0 -1
- package/dist/webhooks/retry.js +0 -270
- package/dist/webhooks/retry.js.map +0 -1
- package/dist/webhooks/router.js +0 -290
- package/dist/webhooks/router.js.map +0 -1
- package/dist/webhooks/twilio.js +0 -129
- package/dist/webhooks/twilio.js.map +0 -1
- package/dist/webhooks/types.js +0 -8
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/verify.js +0 -154
- package/dist/webhooks/verify.js.map +0 -1
package/public/index.html
CHANGED
|
@@ -28,6 +28,36 @@
|
|
|
28
28
|
--max-width: 720px;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/* Light theme */
|
|
32
|
+
[data-theme="light"] {
|
|
33
|
+
--bg: #ffffff;
|
|
34
|
+
--surface: #f5f5f5;
|
|
35
|
+
--border: #e0e0e0;
|
|
36
|
+
--text: #1a1a1a;
|
|
37
|
+
--text-dim: #666666;
|
|
38
|
+
--accent: #6c5ce7;
|
|
39
|
+
--accent-dim: #4a3fb0;
|
|
40
|
+
--error: #dc2626;
|
|
41
|
+
--user-bg: #eef0ff;
|
|
42
|
+
--assistant-bg: #f5f5f5;
|
|
43
|
+
}
|
|
44
|
+
[data-theme="light"] body { background: var(--bg); color: var(--text); }
|
|
45
|
+
[data-theme="light"] .chat-header { background: var(--surface); border-color: var(--border); }
|
|
46
|
+
[data-theme="light"] .card { background: var(--surface); border-color: var(--border); }
|
|
47
|
+
[data-theme="light"] .card input { background: var(--bg); border-color: var(--border); color: var(--text); }
|
|
48
|
+
[data-theme="light"] .composer { border-color: var(--border); background: var(--surface); }
|
|
49
|
+
[data-theme="light"] .composer textarea { background: var(--bg); color: var(--text); border-color: var(--border); }
|
|
50
|
+
[data-theme="light"] .message.user { background: var(--user-bg); }
|
|
51
|
+
[data-theme="light"] .message.assistant { background: var(--assistant-bg); }
|
|
52
|
+
[data-theme="light"] .content-sidebar { background: var(--surface); border-color: var(--border); }
|
|
53
|
+
[data-theme="light"] .thread-item { border-color: var(--border); }
|
|
54
|
+
[data-theme="light"] .thread-item:hover { background: rgba(108,92,231,0.06); }
|
|
55
|
+
[data-theme="light"] .vault-panel { background: var(--surface); border-color: var(--border); }
|
|
56
|
+
[data-theme="light"] .vault-panel input, [data-theme="light"] .vault-panel select { background: var(--bg); color: var(--text); border-color: var(--border); }
|
|
57
|
+
[data-theme="light"] .lane-node { border-color: var(--bg); }
|
|
58
|
+
[data-theme="light"] code { background: #e8e8e8; color: #333; }
|
|
59
|
+
[data-theme="light"] pre { background: #f0f0f0; }
|
|
60
|
+
|
|
31
61
|
body {
|
|
32
62
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
33
63
|
background: var(--bg);
|
|
@@ -260,48 +290,66 @@
|
|
|
260
290
|
}
|
|
261
291
|
|
|
262
292
|
.message {
|
|
263
|
-
padding: 12px 20px 12px
|
|
293
|
+
padding: 12px 20px 12px 76px;
|
|
264
294
|
max-width: var(--max-width);
|
|
265
295
|
margin: 0 auto;
|
|
266
296
|
width: 100%;
|
|
267
297
|
position: relative;
|
|
268
|
-
overflow:
|
|
298
|
+
overflow: visible;
|
|
269
299
|
}
|
|
270
300
|
|
|
271
|
-
/* ---
|
|
272
|
-
.drift-
|
|
301
|
+
/* --- Conversation graph (git-style branch visualization) --- */
|
|
302
|
+
.drift-graph {
|
|
273
303
|
position: absolute;
|
|
274
|
-
left:
|
|
275
|
-
top:
|
|
276
|
-
bottom:
|
|
277
|
-
width:
|
|
278
|
-
|
|
304
|
+
left: 0;
|
|
305
|
+
top: 0;
|
|
306
|
+
bottom: 0;
|
|
307
|
+
width: 68px;
|
|
308
|
+
pointer-events: none;
|
|
279
309
|
z-index: 0;
|
|
280
310
|
}
|
|
281
|
-
.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
311
|
+
.lane-line {
|
|
312
|
+
position: absolute;
|
|
313
|
+
top: 0;
|
|
314
|
+
bottom: 0;
|
|
315
|
+
width: 2px;
|
|
316
|
+
opacity: 0.5;
|
|
317
|
+
border-radius: 1px;
|
|
318
|
+
}
|
|
319
|
+
.lane-line.active-lane { opacity: 0.8; }
|
|
320
|
+
.lane-node {
|
|
287
321
|
position: absolute;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
height: 9px;
|
|
322
|
+
top: 14px;
|
|
323
|
+
width: 10px;
|
|
324
|
+
height: 10px;
|
|
292
325
|
border-radius: 50%;
|
|
293
326
|
border: 2px solid var(--bg);
|
|
294
|
-
|
|
327
|
+
z-index: 2;
|
|
328
|
+
transform: translateX(-4px);
|
|
295
329
|
}
|
|
296
|
-
.
|
|
330
|
+
.lane-svg {
|
|
297
331
|
position: absolute;
|
|
298
|
-
top:
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
332
|
+
top: 0;
|
|
333
|
+
left: 0;
|
|
334
|
+
width: 68px;
|
|
335
|
+
height: 40px;
|
|
336
|
+
overflow: visible;
|
|
337
|
+
z-index: 1;
|
|
338
|
+
}
|
|
339
|
+
.drift-label {
|
|
340
|
+
position: absolute;
|
|
341
|
+
left: 68px;
|
|
342
|
+
top: 2px;
|
|
343
|
+
font-size: 9px;
|
|
344
|
+
font-family: "SF Mono", "Cascadia Code", "Consolas", monospace;
|
|
345
|
+
color: var(--text-dim);
|
|
346
|
+
opacity: 0.6;
|
|
347
|
+
white-space: nowrap;
|
|
348
|
+
pointer-events: none;
|
|
349
|
+
max-width: 80px;
|
|
350
|
+
overflow: hidden;
|
|
351
|
+
text-overflow: ellipsis;
|
|
302
352
|
}
|
|
303
|
-
/* Connector from previous position to current */
|
|
304
|
-
.drift-line[data-drift="0"] .drift-connector { display: none; }
|
|
305
353
|
|
|
306
354
|
/* Continuity score badge */
|
|
307
355
|
.continuity-badge {
|
|
@@ -2286,7 +2334,23 @@
|
|
|
2286
2334
|
font-size: 11px;
|
|
2287
2335
|
color: var(--text-dim);
|
|
2288
2336
|
margin-top: 2px;
|
|
2337
|
+
display: flex;
|
|
2338
|
+
align-items: center;
|
|
2339
|
+
gap: 6px;
|
|
2340
|
+
}
|
|
2341
|
+
.thread-delete-btn {
|
|
2342
|
+
background: none;
|
|
2343
|
+
border: none;
|
|
2344
|
+
color: var(--text-dim);
|
|
2345
|
+
cursor: pointer;
|
|
2346
|
+
font-size: 14px;
|
|
2347
|
+
padding: 0 2px;
|
|
2348
|
+
margin-left: auto;
|
|
2349
|
+
opacity: 0;
|
|
2350
|
+
transition: opacity 0.15s, color 0.15s;
|
|
2289
2351
|
}
|
|
2352
|
+
.thread-item:hover .thread-delete-btn { opacity: 0.7; }
|
|
2353
|
+
.thread-delete-btn:hover { color: var(--error); opacity: 1 !important; }
|
|
2290
2354
|
|
|
2291
2355
|
.thread-toggle-btn {
|
|
2292
2356
|
width: 32px;
|
|
@@ -2443,9 +2507,11 @@
|
|
|
2443
2507
|
.content-sidebar.collapsed { width: 0; display: none; }
|
|
2444
2508
|
|
|
2445
2509
|
/* Messages: tighter padding */
|
|
2446
|
-
.message { padding: 10px 12px; }
|
|
2510
|
+
.message { padding: 10px 12px 10px 56px; }
|
|
2447
2511
|
.message .content { font-size: 14px; }
|
|
2448
2512
|
.message .role { font-size: 10px; }
|
|
2513
|
+
.drift-graph { width: 48px; }
|
|
2514
|
+
.drift-label { left: 48px; display: none; }
|
|
2449
2515
|
|
|
2450
2516
|
/* Composer: stack on small screens */
|
|
2451
2517
|
.composer { padding: 8px 10px; }
|
|
@@ -2610,11 +2676,12 @@
|
|
|
2610
2676
|
<nav class="header-nav" id="header-nav">
|
|
2611
2677
|
<a href="/" class="active">Chat</a>
|
|
2612
2678
|
</nav>
|
|
2613
|
-
<button class="thread-toggle-btn" id="thread-toggle-btn" title="Toggle
|
|
2614
|
-
<span class="thread-current-label" id="thread-current-label" title="Click to toggle
|
|
2679
|
+
<button class="thread-toggle-btn" id="thread-toggle-btn" title="Toggle chats">☰</button>
|
|
2680
|
+
<span class="thread-current-label" id="thread-current-label" title="Click to toggle chats"></span>
|
|
2615
2681
|
<span class="spacer"></span>
|
|
2616
2682
|
<button class="gear-btn" id="mobile-pair-btn" onclick="openMobileModal()" title="Go Mobile"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg></button>
|
|
2617
2683
|
<button class="gear-btn" id="share-btn" onclick="nativeShare()" title="Share"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg></button>
|
|
2684
|
+
<button class="gear-btn" id="theme-toggle-btn" title="Toggle theme"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg></button>
|
|
2618
2685
|
<button class="gear-btn" id="vault-open-btn" title="Settings">⚙</button>
|
|
2619
2686
|
<span class="tab-badge" id="activity-badge" style="display:none;"></span>
|
|
2620
2687
|
</div>
|
|
@@ -2624,13 +2691,13 @@
|
|
|
2624
2691
|
<input type="text" id="sidebar-search" placeholder="Search..." />
|
|
2625
2692
|
</div>
|
|
2626
2693
|
<div class="sidebar-tabs">
|
|
2627
|
-
<button class="sidebar-tab active" data-tab="threads">
|
|
2694
|
+
<button class="sidebar-tab active" data-tab="threads">Chats</button>
|
|
2628
2695
|
<button class="sidebar-tab" data-tab="files">Files</button>
|
|
2629
2696
|
</div>
|
|
2630
|
-
<!--
|
|
2697
|
+
<!-- Chats tab -->
|
|
2631
2698
|
<div class="sidebar-tab-content active" id="sidebar-threads">
|
|
2632
2699
|
<div class="thread-sidebar-header">
|
|
2633
|
-
<button class="thread-new-btn" id="thread-new-btn">+ New</button>
|
|
2700
|
+
<button class="thread-new-btn" id="thread-new-btn">+ New chat</button>
|
|
2634
2701
|
</div>
|
|
2635
2702
|
<div class="thread-list" id="thread-list"></div>
|
|
2636
2703
|
</div>
|
|
@@ -3210,7 +3277,7 @@
|
|
|
3210
3277
|
// Add "Main chat" as the default option
|
|
3211
3278
|
const mainItem = document.createElement("div");
|
|
3212
3279
|
mainItem.className = "thread-item" + (currentThreadId === null ? " active" : "");
|
|
3213
|
-
mainItem.innerHTML = '<div class="thread-item-title">Main
|
|
3280
|
+
mainItem.innerHTML = '<div class="thread-item-title">Main</div><div class="thread-item-meta">Always here</div>';
|
|
3214
3281
|
mainItem.addEventListener("click", () => switchThread(null));
|
|
3215
3282
|
threadListEl.appendChild(mainItem);
|
|
3216
3283
|
|
|
@@ -3220,8 +3287,24 @@
|
|
|
3220
3287
|
item.dataset.id = t.id;
|
|
3221
3288
|
const ago = timeAgo(t.updatedAt);
|
|
3222
3289
|
item.innerHTML = '<div class="thread-item-title">' + escapeHtml(t.title) + '</div>'
|
|
3223
|
-
+ '<div class="thread-item-meta">' + ago
|
|
3224
|
-
|
|
3290
|
+
+ '<div class="thread-item-meta">' + ago
|
|
3291
|
+
+ '<button class="thread-delete-btn" title="Delete chat" data-thread-id="' + t.id + '">×</button></div>';
|
|
3292
|
+
item.addEventListener("click", (e) => {
|
|
3293
|
+
if (e.target.classList && e.target.classList.contains("thread-delete-btn")) return;
|
|
3294
|
+
switchThread(t.id);
|
|
3295
|
+
});
|
|
3296
|
+
item.querySelector(".thread-delete-btn").addEventListener("click", async (e) => {
|
|
3297
|
+
e.stopPropagation();
|
|
3298
|
+
const tid = e.target.dataset ? e.target.dataset.threadId : null;
|
|
3299
|
+
if (!tid) return;
|
|
3300
|
+
try {
|
|
3301
|
+
await api("/api/threads/" + encodeURIComponent(tid) + "?sessionId=" + encodeURIComponent(sessionId), {
|
|
3302
|
+
method: "DELETE",
|
|
3303
|
+
});
|
|
3304
|
+
if (currentThreadId === tid) await switchThread(null);
|
|
3305
|
+
loadThreads();
|
|
3306
|
+
} catch (err) { console.log("Delete thread failed:", err.message); }
|
|
3307
|
+
});
|
|
3225
3308
|
threadListEl.appendChild(item);
|
|
3226
3309
|
}
|
|
3227
3310
|
}
|
|
@@ -3253,6 +3336,12 @@
|
|
|
3253
3336
|
topicState.scores = [];
|
|
3254
3337
|
topicState.messageTexts = [];
|
|
3255
3338
|
topicState.topic = "";
|
|
3339
|
+
topicState.branches = 0;
|
|
3340
|
+
topicState.maxDrift = 0;
|
|
3341
|
+
topicState.merges = 0;
|
|
3342
|
+
graphState.lanes = [true, false, false, false, false];
|
|
3343
|
+
graphState.currentLane = 0;
|
|
3344
|
+
graphState.history = [];
|
|
3256
3345
|
renderThreadList();
|
|
3257
3346
|
updateThreadLabel();
|
|
3258
3347
|
|
|
@@ -3294,7 +3383,7 @@
|
|
|
3294
3383
|
function updateThreadLabel() {
|
|
3295
3384
|
if (currentThreadId) {
|
|
3296
3385
|
const t = threads.find(t => t.id === currentThreadId);
|
|
3297
|
-
threadCurrentLabel.textContent = t ? t.title : "
|
|
3386
|
+
threadCurrentLabel.textContent = t ? t.title : "Chat";
|
|
3298
3387
|
} else {
|
|
3299
3388
|
threadCurrentLabel.textContent = "";
|
|
3300
3389
|
}
|
|
@@ -3317,6 +3406,57 @@
|
|
|
3317
3406
|
}
|
|
3318
3407
|
});
|
|
3319
3408
|
|
|
3409
|
+
// --- Auto-title chats after first exchange ---
|
|
3410
|
+
var chatAutoTitled = {}; // threadId → true if already titled
|
|
3411
|
+
function autoTitleChat(threadId) {
|
|
3412
|
+
if (!threadId || chatAutoTitled[threadId]) return;
|
|
3413
|
+
// Skip if already has a real title
|
|
3414
|
+
var existing = threads.find(function(x) { return x.id === threadId; });
|
|
3415
|
+
if (existing && existing.title && existing.title !== "New chat" && existing.title !== "New thread") {
|
|
3416
|
+
chatAutoTitled[threadId] = true;
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3419
|
+
// Get the first user message in the current view
|
|
3420
|
+
var msgs = messagesEl.querySelectorAll(".message.user .content");
|
|
3421
|
+
if (msgs.length === 0) return;
|
|
3422
|
+
var firstMsg = (msgs[0].textContent || "").trim();
|
|
3423
|
+
if (firstMsg.length < 3) return;
|
|
3424
|
+
|
|
3425
|
+
// Generate title: first sentence or first ~40 chars, cleaned up
|
|
3426
|
+
var title = firstMsg
|
|
3427
|
+
.replace(/```[\s\S]*?```/g, " ")
|
|
3428
|
+
.replace(/https?:\/\/\S+/g, "")
|
|
3429
|
+
.replace(/\s+/g, " ")
|
|
3430
|
+
.trim();
|
|
3431
|
+
// Use first sentence if short enough
|
|
3432
|
+
var sentenceEnd = title.search(/[.!?\n]/);
|
|
3433
|
+
if (sentenceEnd > 0 && sentenceEnd <= 50) {
|
|
3434
|
+
title = title.slice(0, sentenceEnd);
|
|
3435
|
+
} else {
|
|
3436
|
+
title = title.slice(0, 44);
|
|
3437
|
+
// Cut at last word boundary
|
|
3438
|
+
var lastSpace = title.lastIndexOf(" ");
|
|
3439
|
+
if (lastSpace > 20) title = title.slice(0, lastSpace);
|
|
3440
|
+
}
|
|
3441
|
+
title = title.trim();
|
|
3442
|
+
if (title.length < 3) return;
|
|
3443
|
+
|
|
3444
|
+
chatAutoTitled[threadId] = true;
|
|
3445
|
+
|
|
3446
|
+
// Update server
|
|
3447
|
+
fetch("/api/threads/" + encodeURIComponent(threadId), {
|
|
3448
|
+
method: "PATCH",
|
|
3449
|
+
headers: { "Content-Type": "application/json", ...authHeaders() },
|
|
3450
|
+
body: JSON.stringify({ sessionId: sessionId, title: title }),
|
|
3451
|
+
}).then(function() {
|
|
3452
|
+
// Update local state and sidebar
|
|
3453
|
+
var t = threads.find(function(x) { return x.id === threadId; });
|
|
3454
|
+
if (t) t.title = title;
|
|
3455
|
+
renderThreadList();
|
|
3456
|
+
updateThreadLabel();
|
|
3457
|
+
}).catch(function() {});
|
|
3458
|
+
}
|
|
3459
|
+
|
|
3320
3460
|
// --- Attached files ---
|
|
3321
3461
|
let pendingImages = []; // { data: base64, mimeType: string }
|
|
3322
3462
|
let pendingFiles = []; // { name: string, text: string }
|
|
@@ -4069,6 +4209,20 @@
|
|
|
4069
4209
|
// Pre-load threads list
|
|
4070
4210
|
await loadThreads();
|
|
4071
4211
|
|
|
4212
|
+
// Load seal values from membrane so flagged terms blur on refresh
|
|
4213
|
+
try {
|
|
4214
|
+
const sealRes = await fetch("/api/sensitive/seals?" + new URLSearchParams({ sessionId: sessionId || "" }));
|
|
4215
|
+
if (sealRes.ok) {
|
|
4216
|
+
const sealData = await sealRes.json();
|
|
4217
|
+
if (sealData.values && sealData.values.length > 0) {
|
|
4218
|
+
window._serverSealValues = sealData.values;
|
|
4219
|
+
document.querySelectorAll("#messages .message .content").forEach(function(el) {
|
|
4220
|
+
applyServerSeals(el, window._serverSealValues);
|
|
4221
|
+
});
|
|
4222
|
+
}
|
|
4223
|
+
}
|
|
4224
|
+
} catch (e) { /* best effort */ }
|
|
4225
|
+
|
|
4072
4226
|
// Restore thread + scroll after toast refresh
|
|
4073
4227
|
try {
|
|
4074
4228
|
const restore = sessionStorage.getItem("_dash_restore");
|
|
@@ -4399,13 +4553,27 @@
|
|
|
4399
4553
|
}
|
|
4400
4554
|
}
|
|
4401
4555
|
|
|
4402
|
-
// ---
|
|
4556
|
+
// --- Conversation graph (git-style branch visualization) ---
|
|
4557
|
+
var LANE_X = [10, 22, 34, 46, 58]; // 5 lanes, 12px apart
|
|
4558
|
+
var LANE_COLORS = ["#2ea043", "#3fb950", "#d29922", "#db6d28", "#f85149"];
|
|
4559
|
+
// Compat aliases for old code paths
|
|
4560
|
+
var DRIFT_POSITIONS = LANE_X;
|
|
4561
|
+
var DRIFT_COLORS = LANE_COLORS;
|
|
4403
4562
|
var topicState = {
|
|
4404
4563
|
keywords: [], // main topic keywords extracted from first messages
|
|
4405
4564
|
established: false, // topic established after N messages
|
|
4406
4565
|
scores: [], // drift score per message (0-4)
|
|
4407
4566
|
messageTexts: [], // raw text per message for scoring
|
|
4408
4567
|
topic: "", // detected main topic label
|
|
4568
|
+
branches: 0, // number of active divergences
|
|
4569
|
+
maxDrift: 0, // peak drift in current branch
|
|
4570
|
+
merges: 0, // times conversation returned to topic
|
|
4571
|
+
};
|
|
4572
|
+
// Graph state: tracks which lanes are currently active
|
|
4573
|
+
var graphState = {
|
|
4574
|
+
lanes: [true, false, false, false, false],
|
|
4575
|
+
currentLane: 0,
|
|
4576
|
+
history: [], // per message: { lane, activeLanes, forkFrom?, mergeTo?, label? }
|
|
4409
4577
|
};
|
|
4410
4578
|
|
|
4411
4579
|
// Stop words to filter out
|
|
@@ -4496,6 +4664,120 @@
|
|
|
4496
4664
|
+ '<span class="continuity-topic">' + (topicState.topic || "detecting...") + '</span>';
|
|
4497
4665
|
}
|
|
4498
4666
|
|
|
4667
|
+
// Compute graph entry for a new message at given drift level
|
|
4668
|
+
function computeGraphEntry(drift, prevDrift) {
|
|
4669
|
+
var entry = {
|
|
4670
|
+
lane: drift,
|
|
4671
|
+
activeLanes: graphState.lanes.slice(),
|
|
4672
|
+
forkFrom: undefined,
|
|
4673
|
+
mergeTo: undefined,
|
|
4674
|
+
label: undefined,
|
|
4675
|
+
};
|
|
4676
|
+
|
|
4677
|
+
if (drift > prevDrift && drift >= 2) {
|
|
4678
|
+
// Fork: activate new lane, keep old active
|
|
4679
|
+
graphState.lanes[drift] = true;
|
|
4680
|
+
entry.forkFrom = prevDrift;
|
|
4681
|
+
entry.activeLanes = graphState.lanes.slice();
|
|
4682
|
+
// Extract fork label from recent keywords
|
|
4683
|
+
var recent = topicState.messageTexts.slice(-2).join(" ");
|
|
4684
|
+
var rk = extractKeywords(recent);
|
|
4685
|
+
var topicSet = new Set(topicState.keywords);
|
|
4686
|
+
var newWords = rk.filter(function(w) { return !topicSet.has(w); }).slice(0, 2);
|
|
4687
|
+
if (newWords.length > 0) entry.label = newWords.join(" ");
|
|
4688
|
+
} else if (drift < prevDrift) {
|
|
4689
|
+
// Merge: deactivate old lane(s) between current and previous
|
|
4690
|
+
for (var i = drift + 1; i <= prevDrift; i++) {
|
|
4691
|
+
graphState.lanes[i] = false;
|
|
4692
|
+
}
|
|
4693
|
+
entry.mergeTo = prevDrift;
|
|
4694
|
+
entry.activeLanes = graphState.lanes.slice();
|
|
4695
|
+
}
|
|
4696
|
+
|
|
4697
|
+
graphState.currentLane = drift;
|
|
4698
|
+
graphState.history.push(entry);
|
|
4699
|
+
return entry;
|
|
4700
|
+
}
|
|
4701
|
+
|
|
4702
|
+
// Render the graph column for a message
|
|
4703
|
+
function renderGraphRow(messageDiv, entry) {
|
|
4704
|
+
var graph = document.createElement("div");
|
|
4705
|
+
graph.className = "drift-graph";
|
|
4706
|
+
|
|
4707
|
+
// Draw vertical line segments for each active lane
|
|
4708
|
+
for (var i = 0; i < 5; i++) {
|
|
4709
|
+
if (!entry.activeLanes[i]) continue;
|
|
4710
|
+
var line = document.createElement("div");
|
|
4711
|
+
line.className = "lane-line" + (i === entry.lane ? " active-lane" : "");
|
|
4712
|
+
line.style.left = LANE_X[i] + "px";
|
|
4713
|
+
line.style.background = LANE_COLORS[i];
|
|
4714
|
+
graph.appendChild(line);
|
|
4715
|
+
}
|
|
4716
|
+
|
|
4717
|
+
// Draw commit node on current lane
|
|
4718
|
+
var node = document.createElement("div");
|
|
4719
|
+
node.className = "lane-node";
|
|
4720
|
+
node.style.left = LANE_X[entry.lane] + "px";
|
|
4721
|
+
node.style.background = LANE_COLORS[entry.lane];
|
|
4722
|
+
graph.appendChild(node);
|
|
4723
|
+
|
|
4724
|
+
// Draw fork or merge curve via SVG
|
|
4725
|
+
if (entry.forkFrom !== undefined || entry.mergeTo !== undefined) {
|
|
4726
|
+
var svgNS = "http://www.w3.org/2000/svg";
|
|
4727
|
+
var svg = document.createElementNS(svgNS, "svg");
|
|
4728
|
+
svg.setAttribute("class", "lane-svg");
|
|
4729
|
+
svg.setAttribute("viewBox", "0 0 68 40");
|
|
4730
|
+
svg.setAttribute("fill", "none");
|
|
4731
|
+
|
|
4732
|
+
if (entry.forkFrom !== undefined) {
|
|
4733
|
+
// Curve from parent lane down to new lane
|
|
4734
|
+
var fx = LANE_X[entry.forkFrom] + 1;
|
|
4735
|
+
var tx = LANE_X[entry.lane] + 1;
|
|
4736
|
+
var path = document.createElementNS(svgNS, "path");
|
|
4737
|
+
path.setAttribute("d", "M" + fx + ",0 C" + fx + ",12 " + tx + ",7 " + tx + ",19");
|
|
4738
|
+
path.setAttribute("stroke", LANE_COLORS[entry.lane]);
|
|
4739
|
+
path.setAttribute("stroke-width", "2");
|
|
4740
|
+
path.setAttribute("stroke-linecap", "round");
|
|
4741
|
+
svg.appendChild(path);
|
|
4742
|
+
}
|
|
4743
|
+
|
|
4744
|
+
if (entry.mergeTo !== undefined) {
|
|
4745
|
+
// Curve from old lane merging back to current
|
|
4746
|
+
var mx = LANE_X[entry.mergeTo] + 1;
|
|
4747
|
+
var cx = LANE_X[entry.lane] + 1;
|
|
4748
|
+
var path2 = document.createElementNS(svgNS, "path");
|
|
4749
|
+
path2.setAttribute("d", "M" + mx + ",0 C" + mx + ",12 " + cx + ",7 " + cx + ",19");
|
|
4750
|
+
path2.setAttribute("stroke", LANE_COLORS[entry.mergeTo]);
|
|
4751
|
+
path2.setAttribute("stroke-width", "2");
|
|
4752
|
+
path2.setAttribute("stroke-linecap", "round");
|
|
4753
|
+
path2.setAttribute("opacity", "0.6");
|
|
4754
|
+
svg.appendChild(path2);
|
|
4755
|
+
}
|
|
4756
|
+
|
|
4757
|
+
graph.appendChild(svg);
|
|
4758
|
+
}
|
|
4759
|
+
|
|
4760
|
+
// Fork label
|
|
4761
|
+
if (entry.label) {
|
|
4762
|
+
var lbl = document.createElement("div");
|
|
4763
|
+
lbl.className = "drift-label";
|
|
4764
|
+
lbl.textContent = entry.label;
|
|
4765
|
+
lbl.style.color = LANE_COLORS[entry.lane];
|
|
4766
|
+
graph.appendChild(lbl);
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4769
|
+
// Merge indicator
|
|
4770
|
+
if (entry.mergeTo !== undefined && entry.lane <= 1) {
|
|
4771
|
+
var ml = document.createElement("div");
|
|
4772
|
+
ml.className = "drift-label";
|
|
4773
|
+
ml.textContent = "↩ merged";
|
|
4774
|
+
ml.style.color = LANE_COLORS[0];
|
|
4775
|
+
graph.appendChild(ml);
|
|
4776
|
+
}
|
|
4777
|
+
|
|
4778
|
+
messageDiv.appendChild(graph);
|
|
4779
|
+
}
|
|
4780
|
+
|
|
4499
4781
|
function addMessage(role, content, labelOverride) {
|
|
4500
4782
|
const div = document.createElement("div");
|
|
4501
4783
|
div.className = "message " + role;
|
|
@@ -4516,29 +4798,29 @@
|
|
|
4516
4798
|
applyPrivacySeals(div.querySelector(".content"));
|
|
4517
4799
|
if (window._serverSealValues) applyServerSeals(div.querySelector(".content"), window._serverSealValues);
|
|
4518
4800
|
|
|
4519
|
-
// ---
|
|
4801
|
+
// --- Conversation graph ---
|
|
4520
4802
|
if (role !== "system") {
|
|
4521
4803
|
var text = typeof content === "string" ? content : "";
|
|
4522
4804
|
topicState.messageTexts.push(text);
|
|
4523
4805
|
|
|
4524
|
-
// Establish topic after a few messages
|
|
4525
4806
|
if (!topicState.established && topicState.messageTexts.length >= 2) {
|
|
4526
4807
|
updateTopicFromMessages();
|
|
4527
4808
|
}
|
|
4528
4809
|
|
|
4529
4810
|
var drift = scoreDrift(text);
|
|
4811
|
+
var prevDrift = topicState.scores.length > 0 ? topicState.scores[topicState.scores.length - 1] : 0;
|
|
4530
4812
|
topicState.scores.push(drift);
|
|
4531
4813
|
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
div.appendChild(driftLine);
|
|
4814
|
+
if (drift > prevDrift && drift >= 2) {
|
|
4815
|
+
topicState.branches++;
|
|
4816
|
+
topicState.maxDrift = Math.max(topicState.maxDrift, drift);
|
|
4817
|
+
}
|
|
4818
|
+
if (drift < prevDrift && drift <= 1 && prevDrift >= 2) {
|
|
4819
|
+
topicState.merges++;
|
|
4820
|
+
}
|
|
4540
4821
|
|
|
4541
|
-
|
|
4822
|
+
var entry = computeGraphEntry(drift, prevDrift);
|
|
4823
|
+
renderGraphRow(div, entry);
|
|
4542
4824
|
renderContinuityBadge();
|
|
4543
4825
|
}
|
|
4544
4826
|
|
|
@@ -4883,16 +5165,16 @@
|
|
|
4883
5165
|
updateTopicFromMessages();
|
|
4884
5166
|
}
|
|
4885
5167
|
var drift = scoreDrift(finalText);
|
|
5168
|
+
var prevDrift = topicState.scores.length > 0 ? topicState.scores[topicState.scores.length - 1] : 0;
|
|
4886
5169
|
topicState.scores.push(drift);
|
|
5170
|
+
|
|
5171
|
+
if (drift > prevDrift && drift >= 2) topicState.branches++;
|
|
5172
|
+
if (drift < prevDrift && drift <= 1 && prevDrift >= 2) topicState.merges++;
|
|
5173
|
+
|
|
4887
5174
|
var msgDiv = contentEl.closest(".message");
|
|
4888
|
-
if (msgDiv && !msgDiv.querySelector(".drift-
|
|
4889
|
-
var
|
|
4890
|
-
|
|
4891
|
-
driftLine.setAttribute("data-drift", String(drift));
|
|
4892
|
-
var node = document.createElement("div");
|
|
4893
|
-
node.className = "drift-node";
|
|
4894
|
-
driftLine.appendChild(node);
|
|
4895
|
-
msgDiv.appendChild(driftLine);
|
|
5175
|
+
if (msgDiv && !msgDiv.querySelector(".drift-graph")) {
|
|
5176
|
+
var entry = computeGraphEntry(drift, prevDrift);
|
|
5177
|
+
renderGraphRow(msgDiv, entry);
|
|
4896
5178
|
}
|
|
4897
5179
|
renderContinuityBadge();
|
|
4898
5180
|
}
|
|
@@ -4921,8 +5203,11 @@
|
|
|
4921
5203
|
abortController = null;
|
|
4922
5204
|
setButtonSend();
|
|
4923
5205
|
chatInput.focus();
|
|
4924
|
-
//
|
|
4925
|
-
if (currentThreadId)
|
|
5206
|
+
// Auto-title chat after first assistant response
|
|
5207
|
+
if (currentThreadId) {
|
|
5208
|
+
autoTitleChat(currentThreadId);
|
|
5209
|
+
loadThreads();
|
|
5210
|
+
}
|
|
4926
5211
|
}
|
|
4927
5212
|
}
|
|
4928
5213
|
|
|
@@ -5732,6 +6017,41 @@
|
|
|
5732
6017
|
document.getElementById("vault-open-btn").addEventListener("click", openSettings);
|
|
5733
6018
|
document.getElementById("vault-close-btn").addEventListener("click", closeVault);
|
|
5734
6019
|
|
|
6020
|
+
// --- Theme toggle: dark → light → system ---
|
|
6021
|
+
var THEMES = ["dark", "light", "system"];
|
|
6022
|
+
var THEME_ICONS = {
|
|
6023
|
+
dark: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>',
|
|
6024
|
+
light: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>',
|
|
6025
|
+
system: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>',
|
|
6026
|
+
};
|
|
6027
|
+
function getStoredTheme() { return localStorage.getItem("dash_theme") || "dark"; }
|
|
6028
|
+
function applyTheme(theme) {
|
|
6029
|
+
var effective = theme;
|
|
6030
|
+
if (theme === "system") {
|
|
6031
|
+
effective = window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
|
6032
|
+
}
|
|
6033
|
+
document.documentElement.setAttribute("data-theme", effective);
|
|
6034
|
+
var themeBtn = document.getElementById("theme-toggle-btn");
|
|
6035
|
+
if (themeBtn) {
|
|
6036
|
+
themeBtn.innerHTML = THEME_ICONS[theme];
|
|
6037
|
+
themeBtn.title = "Theme: " + theme;
|
|
6038
|
+
}
|
|
6039
|
+
// Update meta theme-color
|
|
6040
|
+
var meta = document.querySelector('meta[name="theme-color"]');
|
|
6041
|
+
if (meta) meta.setAttribute("content", effective === "light" ? "#ffffff" : "#0a0a0a");
|
|
6042
|
+
}
|
|
6043
|
+
applyTheme(getStoredTheme());
|
|
6044
|
+
// Listen for system preference changes
|
|
6045
|
+
window.matchMedia("(prefers-color-scheme: light)").addEventListener("change", function() {
|
|
6046
|
+
if (getStoredTheme() === "system") applyTheme("system");
|
|
6047
|
+
});
|
|
6048
|
+
document.getElementById("theme-toggle-btn").addEventListener("click", function() {
|
|
6049
|
+
var current = getStoredTheme();
|
|
6050
|
+
var next = THEMES[(THEMES.indexOf(current) + 1) % THEMES.length];
|
|
6051
|
+
localStorage.setItem("dash_theme", next);
|
|
6052
|
+
applyTheme(next);
|
|
6053
|
+
});
|
|
6054
|
+
|
|
5735
6055
|
document.getElementById("save-your-name-btn").addEventListener("click", async () => {
|
|
5736
6056
|
const nameInput = document.getElementById("settings-your-name");
|
|
5737
6057
|
const newName = nameInput.value.trim();
|