ns-kiro-core 0.1.2 → 0.2.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.
@@ -0,0 +1,330 @@
1
+ // ABOUTME: Turns Kiro wire events into neutral content blocks and a stop reason.
2
+ // ABOUTME: Owns what the response says; the request loop owns whether to ask again.
3
+ import { KiroBlockBuffer } from "./blocks.js";
4
+ import { parseBracketToolCalls } from "./bracket-tool-parser.js";
5
+ import { calculateKiroCost } from "./cost.js";
6
+ import { debugEnabled, debugLog, formatSafeError, redactSensitiveText } from "./debug.js";
7
+ import { parseInvokeToolCalls } from "./invoke-tool-parser.js";
8
+ import { ThinkingTagParser } from "./thinking-parser.js";
9
+ import { countTokens } from "./tokenizer.js";
10
+ /** Text that is an artifact of history padding rather than an answer. */
11
+ const ECHO_NOISE_PATTERN = /^\s*(continue|\.+)\s*$/i;
12
+ /**
13
+ * Accumulates one response.
14
+ *
15
+ * Block indexes are monotonic across the whole call, including across an
16
+ * internal retry, so the buffer and the usage totals outlive a single attempt
17
+ * while everything else is reset by {@link beginAttempt}.
18
+ */
19
+ export class KiroResponseAssembler {
20
+ model;
21
+ thinkingEnabled;
22
+ pending = [];
23
+ blocks = new KiroBlockBuffer((event) => this.pending.push(event));
24
+ usage = {
25
+ input: 0,
26
+ output: 0,
27
+ totalTokens: 0,
28
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
29
+ };
30
+ totalContent = "";
31
+ lastContentData = "";
32
+ usageEvent = null;
33
+ receivedContextUsage = false;
34
+ thinkingParser = null;
35
+ nativeThinkingBlockIndex = null;
36
+ nativeThinkingEnded = false;
37
+ textBlockIndex = null;
38
+ emittedToolCalls = 0;
39
+ sawAnyToolCalls = false;
40
+ currentToolCall = null;
41
+ constructor(model, thinkingEnabled) {
42
+ this.model = model;
43
+ this.thinkingEnabled = thinkingEnabled;
44
+ }
45
+ /** Clear per-attempt state. Block indexes and accumulated usage are kept. */
46
+ beginAttempt() {
47
+ this.totalContent = "";
48
+ this.lastContentData = "";
49
+ this.usageEvent = null;
50
+ this.receivedContextUsage = false;
51
+ this.thinkingParser = this.thinkingEnabled ? new ThinkingTagParser(this.blocks) : null;
52
+ this.nativeThinkingBlockIndex = null;
53
+ this.nativeThinkingEnded = false;
54
+ this.textBlockIndex = null;
55
+ this.emittedToolCalls = 0;
56
+ this.sawAnyToolCalls = false;
57
+ this.currentToolCall = null;
58
+ }
59
+ /** Hand over the events buffered so far. */
60
+ takeEvents() {
61
+ return this.pending.splice(0, this.pending.length);
62
+ }
63
+ /** Announce that a retry discarded everything emitted so far. */
64
+ discard() {
65
+ this.blocks.reset();
66
+ this.textBlockIndex = null;
67
+ }
68
+ handle(frame) {
69
+ const { event, payload } = frame;
70
+ switch (event.type) {
71
+ case "contextUsage": {
72
+ const pct = event.data.contextUsagePercentage;
73
+ this.usage.input = Math.round((pct / 100) * this.model.contextWindow);
74
+ this.usage.contextPercent = pct;
75
+ this.receivedContextUsage = true;
76
+ break;
77
+ }
78
+ case "thinkingText": {
79
+ if (!this.thinkingEnabled)
80
+ break;
81
+ this.blocks.appendThinking(this.ensureNativeThinkingBlock(), event.data);
82
+ this.totalContent += event.data;
83
+ break;
84
+ }
85
+ case "thinkingSignature": {
86
+ if (!this.thinkingEnabled)
87
+ break;
88
+ this.ensureNativeThinkingBlock();
89
+ this.endNativeThinking(event.data);
90
+ break;
91
+ }
92
+ case "content": {
93
+ this.endNativeThinking();
94
+ // Kiro repeats the last content frame on some turns; a repeat carries no
95
+ // new text and must not be appended twice.
96
+ if (event.data === this.lastContentData)
97
+ break;
98
+ this.lastContentData = event.data;
99
+ this.totalContent += event.data;
100
+ if (this.thinkingParser) {
101
+ this.thinkingParser.processChunk(event.data);
102
+ }
103
+ else {
104
+ if (this.textBlockIndex === null)
105
+ this.textBlockIndex = this.blocks.openText();
106
+ this.blocks.appendText(this.textBlockIndex, event.data);
107
+ }
108
+ break;
109
+ }
110
+ case "toolUse": {
111
+ const tc = event.data;
112
+ this.sawAnyToolCalls = true;
113
+ if (!this.currentToolCall || this.currentToolCall.toolUseId !== tc.toolUseId) {
114
+ this.flushToolCall();
115
+ this.currentToolCall = { toolUseId: tc.toolUseId, name: tc.name, input: "" };
116
+ }
117
+ this.currentToolCall.input += tc.input || "";
118
+ if (tc.input)
119
+ this.totalContent += tc.input;
120
+ if (tc.stop)
121
+ this.flushToolCall();
122
+ break;
123
+ }
124
+ case "toolUseInput": {
125
+ if (this.currentToolCall)
126
+ this.currentToolCall.input += event.data.input || "";
127
+ if (event.data.input)
128
+ this.totalContent += event.data.input;
129
+ break;
130
+ }
131
+ case "toolUseStop": {
132
+ if (event.data.stop)
133
+ this.flushToolCall();
134
+ break;
135
+ }
136
+ case "usage": {
137
+ this.usageEvent = event.data;
138
+ // The parsed event keeps only the fields this package understands.
139
+ // Log the frame verbatim so a field Kiro adds — cache counters above
140
+ // all — is visible without having to guess its name first.
141
+ if (debugEnabled())
142
+ debugLog("response.usageRaw", payload);
143
+ break;
144
+ }
145
+ // followupPrompt events are intentionally ignored
146
+ }
147
+ }
148
+ /**
149
+ * Close the turn: flush a trailing tool call, close thinking, and run the
150
+ * text-dialect recovery and echo-stripping passes.
151
+ */
152
+ endTurn() {
153
+ if (this.currentToolCall && this.emitToolCall(this.currentToolCall))
154
+ this.emittedToolCalls++;
155
+ this.currentToolCall = null;
156
+ this.endNativeThinking();
157
+ if (this.thinkingParser) {
158
+ this.thinkingParser.finalize();
159
+ this.textBlockIndex = this.thinkingParser.getTextBlockIndex();
160
+ }
161
+ this.recoverTextToolCalls();
162
+ this.stripEchoNoise();
163
+ const responseText = this.textBlockIndex === null ? "" : this.blocks.getText(this.textBlockIndex);
164
+ const hasText = responseText.length > 0;
165
+ return {
166
+ responseText,
167
+ hasText,
168
+ sawAnyToolCalls: this.sawAnyToolCalls,
169
+ emittedToolCalls: this.emittedToolCalls,
170
+ isEchoLoop: hasText && !this.sawAnyToolCalls && ECHO_NOISE_PATTERN.test(responseText),
171
+ isEmpty: !hasText && !this.sawAnyToolCalls,
172
+ };
173
+ }
174
+ /** Drop an echo the caller decided not to retry, so it is not read as a continuation signal. */
175
+ stripEcho() {
176
+ if (this.textBlockIndex !== null)
177
+ this.blocks.setText(this.textBlockIndex, "");
178
+ }
179
+ /** Close the text block and settle usage and the stop reason. */
180
+ complete() {
181
+ if (this.textBlockIndex !== null)
182
+ this.blocks.endText(this.textBlockIndex);
183
+ // Kiro does not reliably emit per-response output token counts. When the
184
+ // `usage` event is missing or reports only `inputTokens`, fall back to a
185
+ // tiktoken estimate over everything the assistant emitted — text plus
186
+ // tool-call input JSON. Otherwise tool-call-only turns report 0 output
187
+ // tokens and break consumers that watch it.
188
+ if (this.usageEvent?.inputTokens !== undefined)
189
+ this.usage.input = this.usageEvent.inputTokens;
190
+ this.usage.output = this.usageEvent?.outputTokens ?? countTokens(this.totalContent);
191
+ this.usage.totalTokens = this.usage.input + this.usage.output;
192
+ // Only set when reported: leaving these absent is what tells a host that
193
+ // Kiro said nothing about caching, rather than that nothing was cached.
194
+ if (this.usageEvent?.cacheReadTokens !== undefined)
195
+ this.usage.cacheRead = this.usageEvent.cacheReadTokens;
196
+ if (this.usageEvent?.cacheWriteTokens !== undefined)
197
+ this.usage.cacheWrite = this.usageEvent.cacheWriteTokens;
198
+ if (this.usageEvent?.credits !== undefined)
199
+ this.usage.credits = this.usageEvent.credits;
200
+ if (this.usageEvent?.creditUnit !== undefined)
201
+ this.usage.creditUnit = this.usageEvent.creditUnit;
202
+ this.usage.cost = calculateKiroCost(this.model.cost, this.usage);
203
+ // Use `emittedToolCalls`, not the count seen on the wire: a turn whose calls
204
+ // were all dropped for unparseable input must not report `toolUse`, because
205
+ // an empty turn with a tool-use stop stalls an agent loop waiting for
206
+ // results that will never arrive.
207
+ //
208
+ // `length` is inferred, not reported: Kiro sends no stop reason, so a turn
209
+ // that produced no tool call and never carried a contextUsage frame is
210
+ // treated as cut short.
211
+ //
212
+ // That rests on contextUsage closing every complete response. Checked
213
+ // 2026-09-06 across a short reply, a ~5000-character one, a tool-call turn,
214
+ // a model with no effort schema (claude-haiku-4.5) and a non-Claude model
215
+ // (glm-5): the frame arrived in all five, so its absence really does mark an
216
+ // abnormal turn. `response.done` logs `receivedContextUsage` in case a later
217
+ // Kiro stops sending it — a false `length` is read by hosts as truncation
218
+ // and prepends TRUNCATION_NOTICE, asking the model to continue work it
219
+ // already finished.
220
+ const stopReason = !this.receivedContextUsage && this.emittedToolCalls === 0
221
+ ? "length"
222
+ : this.emittedToolCalls > 0
223
+ ? "toolUse"
224
+ : "stop";
225
+ debugLog("response.done", {
226
+ stopReason,
227
+ receivedContextUsage: this.receivedContextUsage,
228
+ emittedToolCalls: this.emittedToolCalls,
229
+ sawAnyToolCalls: this.sawAnyToolCalls,
230
+ textLen: this.textBlockIndex === null ? 0 : this.blocks.getText(this.textBlockIndex).length,
231
+ usage: this.usage,
232
+ });
233
+ return { stopReason, usage: this.usage };
234
+ }
235
+ ensureNativeThinkingBlock() {
236
+ if (this.nativeThinkingBlockIndex === null)
237
+ this.nativeThinkingBlockIndex = this.blocks.openThinking();
238
+ return this.nativeThinkingBlockIndex;
239
+ }
240
+ endNativeThinking(signature) {
241
+ if (this.nativeThinkingBlockIndex === null || this.nativeThinkingEnded)
242
+ return;
243
+ this.nativeThinkingEnded = true;
244
+ this.blocks.endThinking(this.nativeThinkingBlockIndex, signature);
245
+ }
246
+ emitToolCall(state) {
247
+ if (!state.input.trim()) {
248
+ // Kiro omits the input payload when the model calls a tool with no
249
+ // arguments (e.g. `mcp({})`). Treat empty input as an empty object
250
+ // rather than skipping — these are valid zero-arg calls, not truncations.
251
+ state.input = "{}";
252
+ }
253
+ let args;
254
+ try {
255
+ args = JSON.parse(state.input);
256
+ }
257
+ catch (e) {
258
+ console.warn(`[kiro-core] Failed to parse tool input for "${state.name}" (toolUseId: ${state.toolUseId}): ${formatSafeError(e)}. Raw input (${state.input.length} chars): ${redactSensitiveText(state.input.substring(0, 200))}`);
259
+ return false;
260
+ }
261
+ const index = this.blocks.reserve();
262
+ this.pending.push({ type: "tool_call_start", index, id: state.toolUseId, name: state.name });
263
+ this.pending.push({ type: "tool_call_delta", index, id: state.toolUseId, argumentsDelta: state.input });
264
+ this.pending.push({ type: "tool_call_end", index, id: state.toolUseId, name: state.name, arguments: args });
265
+ return true;
266
+ }
267
+ flushToolCall() {
268
+ if (!this.currentToolCall)
269
+ return;
270
+ if (this.emitToolCall(this.currentToolCall))
271
+ this.emittedToolCalls++;
272
+ this.currentToolCall = null;
273
+ }
274
+ /**
275
+ * Extract text-dialect tool calls from content when no native tool calls
276
+ * arrived. Two dialects are recovered at this seam:
277
+ * 1. Kiro's own `[Called name with args: {...}]` bracket form.
278
+ * 2. Anthropic's `<invoke name="..."><parameter .../></invoke>` XML form,
279
+ * which opus-class models emit as plain text at high context.
280
+ * Without this, the turn ends `stop` with zero tool calls — the agent loop
281
+ * sees a finished answer and an unattended session stalls with no error
282
+ * recorded anywhere.
283
+ *
284
+ * Models that emit native tool-use events opt out via
285
+ * `recoverTextToolCalls: false`. For them this pass has nothing to rescue
286
+ * and everything to break: prose that merely *quotes* the syntax — a model
287
+ * explaining how a tool is called — would be lifted into a real call the
288
+ * model never made. Absent means recover, so a model the catalog says
289
+ * nothing about keeps the fallback.
290
+ */
291
+ recoverTextToolCalls() {
292
+ if (this.model.recoverTextToolCalls === false || this.sawAnyToolCalls || this.textBlockIndex === null)
293
+ return;
294
+ let text = this.blocks.getText(this.textBlockIndex);
295
+ const recovered = [];
296
+ const bracketResult = parseBracketToolCalls(text);
297
+ if (bracketResult.toolCalls.length > 0) {
298
+ text = bracketResult.cleanedText;
299
+ recovered.push(...bracketResult.toolCalls);
300
+ }
301
+ const invokeResult = parseInvokeToolCalls(text);
302
+ if (invokeResult.toolCalls.length > 0) {
303
+ text = invokeResult.cleanedText;
304
+ recovered.push(...invokeResult.toolCalls);
305
+ }
306
+ if (recovered.length === 0)
307
+ return;
308
+ this.blocks.setText(this.textBlockIndex, text);
309
+ this.sawAnyToolCalls = true;
310
+ for (const call of recovered) {
311
+ if (this.emitToolCall({ toolUseId: call.toolUseId, name: call.name, input: JSON.stringify(call.arguments) })) {
312
+ this.emittedToolCalls++;
313
+ }
314
+ }
315
+ }
316
+ /**
317
+ * Strip echo noise: when tool calls are present and the text content is just
318
+ * "." or a similar short echo from history padding, remove it. This prevents
319
+ * the echo from accumulating in conversation history and reinforcing the
320
+ * pattern in future turns.
321
+ */
322
+ stripEchoNoise() {
323
+ if (this.emittedToolCalls === 0 || this.textBlockIndex === null)
324
+ return;
325
+ if (ECHO_NOISE_PATTERN.test(this.blocks.getText(this.textBlockIndex))) {
326
+ this.blocks.setText(this.textBlockIndex, "");
327
+ }
328
+ }
329
+ }
330
+ //# sourceMappingURL=response-assembler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-assembler.js","sourceRoot":"","sources":["../src/response-assembler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { type KiroWireEvent } from "./event-parser.js";
2
+ /** Longest gap between two frames before the response is treated as stalled. */
3
+ export declare const IDLE_TIMEOUT = 300000;
4
+ /**
5
+ * Why the stream stopped. Every field is a retryable condition; all false means
6
+ * the response ended normally.
7
+ */
8
+ export interface KiroEventStreamOutcome {
9
+ firstTokenTimedOut: boolean;
10
+ idleTimedOut: boolean;
11
+ /** Message from a Smithy protocol error or a Kiro `error` frame. */
12
+ error: string | null;
13
+ }
14
+ export interface KiroWireEventFrame {
15
+ event: KiroWireEvent;
16
+ /** The frame verbatim, for logging fields this package does not model. */
17
+ payload: Record<string, unknown>;
18
+ }
19
+ export interface KiroEventStreamOptions {
20
+ firstTokenTimeoutMs: number;
21
+ idleTimeoutMs?: number;
22
+ }
23
+ export interface KiroEventStreamReader {
24
+ frames: AsyncGenerator<KiroWireEventFrame>;
25
+ /** Populated by the time `frames` completes. */
26
+ outcome: KiroEventStreamOutcome;
27
+ }
28
+ /**
29
+ * Turn a Kiro response body into parsed wire events.
30
+ *
31
+ * Terminal conditions are reported through {@link KiroEventStreamOutcome}
32
+ * rather than thrown: the caller retries all three the same way, and a throw
33
+ * would force it to re-classify the cause it already knows.
34
+ *
35
+ * A Kiro `error` frame ends the stream and is not yielded — it carries no
36
+ * content, and every caller treats it as the same retryable failure as a
37
+ * protocol error.
38
+ */
39
+ export declare function readKiroEventStream(body: ReadableStream<Uint8Array>, options: KiroEventStreamOptions): KiroEventStreamReader;
@@ -0,0 +1,123 @@
1
+ // ABOUTME: Reads Kiro's AWS event-stream response into parsed wire events.
2
+ // ABOUTME: Owns framing and the stall timeouts; block assembly lives elsewhere.
3
+ import { UniversalEventStreamMarshaller } from "@smithy/core/event-streams";
4
+ import { debugEnabled, debugLog } from "./debug.js";
5
+ import { parseKiroEvent } from "./event-parser.js";
6
+ /** Longest gap between two frames before the response is treated as stalled. */
7
+ export const IDLE_TIMEOUT = 300_000;
8
+ const eventStreamMarshaller = new UniversalEventStreamMarshaller({
9
+ utf8Encoder: (input) => new TextDecoder().decode(input),
10
+ utf8Decoder: (input) => new TextEncoder().encode(input),
11
+ });
12
+ /**
13
+ * Turn a Kiro response body into parsed wire events.
14
+ *
15
+ * Terminal conditions are reported through {@link KiroEventStreamOutcome}
16
+ * rather than thrown: the caller retries all three the same way, and a throw
17
+ * would force it to re-classify the cause it already knows.
18
+ *
19
+ * A Kiro `error` frame ends the stream and is not yielded — it carries no
20
+ * content, and every caller treats it as the same retryable failure as a
21
+ * protocol error.
22
+ */
23
+ export function readKiroEventStream(body, options) {
24
+ const outcome = { firstTokenTimedOut: false, idleTimedOut: false, error: null };
25
+ const idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT;
26
+ const bodyReader = body.getReader();
27
+ async function* frames() {
28
+ let idleTimer = null;
29
+ const resetIdle = () => {
30
+ if (idleTimer)
31
+ clearTimeout(idleTimer);
32
+ idleTimer = setTimeout(() => {
33
+ outcome.idleTimedOut = true;
34
+ void bodyReader.cancel().catch(() => { });
35
+ }, idleTimeoutMs);
36
+ };
37
+ // Smithy's marshaller handles chunk reassembly, CRC validation, protocol
38
+ // error/exception detection, and payload deserialization.
39
+ const bodyIterable = {
40
+ async *[Symbol.asyncIterator]() {
41
+ try {
42
+ while (true) {
43
+ const { done, value } = await bodyReader.read();
44
+ if (done)
45
+ return;
46
+ yield value;
47
+ }
48
+ }
49
+ finally {
50
+ bodyReader.releaseLock();
51
+ }
52
+ },
53
+ };
54
+ const utf8Decoder = new TextDecoder();
55
+ const eventStream = eventStreamMarshaller.deserialize(bodyIterable, async (event) => {
56
+ const entry = Object.entries(event)[0];
57
+ if (!entry)
58
+ throw new Error("Received an empty event stream message");
59
+ const [key, msg] = entry;
60
+ const parsed = JSON.parse(utf8Decoder.decode(msg.body));
61
+ return { [key]: parsed };
62
+ });
63
+ const iterator = eventStream[Symbol.asyncIterator]();
64
+ let gotFirstToken = false;
65
+ const FIRST_TOKEN_SENTINEL = Symbol("firstTokenTimeout");
66
+ try {
67
+ while (true) {
68
+ let iterResult;
69
+ try {
70
+ if (!gotFirstToken) {
71
+ const readPromise = iterator.next();
72
+ const result = await Promise.race([
73
+ readPromise,
74
+ new Promise((resolve) => setTimeout(() => resolve(FIRST_TOKEN_SENTINEL), options.firstTokenTimeoutMs)),
75
+ ]);
76
+ if (result === FIRST_TOKEN_SENTINEL) {
77
+ readPromise.catch(() => { }); // suppress dangling rejection
78
+ void bodyReader.cancel().catch(() => { });
79
+ outcome.firstTokenTimedOut = true;
80
+ return;
81
+ }
82
+ iterResult = result;
83
+ gotFirstToken = true;
84
+ resetIdle();
85
+ }
86
+ else {
87
+ iterResult = await iterator.next();
88
+ }
89
+ }
90
+ catch (e) {
91
+ // Smithy throws on `:message-type` error/exception headers.
92
+ outcome.error =
93
+ e instanceof Error
94
+ ? e.message
95
+ : (typeof e === "object" && e !== null ? JSON.stringify(e) : String(e)) || "Unknown stream error";
96
+ return;
97
+ }
98
+ const { done, value } = iterResult;
99
+ if (done)
100
+ return;
101
+ resetIdle();
102
+ const payload = Object.values(value)[0];
103
+ const event = parseKiroEvent(payload);
104
+ if (!event)
105
+ continue;
106
+ if (debugEnabled())
107
+ debugLog("stream.events", [event]);
108
+ if (event.type === "error") {
109
+ outcome.error = event.data.message ? `${event.data.error}: ${event.data.message}` : event.data.error;
110
+ void bodyReader.cancel().catch(() => { });
111
+ return;
112
+ }
113
+ yield { event, payload };
114
+ }
115
+ }
116
+ finally {
117
+ if (idleTimer)
118
+ clearTimeout(idleTimer);
119
+ }
120
+ }
121
+ return { frames: frames(), outcome };
122
+ }
123
+ //# sourceMappingURL=response-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-stream.js","sourceRoot":"","sources":["../src/response-stream.ts"],"names":[],"mappings":"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"}