Skip to content

research provider model params

sinrimin edited this page Oct 20, 2026 · 1 revision

Research — provider model registry parameters × per-agent support (2026-10-15)

Status 2026-10-15: the serverTools candidate design below shipped as issue #56 — durable version in design-server-tools.md. The other follow-ups remain open.

How each ProviderModelConfig field (#51 registry) is actually consumed by the platform assistant and each client Agent target, and what each target's native config could additionally express. Research only — no code changed, no decisions made here. Companion docs: design-provider-model-registry.md (the registry), design-phase-9-w10-llm-providers.md (providers), design-phase-9-harness-runtime.md §4.3 (the W3 push).

Method — three-way cross-verification:

  • Local code: server/src/assistant/provider.ts (assistant model construction), cli/src/daemon/runtime-config.ts (the five W3 writers), core/src/domain/{llm-provider,runtime-config}.ts, shared zod schemas.
  • Rig container (read-only): the installed pi bundle's TypeBox ModelsConfigSchema (pi 0.85.1), @deepseek-ai/dsh-llm-pi-ai .d.ts declarations (dsh 0.2.0-rc.2), config-key strings in the codex binary (codex-cli 0.154.0). Versions in the container: pi 0.85.1, dsh 0.2.0-rc.2, codex-cli 0.154.0, opencode 1.18.31.
  • Web/doc verification (Oct 2026): Claude Code official docs (line 2.1.296), openai/codex config reference + codex-rs source (master @3ee47c1, tag rust-v0.154.0 diffed), sst/opencode source at v1.18.31/v1.19.0/ master + https://opencode.ai/config.json, @earendil-works/pi-ai@1.1.0 and @earendil-works/pi-coding-agent@1.1.0/1.2.0 npm tarballs, @deepseek-ai/dsh-*@0.2.0-rc.2 npm tarballs.

Version anchors worth remembering: the pi repo moved (badlogic/pi-mono → earendil-works/pi); pi-coding-agent npm latest is 1.2.0 while the rig runs 0.85.1 (1.x models.json adds inputLimits + promptCache, otherwise the schema below is the same); dsh bundles pi-ai 0.87.x, not 1.x; opencode 1.19.0's provider/model schema is byte-identical to 1.18.31 (master is the "V2" rewrite — re-verify wire behavior before any major pin bump); codex keys below are unchanged between 0.154.0 and 0.162.1.

1. Current wiring (what the code does today)

Registry fields per model: regular displayName, contextWindow, maxOutputTokens, vision (+ id, type chat|embedding); advanced temperature (0–2), topP (0–1), serverTools (meaningful for openai-responses only), extraBody (meaningful for openai-compatible only). The web dialog exposes all of them; api-irrelevant combos WARN, never reject.

  • Assistant (provider.ts): the only full consumer. Regular fields → pi-ai Model (fallbacks 128k/8192 when unset). Advanced fields → per- request injection in streamFn: temperature → StreamOptions.temperature; topP/extraBody → samplingParams (top_p + verbatim merge); serverTools → samplingParams.tools = [{type}] (responses kind only).
  • W3 push: the spec snapshot carries modelEntries — the regular-fields subset only; advanced params never leave the server (by design). Writer utilization differs sharply per target (matrix below).

2. Support matrix

✅ consumed today · 🟡 expressible on the target but not written today · ❌ no surface on that target (silently ineffective) · ⚠️ has a defect/gate

Field Assistant (pi-ai 1.1.0) claude-code opencode 1.18.31 codex 0.154.0 dsh 0.2.0-rc.2 pi client 0.85.1
displayName ✅ Model.name ❌ ✅ name 🟡 model_catalog_json display_name only 🟡 models entry name ✅ name
contextWindow ✅ (fallback 128k) ✅ env CLAUDE_CODE_MAX_CONTEXT_TOKENS (#60 panel; [1m] is the alternative) ✅ limit.context (informational only) 🟡 root key model_context_window 🟡 models entry contextWindow (route default 262,144) ✅ contextWindow
maxOutputTokens ✅ (fallback 8192) ✅ env CLAUDE_CODE_MAX_OUTPUT_TOKENS (#60 panel, global) ✅ limit.output ⚠️ real cap, globally clamped to 32,000 ❌ key removed; unknown keys silently ignored 🟡 models entry maxTokens (becomes per-request default; route default 32,768) ✅ maxTokens
vision ✅ input:['text','image'] ❌ (tier _SUPPORTED_CAPABILITIES is an effort/thinking-style list, not modality) 🟡 modalities.input:['image'] / attachment:true ❌ 🟡 models entry input ✅ input
temperature ✅ all three wires ⚠️ anthropic gate (§4.1) 🟡 env CLAUDE_CODE_EXTRA_BODY (one global JSON, not per-model) 🟡 entry temperature is a BOOLEAN capability gate; the value lives in agent.<name>.temperature ❌ no config key, no body passthrough ❌ programmatic GenerateOptions only; no producer sets it ❌ no static field anywhere; per-request RPC options only
topP ✅ openai wires only (anthropic ignores samplingParams entirely) 🟡 same EXTRA_BODY 🟡 agent.<name>.top_p only ❌ ❌ 🟡 per-model samplingParams (openai wires only)
serverTools ⚠️ defect — §4.2 ❌ ❌ (responses excluded for opencode) ❌ (despite being the Responses target) ❌ 🟡 would ride samplingParams.tools — same clobber risk as §4.2
extraBody ✅ openai wires only ✅ env CLAUDE_CODE_EXTRA_BODY (#60 panel, global blob) 🟡 models.<id>.options → verbatim body keys on the openai-compatible wire ❌ (responses_api_metadata is a string map, not body) ❌ 🟡 per-model samplingParams
model list (W13) ✅ picker ✅ availableModels (documented allowlist semantics) ✅ provider models map 🟡 model_catalog_json (whole-catalog replace) vs today's ACP-only rewrite ✅ models: list ✅ models[] + enabledModels

3. Per-target ground truth

3.1 Assistant (pi-ai 1.1.0, in-process)

  • StreamOptions.temperature is first-class; all three adapters forward it into the request body. The anthropic-messages adapter gates it: temperature !== undefined && !thinkingEnabled && compat.supportsMidConvoEffort !== true && compat.supportsTemperature — i.e. it is silently DROPPED when thinking is enabled, on managed mid-conversation-effort models, and on models whose compat flags it off (the flag doc: "Claude Opus 4.7+ rejects non-default temperature values").
  • StreamOptions.samplingParams is merged into the request body by the OpenAI-compatible adapters ONLY (completions, responses, azure-responses); the anthropic-messages adapter has zero references to it — topP/ extraBody/serverTools silently vanish on the anthropic wire.
  • Model.samplingParams / samplingParamsByThinkingLevel / compat exist on the Model type (and in pi's models.json — §3.6) but the assistant's provider build sets none of them.

serverTools upstream history (pi issues, checked 2026-10-15). Three community proposals exist, all auto-closed no-action by the repo's contribution gate (github-actions[bot]; CONTRIBUTING: "All issues and PRs from new contributors are auto-closed by default. Maintainers review auto-closed issues daily and reopen worthwhile ones") and never reopened:

  • #9560 + PR #9556 (2026-09-13, closed in seconds, merged: false) — Model.serverTools in models.json/modelOverrides: raw API-native tool entries APPENDED verbatim to the request's tools array by the openai-responses AND anthropic-messages transports (follows the samplingParams/headers passthrough precedent; replaces wholesale in modelOverrides). Empirically verified by the author: GLM coding plan executes {"type":"web_search"} on its Responses proxy (api.z.ai/api/v1), Anthropic executes web_search_20250305 on the Messages wire; server-side output items (web_search_call / server_tool_use) are already harmlessly ignored by pi's stream processing. The author also ran it as an extension ("wrap the built-in transport, inject the tool") — the pattern that works WITHOUT core support, and exactly the seam our buildGatewayModel already has (we pass the api module into createProvider, so a wrapper adapter can append entries to the request tools before calling through).
  • #7704 (2026-08) — same concept as builtinTools inside OpenAIResponsesCompat (DeepSeek V4 Flash web_search motivation); auto- closed, not adopted.
  • #8661 (2026-08) — client tools NAMED web_search are rejected by Responses upstreams ("custom function name "web_search" is reserved", upstream-dependent); proposed translating such client tools into the native {type:"web_search"} inside convertResponsesTools. Not adopted either, but the reserved-name 400 is a live wire constraint.

Net: no released pi-ai (1.1.0/1.2.0) and no master packages/ai carries server-side tool support (the lone serverTools code hit is an unrelated local variable in the MCP extension). The append-not-replace semantics and the both-wires scope of PR #9556 are the reference design if we ever fix our assistant mapping; note Anthropic's dated tool types (web_search_20250305) mean our bare-string serverTools list would need full entry values to cover the anthropic wire.

3.2 claude-code (verified against the 2.1.205 binary + official env-vars/model-config docs; our writer: settings.json env)

Writer today (#60): env.ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEY (panel-chosen slot), optional ANTHROPIC_BASE_URL, model, availableModels, plus the spec.claudeCode knobs — tier pins, [1m] markers, subagent, token caps, extra body, six behavior switches (see design-claude-code-config.md for the full map). Additional verified surface (all settable from the same settings.json we already own):

  • ANTHROPIC_DEFAULT_{SONNET,OPUS,FABLE,HAIKU}_MODEL — alias-tier pins, each with _NAME / _DESCRIPTION / _SUPPORTED_CAPABILITIES companions that DO take effect on gateways (ANTHROPIC_BASE_URL third-party). The capabilities value is a comma-separated list (effort,thinking example; open vocabulary — declares which capabilities the pinned model supports). A fifth slot ANTHROPIC_CUSTOM_MODEL_OPTION (+ companions) adds one custom /model picker entry (unused by us: allowlist + tiers supersede it).
  • The [1m] suffix — claude-code's 1M-context switch on a model alias or full name (sonnet[1m], gw-plus[1m]): the id is sent marker-stripped with the context-1m-2025-08-07 beta, and for ids it does not know it ASSUMES a 1M window (then CLAUDE_CODE_MAX_CONTEXT_TOKENS does NOT apply; CLAUDE_CODE_DISABLE_1M_CONTEXT turns the variants off).
  • CLAUDE_CODE_SUBAGENT_MODEL (+ _FORCE) — subagent default model.
  • CLAUDE_CODE_MAX_OUTPUT_TOKENS — request output cap; unresolvable model ids default 32,000, cap 128,000. One global value (not per-model).
  • CLAUDE_CODE_MAX_CONTEXT_TOKENS — overrides the assumed context window; for unrecognized non-claude- ids (i.e. gateway aliases — our case) it applies directly. Also CLAUDE_CODE_DISABLE_UNKNOWN_MODEL_WINDOW_ENFORCEMENT.
  • CLAUDE_CODE_EXTRA_BODY — a JSON object merged into the top level of EVERY request body; the documented escape hatch for provider-specific parameters. Could carry temperature/top_p/extraBody keys, but it is one global blob per install — per-model values would collide across the switchable set.
  • Behavior switches (#60 ground truth, cc-switch's live writer agrees): settings attribution = {commit:'', pr:'', sessionUrl:false} hides attribution (successor of the deprecated includeCoAuthoredBy); CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1; ENABLE_TOOL_SEARCH=true (UNPREFIXED — its documented spelling); CLAUDE_CODE_EFFORT_LEVEL (low/medium/high/xhigh/max); DISABLE_AUTOUPDATER=1 (unprefixed); CLAUDE_CODE_DISABLE_ARTIFACT=1 (settings disableArtifact equivalent).
  • availableModels semantics confirmed: restricts the /model picker AND --model/env/setting values, subagent/skill model pins (our W13 usage is the documented pattern; enforceAvailableModels exists for managed locks); a tier pin the allowlist rejects would dead-letter the alias — our writer unions every managed id into the list, markers stripped.
  • No surface for: per-model display names or vision/capability declarations behind a gateway beyond the tier _NAME/_SUPPORTED_CAPABILITIES pins (gateway discovery reads only id/display_name/description from the gateway's own /v1/models response; CLAUDE_CODE_ENABLE_GATEWAY_MODEL_ DISCOVERY=1 populates the picker from it — unused by us).
  • Deprecated trivia: ANTHROPIC_SMALL_FAST_MODEL → ANTHROPIC_DEFAULT_HAIKU_MODEL (our writer retires the legacy key on sight).

3.3 opencode (1.18.31; schema identical on 1.19.0 and master)

provider.<id>.models.<modelId> is additionalProperties: false; accepted keys: id (wire-id override), name, family, release_date, attachment, reasoning (BOOLEAN capability), temperature (BOOLEAN capability — gates whether agent temperature is sent at all), tool_call, interleaved, cost, limit (context + output REQUIRED, input?), modalities, experimental, status, provider, options (Record<string,any>), headers, variants. Entries MERGE onto the models.dev catalog entry of the same id (per-field ??, deep-merge for options/headers/variants).

  • Sampling VALUES live in agent.<name>.temperature / agent.<name>.top_p (+ agent.<name>.options), not on the model entry; the model entry's temperature: true only enables sending. We write no agent config today.
  • limit.output is a real request cap: maxOutputTokens = min(limit.output, OUTPUT_TOKEN_MAX) with a hardcoded global OUTPUT_TOKEN_MAX = 32000 (env OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX overrides); it also sizes anthropic thinking budgets. limit.context is informational (context-remaining UI, auto-compaction) and never sent.
  • Extra-body equivalent: models.<id>.options merges into the providerOptions[<provider>] namespace and @ai-sdk/openai-compatible spreads every unknown key VERBATIM into the JSON body (this is how opencode's own enable_thinking/chat_template_args reach the wire). No such passthrough for the @ai-sdk/anthropic flavor. Caveat: a temperature key inside model options would override the explicit agent param on the openai-compatible wire.
  • Vision is expressible (modalities.input: ['image'] or attachment: true) — our writer currently omits it.

3.4 codex (0.154.0; keys unchanged through 0.162.1)

Writer today (post-#63): root model + model_provider + the [model_providers.harness_nexus] block + auth.json, PLUS the #63 panel dials (model_reasoning_effort / model_reasoning_summary / model_verbosity / model_context_window / model_auto_compact_token_limit / check_for_update_on_startup) — see design-codex-config.md. Additional surface:

  • Root key model_context_window EXISTS in 0.154.0 (overrides the catalog's context window; clamped to the catalog's max_context_window; unknown models fall back to 272k metadata). Single global value per config.
  • model_max_output_tokens does NOT exist (zero occurrences in the repo; serde does not deny unknown fields, so a stale key is silently ignored).
  • No temperature/top_p anywhere (config, request payloads, docs). No arbitrary body merge: responses_api_metadata is a validated string map attached as client metadata, not body; query_params/http_headers are URL/headers.
  • model_catalog_json (root or profile; landed 2026-02, present in 0.154.0): path to a JSON file in the Codex-native ModelsResponse shape ({models: [{slug, display_name, description, default_reasoning_level, supported_reasoning_levels, visibility, context_window, max_context_window, …}]}). It REPLACES the whole catalog for the process (startup-only, ≥1 model). The in-session /model picker lists from it (or from <provider.base_url>/models — which must speak the Codex-native shape, not OpenAI /v1/models). This is the natural landing spot for our registry's model list + displayName + contextWindow — and it would silence the codex-acp "Model metadata for <id> not found" notices (chat.ts CODEX_MODEL_METADATA_NOTICE). Not used by our writer today. #63 verdict: rejected for now — the catalog owns the SYSTEM PROMPT. ModelInfo deserialization REQUIRES each entry to carry base_instructions (or model_messages.instructions_template — the deserializer errors "missing both"), and get_model_instructions returns the template VERBATIM (no template → empty instructions + warn). There is no built-in-prompt fallback on that path, so owning the catalog means freezing codex's instruction text per version — fragile. Stays a design question.
  • disable_response_storage is REMOVED (source-verified 2026-10-16: zero occurrences in 0.154's root config AND ModelProviderInfo; absent from the current official config reference). cc-switch's codex template still writes it at root — a silently-ignored dead key on current codex (serde does not deny unknown fields). Do not copy it.
  • Reasoning dials that exist but have no registry counterpart: model_reasoning_effort (open-ended enum; docs list minimal–xhigh), model_verbosity (low|medium|high), [profiles.<name>] pinning model+effort+verbosity (profiles notably do NOT carry model_context_window).

3.5 dsh (0.2.0-rc.2; llm-pi-ai plugin; bundles pi-ai 0.87.x)

Writer today (post-#64): settings.yaml llm-pi-ai.providers.harness-nexus with displayName/api/baseURL/apiKeyEnv and per-model detail on the models: entries (name / contextWindow / maxTokens / input for vision, precedence panel > #51 seed > omitted — bare ids stay byte-identical for untouched specs; see design-deepseek-config.md). The plugin's actual PiAiModelProfile also accepts per entry: reasoningEfforts (false | level→wire map) and compat (incl. supportsTemperature, thinkingFormat, chatTemplateKwargs) — both OUT of #64 v1 (per-gateway wire spellings we cannot guess; follow-ups).

Provider-level extras on the route: defaultContextWindow (default 262,144), defaultMaxTokens (default 32,768), defaultInput, compat, headers, reasoning (route thinking level), thinkingBudgets, cacheRetention, transport, timeouts, image budgets, retryPolicy. Unset model fields default from the installed catalog entry of the same id (our route ids are unknown to the catalog, so entries really start empty).

No sampling knobs: no temperature/top_p/samplingParams anywhere in the settings schema. The internal seam (GenerateOptions.temperature) is programmatic only; no dsh producer sets it. dsh-llm's own README: sampling is temperature/maxTokens/stop only, "the vocabulary grows when a producer lands".

3.6 pi client (rig 0.85.1; npm latest 1.2.0)

models.json is JSONC validated by a compiled TypeBox schema (ModelConfig.load). Provider fields: name, baseUrl, apiKey, api, oauth, headers, compat, authHeader, models[], modelOverrides{}. Per-model: id (required), name, api, baseUrl, reasoning, thinkingLevelMap, input, cost, contextWindow, maxTokens, samplingParams (free Record<string,unknown>), samplingParamsByThinkingLevel, headers, compat (1.x adds inputLimits, promptCache). Sampling merge order (pi-ai resolveSamplingParams): {...model.samplingParams, ...samplingParamsByThinkingLevel[level], ...requestParams}.

  • Our writer already lands name/contextWindow/maxTokens/input when present (#65 adds the panel overlay spec.pi.models + the panel-only reasoning flag and samplingParams free body keys — see design-pi-config.md).
  • topP/extraBody COULD ride per-model samplingParams — effective on the openai wires, silently ignored on anthropic (same semantics as the assistant; consistent with the registry's warn-not-reject stance) (shipped #65 as the panel's 采样参数 editor).
  • serverTools has no dedicated field; riding samplingParams.tools has the same clobber risk as §4.2.
  • temperature has NO static surface: not in models.json, not in settings.json (55 fields, none sampling), no CLI flag, no TUI knob. Only per-request options carry it (the RPC request-options struct does — a seam our daemon-side PiRpcConnection could theoretically drive).

4. Defects / surprises found

  1. Assistant serverTools clobbers the agent's own tools (pi-ai 1.1.0). In openai-responses.js the client tools are built first (params.tools = convertResponsesTools(...), ~L258) and Object.assign(params, samplingParams) runs LAST (~L287, "Last so model and request sampling parameters override named request fields") — a shallow merge that REPLACES the tools array. The assistant sends its AgentTools (M2 MCP bridge + read_skill) on every turn, so any registry entry with serverTools set strips them all. The #51 S0 spike verified the seam exists but not the merge semantics. (Same risk exists for pi clients via samplingParams.tools.)
  2. Anthropic-wire temperature is silently gated in the assistant (thinking enabled / supportsTemperature off / mid-convo-effort models → dropped), and topP/extraBody are silently ignored on that wire. The web dialog warns only for serverToolsIrrelevant and extraBodyIrrelevant — these two paths have no warning.
  3. Fallback divergence: the assistant and the opencode writer fall back to 128k/8192 for unsized models; dsh's own defaults are 262,144/32,768; codex assumes 272k for unknown ids. Not a bug, but a dsh push of an entry without contextWindow makes dsh assume 262k where the assistant would assume 128k — same registry row, different effective window.

5. Follow-up options (tiered, undecided)

  • Tier 1 — pure wins, no design tradeoff: dsh writer emits name/contextWindow/maxTokens/input per models entry (shipped #64 — panel value > #51 seed > omitted); opencode writer adds vision (modalities/attachment); codex writer adds root model_context_window from the default model's entry (shipped #63 — panel value > seed > key-removed, with the full dial set).
  • Tier 2 — small tradeoffs to write down: claude-code writer derives CLAUDE_CODE_MAX_OUTPUT_TOKENS / CLAUDE_CODE_MAX_CONTEXT_TOKENS / CLAUDE_CODE_EXTRA_BODY from the DEFAULT model's entry (all three are one-global-value-per-install — extras in the switchable set do not benefit; needs explicit doc); pi writer maps topP/extraBody into per-model samplingParams.
  • Fix-first: the §4.1/§4.2 assistant issues. For serverTools the upstream reference is PR #9556 (§3.1): APPEND raw tool entries to the request tools — implementable without forking pi-ai by wrapping the api adapter module we already pass into createProvider (the same "extension wraps the transport" pattern the pi contributor shipped); extending the registry value shape (full entries, not bare strings) is a prerequisite for the anthropic wire's dated tool types. The §4.1 warning gap (temperature/topP silently dropped on the anthropic wire) is a shared-code warning addition.
  • Candidate design for serverTools + extraBody (2026-10-15, simplified — supersedes the earlier union-with-alias-map sketch): ONE reusable creatable multi-select interaction (chosen items render as removable × tags, arbitrary typed values allowed) for BOTH fields, with preset option lists per api kind, baselined on Alibaba Bailian/Model Studio (docs.bailian.console.aliyun.com/zh/model-studio/web-search, 2026-10):
    • serverTools (value stays string[], wire-ready WYSIWYG — no alias map, no request-build translation): openai-responses presets web_search / web_extractor / code_interpreter; anthropic preset IS the dated wire value web_search_20250305 (picked from the list, never hand-typed; Bailian notes the date suffix is client-version- dependent and not server-validated; extra fields like max_uses are deliberately out of scope for the string form); openai-chat has NO tools[]-shaped server tools on this wire — hint text instead, because Bailian's chat-wire search rides body params.
    • extraBody (扩展参数, same interaction): keys are tag-selected with presets per kind — openai-chat: enable_search / search_options / enable_text_image_mixed / enable_thinking; openai-responses: enable_thinking; anthropic: none — then each selected key gets a value editor (toggle for known booleans, JSON input otherwise). On the openai-chat wire this field is not merely an escape hatch: it is the ONLY carrier for Bailian-style search. Typed custom entries in either combobox ARE the gateway-compat escape hatch (a future dated alias, a vendor-specific tool name) — no separate full-object arm. With append-injection in place (§3.1 adapter-wrapper fix), serverToolsIrrelevant narrows to openai-chat. Reserved-name 400s (client tool literally named web_search on a Responses wire, #8661) accepted as low priority: MCP bridge tools are <server>__<tool>- prefixed, only custom tool names can collide, and the upstream error message is self-explanatory.
  • Design questions, not urgent: adopting codex model_catalog_json (solves multi-model + displayName + the metadata-not-found notices, at the cost of owning the WHOLE catalog replacement); whether assistant advanced params deserve a third warning class (temperature×anthropic×thinking).

6. Sources

  • Claude Code: code.claude.com/docs/en/{model-config, settings, settings-reference, env-vars, llm-gateway, llm-gateway-protocol}; anthropics/claude-code CHANGELOG.
  • codex: developers.openai.com/codex/{config-reference, config-schema.json}; github.com/openai/codex codex-rs/{config/src/config_toml.rs, config/src/profile_toml.rs, model-provider-info, models-manager, model-provider, protocol/src/openai_models.rs}; discussion #7782.
  • opencode: opencode.ai/docs/{providers, config, agents, tui}; opencode.ai/config.json; github.com/sst/opencode at v1.18.31 (packages/core/src/v1/config/{provider,agent}.ts, packages/opencode/src/session/llm{,/request}.ts, packages/opencode/src/provider/{provider,transform}.ts); @ai-sdk/openai-compatible@2.0.41 dist.
  • pi: npm @earendil-works/pi-ai@1.1.0 dist (types.d.ts, api/*.js, api/simple-options.js) + @earendil-works/pi-coding-agent@1.1.0/1.2.0 (dist/core/model-config.js, settings-manager.d.ts); rig bundle (pi 0.85.1 TypeBox schema); github.com/earendil-works/pi.
  • dsh: npm @deepseek-ai/dsh-llm-pi-ai@0.2.0-rc.2 (lib/types/*.d.ts + lib/index.js) + dsh-llm/dsh-agent/dsh-settings tarballs; github.com/deepseek-ai/deepseek-harness; rig install.

Clone this wiki locally