Skip to content
Draft
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
77 changes: 67 additions & 10 deletions desktop/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,85 @@
# openmud Desktop

Desktop app that loads openmud.ai. Built with Electron.
Electron desktop app for openmud.

## Local dev
## Local development

### Full stack (web API + desktop shell)

From repository root:

**Full stack (matches production):**
```bash
npm run dev
```
Runs vercel dev + desktop. Desktop loads localhost:3947. Add `OPENAI_API_KEY` to `web/.env`.

**Desktop only** (hits production API):
This runs the local web app and launches desktop pointed at local web (`PORT=3947` in dev scripts).

### Desktop app only

```bash
cd desktop && npm start
cd desktop
npm start
```

## Build .dmg (macOS only)
This launches the desktop shell directly.

## Build outputs (macOS)

From `desktop/`:

```bash
npm run build:dmg
```

Output: `dist/mudrag-1.0.0.dmg`
Default artifact location: `desktop/dist/` (for example `openmud-<version>.dmg` and/or zip artifacts, depending on build mode).

## Local signed + notarized build

Use when testing signing locally (without GitHub Actions secrets):

1. Copy `desktop/.env.signing.example` to `desktop/.env.signing`.
2. Fill `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, and `APPLE_TEAM_ID`.
3. Run:

```bash
cd desktop
npm run build:local
```

This uses `scripts/build-signed-local.js` to build, notarize, staple, and verify a zip artifact.

## Release runbook

From repository root:

```bash
npm run release:desktop
```

Optional version bump arg:

```bash
npm run release:desktop patch
npm run release:desktop minor
npm run release:desktop major
```

What this does:

1. Bumps `desktop/package.json` version.
2. Commits the version bump.
3. Creates and pushes tag `desktop-v<version>`.
4. Triggers `.github/workflows/release-desktop.yml`.

## CI behavior

`release-desktop.yml` builds on macOS when a `desktop-v*` tag is pushed (or manually via workflow dispatch).

- If signing secrets are present, CI builds signed `zip` and `dmg`.
- If signing secrets are absent, CI builds unsigned app bundle and zips `openmud.app`.

## CI
## Common pitfalls

GitHub Actions builds the .dmg on release. See `.github/workflows/desktop.yml`.
1. Packaging scripts currently assume Node 20 for deterministic desktop build/test flow (`scripts/build-and-verify.sh` enforces this).
2. Missing Apple signing credentials will produce unsigned output in CI/local.
3. Auto-update checks use `/api/desktop-version`; releases without zip/dmg assets will not be picked up by updater endpoints.
169 changes: 115 additions & 54 deletions docs/API.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,147 @@
# openmud Chat API Contract
# openmud API Notes

The frontend calls `POST /chat` on the Contech API. Backend should support:
This document covers the current serverless API under `web/api`.
It focuses on the routes that drive chat, model access policy, usage limits, desktop updates, and project/chat sync.

## Where to put API keys
## Runtime and config

**Never put API keys in the chat or in the frontend.** They would be exposed in logs, browser dev tools, and chat history.
- Deploy target: Vercel serverless functions in `web/api`.
- Local env template: `web/.env.example`.
- Required for chat: at least one of `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
- Required for authenticated usage tracking and dashboards: `SUPABASE_URL`, `SUPABASE_SERVICE_ROLE_KEY`.

Put keys in your **openmud Vercel project** (the `/api` serverless functions use them):
## Core chat route

1. **Vercel** – Project → Settings → Environment Variables
2. **Local** – Copy `config/env.example` to `.env` (add `.env` to `.gitignore`)
`POST /api/chat`

```
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
```

The frontend never sees or sends keys—it only sends the model name. The backend picks the key based on the model.

## Request body
### Request body

```json
{
"messages": [{"role": "user|assistant", "content": "..."}],
"model": "gpt-4o-mini|mud1|claude-3-5-haiku-20241022|...",
"messages": [{ "role": "user|assistant|system", "content": "..." }],
"model": "mud1",
"temperature": 0.7,
"max_tokens": 512,
"use_tools": true,
"available_tools": ["build_schedule", "render_proposal_html", "estimate_project_cost", ...]
"max_tokens": 1024,
"use_tools": false,
"estimate_context": null,
"stream": false,
"project_id": "optional-project-id"
}
```

## Model routing
### Provider override headers (BYOK)

- **mud1** – openmud custom model (in development)
- **gpt-*** – OpenAI API (OPENAI_API_KEY)
- **claude-*** – Anthropic API (ANTHROPIC_API_KEY)
- `X-OpenAI-Api-Key`
- `X-Anthropic-Api-Key`
- `X-Grok-Api-Key`
- `X-OpenRouter-Api-Key`
- `X-OpenClaw-Api-Key`
- `X-OpenClaw-Base-Url`
- `X-OpenClaw-Model`
- `X-Openmud-Relay-Token`
- `X-Client-Date` (calendar intent timezone helper)

## Tool calling
### Auth and model policy

When `use_tools: true`, OpenAI and Anthropic models run tool-calling with:
Policy is enforced in `web/api/chat.js` + `web/api/lib/model-policy.js`:

1. Enable function/tool calling for the selected model
2. Load schemas from `tools/registry.py` through `GET /api/python/registry`
3. Execute estimating tools through `POST /api/python/tools`
4. Return the tool result in the response
1. `mud1` is hosted and free (`hosted_free`).
2. Hosted beta models are platform-hosted with daily caps (`hosted_beta`).
3. Premium/non-hosted models require BYOK (`byok`).
4. Desktop agent model (`openclaw`) is treated as `desktop_agent`.

## Response
Auth behavior:

```json
{
"response": "Assistant message text",
"tools_used": ["build_schedule", "estimate_project_cost"]
}
```
1. Hosted requests require authenticated user context.
2. BYOK requests can run without sign-in.
3. Hosted beta requests allocate usage before model execution.

## Python tool executor
### Response shape

`POST /api/python/tools`
Base response:

```json
{
"tool_name": "calculate_labor_cost",
"arguments": {
"labor_type": "operator",
"hours": 40,
"region": "utah"
}
"response": "Assistant text",
"tools_used": []
}
```

## Tool registry endpoint
Optional fields returned for specific flows:

- `rag`: mud1 retrieval metadata (`confidence`, `fallback_used`, `sources`).
- `_proposal_html`: proposal/document generation HTML payload.
- `_choices`: disambiguation choices (for relay contact ambiguity).

### Important behavior

- `mud1` path runs RAG with optional project context merge.
- `stream=true` is only supported when `use_tools=false`.
- Relay token path can execute email/calendar/iMessage workflows through local agent relay.
- Usage events are logged when user context is present.

## Related platform routes

### `GET /api/platform`

Returns public platform policy and model catalog:

- `default_model`
- `tier_limits`
- policy notes (`mud1 free`, hosted beta limits, BYOK support)
- `models` with `access` classification

### `GET|POST /api/usage`

- `GET`: current daily usage (`used`, `limit`, `tier`, `date`)
- `POST`: allocate usage (unless `increment=false`) and optionally log usage event

### `GET /api/dashboard?days=30`

Per-user analytics from `usage_events`:

- totals
- daily breakdown
- by model/source/usage kind
- recent events

Returns `needs_setup: true` when usage tables are missing.

## Agentic step route (desktop/tool loop)

`POST /api/agentic-step`

- Requires authenticated user.
- Allocates usage using the same limit path as chat.
- Calls Anthropic with a fixed agentic tool set for one step.
- Returns `{ stop_reason, text, tool_calls, content, usage }`.

## Project and message sync routes

- `GET|POST|PUT /api/projects`
- `GET|POST|PUT /api/chat-messages`

Both require authenticated user and Supabase service role access.
Both enforce project ownership (`user_id`) before read/write.

## Desktop delivery routes

- `GET /api/desktop-version`: latest desktop version metadata for updater.
- `GET /api/download-desktop`: redirect to latest zip (or dmg fallback).
- `GET /api/download-dmg`: dmg download endpoint (supports proxy streaming with `GITHUB_TOKEN`).

`GET /api/python/registry`
## Setup runbook: usage tables

Returns OpenAI-compatible function schemas from `tools/registry.py`.
If dashboard or usage APIs indicate setup is missing:

## Tool telemetry endpoint
1. Open Supabase SQL editor for the project.
2. Run `web/api/lib/migrations/003_combined_setup.sql`.
3. Re-test `GET /api/dashboard`.

`GET /api/tool-metrics`
## Common pitfalls

Returns in-memory metrics for:
- tool success/error rate
- fallback rate when tools were enabled
- tool latency and recent errors
1. `401` on `/api/chat`: hosted request without auth session.
2. `403` on `/api/chat`: model requires BYOK key, but no provider key header was supplied.
3. `429` on `/api/chat`: hosted beta daily cap reached.
4. `needs_setup: true` on dashboard: usage migrations not applied.
5. Relay automation failures with `openclaw`: missing/invalid `X-Openmud-Relay-Token` or no connected Mac agent.
34 changes: 28 additions & 6 deletions scripts/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
# Scripts

Build and utility scripts for the openmud project.
Build, release, and maintenance scripts used from the repository root.

| Script | Purpose |
|--------|---------|
| `release-desktop.js` | Bump version, commit, tag, push → triggers GitHub Actions to build .dmg. Run via `npm run release:desktop` |
| `make_favicon.py` | Generate favicon assets for the web app |
| `make_logo_transparent.py` | Process logo for transparency |
## Common developer flows

| Command | What it runs | Purpose |
|---|---|---|
| `npm run dev` | `scripts/dev-wrapper.sh` | Start local web + desktop dev workflow. |
| `npm run dev:test` | `scripts/dev-and-test.sh` | Start dev environment and run validation checks. |
| `npm run build:test` | `scripts/build-and-verify.sh` | Build unsigned desktop app bundle, zip, and verify archive integrity. |
| `npm run release:desktop` | `scripts/release-desktop.js` | Bump desktop version, commit, tag, and push (`desktop-v*`) to trigger release workflow. |

## Script inventory

| File | Purpose |
|---|---|
| `scripts/release-desktop.js` | Desktop release automation (version bump + git tag/push). |
| `scripts/build-signed-local.js` | Local signed + notarized desktop build using keychain cert + `.env.signing`. |
| `scripts/build-and-verify.sh` | Local unsigned packaging test (`openmud.app` zip smoke check). |
| `scripts/dev-wrapper.sh` | Root dev bootstrap used by `npm run dev`. |
| `scripts/dev-from-symlink.sh` | Local static/site dev helper used by `dev:site`. |
| `scripts/dev-and-test.sh` | Combined dev/test helper. |
| `scripts/smoke-test.js` | Smoke checks for local build/runtime behavior. |
| `scripts/site-bot.js` | Synthetic site checks used in CI and local QA. |
| `scripts/setup-auth.js` | Auth setup helper for local/dev environment. |
| `scripts/generate-apple-jwt.js` | Utility for generating Apple auth JWTs. |
| `scripts/install-latest-dmg.sh` | Download/install latest desktop DMG helper. |
| `scripts/after-pack.js` | Electron post-pack hook used during desktop build. |
| `scripts/make_favicon.py` | Favicon generation utility. |
| `scripts/make_logo_transparent.py` | Logo processing utility. |