draken 0.1.6 → 0.3.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/ACCEPTANCE.md +34 -0
- package/CHANGELOG.md +65 -0
- package/CONTRIBUTING.md +129 -0
- package/MEMORY.md +118 -0
- package/PERSONA.md +67 -0
- package/README.md +168 -78
- package/SETUP.md +111 -0
- package/SOURCES.md +75 -0
- package/TRAY.md +54 -0
- package/VOICE.md +126 -0
- package/dist/auth/middleware.d.ts +3 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +20 -15
- package/dist/auth/middleware.js.map +1 -1
- package/dist/cli.js +77 -113
- package/dist/cli.js.map +1 -1
- package/dist/db/agent-migration.d.ts +7 -0
- package/dist/db/agent-migration.d.ts.map +1 -0
- package/dist/db/agent-migration.js +36 -0
- package/dist/db/agent-migration.js.map +1 -0
- package/dist/db/evidence.d.ts +37 -0
- package/dist/db/evidence.d.ts.map +1 -0
- package/dist/db/evidence.js +110 -0
- package/dist/db/evidence.js.map +1 -0
- package/dist/db/pointer-migration.d.ts +7 -0
- package/dist/db/pointer-migration.d.ts.map +1 -0
- package/dist/db/pointer-migration.js +117 -0
- package/dist/db/pointer-migration.js.map +1 -0
- package/dist/db/retained-text.d.ts +8 -0
- package/dist/db/retained-text.d.ts.map +1 -0
- package/dist/db/retained-text.js +36 -0
- package/dist/db/retained-text.js.map +1 -0
- package/dist/db/schema.d.ts +1 -5
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +206 -55
- package/dist/db/schema.js.map +1 -1
- package/dist/db/snapshot-pointers.d.ts +5 -0
- package/dist/db/snapshot-pointers.d.ts.map +1 -0
- package/dist/db/snapshot-pointers.js +174 -0
- package/dist/db/snapshot-pointers.js.map +1 -0
- package/dist/memory/automatic.d.ts +38 -0
- package/dist/memory/automatic.d.ts.map +1 -0
- package/dist/memory/automatic.js +155 -0
- package/dist/memory/automatic.js.map +1 -0
- package/dist/memory/context.d.ts +12 -0
- package/dist/memory/context.d.ts.map +1 -0
- package/dist/memory/context.js +107 -0
- package/dist/memory/context.js.map +1 -0
- package/dist/memory/embedding-pool.d.ts +28 -0
- package/dist/memory/embedding-pool.d.ts.map +1 -0
- package/dist/memory/embedding-pool.js +135 -0
- package/dist/memory/embedding-pool.js.map +1 -0
- package/dist/memory/embedding-worker.d.ts +2 -0
- package/dist/memory/embedding-worker.d.ts.map +1 -0
- package/dist/memory/embedding-worker.js +32 -0
- package/dist/memory/embedding-worker.js.map +1 -0
- package/dist/memory/index.d.ts +32 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +441 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/model-files.d.ts +9 -0
- package/dist/memory/model-files.d.ts.map +1 -0
- package/dist/memory/model-files.js +13 -0
- package/dist/memory/model-files.js.map +1 -0
- package/dist/memory/model.d.ts +15 -0
- package/dist/memory/model.d.ts.map +1 -0
- package/dist/memory/model.js +147 -0
- package/dist/memory/model.js.map +1 -0
- package/dist/memory/readiness.d.ts +16 -0
- package/dist/memory/readiness.d.ts.map +1 -0
- package/dist/memory/readiness.js +131 -0
- package/dist/memory/readiness.js.map +1 -0
- package/dist/memory/reconcile.d.ts +11 -0
- package/dist/memory/reconcile.d.ts.map +1 -0
- package/dist/memory/reconcile.js +132 -0
- package/dist/memory/reconcile.js.map +1 -0
- package/dist/memory/service.d.ts +10 -0
- package/dist/memory/service.d.ts.map +1 -0
- package/dist/memory/service.js +243 -0
- package/dist/memory/service.js.map +1 -0
- package/dist/memory/sources.d.ts +15 -0
- package/dist/memory/sources.d.ts.map +1 -0
- package/dist/memory/sources.js +94 -0
- package/dist/memory/sources.js.map +1 -0
- package/dist/memory/stamps.d.ts +13 -0
- package/dist/memory/stamps.d.ts.map +1 -0
- package/dist/memory/stamps.js +101 -0
- package/dist/memory/stamps.js.map +1 -0
- package/dist/memory/storage.d.ts +5 -0
- package/dist/memory/storage.d.ts.map +1 -0
- package/dist/memory/storage.js +116 -0
- package/dist/memory/storage.js.map +1 -0
- package/dist/memory/types.d.ts +89 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +8 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/memory/worker.d.ts +2 -0
- package/dist/memory/worker.d.ts.map +1 -0
- package/dist/memory/worker.js +84 -0
- package/dist/memory/worker.js.map +1 -0
- package/dist/npm-cli.d.ts +4 -0
- package/dist/npm-cli.d.ts.map +1 -0
- package/dist/npm-cli.js +36 -0
- package/dist/npm-cli.js.map +1 -0
- package/dist/pi/runtime.d.ts +34 -0
- package/dist/pi/runtime.d.ts.map +1 -0
- package/dist/pi/runtime.js +210 -0
- package/dist/pi/runtime.js.map +1 -0
- package/dist/pi/setup.d.ts +5 -0
- package/dist/pi/setup.d.ts.map +1 -0
- package/dist/pi/setup.js +147 -0
- package/dist/pi/setup.js.map +1 -0
- package/dist/routes/auth.d.ts.map +1 -1
- package/dist/routes/auth.js +3 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/live-voice.d.ts +3 -0
- package/dist/routes/live-voice.d.ts.map +1 -0
- package/dist/routes/live-voice.js +49 -0
- package/dist/routes/live-voice.js.map +1 -0
- package/dist/routes/{browse.d.ts → memory.d.ts} +1 -1
- package/dist/routes/memory.d.ts.map +1 -0
- package/dist/routes/memory.js +18 -0
- package/dist/routes/memory.js.map +1 -0
- package/dist/routes/{tasks.d.ts → sync.d.ts} +1 -1
- package/dist/routes/sync.d.ts.map +1 -0
- package/dist/routes/sync.js +145 -0
- package/dist/routes/sync.js.map +1 -0
- package/dist/routes/{projects.d.ts → voice.d.ts} +1 -1
- package/dist/routes/voice.d.ts.map +1 -0
- package/dist/routes/voice.js +35 -0
- package/dist/routes/voice.js.map +1 -0
- package/dist/server-state.d.ts +30 -0
- package/dist/server-state.d.ts.map +1 -0
- package/dist/server-state.js +113 -0
- package/dist/server-state.js.map +1 -0
- package/dist/server-status.d.ts +7 -0
- package/dist/server-status.d.ts.map +1 -0
- package/dist/server-status.js +34 -0
- package/dist/server-status.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +148 -46
- package/dist/server.js.map +1 -1
- package/dist/sources/adapters.d.ts +15 -0
- package/dist/sources/adapters.d.ts.map +1 -0
- package/dist/sources/adapters.js +159 -0
- package/dist/sources/adapters.js.map +1 -0
- package/dist/sources/registry.d.ts +17 -0
- package/dist/sources/registry.d.ts.map +1 -0
- package/dist/sources/registry.js +56 -0
- package/dist/sources/registry.js.map +1 -0
- package/dist/sync/collector.d.ts +3 -0
- package/dist/sync/collector.d.ts.map +1 -0
- package/dist/sync/collector.js +324 -0
- package/dist/sync/collector.js.map +1 -0
- package/dist/sync/cost.d.ts +7 -0
- package/dist/sync/cost.d.ts.map +1 -0
- package/dist/sync/cost.js +31 -0
- package/dist/sync/cost.js.map +1 -0
- package/dist/sync/jsonl.d.ts +34 -0
- package/dist/sync/jsonl.d.ts.map +1 -0
- package/dist/sync/jsonl.js +161 -0
- package/dist/sync/jsonl.js.map +1 -0
- package/dist/sync/manager.d.ts +15 -0
- package/dist/sync/manager.d.ts.map +1 -0
- package/dist/sync/manager.js +287 -0
- package/dist/sync/manager.js.map +1 -0
- package/dist/sync/normalize.d.ts +22 -0
- package/dist/sync/normalize.d.ts.map +1 -0
- package/dist/sync/normalize.js +107 -0
- package/dist/sync/normalize.js.map +1 -0
- package/dist/sync/pi-output.d.ts +33 -0
- package/dist/sync/pi-output.d.ts.map +1 -0
- package/dist/sync/pi-output.js +186 -0
- package/dist/sync/pi-output.js.map +1 -0
- package/dist/sync/pi.d.ts +15 -0
- package/dist/sync/pi.d.ts.map +1 -0
- package/dist/sync/pi.js +149 -0
- package/dist/sync/pi.js.map +1 -0
- package/dist/sync/recap.d.ts +25 -0
- package/dist/sync/recap.d.ts.map +1 -0
- package/dist/sync/recap.js +118 -0
- package/dist/sync/recap.js.map +1 -0
- package/dist/sync/reconciliation.d.ts +16 -0
- package/dist/sync/reconciliation.d.ts.map +1 -0
- package/dist/sync/reconciliation.js +22 -0
- package/dist/sync/reconciliation.js.map +1 -0
- package/dist/sync/references.d.ts +10 -0
- package/dist/sync/references.d.ts.map +1 -0
- package/dist/sync/references.js +50 -0
- package/dist/sync/references.js.map +1 -0
- package/dist/sync/source-files.d.ts +16 -0
- package/dist/sync/source-files.d.ts.map +1 -0
- package/dist/sync/source-files.js +56 -0
- package/dist/sync/source-files.js.map +1 -0
- package/dist/sync/store.d.ts +36 -0
- package/dist/sync/store.d.ts.map +1 -0
- package/dist/sync/store.js +359 -0
- package/dist/sync/store.js.map +1 -0
- package/dist/sync/summary-budget.d.ts +19 -0
- package/dist/sync/summary-budget.d.ts.map +1 -0
- package/dist/sync/summary-budget.js +39 -0
- package/dist/sync/summary-budget.js.map +1 -0
- package/dist/sync/tree.d.ts +69 -0
- package/dist/sync/tree.d.ts.map +1 -0
- package/dist/sync/tree.js +599 -0
- package/dist/sync/tree.js.map +1 -0
- package/dist/tray/controller.d.ts +51 -0
- package/dist/tray/controller.d.ts.map +1 -0
- package/dist/tray/controller.js +178 -0
- package/dist/tray/controller.js.map +1 -0
- package/dist/tray/launcher.d.ts +3 -0
- package/dist/tray/launcher.d.ts.map +1 -0
- package/dist/tray/launcher.js +47 -0
- package/dist/tray/launcher.js.map +1 -0
- package/dist/tray/native.d.ts +12 -0
- package/dist/tray/native.d.ts.map +1 -0
- package/dist/tray/native.js +93 -0
- package/dist/tray/native.js.map +1 -0
- package/dist/tray/processes.d.ts +5 -0
- package/dist/tray/processes.d.ts.map +1 -0
- package/dist/tray/processes.js +99 -0
- package/dist/tray/processes.js.map +1 -0
- package/dist/tray/worker.d.ts +4 -0
- package/dist/tray/worker.d.ts.map +1 -0
- package/dist/tray/worker.js +150 -0
- package/dist/tray/worker.js.map +1 -0
- package/dist/types.d.ts +221 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/voice/continuation.d.ts +25 -0
- package/dist/voice/continuation.d.ts.map +1 -0
- package/dist/voice/continuation.js +95 -0
- package/dist/voice/continuation.js.map +1 -0
- package/dist/voice/history-focus.d.ts +14 -0
- package/dist/voice/history-focus.d.ts.map +1 -0
- package/dist/voice/history-focus.js +39 -0
- package/dist/voice/history-focus.js.map +1 -0
- package/dist/voice/legacy-history.d.ts +5 -0
- package/dist/voice/legacy-history.d.ts.map +1 -0
- package/dist/voice/legacy-history.js +34 -0
- package/dist/voice/legacy-history.js.map +1 -0
- package/dist/voice/live-context.d.ts +14 -0
- package/dist/voice/live-context.d.ts.map +1 -0
- package/dist/voice/live-context.js +137 -0
- package/dist/voice/live-context.js.map +1 -0
- package/dist/voice/live.d.ts +37 -0
- package/dist/voice/live.d.ts.map +1 -0
- package/dist/voice/live.js +462 -0
- package/dist/voice/live.js.map +1 -0
- package/dist/voice/preparation.d.ts +8 -0
- package/dist/voice/preparation.d.ts.map +1 -0
- package/dist/voice/preparation.js +59 -0
- package/dist/voice/preparation.js.map +1 -0
- package/package.json +49 -16
- package/public/assets/index-BQFBaSKm.js +40 -0
- package/public/assets/index-CYCbTSh1.js +131 -0
- package/public/assets/index-DntUQtGK.css +1 -0
- package/public/assets/persona-BVIfx5k8.js +1 -0
- package/public/assets/persona-C_m1CVKe.css +1 -0
- package/public/assets/scene-CBV2oPhA.js +3854 -0
- package/public/index.html +6 -8
- package/public/persona/THREE-LICENSE.txt +21 -0
- package/public/persona/call-poster.webp +0 -0
- package/public/persona/chat-avatar.webp +0 -0
- package/public/persona/reference.jpg +0 -0
- package/public/persona/sample.wav +0 -0
- package/public/persona.html +7 -0
- package/runtime/pi/package-lock.json +1549 -0
- package/runtime/pi/package.json +12 -0
- package/tests/fixtures/voice-question.wav +0 -0
- package/tray/assets/error.ico +0 -0
- package/tray/assets/error.png +0 -0
- package/tray/assets/running.ico +0 -0
- package/tray/assets/running.png +0 -0
- package/tray/assets/starting.ico +0 -0
- package/tray/assets/starting.png +0 -0
- package/tray/assets/stopped.ico +0 -0
- package/tray/assets/stopped.png +0 -0
- package/tray/assets/stopping.ico +0 -0
- package/tray/assets/stopping.png +0 -0
- package/tray/macos.js +72 -0
- package/tray/windows.ps1 +104 -0
- package/voice/realtime/README.md +84 -0
- package/voice/realtime/backend.mjs +81 -0
- package/voice/realtime/native.mjs +210 -0
- package/voice/realtime/peer.d.mts +15 -0
- package/voice/realtime/peer.mjs +116 -0
- package/voice/realtime/probe-browser.mjs +81 -0
- package/voice/realtime/probe-server.mjs +86 -0
- package/voice/realtime/probe.html +11 -0
- package/voice/realtime/probe.mjs +42 -0
- package/voice/realtime/rpc.mjs +118 -0
- package/voice/realtime/setup.mjs +32 -0
- package/voice/tls.mjs +49 -0
- package/dist/db/queries.d.ts +0 -16
- package/dist/db/queries.d.ts.map +0 -1
- package/dist/db/queries.js +0 -91
- package/dist/db/queries.js.map +0 -1
- package/dist/docker/dockerfile.d.ts +0 -50
- package/dist/docker/dockerfile.d.ts.map +0 -1
- package/dist/docker/dockerfile.js +0 -160
- package/dist/docker/dockerfile.js.map +0 -1
- package/dist/docker/manager.d.ts +0 -42
- package/dist/docker/manager.d.ts.map +0 -1
- package/dist/docker/manager.js +0 -421
- package/dist/docker/manager.js.map +0 -1
- package/dist/git/status.d.ts +0 -76
- package/dist/git/status.d.ts.map +0 -1
- package/dist/git/status.js +0 -332
- package/dist/git/status.js.map +0 -1
- package/dist/routes/browse.d.ts.map +0 -1
- package/dist/routes/browse.js +0 -49
- package/dist/routes/browse.js.map +0 -1
- package/dist/routes/git.d.ts +0 -9
- package/dist/routes/git.d.ts.map +0 -1
- package/dist/routes/git.js +0 -338
- package/dist/routes/git.js.map +0 -1
- package/dist/routes/projects.d.ts.map +0 -1
- package/dist/routes/projects.js +0 -220
- package/dist/routes/projects.js.map +0 -1
- package/dist/routes/tasks.d.ts.map +0 -1
- package/dist/routes/tasks.js +0 -313
- package/dist/routes/tasks.js.map +0 -1
- package/draken.dockerfile.template +0 -18
- package/public/assets/index-3ngsG5kF.css +0 -1
- package/public/assets/index-B3YSD0ee.js +0 -252
package/VOICE.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# ChatGPT voice calls
|
|
2
|
+
|
|
3
|
+
**Draken has one voice engine: subscription-backed ChatGPT live voice.** It uses the pinned official Codex helper and a separate native sign-in to the same paid ChatGPT account. Microphone audio and bounded context go to OpenAI over a persistent browser audio connection.
|
|
4
|
+
|
|
5
|
+
The former Whisper → pi → Kokoro engine has been removed, including its Python worker, installer, browser speech detector and execution endpoints. Old call records are still readable; they are not a second working voice option. There is no local-speech, Platform API-key or alternative-provider fallback.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
After [installing Draken](SETUP.md#install-and-start), run:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
draken voice setup
|
|
13
|
+
draken voice login # Complete the official ChatGPT device sign-in
|
|
14
|
+
draken voice status # Local prerequisites only; not an audio test
|
|
15
|
+
draken # Start the server if it is not already running
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
No voice-mode setting is needed. An existing `DRAKEN_VOICE_MODE=native` remains accepted so installed launchers keep working. Any other value, including `local`, fails startup rather than silently changing an old privacy choice into cloud audio. Remove obsolete local speech settings from launchers; `voice:setup` no longer exists.
|
|
19
|
+
|
|
20
|
+
Setup runs npm's resolved JavaScript entry under the current Node executable, without a shell or command-shim evaluation. On Windows x64/arm64, status/login/calls launch the pinned official package's `codex.exe` directly, so the owned child is the native process rather than a `.cmd`/Node wrapper. HOME and Windows profile directories are private to the voice account. Runtime installation/version checks do not qualify sign-in, refresh, WebRTC or physical audio.
|
|
21
|
+
|
|
22
|
+
The helper and its credentials live under `~/.draken/realtime/`, separate from the installed application. Provider credentials never enter the browser. Pi credentials are not copied or converted. Preserve the existing database, dashboard credentials and TLS configuration when updating an installation. No snapshot regeneration is needed to enable voice.
|
|
23
|
+
|
|
24
|
+
This uses an experimental native interface, not a stable public embedding API. Successful setup or a connection handshake is not proof that an account can receive usable audio. The opt-in probe tests actual audio separately. Quota, idle accounting, coding-allowance impact and future compatibility are not established.
|
|
25
|
+
|
|
26
|
+
## Chat instead
|
|
27
|
+
|
|
28
|
+
For a keyboard-only conversation, choose **Chat instead** on Home or next to **Call Draken**. This is a separate `/syncs/:id/chat` surface, not a muted call. It uses the configured text model through pi and requires no microphone permission, WebRTC connection or native ChatGPT sign-in. It shows a square Draken portrait, searching/thinking status, saved messages and source links. Its model access/quota is separate from the native voice account. See [the text-chat guide](README.md#text-chat).
|
|
29
|
+
|
|
30
|
+
Choosing chat while a one-click call is still preparing consumes that browser call intent; preparation can finish without opening a microphone. Returning to **Voice & call history** never automatically starts a call. Existing voice history remains preserved and separately labelled.
|
|
31
|
+
|
|
32
|
+
## Start and use a call
|
|
33
|
+
|
|
34
|
+
1. Open Draken on **localhost or trusted HTTPS**. Plain LAN HTTP normally cannot access the microphone.
|
|
35
|
+
2. **Sync with Draken** finishes importing each discovered file's captured prefix, prepares the briefing and searchable history, then opens its call. Import errors stop preparation instead of silently freezing an old prefix. On an existing sync, **Call Draken** stays disabled until both are ready. If imported history has changed, use **Prepare history** first. An already-ready sync also offers **Refresh history** to capture later work without rebuilding its frozen briefing.
|
|
36
|
+
3. Any needed history download/indexing happens on the sync page, before a call can start. Progress and **Cancel preparation** are available there; the microphone remains off. Once ready, start the call and allow microphone access. A failed or cancelled preparation does not request permission, and if the page is hidden when preparation finishes, start the call again explicitly. You can also type if microphone permission is unavailable.
|
|
37
|
+
4. Speaker-safe mode pauses input during replies. Use **Stop reply** to speak, or enable **Headphone mode** to allow spoken interruption. Headphones are recommended.
|
|
38
|
+
5. **Mute** releases the microphone tracks. **Stop reply** cuts playback locally and asks the provider to stop; it does not prove immediate remote cancellation. **End call** stops capture/playback and keeps the text history.
|
|
39
|
+
|
|
40
|
+
Capture follows a transient browser action, never a URL flag. Reloading or opening `/syncs/:id` does not restart the microphone. Failed preparation, a hidden page, denied permission or an ended connection requires explicit recovery. There is no automatic reconnect or fallback voice engine.
|
|
41
|
+
|
|
42
|
+
Reply waiting is owned by the server's identified user transcript and pending-answer events. Unkeyed WebRTC user events can arrive late and must not switch an already pending reply back to listening, erase its waiting caption, or restart a settled reply. A lookup acknowledgement such as “I’ll check what’s recorded” is not meant to end the answer. Draken keeps the question pending and can automatically resume ChatGPT speech when its context arrives; you should not need to ask “have you checked?” Quiet captions in the dragon scene show **[Thinking...]**, **[Hmmm...]** and **[Hmmmmmm...]** during a pending reply, including silence after an acknowledgement. They change every five seconds without animation. **[Checking...]** and **[Looking that up...]** are used only while the local history worker reports fresh lookup activity; these labels are not proof of a match or exhaustive search. These are visual waiting cues—not the model’s private thoughts, spoken messages, a percentage or an ETA. They are never saved in the transcript or sent to the model. The separate waiting banner and elapsed-wait timer have been removed. Stop, a newer question, interruption, or ending the call cancels the old pending continuation. There is at most one automatic completion cue per question—not a retry loop or a fabricated user message. A failed lookup must be disclosed; a failed or silent continuation produces a visible notice instead of silently retrying.
|
|
43
|
+
|
|
44
|
+
Work questions use original project evidence and preserve the project across follow-ups; old conversation recall remains available when explicitly requested. History is captured at the displayed preparation cutoff, not observed live. The helper can refine a lookup or read a longer H source. Each turn allows three distinct lookups, with source packets bounded to 7,000 UTF-8 bytes (the native context envelope is bounded to 8 KiB). Supplied source IDs belong to that turn; they are not proof that each generated claim was verified. The larger text-chat reconciliation packet and bounded pi answer-repair pass do not apply to streaming native voice; this call path retains its existing lookup budget. See [MEMORY.md](MEMORY.md) for retrieval limits.
|
|
45
|
+
|
|
46
|
+
One call may be active at a time, with a 30-minute limit, at most 60 user messages and a 90-second disconnect timeout. These are resource limits, not spending guarantees. A new call cannot start until helper cleanup is confirmed. The browser chooses its reservation UUID before sending creation, so End can release a reservation even if the create response is lost. If End overtakes creation, the server retains a bounded cancellation marker for five minutes; an already-created ID can never be reused. Network loss can still require the disconnect timeout or explicit End previous call.
|
|
47
|
+
|
|
48
|
+
## Evidence, records and recap
|
|
49
|
+
|
|
50
|
+
- Voice questions do **not** start pi, local transcription or local synthesis. The call receives a bounded briefing, saved notes and source excerpts. Explicit source/history questions can request more data from the same frozen snapshot. Calls use bounded semantic + keyword retrieval across retained older records, using the local index described in [MEMORY.md](MEMORY.md). The local model/index must be prepared before calling is enabled; first preparation may take minutes. During the call, retrieval uses that prepared cutoff and verifies original sources without building new corpus embeddings. Expand **Conversation & details** for the full transcript, sources and any later history progress. Optional **Settings → Automatically index history** prepares that same call/search history in idle batches of at least 64 changed source records; it never starts capture, calls or provider summaries. Smaller batches wait for explicit preparation, and keep Call disabled if history is not ready. This block starts collapsed for every call; its progress polling reads metadata only. Those dated excerpts also go to ChatGPT; they are not new snapshot evidence. The embedding runtime is text-only and is not a replacement speech engine.
|
|
51
|
+
- The read-only lookup service is not a coding model or a general web search. Tool-execution and approval requests are denied. Calls cannot edit files, deploy work, save decisions by model instruction, finish syncs or advance coverage.
|
|
52
|
+
- Speech may paraphrase. **Sources supplied** means context was given to the model, not that every spoken claim was verified. Responses are not held for whole-answer JSON validation before playback.
|
|
53
|
+
- History stores ordered user/assistant messages with generated/interrupted labels. It does not invent question–answer pairs, exact played words, human hearing or agreement. Historical records from the retired engine retain their original playback reports and are labelled separately.
|
|
54
|
+
- No raw microphone recording is persisted locally. Text, source references and call status are stored in the private SQLite database. There is no retention/purge UI yet.
|
|
55
|
+
- Ending the call does not mark the sync reviewed. Closing the call UI requests a short text recap through pi using the sync's cheaper summary model. This is separate from live audio; a browser exit cannot guarantee the request is sent or completes. You can explicitly refresh the recap later.
|
|
56
|
+
|
|
57
|
+
See [the native implementation guide](voice/realtime/README.md) for packet limits, helper restrictions, recall rules and verification details. Provider retention and exact subscription accounting are not promised by Draken.
|
|
58
|
+
|
|
59
|
+
## Animated dragon
|
|
60
|
+
|
|
61
|
+
The local 3D dragon follows received audio energy, not exact words or phonemes. Its drawing code cannot capture audio, call a model or change records. Silence and stopped playback close its mouth. Drawing failure leaves a still image without disabling the call.
|
|
62
|
+
|
|
63
|
+
Live subtitles appear over the bottom of the call scene, labelled **You** or **Draken**. They show a bounded window of the latest transcript, not word-timed audio alignment; the complete text remains in the collapsed **Conversation & details** block. Captions also work over the static fallback image. Errors and recovery buttons remain visible outside that block. There is no animation-control overlay. The separate `/persona.html` preview uses a stored sample without microphone access, sign-in or model use. See [PERSONA.md](PERSONA.md).
|
|
64
|
+
|
|
65
|
+
## LAN microphone access
|
|
66
|
+
|
|
67
|
+
Use an existing **trusted HTTPS reverse proxy** preserving Host/Origin, or the built-in TLS listener. For the latter, the globally installed npm package includes a certificate helper. It requires **OpenSSL** on PATH. In Bash or PowerShell, run:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npm --prefix "$(npm root -g)/draken" run voice:tls -- --host 192.168.1.20
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use your actual server address. This runs the helper from the installed package; no repository clone or build is needed.
|
|
74
|
+
|
|
75
|
+
This creates a private local certificate authority and a server certificate, then prints settings like:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
DRAKEN_HTTPS_PORT=44433
|
|
79
|
+
DRAKEN_TLS_CERT=/absolute/path/to/draken-server.crt
|
|
80
|
+
DRAKEN_TLS_KEY=/absolute/path/to/draken-server.key
|
|
81
|
+
DRAKEN_TLS_CA=/absolute/path/to/draken-local-root.crt
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Export them alongside your existing authenticated LAN configuration and restart Draken while idle. `.env` is not loaded automatically. The command does not change firewall rules, install system trust, change dashboard credentials or expose Draken to the internet.
|
|
85
|
+
|
|
86
|
+
### One-time browser trust
|
|
87
|
+
|
|
88
|
+
In the voice card, open **First-time browser setup** and download the public certificate using your dashboard login. Compare its fingerprint with the TLS setup output. Trust **only your own** `draken-local-root.crt`:
|
|
89
|
+
|
|
90
|
+
- **Windows:** open the certificate → Install Certificate → Current User → Trusted Root Certification Authorities.
|
|
91
|
+
- **macOS:** import into the login keychain → open its Trust section → Always Trust.
|
|
92
|
+
- **Firefox:** Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import; trust it to identify websites.
|
|
93
|
+
- **Chromium/Linux:** use your browser/platform certificate manager. Firefox trust settings do not necessarily apply to Chromium.
|
|
94
|
+
|
|
95
|
+
Restart the browser if needed, visit `https://your-server:44433`, sign in and allow the microphone when starting a call. HTTPS is a separate browser origin, so an HTTP login is not automatically transferred. Dismissing a certificate warning is not the supported setup.
|
|
96
|
+
|
|
97
|
+
Keep both `.key` files private. The authenticated download route re-encodes only the public certificate. Rerunning TLS setup preserves the CA and reuses valid matching certificates; it renews certificates near expiry or with changed hostnames. There is no renewal daemon.
|
|
98
|
+
|
|
99
|
+
### SSH alternative
|
|
100
|
+
|
|
101
|
+
If you already have trusted SSH access, forward Draken to your own localhost:
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
ssh -N -L 40333:192.168.1.20:40333 your-user@192.168.1.20
|
|
105
|
+
# Open http://localhost:40333 on the client computer.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The localhost browser exception permits microphone access; SSH encrypts the connection. Dashboard authentication is still required for an authenticated server.
|
|
109
|
+
|
|
110
|
+
## Server settings
|
|
111
|
+
|
|
112
|
+
| Variable | Purpose |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `DRAKEN_CODEX_BIN`, `DRAKEN_CODEX_HOME` | Trusted operator/test overrides for the pinned helper and its account directory |
|
|
115
|
+
| `DRAKEN_HTTPS_PORT` | Optional second listener |
|
|
116
|
+
| `DRAKEN_TLS_CERT`, `DRAKEN_TLS_KEY` | Certificate and key for that listener |
|
|
117
|
+
| `DRAKEN_TLS_CA` | Optional public certificate download |
|
|
118
|
+
| `DRAKEN_TLS_DIR` | TLS setup output; defaults to `<data dir>/runtime/tls` |
|
|
119
|
+
|
|
120
|
+
There are no per-call model selectors or API keys. Native helper version and native-auth checks still apply to operator overrides.
|
|
121
|
+
|
|
122
|
+
## Verification and limits
|
|
123
|
+
|
|
124
|
+
`draken voice status` checks local helper/sign-in metadata. It does not establish provider access, usable audio, microphone quality, speaker echo, Bluetooth behavior or support for every browser/device. Test those explicitly with your intended account and device.
|
|
125
|
+
|
|
126
|
+
Automated checks and optional real-provider probes are documented in [CONTRIBUTING.md](CONTRIBUTING.md#voice-qualification). They are contributor tools, not installation prerequisites. Ordinary tests use temporary synthetic records and audio; real-provider probes require explicit consent and are not part of the ordinary suite.
|
|
@@ -5,7 +5,7 @@ export interface AuthConfig {
|
|
|
5
5
|
jwtSecret: string;
|
|
6
6
|
tokenExpiry: string;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
interface JwtPayload {
|
|
9
9
|
username: string;
|
|
10
10
|
iat: number;
|
|
11
11
|
exp: number;
|
|
@@ -13,6 +13,7 @@ export interface JwtPayload {
|
|
|
13
13
|
export interface AuthenticatedRequest extends Request {
|
|
14
14
|
user?: JwtPayload;
|
|
15
15
|
}
|
|
16
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
16
17
|
export declare function isNoAuthMode(): boolean;
|
|
17
18
|
export declare function getAuthConfig(): AuthConfig | null;
|
|
18
19
|
export declare function validateAuthConfig(): void;
|
|
@@ -20,4 +21,5 @@ export declare function isAuthEnabled(): boolean;
|
|
|
20
21
|
export declare function authMiddleware(req: AuthenticatedRequest, res: Response, next: NextFunction): void;
|
|
21
22
|
export declare function generateToken(username: string): string;
|
|
22
23
|
export declare function validateCredentials(username: string, password: string): boolean;
|
|
24
|
+
export {};
|
|
23
25
|
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG1D,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAID,wBAAgB,YAAY,IAAI,OAAO,CAStC;AAKD,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CA6BjD;AAGD,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAGD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAGD,wBAAgB,cAAc,CAAC,GAAG,EAAE,oBAAoB,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CA2BjG;AAGD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAStD;AAGD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQ/E"}
|
package/dist/auth/middleware.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isLoopbackHost = isLoopbackHost;
|
|
6
7
|
exports.isNoAuthMode = isNoAuthMode;
|
|
7
8
|
exports.getAuthConfig = getAuthConfig;
|
|
8
9
|
exports.validateAuthConfig = validateAuthConfig;
|
|
@@ -11,15 +12,28 @@ exports.authMiddleware = authMiddleware;
|
|
|
11
12
|
exports.generateToken = generateToken;
|
|
12
13
|
exports.validateCredentials = validateCredentials;
|
|
13
14
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
14
|
-
|
|
15
|
+
function isLoopbackHost(host) {
|
|
16
|
+
return ['127.0.0.1', 'localhost', '::1'].includes(host);
|
|
17
|
+
}
|
|
18
|
+
// A plain local launch needs no account setup. Explicit credentials keep their
|
|
19
|
+
// existing meaning, and non-loopback bindings never default to anonymous access.
|
|
15
20
|
function isNoAuthMode() {
|
|
16
|
-
|
|
21
|
+
const override = process.env.DRAKEN_NO_AUTH;
|
|
22
|
+
if (override !== undefined) {
|
|
23
|
+
if (override === 'true')
|
|
24
|
+
return true;
|
|
25
|
+
if (override === 'false')
|
|
26
|
+
return false;
|
|
27
|
+
throw new Error('DRAKEN_NO_AUTH must be true or false, or unset for automatic local mode');
|
|
28
|
+
}
|
|
29
|
+
const credentialsConfigured = Boolean(process.env.DRAKEN_USERNAME || process.env.DRAKEN_PASSWORD || process.env.DRAKEN_JWT_SECRET);
|
|
30
|
+
return isLoopbackHost(process.env.DRAKEN_HOST || '127.0.0.1') && !credentialsConfigured;
|
|
17
31
|
}
|
|
18
32
|
// Get auth configuration from environment variables
|
|
19
33
|
// Returns null only if NO_AUTH mode is enabled
|
|
20
34
|
// Throws error if auth is required but not properly configured
|
|
21
35
|
function getAuthConfig() {
|
|
22
|
-
//
|
|
36
|
+
// Loopback defaults to no login; an explicit override is also supported.
|
|
23
37
|
if (isNoAuthMode()) {
|
|
24
38
|
return null;
|
|
25
39
|
}
|
|
@@ -36,7 +50,7 @@ function getAuthConfig() {
|
|
|
36
50
|
missing.push('DRAKEN_JWT_SECRET');
|
|
37
51
|
if (missing.length > 0) {
|
|
38
52
|
throw new Error(`Authentication is required. Missing environment variables: ${missing.join(', ')}\n` +
|
|
39
|
-
`Set these variables or
|
|
53
|
+
`Set these variables for authenticated access, or use a loopback bind without credentials for local-only access.`);
|
|
40
54
|
}
|
|
41
55
|
return {
|
|
42
56
|
username: username,
|
|
@@ -48,7 +62,7 @@ function getAuthConfig() {
|
|
|
48
62
|
// Validate auth config on startup (call this early in server initialization)
|
|
49
63
|
function validateAuthConfig() {
|
|
50
64
|
if (isNoAuthMode()) {
|
|
51
|
-
console.log('
|
|
65
|
+
console.log('Local mode: no dashboard login (loopback only).');
|
|
52
66
|
return;
|
|
53
67
|
}
|
|
54
68
|
// This will throw if config is invalid
|
|
@@ -66,17 +80,8 @@ function authMiddleware(req, res, next) {
|
|
|
66
80
|
return next();
|
|
67
81
|
}
|
|
68
82
|
const config = getAuthConfig();
|
|
69
|
-
// Get token from Authorization header or query param (for SSE endpoints)
|
|
70
83
|
const authHeader = req.headers.authorization;
|
|
71
|
-
const
|
|
72
|
-
let token = null;
|
|
73
|
-
if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
74
|
-
token = authHeader.substring(7); // Remove 'Bearer ' prefix
|
|
75
|
-
}
|
|
76
|
-
else if (queryToken) {
|
|
77
|
-
// Allow token via query param for SSE (EventSource doesn't support headers)
|
|
78
|
-
token = queryToken;
|
|
79
|
-
}
|
|
84
|
+
const token = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : null;
|
|
80
85
|
if (!token) {
|
|
81
86
|
res.status(401).json({ error: 'Authentication required', code: 'NO_TOKEN' });
|
|
82
87
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/auth/middleware.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -37,125 +37,89 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
38
|
};
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
const path_1 = __importDefault(require("path"));
|
|
41
40
|
const fs_1 = __importDefault(require("fs"));
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
async function checkForUpdates() {
|
|
50
|
-
const dataDir = process.env.DRAKEN_DATA_DIR || path_1.default.join(os_1.default.homedir(), '.draken');
|
|
51
|
-
const cacheFile = path_1.default.join(dataDir, '.update-check');
|
|
52
|
-
// Check cache (24 hour TTL)
|
|
53
|
-
try {
|
|
54
|
-
if (fs_1.default.existsSync(cacheFile)) {
|
|
55
|
-
const cache = JSON.parse(fs_1.default.readFileSync(cacheFile, 'utf-8'));
|
|
56
|
-
const age = Date.now() - cache.timestamp;
|
|
57
|
-
if (age < 24 * 60 * 60 * 1000) {
|
|
58
|
-
// Cache still valid
|
|
59
|
-
if (cache.latest && cache.latest !== currentVersion) {
|
|
60
|
-
showUpdateMessage(cache.latest);
|
|
61
|
-
}
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch { }
|
|
67
|
-
// Fetch latest version from npm
|
|
68
|
-
return new Promise((resolve) => {
|
|
69
|
-
const req = https_1.default.get('https://registry.npmjs.org/draken/latest', { timeout: 3000 }, (res) => {
|
|
70
|
-
let data = '';
|
|
71
|
-
res.on('data', chunk => data += chunk);
|
|
72
|
-
res.on('end', () => {
|
|
73
|
-
try {
|
|
74
|
-
const latest = JSON.parse(data).version;
|
|
75
|
-
// Save to cache
|
|
76
|
-
if (!fs_1.default.existsSync(dataDir)) {
|
|
77
|
-
fs_1.default.mkdirSync(dataDir, { recursive: true });
|
|
78
|
-
}
|
|
79
|
-
fs_1.default.writeFileSync(cacheFile, JSON.stringify({ latest, timestamp: Date.now() }));
|
|
80
|
-
if (latest !== currentVersion) {
|
|
81
|
-
showUpdateMessage(latest);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch { }
|
|
85
|
-
resolve();
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
req.on('error', () => resolve());
|
|
89
|
-
req.on('timeout', () => { req.destroy(); resolve(); });
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
function showUpdateMessage(latest) {
|
|
93
|
-
console.log(`\n 📦 Update available: ${currentVersion} → ${latest}`);
|
|
94
|
-
console.log(` Run: npm i -g draken@latest\n`);
|
|
95
|
-
}
|
|
96
|
-
// Handle --version and --help before anything else
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const server_1 = require("./server");
|
|
43
|
+
const server_state_1 = require("./server-state");
|
|
44
|
+
const server_status_1 = require("./server-status");
|
|
45
|
+
const launcher_1 = require("./tray/launcher");
|
|
46
|
+
const setup_1 = require("./pi/setup");
|
|
47
|
+
const version = JSON.parse(fs_1.default.readFileSync(path_1.default.join(__dirname, '../package.json'), 'utf8')).version;
|
|
97
48
|
const args = process.argv.slice(2);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
49
|
+
async function main() {
|
|
50
|
+
if (!args.length)
|
|
51
|
+
return (0, server_1.startServer)();
|
|
52
|
+
if (args.length === 1 && args[0] === 'tray')
|
|
53
|
+
return (0, launcher_1.launchTray)();
|
|
54
|
+
if (args.length === 1 && args[0] === '--tray-server' && process.send)
|
|
55
|
+
return (0, server_1.startServer)(true);
|
|
56
|
+
if (args.length === 1 && args[0] === '--tray-worker' && process.send) {
|
|
57
|
+
const { runTrayWorker } = await Promise.resolve().then(() => __importStar(require('./tray/worker')));
|
|
58
|
+
return runTrayWorker();
|
|
59
|
+
}
|
|
60
|
+
if (args.length === 1 && ['--version', '-v'].includes(args[0])) {
|
|
61
|
+
console.log(`draken ${version}`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (args.length === 1 && ['--help', '-h'].includes(args[0])) {
|
|
65
|
+
console.log(`Draken ${version} — read-only sync across pi, Codex and Claude sessions
|
|
109
66
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
67
|
+
Usage:
|
|
68
|
+
draken Start the server in this terminal; Ctrl+C stops it
|
|
69
|
+
draken tray Background tray companion (macOS / Windows desktop)
|
|
70
|
+
draken status Find and check this data directory's last server
|
|
71
|
+
draken doctor Check pi/model credential configuration, without inference
|
|
72
|
+
draken setup [--yes] Install and select Draken's private, pinned pi runtime
|
|
73
|
+
draken login Open pi's own /login interface for the selected runtime
|
|
74
|
+
draken voice setup Install the pinned native voice helper
|
|
75
|
+
draken voice login Separate official ChatGPT voice sign-in
|
|
76
|
+
draken voice status Check native helper/sign-in metadata
|
|
113
77
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
DRAKEN_NO_AUTH Set to 'true' to disable auth
|
|
119
|
-
DRAKEN_PORT Server port (default: 40333)
|
|
120
|
-
DRAKEN_DATA_DIR Data directory (default: ~/.draken)
|
|
78
|
+
First use: draken setup → draken login → draken voice setup → draken voice login
|
|
79
|
+
Then run draken, open its printed URL, and choose Settings → Agents & sessions.
|
|
80
|
+
Existing configured pi works without a private install. No provider authentication
|
|
81
|
+
is reimplemented by Draken. Installing the npm package does not start a server.
|
|
121
82
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
83
|
+
Run setup/login as the server's user with the same environment:
|
|
84
|
+
DRAKEN_DATA_DIR Private state (default: ~/.draken)
|
|
85
|
+
DRAKEN_PI_BIN Explicit pi executable; overrides private selection
|
|
86
|
+
PI_CODING_AGENT_DIR Existing/external pi config; managed pi is isolated
|
|
87
|
+
DRAKEN_PI_SUMMARY_MODEL Summary model (default: openai/gpt-6-luna)
|
|
88
|
+
DRAKEN_PI_FINAL_MODEL Final model (default: openai/gpt-6-astra)
|
|
89
|
+
DRAKEN_PI_MODEL Legacy final-model fallback
|
|
90
|
+
DRAKEN_PI_SESSIONS_DIR Pi history source, not the summarization runtime
|
|
91
|
+
DRAKEN_CODEX_SESSIONS_DIR / DRAKEN_CLAUDE_SESSIONS_DIR
|
|
92
|
+
Optional history roots; enable in Settings
|
|
93
|
+
DRAKEN_HOST / DRAKEN_PORT Bind address/port (default: 127.0.0.1:40333)
|
|
125
94
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
// Check for required environment variables
|
|
133
|
-
const noAuth = process.env.DRAKEN_NO_AUTH === 'true';
|
|
134
|
-
if (!noAuth) {
|
|
135
|
-
const required = ['DRAKEN_USERNAME', 'DRAKEN_PASSWORD', 'DRAKEN_JWT_SECRET'];
|
|
136
|
-
const missing = required.filter(key => !process.env[key]);
|
|
137
|
-
if (missing.length > 0) {
|
|
138
|
-
console.log('\n Draken - Claude Code Dashboard\n');
|
|
139
|
-
console.log(' Authentication is required. Set these environment variables:');
|
|
140
|
-
missing.forEach(key => console.log(` - ${key}`));
|
|
141
|
-
console.log('\n Or disable auth for local development:');
|
|
142
|
-
console.log(' DRAKEN_NO_AUTH=true npx draken\n');
|
|
143
|
-
process.exit(1);
|
|
95
|
+
Loopback needs no dashboard login. LAN bindings require authentication:
|
|
96
|
+
DRAKEN_USERNAME / DRAKEN_PASSWORD / DRAKEN_JWT_SECRET; use trusted HTTPS.
|
|
97
|
+
DRAKEN_NO_AUTH=false also requires dashboard login on loopback.
|
|
98
|
+
Scanning works without pi; summarization needs pi and model credentials.
|
|
99
|
+
Native voice has a separate account. No startup action captures audio or calls models.`);
|
|
100
|
+
return;
|
|
144
101
|
}
|
|
102
|
+
if (args[0] === 'setup' && (args.length === 1 || args.length === 2 && args[1] === '--yes'))
|
|
103
|
+
return (0, setup_1.installPi)(args[1] === '--yes');
|
|
104
|
+
if (args[0] === 'login' && args.length === 1)
|
|
105
|
+
return (0, setup_1.loginPi)();
|
|
106
|
+
if (args[0] === 'doctor' && args.length === 1)
|
|
107
|
+
return (0, setup_1.doctor)();
|
|
108
|
+
if (args[0] === 'voice' && args.length === 2)
|
|
109
|
+
return (0, setup_1.voiceSetup)(args[1]);
|
|
110
|
+
if (args[0] === 'status' && args.length === 1) {
|
|
111
|
+
const target = (0, server_state_1.serverTarget)(), url = target.url;
|
|
112
|
+
try {
|
|
113
|
+
await (0, server_status_1.probeServer)(target);
|
|
114
|
+
console.log(`Draken is responding at ${url}.\nOpen ${target.open}\nThis checks connectivity${target.instance ? ' and the saved server instance' : ''}, not summary/voice readiness. Use draken doctor for pi setup.`);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
console.error(`Draken was not confirmed at ${url}. It may be stopped, or the saved address belongs to an old instance. Start it with draken, or check the server log. If you use a custom data directory, set DRAKEN_DATA_DIR to the same directory.`);
|
|
118
|
+
process.exitCode = 1;
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`Unknown arguments: ${args.join(' ')}. Use draken --help.`);
|
|
145
123
|
}
|
|
146
|
-
|
|
147
|
-
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || path_1.default.join(os_1.default.homedir(), '.claude');
|
|
148
|
-
const hasOAuth = fs_1.default.existsSync(path_1.default.join(claudeConfigDir, '.credentials.json'));
|
|
149
|
-
const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
|
|
150
|
-
if (!hasOAuth && !hasApiKey) {
|
|
151
|
-
console.log('\n Draken - Claude Code Dashboard\n');
|
|
152
|
-
console.log(' Claude authentication required. Choose one:');
|
|
153
|
-
console.log(' 1. Run: claude login');
|
|
154
|
-
console.log(' 2. Set: ANTHROPIC_API_KEY=your-key\n');
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
// Check for updates in background (non-blocking)
|
|
158
|
-
checkForUpdates();
|
|
159
|
-
// Import and start the server
|
|
160
|
-
Promise.resolve().then(() => __importStar(require('./server')));
|
|
124
|
+
void main().catch(error => { console.error(error instanceof Error ? error.message : 'Draken could not complete the command.'); process.exitCode = 1; });
|
|
161
125
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4CAAoB;AACpB,gDAAwB;AACxB,qCAAuC;AACvC,iDAA8C;AAC9C,mDAA8C;AAC9C,8CAA6C;AAC7C,sCAAoE;AAEpE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACrG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAA,oBAAW,GAAE,CAAC;IACvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO,IAAA,qBAAU,GAAE,CAAC;IACjE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,IAAI,OAAO,CAAC,IAAI;QAAE,OAAO,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;IAC/F,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACrE,MAAM,EAAE,aAAa,EAAE,GAAG,wDAAa,eAAe,GAAC,CAAC;QACxD,OAAO,aAAa,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAAC,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QAAC,OAAO;IAAC,CAAC;IAC7G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uFAkCsD,CAAC,CAAC;QACrF,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,IAAA,iBAAS,EAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAClI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAA,eAAO,GAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAA,cAAM,GAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAA,kBAAU,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAA,2BAAY,GAAE,EAAE,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,IAAA,2BAAW,EAAC,MAAM,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,2BAA2B,GAAG,WAAW,MAAM,CAAC,IAAI,6BAA6B,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,EAAE,gEAAgE,CAAC,CAAC;QACxN,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,qMAAqM,CAAC,CAAC;YAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QAAC,CAAC;QACzR,OAAO;IACT,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAC9E,CAAC;AACD,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
/** Runs inside initSchema's transaction, before any generic schema statements.
|
|
3
|
+
* ALTER TABLE preserves row IDs, foreign keys and AUTOINCREMENT high-water marks.
|
|
4
|
+
* There are deliberately no writable pi_* aliases or copied session tables. */
|
|
5
|
+
export declare function renameAgentTables(db: Database.Database): void;
|
|
6
|
+
export declare function migrateAgents(db: Database.Database): void;
|
|
7
|
+
//# sourceMappingURL=agent-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-migration.d.ts","sourceRoot":"","sources":["../../src/db/agent-migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C;;+EAE+E;AAC/E,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAM7D;AACD,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAezD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renameAgentTables = renameAgentTables;
|
|
4
|
+
exports.migrateAgents = migrateAgents;
|
|
5
|
+
/** Runs inside initSchema's transaction, before any generic schema statements.
|
|
6
|
+
* ALTER TABLE preserves row IDs, foreign keys and AUTOINCREMENT high-water marks.
|
|
7
|
+
* There are deliberately no writable pi_* aliases or copied session tables. */
|
|
8
|
+
function renameAgentTables(db) {
|
|
9
|
+
const has = (name) => Boolean(db.prepare("SELECT 1 FROM sqlite_schema WHERE type='table' AND name=?").get(name));
|
|
10
|
+
if (has('pi_sessions') || has('pi_entries')) {
|
|
11
|
+
if (!has('pi_sessions') || !has('pi_entries') || has('agent_sessions') || has('agent_entries'))
|
|
12
|
+
throw new Error('Ambiguous agent schema; existing data was not changed');
|
|
13
|
+
db.exec('ALTER TABLE pi_sessions RENAME TO agent_sessions; ALTER TABLE pi_entries RENAME TO agent_entries; DROP INDEX IF EXISTS pi_entries_pending; DROP INDEX IF EXISTS pi_entries_event');
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function migrateAgents(db) {
|
|
17
|
+
const marker = db.prepare("SELECT value FROM sync_settings WHERE key='source_schema'").get()?.value;
|
|
18
|
+
if (marker && marker !== 'agents-v1')
|
|
19
|
+
throw new Error('Unknown agent source schema; existing data was not changed');
|
|
20
|
+
db.exec(`CREATE TABLE IF NOT EXISTS agent_sources(id TEXT PRIMARY KEY, enabled INTEGER NOT NULL CHECK(enabled IN (0,1)));
|
|
21
|
+
INSERT OR IGNORE INTO agent_sources VALUES('pi',1),('codex',0),('claude',0);`);
|
|
22
|
+
const columns = new Set(db.pragma('table_info(agent_sessions)').map(row => row.name));
|
|
23
|
+
if (!columns.has('agent'))
|
|
24
|
+
db.exec("ALTER TABLE agent_sessions ADD COLUMN agent TEXT NOT NULL DEFAULT 'pi'");
|
|
25
|
+
if (!columns.has('external_id')) {
|
|
26
|
+
db.exec('ALTER TABLE agent_sessions ADD COLUMN external_id TEXT');
|
|
27
|
+
db.exec('UPDATE agent_sessions SET external_id=id');
|
|
28
|
+
}
|
|
29
|
+
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS agent_sessions_identity ON agent_sessions(agent,external_id)');
|
|
30
|
+
if (!db.pragma('table_info(agent_entries)').some(row => row.name === 'parser_version'))
|
|
31
|
+
db.exec('ALTER TABLE agent_entries ADD COLUMN parser_version INTEGER NOT NULL DEFAULT 1');
|
|
32
|
+
db.prepare("INSERT OR IGNORE INTO sync_settings VALUES('source_schema','agents-v1')").run();
|
|
33
|
+
if (db.pragma('foreign_key_check').length)
|
|
34
|
+
throw new Error('Agent migration failed foreign-key verification');
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=agent-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-migration.js","sourceRoot":"","sources":["../../src/db/agent-migration.ts"],"names":[],"mappings":";;AAKA,8CAMC;AACD,sCAeC;AAzBD;;+EAE+E;AAC/E,SAAgB,iBAAiB,CAAC,EAAqB;IACrD,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACzH,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,eAAe,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACzK,EAAE,CAAC,IAAI,CAAC,kLAAkL,CAAC,CAAC;IAC9L,CAAC;AACH,CAAC;AACD,SAAgB,aAAa,CAAC,EAAqB;IACjD,MAAM,MAAM,GAAI,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC,GAAG,EAAU,EAAE,KAAK,CAAC;IAC7G,IAAI,MAAM,IAAI,MAAM,KAAK,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IACpH,EAAE,CAAC,IAAI,CAAC;iFACuE,CAAC,CAAC;IACjF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAE,EAAE,CAAC,MAAM,CAAC,4BAA4B,CAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3G,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,EAAE,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IAC7G,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;QAChC,EAAE,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QAClE,EAAE,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACtD,CAAC;IACD,EAAE,CAAC,IAAI,CAAC,gGAAgG,CAAC,CAAC;IAC1G,IAAI,CAAE,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,gBAAgB,CAAC;QAAE,EAAE,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAC;IACvM,EAAE,CAAC,OAAO,CAAC,yEAAyE,CAAC,CAAC,GAAG,EAAE,CAAC;IAC5F,IAAK,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAe,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AAC/H,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { Evidence } from '../types';
|
|
3
|
+
import { type NormalizationVersion } from '../sync/normalize';
|
|
4
|
+
import { type RecordPointer, type NormalizationCache } from '../sync/jsonl';
|
|
5
|
+
import { type RootInput, type SourceIdentity } from '../sources/registry';
|
|
6
|
+
export interface FrozenPointer {
|
|
7
|
+
version: 1 | 2;
|
|
8
|
+
source?: SourceIdentity;
|
|
9
|
+
original: RecordPointer;
|
|
10
|
+
normalization: NormalizationVersion;
|
|
11
|
+
edit?: RecordPointer & {
|
|
12
|
+
entry_id: string;
|
|
13
|
+
event_key: string;
|
|
14
|
+
normalization: NormalizationVersion;
|
|
15
|
+
};
|
|
16
|
+
clip?: {
|
|
17
|
+
limit: number;
|
|
18
|
+
normalization: NormalizationVersion;
|
|
19
|
+
};
|
|
20
|
+
text_hash: string;
|
|
21
|
+
legacy_edit_match?: true;
|
|
22
|
+
}
|
|
23
|
+
export declare const recordPointer: (row: RecordPointer) => RecordPointer;
|
|
24
|
+
export declare function encodeEvidence(item: Evidence, pointer: FrozenPointer): string;
|
|
25
|
+
/** Frozen membership, attribution and projection; original bytes stay in pi.
|
|
26
|
+
* Share one reader per snapshot/request rather than reopening a file per item. */
|
|
27
|
+
export declare class EvidenceReader {
|
|
28
|
+
private db;
|
|
29
|
+
private reader;
|
|
30
|
+
private paths;
|
|
31
|
+
constructor(db: Database.Database, root?: RootInput, cache?: NormalizationCache);
|
|
32
|
+
project(item: Evidence, pointer: FrozenPointer): string;
|
|
33
|
+
read(value: string | Record<string, any>, tolerateUnavailable?: boolean): Evidence;
|
|
34
|
+
freeze(item: Evidence): string;
|
|
35
|
+
close(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../src/db/evidence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAgC,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5F,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC1F,OAAO,EAA4C,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGpH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IACf,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,oBAAoB,CAAC;IACpC,IAAI,CAAC,EAAE,aAAa,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,oBAAoB,CAAA;KAAE,CAAC;IACpG,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,oBAAoB,CAAA;KAAE,CAAC;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,IAAI,CAAC;CAC1B;AAGD,eAAO,MAAM,aAAa,GAAI,KAAK,aAAa,KAAG,aAAqH,CAAC;AACzK,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAG7E;AAED;kFACkF;AAClF,qBAAa,cAAc;IAGb,OAAO,CAAC,EAAE;IAFtB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAyC;gBAClC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAE,SAA4B,EAAE,KAAK,CAAC,EAAE,kBAAkB;IACzG,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM;IA2BvD,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,mBAAmB,UAAQ,GAAG,QAAQ;IAYhF,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM;IAkB9B,KAAK;CACN"}
|