feat(agent): unify models and validate OpenCode providers
Generate chat, task and learning models from agent-models.json. Use WaterNetwork fast/expert models with 272k context and validate upstream names before readiness. Add an isolated model check command with signal-safe cleanup and plugin, Skill and MCP management docs. Verified in isolation: type checks, 26 focused tests and both model catalog checks; no model inference requests.
This commit is contained in:
@@ -1,59 +1,185 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure
|
||||
## Scope and Structure
|
||||
|
||||
This is the experimental TJWater supply Agent service. Runtime TypeScript lives
|
||||
in `src/`; opencode agent assets live in `.opencode/`; tests live in `tests/`.
|
||||
The project intentionally has no `cli/` directory and no user-auth middleware.
|
||||
This repository is the experimental TJWater supply Agent service. Keep drainage
|
||||
data, workflows, layer IDs, and terminology in the drainage repositories.
|
||||
Read [README.md](README.md) for setup, configuration, and operational behavior.
|
||||
|
||||
Key boundaries:
|
||||
- `src/server.ts` assembles dependencies and starts the service.
|
||||
- `src/routes/` owns HTTP/SSE wiring; keep orchestration thin.
|
||||
- `src/context/` owns local and Server-verified request context.
|
||||
- `src/product/` owns typed TJWater Server adapters and business contracts.
|
||||
- `src/frontendAction/` owns controlled browser actions and their receipts.
|
||||
- `src/uiEnvelope/` owns the `agent-ui@1` compatibility protocol and registry.
|
||||
- `src/runtime/` owns OpenCode lifecycle, readiness, and workspace binding.
|
||||
- `src/sandbox/` and `scripts/landlock_sandbox.py` own Shell enforcement.
|
||||
- `src/sessions/`, `src/results/`, `src/memory/`, and `src/learning/` retain their
|
||||
respective persistence responsibilities.
|
||||
- `.opencode/` contains trusted service instructions, plugins, and tools.
|
||||
- `.opencode/agent-plugin.json` describes agents, plugins, Skill storage, and MCP
|
||||
configuration sources; `.opencode/README.md` explains their management.
|
||||
- `tests/` contains focused tests and opt-in native integration scripts.
|
||||
|
||||
- `src/context/` owns local request context.
|
||||
- `src/uiEnvelope/` owns the `agent-ui@1` protocol, registry, and tool mapping.
|
||||
- `src/routes/` owns HTTP/SSE wiring.
|
||||
- `src/results/`, `src/sessions/`, `src/memory/`, and `src/learning/` keep their existing persistence responsibilities.
|
||||
Use TypeScript ESM, two-space indentation, kebab-case module filenames, and
|
||||
explicit types at public boundaries. Preserve established service patterns
|
||||
before adding new abstractions. Backend access must use typed tools/adapters;
|
||||
do not introduce `cli/`, `tjwater_cli`, or a free-form business command bridge.
|
||||
The existing approved sandbox Shell is the only local command execution path.
|
||||
|
||||
Generated `data/`, `logs/`, and dependency folders must not be committed. Keep
|
||||
drainage datasets, drainage workflows, and drainage-network terminology out of
|
||||
this repository.
|
||||
## Model Configuration
|
||||
|
||||
## Commands
|
||||
`agent-models.json` is the single model configuration source. An explicit
|
||||
`AGENT_MODEL_CONFIG_PATH` selects a complete replacement; relative paths resolve
|
||||
from the process working directory. `agent-models.local.json` is ignored by Git
|
||||
and the Docker build.
|
||||
|
||||
Use Bun:
|
||||
- Define provider IDs, `api_url`, API key references, models, aliases, capabilities,
|
||||
limits, and chat/task/learning role defaults in that file.
|
||||
- Generate OpenCode definitions and the public chat model menu from it through
|
||||
`src/chat/modelConfig.ts` and `src/runtime/opencode2-config.ts`.
|
||||
- Do not add independent model defaults in `opencode.json`, agent frontmatter,
|
||||
routes, learning code, or environment variables. Legacy `OPENCODE_MODEL`,
|
||||
`OPERATIONAL_TASK_MODEL`, and `OPENCODE_MODEL_OPTIONS` no longer select models.
|
||||
- Use `model_id` when the Agent-facing name differs from the upstream name;
|
||||
preserve existing public references when correcting upstream aliases.
|
||||
- Keep real API keys in ignored `.local.env` or deployment environment variables;
|
||||
use `{env:NAME}` references in model files. Existing system environment values
|
||||
take precedence over `.local.env`.
|
||||
- Never return provider URLs, keys, headers, or effective credential settings in
|
||||
model menus, validation reports, status endpoints, or logs.
|
||||
|
||||
After model/provider changes, run `bun run check:models`. It launches an isolated
|
||||
OpenCode and validates all non-disabled models, including hidden task/learning
|
||||
models, against effective native definitions and upstream `/models` inventories.
|
||||
A self-declared `model.list` entry alone is not validation. `disabled` skips a
|
||||
model; `selectable: false` only hides it from the chat menu and does not skip it.
|
||||
Do not use paid inference as the default configuration check.
|
||||
|
||||
The checker lives in `.opencode/model-check.ts`, with shared report/target types
|
||||
in `src/runtime/model-check.ts` and the command in `scripts/check-models.ts`.
|
||||
Preserve safe errors and cancellation. SIGINT/SIGTERM must abort model checking,
|
||||
wait for its owned OpenCode process to exit, and clean its temporary directories.
|
||||
Unsupported catalogs, absent upstream
|
||||
names, authentication failures, and invalid inventories must fail validation.
|
||||
Changes require an Agent restart; client mode also requires synchronized external
|
||||
OpenCode configuration and plugins.
|
||||
|
||||
## Runtime and Security
|
||||
|
||||
Production chat requests require Bearer authorization and `X-Project-Id`, verified
|
||||
by TJWater Server. Preserve actor/project/user ownership checks on session create,
|
||||
read, actions, and MCP status. Development-only local context does not grant
|
||||
business-data access. Never accept a tool-supplied identity, project scope,
|
||||
authorization header, or arbitrary Server URL.
|
||||
|
||||
Complete the OS sandbox probe, OpenCode health check, warmup session, business
|
||||
tool discovery, enabled-model validation, workspace-root check, and MCP
|
||||
configuration check before HTTP starts listening. A failure must fail startup.
|
||||
Preserve `/health` fields `ready`, `warmed_up`, and `sandbox`.
|
||||
|
||||
Use the V2 SDK and trusted plugin registration. A cold Location may need plugin
|
||||
initialization before its tool/model catalog is usable. Verify actual tool IDs;
|
||||
a version string or MCP connection status alone does not prove availability.
|
||||
Keep native call IDs and the existing frontend SSE contracts.
|
||||
|
||||
Client mode requires the same stable `AGENT_INTERNAL_TOKEN` in both processes,
|
||||
the external OpenCode server password, and trusted assets loaded through
|
||||
`serviceOpencodeConfig`. Its absolute `TJWATER_AGENT_WORKSPACE_ROOT` must match
|
||||
the Agent workspace root. Prefer `bun run start:integration:isolated` when an
|
||||
existing user service must remain available. Stop only processes started for the
|
||||
current task; do not terminate unrelated services.
|
||||
|
||||
Preserve static sensitive-path denials in `opencode.json`, explicit approval for
|
||||
Shell/file edits, and disabled subagents. Do not replace enforcement with prompt
|
||||
instructions. The Shell replacement must retain Landlock/seccomp, credential
|
||||
isolation, cancellation, process-group cleanup, and denied alternate host Shell
|
||||
entry points. Code Mode must not bypass these controls.
|
||||
|
||||
## Workspaces and Persistence
|
||||
|
||||
`CONVERSATION_WORKSPACE_ROOT` defaults to `.agent-workspaces/`, separate from
|
||||
protected `data/` and `logs/`. `src/runtime/conversationWorkspace.ts` creates one
|
||||
`conversation-<uuid>` per native session, with writable `files/`, `tmp/`, and
|
||||
`.cache/`; the location root is read-only and Shell starts in `files/`.
|
||||
|
||||
Keep canonical-path and symlink checks, per-session access restrictions, native
|
||||
session directory bindings, and empty independent workspaces for new branches.
|
||||
Do not copy source code, credentials, or other sessions into a workspace.
|
||||
|
||||
Workspaces contain persistent session files. They currently have no expiration
|
||||
cleanup, and deleting chat metadata does not remove their directories. Do not
|
||||
clean them as build artifacts or describe them as automatically disposable.
|
||||
Startup probes, warmup, and failed creation clean their own temporary workspaces.
|
||||
Changing the root requires preserving directory bindings and associated native
|
||||
session data; do not silently move or delete existing user files.
|
||||
|
||||
Deployment must preserve the workspace, Agent data, Skill files, and OpenCode
|
||||
session database. Mounting only `/app/data` does not preserve session files.
|
||||
Result-reference TTL cleanup is separate from workspace retention.
|
||||
|
||||
## MCP and Business Boundaries
|
||||
|
||||
Keep the `.opencode/agent-plugin.json` descriptor and package descriptions aligned
|
||||
with actual IDs and paths when agent/plugin assets change. The descriptor is a
|
||||
documentation index, not a runtime configuration file or native OpenCode plugin
|
||||
manifest. Do not duplicate model definitions, Skill inventories, MCP connections,
|
||||
or credentials in it. Use the established configuration builder and source files.
|
||||
Skill storage is shared by the deployment instance; do not describe it as isolated
|
||||
per user or project, and preserve the existing validated persistence workflow.
|
||||
|
||||
Configure external MCP only through administrator-owned `mcp.servers` in
|
||||
`opencode.json` or `OPENCODE_CONFIG_CONTENT`; server names use the `mcp_` prefix.
|
||||
Preserve exact read-only tool allow rules, interactive approval outside that
|
||||
allowlist, read-only background task access, and disabled MCP in learning review.
|
||||
Broad wildcard allows and server `readOnlyHint` values are not read-only grants.
|
||||
Apply the same policy to Code Mode and generic MCP resource access.
|
||||
|
||||
Local stdio MCP is a trusted host process, not a sandbox Shell process. Preserve
|
||||
its explicit environment filtering and never forward Agent/OpenCode credentials.
|
||||
Return only sanitized server status and actual tool IDs to the browser.
|
||||
|
||||
Keep business state authoritative in Server. Background execution uses persisted
|
||||
`task_id`, `run_id`, and `execution_request_id`, with explicit claim, heartbeat,
|
||||
and complete/fail transitions. Plans, reports, browser receipts, and final text
|
||||
are distinct from execution completion. See [docs/execution-plan.md](docs/execution-plan.md)
|
||||
and [docs/agent-ui-protocol.md](docs/agent-ui-protocol.md).
|
||||
|
||||
## Commands and Verification
|
||||
|
||||
Run commands from this repository with Bun:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
bun run dev
|
||||
bun run start
|
||||
bun run check
|
||||
bun test tests/**/*.test.ts
|
||||
bun run check:models
|
||||
bun run start:integration:isolated
|
||||
```
|
||||
|
||||
`bun run dev` starts `src/server.ts` in watch mode. `bun run check` runs
|
||||
TypeScript checks for the main project and `.opencode`.
|
||||
`bun run check` type-checks both the service and `.opencode`; this repository has
|
||||
no separate lint command. Run focused tests for the changed behavior. For model
|
||||
and readiness changes, the relevant suite is:
|
||||
|
||||
## Coding Notes
|
||||
```bash
|
||||
bun test tests/chat/models.test.ts tests/opencode/modelCheck.test.ts tests/runtime/opencode.test.ts tests/runtime/modelCheckCommand.test.ts tests/frontendAction/callIdPlugin.test.ts
|
||||
```
|
||||
|
||||
Use TypeScript ESM and keep types explicit at module boundaries. Preserve the
|
||||
local service patterns before adding new abstractions. Do not reintroduce
|
||||
free-form CLI command execution; future backend access should use typed tools or
|
||||
adapters.
|
||||
Do not over-test reversible low-impact edits. Documentation-only changes need
|
||||
local link/path and command validation plus `git diff --check`, without starting
|
||||
services or calling providers. Tests must not depend on mutable `data/` files.
|
||||
Use opt-in native smoke scripts only when actual integration behavior needs
|
||||
verification; configuration/catalog checks must not invoke model inference.
|
||||
|
||||
## Tests
|
||||
## Repository Hygiene and Delivery
|
||||
|
||||
Add focused Bun tests for route behavior, runtime/session state, result refs,
|
||||
and UIEnvelope mapping. Tests must not depend on mutable files under `data/`.
|
||||
Never commit secrets, private environment files, generated runtime data, logs,
|
||||
dependencies, `.agent-workspaces/`, session dumps, or result references. Avoid
|
||||
printing private configuration contents while inspecting a workspace.
|
||||
|
||||
## Security
|
||||
|
||||
This experimental service has no user authentication. Do not add secrets,
|
||||
tokens, passwords, API keys, session dumps, or generated result references to
|
||||
the repository. Keep `.env`, `data/`, and `logs/` statically denied in
|
||||
`opencode.json`; do not replace those denials with prompt-only guidance. Keep
|
||||
arbitrary Bash and edit operations approval-gated and subagents disabled.
|
||||
|
||||
## Runtime Readiness
|
||||
|
||||
Complete the OpenCode health check, warmup session, and model tool discovery
|
||||
before the HTTP server starts listening. A warmup failure must fail startup.
|
||||
Once listening, `/health` must expose the `ready` and `warmed_up` readiness
|
||||
fields used by deployment checks.
|
||||
Preserve unrelated dirty and untracked work. Keep `README.md` useful to people:
|
||||
configuration locations, runnable setup steps, model checks, workspace retention,
|
||||
and current capabilities. Update it when those operational behaviors change.
|
||||
Use concise Conventional Commit subjects and scope commits to requested files.
|
||||
Do not push or deploy without authorization for the current task.
|
||||
|
||||
Reference in New Issue
Block a user