From 8fa93f2da893f041cb5f9d22ea071b80baf05758 Mon Sep 17 00:00:00 2001 From: Aditya Balakrishnan Date: Sat, 5 Sep 2026 15:18:29 +0000 Subject: [PATCH] Configure Niteshift setup and AGX dashboard preview Run-on: Niteshift --- .niteshift/README.md | 29 +++++++++++++++++++++++ .niteshift/services.yaml | 13 +++++++++++ .niteshift/settings.yaml | 1 + .niteshift/setup | 41 +++++++++++++++++++++++++++++++++ apps/agx-web/src/adpUrl.test.ts | 16 +++++++++++++ apps/agx-web/src/adpUrl.ts | 4 ++++ apps/agx-web/src/useAdp.ts | 4 +++- apps/agx-web/vite.config.ts | 9 ++++++++ 8 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 .niteshift/README.md create mode 100644 .niteshift/services.yaml create mode 100644 .niteshift/settings.yaml create mode 100755 .niteshift/setup create mode 100644 apps/agx-web/src/adpUrl.test.ts create mode 100644 apps/agx-web/src/adpUrl.ts diff --git a/.niteshift/README.md b/.niteshift/README.md new file mode 100644 index 0000000..f23e5cb --- /dev/null +++ b/.niteshift/README.md @@ -0,0 +1,29 @@ +# Niteshift development environment + +The default preview is the AGX dashboard on port 5173, backed by the demo +runtime on internal port 9222. Vite proxies `/adp` so remote browsers use the +same authenticated preview origin for HTTP and WebSockets. The dashboard has +no application login. Its initial nodes and logs are built-in sample data; +the ADP indicator reports the actual connection. + +Setup installs the repository's pinned mise toolchains, frozen pnpm workspace +dependencies, Playwright browsers and system dependencies, and the shared +runtime, orchestrator, and dashboard packages. It does not start background +processes. No resume script is needed: installed tools and dependencies persist, +and Niteshift restarts the declared services automatically. + +Add `OPENAI_API_KEY` to the repository's Niteshift environment variables. The +runtime receives it through a secret reference; it cannot start until that +variable exists. The manifest defaults to the OpenAI API and `gpt-4o`, matching +the demo's example environment. Change `OPENAI_BASE_URL` and `AGENT_MODEL` in +`services.yaml` when using another compatible provider. + +Run `ns services status --wait`, `ns services logs runtime`, or +`ns services restart dashboard runtime` to operate the environment. Rebuild a +changed library with `mise exec -- pnpm exec vp run @agentx/core#build` (or its +own package task), then restart the runtime. Dashboard source changes use HMR. +Run tests from the repository root with `mise exec -- pnpm test`. + +Other applications, including Music Scanner and Zettel, remain opt-in workflows; +they require their own service and provider configuration. This setup does not +provision cloud resources, authenticate Google Cloud, or run extraction jobs. diff --git a/.niteshift/services.yaml b/.niteshift/services.yaml new file mode 100644 index 0000000..b1edf29 --- /dev/null +++ b/.niteshift/services.yaml @@ -0,0 +1,13 @@ +services: + - name: dashboard + command: 'export PATH="$HOME/.local/bin:$PATH"; exec mise exec -- pnpm --filter agx-web dev' + port: 5173 + - name: runtime + command: 'export PATH="$HOME/.local/bin:$PATH"; exec mise exec -- pnpm --filter demo dev' + environment: + - name: OPENAI_API_KEY + secret: OPENAI_API_KEY + - name: OPENAI_BASE_URL + value: https://api.openai.com/v1 + - name: AGENT_MODEL + value: gpt-4o diff --git a/.niteshift/settings.yaml b/.niteshift/settings.yaml new file mode 100644 index 0000000..b825518 --- /dev/null +++ b/.niteshift/settings.yaml @@ -0,0 +1 @@ +version: 1 diff --git a/.niteshift/setup b/.niteshift/setup new file mode 100755 index 0000000..3385731 --- /dev/null +++ b/.niteshift/setup @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "${NITESHIFT_ENVIRONMENT_SETTINGS_DIR:?}/.." +export PATH="$HOME/.local/bin:$PATH" +mise_version="2026.8.14" + +if [[ "$(mise --version 2>/dev/null | awk '{print $1}' || true)" != "$mise_version" ]]; then + case "$(uname -m)" in + x86_64) + mise_arch="x64" + mise_sha256="7cd12d6002d5b3c83a89cad79023712faf2a36f9e8b2ee2061dac5135b3de0ed" + ;; + aarch64 | arm64) + mise_arch="arm64" + mise_sha256="bc2c447a7e498b0bed0a421cc2101b407fef09a3195670d35a4aa3f43cd868a1" + ;; + *) + echo "Unsupported Niteshift architecture: $(uname -m)" >&2 + exit 1 + ;; + esac + + mise_download="$(mktemp)" + trap 'rm -f "$mise_download"' EXIT + curl -fsSL \ + "https://github.com/jdx/mise/releases/download/v$mise_version/mise-v$mise_version-linux-$mise_arch" \ + -o "$mise_download" + printf '%s %s\n' "$mise_sha256" "$mise_download" | sha256sum --check --status + install -D -m 0755 "$mise_download" "$HOME/.local/bin/mise" + rm -f "$mise_download" + trap - EXIT +fi + + +mise trust +MISE_YES=1 mise install +mise exec -- pnpm install --frozen-lockfile +mise exec -- pnpm --filter zettel exec playwright install --with-deps chromium firefox webkit +mise exec -- pnpm exec vp run @agentx/orchestrator#build +mise exec -- pnpm exec vp run @agentx/agx-core#build diff --git a/apps/agx-web/src/adpUrl.test.ts b/apps/agx-web/src/adpUrl.test.ts new file mode 100644 index 0000000..26358bd --- /dev/null +++ b/apps/agx-web/src/adpUrl.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from "vitest"; +import { getAdpUrl } from "./adpUrl.js"; + +describe("dashboard ADP connection", () => { + it("uses the local dev server's WebSocket proxy", () => { + expect(getAdpUrl({ protocol: "http:", host: "localhost:5173" })).toBe( + "ws://localhost:5173/adp", + ); + }); + + it("uses secure WebSockets on the preview's own origin", () => { + expect(getAdpUrl({ protocol: "https:", host: "example.preview.niteshift.dev" })).toBe( + "wss://example.preview.niteshift.dev/adp", + ); + }); +}); diff --git a/apps/agx-web/src/adpUrl.ts b/apps/agx-web/src/adpUrl.ts new file mode 100644 index 0000000..b73f9b5 --- /dev/null +++ b/apps/agx-web/src/adpUrl.ts @@ -0,0 +1,4 @@ +/** Keep the control-plane connection on the browser's origin via the dev proxy. */ +export function getAdpUrl(location: { protocol: string; host: string }): string { + return `${location.protocol === "https:" ? "wss:" : "ws:"}//${location.host}/adp`; +} diff --git a/apps/agx-web/src/useAdp.ts b/apps/agx-web/src/useAdp.ts index c728d96..499fd42 100644 --- a/apps/agx-web/src/useAdp.ts +++ b/apps/agx-web/src/useAdp.ts @@ -9,9 +9,11 @@ import { type LogEntry, } from "@agentx/agx-core"; +import { getAdpUrl } from "./adpUrl.js"; + export type { AgentNode, LogEntry }; -export function useAdp(url = "ws://localhost:9222") { +export function useAdp(url = getAdpUrl(window.location)) { const [connected, setConnected] = useState(false); const [nodes, dispatch] = useReducer(nodeReducer, DEFAULT_NODES); const [logs, setLogs] = useState(DEFAULT_LOGS); diff --git a/apps/agx-web/vite.config.ts b/apps/agx-web/vite.config.ts index 6b37724..c42247e 100644 --- a/apps/agx-web/vite.config.ts +++ b/apps/agx-web/vite.config.ts @@ -3,6 +3,15 @@ import react from "@vitejs/plugin-react"; export default defineConfig({ plugins: [react()], + server: { + host: "0.0.0.0", + port: 5173, + strictPort: true, + allowedHosts: [".preview.niteshift.dev"], + proxy: { + "/adp": { target: "ws://localhost:9222", ws: true }, + }, + }, run: { tasks: { build: {