ns-dsh-llm-kiro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ngosangns
4
+ Copyright (c) 2025-2026 Mike O'Brien (pi-provider-kiro)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # ns-dsh-llm-kiro
2
+
3
+ Kiro (AWS CodeWhisperer/Q) as a provider route in the
4
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
5
+
6
+ Kiro speaks its own streaming protocol — AWS event-stream framing over
7
+ `generateAssistantResponse` — which no configurable route can describe, so this
8
+ registers a real `LlmAdapter` rather than a profile on a generic one.
9
+
10
+ ## Install
11
+
12
+ Not on npm yet — install from a clone of
13
+ [ns-kiro-provider](https://github.com/ngosangns/ns-kiro-provider):
14
+
15
+ ```bash
16
+ kiro-cli login
17
+ pnpm install && pnpm -r build
18
+ dsh plugin --profile <profile> add link:$PWD/packages/dsh-llm-kiro
19
+ ```
20
+
21
+ `link:` rather than a tarball because `ns-dsh-llm-kiro` depends on the unpublished
22
+ `ns-kiro-core`; the link resolves it out of the workspace.
23
+
24
+ Add the row to that profile's `cordis.patch.yml`:
25
+
26
+ ```yaml
27
+ - insert:
28
+ - id: llm-kiro
29
+ name: 'ns-dsh-llm-kiro'
30
+ config:
31
+ provider: kiro
32
+
33
+ - id: agent-default-model
34
+ config:
35
+ provider: kiro
36
+ model: claude-sonnet-4-6
37
+ ```
38
+
39
+ Verify the composition, then run:
40
+
41
+ ```bash
42
+ dsh --profile <profile> --dump-config | grep -A3 llm-kiro
43
+ dsh --profile <profile> "what changed in this repo?"
44
+ ```
45
+
46
+ ## Configuration
47
+
48
+ | Key | Default | Meaning |
49
+ | --- | --- | --- |
50
+ | `provider` | `kiro` | Provider route the adapter registers under |
51
+ | `displayName` | `Kiro` | Name shown in model selectors |
52
+ | `region` | derived | Kiro API region; derived from the credential when absent |
53
+
54
+ ## Notes
55
+
56
+ - Sessions come from the machine. The adapter reads the kiro-cli store or the
57
+ Kiro IDE token file, refreshes on expiry, and writes the refresh back. It runs
58
+ no browser flow of its own.
59
+ - Images are sent when the deployment mounts the `attachments` service, and
60
+ dropped otherwise — the plugin does not require that service, so a text-only
61
+ profile still boots.
62
+ - Kiro's failure vocabulary is mapped onto the Harness routing codes
63
+ (`AUTH`, `RATE_LIMIT`, `OVERLOADED`, `QUOTA_EXCEEDED`, `CONTEXT_OVERFLOW`,
64
+ `TIMEOUT`), so the loop's retry policy sees a classified failure rather than
65
+ provider prose.
66
+ - A degenerate response is retried inside the adapter only while nothing has
67
+ been delivered: the Harness assembler cannot un-deliver a block, so a response
68
+ already streamed out is settled rather than replayed.
69
+
70
+ Part of [ns-kiro-provider](https://github.com/ngosangns/ns-kiro-provider).
@@ -0,0 +1,26 @@
1
+ import type { AttachmentStore } from "@deepseek-ai/dsh-attachment";
2
+ import { type GenerateOptions, LlmAdapter, type LlmModelInfo, type LlmProviderInfo, type LlmResolvedModelInfo, type StreamChunk } from "@deepseek-ai/dsh-llm";
3
+ import { type KiroCredentials } from "ns-kiro-core";
4
+ /** What the plugin resolves per request and freezes for the duration of one call. */
5
+ export interface KiroAdapterOptions {
6
+ /** The route this adapter is registered under. */
7
+ provider: string;
8
+ /** Human-readable provider name for selectors and diagnostics. */
9
+ displayName: string;
10
+ /** Resolve the current session; called once per request. */
11
+ credentials: () => Promise<KiroCredentials>;
12
+ /** Optional durable attachment service, resolved at request time. */
13
+ attachments?: () => AttachmentStore | undefined;
14
+ /** Region override; absent derives it from the credential. */
15
+ region?: string;
16
+ }
17
+ export declare class KiroAdapter extends LlmAdapter {
18
+ private readonly options;
19
+ constructor(options: KiroAdapterOptions);
20
+ providerInfo(provider: string): LlmProviderInfo;
21
+ listModels(provider: string): Promise<readonly LlmModelInfo[]>;
22
+ resolveModel(provider: string, model: string): Promise<LlmResolvedModelInfo>;
23
+ stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
24
+ private streamInner;
25
+ private catalog;
26
+ }
@@ -0,0 +1,185 @@
1
+ // ABOUTME: The Harness LLM seam over kiro-core.
2
+ import { LlmAdapter, LlmError, } from "@deepseek-ai/dsh-llm";
3
+ import { getCachedModels, resolveApiRegion, streamKiro, } from "ns-kiro-core";
4
+ import { toLlmError } from "./errors.js";
5
+ import { toKiroMessages } from "./messages.js";
6
+ const EFFORT_NAMES = {
7
+ minimal: "Minimal",
8
+ low: "Low",
9
+ medium: "Medium",
10
+ high: "High",
11
+ xhigh: "Extra high",
12
+ max: "Maximum",
13
+ };
14
+ export class KiroAdapter extends LlmAdapter {
15
+ options;
16
+ constructor(options) {
17
+ super();
18
+ this.options = options;
19
+ }
20
+ providerInfo(provider) {
21
+ return { id: provider, name: this.options.displayName };
22
+ }
23
+ async listModels(provider) {
24
+ return this.catalog().map((model) => ({
25
+ provider,
26
+ id: model.id,
27
+ name: model.name,
28
+ inputModalities: model.input.filter((modality) => modality === "text" || modality === "image"),
29
+ }));
30
+ }
31
+ async resolveModel(provider, model) {
32
+ const known = this.catalog().find((candidate) => candidate.id === model);
33
+ if (!known)
34
+ throw new LlmError(`Unknown Kiro model: ${model}`, "UNKNOWN_MODEL");
35
+ return {
36
+ provider,
37
+ id: known.id,
38
+ name: known.name,
39
+ inputModalities: known.input.filter((modality) => modality === "text" || modality === "image"),
40
+ context: { contextWindow: known.contextWindow },
41
+ defaultMaxTokens: known.maxTokens,
42
+ ...(known.efforts?.length
43
+ ? {
44
+ reasoning: {
45
+ efforts: known.efforts.map((effort) => ({
46
+ id: effort,
47
+ name: EFFORT_NAMES[effort],
48
+ })),
49
+ },
50
+ }
51
+ : {}),
52
+ };
53
+ }
54
+ async *stream(options) {
55
+ try {
56
+ yield* this.streamInner(options);
57
+ }
58
+ catch (error) {
59
+ // `LlmRuntime.stream()` normalizes a throw into a terminal finish, but only
60
+ // after this generator has surfaced it. Converting here is what gives the
61
+ // loop a routing code instead of Kiro's raw wording.
62
+ throw toLlmError(error);
63
+ }
64
+ }
65
+ async *streamInner(options) {
66
+ const credentials = await this.options.credentials();
67
+ const region = this.options.region ?? resolveApiRegion(credentials.region);
68
+ const model = this.catalog(region).find((candidate) => candidate.id === options.model);
69
+ if (!model)
70
+ throw new LlmError(`Unknown Kiro model: ${options.model}`, "UNKNOWN_MODEL");
71
+ const projected = await toKiroMessages(options.messages, {
72
+ attachments: this.options.attachments?.(),
73
+ signal: options.signal,
74
+ });
75
+ // The Harness passes the system prompt as a request field, but a history it
76
+ // replays may also carry `system`-role messages. Both are real system text,
77
+ // so they are joined rather than one silently winning.
78
+ const system = [options.system, projected.system].filter((part) => !!part).join("\n\n") || undefined;
79
+ const tools = options.tools?.map((tool) => ({
80
+ name: tool.name,
81
+ description: tool.description,
82
+ parameters: tool.parameters,
83
+ }));
84
+ const openBlocks = new Set();
85
+ for await (const event of streamKiro({
86
+ model: { ...model, region, ...(credentials.profileArn ? { profileArn: credentials.profileArn } : {}) },
87
+ messages: projected.messages,
88
+ systemPrompt: system,
89
+ tools,
90
+ effort: options.reasoningEffort,
91
+ accessToken: credentials.access,
92
+ sessionId: options.sessionId,
93
+ signal: options.signal,
94
+ profileArn: credentials.profileArn,
95
+ // The Harness assembler has no way to un-deliver a block, so the core must
96
+ // settle a degenerate response rather than replay over one already sent.
97
+ canDiscardEmittedBlocks: false,
98
+ })) {
99
+ switch (event.type) {
100
+ case "text_start":
101
+ openBlocks.add(event.index);
102
+ yield { type: "block-start", index: event.index, blockType: "text" };
103
+ break;
104
+ case "text_delta":
105
+ yield { type: "text-delta", index: event.index, text: event.delta };
106
+ break;
107
+ case "text_end":
108
+ openBlocks.delete(event.index);
109
+ yield { type: "block-end", index: event.index, block: { type: "text", text: event.text } };
110
+ break;
111
+ case "thinking_start":
112
+ openBlocks.add(event.index);
113
+ yield { type: "block-start", index: event.index, blockType: "reasoning" };
114
+ break;
115
+ case "thinking_delta":
116
+ yield { type: "reasoning-delta", index: event.index, text: event.delta };
117
+ break;
118
+ case "thinking_end":
119
+ openBlocks.delete(event.index);
120
+ yield { type: "block-end", index: event.index, block: { type: "reasoning", text: event.thinking } };
121
+ break;
122
+ case "tool_call_start":
123
+ openBlocks.add(event.index);
124
+ yield { type: "block-start", index: event.index, blockType: "tool-call" };
125
+ yield {
126
+ type: "tool-call-delta",
127
+ index: event.index,
128
+ id: event.id,
129
+ name: event.name,
130
+ argumentsDelta: "",
131
+ };
132
+ break;
133
+ case "tool_call_delta":
134
+ yield {
135
+ type: "tool-call-delta",
136
+ index: event.index,
137
+ id: event.id,
138
+ argumentsDelta: event.argumentsDelta,
139
+ };
140
+ break;
141
+ case "tool_call_end":
142
+ openBlocks.delete(event.index);
143
+ yield {
144
+ type: "block-end",
145
+ index: event.index,
146
+ block: {
147
+ type: "tool-call",
148
+ id: event.id,
149
+ name: event.name,
150
+ arguments: JSON.stringify(event.arguments),
151
+ },
152
+ };
153
+ break;
154
+ case "usage":
155
+ yield {
156
+ type: "usage",
157
+ usage: { inputTokens: event.usage.input, outputTokens: event.usage.output },
158
+ };
159
+ break;
160
+ case "done":
161
+ yield {
162
+ type: "finish",
163
+ reason: event.stopReason === "toolUse"
164
+ ? { kind: "tool-calls" }
165
+ : event.stopReason === "length"
166
+ ? { kind: "max-tokens" }
167
+ : { kind: "stop" },
168
+ };
169
+ break;
170
+ // `start` needs no chunk, and `reset` cannot happen: this adapter tells
171
+ // the core it can never discard a delivered block.
172
+ }
173
+ }
174
+ // A block the core opened but never closed would leave the assembler waiting
175
+ // for content that is not coming. That is only reachable if the core adds an
176
+ // exit path before its terminal events, so close them rather than trust it.
177
+ for (const index of openBlocks) {
178
+ yield { type: "block-end", index, block: { type: "text", text: "" } };
179
+ }
180
+ }
181
+ catalog(region) {
182
+ return getCachedModels(region ?? this.options.region ?? "us-east-1");
183
+ }
184
+ }
185
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { LlmError } from "@deepseek-ai/dsh-llm";
2
+ /**
3
+ * Classify a core failure for the Harness.
4
+ *
5
+ * The core throws `Error` with Kiro's own wording because it serves two hosts
6
+ * with different error types. This is where that wording becomes one of the
7
+ * Harness's routing codes — the loop branches on `code`, so a mislabelled
8
+ * failure either retries forever or gives up on something transient.
9
+ */
10
+ export declare function toLlmError(error: unknown): LlmError;
package/dist/errors.js ADDED
@@ -0,0 +1,39 @@
1
+ // ABOUTME: Maps Kiro's failure vocabulary onto the Harness LlmError taxonomy.
2
+ import { LlmError } from "@deepseek-ai/dsh-llm";
3
+ import { isCapacityError, isNonRetryableBodyError, KIRO_REASON_CODES } from "ns-kiro-core";
4
+ const STATUS_PATTERN = /Kiro API error: (\d{3})\b/;
5
+ /**
6
+ * Classify a core failure for the Harness.
7
+ *
8
+ * The core throws `Error` with Kiro's own wording because it serves two hosts
9
+ * with different error types. This is where that wording becomes one of the
10
+ * Harness's routing codes — the loop branches on `code`, so a mislabelled
11
+ * failure either retries forever or gives up on something transient.
12
+ */
13
+ export function toLlmError(error) {
14
+ if (error instanceof LlmError)
15
+ return error;
16
+ const cause = error instanceof Error ? error : undefined;
17
+ const message = cause?.message ?? String(error);
18
+ if (cause?.name === "AbortError")
19
+ return new LlmError(message, "ABORTED", { cause });
20
+ const status = Number(STATUS_PATTERN.exec(message)?.[1]);
21
+ const options = { cause, ...(Number.isFinite(status) ? { status } : {}) };
22
+ if (message.includes("context_length_exceeded"))
23
+ return new LlmError(message, "CONTEXT_OVERFLOW", options);
24
+ if (message.includes(KIRO_REASON_CODES.MONTHLY_REQUEST_COUNT) || isNonRetryableBodyError(message)) {
25
+ return new LlmError(message, "QUOTA_EXCEEDED", options);
26
+ }
27
+ if (isCapacityError(message))
28
+ return new LlmError(message, "OVERLOADED", options);
29
+ if (message.includes(KIRO_REASON_CODES.USER_REQUEST_RATE_EXCEEDED) || status === 429) {
30
+ return new LlmError(message, "RATE_LIMIT", options);
31
+ }
32
+ if (message.includes("credentials not set") || status === 401 || status === 403) {
33
+ return new LlmError(message, "AUTH", options);
34
+ }
35
+ if (message.includes("timeout"))
36
+ return new LlmError(message, "TIMEOUT", options);
37
+ return new LlmError(message, "PROVIDER_ERROR", options);
38
+ }
39
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAE3F,MAAM,cAAc,GAAG,2BAA2B,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,YAAY,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhD,IAAI,KAAK,EAAE,IAAI,KAAK,YAAY;QAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAErF,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAE1E,IAAI,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,CAAC,CAAC;IAC3G,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,IAAI,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;QAClG,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,eAAe,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAClF,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,0BAA0B,CAAC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QACrF,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAChF,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAClF,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Kiro adapter plugin for the DeepSeek Harness LLM seam.
3
+ *
4
+ * Kiro speaks its own streaming protocol — AWS event-stream framing over
5
+ * `generateAssistantResponse` — which no configurable route can describe, so
6
+ * this registers a real adapter rather than a profile on a generic one.
7
+ *
8
+ * Sessions come from the machine: `kiro-cli login` (Builder ID, IAM Identity
9
+ * Center, Google, GitHub, enterprise OIDC) or the Kiro IDE. This plugin reads
10
+ * that session, refreshes it when it expires, and writes the refresh back so
11
+ * both tools stay on the same token.
12
+ *
13
+ * ```yaml
14
+ * - id: llm-kiro
15
+ * name: 'dsh-llm-kiro'
16
+ * config:
17
+ * provider: kiro
18
+ * region: us-east-1
19
+ * ```
20
+ *
21
+ * @module dsh-llm-kiro
22
+ */
23
+ import type { Context } from "@deepseek-ai/cordis";
24
+ import z from "@deepseek-ai/schemastery";
25
+ export { KiroAdapter, type KiroAdapterOptions } from "./adapter.js";
26
+ export { toLlmError } from "./errors.js";
27
+ export { toKiroMessages } from "./messages.js";
28
+ export declare const name = "llm-kiro";
29
+ /**
30
+ * Only `llm` is a hard dependency. Cordis's object form of `inject` maps a
31
+ * service name to intercept config rather than marking it optional, and reading
32
+ * an uninjected service throws — so the optional attachment store is picked up
33
+ * through a scoped `ctx.inject` inside {@link apply} instead.
34
+ */
35
+ export declare const inject: string[];
36
+ export interface Config {
37
+ /** Provider route to register the adapter under. */
38
+ provider: string;
39
+ /** Display name for selectors and status labels. */
40
+ displayName: string;
41
+ /**
42
+ * Kiro API region. Absent derives it from the credential, which is what a
43
+ * single-account machine wants; pin it when one account spans regions.
44
+ */
45
+ region?: string;
46
+ }
47
+ export declare const Config: z<Config>;
48
+ export declare function apply(ctx: Context, config: Config): void;
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Kiro adapter plugin for the DeepSeek Harness LLM seam.
3
+ *
4
+ * Kiro speaks its own streaming protocol — AWS event-stream framing over
5
+ * `generateAssistantResponse` — which no configurable route can describe, so
6
+ * this registers a real adapter rather than a profile on a generic one.
7
+ *
8
+ * Sessions come from the machine: `kiro-cli login` (Builder ID, IAM Identity
9
+ * Center, Google, GitHub, enterprise OIDC) or the Kiro IDE. This plugin reads
10
+ * that session, refreshes it when it expires, and writes the refresh back so
11
+ * both tools stay on the same token.
12
+ *
13
+ * ```yaml
14
+ * - id: llm-kiro
15
+ * name: 'dsh-llm-kiro'
16
+ * config:
17
+ * provider: kiro
18
+ * region: us-east-1
19
+ * ```
20
+ *
21
+ * @module dsh-llm-kiro
22
+ */
23
+ import { LlmError } from "@deepseek-ai/dsh-llm";
24
+ import z from "@deepseek-ai/schemastery";
25
+ import { isExpired, refreshKiroToken, resolveKiroCredentials } from "ns-kiro-core";
26
+ import { KiroAdapter } from "./adapter.js";
27
+ export { KiroAdapter } from "./adapter.js";
28
+ export { toLlmError } from "./errors.js";
29
+ export { toKiroMessages } from "./messages.js";
30
+ export const name = "llm-kiro";
31
+ /**
32
+ * Only `llm` is a hard dependency. Cordis's object form of `inject` maps a
33
+ * service name to intercept config rather than marking it optional, and reading
34
+ * an uninjected service throws — so the optional attachment store is picked up
35
+ * through a scoped `ctx.inject` inside {@link apply} instead.
36
+ */
37
+ export const inject = ["llm"];
38
+ export const Config = z.object({
39
+ provider: z.string().default("kiro").description("Provider route to register the adapter under."),
40
+ displayName: z.string().default("Kiro").description("Display name shown in model selectors."),
41
+ region: z.string().description("Kiro API region; derived from the credential when absent."),
42
+ });
43
+ /**
44
+ * Resolve the current session for one request.
45
+ *
46
+ * Sessions are re-read rather than cached: kiro-cli rotates the token from
47
+ * another process, and a cached copy would send a token the service has already
48
+ * replaced. The read is a local file, so the cost is not worth the staleness.
49
+ */
50
+ async function currentCredentials() {
51
+ const credentials = await resolveKiroCredentials();
52
+ if (!credentials) {
53
+ throw new LlmError("No Kiro session found. Sign in with `kiro-cli login`, or install the Kiro IDE and sign in there.", "MISSING_CREDENTIAL");
54
+ }
55
+ return isExpired(credentials) ? refreshKiroToken(credentials) : credentials;
56
+ }
57
+ export function apply(ctx, config) {
58
+ // Held here rather than read per request: a deployment without the attachment
59
+ // service never mounts it, and reading an uninjected service throws. The
60
+ // scoped fiber below sets it while the service exists and clears it when the
61
+ // service goes away, so an image-capable deployment gains image support
62
+ // without a text-only one failing to boot.
63
+ let attachments;
64
+ ctx.inject(["attachments"], (scope) => {
65
+ attachments = scope.attachments;
66
+ scope.effect(() => () => {
67
+ attachments = undefined;
68
+ }, "dsh-llm-kiro attachment store");
69
+ });
70
+ const adapter = new KiroAdapter({
71
+ provider: config.provider,
72
+ displayName: config.displayName,
73
+ credentials: currentCredentials,
74
+ attachments: () => attachments,
75
+ ...(config.region ? { region: config.region } : {}),
76
+ });
77
+ ctx.llm.registerAdapter([config.provider], adapter);
78
+ }
79
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,CAAC,MAAM,0BAA0B,CAAC;AACzC,OAAO,EAAE,SAAS,EAAwB,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACzG,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,WAAW,EAA2B,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,CAAC,MAAM,IAAI,GAAG,UAAU,CAAC;AAE/B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;AAc9B,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,+CAA+C,CAAC;IACjG,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,wCAAwC,CAAC;IAC7F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,2DAA2D,CAAC;CAC5F,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,KAAK,UAAU,kBAAkB;IAC/B,MAAM,WAAW,GAAG,MAAM,sBAAsB,EAAE,CAAC;IACnD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,QAAQ,CAChB,kGAAkG,EAClG,oBAAoB,CACrB,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAc;IAChD,8EAA8E;IAC9E,yEAAyE;IACzE,6EAA6E;IAC7E,wEAAwE;IACxE,2CAA2C;IAC3C,IAAI,WAAwC,CAAC;IAC7C,GAAG,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;QACpC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;QAChC,KAAK,CAAC,MAAM,CACV,GAAG,EAAE,CAAC,GAAG,EAAE;YACT,WAAW,GAAG,SAAS,CAAC;QAC1B,CAAC,EACD,+BAA+B,CAChC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,kBAAkB;QAC/B,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW;QAC9B,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpD,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { AttachmentStore } from "@deepseek-ai/dsh-attachment";
2
+ import type { Message } from "@deepseek-ai/dsh-llm";
3
+ import type { KiroMessage } from "ns-kiro-core";
4
+ /**
5
+ * Harness images live in the attachment service, so their bytes are read here
6
+ * rather than carried on the block. A store is optional: without one the images
7
+ * are dropped and the rest of the turn still reaches the model, which is the
8
+ * behaviour a text-only deployment wants.
9
+ */
10
+ export interface MessageProjectionContext {
11
+ attachments?: AttachmentStore;
12
+ signal?: AbortSignal;
13
+ }
14
+ /**
15
+ * Flatten one Harness history into the neutral shape.
16
+ *
17
+ * Two structural differences drive the whole mapping. The Harness has no
18
+ * `toolResult` role — a result is a `tool-result` block inside a user message —
19
+ * so those blocks are lifted into their own neutral messages. And its system
20
+ * prompt travels as a `system`-role message rather than a request field, so
21
+ * system text is returned separately for the caller to pass as the system slot.
22
+ */
23
+ export declare function toKiroMessages(messages: readonly Message[], context?: MessageProjectionContext): Promise<{
24
+ messages: KiroMessage[];
25
+ system?: string;
26
+ }>;
@@ -0,0 +1,85 @@
1
+ // ABOUTME: Projects the Harness conversation vocabulary onto the neutral one kiro-core reads.
2
+ async function userContent(blocks, context) {
3
+ const out = [];
4
+ for (const block of blocks) {
5
+ if (block.type === "text")
6
+ out.push({ type: "text", text: block.text });
7
+ else if (block.type === "reasoning")
8
+ out.push({ type: "text", text: block.text });
9
+ else if (block.type === "image" && context.attachments) {
10
+ const stored = await context.attachments.readImage(block.attachment, context.signal);
11
+ out.push({
12
+ type: "image",
13
+ data: Buffer.from(stored.data).toString("base64"),
14
+ mimeType: block.attachment.mediaType,
15
+ });
16
+ }
17
+ }
18
+ return out;
19
+ }
20
+ function isToolResult(block) {
21
+ return block.type === "tool-result";
22
+ }
23
+ /**
24
+ * Flatten one Harness history into the neutral shape.
25
+ *
26
+ * Two structural differences drive the whole mapping. The Harness has no
27
+ * `toolResult` role — a result is a `tool-result` block inside a user message —
28
+ * so those blocks are lifted into their own neutral messages. And its system
29
+ * prompt travels as a `system`-role message rather than a request field, so
30
+ * system text is returned separately for the caller to pass as the system slot.
31
+ */
32
+ export async function toKiroMessages(messages, context = {}) {
33
+ const out = [];
34
+ const systemParts = [];
35
+ for (const message of messages) {
36
+ if (message.role === "system") {
37
+ for (const block of message.content)
38
+ if (block.type === "text")
39
+ systemParts.push(block.text);
40
+ continue;
41
+ }
42
+ if (message.role === "assistant") {
43
+ const content = [];
44
+ for (const block of message.content) {
45
+ if (block.type === "text")
46
+ content.push({ type: "text", text: block.text });
47
+ else if (block.type === "reasoning")
48
+ content.push({ type: "thinking", thinking: block.text });
49
+ else if (block.type === "tool-call") {
50
+ let args;
51
+ try {
52
+ args = JSON.parse(block.arguments || "{}");
53
+ }
54
+ catch {
55
+ // A stored call whose arguments no longer parse is still part of the
56
+ // exchange the model must see; sending it with empty arguments keeps
57
+ // the call/result pairing Kiro validates, which dropping would break.
58
+ args = {};
59
+ }
60
+ content.push({ type: "toolCall", id: block.id, name: block.name, arguments: args });
61
+ }
62
+ }
63
+ out.push({ role: "assistant", content });
64
+ continue;
65
+ }
66
+ const results = message.content.filter(isToolResult);
67
+ const plain = message.content.filter((block) => !isToolResult(block));
68
+ if (plain.length > 0)
69
+ out.push({ role: "user", content: await userContent(plain, context) });
70
+ for (const result of results) {
71
+ out.push({
72
+ role: "toolResult",
73
+ toolCallId: result.toolCallId,
74
+ // The Harness correlates a result by id alone and carries no tool name
75
+ // on the block. Kiro's wire format does not read the name back either —
76
+ // `toolUseId` is the whole pairing — so a placeholder is honest here.
77
+ toolName: "tool",
78
+ content: await userContent(result.content, context),
79
+ isError: result.isError === true,
80
+ });
81
+ }
82
+ }
83
+ return { messages: out, ...(systemParts.length > 0 ? { system: systemParts.join("\n\n") } : {}) };
84
+ }
85
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "ns-dsh-llm-kiro",
3
+ "version": "0.1.0",
4
+ "description": "DeepSeek Harness LLM adapter for the Kiro API (AWS CodeWhisperer/Q)",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/ngosangns/ns-kiro-provider.git",
19
+ "directory": "packages/dsh-llm-kiro"
20
+ },
21
+ "keywords": [
22
+ "deepseek-harness",
23
+ "dsh",
24
+ "dsh-plugin",
25
+ "cordis",
26
+ "kiro",
27
+ "aws",
28
+ "codewhisperer",
29
+ "ai",
30
+ "llm"
31
+ ],
32
+ "files": [
33
+ "dist",
34
+ "README.md"
35
+ ],
36
+ "dependencies": {
37
+ "@deepseek-ai/schemastery": "^3.18.1",
38
+ "ns-kiro-core": "0.1.0"
39
+ },
40
+ "peerDependencies": {
41
+ "@deepseek-ai/cordis": "^4.0.1",
42
+ "@deepseek-ai/dsh-attachment": ">=0.1.1-rc.1 <0.2.0",
43
+ "@deepseek-ai/dsh-credentials": ">=0.1.1-rc.1 <0.2.0",
44
+ "@deepseek-ai/dsh-llm": ">=0.1.1-rc.1 <0.2.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@deepseek-ai/dsh-attachment": {
48
+ "optional": true
49
+ },
50
+ "@deepseek-ai/dsh-credentials": {
51
+ "optional": true
52
+ }
53
+ },
54
+ "devDependencies": {
55
+ "@deepseek-ai/cordis": "4.0.1",
56
+ "@deepseek-ai/dsh-attachment": "0.1.1-rc.1",
57
+ "@deepseek-ai/dsh-credentials": "0.1.1-rc.1",
58
+ "@deepseek-ai/dsh-llm": "0.1.1-rc.1",
59
+ "@types/node": "^22.10.0"
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.json",
63
+ "check": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json"
64
+ }
65
+ }