Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .niteshift/README.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 13 additions & 0 deletions .niteshift/services.yaml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions .niteshift/settings.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version: 1
41 changes: 41 additions & 0 deletions .niteshift/setup
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions apps/agx-web/src/adpUrl.test.ts
Original file line number Diff line number Diff line change
@@ -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",
);
});
});
4 changes: 4 additions & 0 deletions apps/agx-web/src/adpUrl.ts
Original file line number Diff line number Diff line change
@@ -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`;
}
4 changes: 3 additions & 1 deletion apps/agx-web/src/useAdp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<LogEntry[]>(DEFAULT_LOGS);
Expand Down
9 changes: 9 additions & 0 deletions apps/agx-web/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
Loading