caopu16/dsh-llm-kiro

DeepSeek-Harness插件,可使用Kiro模型(Claude系列)及账号。

项目介绍Project Overview

这是 DSH 的 AWS Kiro(CodeWhisperer)适配器插件,注册 kiro provider,复用本机 Kiro 登录令牌,无需单独 API 密钥即可在 harness 中调用 Claude 与开放权重模型,并支持代理、区域、推理强度等配置。适合已登录 Kiro、想把其模型接入 DSH 时使用。注意:Claude 模型需自备允许出口的 HTTP/HTTPS 代理,否则报 INVALID_MODEL;令牌用量仅按上下文占比推算,输出 token 计为零。

A DSH plugin adapter for AWS Kiro (CodeWhisperer), registering the kiro provider so a signed-in local Kiro account serves Claude and open-weight models to the harness without a separate API key. Use it when Kiro is installed and signed in and you want those models available in DSH. Configure proxy, region, reasoning effort, and model catalog as needed. Caveat: Claude models require a permitted HTTP/HTTPS egress proxy or requests fail with INVALID_MODEL; usage reports only context occupancy, with output tokens counted as zero.

或使用命令行安装(适合开发者)Or use CLI install (for developers)

命令行安装CLI Install

dsh plugin --profile web add github:caopu16/dsh-llm-kiro

caopu16/dsh-llm-kiro 加入你的 DSH 配置(web profile)即可启用。

READMEREADME

dsh-llm-kiro

English | 中文

An AWS Kiro (CodeWhisperer) adapter for the DeepSeek Harness LLM seam. It registers the kiro provider route, so a signed-in Kiro account serves Claude and open-weight models to the harness without a separate API key.

Requirements

  • A working dsh install (this package is a plugin, not a standalone tool).
  • A Kiro sign-in on the same machine. The Kiro IDE or kiro-cli writes the tokens this adapter reads; it never stores a second copy of the credential.
  • For Claude models: a permitted network egress. See Why Claude needs a proxy.

Install

dsh plugin --profile web add github:caopu16/dsh-llm-kiro

That is the whole install, and upgrading is the same command again. Built lib/ is committed to the repository precisely so a git-sourced install runs no build script: pnpm 10 and later block dependency build scripts until each is allowlisted by a key carrying its resolved commit, which would make every upgrade a manual allowlist edit.

The package declares its own patch layer, so installing it mounts the adapter — no cordis.yml editing required to make the route exist. Add configuration only for the facts this package deliberately leaves empty.

Without the dsh command

dsh on PATH comes from an installed @deepseek-ai/dsh. When you are working from a harness source checkout instead, run the CLI from that checkout and every command above works unchanged:

cd /path/to/deepseek-harness
pnpm dsh plugin --profile web add github:caopu16/dsh-llm-kiro
pnpm dsh --profile web

A source checkout requires pnpm run build first, since the profile loads built lib/ rather than TypeScript sources.

Developing this plugin

lib/ is committed, so a change to src/ reaches consumers only after it is rebuilt and committed too:

npm install
npm run build
npm test

Configure

Kiro authorizes Claude models by request egress, and the permitted egress differs per deployment, so no proxy is shipped as a default. Put yours in the llm-kiro: section of $DSH_HOME/settings.yaml (~/.dsh/settings.yaml):

llm-kiro:
  proxyUrl: http://proxy.example:1082
  reasoningEffort: medium

This is the recommended home for every field below. The plugin registers llm-kiro as a settings namespace, so the section reloads without a restart, it outranks the composition entry, and it is what the web Models page writes.

Note that --dump-config prints the composition tree only, so a field configured here does not appear there. To confirm the proxy is in use, ask a claude-* model something: without a permitted egress it fails with INVALID_MODEL.

Every field is optional:

Field Default Meaning
proxyUrl none (direct) Egress for every Kiro request, http:// or https://, with optional user:pass@. An invalid value fails plugin loading.
region the signed-in token's region Selects the q.<region>.amazonaws.com endpoint.
profileArn the signed-in client's own ARN CodeWhisperer profile the account bills against; discovered from Kiro's profile.json, so set this only to override it.
thinking enabled disabled locks every request to effort off.
reasoningEffort off off, low, medium, or high.
defaultContextWindow 200000 Capacity used for a model with no exact value.
models the verified account tier Advisory catalog for model selectors; unlisted ids still reach the wire.
streamIdleTimeoutMs 300000 Maximum provider idle time while one read is outstanding.
tokenExpiryBufferMs 300000 Refresh the access token this long before expiry.
retryPolicy bounded normal Provider-owned retry policy, executed by dsh-llm-retry.

Configuring in the profile instead

A deployment that wants the proxy pinned to one profile, rather than to the machine, can patch the row in ~/.dsh/profiles/<name>/cordis.patch.yml instead:

- id: llm-kiro
  config:
    proxyUrl: http://proxy.example:1082

Two cautions. The entry targets the existing row by id — do not wrap it in an insert: list, because this package's own patch layer already inserts llm-kiro, and a second insert of the same id fails the whole profile at boot with duplicate loader entry id: llm-kiro. And a patch layer only takes effect on restart, whereas the settings section reloads live.

Configure any one field in one place. A field set in both is not an error — the settings section simply wins — but changing the patch layer then appears to do nothing.

Use

Select provider kiro and any model id it serves:

claude-opus-5     claude-opus-4.8    claude-opus-4.7   claude-opus-4.6  claude-opus-4.6-1m
claude-opus-4.5   claude-sonnet-5    claude-sonnet-4.6 claude-sonnet-4.6-1m
claude-sonnet-4.5 claude-sonnet-4    claude-haiku-4.5  auto
deepseek-3.2      glm-5              minimax-m2.5      qwen3-coder-next

Model ids are passed through as the wire modelId, so a model Kiro adds later works without upgrading this package. The shipped catalog is advisory only: an unlisted id still reaches the service, and the ids above are the ones one account tier was observed to accept. minimax-m2.1 is omitted because the service reports it temporarily unavailable, and the -1m variants of Sonnet 4.5, Sonnet 5, and Opus 4.8 because it rejects them as unknown — another tier may differ.

Why Claude needs a proxy

Kiro authorizes model families by request egress, not only by account entitlement. From an unauthorized egress every claude-* id is refused with INVALID_MODEL while the open-weight ids answer normally; through a permitted egress the same account and token reach the whole catalog. proxyUrl therefore exists for correctness, not performance, and the open-weight models need no proxy at all.

The proxy is opened as an HTTP CONNECT tunnel with TLS negotiated inside it, so the proxy sees only the target host name, never request contents or the bearer token.

Credentials

The adapter reads ~/.aws/sso/cache/kiro-auth-token.json plus the sibling device-registration file it names. When the stored access token is still valid it is used as-is; otherwise the adapter exchanges the refresh token for a fresh one and caches that in memory only. Kiro owns those files and writes them from its own sign-in, so writing back would race a process this plugin does not coordinate with.

The profile ARN is discovered the same way, from the profile.json the signed-in Kiro client writes under its globalStorage (~/.kiro-server/data/User/globalStorage/kiro.kiroagent/, then ~/.kiro/...). This is required rather than convenient: an IdC or Enterprise account has no implicit default profile, and a request naming none is refused with 403 User is not authorized to make this call. A personal account needs no profile, so a missing or malformed file is not an error — the request simply carries none. Configuration outranks discovery: set profileArn only to override it.

A missing sign-in fails the first request with MISSING_CREDENTIAL naming the expected path, rather than failing at load or silently producing nothing.

Model Experience

Kiro request

What the model sees. Kiro has no system slot, so the harness system prompt is prepended to the earliest user turn, where thinking markers also go. History is folded into the strict user/assistant alternation the service requires; a gap becomes a [system: conversation continues] placeholder. Tool schemas ride on the current turn. A tool result whose issuing call is absent from history (compaction dropped it) is carried as text, because the service rejects the unmatched id.

Token effect. Provider tokenization governs exact input. The thinking markers add a fixed short prefix at any effort above off; placeholders add a few tokens per gap.

KV Cache effect. Kiro assigns a fresh conversationId per request and this adapter does not replay provider-side conversation state, so cache reuse is the service's own concern. Keeping the system prompt on the earliest turn preserves a stable prefix.

Kiro response

What the model sees. The response is a vnd.amazon.eventstream frame sequence. Text and thinking share one channel delimited by <thinking> markers; the adapter routes them into harness text and reasoning blocks, holding back only a tail short enough to be a partial marker so a marker split across frames is still recognized. The open-weight routes additionally leak a <|DSML| tool-call preamble into that channel, which is suppressed as a prompt-format artifact.

Token effect. Kiro reports context occupancy, not token counts: each response stream ends with a contextUsageEvent carrying the percentage of the model's context window the request consumed, and the adapter emits it as a usage chunk by multiplying that percentage by the model's window. Output tokens and cache splits are not reported and are counted as zero.

KV Cache effect. Loop-retained blocks append to the next request like any other adapter's.

Errors

AUTH (401, or a 403 naming an invalid bearer token), FORBIDDEN (other 403s, including an unentitled subscription), RATE_LIMIT (429), INVALID_MODEL (a 400 whose body names INVALID_MODEL_ID — usually an unauthorized egress), INVALID_REQUEST (other 400s), SERVER (5xx). Transport failures throw TRANSPORT naming the target host; caller aborts throw ABORTED. Protocol violations raise STREAM_CLOSED (a stream ending mid-frame) or MALFORMED_RESPONSE (a bad frame header or payload). A stream that completes with no content at all finishes as EMPTY_RESPONSE.

Known Limitations and Deferred Work

  • Coarse token usage. Kiro reports only the percentage of the context window a request consumed, so the emitted usage chunk carries the derived input count and a zero output count: pressure tracking is accurate, billing-style breakdowns are not.
  • No image input. Image content is refused with UNSUPPORTED_CONTENT rather than silently flattened, though the wire operation does accept images.
  • Tool names must match ^[A-Za-z][A-Za-z0-9_]{0,63}$. A name that does not is aliased by replacing every illegal character with _ (so mcp__a-b__c-d goes on the wire as mcp__a_b__c_d) and reversed before dispatch; only a name no alias can rescue (empty, over-long, or not starting with a letter) is refused with UNSUPPORTED_TOOL_NAME. Two names that alias to the same wire name in one turn collide, last one wins.
  • SOCKS proxies are unsupported. Only http:// and https:// egress; a SOCKS proxy would need a dependency this package avoids.
  • Thinking effort is a prompt marker, not a request field. The budgets are fixed per effort level and the service may ignore them.
  • The shipped model catalog reflects one verified account tier. Another tier may serve more or fewer ids; the catalog is advisory and unlisted ids pass through.

License

MIT

上一个 Prev dsh-workbench 下一个 Next dsh-human-coding