| @@ -39,6 +39,50 @@ directory to route session and turn operations for a thread, so callers name a t · 38 unmodified lines |
| 39 | 39 | Adding a driver means writing the driver plus adapter and adding it to `BUILT_IN_DRIVERS`. No |
| 40 | 40 | orchestration, contract, or client change is required for the common case. |
| 41 | 41 | |
| 42 | +## OpenCode server ownership and catalog |
| 43 | + |
| 44 | +Each OpenCode provider instance owns one lazy local server for catalog discovery and |
| 45 | +text-generation helpers through [`OpenCodeServerOwner.ts`][opencode-server-owner]. Concurrent |
| 46 | +borrowers share startup. The server closes 30 seconds after the last borrower releases it, or |
| 47 | +when the provider instance closes. A failed or exited process can be started again on the next |
| 48 | +use. An externally configured OpenCode server remains externally owned. |
| 49 | + |
| 50 | +The local server and its SDK clients use one resolved password. An explicit provider password |
| 51 | +overrides `OPENCODE_SERVER_PASSWORD` in the spawned environment. Without an explicit password, |
| 52 | +the client uses the password from the environment that the process inherits. External servers use |
| 53 | +only their explicit provider password and never inherit the host's local password. |
| 54 | + |
| 55 | +Every server connection must pass the authenticated `/global/health` check before inventory or |
| 56 | +session operations start. The response must contain a valid version at or above 1.14.19. Local |
| 57 | +owners cache this result for the lifetime of the spawned process. External actions check once when |
| 58 | +they create their server connection, not for each model or SDK request. |
| 59 | + |
| 60 | +Chat adapters keep their own server per thread. They register a thread-specific `t3-code` MCP |
| 61 | +connection, while OpenCode stores MCP connections by directory. Sharing these chat servers |
| 62 | +without changing MCP routing would let two threads in one directory replace each other's |
| 63 | +connection. |
| 64 | + |
| 65 | +OpenCode loads its catalog through the HTTP API when an enabled provider instance starts. The |
| 66 | +provider registry keeps the snapshot in memory and persists it in the existing per-instance cache. |
| 67 | +Each `subscribeServerConfig` connection refreshes all providers, so a client reconnect reloads the |
| 68 | +OpenCode catalog from the current helper. The `serverRefreshProviders` request also refreshes it. |
| 69 | +Periodic OpenCode probes remain disabled. OpenCode reads credentials for each inventory request, |
| 70 | +but its native configuration files can remain cached for the lifetime of the helper process. The |
| 71 | +helper closes 30 seconds after its last inventory or text-generation borrower releases it. A |
| 72 | +refresh after that idle period starts a new helper and reads file changes. Repeated refreshes and |
| 73 | +active text-generation work can extend process reuse. Changes to the provider configuration or |
| 74 | +environment replace the instance and start a new discovery. Changes to unrelated settings only |
| 75 | +update snapshot enrichment. Other providers retain their existing refresh policy. |
| 76 | + |
| 77 | +T3 Code does not own an external OpenCode process. Native configuration changes there can require |
| 78 | +an external reload or restart before T3 Code's next refresh sees them. |
| 79 | + |
| 80 | +The shared server's idle shutdown does not clear the catalog. Failed discovery keeps the last |
| 81 | +known models, slash commands, and skills through the registry's existing merge rules. A successful |
| 82 | +empty inventory is authoritative. Existing threads keep their explicit model identifier and |
| 83 | +options when catalog metadata is missing; the catalog is not permission to choose a different |
| 84 | +model for a thread. |
| 85 | + |
| 42 | 86 | ## Model manifest |
| 43 | 87 | |
| 44 | 88 | The model picker's legacy section is driven by `apps/server/src/provider/model-manifest.json`, which |
| @@ -121,6 +165,7 @@ when a request opens (approval) or user input is requested, via · 76 unmodified lines |
| 121 | 165 | [cursor]: ../../apps/server/src/provider/Drivers/CursorDriver.ts |
| 122 | 166 | [grok]: ../../apps/server/src/provider/Drivers/GrokDriver.ts |
| 123 | 167 | [opencode]: ../../apps/server/src/provider/Drivers/OpenCodeDriver.ts |
| 168 | +[opencode-server-owner]: ../../apps/server/src/provider/OpenCodeServerOwner.ts |
| 124 | 169 | [adapter]: ../../apps/server/src/provider/Services/ProviderAdapter.ts |
| 125 | 170 | [instances]: ../../apps/server/src/provider/Services/ProviderInstanceRegistry.ts |
| 126 | 171 | [registry]: ../../apps/server/src/provider/Services/ProviderAdapterRegistry.ts |