# session_api — Shared OpenCode Server API Client Module

**Script name:** `session_api` (module — not a standalone CLI)

**Script location:** [`scripts/session_api.ts`](../../../scripts/session_api.ts)

This file is an **importable module only**. It is not meant to be run directly.
It is imported by every `session_*.ts` script.

## Purpose

Provides shared types, API client functions, and utility helpers for the
OpenCode Server at `localhost:4096`. Centralising all HTTP logic here means
every session script benefits from the same retry behaviour, JSON handling,
and type safety without duplication.

## Exports

### Constants

| Export | Value | Description |
|--------|-------|-------------|
| `DEFAULT_SERVER` | `http://localhost:4096` | Default OpenCode Server URL |

### Types

| Type | Description |
|------|-------------|
| `Session` | Full session object from `GET /session` or `POST /session` |
| `SessionStatus` | `{ type: 'busy' \| 'idle' }` |
| `AllStatuses` | `Record<session_id, SessionStatus>` from `GET /session/status` |
| `SessionWithStatus` | `Session` enriched with `tag`, `status`, and `last_active` |
| `MessageInfo` | Message metadata (`id`, `role`, `agent`, `time`, etc.) |
| `MessagePart` | One content unit within a message |
| `Message` | Full API message object (`{ info, parts }`) |
| `FormattedMessage` | Reduced message: `{ role, agent, text, time }` |
| `HealthDataEntry` | Session + status + recent messages for health classification |
| `SessionActionResult` | Result of a stop/delete action on one session |

### API Functions

| Function | Endpoint | Description |
|----------|----------|-------------|
| `listSessions(server)` | `GET /session` | List all sessions |
| `createSession(server, title)` | `POST /session` | Create a new session |
| `getAllStatuses(server)` | `GET /session/status` | Get all session statuses |
| `getSession(server, id)` | `GET /session/{id}` | Get a single session (throws on 404) |
| `promptAsync(server, id, agent, text)` | `POST /session/{id}/prompt_async` | Launch an agent async (fire-and-forget) |
| `getMessages(server, id, limit?)` | `GET /session/{id}/message` | Get session messages, optionally limited |
| `deleteSession(server, id)` | `DELETE /session/{id}` | Delete a session |

### Utility Functions

| Function | Description |
|----------|-------------|
| `extractTag(title)` | Extract `[TAG]` from `"[TAG] display-name"` → `"TAG"`, or `null` |
| `sleep(ms)` | Promise-based delay |
| `formatMessages(messages)` | Reduce `Message[]` to `FormattedMessage[]` (text parts joined) |
| `withStatuses(sessions, statuses)` | Merge sessions and status map into `SessionWithStatus[]` |
| `parseServerFlag(argv)` | Strip `--server URL` from argv, return `{ server, rest }` |
| `getFlag(args, flag)` | Get the value of a named flag from a flat args array |
| `hasFlag(args, flag)` | Return `true` if a boolean flag is present |

## Retry Behaviour

`apiRequest` (internal) retries up to **3 times** with delays of **2 s, 5 s, 10 s**
between attempts before throwing. All exported API functions inherit this behaviour.
Network timeouts are set to **30 seconds** per request.

## Usage

```typescript
import {
  listSessions,
  getAllStatuses,
  withStatuses,
  type SessionWithStatus,
} from './session_api.ts';

const sessions = await listSessions('http://localhost:4096');
const statuses = await getAllStatuses('http://localhost:4096');
const enriched: SessionWithStatus[] = withStatuses(sessions, statuses);
```

## Dependencies

- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution (when imported by a script)
- Zero external npm packages
