Summary
The pi agent catalog fails to load when the active account's default model is a bare model id (e.g. deepseek-v4-flash), because the pi adapter requires provider/modelId format and throws, which fails the whole catalog. Separately, at startup the daemon reports @earendil-works/pi-coding-agent as missing (ERR_MODULE_NOT_FOUND) until the managed runtime asset is ready, producing repeated "Failed to load agent catalog" noise.
Environment
- LinkCode desktop 0.20.0
- Windows 11 x64
- Account created from the "opencode-go" service catalog:
{ "model": "deepseek-v4-flash", "endpoint": { "baseUrl": "https://opencode.ai/zen/go/v1", "protocol": "openai-chat" } }
Symptom
%APPDATA%\LinkCode\logs\main.log:
{"subsystem":"agent","operation":"agent.catalog","err":{"type":"Error",
"message":"pi: model must be 'provider/modelId' (got 'deepseek-v4-flash')",
"stack":"Error: pi: model must be 'provider/modelId' (got 'deepseek-v4-flash')
at createConfiguredRegistry (.../out/daemon/index.mjs:97941:11)
at PiAdapter.startCatalog (.../out/daemon/index.mjs:97993:17)"},
"msg":"Failed to load agent catalog"}
and, during the first ~20 s after startup:
"message":"pi: SDK '@earendil-works/pi-coding-agent' is unavailable (Error: Cannot find package '@earendil-works/pi-coding-agent' imported from .../out/daemon/index.mjs)"
"cause":{"code":"ERR_MODULE_NOT_FOUND"}
Root cause 1 — model format
PiAdapter.startCatalog → createConfiguredRegistry does:
const ref = opts.model ? parseModel(opts.model) : null;
if (!ref && opts.model) {
throw new Error(`pi: model must be 'provider/modelId' (got '${opts.model}')`);
}
opts.model is the account's default model, which service-catalog accounts store as a bare id (the correct format for the claude-code/codex/opencode CLIs that share the same account). A bare id makes pi's catalog throw, so the pi agent surface is entirely unavailable until the user manually sets the model to provider/modelId (e.g. opencode-go/deepseek-v4-flash).
Root cause 2 — SDK not bundled
PiAdapter.importSdk() first tries agentRuntimeProber.resolveEntry("pi") (the managed runtime asset) and only falls back to import("@earendil-works/pi-coding-agent"), which is not bundled in app.asar. Catalog retries fail with ERR_MODULE_NOT_FOUND until asset.ensure finishes ("Managed agent runtime ready", ~20 s after startup). If the managed runtime is GC'd by asset.gc (we observed "Removed superseded managed assets"), the errors return until the asset is re-ensured.
Repro
- Create an account from a service catalog with a bare default model (e.g.
deepseek-v4-flash).
- Enable the
pi provider.
- Restart the app; watch
agent.catalog errors in main.log.
Workaround
Set the account's model to provider/modelId format (e.g. opencode-go/deepseek-v4-flash) in the app settings or ~/.linkcode/config.json.
Suggested fix
- pi adapter: tolerate bare model ids by defaulting the provider to the account's service/endpoint name instead of throwing (or normalize the account model when configuring pi), so a shared account with a bare model id still produces a working catalog.
- Packaging: bundle
@earendil-works/pi-coding-agent in the app, or gate catalog errors on the managed-runtime readiness state to avoid the misleading ERR_MODULE_NOT_FOUND noise.
Summary
The
piagent catalog fails to load when the active account's default model is a bare model id (e.g.deepseek-v4-flash), because the pi adapter requiresprovider/modelIdformat and throws, which fails the whole catalog. Separately, at startup the daemon reports@earendil-works/pi-coding-agentas missing (ERR_MODULE_NOT_FOUND) until the managed runtime asset is ready, producing repeated "Failed to load agent catalog" noise.Environment
{ "model": "deepseek-v4-flash", "endpoint": { "baseUrl": "https://opencode.ai/zen/go/v1", "protocol": "openai-chat" } }Symptom
%APPDATA%\LinkCode\logs\main.log:and, during the first ~20 s after startup:
Root cause 1 — model format
PiAdapter.startCatalog→createConfiguredRegistrydoes:opts.modelis the account's default model, which service-catalog accounts store as a bare id (the correct format for the claude-code/codex/opencode CLIs that share the same account). A bare id makes pi's catalog throw, so the pi agent surface is entirely unavailable until the user manually sets the model toprovider/modelId(e.g.opencode-go/deepseek-v4-flash).Root cause 2 — SDK not bundled
PiAdapter.importSdk()first triesagentRuntimeProber.resolveEntry("pi")(the managed runtime asset) and only falls back toimport("@earendil-works/pi-coding-agent"), which is not bundled inapp.asar. Catalog retries fail with ERR_MODULE_NOT_FOUND untilasset.ensurefinishes ("Managed agent runtime ready", ~20 s after startup). If the managed runtime is GC'd byasset.gc(we observed "Removed superseded managed assets"), the errors return until the asset is re-ensured.Repro
deepseek-v4-flash).piprovider.agent.catalogerrors inmain.log.Workaround
Set the account's model to
provider/modelIdformat (e.g.opencode-go/deepseek-v4-flash) in the app settings or~/.linkcode/config.json.Suggested fix
@earendil-works/pi-coding-agentin the app, or gate catalog errors on the managed-runtime readiness state to avoid the misleading ERR_MODULE_NOT_FOUND noise.