Skip to content
Merged
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
103 changes: 78 additions & 25 deletions docs/deployment/CLOUD_RUN_DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,36 @@ This guide walks you through deploying Jiva as a stateless, auto-scaling service
## Architecture Overview

```
┌─────────────┐
Client
│ (React UI) │
└──────┬──────┘
│ WebSocket/HTTP
┌─────────────┐ ┌─────────────┐
Tenant A │ │ Tenant B
│ (React UI) │ │ (React UI) │
└──────┬──────┘ └──────┬──────┘
│ WebSocket/HTTP
┌──────────────────────────────────────┐
│ Cloud Run Service │
│ ┌────────────────────────────────┐ │
│ │ Jiva HTTP/WebSocket Server │ │
│ │ - Session Manager │ │
│ │ - DualAgent Instances │ │
│ │ - StorageProvider │ │
│ │ - SessionManager │ │
│ │ ├─ Session(tenantA) │ │
│ │ │ ├─ ScopedStorageProvider│ │ ← isolated per tenant
│ │ │ ├─ OrchestrationLogger │ │ ← isolated per session
│ │ │ └─ DualAgent │ │
│ │ └─ Session(tenantB) │ │
│ │ ├─ ScopedStorageProvider│ │
│ │ ├─ OrchestrationLogger │ │
│ │ └─ DualAgent │ │
│ └────────────┬───────────────────┘ │
└───────────────┼──────────────────────┘
┌───────────────────────┐
│ GCS Bucket │
- Conversations
- Configuration
- Workspace Files
- Logs
└───────────────────────┘
┌───────────────────────────────────
│ GCS Bucket
{tenantId}/config.json │ ← per-tenant MCP + LLM config
{tenantId}/conversations/
{tenantId}/directives/
{tenantId}/logs/
└───────────────────────────────────
```

## Prerequisites
Expand Down Expand Up @@ -138,7 +144,7 @@ Key environment variables are set in `cloud-run.yaml`:

| Variable | Description | Default |
|----------|-------------|---------|
| `JIVA_STORAGE_PROVIDER` | Storage backend | `gcp` |
| `JIVA_STORAGE_PROVIDER` | Storage backend | `gcp-bucket` |
| `JIVA_GCP_BUCKET` | GCS bucket name | `jiva-state-{project}` |
| `MAX_CONCURRENT_SESSIONS` | Max sessions per instance | `100` |
| `SESSION_IDLE_TIMEOUT_MS` | Session timeout | `1800000` (30 min) |
Expand Down Expand Up @@ -369,20 +375,67 @@ Common causes:
- Configure VPC connector if needed
- Use Cloud Armor for DDoS protection

## Multi-Tenant Configuration

Each tenant's MCP servers, LLM model, and directives are driven by a single JSON file stored in GCS at `{tenantId}/config.json`. The file is read fresh on every new session creation (the in-memory cache is invalidated per tenant). If the file is missing, the service falls back to the server-level defaults from environment variables.

### Per-Tenant config.json

Upload to `gs://your-bucket/{tenantId}/config.json`:

```json
{
"models": {
"reasoning": {
"endpoint": "https://api.groq.com/openai/v1/chat/completions",
"apiKey": "gsk_...",
"model": "openai/gpt-oss-120b"
},
"multimodal": null
},
"mcpServers": [
{
"name": "tavily-mcp",
"command": "npx",
"args": ["-y", "tavily-mcp@latest"],
"env": { "TAVILY_API_KEY": "tvly-..." }
},
{
"name": "filesystem",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
]
}
```

```bash
gsutil cp config.json gs://your-bucket/my-tenant/config.json
```

### Session Isolation Model

Every HTTP session gets its own storage provider instance that shares the stateless GCS client and per-tenant config cache, but holds a fixed, immutable context (`tenantId` + `sessionId`). Concurrent requests from different tenants can never corrupt each other's GCS paths. See [release notes v0.3.46](../release_notes/v0.3.46.md) for full details.

### Per-Tenant Directives

Store a workspace directive at `{tenantId}/directives/{hash}.md`. It is loaded automatically on session start and shapes agent behaviour for that tenant. Upload via:

```bash
gsutil cp my-directive.md gs://your-bucket/my-tenant/directives/$(echo -n "$(cat my-directive.md)" | md5sum | cut -d' ' -f1).md
```

---

## Next Steps

1. **React UI Integration**
- See `docs/REACT_INTEGRATION.md` (TODO)

2. **Custom MCP Servers**
- Add MCP server configs to GCS
- Upload to `gs://bucket/config/mcpServers.json`

3. **Multi-tenancy**
- Configure tenantId extraction from JWT
- Implement per-tenant quotas
2. **Per-Tenant Quotas**
- Implement rate limiting / token budget checks in `SessionManager.getOrCreateSession()`

4. **Monitoring & Alerting**
3. **Monitoring & Alerting**
- Setup Cloud Monitoring dashboards
- Configure alerting policies

Expand Down
42 changes: 34 additions & 8 deletions docs/guides/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -662,18 +662,44 @@ For the full reference see [Code Mode Architecture](../architecture/CODE_MODE.md

## Cloud Run Configuration

For Cloud Run deployments, configuration is loaded dynamically from GCS bucket using the StorageProvider. See [CLOUD_RUN_DEPLOYMENT.md](./CLOUD_RUN_DEPLOYMENT.md) for details.
For Cloud Run deployments, configuration is loaded dynamically from GCS using a per-session scoped `StorageProvider`. See [CLOUD_RUN_DEPLOYMENT.md](../deployment/CLOUD_RUN_DEPLOYMENT.md) for full deployment details.

### Configuration storage path

All per-tenant configuration lives in a **single JSON file** per tenant:

Configuration storage path:
```
gs://your-bucket/{tenantId}/config/models.json
gs://your-bucket/{tenantId}/config/mcpServers.json
gs://your-bucket/{tenantId}/config.json
```

The SessionManager automatically:
1. Loads config from storage on session creation
2. Falls back to environment variables if not found
3. Saves default config back to storage
The file combines model config and MCP server list — there is no separate `models.json` / `mcpServers.json` split.

### What SessionManager does on session creation

1. Calls `storageProvider.createSessionScoped({ tenantId, sessionId })` to get an isolated provider instance with a fixed, immutable GCS path prefix — concurrent tenants can never corrupt each other's paths.
2. Reads `{tenantId}/config.json` from GCS (cache is invalidated per-tenant on each new session).
3. Falls back to server-level environment variables (`JIVA_MODEL_*`, etc.) if no per-tenant config file is found.
4. Saves the resolved config back to `{tenantId}/config.json` so subsequent sessions inherit it.

### Uploading per-tenant config

```bash
cat > config.json <<'EOF'
{
"models": {
"reasoning": {
"endpoint": "https://api.groq.com/openai/v1/chat/completions",
"apiKey": "gsk_...",
"model": "openai/gpt-oss-120b"
}
},
"mcpServers": [
{ "name": "tavily-mcp", "command": "npx", "args": ["-y", "tavily-mcp@latest"], "env": { "TAVILY_API_KEY": "tvly-..." } }
]
}
EOF
gsutil cp config.json gs://your-bucket/my-tenant/config.json
```

### Programmatic Configuration

Expand Down
44 changes: 44 additions & 0 deletions docs/release_notes/v0.3.45.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Jiva v0.3.45 — Windows Compatibility Fixes for Code Mode

**Release Date:** May 8, 2026

---

## Bug Fixes

### Code mode wrote files to `/workspace/` instead of the actual workspace directory on Windows

**Symptom:** On Windows, Jiva code mode correctly displayed the workspace directory (e.g. `C:\Users\<user>\myproject`) at startup, but then wrote and edited files under `C:\workspace\...` instead.

**Root cause:** The `read_file` tool description contained hardcoded example paths:
```
Example: {"path": "/workspace/src/index.ts"}
```
The LLM pattern-matched against these examples when generating tool calls, producing `/workspace/...` paths rather than paths relative to the actual workspace. On Windows, Node.js treats `/workspace/src/index.ts` as an absolute path (root of the current drive), so `path.isAbsolute()` returned `true` and `workspaceDir` was bypassed entirely.

**Fix:** The example paths in the `read_file` tool description are now relative (`src/index.ts`), which the tool resolves correctly against the workspace directory on all platforms. (`src/code/tools/read.ts`)

---

### Shell commands failed on Windows due to `cmd.exe` being used instead of PowerShell

**Symptom:** The `bash` tool executed commands via `cmd.exe` on Windows. Commands using common shell syntax (`&&` chaining, `$VAR` substitution, pipes) failed or produced unexpected results.

**Fix:** On Windows, the `bash` tool now explicitly uses `powershell.exe` as the shell, which supports the developer workflows (npm, git, build tools) that code mode relies on. (`src/code/tools/bash.ts`)

---

### `grep` results showed Windows-style backslash paths, causing path inconsistency

**Symptom:** On Windows, `grep` returned match locations like `src\file.ts:5: content` (backslashes), while other tools returned forward-slash paths. This inconsistency could cause the LLM to mix path separator styles across tool calls.

**Fix:** `grep` output now normalises relative paths to forward slashes on all platforms. (`src/code/tools/grep.ts`)

---

## Upgrade

```bash
# This bug fix version was only released as a dev release and will be bundled into v0.3.46
npm install -g jiva-core@0.3.45-dev.53be99d
```
Loading
Loading