@knowzai/cli 0.1.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/LICENSE +21 -0
- package/assets/portable/.env.example +250 -0
- package/assets/portable/docker-compose.yml +444 -0
- package/assets/portable/postgres-initdb/00-databases-and-extensions.sql +16 -0
- package/assets/portable/releases.json +37 -0
- package/assets/portable/runtime-contract.json +149 -0
- package/bin/run.js +4 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/base-command.d.ts +47 -0
- package/dist/base-command.d.ts.map +1 -0
- package/dist/base-command.js +98 -0
- package/dist/base-command.js.map +1 -0
- package/dist/commands/activate.d.ts +39 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +103 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/ask.d.ts +14 -0
- package/dist/commands/ask.d.ts.map +1 -0
- package/dist/commands/ask.js +33 -0
- package/dist/commands/ask.js.map +1 -0
- package/dist/commands/auth/status.d.ts +7 -0
- package/dist/commands/auth/status.d.ts.map +1 -0
- package/dist/commands/auth/status.js +26 -0
- package/dist/commands/auth/status.js.map +1 -0
- package/dist/commands/backup.d.ts +15 -0
- package/dist/commands/backup.d.ts.map +1 -0
- package/dist/commands/backup.js +52 -0
- package/dist/commands/backup.js.map +1 -0
- package/dist/commands/capture/observe.d.ts +23 -0
- package/dist/commands/capture/observe.d.ts.map +1 -0
- package/dist/commands/capture/observe.js +68 -0
- package/dist/commands/capture/observe.js.map +1 -0
- package/dist/commands/capture/seal.d.ts +27 -0
- package/dist/commands/capture/seal.d.ts.map +1 -0
- package/dist/commands/capture/seal.js +144 -0
- package/dist/commands/capture/seal.js.map +1 -0
- package/dist/commands/capture/status.d.ts +33 -0
- package/dist/commands/capture/status.d.ts.map +1 -0
- package/dist/commands/capture/status.js +52 -0
- package/dist/commands/capture/status.js.map +1 -0
- package/dist/commands/chat.d.ts +21 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +142 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/cmek/decrypt.d.ts +13 -0
- package/dist/commands/cmek/decrypt.d.ts.map +1 -0
- package/dist/commands/cmek/decrypt.js +25 -0
- package/dist/commands/cmek/decrypt.js.map +1 -0
- package/dist/commands/cmek/encrypt.d.ts +15 -0
- package/dist/commands/cmek/encrypt.d.ts.map +1 -0
- package/dist/commands/cmek/encrypt.js +26 -0
- package/dist/commands/cmek/encrypt.js.map +1 -0
- package/dist/commands/cmek/init.d.ts +13 -0
- package/dist/commands/cmek/init.d.ts.map +1 -0
- package/dist/commands/cmek/init.js +27 -0
- package/dist/commands/cmek/init.js.map +1 -0
- package/dist/commands/cmek/status.d.ts +11 -0
- package/dist/commands/cmek/status.d.ts.map +1 -0
- package/dist/commands/cmek/status.js +23 -0
- package/dist/commands/cmek/status.js.map +1 -0
- package/dist/commands/completion.d.ts +13 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +19 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/config/get.d.ts +13 -0
- package/dist/commands/config/get.d.ts.map +1 -0
- package/dist/commands/config/get.js +28 -0
- package/dist/commands/config/get.js.map +1 -0
- package/dist/commands/config/list.d.ts +7 -0
- package/dist/commands/config/list.d.ts.map +1 -0
- package/dist/commands/config/list.js +28 -0
- package/dist/commands/config/list.js.map +1 -0
- package/dist/commands/config/path.d.ts +9 -0
- package/dist/commands/config/path.d.ts.map +1 -0
- package/dist/commands/config/path.js +15 -0
- package/dist/commands/config/path.js.map +1 -0
- package/dist/commands/config/set.d.ts +16 -0
- package/dist/commands/config/set.d.ts.map +1 -0
- package/dist/commands/config/set.js +36 -0
- package/dist/commands/config/set.js.map +1 -0
- package/dist/commands/doctor.d.ts +56 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +151 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/down.d.ts +30 -0
- package/dist/commands/down.d.ts.map +1 -0
- package/dist/commands/down.js +20 -0
- package/dist/commands/down.js.map +1 -0
- package/dist/commands/entities/find.d.ts +16 -0
- package/dist/commands/entities/find.d.ts.map +1 -0
- package/dist/commands/entities/find.js +27 -0
- package/dist/commands/entities/find.js.map +1 -0
- package/dist/commands/hooks/install.d.ts +19 -0
- package/dist/commands/hooks/install.d.ts.map +1 -0
- package/dist/commands/hooks/install.js +53 -0
- package/dist/commands/hooks/install.js.map +1 -0
- package/dist/commands/index/graph.d.ts +11 -0
- package/dist/commands/index/graph.d.ts.map +1 -0
- package/dist/commands/index/graph.js +31 -0
- package/dist/commands/index/graph.js.map +1 -0
- package/dist/commands/index/scan.d.ts +22 -0
- package/dist/commands/index/scan.d.ts.map +1 -0
- package/dist/commands/index/scan.js +48 -0
- package/dist/commands/index/scan.js.map +1 -0
- package/dist/commands/index/search.d.ts +18 -0
- package/dist/commands/index/search.d.ts.map +1 -0
- package/dist/commands/index/search.js +40 -0
- package/dist/commands/index/search.js.map +1 -0
- package/dist/commands/ingest/add.d.ts +15 -0
- package/dist/commands/ingest/add.d.ts.map +1 -0
- package/dist/commands/ingest/add.js +50 -0
- package/dist/commands/ingest/add.js.map +1 -0
- package/dist/commands/knowledge/amend.d.ts +19 -0
- package/dist/commands/knowledge/amend.d.ts.map +1 -0
- package/dist/commands/knowledge/amend.js +27 -0
- package/dist/commands/knowledge/amend.js.map +1 -0
- package/dist/commands/knowledge/comment.d.ts +16 -0
- package/dist/commands/knowledge/comment.d.ts.map +1 -0
- package/dist/commands/knowledge/comment.js +27 -0
- package/dist/commands/knowledge/comment.js.map +1 -0
- package/dist/commands/knowledge/comments.d.ts +11 -0
- package/dist/commands/knowledge/comments.d.ts.map +1 -0
- package/dist/commands/knowledge/comments.js +20 -0
- package/dist/commands/knowledge/comments.js.map +1 -0
- package/dist/commands/knowledge/create.d.ts +18 -0
- package/dist/commands/knowledge/create.d.ts.map +1 -0
- package/dist/commands/knowledge/create.js +45 -0
- package/dist/commands/knowledge/create.js.map +1 -0
- package/dist/commands/knowledge/delete.d.ts +14 -0
- package/dist/commands/knowledge/delete.d.ts.map +1 -0
- package/dist/commands/knowledge/delete.js +30 -0
- package/dist/commands/knowledge/delete.js.map +1 -0
- package/dist/commands/knowledge/get.d.ts +13 -0
- package/dist/commands/knowledge/get.d.ts.map +1 -0
- package/dist/commands/knowledge/get.js +20 -0
- package/dist/commands/knowledge/get.js.map +1 -0
- package/dist/commands/knowledge/list.d.ts +13 -0
- package/dist/commands/knowledge/list.d.ts.map +1 -0
- package/dist/commands/knowledge/list.js +31 -0
- package/dist/commands/knowledge/list.js.map +1 -0
- package/dist/commands/knowledge/status.d.ts +11 -0
- package/dist/commands/knowledge/status.d.ts.map +1 -0
- package/dist/commands/knowledge/status.js +23 -0
- package/dist/commands/knowledge/status.js.map +1 -0
- package/dist/commands/knowledge/update.d.ts +16 -0
- package/dist/commands/knowledge/update.d.ts.map +1 -0
- package/dist/commands/knowledge/update.js +32 -0
- package/dist/commands/knowledge/update.js.map +1 -0
- package/dist/commands/knowledge/versions.d.ts +11 -0
- package/dist/commands/knowledge/versions.d.ts.map +1 -0
- package/dist/commands/knowledge/versions.js +22 -0
- package/dist/commands/knowledge/versions.js.map +1 -0
- package/dist/commands/local/info.d.ts +17 -0
- package/dist/commands/local/info.d.ts.map +1 -0
- package/dist/commands/local/info.js +26 -0
- package/dist/commands/local/info.js.map +1 -0
- package/dist/commands/local/init.d.ts +16 -0
- package/dist/commands/local/init.d.ts.map +1 -0
- package/dist/commands/local/init.js +31 -0
- package/dist/commands/local/init.js.map +1 -0
- package/dist/commands/local/list.d.ts +13 -0
- package/dist/commands/local/list.d.ts.map +1 -0
- package/dist/commands/local/list.js +29 -0
- package/dist/commands/local/list.js.map +1 -0
- package/dist/commands/local/reset.d.ts +12 -0
- package/dist/commands/local/reset.d.ts.map +1 -0
- package/dist/commands/local/reset.js +34 -0
- package/dist/commands/local/reset.js.map +1 -0
- package/dist/commands/local/show.d.ts +15 -0
- package/dist/commands/local/show.d.ts.map +1 -0
- package/dist/commands/local/show.js +33 -0
- package/dist/commands/local/show.js.map +1 -0
- package/dist/commands/login.d.ts +23 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +139 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +11 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +23 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/menu.d.ts +10 -0
- package/dist/commands/menu.d.ts.map +1 -0
- package/dist/commands/menu.js +50 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/pg/destroy.d.ts +13 -0
- package/dist/commands/pg/destroy.d.ts.map +1 -0
- package/dist/commands/pg/destroy.js +36 -0
- package/dist/commands/pg/destroy.js.map +1 -0
- package/dist/commands/pg/down.d.ts +12 -0
- package/dist/commands/pg/down.d.ts.map +1 -0
- package/dist/commands/pg/down.js +20 -0
- package/dist/commands/pg/down.js.map +1 -0
- package/dist/commands/pg/status.d.ts +13 -0
- package/dist/commands/pg/status.d.ts.map +1 -0
- package/dist/commands/pg/status.js +28 -0
- package/dist/commands/pg/status.js.map +1 -0
- package/dist/commands/pg/up.d.ts +13 -0
- package/dist/commands/pg/up.d.ts.map +1 -0
- package/dist/commands/pg/up.js +34 -0
- package/dist/commands/pg/up.js.map +1 -0
- package/dist/commands/platform/destroy.d.ts +18 -0
- package/dist/commands/platform/destroy.d.ts.map +1 -0
- package/dist/commands/platform/destroy.js +41 -0
- package/dist/commands/platform/destroy.js.map +1 -0
- package/dist/commands/platform/doctor.d.ts +11 -0
- package/dist/commands/platform/doctor.d.ts.map +1 -0
- package/dist/commands/platform/doctor.js +18 -0
- package/dist/commands/platform/doctor.js.map +1 -0
- package/dist/commands/platform/down.d.ts +26 -0
- package/dist/commands/platform/down.d.ts.map +1 -0
- package/dist/commands/platform/down.js +16 -0
- package/dist/commands/platform/down.js.map +1 -0
- package/dist/commands/platform/logs.d.ts +26 -0
- package/dist/commands/platform/logs.d.ts.map +1 -0
- package/dist/commands/platform/logs.js +24 -0
- package/dist/commands/platform/logs.js.map +1 -0
- package/dist/commands/platform/reset.d.ts +26 -0
- package/dist/commands/platform/reset.d.ts.map +1 -0
- package/dist/commands/platform/reset.js +49 -0
- package/dist/commands/platform/reset.js.map +1 -0
- package/dist/commands/platform/setup.d.ts +24 -0
- package/dist/commands/platform/setup.d.ts.map +1 -0
- package/dist/commands/platform/setup.js +21 -0
- package/dist/commands/platform/setup.js.map +1 -0
- package/dist/commands/platform/status.d.ts +28 -0
- package/dist/commands/platform/status.d.ts.map +1 -0
- package/dist/commands/platform/status.js +37 -0
- package/dist/commands/platform/status.js.map +1 -0
- package/dist/commands/platform/up.d.ts +42 -0
- package/dist/commands/platform/up.d.ts.map +1 -0
- package/dist/commands/platform/up.js +22 -0
- package/dist/commands/platform/up.js.map +1 -0
- package/dist/commands/platform/upgrade.d.ts +14 -0
- package/dist/commands/platform/upgrade.d.ts.map +1 -0
- package/dist/commands/platform/upgrade.js +22 -0
- package/dist/commands/platform/upgrade.js.map +1 -0
- package/dist/commands/profile/add.d.ts +18 -0
- package/dist/commands/profile/add.d.ts.map +1 -0
- package/dist/commands/profile/add.js +26 -0
- package/dist/commands/profile/add.js.map +1 -0
- package/dist/commands/profile/list.d.ts +10 -0
- package/dist/commands/profile/list.d.ts.map +1 -0
- package/dist/commands/profile/list.js +20 -0
- package/dist/commands/profile/list.js.map +1 -0
- package/dist/commands/profile/remove.d.ts +15 -0
- package/dist/commands/profile/remove.d.ts.map +1 -0
- package/dist/commands/profile/remove.js +19 -0
- package/dist/commands/profile/remove.js.map +1 -0
- package/dist/commands/profile/use.d.ts +12 -0
- package/dist/commands/profile/use.d.ts.map +1 -0
- package/dist/commands/profile/use.js +18 -0
- package/dist/commands/profile/use.js.map +1 -0
- package/dist/commands/recall.d.ts +29 -0
- package/dist/commands/recall.d.ts.map +1 -0
- package/dist/commands/recall.js +94 -0
- package/dist/commands/recall.js.map +1 -0
- package/dist/commands/repo/context.d.ts +24 -0
- package/dist/commands/repo/context.d.ts.map +1 -0
- package/dist/commands/repo/context.js +52 -0
- package/dist/commands/repo/context.js.map +1 -0
- package/dist/commands/repo/graph.d.ts +24 -0
- package/dist/commands/repo/graph.d.ts.map +1 -0
- package/dist/commands/repo/graph.js +72 -0
- package/dist/commands/repo/graph.js.map +1 -0
- package/dist/commands/repo/index/index.d.ts +28 -0
- package/dist/commands/repo/index/index.d.ts.map +1 -0
- package/dist/commands/repo/index/index.js +76 -0
- package/dist/commands/repo/index/index.js.map +1 -0
- package/dist/commands/repo/search.d.ts +22 -0
- package/dist/commands/repo/search.d.ts.map +1 -0
- package/dist/commands/repo/search.js +50 -0
- package/dist/commands/repo/search.js.map +1 -0
- package/dist/commands/repo/setup.d.ts +41 -0
- package/dist/commands/repo/setup.d.ts.map +1 -0
- package/dist/commands/repo/setup.js +144 -0
- package/dist/commands/repo/setup.js.map +1 -0
- package/dist/commands/repo/status.d.ts +31 -0
- package/dist/commands/repo/status.d.ts.map +1 -0
- package/dist/commands/repo/status.js +60 -0
- package/dist/commands/repo/status.js.map +1 -0
- package/dist/commands/restore.d.ts +16 -0
- package/dist/commands/restore.d.ts.map +1 -0
- package/dist/commands/restore.js +53 -0
- package/dist/commands/restore.js.map +1 -0
- package/dist/commands/search.d.ts +14 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +32 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/setup.d.ts +24 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +21 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/stats.d.ts +6 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +16 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/status.d.ts +20 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +33 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync/conflicts.d.ts +14 -0
- package/dist/commands/sync/conflicts.d.ts.map +1 -0
- package/dist/commands/sync/conflicts.js +23 -0
- package/dist/commands/sync/conflicts.js.map +1 -0
- package/dist/commands/sync/pull.d.ts +13 -0
- package/dist/commands/sync/pull.d.ts.map +1 -0
- package/dist/commands/sync/pull.js +26 -0
- package/dist/commands/sync/pull.js.map +1 -0
- package/dist/commands/sync/push.d.ts +13 -0
- package/dist/commands/sync/push.d.ts.map +1 -0
- package/dist/commands/sync/push.js +26 -0
- package/dist/commands/sync/push.js.map +1 -0
- package/dist/commands/sync/recover.d.ts +16 -0
- package/dist/commands/sync/recover.d.ts.map +1 -0
- package/dist/commands/sync/recover.js +29 -0
- package/dist/commands/sync/recover.js.map +1 -0
- package/dist/commands/sync/resolve.d.ts +21 -0
- package/dist/commands/sync/resolve.d.ts.map +1 -0
- package/dist/commands/sync/resolve.js +38 -0
- package/dist/commands/sync/resolve.js.map +1 -0
- package/dist/commands/sync/run.d.ts +13 -0
- package/dist/commands/sync/run.d.ts.map +1 -0
- package/dist/commands/sync/run.js +26 -0
- package/dist/commands/sync/run.js.map +1 -0
- package/dist/commands/sync/status.d.ts +13 -0
- package/dist/commands/sync/status.d.ts.map +1 -0
- package/dist/commands/sync/status.js +28 -0
- package/dist/commands/sync/status.js.map +1 -0
- package/dist/commands/topics/list.d.ts +11 -0
- package/dist/commands/topics/list.d.ts.map +1 -0
- package/dist/commands/topics/list.js +20 -0
- package/dist/commands/topics/list.js.map +1 -0
- package/dist/commands/tui.d.ts +10 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +124 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/commands/up.d.ts +108 -0
- package/dist/commands/up.d.ts.map +1 -0
- package/dist/commands/up.js +210 -0
- package/dist/commands/up.js.map +1 -0
- package/dist/commands/vault/contents.d.ts +14 -0
- package/dist/commands/vault/contents.d.ts.map +1 -0
- package/dist/commands/vault/contents.js +24 -0
- package/dist/commands/vault/contents.js.map +1 -0
- package/dist/commands/vault/create.d.ts +15 -0
- package/dist/commands/vault/create.d.ts.map +1 -0
- package/dist/commands/vault/create.js +26 -0
- package/dist/commands/vault/create.js.map +1 -0
- package/dist/commands/vault/get.d.ts +10 -0
- package/dist/commands/vault/get.d.ts.map +1 -0
- package/dist/commands/vault/get.js +25 -0
- package/dist/commands/vault/get.js.map +1 -0
- package/dist/commands/vault/list.d.ts +7 -0
- package/dist/commands/vault/list.d.ts.map +1 -0
- package/dist/commands/vault/list.js +17 -0
- package/dist/commands/vault/list.js.map +1 -0
- package/dist/commands/web.d.ts +14 -0
- package/dist/commands/web.d.ts.map +1 -0
- package/dist/commands/web.js +50 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +24 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/hooks/init/launch-menu.d.ts +10 -0
- package/dist/hooks/init/launch-menu.d.ts.map +1 -0
- package/dist/hooks/init/launch-menu.js +11 -0
- package/dist/hooks/init/launch-menu.js.map +1 -0
- package/dist/lib/activate.d.ts +92 -0
- package/dist/lib/activate.d.ts.map +1 -0
- package/dist/lib/activate.js +292 -0
- package/dist/lib/activate.js.map +1 -0
- package/dist/lib/browser.d.ts +30 -0
- package/dist/lib/browser.d.ts.map +1 -0
- package/dist/lib/browser.js +45 -0
- package/dist/lib/browser.js.map +1 -0
- package/dist/lib/chat.d.ts +41 -0
- package/dist/lib/chat.d.ts.map +1 -0
- package/dist/lib/chat.js +63 -0
- package/dist/lib/chat.js.map +1 -0
- package/dist/lib/claude-hooks.d.ts +34 -0
- package/dist/lib/claude-hooks.d.ts.map +1 -0
- package/dist/lib/claude-hooks.js +85 -0
- package/dist/lib/claude-hooks.js.map +1 -0
- package/dist/lib/completion.d.ts +9 -0
- package/dist/lib/completion.d.ts.map +1 -0
- package/dist/lib/completion.js +57 -0
- package/dist/lib/completion.js.map +1 -0
- package/dist/lib/container-engine.d.ts +45 -0
- package/dist/lib/container-engine.d.ts.map +1 -0
- package/dist/lib/container-engine.js +348 -0
- package/dist/lib/container-engine.js.map +1 -0
- package/dist/lib/content.d.ts +9 -0
- package/dist/lib/content.d.ts.map +1 -0
- package/dist/lib/content.js +20 -0
- package/dist/lib/content.js.map +1 -0
- package/dist/lib/doctor-fixture.d.ts +8 -0
- package/dist/lib/doctor-fixture.d.ts.map +1 -0
- package/dist/lib/doctor-fixture.js +50 -0
- package/dist/lib/doctor-fixture.js.map +1 -0
- package/dist/lib/embedding-guard.d.ts +34 -0
- package/dist/lib/embedding-guard.d.ts.map +1 -0
- package/dist/lib/embedding-guard.js +50 -0
- package/dist/lib/embedding-guard.js.map +1 -0
- package/dist/lib/hook-io.d.ts +24 -0
- package/dist/lib/hook-io.d.ts.map +1 -0
- package/dist/lib/hook-io.js +73 -0
- package/dist/lib/hook-io.js.map +1 -0
- package/dist/lib/ingest.d.ts +24 -0
- package/dist/lib/ingest.d.ts.map +1 -0
- package/dist/lib/ingest.js +44 -0
- package/dist/lib/ingest.js.map +1 -0
- package/dist/lib/login.d.ts +40 -0
- package/dist/lib/login.d.ts.map +1 -0
- package/dist/lib/login.js +56 -0
- package/dist/lib/login.js.map +1 -0
- package/dist/lib/pending-captures.d.ts +25 -0
- package/dist/lib/pending-captures.d.ts.map +1 -0
- package/dist/lib/pending-captures.js +143 -0
- package/dist/lib/pending-captures.js.map +1 -0
- package/dist/lib/platform-backup.d.ts +110 -0
- package/dist/lib/platform-backup.d.ts.map +1 -0
- package/dist/lib/platform-backup.js +579 -0
- package/dist/lib/platform-backup.js.map +1 -0
- package/dist/lib/platform-command-shared.d.ts +132 -0
- package/dist/lib/platform-command-shared.d.ts.map +1 -0
- package/dist/lib/platform-command-shared.js +159 -0
- package/dist/lib/platform-command-shared.js.map +1 -0
- package/dist/lib/platform-frontdoor-runtime.d.ts +33 -0
- package/dist/lib/platform-frontdoor-runtime.d.ts.map +1 -0
- package/dist/lib/platform-frontdoor-runtime.js +285 -0
- package/dist/lib/platform-frontdoor-runtime.js.map +1 -0
- package/dist/lib/platform-frontdoor.d.ts +155 -0
- package/dist/lib/platform-frontdoor.d.ts.map +1 -0
- package/dist/lib/platform-frontdoor.js +467 -0
- package/dist/lib/platform-frontdoor.js.map +1 -0
- package/dist/lib/platform-image-source.d.ts +81 -0
- package/dist/lib/platform-image-source.d.ts.map +1 -0
- package/dist/lib/platform-image-source.js +143 -0
- package/dist/lib/platform-image-source.js.map +1 -0
- package/dist/lib/platform-lifecycle.d.ts +112 -0
- package/dist/lib/platform-lifecycle.d.ts.map +1 -0
- package/dist/lib/platform-lifecycle.js +725 -0
- package/dist/lib/platform-lifecycle.js.map +1 -0
- package/dist/lib/platform-onboarding.d.ts +128 -0
- package/dist/lib/platform-onboarding.d.ts.map +1 -0
- package/dist/lib/platform-onboarding.js +227 -0
- package/dist/lib/platform-onboarding.js.map +1 -0
- package/dist/lib/platform-preflight.d.ts +48 -0
- package/dist/lib/platform-preflight.d.ts.map +1 -0
- package/dist/lib/platform-preflight.js +90 -0
- package/dist/lib/platform-preflight.js.map +1 -0
- package/dist/lib/platform-profile-purge.d.ts +18 -0
- package/dist/lib/platform-profile-purge.d.ts.map +1 -0
- package/dist/lib/platform-profile-purge.js +26 -0
- package/dist/lib/platform-profile-purge.js.map +1 -0
- package/dist/lib/platform-provider-fields.d.ts +2 -0
- package/dist/lib/platform-provider-fields.d.ts.map +1 -0
- package/dist/lib/platform-provider-fields.js +2 -0
- package/dist/lib/platform-provider-fields.js.map +1 -0
- package/dist/lib/platform-provider-probe.d.ts +75 -0
- package/dist/lib/platform-provider-probe.d.ts.map +1 -0
- package/dist/lib/platform-provider-probe.js +781 -0
- package/dist/lib/platform-provider-probe.js.map +1 -0
- package/dist/lib/platform-provider-prompt.d.ts +118 -0
- package/dist/lib/platform-provider-prompt.d.ts.map +1 -0
- package/dist/lib/platform-provider-prompt.js +245 -0
- package/dist/lib/platform-provider-prompt.js.map +1 -0
- package/dist/lib/platform-release-manifest.d.ts +34 -0
- package/dist/lib/platform-release-manifest.d.ts.map +1 -0
- package/dist/lib/platform-release-manifest.js +100 -0
- package/dist/lib/platform-release-manifest.js.map +1 -0
- package/dist/lib/platform-runtime.d.ts +212 -0
- package/dist/lib/platform-runtime.d.ts.map +1 -0
- package/dist/lib/platform-runtime.js +866 -0
- package/dist/lib/platform-runtime.js.map +1 -0
- package/dist/lib/poll.d.ts +9 -0
- package/dist/lib/poll.d.ts.map +1 -0
- package/dist/lib/poll.js +18 -0
- package/dist/lib/poll.js.map +1 -0
- package/dist/lib/prompt.d.ts +7 -0
- package/dist/lib/prompt.d.ts.map +1 -0
- package/dist/lib/prompt.js +28 -0
- package/dist/lib/prompt.js.map +1 -0
- package/dist/lib/provider-presets.d.ts +108 -0
- package/dist/lib/provider-presets.d.ts.map +1 -0
- package/dist/lib/provider-presets.js +184 -0
- package/dist/lib/provider-presets.js.map +1 -0
- package/dist/lib/recall.d.ts +32 -0
- package/dist/lib/recall.d.ts.map +1 -0
- package/dist/lib/recall.js +69 -0
- package/dist/lib/recall.js.map +1 -0
- package/dist/lib/redact.d.ts +41 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +130 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/render.d.ts +55 -0
- package/dist/lib/render.d.ts.map +1 -0
- package/dist/lib/render.js +172 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/repo-binding.d.ts +53 -0
- package/dist/lib/repo-binding.d.ts.map +1 -0
- package/dist/lib/repo-binding.js +127 -0
- package/dist/lib/repo-binding.js.map +1 -0
- package/dist/lib/repo-command-support.d.ts +18 -0
- package/dist/lib/repo-command-support.d.ts.map +1 -0
- package/dist/lib/repo-command-support.js +54 -0
- package/dist/lib/repo-command-support.js.map +1 -0
- package/dist/lib/seal-core.d.ts +34 -0
- package/dist/lib/seal-core.d.ts.map +1 -0
- package/dist/lib/seal-core.js +154 -0
- package/dist/lib/seal-core.js.map +1 -0
- package/dist/lib/setup-console.d.ts +46 -0
- package/dist/lib/setup-console.d.ts.map +1 -0
- package/dist/lib/setup-console.js +191 -0
- package/dist/lib/setup-console.js.map +1 -0
- package/dist/lib/setup-page.d.ts +21 -0
- package/dist/lib/setup-page.d.ts.map +1 -0
- package/dist/lib/setup-page.js +656 -0
- package/dist/lib/setup-page.js.map +1 -0
- package/dist/lib/setup-plan.d.ts +52 -0
- package/dist/lib/setup-plan.d.ts.map +1 -0
- package/dist/lib/setup-plan.js +154 -0
- package/dist/lib/setup-plan.js.map +1 -0
- package/dist/lib/setup-server.d.ts +71 -0
- package/dist/lib/setup-server.d.ts.map +1 -0
- package/dist/lib/setup-server.js +936 -0
- package/dist/lib/setup-server.js.map +1 -0
- package/dist/lib/tui.d.ts +77 -0
- package/dist/lib/tui.d.ts.map +1 -0
- package/dist/lib/tui.js +126 -0
- package/dist/lib/tui.js.map +1 -0
- package/dist/lib/ui.d.ts +23 -0
- package/dist/lib/ui.d.ts.map +1 -0
- package/dist/lib/ui.js +100 -0
- package/dist/lib/ui.js.map +1 -0
- package/dist/lib/vault.d.ts +10 -0
- package/dist/lib/vault.d.ts.map +1 -0
- package/dist/lib/vault.js +18 -0
- package/dist/lib/vault.js.map +1 -0
- package/dist/menu/forms.d.ts +13 -0
- package/dist/menu/forms.d.ts.map +1 -0
- package/dist/menu/forms.js +45 -0
- package/dist/menu/forms.js.map +1 -0
- package/dist/menu/frontends.d.ts +32 -0
- package/dist/menu/frontends.d.ts.map +1 -0
- package/dist/menu/frontends.js +31 -0
- package/dist/menu/frontends.js.map +1 -0
- package/dist/menu/help.d.ts +11 -0
- package/dist/menu/help.d.ts.map +1 -0
- package/dist/menu/help.js +33 -0
- package/dist/menu/help.js.map +1 -0
- package/dist/menu/palette.d.ts +28 -0
- package/dist/menu/palette.d.ts.map +1 -0
- package/dist/menu/palette.js +57 -0
- package/dist/menu/palette.js.map +1 -0
- package/dist/menu/reducer.d.ts +19 -0
- package/dist/menu/reducer.d.ts.map +1 -0
- package/dist/menu/reducer.js +37 -0
- package/dist/menu/reducer.js.map +1 -0
- package/dist/menu/run.d.ts +34 -0
- package/dist/menu/run.d.ts.map +1 -0
- package/dist/menu/run.js +490 -0
- package/dist/menu/run.js.map +1 -0
- package/dist/menu/screens.d.ts +15 -0
- package/dist/menu/screens.d.ts.map +1 -0
- package/dist/menu/screens.js +251 -0
- package/dist/menu/screens.js.map +1 -0
- package/dist/menu/should-launch.d.ts +19 -0
- package/dist/menu/should-launch.d.ts.map +1 -0
- package/dist/menu/should-launch.js +22 -0
- package/dist/menu/should-launch.js.map +1 -0
- package/dist/menu/types.d.ts +95 -0
- package/dist/menu/types.d.ts.map +1 -0
- package/dist/menu/types.js +7 -0
- package/dist/menu/types.js.map +1 -0
- package/oclif.manifest.json +7995 -0
- package/package.json +133 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
import { DEFAULT_PORTABLE_VERSION } from './platform-frontdoor.js';
|
|
2
|
+
import { VERTEX_CHAT_DEFAULT, VERTEX_EMBEDDING_DEFAULT, QWEN3_EMBEDDING_DEFAULT, QWEN3_EMBEDDING_DIMENSIONS } from './platform-provider-probe.js';
|
|
3
|
+
import { OLLAMA_LOOPBACK_ENDPOINT } from './platform-provider-prompt.js';
|
|
4
|
+
import { PROVIDER_ALIAS_OPTIONS, PROVIDER_PRESETS } from './provider-presets.js';
|
|
5
|
+
export function escapeHtml(value) {
|
|
6
|
+
return value
|
|
7
|
+
.replaceAll('&', '&')
|
|
8
|
+
.replaceAll('<', '<')
|
|
9
|
+
.replaceAll('>', '>')
|
|
10
|
+
.replaceAll('"', '"')
|
|
11
|
+
.replaceAll("'", ''');
|
|
12
|
+
}
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
function renderProviderCard(provider, checked) {
|
|
17
|
+
const meta = PROVIDER_PRESETS[provider].display;
|
|
18
|
+
const id = `provider-${provider}`.replace(/[^A-Za-z0-9_-]/g, '-');
|
|
19
|
+
return `<label class="provider-card" for="${escapeHtml(id)}" data-provider-mode="${escapeHtml(provider)}">
|
|
20
|
+
<input id="${escapeHtml(id)}" name="provider" type="radio" value="${escapeHtml(provider)}"${checked ? ' checked' : ''}>
|
|
21
|
+
${meta.icon}<strong>${escapeHtml(meta.title)}</strong><small>${escapeHtml(meta.blurb)}</small>
|
|
22
|
+
</label>`;
|
|
23
|
+
}
|
|
24
|
+
function renderEngineGuide(preflight) {
|
|
25
|
+
const engine = preflight.engine;
|
|
26
|
+
if (!engine)
|
|
27
|
+
return '';
|
|
28
|
+
const machineNeedsHelp = engine.engine === 'podman'
|
|
29
|
+
&& engine.machine !== undefined
|
|
30
|
+
&& engine.machine.state !== 'running';
|
|
31
|
+
if (engine.engine !== 'none' && engine.daemonReachable && !machineNeedsHelp)
|
|
32
|
+
return '';
|
|
33
|
+
const machineHint = machineNeedsHelp
|
|
34
|
+
? `<aside class="banner banner-danger"><div><strong>Podman machine is ${escapeHtml(engine.machine.state)}</strong><span>Run <code>knowz up</code> once to create or start it automatically, then re-check this page.</span></div></aside>`
|
|
35
|
+
: engine.engine === 'docker'
|
|
36
|
+
? '<aside class="banner banner-danger"><div><strong>Docker is installed but not running</strong><span>Start Docker Desktop or the Docker daemon, then re-check.</span></div></aside>'
|
|
37
|
+
: '';
|
|
38
|
+
return `<section class="card" aria-labelledby="engine-setup-title">
|
|
39
|
+
<div class="card-heading"><span class="step-number">!</span><div><h2 id="engine-setup-title">Container engine setup</h2><p>Install either Docker Desktop or Podman Desktop for your operating system.</p></div></div>
|
|
40
|
+
${machineHint}
|
|
41
|
+
<div class="split">
|
|
42
|
+
<div class="banner"><div><strong>macOS</strong><span><a href="https://docs.docker.com/desktop/setup/install/mac-install/" target="_blank" rel="noreferrer">Docker Desktop</a> · <a href="https://podman-desktop.io/downloads/macos" target="_blank" rel="noreferrer">Podman Desktop</a></span></div></div>
|
|
43
|
+
<div class="banner"><div><strong>Windows</strong><span><a href="https://docs.docker.com/desktop/setup/install/windows-install/" target="_blank" rel="noreferrer">Docker Desktop</a> · <a href="https://podman-desktop.io/downloads/windows" target="_blank" rel="noreferrer">Podman Desktop</a></span></div></div>
|
|
44
|
+
<div class="banner"><div><strong>Linux</strong><span><a href="https://docs.docker.com/engine/install/" target="_blank" rel="noreferrer">Docker Engine</a> · <a href="https://podman.io/docs/installation" target="_blank" rel="noreferrer">Podman</a></span></div></div>
|
|
45
|
+
</div>
|
|
46
|
+
<div class="test-row"><a class="button" href="/">Re-check</a><span class="chip">Reloads this local page and runs preflight again.</span></div>
|
|
47
|
+
</section>`;
|
|
48
|
+
}
|
|
49
|
+
/** Pure template composition. Authentication and transport stay in setup-server.ts. */
|
|
50
|
+
export function renderPage(model) {
|
|
51
|
+
const { token, schema, preflight, currentState, defaults, credentialFilePath } = model;
|
|
52
|
+
const tokenLiteral = JSON.stringify(token).replaceAll('<', '\\u003c');
|
|
53
|
+
const schemaLiteral = JSON.stringify(schema).replaceAll('<', '\\u003c');
|
|
54
|
+
const ollamaEndpointSuffixLiteral = JSON.stringify(OLLAMA_LOOPBACK_ENDPOINT.slice('http'.length)).replaceAll('<', '\\u003c');
|
|
55
|
+
// alias -> { preset, fields } prefill map consumed by applyProviderAliasPrefill().
|
|
56
|
+
// Emitted from the shared table so the browser console and the TTY picker seed
|
|
57
|
+
// identical values; prefill NEVER overwrites a field the operator already typed.
|
|
58
|
+
const aliasPrefillLiteral = JSON.stringify(Object.fromEntries(PROVIDER_ALIAS_OPTIONS
|
|
59
|
+
.filter((option) => option.prefill && Object.prototype.hasOwnProperty.call(schema, option.preset))
|
|
60
|
+
.map((option) => [option.alias, { preset: option.preset, fields: option.prefill }]))).replaceAll('<', '\\u003c');
|
|
61
|
+
const vertexChatDefaultLiteral = JSON.stringify(VERTEX_CHAT_DEFAULT).replaceAll('<', '\\u003c');
|
|
62
|
+
const vertexEmbeddingDefaultLiteral = JSON.stringify(VERTEX_EMBEDDING_DEFAULT).replaceAll('<', '\\u003c');
|
|
63
|
+
const qwen3EmbeddingDefaultLiteral = JSON.stringify(QWEN3_EMBEDDING_DEFAULT).replaceAll('<', '\\u003c');
|
|
64
|
+
const qwen3EmbeddingDimsLiteral = JSON.stringify(String(QWEN3_EMBEDDING_DIMENSIONS)).replaceAll('<', '\\u003c');
|
|
65
|
+
const stateRecord = isRecord(currentState) ? currentState : undefined;
|
|
66
|
+
const existingStateLiteral = stateRecord ? 'true' : 'false';
|
|
67
|
+
const checks = preflight.checks.map((check) => `
|
|
68
|
+
<li class="check ${check.ok ? 'check-ok' : 'check-bad'}">
|
|
69
|
+
<span class="check-icon" aria-hidden="true">${check.ok ? '✓' : '!'}</span>
|
|
70
|
+
<span>${escapeHtml(check.ok ? check.label : check.message)}${!check.ok && check.remedy ? `<small>${escapeHtml(check.remedy)}</small>` : ''}</span>
|
|
71
|
+
</li>`).join('');
|
|
72
|
+
const providerFields = Object.entries(schema).flatMap(([provider, fields]) => fields.map((field) => {
|
|
73
|
+
const id = `provider-${provider}-${field.key}`.replace(/[^A-Za-z0-9_-]/g, '-');
|
|
74
|
+
const sharedAttributes = [
|
|
75
|
+
`id="${escapeHtml(id)}"`,
|
|
76
|
+
`name="provider.${escapeHtml(field.key)}"`,
|
|
77
|
+
`data-provider="${escapeHtml(provider)}"`,
|
|
78
|
+
field.required ? 'required aria-required="true"' : '',
|
|
79
|
+
'autocomplete="off"',
|
|
80
|
+
].filter(Boolean).join(' ');
|
|
81
|
+
let control;
|
|
82
|
+
if (!field.secret && !field.locked && field.selectOptions?.length) {
|
|
83
|
+
// Closed value set — render a select with the runtime default preselected.
|
|
84
|
+
const options = field.selectOptions.map((option) => `<option value="${escapeHtml(option)}"${option === field.defaultValue ? ' selected' : ''}>${escapeHtml(option)}</option>`).join('');
|
|
85
|
+
control = `<select ${sharedAttributes}>${options}</select>`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const listId = `${id}-list`;
|
|
89
|
+
const inputAttributes = [
|
|
90
|
+
sharedAttributes,
|
|
91
|
+
`type="${field.secret ? 'password' : field.number ? 'number' : 'text'}"`,
|
|
92
|
+
!field.secret && field.defaultValue !== undefined ? `value="${escapeHtml(field.defaultValue)}"` : '',
|
|
93
|
+
!field.secret && field.suggestions?.length ? `list="${escapeHtml(listId)}"` : '',
|
|
94
|
+
field.locked ? 'readonly aria-readonly="true"' : '',
|
|
95
|
+
].filter(Boolean).join(' ');
|
|
96
|
+
const datalist = !field.secret && field.suggestions?.length
|
|
97
|
+
? `<datalist id="${escapeHtml(listId)}">${field.suggestions.map((suggestion) => `<option value="${escapeHtml(suggestion)}"></option>`).join('')}</datalist>`
|
|
98
|
+
: '';
|
|
99
|
+
control = `<input ${inputAttributes}>${datalist}`;
|
|
100
|
+
}
|
|
101
|
+
const secretAlreadySet = Boolean(field.secret && stateRecord?.provider === provider);
|
|
102
|
+
const secretPosture = secretAlreadySet
|
|
103
|
+
? '<small>Currently set — hidden. Replace by entering a new value.</small>'
|
|
104
|
+
: '';
|
|
105
|
+
return `<div class="field" data-provider-group="${escapeHtml(provider)}"${secretAlreadySet ? ' data-secret-set="1"' : ''} hidden>
|
|
106
|
+
<label for="${escapeHtml(id)}">${escapeHtml(field.label)}${field.required ? '<span class="required" aria-hidden="true"> *</span>' : ''}</label>
|
|
107
|
+
${control}
|
|
108
|
+
${secretPosture}
|
|
109
|
+
</div>`;
|
|
110
|
+
})).join('');
|
|
111
|
+
const providerDisclosures = Object.keys(schema).flatMap((provider) => {
|
|
112
|
+
const disclosure = PROVIDER_PRESETS[provider].disclosure;
|
|
113
|
+
if (!disclosure)
|
|
114
|
+
return [];
|
|
115
|
+
return [`<aside class="banner banner-info" data-provider-group="${escapeHtml(provider)}" hidden><div><strong>Knowz Cloud AI notice</strong>${disclosure.map((line) => `<span>${escapeHtml(line)}</span>`).join('')}</div></aside>`];
|
|
116
|
+
}).join('');
|
|
117
|
+
const cloudActivation = Object.prototype.hasOwnProperty.call(schema, 'knowz-cloud')
|
|
118
|
+
? `<div class="test-row" data-provider-group="knowz-cloud" hidden><button id="activate-cloud-ai" class="button" type="button">Activate with your Knowz account</button><span id="activate-cloud-ai-status" class="chip" aria-live="polite">Or paste an existing kzai_ key below</span></div>`
|
|
119
|
+
: '';
|
|
120
|
+
const existing = stateRecord ? `<aside id="existing-state" class="banner banner-info">
|
|
121
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 8v5m0 3h.01M4.9 19h14.2a2 2 0 0 0 1.7-3L13.7 4a2 2 0 0 0-3.4 0L3.2 16a2 2 0 0 0 1.7 3Z"/></svg>
|
|
122
|
+
<div><strong>Existing stack detected</strong><span>${escapeHtml(String(stateRecord.name ?? 'knowz'))} ${escapeHtml(String(stateRecord.version ?? 'unknown'))} · ${escapeHtml(String(stateRecord.provider ?? 'unknown'))}. Leave reconfigure off to inspect it without changing anything.</span></div>
|
|
123
|
+
</aside>` : '';
|
|
124
|
+
const license = model.licenseStatus ?? { linked: false };
|
|
125
|
+
let upgradeUrl;
|
|
126
|
+
try {
|
|
127
|
+
const candidate = new URL(license.mothershipUrl ?? 'https://api.knowz.io');
|
|
128
|
+
if (candidate.protocol === 'https:' || (candidate.protocol === 'http:' && ['localhost', '127.0.0.1', '::1'].includes(candidate.hostname))) {
|
|
129
|
+
upgradeUrl = `${candidate.toString().replace(/\/$/, '')}/account/plan`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch { /* An invalid configured URL must not become an href. */ }
|
|
133
|
+
const licenseCopy = license.linked
|
|
134
|
+
? `Linked to ${escapeHtml(license.account ?? 'your Knowz account')} — ${escapeHtml(license.displayPlan ?? 'linked plan')}`
|
|
135
|
+
: 'Not linked — run <code>knowz activate</code>';
|
|
136
|
+
const licenseRow = `<aside id="license-status" class="banner banner-info"><div><strong>License</strong><span>${licenseCopy}</span>${license.linked && upgradeUrl ? `<a class="button" href="${escapeHtml(upgradeUrl)}" target="_blank" rel="noreferrer">Upgrade</a>` : ''}</div></aside>`;
|
|
137
|
+
const defaultName = escapeHtml(defaults.name ?? 'knowz');
|
|
138
|
+
const defaultVersion = escapeHtml(defaults.version ?? DEFAULT_PORTABLE_VERSION);
|
|
139
|
+
const defaultApiPort = escapeHtml(String(defaults.ports?.api ?? 5000));
|
|
140
|
+
const defaultWebPort = escapeHtml(String(defaults.ports?.web ?? 3000));
|
|
141
|
+
const defaultMcpPort = escapeHtml(String(defaults.ports?.mcp ?? 3001));
|
|
142
|
+
const defaultPublicSitePort = escapeHtml(String(defaults.ports?.publicSite ?? 3002));
|
|
143
|
+
const defaultMcpEnabled = defaults.components?.mcp !== false;
|
|
144
|
+
const defaultPublicSiteEnabled = defaults.components?.publicSite === true;
|
|
145
|
+
const defaultAccountName = escapeHtml(defaults.account?.name ?? 'Local');
|
|
146
|
+
const defaultAccountEmail = escapeHtml(defaults.account?.email ?? 'local@knowz.local');
|
|
147
|
+
const defaultOrgName = escapeHtml(defaults.orgName ?? '');
|
|
148
|
+
const defaultPublicApiUrl = escapeHtml(defaults.publicUrls?.api ?? '');
|
|
149
|
+
const defaultPublicWebUrl = escapeHtml(defaults.publicUrls?.web ?? '');
|
|
150
|
+
const defaultPublicMcpUrl = escapeHtml(defaults.publicUrls?.mcp ?? '');
|
|
151
|
+
const buildSelected = defaults.imageMode === 'build';
|
|
152
|
+
const filesystemSelected = defaults.storage === 'filesystem';
|
|
153
|
+
const defaultProvider = defaults.provider && Object.prototype.hasOwnProperty.call(schema, defaults.provider)
|
|
154
|
+
? defaults.provider
|
|
155
|
+
: 'offline';
|
|
156
|
+
const providerCards = Object.keys(schema).map((provider) => renderProviderCard(provider, provider === defaultProvider)).join('');
|
|
157
|
+
// Named shortcuts (ollama/openai/lmstudio/vllm) render as their own cards but
|
|
158
|
+
// SUBMIT their backing preset — `value` is the preset, `data-provider-alias`
|
|
159
|
+
// only drives the client-side field prefill. Rendered from the shared table so
|
|
160
|
+
// adding an option in provider-presets lights it up here with no edit.
|
|
161
|
+
// Guarded on the backing preset being present in the schema: a card whose
|
|
162
|
+
// preset was filtered out would submit a value the server rejects.
|
|
163
|
+
const aliasCards = PROVIDER_ALIAS_OPTIONS
|
|
164
|
+
.filter((option) => Object.prototype.hasOwnProperty.call(schema, option.preset))
|
|
165
|
+
.map((option) => {
|
|
166
|
+
const id = `provider-${option.alias}`.replace(/[^A-Za-z0-9_-]/g, '-');
|
|
167
|
+
return `<label class="provider-card" for="${escapeHtml(id)}" data-provider-mode="${escapeHtml(option.preset)}">
|
|
168
|
+
<input id="${escapeHtml(id)}" name="provider" type="radio" data-provider-alias="${escapeHtml(option.alias)}" value="${escapeHtml(option.preset)}">
|
|
169
|
+
${option.display.icon}<strong>${escapeHtml(option.display.title)}</strong><small>${escapeHtml(option.display.blurb)}</small>
|
|
170
|
+
</label>`;
|
|
171
|
+
})
|
|
172
|
+
.join('');
|
|
173
|
+
const preflightOpen = preflight.ok ? '' : ' open';
|
|
174
|
+
const engineGuide = renderEngineGuide(preflight);
|
|
175
|
+
const credentialPath = escapeHtml(credentialFilePath ?? '.env');
|
|
176
|
+
return `<!doctype html>
|
|
177
|
+
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
178
|
+
<title>Knowz local setup</title><style>@font-face{font-family:'Pacifico';font-style:normal;font-weight:400;font-display:swap;src:url(data:font/woff2;base64,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) format('woff2')}
|
|
179
|
+
|
|
180
|
+
/* ── Knowz Portable setup console ──────────────────────────────────────────────────────────────
|
|
181
|
+
Design direction: "engineering paper". This is an installer for a PRIVATE knowledge graph that
|
|
182
|
+
runs on your own machine, so it reads as a precise technical document, not a cloud dashboard.
|
|
183
|
+
Two saturated colours only, each with a fixed job:
|
|
184
|
+
--signal (blue) = intent — actions you can take, the currently selected thing
|
|
185
|
+
--live (teal) = proven — reserved for state VERIFIED at runtime. Never decorative.
|
|
186
|
+
Everything structural is ink + hairline. Monospace is the third type role and carries the
|
|
187
|
+
subject's vernacular: ports, endpoints, versions, hosts.
|
|
188
|
+
Signature: the step markers are graph NODES joined by a spine — setup is literally assembling
|
|
189
|
+
the graph you are about to run. That is why the sequence is numbered: order is real here. */
|
|
190
|
+
:root{
|
|
191
|
+
color-scheme:dark;
|
|
192
|
+
--ink:#E9EDF7;--paper:#080B14;--surface:#0F1420;--surface-raised:#141A28;--surface-soft:#1B2233;
|
|
193
|
+
--edge:#252D40;--edge-strong:#3A4459;--muted:#9AA6BF;
|
|
194
|
+
--signal:#818CF8;--signal-soft:#1B1F3D;--live:#34D399;--live-soft:#0C2A22;
|
|
195
|
+
--danger:#FB7185;--warning:#FBBF24;--success:#34D399;
|
|
196
|
+
/* legacy aliases — existing markup/JS still reference these names */
|
|
197
|
+
--brand:var(--signal);--brand-strong:var(--signal);--teal:var(--live);--focus:var(--signal);
|
|
198
|
+
--bg:var(--paper);--text:var(--ink);--border:var(--edge);--shadow:#01030A;--overlay:#080B14E6;
|
|
199
|
+
--model-on:#34D399;--model-warn:#FBBF24;--model-off:#9AA6BF;
|
|
200
|
+
--model-on-bg:#0C2A22;--model-warn-bg:#3A2D14;--model-off-bg:#1B2233;
|
|
201
|
+
--cap-vision:#818CF8;--cap-function:#C4B5FD;--cap-structured:#34D399;--cap-embedding:#FBBF24;
|
|
202
|
+
--cap-vision-bg:#1B1F3D;--cap-function-bg:#241A3D;--cap-structured-bg:#0C2A22;--cap-embedding-bg:#3A2D14;
|
|
203
|
+
--radius-lg:14px;--radius-md:10px;--radius-sm:8px;--radius-pill:999px;--space:8px;
|
|
204
|
+
--sans:'Inter',system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;--script:'Pacifico','Segoe Script',cursive;
|
|
205
|
+
--mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
|
|
206
|
+
}
|
|
207
|
+
:root[data-theme="light"]{color-scheme:light;--ink:#0A1628;--paper:#F7F9FC;--surface:#FFFFFF;--surface-raised:#FBFCFE;--surface-soft:#EEF3FA;--edge:#DCE4F0;--edge-strong:#C2CEE0;--muted:#5A6B84;--signal:#4F46E5;--signal-soft:#EEF0FE;--live:#0D9488;--live-soft:#E2F5F2;--danger:#C2334A;--warning:#8A5200;--success:#0D9488;--shadow:#93A6C4;--overlay:#F7F9FCE6;--model-on:#0D9488;--model-warn:#8A5200;--model-off:#5A6B84;--model-on-bg:#E2F5F2;--model-warn-bg:#FBF0DC;--model-off-bg:#EEF3FA}
|
|
208
|
+
:root[data-theme="dark"],:root[data-theme="dark"] *{color-scheme:dark}
|
|
209
|
+
:root[data-theme="dark"]{
|
|
210
|
+
--ink:#E8EEF8;--paper:#080D16;--surface:#101725;--surface-raised:#141C2C;--surface-soft:#1B2436;
|
|
211
|
+
--edge:#26314617;--edge:#263146;--edge-strong:#39465F;--muted:#94A4BE;
|
|
212
|
+
--signal:#6E9BFF;--signal-soft:#15224024;--signal-soft:#152240;--live:#3ED6C0;--live-soft:#0E2E2C;
|
|
213
|
+
--danger:#FF8494;--warning:#F0C177;--success:#3ED6C0;
|
|
214
|
+
--shadow:#01040A;--overlay:#080D16E6;
|
|
215
|
+
--model-on:#3ED6C0;--model-warn:#F0C177;--model-off:#94A4BE;
|
|
216
|
+
--model-on-bg:#0E2E2C;--model-warn-bg:#3A2D14;--model-off-bg:#1B2436;
|
|
217
|
+
--cap-vision:#6E9BFF;--cap-function:#B79BFF;--cap-structured:#3ED6C0;--cap-embedding:#F0B36E;
|
|
218
|
+
--cap-vision-bg:#152240;--cap-function-bg:#241A3D;--cap-structured-bg:#0E2E2C;--cap-embedding-bg:#3A2D14;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
*{box-sizing:border-box}
|
|
222
|
+
html{min-width:320px;background:var(--paper)}
|
|
223
|
+
body{margin:0;background:var(--paper);color:var(--ink);font:15px/1.55 var(--sans);overflow-x:hidden;-webkit-font-smoothing:antialiased}
|
|
224
|
+
button,input,select{font:inherit}
|
|
225
|
+
button,a,input,select,summary{outline:none}
|
|
226
|
+
button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,summary:focus-visible{box-shadow:0 0 0 2px var(--paper),0 0 0 4px var(--signal)}
|
|
227
|
+
button{cursor:pointer}button:disabled{cursor:not-allowed}
|
|
228
|
+
.shell{width:min(100% - 32px,780px);margin:0 auto;padding:28px 0 72px}
|
|
229
|
+
|
|
230
|
+
/* ── Brand lockup ─────────────────────────────────────────────────────────────────────────── */
|
|
231
|
+
.wordmark .script{font-family:var(--script);font-size:1.30em;font-weight:400;letter-spacing:0;padding-right:.06em;color:var(--ink)}
|
|
232
|
+
.brand svg{width:24px;height:24px}
|
|
233
|
+
|
|
234
|
+
.statusbar{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:9px}
|
|
235
|
+
.statusbar:empty{display:none}
|
|
236
|
+
.statusbar .banner{margin:0;height:100%}
|
|
237
|
+
|
|
238
|
+
/* ── Wizard rail ──────────────────────────────────────────────────────────────────────────── */
|
|
239
|
+
/* Four steps, so the numbering is a real sequence and the rail is the only place that says so. */
|
|
240
|
+
.rail{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0 0 4px;padding:6px;border:1px solid var(--edge);border-radius:var(--radius-lg);background:var(--surface)}
|
|
241
|
+
.rail-step{display:flex;align-items:center;gap:10px;padding:11px 12px;border:1px solid transparent;border-radius:var(--radius-md);background:transparent;color:var(--muted);text-align:left}
|
|
242
|
+
.rail-step:hover:not(:disabled){background:var(--surface-soft);color:var(--ink)}
|
|
243
|
+
.rail-step:disabled{opacity:.45;cursor:not-allowed}
|
|
244
|
+
.rail-step[data-state="active"]{border-color:var(--signal);background:var(--signal-soft);color:var(--ink)}
|
|
245
|
+
.rail-step[data-state="done"]{color:var(--ink)}
|
|
246
|
+
.rail-num{flex:0 0 auto;width:24px;height:24px;display:grid;place-items:center;border:1.5px solid var(--edge-strong);border-radius:var(--radius-pill);font:11.5px var(--mono);font-weight:700}
|
|
247
|
+
.rail-step[data-state="active"] .rail-num{border-color:var(--signal);color:var(--signal)}
|
|
248
|
+
.rail-step[data-state="done"] .rail-num{border-color:var(--live);color:var(--live);background:var(--live-soft)}
|
|
249
|
+
.rail-step[data-state="done"] .rail-num:after{content:"✓";font-size:11px}
|
|
250
|
+
.rail-step[data-state="done"] .rail-num{font-size:0}
|
|
251
|
+
.rail-text{display:grid;min-width:0}
|
|
252
|
+
.rail-text strong{font-size:13px;font-weight:660;letter-spacing:-.01em}
|
|
253
|
+
.rail-text small{color:var(--muted);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
254
|
+
@media(max-width:760px){.rail-text small{display:none}}
|
|
255
|
+
@media(max-width:560px){.rail{grid-template-columns:repeat(4,1fr);gap:3px}.rail-step{flex-direction:column;gap:5px;padding:9px 4px;text-align:center}.rail-text strong{font-size:11px}}
|
|
256
|
+
|
|
257
|
+
/* ── Wizard panels + nav ──────────────────────────────────────────────────────────────────── */
|
|
258
|
+
.step-panel{display:grid;gap:14px}
|
|
259
|
+
.step-panel[hidden]{display:none}
|
|
260
|
+
.wizard-nav{display:flex;align-items:center;gap:10px;margin-top:2px}
|
|
261
|
+
.wizard-spacer{flex:1}
|
|
262
|
+
.button-inline{width:auto;min-width:150px}
|
|
263
|
+
/* The hero is one line now; the page was too long and the masthead was doing none of the work. */
|
|
264
|
+
.hero{padding:14px 2px 10px}
|
|
265
|
+
.hero h1{margin:9px 0 0;font-size:clamp(20px,2.3vw,25px);font-weight:760;letter-spacing:-.032em;line-height:1.15}
|
|
266
|
+
|
|
267
|
+
/* ── Header ───────────────────────────────────────────────────────────────────────────────── */
|
|
268
|
+
.site-header{position:sticky;top:0;z-index:20;border-bottom:1px solid var(--edge);background:var(--overlay);backdrop-filter:blur(14px) saturate(1.4)}
|
|
269
|
+
.header-inner{width:min(100% - 32px,980px);min-height:60px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}
|
|
270
|
+
.brand{display:flex;align-items:center;gap:9px;font-size:16px;font-weight:750;letter-spacing:-.025em}
|
|
271
|
+
.brand svg{width:26px;height:26px;color:var(--signal);fill:none;stroke:currentColor;stroke-width:1.7}
|
|
272
|
+
.wordmark span{color:var(--muted);font-weight:550}
|
|
273
|
+
.header-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
|
274
|
+
/* The trust chip is the page's promise. Mono + a live dot: this is a fact, not marketing. */
|
|
275
|
+
.trust{padding:5px 11px;display:inline-flex;align-items:center;gap:7px;border:1px solid var(--edge);border-radius:var(--radius-pill);color:var(--muted);font:11.5px var(--mono);letter-spacing:-.01em;background:var(--surface)}
|
|
276
|
+
.trust:before{content:"";width:6px;height:6px;border-radius:50%;background:var(--live);box-shadow:0 0 0 3px var(--live-soft)}
|
|
277
|
+
.icon-button{width:34px;height:34px;padding:7px;display:grid;place-items:center;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface);color:var(--muted)}
|
|
278
|
+
.icon-button:hover{color:var(--ink);border-color:var(--edge-strong)}
|
|
279
|
+
.icon-button svg,.banner svg,.button-icon{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8}
|
|
280
|
+
|
|
281
|
+
/* ── Hero ─────────────────────────────────────────────────────────────────────────────────── */
|
|
282
|
+
.eyebrow-inline{margin:0;display:inline-block;padding:3px 9px;border:1px solid var(--edge);border-radius:var(--radius-pill);color:var(--muted);font:10px var(--mono);font-weight:600;letter-spacing:.13em;text-transform:uppercase}
|
|
283
|
+
|
|
284
|
+
.hero h1 em{font-style:normal;color:var(--signal)}
|
|
285
|
+
/* Signature: the graph this installer is about to stand up. Ambient, drawn once, never loops. */
|
|
286
|
+
/* ── Cards + the graph spine ──────────────────────────────────────────────────────────────── */
|
|
287
|
+
.stack{display:grid;gap:11px}
|
|
288
|
+
.card{position:relative;padding:20px;border:1px solid var(--edge);border-radius:var(--radius-lg);background:var(--surface)}
|
|
289
|
+
.card-heading{display:flex;align-items:flex-start;gap:14px;margin-bottom:18px}
|
|
290
|
+
/* Step markers are graph nodes; the hairline spine joins each to the next. */
|
|
291
|
+
.step-number{position:relative;flex:0 0 auto;width:28px;height:28px;display:grid;place-items:center;border:1.5px solid var(--edge-strong);border-radius:var(--radius-pill);background:var(--surface);color:var(--muted);font:12.5px var(--mono);font-weight:700}
|
|
292
|
+
.card:has(.step-number) .step-number:after{content:"";position:absolute;top:calc(100% + 1.5px);left:50%;width:1px;height:26px;background:linear-gradient(var(--edge-strong),transparent);transform:translateX(-50%)}
|
|
293
|
+
.card:last-of-type .step-number:after{display:none}
|
|
294
|
+
.card-heading h2{margin:0;font-size:17px;font-weight:700;letter-spacing:-.02em}
|
|
295
|
+
.card-heading p{margin:3px 0 0;color:var(--muted);font-size:13px}
|
|
296
|
+
|
|
297
|
+
/* ── Preflight ────────────────────────────────────────────────────────────────────────────── */
|
|
298
|
+
.preflight{padding:0;overflow:hidden}
|
|
299
|
+
.preflight summary{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;cursor:pointer;font-weight:650;font-size:14px}
|
|
300
|
+
.preflight summary::-webkit-details-marker{display:none}
|
|
301
|
+
.preflight-state{font:12px var(--mono);color:var(--live)}
|
|
302
|
+
.preflight:not([open]) .preflight-state:after{content:" · details";color:var(--muted)}
|
|
303
|
+
.checks{list-style:none;margin:0;padding:0 20px 18px;display:grid;gap:9px}
|
|
304
|
+
.check{display:flex;align-items:flex-start;gap:10px;color:var(--muted);font-size:13.5px}
|
|
305
|
+
.check-icon{width:19px;height:19px;display:grid;place-items:center;border-radius:var(--radius-pill);font-weight:800;font-size:11px}
|
|
306
|
+
.check-ok .check-icon{color:var(--live);background:var(--live-soft)}
|
|
307
|
+
.check-bad .check-icon{color:var(--danger);background:var(--surface-soft)}
|
|
308
|
+
.check small{display:block;color:var(--muted)}
|
|
309
|
+
.banner{display:flex;gap:9px;align-items:center;padding:9px 12px;font-size:12.5px;border:1px solid var(--edge);border-radius:var(--radius-md);background:var(--surface-raised);font-size:13.5px}
|
|
310
|
+
.banner svg{flex:0 0 auto;color:var(--signal)}
|
|
311
|
+
.banner strong,.banner span{display:block}
|
|
312
|
+
.banner strong{font-size:12.5px;letter-spacing:-.01em}
|
|
313
|
+
.banner span{color:var(--muted)}
|
|
314
|
+
.banner-danger{border-color:var(--danger);color:var(--danger)}
|
|
315
|
+
|
|
316
|
+
/* ── Provider grid ────────────────────────────────────────────────────────────────────────── */
|
|
317
|
+
.provider-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px}
|
|
318
|
+
.provider-card{position:relative;display:grid;gap:3px;padding:14px 14px 15px;border:1px solid var(--edge);border-radius:var(--radius-md);background:var(--surface-raised);cursor:pointer;transition:border-color .13s ease,background .13s ease}
|
|
319
|
+
.provider-card:hover{border-color:var(--edge-strong);background:var(--surface)}
|
|
320
|
+
.provider-card:has(input:checked){border-color:var(--signal);background:var(--signal-soft)}
|
|
321
|
+
.provider-card:has(input:checked) strong{color:var(--signal)}
|
|
322
|
+
.provider-card input{position:absolute;opacity:0;pointer-events:none}
|
|
323
|
+
.provider-card strong{font-size:13.5px;font-weight:680;letter-spacing:-.015em}
|
|
324
|
+
.provider-card small{color:var(--muted);font-size:12px;line-height:1.4}
|
|
325
|
+
|
|
326
|
+
/* ── Fields ───────────────────────────────────────────────────────────────────────────────── */
|
|
327
|
+
.fields{display:grid;gap:13px;margin-top:17px}
|
|
328
|
+
.field{display:grid;gap:6px}
|
|
329
|
+
.field[hidden]{display:none}
|
|
330
|
+
.field label{font-weight:620;font-size:12.5px;letter-spacing:-.005em}
|
|
331
|
+
.required{color:var(--danger);font-weight:600}
|
|
332
|
+
input,select{width:100%;min-height:42px;padding:10px 12px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink)}
|
|
333
|
+
input:hover,select:hover{border-color:var(--edge-strong)}
|
|
334
|
+
input::placeholder{color:var(--muted);opacity:.75}
|
|
335
|
+
/* Ports, versions and endpoints are data — set them in the utility face. */
|
|
336
|
+
input[name$="Port"],input[name="version"],input[name$=".endpoint"],input[name$=".embeddingDimensions"]{font:14px var(--mono)}
|
|
337
|
+
.split{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
|
338
|
+
.ports{grid-template-columns:repeat(3,1fr)}
|
|
339
|
+
.url-preview{margin:13px 0 0;padding:11px 12px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface-soft);color:var(--muted);font:11.5px/1.7 var(--mono);overflow-wrap:anywhere}
|
|
340
|
+
.choice-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
|
|
341
|
+
.choice{display:flex;align-items:center;gap:10px;padding:11px 13px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface-raised);font-size:13.5px}
|
|
342
|
+
.choice input{width:auto;min-height:auto;accent-color:var(--signal)}
|
|
343
|
+
|
|
344
|
+
/* ── Buttons + chips ──────────────────────────────────────────────────────────────────────── */
|
|
345
|
+
.test-row{margin-top:15px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
|
346
|
+
.button{min-height:40px;padding:9px 15px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border:1px solid var(--edge-strong);border-radius:var(--radius-sm);background:var(--surface);color:var(--ink);font-weight:640;font-size:13.5px;text-decoration:none;transition:border-color .13s ease,background .13s ease}
|
|
347
|
+
.button:hover{border-color:var(--signal);color:var(--signal)}
|
|
348
|
+
.button-primary{width:100%;min-height:52px;margin-top:4px;border-color:transparent;background:var(--signal);color:#fff;font-size:15.5px;font-weight:700;letter-spacing:-.01em;box-shadow:0 10px 24px -14px var(--signal)}
|
|
349
|
+
.button-primary:hover{background:var(--signal);color:#fff;filter:brightness(1.08)}
|
|
350
|
+
.button-quiet{background:transparent}
|
|
351
|
+
.chip{min-height:29px;padding:5px 11px;display:inline-flex;align-items:center;gap:7px;border:1px solid var(--edge);border-radius:var(--radius-pill);color:var(--muted);background:var(--surface);font:12px var(--mono)}
|
|
352
|
+
.chip[data-test-state="testing"],.chip[data-model-test-state="testing"]{color:var(--signal);border-color:var(--signal)}
|
|
353
|
+
.chip[data-test-state="pass"],.chip[data-model-test-state="pass"]{color:var(--live);border-color:var(--live);background:var(--live-soft)}
|
|
354
|
+
.chip[data-test-state="fail"],.chip[data-model-test-state="fail"]{color:var(--danger);border-color:var(--danger)}
|
|
355
|
+
.chip[data-model-test-state="notconfigured"]{color:var(--warning);border-color:var(--warning)}
|
|
356
|
+
.spinner{width:13px;height:13px;border:2px solid var(--edge);border-top-color:var(--signal);border-radius:var(--radius-pill);animation:spin .8s linear infinite}
|
|
357
|
+
|
|
358
|
+
/* ── Models band ──────────────────────────────────────────────────────────────────────────── */
|
|
359
|
+
.models-band{margin-top:22px;padding-top:19px;border-top:1px solid var(--edge)}
|
|
360
|
+
.models-heading{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:12px}
|
|
361
|
+
.models-heading h3{margin:0;font-size:15px;font-weight:700;letter-spacing:-.02em}
|
|
362
|
+
.models-heading span{color:var(--muted);font:11.5px var(--mono)}
|
|
363
|
+
.model-cards{display:grid;grid-template-columns:minmax(0,1fr);gap:10px}
|
|
364
|
+
.model-card{display:grid;gap:12px;padding:16px;border:1px solid var(--edge);border-radius:var(--radius-md);background:var(--surface-raised);min-width:0}
|
|
365
|
+
.model-card.dimmed{opacity:.66}
|
|
366
|
+
.model-head,.model-facts,.model-test{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap}
|
|
367
|
+
.model-title{margin:0;font-size:14.5px;font-weight:680;letter-spacing:-.015em}
|
|
368
|
+
.model-subtitle{display:block;margin-top:3px;color:var(--muted);font:11.5px var(--mono);overflow-wrap:anywhere}
|
|
369
|
+
.model-pill,.tier-label{padding:4px 10px;display:inline-flex;align-items:center;gap:5px;border-radius:var(--radius-pill);font-size:11.5px;font-weight:650}
|
|
370
|
+
.model-pill svg,.capability svg,.model-test button svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.9}
|
|
371
|
+
.model-pill[data-status="ready"]{color:var(--model-on);background:var(--model-on-bg)}
|
|
372
|
+
.model-pill[data-status="needs"]{color:var(--model-warn);background:var(--model-warn-bg)}
|
|
373
|
+
.model-pill[data-status="local"]{color:var(--model-off);background:var(--model-off-bg)}
|
|
374
|
+
.tier-label{color:var(--muted);background:var(--surface-soft)}
|
|
375
|
+
.pricing{color:var(--muted);font-size:12.5px}
|
|
376
|
+
.capabilities{display:flex;gap:7px;flex-wrap:wrap}
|
|
377
|
+
.capability{padding:5px 9px;display:inline-flex;align-items:center;gap:6px;border-radius:var(--radius-sm);font-size:11.5px;font-weight:600}
|
|
378
|
+
.capability[data-cap="vision"]{color:var(--cap-vision);background:var(--cap-vision-bg)}
|
|
379
|
+
.capability[data-cap="function"]{color:var(--cap-function);background:var(--cap-function-bg)}
|
|
380
|
+
.capability[data-cap="structured"]{color:var(--cap-structured);background:var(--cap-structured-bg)}
|
|
381
|
+
.capability[data-cap="embedding"]{color:var(--cap-embedding);background:var(--cap-embedding-bg)}
|
|
382
|
+
.model-test{align-items:center;justify-content:flex-start}
|
|
383
|
+
.model-test .button{min-height:34px;padding:6px 11px;font-size:12.5px}
|
|
384
|
+
.model-test .chip{font-size:11.5px}
|
|
385
|
+
.model-summary{margin:0 0 14px;padding:11px 13px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface-soft);color:var(--muted);font:12px var(--mono)}
|
|
386
|
+
.soft-confirm{margin-top:12px;padding:14px;border:1px solid var(--warning);border-radius:var(--radius-sm);background:var(--surface-raised);font-size:13.5px}
|
|
387
|
+
.soft-confirm p{margin:0 0 10px}
|
|
388
|
+
.soft-actions{display:flex;gap:8px;flex-wrap:wrap}
|
|
389
|
+
.dimmed{opacity:.42;filter:saturate(.5)}
|
|
390
|
+
[inert]{pointer-events:none}
|
|
391
|
+
|
|
392
|
+
/* ── Progress + result ────────────────────────────────────────────────────────────────────── */
|
|
393
|
+
.progress-card h2,.result-card h2{margin:0}
|
|
394
|
+
.steps{list-style:none;margin:20px 0;padding:0;display:grid;gap:11px}
|
|
395
|
+
.step{display:grid;grid-template-columns:24px 1fr;gap:11px;align-items:center;color:var(--muted);font-size:14px}
|
|
396
|
+
.step-mark{width:22px;height:22px;display:grid;place-items:center;border:1.5px solid var(--edge-strong);border-radius:var(--radius-pill);font:11px var(--mono);font-weight:800}
|
|
397
|
+
.step[data-state="active"]{color:var(--ink)}
|
|
398
|
+
.step[data-state="active"] .step-mark{border-color:var(--signal);color:var(--signal);animation:pulse 1.3s ease-in-out infinite}
|
|
399
|
+
.step[data-state="done"]{color:var(--live)}
|
|
400
|
+
.step[data-state="done"] .step-mark{border-color:var(--live);background:var(--live-soft)}
|
|
401
|
+
.step[data-state="fail"]{color:var(--danger)}
|
|
402
|
+
.step[data-state="fail"] .step-mark{border-color:var(--danger)}
|
|
403
|
+
.raw-log{margin-top:16px;border-top:1px solid var(--edge);padding-top:14px}
|
|
404
|
+
.raw-log summary{cursor:pointer;color:var(--muted);font-size:13px}
|
|
405
|
+
.raw-log pre{max-height:220px;overflow:auto;margin:10px 0 0;padding:13px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface-soft);color:var(--muted);font:11.5px/1.6 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere}
|
|
406
|
+
.result-card{display:grid;gap:18px}
|
|
407
|
+
.result-icon{width:44px;height:44px;display:grid;place-items:center;border-radius:var(--radius-pill);background:var(--live-soft);color:var(--live);font-size:22px;font-weight:800}
|
|
408
|
+
.url-list{display:grid;gap:9px}
|
|
409
|
+
.url-row{display:grid;grid-template-columns:66px minmax(0,1fr) auto auto;gap:9px;align-items:center;padding:11px;border:1px solid var(--edge);border-radius:var(--radius-sm);background:var(--surface-raised)}
|
|
410
|
+
.url-row strong{font-size:12px;color:var(--muted);font-weight:650}
|
|
411
|
+
.url-row code{color:var(--ink);font:12px var(--mono);overflow:hidden;text-overflow:ellipsis}
|
|
412
|
+
.url-row .button{min-height:32px;padding:5px 10px;font-size:12.5px}
|
|
413
|
+
.credential-note{padding:15px;border:1px solid var(--edge);border-radius:var(--radius-md);background:var(--surface-raised)}
|
|
414
|
+
.credential-note strong{display:block;font-size:14px;letter-spacing:-.01em}
|
|
415
|
+
.credential-note p{margin:4px 0 0;color:var(--muted);font-size:13.5px}
|
|
416
|
+
.credential-note code{display:block;margin-top:9px;color:var(--ink);font:11.5px var(--mono);overflow-wrap:anywhere}
|
|
417
|
+
[hidden]{display:none!important}
|
|
418
|
+
|
|
419
|
+
@keyframes spin{to{transform:rotate(360deg)}}
|
|
420
|
+
@keyframes pulse{50%{transform:scale(.88);opacity:.6}}
|
|
421
|
+
@keyframes draw{to{stroke-dashoffset:0}}
|
|
422
|
+
@keyframes pop{to{opacity:1}}
|
|
423
|
+
|
|
424
|
+
@media(max-width:660px){
|
|
425
|
+
.provider-grid,.split,.ports{grid-template-columns:1fr 1fr}
|
|
426
|
+
.provider-grid .provider-card:last-child{grid-column:1/-1}
|
|
427
|
+
.url-row{grid-template-columns:58px minmax(0,1fr)}
|
|
428
|
+
.url-row .button{grid-row:2}
|
|
429
|
+
.header-inner{padding:9px 0}
|
|
430
|
+
}
|
|
431
|
+
@media(max-width:520px){
|
|
432
|
+
.shell,.header-inner{width:min(100% - 22px,780px)}
|
|
433
|
+
.shell{padding-top:20px}
|
|
434
|
+
.card{padding:18px}
|
|
435
|
+
.provider-grid,.split,.ports,.choice-row{grid-template-columns:1fr}
|
|
436
|
+
.provider-grid .provider-card:last-child{grid-column:auto}
|
|
437
|
+
.trust{max-width:100%;white-space:normal}
|
|
438
|
+
.url-row{grid-template-columns:1fr}
|
|
439
|
+
.url-row code{white-space:normal}
|
|
440
|
+
.header-actions{width:100%;justify-content:space-between}
|
|
441
|
+
.model-head,.model-facts,.model-test{align-items:stretch;flex-direction:column}
|
|
442
|
+
.model-pill,.tier-label{align-self:flex-start}
|
|
443
|
+
.model-test .button{width:100%}
|
|
444
|
+
}
|
|
445
|
+
@media (prefers-reduced-motion:reduce){
|
|
446
|
+
*,*:before,*:after{scroll-behavior:auto!important;animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
|
|
447
|
+
}
|
|
448
|
+
</style><style>.provider-card>svg{width:20px;height:20px;margin-bottom:7px;color:var(--muted);fill:none;stroke:currentColor;stroke-width:1.7}.provider-card:has(input:checked)>svg{color:var(--signal)}.provider-card:has(input:focus-visible){box-shadow:0 0 0 2px var(--paper),0 0 0 4px var(--signal)}.chip svg{width:14px;height:14px;flex:0 0 auto;fill:none;stroke:currentColor;stroke-width:1.9}.chip svg.spinner{border:0;border-radius:0;transform-origin:center}</style></head><body>
|
|
449
|
+
<header class="site-header"><div class="header-inner"><div class="brand">
|
|
450
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3 4 4.5 4.5 0 0 1-3-4"/><path d="M12 18v4"/><path d="M8.5 4.5l3.5 3 3.5-3"/></svg>
|
|
451
|
+
<div class="wordmark" aria-label="knowz setup"><span class="script">knowz</span> <span>setup</span></div></div>
|
|
452
|
+
<div class="header-actions"><span class="trust">local · private · 127.0.0.1</span><button id="theme-toggle" class="icon-button" type="button" aria-label="Toggle color theme"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3v2m0 14v2M3 12h2m14 0h2M5.6 5.6 7 7m10 10 1.4 1.4M18.4 5.6 17 7M7 17l-1.4 1.4"/><circle cx="12" cy="12" r="4"/></svg></button></div>
|
|
453
|
+
</div></header>
|
|
454
|
+
<main class="shell"><section class="hero"><p class="eyebrow-inline">Portable edition</p><h1>Set up your private Knowz, <em>locally.</em></h1></section>
|
|
455
|
+
<div class="statusbar">${existing}${licenseRow}</div>
|
|
456
|
+
<form id="setup-form" class="stack">
|
|
457
|
+
<details class="card preflight"${preflightOpen}><summary><span>Preflight checks</span><span class="preflight-state">${preflight.ok ? 'All checks passed' : 'Action needed'}</span></summary><ul class="checks">${checks}</ul></details>${engineGuide}
|
|
458
|
+
<nav class="rail" id="rail" aria-label="Setup steps"><button type="button" class="rail-step" data-goto="1" aria-current="step"><span class="rail-num">1</span><span class="rail-text"><strong>AI provider</strong><small>Choose a model provider</small></span></button><button type="button" class="rail-step" data-goto="2" aria-current="false"><span class="rail-num">2</span><span class="rail-text"><strong>Services</strong><small>What runs, and where</small></span></button><button type="button" class="rail-step" data-goto="3" aria-current="false"><span class="rail-num">3</span><span class="rail-text"><strong>Account</strong><small>The local owner identity</small></span></button><button type="button" class="rail-step" data-goto="4" aria-current="false"><span class="rail-num">4</span><span class="rail-text"><strong>Review</strong><small>Confirm and start</small></span></button></nav>
|
|
459
|
+
<div class="step-panel" data-step="1">
|
|
460
|
+
<section class="card"><div class="card-heading"><div><h2>AI provider</h2><p>Start offline or connect your preferred model endpoint.</p></div></div>
|
|
461
|
+
<div class="provider-grid" role="radiogroup" aria-label="AI provider">
|
|
462
|
+
${providerCards}${aliasCards}
|
|
463
|
+
</div>
|
|
464
|
+
<div class="fields">${providerDisclosures}${cloudActivation}${providerFields}</div>
|
|
465
|
+
<div id="test-row" class="test-row" hidden><button id="test-connection" class="button" type="button"><svg class="button-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m8 12 2.5 2.5L16 9m5 3a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>Test connection</button><span id="test-chip" class="chip" data-test-state="idle" aria-live="polite" tabindex="-1"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg><span>Not tested</span></span></div>
|
|
466
|
+
<div class="models-band"><div class="models-heading"><h3>Models (<span id="model-count">1</span>)</h3><span>Live readiness checks</span></div><div id="model-cards" class="model-cards"></div></div>
|
|
467
|
+
</section>
|
|
468
|
+
</div>
|
|
469
|
+
<div class="step-panel" data-step="2" hidden>
|
|
470
|
+
<section class="card"><div class="card-heading"><div><h2>Components</h2><p>API, worker, web, and data services are always on.</p></div></div>
|
|
471
|
+
<div class="provider-grid">
|
|
472
|
+
<label class="provider-card" for="component-mcp"><input id="component-mcp" name="withMcp" type="checkbox"${defaultMcpEnabled ? ' checked' : ''}><strong>MCP server</strong><small>Lets AI tools query this instance.</small></label>
|
|
473
|
+
<label class="provider-card" for="component-public-site"><input id="component-public-site" name="withPublicSite" type="checkbox"${defaultPublicSiteEnabled ? ' checked' : ''}><strong>Public site</strong><small>Public-facing pages for shared knowledge.</small></label>
|
|
474
|
+
</div>
|
|
475
|
+
</section>
|
|
476
|
+
<section class="card"><div class="card-heading"><div><h2>Ports</h2><p>Loopback-only service ports for this stack.</p></div></div>
|
|
477
|
+
<div class="split ports"><div class="field"><label for="api-port">API port</label><input id="api-port" name="apiPort" type="number" value="${defaultApiPort}" required aria-required="true" autocomplete="off"></div><div class="field"><label for="web-port">Web port</label><input id="web-port" name="webPort" type="number" value="${defaultWebPort}" required aria-required="true" autocomplete="off"></div><div class="field"><label for="mcp-port">MCP port</label><input id="mcp-port" name="mcpPort" type="number" value="${defaultMcpPort}" required aria-required="true" autocomplete="off"></div><div id="public-site-port-field" class="field"${defaultPublicSiteEnabled ? '' : ' hidden'}><label for="public-site-port">Public site port</label><input id="public-site-port" name="publicSitePort" type="number" value="${defaultPublicSitePort}" autocomplete="off"></div></div>
|
|
478
|
+
<p id="url-preview" class="url-preview" aria-live="polite"></p>
|
|
479
|
+
<div class="test-row"><button id="test-ports" class="button" type="button"><svg class="button-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 7h14M5 12h14M5 17h14M8 4v16m8-16v16"/></svg>Test ports</button><span class="chip" data-port-result="api" data-test-state="idle" aria-live="polite"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg><span>API · not tested</span></span><span class="chip" data-port-result="web" data-test-state="idle" aria-live="polite"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg><span>Web · not tested</span></span><span class="chip" data-port-result="mcp" data-test-state="idle" aria-live="polite"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg><span>MCP · not tested</span></span></div>
|
|
480
|
+
<details class="raw-log"><summary>Advanced — public URLs</summary><div class="fields"><div class="field"><label for="public-api-url">Public API URL <span class="required">optional</span></label><input id="public-api-url" name="publicApiUrl" value="${defaultPublicApiUrl}" autocomplete="off" placeholder="HTTPS URL; blank uses localhost"></div><div class="field"><label for="public-web-url">Public web origin <span class="required">optional</span></label><input id="public-web-url" name="publicWebUrl" value="${defaultPublicWebUrl}" autocomplete="off" placeholder="HTTPS origin; blank uses localhost"></div><div class="field"><label for="public-mcp-url">Public MCP URL <span class="required">optional</span></label><input id="public-mcp-url" name="publicMcpUrl" value="${defaultPublicMcpUrl}" autocomplete="off" placeholder="HTTPS URL; blank uses localhost"></div></div></details>
|
|
481
|
+
</section>
|
|
482
|
+
</div>
|
|
483
|
+
<div class="step-panel" data-step="3" hidden>
|
|
484
|
+
<section class="card"><div class="card-heading"><div><h2>First account</h2><p>The local owner identity created during first boot.</p></div></div>
|
|
485
|
+
<div class="field"><label for="org-name">Organization name <span class="required">optional</span></label><input id="org-name" name="orgName" value="${defaultOrgName}" maxlength="64" autocomplete="off"></div>
|
|
486
|
+
<div class="split"><div class="field"><label for="account-name">Name</label><input id="account-name" name="accountName" value="${defaultAccountName}" autocomplete="off"></div><div class="field"><label for="account-email">Email</label><input id="account-email" name="accountEmail" type="email" value="${defaultAccountEmail}" autocomplete="off"></div></div>
|
|
487
|
+
<div class="field"><label for="superadmin-passphrase">SuperAdmin passphrase <span class="required">optional</span></label><input id="superadmin-passphrase" name="superAdminPassphrase" type="password" autocomplete="off" minlength="12" maxlength="128"><small>${stateRecord ? 'Currently set — hidden. Replace it here, or ' : ''}leave blank to auto-generate. It is stored only on this machine and never shown again.</small></div>
|
|
488
|
+
</section>
|
|
489
|
+
</div>
|
|
490
|
+
<div class="step-panel" data-step="4" hidden>
|
|
491
|
+
<section class="card"><div class="card-heading"><div><h2>Image source & version</h2><p>Use a pinned release or build this checkout.</p></div></div>
|
|
492
|
+
<div class="split"><div class="field"><label for="image-mode">Image source</label><select id="image-mode" name="imageMode"><option value="pull"${buildSelected ? '' : ' selected'}>Pull release</option><option value="build"${buildSelected ? ' selected' : ''}>Build checkout</option></select></div><div class="field"><label for="version">Version</label><input id="version" name="version" value="${defaultVersion}" required aria-required="true" autocomplete="off"></div></div>
|
|
493
|
+
<div class="field"><label for="storage-mode">Object storage</label><select id="storage-mode" name="storage"><option value="minio"${filesystemSelected ? '' : ' selected'}>Bundled MinIO · S3-compatible</option><option value="filesystem"${filesystemSelected ? ' selected' : ''}>Filesystem · single shared volume</option></select></div>
|
|
494
|
+
<div class="field"><label for="project-name">Project name</label><input id="project-name" name="name" value="${defaultName}" required aria-required="true" autocomplete="off"></div>
|
|
495
|
+
<div class="field"><label for="ghcr-token">GHCR pull token <span class="required">optional</span></label><input id="ghcr-token" name="ghcrToken" type="password" autocomplete="off"></div>
|
|
496
|
+
</section>
|
|
497
|
+
<section class="card"><div class="card-heading"><div><h2>Review & start</h2><p>Configuration stays on this machine and secret files are written mode 0600.</p></div></div>
|
|
498
|
+
<p id="model-summary" class="model-summary" aria-live="polite">AI offline · 1 models · not verified</p>
|
|
499
|
+
<div class="choice-row"><label class="choice" for="seed-demo"><input id="seed-demo" name="seedDemo" type="checkbox"> Seed demo content</label><label class="choice" for="reconfigure"><input id="reconfigure" name="reconfigure" type="checkbox"> Reconfigure existing stack</label></div>
|
|
500
|
+
<div id="soft-confirm" class="soft-confirm" hidden><p>You haven't confirmed the AI connection works. Start anyway?</p><div class="soft-actions"><button id="start-anyway" class="button" type="button">Start anyway</button><button id="test-first" class="button button-quiet" type="button">Test first</button></div></div>
|
|
501
|
+
<div id="existing-choice" class="soft-confirm" hidden><p>An existing stack was detected. Choose whether to apply these form values or inspect the running stack without changing it.</p><div class="soft-actions"><button id="apply-existing-changes" class="button" type="button">Apply my changes (reconfigure)</button><button id="inspect-existing" class="button button-quiet" type="button">Inspect existing stack only</button></div></div>
|
|
502
|
+
<button class="button button-primary" type="submit"><svg class="button-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="m8 5 11 7-11 7V5Z"/></svg>Start Knowz</button>
|
|
503
|
+
</section>
|
|
504
|
+
</div>
|
|
505
|
+
<div class="wizard-nav"><button type="button" id="step-back" class="button" hidden>Back</button><span class="wizard-spacer"></span><button type="button" id="step-next" class="button button-primary button-inline">Next</button></div>
|
|
506
|
+
</form>
|
|
507
|
+
<section id="progress-view" class="card progress-card" hidden><div class="card-heading"><span class="step-number">→</span><div><h2>Starting your local platform</h2><p>Keep this window open while services initialize.</p></div></div>
|
|
508
|
+
<ol id="step-list" class="steps"><li class="step" data-step="config" data-state="idle"><span class="step-mark">·</span><span>Validate configuration</span></li><li class="step" data-step="images" data-state="idle"><span class="step-mark">·</span><span>Prepare images</span></li><li class="step" data-step="data" data-state="idle"><span class="step-mark">·</span><span>Start data services</span></li><li class="step" data-step="minio" data-state="idle"><span class="step-mark">·</span><span>Initialize object storage · minio-createbucket</span></li><li class="step" data-step="services" data-state="idle"><span class="step-mark">·</span><span>Start Knowz services</span></li><li class="step" data-step="account" data-state="idle"><span class="step-mark">·</span><span>Create first account</span></li><li class="step" data-step="verify" data-state="idle"><span class="step-mark">·</span><span>Verify API</span></li></ol>
|
|
509
|
+
<div id="run-error" class="banner banner-danger" tabindex="-1" aria-live="polite" hidden></div><button id="back-config" class="button" type="button" hidden>Back to configuration</button>
|
|
510
|
+
<details class="raw-log"><summary>Raw setup log</summary><pre id="progress-log" aria-live="polite"></pre></details>
|
|
511
|
+
</section>
|
|
512
|
+
<section id="result-view" class="card result-card" aria-live="polite" hidden><div id="result-icon" class="result-icon" aria-hidden="true">✓</div><div><h2 id="result-heading">Knowz is ready</h2><p id="result-copy">Your local, private platform is running.</p></div><div id="verify-chip" class="chip" aria-label="API verification" hidden></div><div id="url-list" class="url-list"></div><div id="credential-note" class="credential-note"><strong>Admin credentials are stored locally</strong><p>Admin password and SuperAdmin passphrase are in the private mode-0600 environment file:</p><code>${credentialPath}</code><p>View them from the terminal; they are never shown in this page.</p></div></section>
|
|
513
|
+
</main><script>
|
|
514
|
+
const setupToken=${tokenLiteral};
|
|
515
|
+
const consoleSessionEndedCopy='Console session ended — re-run knowz setup';
|
|
516
|
+
const ollamaEndpoint='http'+${ollamaEndpointSuffixLiteral};
|
|
517
|
+
const aliasPrefills=${aliasPrefillLiteral};
|
|
518
|
+
const vertexChatDefault=${vertexChatDefaultLiteral};
|
|
519
|
+
const vertexEmbeddingDefault=${vertexEmbeddingDefaultLiteral};
|
|
520
|
+
const qwen3EmbeddingDefault=${qwen3EmbeddingDefaultLiteral};
|
|
521
|
+
const qwen3EmbeddingDims=${qwen3EmbeddingDimsLiteral};
|
|
522
|
+
const formSchema=${schemaLiteral};
|
|
523
|
+
const hasExistingState=${existingStateLiteral};
|
|
524
|
+
const form=document.getElementById('setup-form');
|
|
525
|
+
const testButton=document.getElementById('test-connection');
|
|
526
|
+
const cloudActivateButton=document.getElementById('activate-cloud-ai');
|
|
527
|
+
const cloudActivateStatus=document.getElementById('activate-cloud-ai-status');
|
|
528
|
+
const testChip=document.getElementById('test-chip');
|
|
529
|
+
const testRow=document.getElementById('test-row');
|
|
530
|
+
const portTestButton=document.getElementById('test-ports');
|
|
531
|
+
const modelCardsElement=document.getElementById('model-cards');
|
|
532
|
+
const modelCountElement=document.getElementById('model-count');
|
|
533
|
+
const modelSummary=document.getElementById('model-summary');
|
|
534
|
+
const softConfirm=document.getElementById('soft-confirm');
|
|
535
|
+
const existingChoice=document.getElementById('existing-choice');
|
|
536
|
+
const progressView=document.getElementById('progress-view');
|
|
537
|
+
const progressLog=document.getElementById('progress-log');
|
|
538
|
+
const resultView=document.getElementById('result-view');
|
|
539
|
+
const runError=document.getElementById('run-error');
|
|
540
|
+
let connectionState='idle';
|
|
541
|
+
let portTestState='idle';
|
|
542
|
+
let modelCards=[];
|
|
543
|
+
let startAnywayArmed=false;
|
|
544
|
+
let existingChoiceArmed=false;
|
|
545
|
+
let terminalEventSeen=false;
|
|
546
|
+
function selectedProviderInput(){return form.querySelector('input[name="provider"]:checked')}
|
|
547
|
+
function selectedProvider(){return selectedProviderInput().value}
|
|
548
|
+
function providerField(key,provider=selectedProvider()){return form.querySelector('[data-provider-group="'+provider+'"] [name="provider.'+key+'"]')}
|
|
549
|
+
function applyProviderAliasPrefill(){const selected=selectedProviderInput();const alias=selected&&selected.dataset?selected.dataset.providerAlias:'';if(!alias)return;const spec=aliasPrefills[alias];if(!spec)return;for(const key of Object.keys(spec.fields)){const el=providerField(key,spec.preset);if(el&&!el.value)el.value=spec.fields[key]}}
|
|
550
|
+
function providerFields(){const provider=selectedProvider();const values={};for(const field of formSchema[provider]){const input=providerField(field.key,provider);if(input&&input.value)values[field.key]=field.number?Number(input.value):input.value}return values}
|
|
551
|
+
function fieldDefault(provider,key){const field=(formSchema[provider]||[]).find(function(candidate){return candidate.key===key});return(field&&field.defaultValue)||''}
|
|
552
|
+
function svgIcon(kind){const svg=document.createElementNS('http'+'://www.w3.org/2000/svg','svg');svg.setAttribute('viewBox','0 0 24 24');svg.setAttribute('aria-hidden','true');const paths={check:'m5 12 4 4L19 6',warn:'M12 8v5m0 3h.01M4.9 19h14.2a2 2 0 0 0 1.7-3L13.7 4a2 2 0 0 0-3.4 0L3.2 16a2 2 0 0 0 1.7 3Z',local:'M8 12h8M12 8v8M4 12a8 8 0 1 0 16 0 8 8 0 0 0-16 0Z',idle:'M4 12a8 8 0 1 0 16 0 8 8 0 0 0-16 0Z',testing:'M20 12a8 8 0 0 0-8-8M4 12a8 8 0 0 0 8 8',fail:'m8 8 8 8m0-8-8 8',play:'m9 6 9 6-9 6V6Z',vision:'M2.5 12s3.5-6 9.5-6 9.5 6 9.5 6-3.5 6-9.5 6S2.5 12 2.5 12Zm9.5 3a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z',function:'M8 4h8M9 4 6 20m5-10h5m-6 6h6',structured:'M7 5H4v14h3m10-14h3v14h-3M9 8h6m-6 4h6m-6 4h6',embedding:'M5 7h14M5 12h14M5 17h14M8 4v16m8-16v16'};const path=document.createElementNS('http'+'://www.w3.org/2000/svg','path');path.setAttribute('d',paths[kind]);svg.append(path);return svg}
|
|
553
|
+
function deriveModelCards(){const provider=selectedProvider();const fields=providerFields();if(provider==='offline')return[{id:'offline-chat',role:'chat',title:'Deterministic stub',providerLabel:'Offline',modelName:'deterministic-stub',configured:true,state:'offline',capabilities:[],pricing:'Local · no metered cost'}];if(provider==='azure'){const configured=Boolean(fields.endpoint&&fields.apiKey);const needed='Add an endpoint & key to test';const azureEmbeddingName=typeof fields.embeddingModel==='string'&&fields.embeddingModel.trim()?fields.embeddingModel.trim():fieldDefault('azure','embeddingModel')||'text-embedding-3-small';return[{id:'azure-chat',role:'chat',title:'GPT-5.4 Mini',providerLabel:'Azure OpenAI',modelName:'gpt-5.4-mini',configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['function','structured'],pricing:'Provider pricing applies'},{id:'azure-embedding',role:'embedding',title:azureEmbeddingName,providerLabel:'Azure OpenAI',modelName:azureEmbeddingName,configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['embedding'],pricing:'Provider pricing applies'},{id:'azure-vision',role:'vision',title:'GPT-5.4 Mini Vision',providerLabel:'Azure OpenAI',modelName:'gpt-5.4-mini',configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['vision'],pricing:'Provider pricing applies'}]};if(provider==='gcp'){const configured=Boolean(fields.project&&fields.adcPath);const needed='Add a Vertex project & ADC path to test';const chatName=typeof fields.chatModel==='string'&&fields.chatModel.trim()?fields.chatModel.trim():vertexChatDefault;const embeddingName=typeof fields.embeddingModel==='string'&&fields.embeddingModel.trim()?fields.embeddingModel.trim():vertexEmbeddingDefault;return[{id:'gcp-chat',role:'chat',title:chatName,providerLabel:'Google Vertex AI',modelName:chatName,configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['function','structured'],pricing:'Provider pricing applies'},{id:'gcp-embedding',role:'embedding',title:embeddingName,providerLabel:'Google Vertex AI',modelName:embeddingName,configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['embedding'],pricing:'Provider pricing applies'},{id:'gcp-vision',role:'vision',title:chatName+' Vision',providerLabel:'Google Vertex AI',modelName:chatName,configured:configured,state:configured?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['vision'],pricing:'Provider pricing applies'}]};const endpointReady=Boolean(fields.endpoint);const chatName=typeof fields.chatModel==='string'?fields.chatModel.trim():'';const embeddingName=typeof fields.embeddingModel==='string'?fields.embeddingModel.trim():'';const managed=provider==='knowz-cloud';const needed=managed?'Activate or paste a Knowz Cloud AI key, then choose models':'Add an endpoint & key to test';const providerLabel=managed?'Knowz Cloud':'OpenAI-compatible';const pricing=managed?'Metered · Knowz credits apply':'Local · no metered cost';return[{id:'compat-chat',role:'chat',title:chatName||'Chat model',providerLabel:providerLabel,modelName:chatName||'Chat model not set',configured:endpointReady&&Boolean(chatName),state:endpointReady&&chatName?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['function','structured'],pricing:pricing},{id:'compat-embedding',role:'embedding',title:embeddingName||'Embedding model',providerLabel:providerLabel,modelName:embeddingName||'Embedding model not set',configured:endpointReady&&Boolean(embeddingName),state:endpointReady&&embeddingName?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['embedding'],pricing:pricing},{id:'compat-vision',role:'vision',title:(chatName||'Chat model')+' Vision',providerLabel:providerLabel,modelName:chatName||'Chat model not set',configured:endpointReady&&Boolean(chatName),state:endpointReady&&chatName?'idle':'notconfigured',notConfiguredCopy:needed,capabilities:['vision'],pricing:pricing}]}
|
|
554
|
+
function statusPill(card){const pill=document.createElement('span');pill.className='model-pill';const connectionFailed=connectionState==='fail'&&card.state!=='pass'&&card.state!=='offline';const status=card.state==='offline'?'local':connectionFailed?'needs':card.configured?'ready':'needs';pill.dataset.status=status;pill.append(svgIcon(status==='ready'?'check':status==='needs'?'warn':'local'));const copy=document.createElement('span');copy.textContent=connectionFailed?'Fix connection':status==='ready'?'Ready':status==='needs'?'Needs credentials':'Local';pill.append(copy);return pill}
|
|
555
|
+
function capabilityTile(capability){const labels={vision:'Vision',function:'Function calling',structured:'Structured output',embedding:'Embedding'};const tile=document.createElement('span');tile.className='capability';tile.dataset.cap=capability;tile.append(svgIcon(capability));const label=document.createElement('span');label.textContent=labels[capability];tile.append(label);return tile}
|
|
556
|
+
function modelStateCopy(card){if(card.state==='notconfigured')return card.notConfiguredCopy||'Add provider configuration to test';if(card.state==='testing')return'Testing model';if(card.state==='pass')return card.message;if(card.state==='fail')return card.message;if(card.state==='offline')return'No model test needed';return'Not tested'}
|
|
557
|
+
function updateModelSummary(){const tested=modelCards.filter(function(card){return card.state==='pass'}).length;modelCountElement.textContent=String(modelCards.length);const providerLabel=selectedProvider()==='knowz-cloud'?'Knowz Cloud':selectedProvider()==='openai-compatible'?'OpenAI-compatible':selectedProvider()==='azure'?'Azure OpenAI':selectedProvider()==='gcp'?'Google Vertex AI':'offline';modelSummary.textContent='AI '+providerLabel+' · '+modelCards.length+' models · '+(tested?tested+' tested ✓':'not verified')}
|
|
558
|
+
function updateModelCard(card){const element=card.element;if(!element)return;element.classList.toggle('dimmed',card.state==='notconfigured');const oldPill=element.querySelector('.model-pill');oldPill.replaceWith(statusPill(card));const button=element.querySelector('button');button.disabled=!card.configured||card.state==='testing'||card.state==='offline';const chip=element.querySelector('.chip');chip.setAttribute('data-model-test-state',card.state);const marker=svgIcon(card.state==='pass'?'check':card.state==='fail'?'fail':card.state==='notconfigured'?'warn':card.state==='testing'?'testing':card.state==='offline'?'local':'idle');if(card.state==='testing')marker.classList.add('spinner');const copy=document.createElement('span');copy.textContent=modelStateCopy(card);chip.replaceChildren(marker,copy);updateModelSummary()}
|
|
559
|
+
async function testModelCard(card){if(!card.configured||card.state==='offline')return;card.state='testing';updateModelCard(card);try{const response=await fetch('/api/test-model',{method:'POST',headers:{'X-Setup-Token':setupToken,'Content-Type':'application/json'},body:JSON.stringify({provider:selectedProvider(),providerFields:providerFields(),modelRole:card.role})});const verdict=await response.json();if(response.ok&&verdict.ok){card.state='pass';card.message='Responded'+(verdict.latencyMs?' · '+verdict.latencyMs+' ms':'')}else if(verdict.category==='endpoint'){card.state='notconfigured';card.configured=false;card.message='Add provider configuration to test'}else{card.state='fail';card.message=verdict.message||'Model test failed'}}catch{card.state='fail';card.message=consoleSessionEndedCopy}updateModelCard(card);if(card.state==='fail')card.element.querySelector('.chip').focus()}
|
|
560
|
+
function renderModelCards(){modelCards=deriveModelCards();modelCardsElement.textContent='';for(const card of modelCards){const element=document.createElement('article');element.className='model-card';element.dataset.modelId=card.id;card.element=element;const head=document.createElement('div');head.className='model-head';const identity=document.createElement('div');const title=document.createElement('h4');title.className='model-title';title.textContent=card.title;const subtitle=document.createElement('span');subtitle.className='model-subtitle';subtitle.textContent=card.providerLabel+' · '+card.modelName;identity.append(title,subtitle);head.append(identity,statusPill(card));const facts=document.createElement('div');facts.className='model-facts';const tier=document.createElement('span');tier.className='tier-label';tier.textContent=(card.role==='embedding'?'Embedding':'Normal')+' tier';const pricing=document.createElement('span');pricing.className='pricing';pricing.textContent=card.pricing;facts.append(tier,pricing);const caps=document.createElement('div');caps.className='capabilities';card.capabilities.forEach(function(capability){caps.append(capabilityTile(capability))});if(!card.capabilities.length){const empty=document.createElement('span');empty.className='pricing';empty.textContent='No live model capabilities';caps.append(empty)}const actions=document.createElement('div');actions.className='model-test';const button=document.createElement('button');button.type='button';button.className='button';button.append(svgIcon('play'));const buttonCopy=document.createElement('span');buttonCopy.textContent='Test model';button.append(buttonCopy);button.addEventListener('click',function(){void testModelCard(card)});const chip=document.createElement('span');chip.className='chip';chip.setAttribute('data-model-test-state','idle');chip.setAttribute('aria-live','polite');chip.tabIndex=-1;actions.append(button,chip);element.append(head,facts,caps,actions);modelCardsElement.append(element);updateModelCard(card)}updateModelSummary()}
|
|
561
|
+
// Summary contract: N models · M tested ✓.
|
|
562
|
+
function firstUntestedModelButton(){const card=modelCards.find(function(candidate){return candidate.configured&&candidate.state!=='pass'&&candidate.state!=='offline'});return card&&card.element.querySelector('button')}
|
|
563
|
+
function verificationComplete(){const aiComplete=selectedProvider()==='offline'||(connectionState==='pass'&&modelCards.every(function(card){return card.state==='pass'}));return aiComplete&&portTestState==='pass'}
|
|
564
|
+
function showFields(){applyProviderAliasPrefill();const provider=selectedProvider();document.querySelectorAll('[data-provider-group]').forEach(function(group){const visible=group.dataset.providerGroup===provider;group.hidden=!visible;group.querySelectorAll('input,select').forEach(function(input){input.disabled=!visible})});testRow.hidden=provider==='offline';softConfirm.hidden=true;invalidateConnectionTest();renderModelCards();}
|
|
565
|
+
function setConnectionState(state,message){const changed=connectionState!==state;connectionState=state;testChip.dataset.testState=state;const marker=svgIcon(state==='pass'?'check':state==='fail'?'fail':state==='testing'?'testing':'idle');if(state==='testing')marker.classList.add('spinner');const copy=document.createElement('span');copy.textContent=message;testChip.replaceChildren(marker,copy);testButton.disabled=state==='testing';if(changed)modelCards.forEach(function(card){updateModelCard(card)});}
|
|
566
|
+
function invalidateConnectionTest(){if(connectionState!=='testing')setConnectionState('idle','Not tested');startAnywayArmed=false;softConfirm.hidden=true;}
|
|
567
|
+
document.querySelectorAll('input[name="provider"]').forEach(function(input){input.addEventListener('change',showFields)});
|
|
568
|
+
document.querySelectorAll('[data-provider-group] input,[data-provider-group] select').forEach(function(input){input.addEventListener('input',function(){const key=input.name.slice('provider.'.length);if(input!==providerField(key))return;invalidateConnectionTest();renderModelCards()})});
|
|
569
|
+
if(cloudActivateButton)cloudActivateButton.addEventListener('click',async function(){cloudActivateButton.disabled=true;cloudActivateStatus.textContent='Waiting for browser approval…';try{const response=await fetch('/api/cloud-ai/activate',{method:'POST',headers:{'X-Setup-Token':setupToken}});const verdict=await response.json();if(response.ok&&verdict.ok&&verdict.credential){providerField('apiKey').value=verdict.credential;cloudActivateStatus.textContent='Account connected — key held privately in this setup session';invalidateConnectionTest();renderModelCards()}else{cloudActivateStatus.textContent=verdict.message||'Activation failed'}}catch{cloudActivateStatus.textContent=consoleSessionEndedCopy}finally{cloudActivateButton.disabled=false}});
|
|
570
|
+
function applyDiscoveredModels(verdict){if(selectedProvider()!=='knowz-cloud'||!verdict.models)return;const chat=providerField('chatModel');const embedding=providerField('embeddingModel');if(chat&&!chat.value&&verdict.models.chat&&verdict.models.chat[0])chat.value=verdict.models.chat[0];if(embedding&&!embedding.value&&verdict.models.embedding&&verdict.models.embedding[0])embedding.value=verdict.models.embedding[0];renderModelCards()}
|
|
571
|
+
testButton.addEventListener('click',async function(){setConnectionState('testing','Testing connection');try{const response=await fetch('/api/test-connection',{method:'POST',headers:{'X-Setup-Token':setupToken,'Content-Type':'application/json'},body:JSON.stringify({provider:selectedProvider(),providerFields:providerFields()})});const verdict=await response.json();if(response.ok&&verdict.ok){applyDiscoveredModels(verdict);setConnectionState('pass',verdict.discoveryWarning|| (verdict.latencyMs?'Connection confirmed · '+verdict.latencyMs+' ms':'Connection confirmed'))}else{setConnectionState('fail',verdict.message||'Connection failed');testChip.focus();}}catch{setConnectionState('fail',consoleSessionEndedCopy);testChip.focus();}});
|
|
572
|
+
function setPortChip(name,state,message){const chip=document.querySelector('[data-port-result="'+name+'"]');chip.dataset.testState=state;const marker=svgIcon(state==='pass'?'check':state==='fail'?'fail':state==='testing'?'testing':'idle');if(state==='testing')marker.classList.add('spinner');const copy=document.createElement('span');copy.textContent=message;chip.replaceChildren(marker,copy)}
|
|
573
|
+
function selectedPortNames(){return['api','web'].concat(form.elements.withMcp.checked?['mcp']:[]).concat(form.elements.withPublicSite.checked?['publicSite']:[])}
|
|
574
|
+
function invalidatePortTest(){if(portTestState!=='testing'){portTestState='idle';setPortChip('api','idle','API · not tested');setPortChip('web','idle','Web · not tested');setPortChip('mcp','idle','MCP · not tested')}startAnywayArmed=false;softConfirm.hidden=true}
|
|
575
|
+
function findDuplicatePorts(){const ports={api:Number(form.elements.apiPort.value),web:Number(form.elements.webPort.value),mcp:Number(form.elements.mcpPort.value),publicSite:Number(form.elements.publicSitePort.value)};const groups={};for(const name of selectedPortNames()){const port=ports[name];(groups[port]||(groups[port]=[])).push(name)}return Object.entries(groups).filter(function(entry){return entry[1].length>1}).map(function(entry){return{port:entry[0],names:entry[1]}})}
|
|
576
|
+
function renderDuplicatePorts(){const collisions=findDuplicatePorts();if(!collisions.length)return false;for(const collision of collisions){for(const name of collision.names){const others=collision.names.filter(function(candidate){return candidate!==name}).map(function(candidate){return candidate.toUpperCase()}).join(' / ');setPortChip(name,'fail',name.toUpperCase()+' · duplicates '+others+' on '+collision.port)}}portTestState='fail';startAnywayArmed=false;softConfirm.hidden=true;return true}
|
|
577
|
+
portTestButton.addEventListener('click',async function(){if(renderDuplicatePorts())return;portTestState='testing';portTestButton.disabled=true;for(const name of selectedPortNames())setPortChip(name,'testing',name.toUpperCase()+' · testing');try{const response=await fetch('/api/test-ports',{method:'POST',headers:{'X-Setup-Token':setupToken,'Content-Type':'application/json'},body:JSON.stringify({ports:{api:Number(form.elements.apiPort.value),web:Number(form.elements.webPort.value),mcp:Number(form.elements.mcpPort.value),publicSite:Number(form.elements.publicSitePort.value)},components:{mcp:form.elements.withMcp.checked,publicSite:form.elements.withPublicSite.checked}})});const verdict=await response.json();if(response.ok&&verdict.ports){for(const name of selectedPortNames()){const result=verdict.ports[name];setPortChip(name,result.available?'pass':'fail',name.toUpperCase()+' · '+(result.available?'available':'in use'))}portTestState=verdict.ok?'pass':'fail'}else{portTestState='fail';for(const name of selectedPortNames())setPortChip(name,'fail',name.toUpperCase()+' · test failed')}}catch{portTestState='fail';for(const name of selectedPortNames())setPortChip(name,'fail',name.toUpperCase()+' · console offline — re-run knowz setup')}finally{portTestButton.disabled=false}});
|
|
578
|
+
function updatePreview(){const web=form.elements.webPort.value||'3000';const api=form.elements.apiPort.value||'5000';const mcp=form.elements.mcpPort.value||'3001';const publicSite=form.elements.publicSitePort.value||'3002';document.getElementById('url-preview').textContent='Web http'+'://127.0.0.1:'+web+' · API http'+'://127.0.0.1:'+api+(form.elements.withMcp.checked?' · MCP http'+'://127.0.0.1:'+mcp:'')+(form.elements.withPublicSite.checked?' · Public site http'+'://127.0.0.1:'+publicSite:'');}
|
|
579
|
+
function updateComponents(){document.getElementById('public-site-port-field').hidden=!form.elements.withPublicSite.checked;updatePreview();invalidatePortTest()}
|
|
580
|
+
['apiPort','webPort','mcpPort','publicSitePort'].forEach(function(name){form.elements[name].addEventListener('input',function(){updatePreview();invalidatePortTest()})});form.elements.withMcp.addEventListener('change',updateComponents);form.elements.withPublicSite.addEventListener('change',updateComponents);updatePreview();showFields();
|
|
581
|
+
document.getElementById('theme-toggle').addEventListener('click',function(){const root=document.documentElement;const current=root.dataset.theme||(matchMedia('(prefers-color-scheme: light)').matches?'light':'dark');root.dataset.theme=current==='light'?'dark':'light';});
|
|
582
|
+
document.getElementById('start-anyway').addEventListener('click',function(){startAnywayArmed=true;softConfirm.hidden=true;form.requestSubmit();});
|
|
583
|
+
document.getElementById('apply-existing-changes').addEventListener('click',function(){existingChoice.hidden=true;existingChoiceArmed=false;form.elements.reconfigure.checked=true;form.requestSubmit()});
|
|
584
|
+
document.getElementById('inspect-existing').addEventListener('click',function(){existingChoice.hidden=true;existingChoiceArmed=true;form.requestSubmit()});
|
|
585
|
+
document.getElementById('test-first').addEventListener('click',function(){softConfirm.hidden=true;if(selectedProvider()!=='offline'&&connectionState!=='pass'){testButton.focus();testButton.click();return}const first=firstUntestedModelButton();if(first){first.scrollIntoView({block:'center'});first.focus();return}if(portTestState!=='pass'){portTestButton.scrollIntoView({block:'center'});portTestButton.focus();portTestButton.click()}});
|
|
586
|
+
function setupBody(){return{provider:selectedProvider(),providerFields:providerFields(),imageMode:form.elements.imageMode.value,name:form.elements.name.value,version:form.elements.version.value,storage:form.elements.storage.value,components:{mcp:form.elements.withMcp.checked,publicSite:form.elements.withPublicSite.checked},publicUrls:{api:form.elements.publicApiUrl.value||undefined,web:form.elements.publicWebUrl.value||undefined,mcp:form.elements.publicMcpUrl.value||undefined},orgName:form.elements.orgName.value||undefined,superAdminPassphrase:form.elements.superAdminPassphrase.value||undefined,ports:{api:Number(form.elements.apiPort.value),web:Number(form.elements.webPort.value),mcp:Number(form.elements.mcpPort.value),publicSite:form.elements.withPublicSite.checked?Number(form.elements.publicSitePort.value):undefined},ghcrToken:form.elements.ghcrToken.value||undefined,accountName:form.elements.accountName.value,accountEmail:form.elements.accountEmail.value,seedDemo:form.elements.seedDemo.checked,reconfigure:form.elements.reconfigure.checked}}
|
|
587
|
+
function parseSseFrame(block){let eventType='message';const data=[];for(const line of block.replace(/\\r/g,'').split('\\n')){if(line.startsWith('event:'))eventType=line.slice(6).trim();if(line.startsWith('data:'))data.push(line.slice(5).trimStart())}if(!data.length)return null;try{return{eventType:eventType,data:JSON.parse(data.join('\\n'))}}catch{return null}}
|
|
588
|
+
function appendRaw(line){if(typeof line!=='string')return;progressLog.textContent+=(progressLog.textContent?'\\n':'')+line;progressLog.scrollTop=progressLog.scrollHeight;advanceStep(line)}
|
|
589
|
+
function stepElement(id){return document.querySelector('[data-step="'+id+'"]')}
|
|
590
|
+
function setStep(id,state){const row=stepElement(id);if(!row)return;row.dataset.state=state;row.querySelector('.step-mark').textContent=state==='done'?'✓':state==='fail'?'✕':state==='active'?'…':'·'}
|
|
591
|
+
function activate(id){const rows=Array.from(document.querySelectorAll('.step'));const next=rows.findIndex(function(row){return row.dataset.step===id});rows.forEach(function(row,index){if(index<next&&row.dataset.state!=='fail')setStep(row.dataset.step,'done')});if(next>=0&&rows[next].dataset.state!=='done')setStep(id,'active')}
|
|
592
|
+
function advanceStep(line){const value=line.toLowerCase();if(value.includes('minio-createbucket')&&(value.includes('bucket ready')||value.includes('exit 0')||value.includes('exited with code 0')||value.includes('completed successfully'))){setStep('minio','done');activate('services');return}if(value.includes('preflight')||value.includes('config'))activate('config');else if(value.includes('pull')||value.includes('image')||value.includes('build'))activate('images');else if(value.includes('postgres')||value.includes('redis')||value.includes('minio'))activate('data');else if(value.includes('worker')||value.includes('compose')||value.includes('service'))activate('services');else if(value.includes('bootstrap')||value.includes('account')||value.includes('sign-in'))activate('account');else if(value.includes('health')||value.includes('provider')||value.includes('verify'))activate('verify')}
|
|
593
|
+
function settleSteps(success){const rows=Array.from(document.querySelectorAll('.step'));if(success){rows.forEach(function(row){setStep(row.dataset.step,'done')});return}const active=rows.find(function(row){return row.dataset.state==='active'});if(active)setStep(active.dataset.step,'fail');rows.forEach(function(row){if(row.dataset.state==='active')setStep(row.dataset.step,'idle')})}
|
|
594
|
+
function handleEvent(eventType,data){if(eventType==='progress'){appendRaw(data);return}terminalEventSeen=true;if(eventType==='result'){settleSteps(true);renderResult(data);return}settleSteps(false);showFailure(typeof data==='string'?data:eventType==='timeout'?'Setup console timed out.':'Setup failed.');}
|
|
595
|
+
async function readProgress(){const response=await fetch('/api/progress',{headers:{'X-Setup-Token':setupToken,'X-Setup-Progress-Stream':'1'}});if(!response.ok)return;const reader=response.body.getReader();const decoder=new TextDecoder();let buffer='';while(true){const chunk=await reader.read();buffer+=decoder.decode(chunk.value||new Uint8Array(),{stream:!chunk.done});let boundary;while((boundary=buffer.indexOf('\\n\\n'))>=0){const parsed=parseSseFrame(buffer.slice(0,boundary));buffer=buffer.slice(boundary+2);if(parsed)handleEvent(parsed.eventType,parsed.data)}if(chunk.done)break}}
|
|
596
|
+
function showFailure(message){runError.textContent=message;runError.hidden=false;document.getElementById('back-config').hidden=false;runError.focus();}
|
|
597
|
+
function addServiceLink(label,address){if(!address)return;const row=document.createElement('div');row.className='url-row';const name=document.createElement('strong');name.textContent=label;const code=document.createElement('code');code.textContent=address;const copy=document.createElement('button');copy.type='button';copy.className='button';copy.textContent='Copy';copy.addEventListener('click',function(){void navigator.clipboard.writeText(address)});const open=document.createElement('a');open.className='button';open.textContent='Open';open.target='_blank';open.rel='noreferrer';open.href=address;row.append(name,code,copy,open);document.getElementById('url-list').append(row)}
|
|
598
|
+
function renderResult(result){progressView.hidden=true;resultView.hidden=false;const inspecting=Boolean(result&&result.existing);document.getElementById('result-icon').textContent=inspecting?'i':'✓';document.getElementById('result-heading').textContent=inspecting?'Existing stack inspected':'Knowz is ready';document.getElementById('result-copy').textContent=inspecting?'Your form changes were NOT applied. Tick Reconfigure existing stack and start again to apply them.':'Your local, private platform is running.';document.getElementById('credential-note').hidden=inspecting;const links=document.getElementById('url-list');links.textContent='';addServiceLink('Web',result&&result.webUrl);addServiceLink('API',result&&result.apiUrl);if(form.elements.withMcp.checked)addServiceLink('MCP',result&&result.mcpUrl);if(form.elements.withPublicSite.checked)addServiceLink('Public site',result&&result.publicSiteUrl);const chip=document.getElementById('verify-chip');chip.hidden=true;if(inspecting)return;if(result&&result.verify&&result.verify.api==='ok'){chip.hidden=false;chip.dataset.testState='pass';chip.textContent='✓ API verification passed'}else if(result&&result.verify&&result.verify.api==='warn'){chip.hidden=false;chip.dataset.testState='fail';chip.textContent='! API not responding yet — give it a moment'}}
|
|
599
|
+
document.getElementById('back-config').addEventListener('click',function(){document.querySelectorAll('input[type=password]').forEach(function(input){input.value=''});form.inert=false;form.classList.remove('dimmed');form.hidden=false;progressView.hidden=true;runError.hidden=true;document.getElementById('back-config').hidden=true;terminalEventSeen=false;document.querySelectorAll('.step').forEach(function(row){setStep(row.dataset.step,'idle')});progressLog.textContent='';invalidateConnectionTest();invalidatePortTest();});
|
|
600
|
+
const stepPanels=Array.from(document.querySelectorAll('.step-panel'));
|
|
601
|
+
const railSteps=Array.from(document.querySelectorAll('.rail-step'));
|
|
602
|
+
const stepBack=document.getElementById('step-back');
|
|
603
|
+
const stepNext=document.getElementById('step-next');
|
|
604
|
+
const submitButton=form.querySelector('button[type=submit]');
|
|
605
|
+
let currentStep=1;
|
|
606
|
+
function furthestReached(){return Number(document.getElementById('rail').dataset.reached||'1')}
|
|
607
|
+
function markReached(n){const r=document.getElementById('rail');if(n>furthestReached())r.dataset.reached=String(n)}
|
|
608
|
+
function goToStep(n){
|
|
609
|
+
const total=stepPanels.length;
|
|
610
|
+
currentStep=Math.min(Math.max(n,1),total);
|
|
611
|
+
markReached(currentStep);
|
|
612
|
+
stepPanels.forEach(function(panel){panel.hidden=Number(panel.dataset.step)!==currentStep});
|
|
613
|
+
railSteps.forEach(function(button){
|
|
614
|
+
const index=Number(button.dataset.goto);
|
|
615
|
+
button.setAttribute('aria-current',index===currentStep?'step':'false');
|
|
616
|
+
button.dataset.state=index<currentStep?'done':index===currentStep?'active':'todo';
|
|
617
|
+
button.disabled=index>furthestReached();
|
|
618
|
+
});
|
|
619
|
+
stepBack.hidden=currentStep===1;
|
|
620
|
+
// The last step owns the real submit; Next would be a second, confusing primary action.
|
|
621
|
+
stepNext.hidden=currentStep===total;
|
|
622
|
+
if(submitButton)submitButton.hidden=currentStep!==total;
|
|
623
|
+
window.scrollTo({top:0,behavior:'smooth'});
|
|
624
|
+
}
|
|
625
|
+
function stepIsValid(n){
|
|
626
|
+
const panel=stepPanels.find(function(p){return Number(p.dataset.step)===n});
|
|
627
|
+
if(!panel)return true;
|
|
628
|
+
// Inspect-only: an existing stack with reconfigure unticked changes nothing, so provider fields
|
|
629
|
+
// are legitimately blank (the console reads state.json, never the .env that holds them).
|
|
630
|
+
// Hard-gating navigation there would trap the operator before they could reach Start.
|
|
631
|
+
if(hasExistingState&&form.elements.reconfigure&&!form.elements.reconfigure.checked)return true;
|
|
632
|
+
const fields=Array.from(panel.querySelectorAll('input,select')).filter(function(el){
|
|
633
|
+
return !el.disabled && el.offsetParent!==null;
|
|
634
|
+
});
|
|
635
|
+
for(const field of fields){
|
|
636
|
+
// A secret that is already persisted renders empty by design (we never echo it back). Blocking
|
|
637
|
+
// on the required attribute here would force re-typing a credential to change step.
|
|
638
|
+
if(field.type==='password'&&field.closest('[data-secret-set]'))continue;
|
|
639
|
+
if(!field.checkValidity()){field.reportValidity();return false}
|
|
640
|
+
}
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
stepNext.addEventListener('click',function(){if(stepIsValid(currentStep))goToStep(currentStep+1)});
|
|
644
|
+
stepBack.addEventListener('click',function(){goToStep(currentStep-1)});
|
|
645
|
+
railSteps.forEach(function(button){
|
|
646
|
+
button.addEventListener('click',function(){
|
|
647
|
+
const target=Number(button.dataset.goto);
|
|
648
|
+
// Forward moves validate; backward moves never trap the operator.
|
|
649
|
+
if(target<=currentStep||stepIsValid(currentStep))goToStep(target);
|
|
650
|
+
});
|
|
651
|
+
});
|
|
652
|
+
goToStep(1);
|
|
653
|
+
form.addEventListener('submit',async function(event){event.preventDefault();if(renderDuplicatePorts()){portTestButton.scrollIntoView({block:'center'});portTestButton.focus();return}if(hasExistingState&&!form.elements.reconfigure.checked&&!existingChoiceArmed){existingChoice.hidden=false;existingChoice.querySelector('button').focus();return}const inspectingExisting=hasExistingState&&!form.elements.reconfigure.checked&&existingChoiceArmed;existingChoiceArmed=false;existingChoice.hidden=true;if(!inspectingExisting&&!verificationComplete()&&!startAnywayArmed){softConfirm.hidden=false;softConfirm.querySelector('button').focus();return}if(form.elements.reconfigure.checked&&!window.confirm('Reconfigure the existing local stack? No data will be deleted.'))return;terminalEventSeen=false;runError.hidden=true;form.inert=true;form.classList.add('dimmed');progressView.hidden=false;activate('config');const progressPromise=readProgress();let response;let result;try{response=await fetch('/api/setup',{method:'POST',headers:{'Content-Type':'application/json','X-Setup-Token':setupToken},body:JSON.stringify(setupBody())});result=await response.json();await progressPromise;if(!response.ok&&!terminalEventSeen)showFailure(result.error||'Setup failed.');if(response.ok&&!terminalEventSeen&&result.result){settleSteps(true);renderResult(result.result)}}catch{settleSteps(false);showFailure('The local setup console disconnected. Re-run setup if the CLI exited.')}});
|
|
654
|
+
</script></body></html>`;
|
|
655
|
+
}
|
|
656
|
+
//# sourceMappingURL=setup-page.js.map
|