ns-kiro-core 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.
Files changed (78) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +51 -0
  3. package/dist/blocks.d.ts +32 -0
  4. package/dist/blocks.js +83 -0
  5. package/dist/blocks.js.map +1 -0
  6. package/dist/bracket-tool-parser.d.ts +11 -0
  7. package/dist/bracket-tool-parser.js +78 -0
  8. package/dist/bracket-tool-parser.js.map +1 -0
  9. package/dist/cost.d.ts +3 -0
  10. package/dist/cost.js +10 -0
  11. package/dist/cost.js.map +1 -0
  12. package/dist/debug.d.ts +6 -0
  13. package/dist/debug.js +63 -0
  14. package/dist/debug.js.map +1 -0
  15. package/dist/effort.d.ts +36 -0
  16. package/dist/effort.js +138 -0
  17. package/dist/effort.js.map +1 -0
  18. package/dist/endpoints.d.ts +8 -0
  19. package/dist/endpoints.js +43 -0
  20. package/dist/endpoints.js.map +1 -0
  21. package/dist/event-parser.d.ts +49 -0
  22. package/dist/event-parser.js +56 -0
  23. package/dist/event-parser.js.map +1 -0
  24. package/dist/history-validator.d.ts +91 -0
  25. package/dist/history-validator.js +370 -0
  26. package/dist/history-validator.js.map +1 -0
  27. package/dist/history.d.ts +21 -0
  28. package/dist/history.js +130 -0
  29. package/dist/history.js.map +1 -0
  30. package/dist/index.d.ts +22 -0
  31. package/dist/index.js +28 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/invoke-tool-parser.d.ts +16 -0
  34. package/dist/invoke-tool-parser.js +152 -0
  35. package/dist/invoke-tool-parser.js.map +1 -0
  36. package/dist/kiro-cli.d.ts +31 -0
  37. package/dist/kiro-cli.js +308 -0
  38. package/dist/kiro-cli.js.map +1 -0
  39. package/dist/kiro-ide.d.ts +12 -0
  40. package/dist/kiro-ide.js +74 -0
  41. package/dist/kiro-ide.js.map +1 -0
  42. package/dist/management.d.ts +34 -0
  43. package/dist/management.js +226 -0
  44. package/dist/management.js.map +1 -0
  45. package/dist/models.d.ts +58 -0
  46. package/dist/models.js +462 -0
  47. package/dist/models.js.map +1 -0
  48. package/dist/oauth.d.ts +50 -0
  49. package/dist/oauth.js +295 -0
  50. package/dist/oauth.js.map +1 -0
  51. package/dist/retry.d.ts +74 -0
  52. package/dist/retry.js +156 -0
  53. package/dist/retry.js.map +1 -0
  54. package/dist/stream.d.ts +36 -0
  55. package/dist/stream.js +898 -0
  56. package/dist/stream.js.map +1 -0
  57. package/dist/thinking-parser.d.ts +21 -0
  58. package/dist/thinking-parser.js +150 -0
  59. package/dist/thinking-parser.js.map +1 -0
  60. package/dist/token-type.d.ts +18 -0
  61. package/dist/token-type.js +45 -0
  62. package/dist/token-type.js.map +1 -0
  63. package/dist/tokenizer.d.ts +1 -0
  64. package/dist/tokenizer.js +19 -0
  65. package/dist/tokenizer.js.map +1 -0
  66. package/dist/transform.d.ts +111 -0
  67. package/dist/transform.js +268 -0
  68. package/dist/transform.js.map +1 -0
  69. package/dist/truncation.d.ts +3 -0
  70. package/dist/truncation.js +12 -0
  71. package/dist/truncation.js.map +1 -0
  72. package/dist/types.d.ts +159 -0
  73. package/dist/types.js +4 -0
  74. package/dist/types.js.map +1 -0
  75. package/dist/usage.d.ts +86 -0
  76. package/dist/usage.js +85 -0
  77. package/dist/usage.js.map +1 -0
  78. package/package.json +31 -0
@@ -0,0 +1,49 @@
1
+ export type KiroWireEvent = {
2
+ type: "content";
3
+ data: string;
4
+ } | {
5
+ type: "thinkingText";
6
+ data: string;
7
+ } | {
8
+ type: "thinkingSignature";
9
+ data: string;
10
+ } | {
11
+ type: "toolUse";
12
+ data: {
13
+ name: string;
14
+ toolUseId: string;
15
+ input: string;
16
+ stop?: boolean;
17
+ };
18
+ } | {
19
+ type: "toolUseInput";
20
+ data: {
21
+ input: string;
22
+ };
23
+ } | {
24
+ type: "toolUseStop";
25
+ data: {
26
+ stop: boolean;
27
+ };
28
+ } | {
29
+ type: "contextUsage";
30
+ data: {
31
+ contextUsagePercentage: number;
32
+ };
33
+ } | {
34
+ type: "followupPrompt";
35
+ data: string;
36
+ } | {
37
+ type: "usage";
38
+ data: {
39
+ inputTokens?: number;
40
+ outputTokens?: number;
41
+ };
42
+ } | {
43
+ type: "error";
44
+ data: {
45
+ error: string;
46
+ message?: string;
47
+ };
48
+ };
49
+ export declare function parseKiroEvent(parsed: Record<string, unknown>): KiroWireEvent | null;
@@ -0,0 +1,56 @@
1
+ // ABOUTME: Kiro stream event type definitions and JSON-to-typed-event mapping.
2
+ // ABOUTME: Binary framing is handled by @smithy/core EventStreamMarshaller in stream.ts.
3
+ // Named `KiroWireEvent` to keep it distinct from `KiroStreamEvent`, which is what
4
+ // this package emits outward after parsing.
5
+ export function parseKiroEvent(parsed) {
6
+ if (parsed.content !== undefined)
7
+ return { type: "content", data: parsed.content };
8
+ if (typeof parsed.text === "string")
9
+ return { type: "thinkingText", data: parsed.text };
10
+ if (typeof parsed.signature === "string")
11
+ return { type: "thinkingSignature", data: parsed.signature };
12
+ if (parsed.name && parsed.toolUseId) {
13
+ const input = typeof parsed.input === "string"
14
+ ? parsed.input
15
+ : parsed.input &&
16
+ typeof parsed.input === "object" &&
17
+ Object.keys(parsed.input).length > 0
18
+ ? JSON.stringify(parsed.input)
19
+ : "";
20
+ return {
21
+ type: "toolUse",
22
+ data: {
23
+ name: parsed.name,
24
+ toolUseId: parsed.toolUseId,
25
+ input,
26
+ stop: parsed.stop,
27
+ },
28
+ };
29
+ }
30
+ if (parsed.input !== undefined && !parsed.name) {
31
+ return {
32
+ type: "toolUseInput",
33
+ data: { input: typeof parsed.input === "string" ? parsed.input : JSON.stringify(parsed.input) },
34
+ };
35
+ }
36
+ if (parsed.stop !== undefined && parsed.contextUsagePercentage === undefined)
37
+ return { type: "toolUseStop", data: { stop: parsed.stop } };
38
+ if (parsed.contextUsagePercentage !== undefined)
39
+ return { type: "contextUsage", data: { contextUsagePercentage: parsed.contextUsagePercentage } };
40
+ if (parsed.followupPrompt !== undefined)
41
+ return { type: "followupPrompt", data: parsed.followupPrompt };
42
+ if (parsed.error !== undefined || parsed.Error !== undefined) {
43
+ const error = (parsed.error || parsed.Error || "unknown");
44
+ const message = (parsed.message || parsed.Message || parsed.reason);
45
+ return { type: "error", data: { error: typeof error === "string" ? error : JSON.stringify(error), message } };
46
+ }
47
+ if (parsed.usage !== undefined) {
48
+ const u = parsed.usage;
49
+ return {
50
+ type: "usage",
51
+ data: { inputTokens: u.inputTokens, outputTokens: u.outputTokens },
52
+ };
53
+ }
54
+ return null;
55
+ }
56
+ //# sourceMappingURL=event-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-parser.js","sourceRoot":"","sources":["../src/event-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import { type KiroHistoryEntry } from "./transform.js";
2
+ /** Identifiers for the seven invariants. Names match kiro-agent's
3
+ * `ValidationRule` enum so diagnostics are greppable across both codebases. */
4
+ export declare enum KiroValidationRule {
5
+ STARTS_WITH_USER_MESSAGE = "STARTS_WITH_USER_MESSAGE",
6
+ ENDS_WITH_USER_MESSAGE = "ENDS_WITH_USER_MESSAGE",
7
+ ALTERNATING_MESSAGES = "ALTERNATING_MESSAGES",
8
+ TOOL_USES_AND_RESULTS = "TOOL_USES_AND_RESULTS",
9
+ TOOL_RESULTS_AND_NO_USES = "TOOL_RESULTS_AND_NO_USES",
10
+ TOOL_RESULTS_ORPHAN_IDS = "TOOL_RESULTS_ORPHAN_IDS",
11
+ NON_EMPTY_USER_MESSAGE = "NON_EMPTY_USER_MESSAGE"
12
+ }
13
+ export declare const KIRO_VALIDATION_MESSAGES: Record<KiroValidationRule, string>;
14
+ export interface KiroValidationError {
15
+ /** The invariant that was violated. */
16
+ rule: KiroValidationRule;
17
+ /** Human-readable description. */
18
+ message: string;
19
+ /** Index into the validated conversation where the violation was found. */
20
+ index: number;
21
+ }
22
+ export interface KiroValidationResult {
23
+ valid: boolean;
24
+ errors: KiroValidationError[];
25
+ }
26
+ /** The subset describing an unbalanced toolUse/toolResult turn — the shape the
27
+ * backend rejects as `TOOL_USE_RESULT_MISMATCH`. Probed 2026-08-11: a history
28
+ * whose final assistant `toolUse` has no matching `toolResult` returns
29
+ * `400 {"reason":"TOOL_USE_RESULT_MISMATCH"}`. */
30
+ export declare const KIRO_TOOL_STRUCTURE_RULES: readonly [KiroValidationRule.TOOL_USES_AND_RESULTS, KiroValidationRule.TOOL_RESULTS_AND_NO_USES, KiroValidationRule.TOOL_RESULTS_ORPHAN_IDS];
31
+ export type KiroToolStructureRule = (typeof KIRO_TOOL_STRUCTURE_RULES)[number];
32
+ export declare function isKiroToolStructureRule(rule: string): boolean;
33
+ /** Text of the synthetic result substituted for a tool result the caller never
34
+ * supplied. A pure function of nothing — same bytes every time, so a repaired
35
+ * conversation is byte-stable across retries. */
36
+ export declare const SYNTHETIC_FAILED_TOOL_RESULT_TEXT = "Tool use was interrupted and did not produce a result.";
37
+ export declare function validateStartsWithUserMessage(entries: KiroHistoryEntry[]): KiroValidationError | null;
38
+ export declare function validateEndsWithUserMessage(entries: KiroHistoryEntry[]): KiroValidationError | null;
39
+ export declare function validateAlternatingMessages(entries: KiroHistoryEntry[]): KiroValidationError | null;
40
+ export declare function validateToolUsesAndResults(entries: KiroHistoryEntry[]): KiroValidationError | null;
41
+ export declare function validateToolResultOrphanIds(entries: KiroHistoryEntry[]): KiroValidationError | null;
42
+ /** Content **or** tool results — not content unconditionally. This is the rule
43
+ * that makes an empty `content` on a tool turn correct rather than malformed. */
44
+ export declare function validateNonEmptyUserMessages(entries: KiroHistoryEntry[]): KiroValidationError | null;
45
+ /** Only the three tool-structure rules, in the order `validateKiroConversation`
46
+ * reports them. Cheaper than a full pass when only pairing matters. */
47
+ export declare function validateKiroToolStructure(entries: KiroHistoryEntry[]): KiroValidationResult;
48
+ /**
49
+ * Validates a whole conversation against all seven invariants.
50
+ *
51
+ * `entries` is the full conversation: the outbound `history` followed by the
52
+ * entry for `currentMessage`. Validating history alone would report a spurious
53
+ * `ENDS_WITH_USER_MESSAGE` — this provider's history deliberately ends on the
54
+ * assistant turn whose tool uses the current message answers. Use
55
+ * {@link kiroConversationEntries} to build the array.
56
+ */
57
+ export declare function validateKiroConversation(entries: KiroHistoryEntry[]): KiroValidationResult;
58
+ /** Assembles the conversation this provider actually sends: history plus the
59
+ * current user message. */
60
+ export declare function kiroConversationEntries(history: KiroHistoryEntry[], currentUserMessage: KiroHistoryEntry["userInputMessage"]): KiroHistoryEntry[];
61
+ export interface KiroRepairResult {
62
+ /** The repaired conversation. */
63
+ entries: KiroHistoryEntry[];
64
+ /** Violations found in the input, before repair. Empty when it was valid. */
65
+ diagnostics: KiroValidationError[];
66
+ /** Violations still present after repair. Non-empty means a shape this
67
+ * repair pass cannot express — report it rather than silently sending. */
68
+ remaining: KiroValidationError[];
69
+ }
70
+ /**
71
+ * Validates and repairs, rather than throwing. Mirrors what kiro-agent's
72
+ * sanitizer does, in this provider's terms:
73
+ *
74
+ * 1. Drop leading entries until the conversation starts with a user message
75
+ * that is not a bare tool-result carrier.
76
+ * 2. Consolidate runs of adjacent tool-result-only user messages into one.
77
+ * This runs **before** orphan-stripping on purpose: a run's later carriers
78
+ * are preceded by a user entry, not the assistant that issued the tool uses,
79
+ * so stripping first would judge their results orphaned and discard real
80
+ * tool output.
81
+ * 3. Strip orphaned and duplicate `toolResults`.
82
+ * 4. Synthesize an ERROR tool result for every assistant `toolUse` still
83
+ * unanswered.
84
+ * 5. Give a user message that has neither text nor tool results the neutral
85
+ * {@link EMPTY_CONTENT_PLACEHOLDER}.
86
+ *
87
+ * A repaired conversation is not guaranteed valid: an input that alternates
88
+ * incorrectly for reasons outside these five shapes is reported in
89
+ * `remaining`. Callers log it; nothing here throws.
90
+ */
91
+ export declare function repairKiroConversation(entries: KiroHistoryEntry[]): KiroRepairResult;
@@ -0,0 +1,370 @@
1
+ // Feature 11: Conversation History Validation
2
+ //
3
+ // The seven invariants first-party Kiro Agent enforces on a conversation before
4
+ // sending it, ported to this provider's request shape.
5
+ //
6
+ // Reference: `packages/kiro-agent/src/utils/message-history-sanitizer/`
7
+ // (`errors.ts` for the rule set, `validator.ts` for the checks, `sanitizer.ts`
8
+ // for the repairs). Only the validation is ported — kiro-agent's sanitizer is
9
+ // coupled to LangChain message types this provider does not use.
10
+ //
11
+ // This provider previously enforced none of these, relying instead on
12
+ // structural merging in `buildHistory` plus the salvage passes in `history.ts`.
13
+ // Repair, not rejection, is the default: failing closed on a history a caller
14
+ // has already built would be a behavior change for existing consumers, so
15
+ // `repairKiroConversation` returns a corrected conversation plus diagnostics
16
+ // and callers decide whether to care.
17
+ import { EMPTY_CONTENT_PLACEHOLDER } from "./transform.js";
18
+ /** Identifiers for the seven invariants. Names match kiro-agent's
19
+ * `ValidationRule` enum so diagnostics are greppable across both codebases. */
20
+ export var KiroValidationRule;
21
+ (function (KiroValidationRule) {
22
+ KiroValidationRule["STARTS_WITH_USER_MESSAGE"] = "STARTS_WITH_USER_MESSAGE";
23
+ KiroValidationRule["ENDS_WITH_USER_MESSAGE"] = "ENDS_WITH_USER_MESSAGE";
24
+ KiroValidationRule["ALTERNATING_MESSAGES"] = "ALTERNATING_MESSAGES";
25
+ KiroValidationRule["TOOL_USES_AND_RESULTS"] = "TOOL_USES_AND_RESULTS";
26
+ KiroValidationRule["TOOL_RESULTS_AND_NO_USES"] = "TOOL_RESULTS_AND_NO_USES";
27
+ KiroValidationRule["TOOL_RESULTS_ORPHAN_IDS"] = "TOOL_RESULTS_ORPHAN_IDS";
28
+ KiroValidationRule["NON_EMPTY_USER_MESSAGE"] = "NON_EMPTY_USER_MESSAGE";
29
+ })(KiroValidationRule || (KiroValidationRule = {}));
30
+ export const KIRO_VALIDATION_MESSAGES = {
31
+ [KiroValidationRule.STARTS_WITH_USER_MESSAGE]: "Conversation must start with a user message",
32
+ [KiroValidationRule.ENDS_WITH_USER_MESSAGE]: "Conversation must end with a user message",
33
+ [KiroValidationRule.ALTERNATING_MESSAGES]: "Between every two user messages there must be an assistant message",
34
+ [KiroValidationRule.TOOL_USES_AND_RESULTS]: "If an assistant message has tool uses, the next message must be a user message with corresponding tool results",
35
+ [KiroValidationRule.TOOL_RESULTS_AND_NO_USES]: "If there is a message with tool result, there has to be a corresponding message with tool use.",
36
+ [KiroValidationRule.NON_EMPTY_USER_MESSAGE]: "User messages must have either content or tool results",
37
+ [KiroValidationRule.TOOL_RESULTS_ORPHAN_IDS]: "User message has toolResults whose toolUseIds do not match any toolUse in the preceding assistant message.",
38
+ };
39
+ /** The subset describing an unbalanced toolUse/toolResult turn — the shape the
40
+ * backend rejects as `TOOL_USE_RESULT_MISMATCH`. Probed 2026-08-11: a history
41
+ * whose final assistant `toolUse` has no matching `toolResult` returns
42
+ * `400 {"reason":"TOOL_USE_RESULT_MISMATCH"}`. */
43
+ export const KIRO_TOOL_STRUCTURE_RULES = [
44
+ KiroValidationRule.TOOL_USES_AND_RESULTS,
45
+ KiroValidationRule.TOOL_RESULTS_AND_NO_USES,
46
+ KiroValidationRule.TOOL_RESULTS_ORPHAN_IDS,
47
+ ];
48
+ export function isKiroToolStructureRule(rule) {
49
+ return KIRO_TOOL_STRUCTURE_RULES.includes(rule);
50
+ }
51
+ /** Text of the synthetic result substituted for a tool result the caller never
52
+ * supplied. A pure function of nothing — same bytes every time, so a repaired
53
+ * conversation is byte-stable across retries. */
54
+ export const SYNTHETIC_FAILED_TOOL_RESULT_TEXT = "Tool use was interrupted and did not produce a result.";
55
+ function error(rule, index, message) {
56
+ return { rule, message: message ?? KIRO_VALIDATION_MESSAGES[rule], index };
57
+ }
58
+ function isUserEntry(entry) {
59
+ return !!entry?.userInputMessage;
60
+ }
61
+ function isAssistantEntry(entry) {
62
+ return !!entry?.assistantResponseMessage;
63
+ }
64
+ function toolResultsOf(entry) {
65
+ return entry?.userInputMessage?.userInputMessageContext?.toolResults ?? [];
66
+ }
67
+ function hasToolResults(entry) {
68
+ return toolResultsOf(entry).length > 0;
69
+ }
70
+ function toolUseIdsOf(entry) {
71
+ return (entry?.assistantResponseMessage?.toolUses ?? []).map((tu) => tu.toolUseId).filter(Boolean);
72
+ }
73
+ function hasToolUses(entry) {
74
+ return toolUseIdsOf(entry).length > 0;
75
+ }
76
+ function hasText(entry) {
77
+ return (entry?.userInputMessage?.content ?? "").trim() !== "";
78
+ }
79
+ /** True when every toolUse has a result and every result has a toolUse. */
80
+ function toolResultsMatch(toolUseIds, toolResults) {
81
+ if (toolUseIds.length === 0)
82
+ return true;
83
+ if (toolResults.length === 0)
84
+ return false;
85
+ const resultIds = new Set(toolResults.map((tr) => tr.toolUseId));
86
+ const useIds = new Set(toolUseIds);
87
+ return toolUseIds.every((id) => resultIds.has(id)) && toolResults.every((tr) => useIds.has(tr.toolUseId));
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Individual rule checks. Each returns the first violation it finds, or null.
91
+ // ---------------------------------------------------------------------------
92
+ export function validateStartsWithUserMessage(entries) {
93
+ if (entries.length === 0 || !isUserEntry(entries[0])) {
94
+ return error(KiroValidationRule.STARTS_WITH_USER_MESSAGE, 0);
95
+ }
96
+ return null;
97
+ }
98
+ export function validateEndsWithUserMessage(entries) {
99
+ if (entries.length === 0 || !isUserEntry(entries[entries.length - 1])) {
100
+ return error(KiroValidationRule.ENDS_WITH_USER_MESSAGE, entries.length - 1);
101
+ }
102
+ return null;
103
+ }
104
+ export function validateAlternatingMessages(entries) {
105
+ for (let i = 1; i < entries.length; i++) {
106
+ if (isUserEntry(entries[i - 1]) && isUserEntry(entries[i])) {
107
+ return error(KiroValidationRule.ALTERNATING_MESSAGES, i, "Between every two user messages there must be an assistant message");
108
+ }
109
+ if (isAssistantEntry(entries[i - 1]) && isAssistantEntry(entries[i])) {
110
+ return error(KiroValidationRule.ALTERNATING_MESSAGES, i, "Between every two assistant messages there must be a user message");
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ export function validateToolUsesAndResults(entries) {
116
+ for (let i = 0; i < entries.length - 1; i++) {
117
+ const current = entries[i];
118
+ const next = entries[i + 1];
119
+ if (isAssistantEntry(current) &&
120
+ hasToolUses(current) &&
121
+ (!isUserEntry(next) || !toolResultsMatch(toolUseIdsOf(current), toolResultsOf(next)))) {
122
+ return error(KiroValidationRule.TOOL_USES_AND_RESULTS, i + 1);
123
+ }
124
+ if (isAssistantEntry(current) && !hasToolUses(current) && isUserEntry(next) && hasToolResults(next)) {
125
+ return error(KiroValidationRule.TOOL_RESULTS_AND_NO_USES, i);
126
+ }
127
+ }
128
+ // A carrier with no assistant predecessor at all — first entry, or preceded by
129
+ // another user entry. The pairwise walk above cannot see it: it only inspects
130
+ // a carrier that follows an assistant entry. kiro-agent never reaches this
131
+ // shape because its sanitizer drops leading carriers before validating, but
132
+ // this provider can send one as the *current* message: `prepareHistory`
133
+ // guarantees every carrier inside `history` has an assistant-with-toolUses
134
+ // predecessor (`sanitizeHistory` drops the rest, `injectSyntheticToolCalls`
135
+ // synthesizes uses for orphans), and the current message is assembled after
136
+ // that pass. Probed 2026-08-11: a lone current-turn carrier reached the wire
137
+ // with `toolResults` and no `toolUse` anywhere while this check stayed silent.
138
+ for (let i = 0; i < entries.length; i++) {
139
+ const entry = entries[i];
140
+ if (!isUserEntry(entry) || !hasToolResults(entry))
141
+ continue;
142
+ const prev = i > 0 ? entries[i - 1] : undefined;
143
+ if (!isAssistantEntry(prev))
144
+ return error(KiroValidationRule.TOOL_RESULTS_AND_NO_USES, i);
145
+ }
146
+ return null;
147
+ }
148
+ export function validateToolResultOrphanIds(entries) {
149
+ for (let i = 1; i < entries.length; i++) {
150
+ const prev = entries[i - 1];
151
+ const current = entries[i];
152
+ if (!isAssistantEntry(prev) || !hasToolUses(prev) || !isUserEntry(current) || !hasToolResults(current))
153
+ continue;
154
+ const validIds = new Set(toolUseIdsOf(prev));
155
+ const toolResults = toolResultsOf(current);
156
+ const hasOrphan = toolResults.some((tr) => !tr.toolUseId || !validIds.has(tr.toolUseId));
157
+ const seen = new Set();
158
+ const hasDuplicate = toolResults.some((tr) => {
159
+ if (!tr.toolUseId)
160
+ return false;
161
+ if (seen.has(tr.toolUseId))
162
+ return true;
163
+ seen.add(tr.toolUseId);
164
+ return false;
165
+ });
166
+ if (hasOrphan || hasDuplicate)
167
+ return error(KiroValidationRule.TOOL_RESULTS_ORPHAN_IDS, i);
168
+ }
169
+ return null;
170
+ }
171
+ /** Content **or** tool results — not content unconditionally. This is the rule
172
+ * that makes an empty `content` on a tool turn correct rather than malformed. */
173
+ export function validateNonEmptyUserMessages(entries) {
174
+ for (let i = 0; i < entries.length; i++) {
175
+ const entry = entries[i];
176
+ if (!isUserEntry(entry))
177
+ continue;
178
+ if (!hasText(entry) && !hasToolResults(entry)) {
179
+ return error(KiroValidationRule.NON_EMPTY_USER_MESSAGE, i);
180
+ }
181
+ }
182
+ return null;
183
+ }
184
+ /** Only the three tool-structure rules, in the order `validateKiroConversation`
185
+ * reports them. Cheaper than a full pass when only pairing matters. */
186
+ export function validateKiroToolStructure(entries) {
187
+ const errors = [validateToolUsesAndResults(entries), validateToolResultOrphanIds(entries)].filter((e) => e !== null);
188
+ return { valid: errors.length === 0, errors };
189
+ }
190
+ /**
191
+ * Validates a whole conversation against all seven invariants.
192
+ *
193
+ * `entries` is the full conversation: the outbound `history` followed by the
194
+ * entry for `currentMessage`. Validating history alone would report a spurious
195
+ * `ENDS_WITH_USER_MESSAGE` — this provider's history deliberately ends on the
196
+ * assistant turn whose tool uses the current message answers. Use
197
+ * {@link kiroConversationEntries} to build the array.
198
+ */
199
+ export function validateKiroConversation(entries) {
200
+ const errors = [
201
+ validateStartsWithUserMessage(entries),
202
+ validateEndsWithUserMessage(entries),
203
+ validateAlternatingMessages(entries),
204
+ ...validateKiroToolStructure(entries).errors,
205
+ validateNonEmptyUserMessages(entries),
206
+ ].filter((e) => e !== null);
207
+ return { valid: errors.length === 0, errors };
208
+ }
209
+ /** Assembles the conversation this provider actually sends: history plus the
210
+ * current user message. */
211
+ export function kiroConversationEntries(history, currentUserMessage) {
212
+ return currentUserMessage ? [...history, { userInputMessage: currentUserMessage }] : [...history];
213
+ }
214
+ /**
215
+ * Validates and repairs, rather than throwing. Mirrors what kiro-agent's
216
+ * sanitizer does, in this provider's terms:
217
+ *
218
+ * 1. Drop leading entries until the conversation starts with a user message
219
+ * that is not a bare tool-result carrier.
220
+ * 2. Consolidate runs of adjacent tool-result-only user messages into one.
221
+ * This runs **before** orphan-stripping on purpose: a run's later carriers
222
+ * are preceded by a user entry, not the assistant that issued the tool uses,
223
+ * so stripping first would judge their results orphaned and discard real
224
+ * tool output.
225
+ * 3. Strip orphaned and duplicate `toolResults`.
226
+ * 4. Synthesize an ERROR tool result for every assistant `toolUse` still
227
+ * unanswered.
228
+ * 5. Give a user message that has neither text nor tool results the neutral
229
+ * {@link EMPTY_CONTENT_PLACEHOLDER}.
230
+ *
231
+ * A repaired conversation is not guaranteed valid: an input that alternates
232
+ * incorrectly for reasons outside these five shapes is reported in
233
+ * `remaining`. Callers log it; nothing here throws.
234
+ */
235
+ export function repairKiroConversation(entries) {
236
+ const diagnostics = validateKiroConversation(entries).errors;
237
+ if (diagnostics.length === 0)
238
+ return { entries, diagnostics, remaining: [] };
239
+ // A synthesized user turn must declare the same model as its neighbours.
240
+ const modelId = entries.find((e) => e.userInputMessage?.modelId)?.userInputMessage?.modelId ?? "";
241
+ // 1. Leading entries that cannot start a conversation.
242
+ let working = [...entries];
243
+ while (working.length > 0 && (!isUserEntry(working[0]) || hasToolResults(working[0])))
244
+ working = working.slice(1);
245
+ // 2. Consolidate adjacent tool-result-only user messages. Must precede the
246
+ // orphan pass: a later carrier in such a run is preceded by a user entry,
247
+ // whose toolUse id set is empty, so orphan-stripping would delete its real
248
+ // results and leave synthesis to substitute failure text for output the
249
+ // caller actually had.
250
+ const consolidated = [];
251
+ for (let i = 0; i < working.length; i++) {
252
+ const entry = working[i];
253
+ const isToolOnly = isUserEntry(entry) && hasToolResults(entry) && !hasText(entry);
254
+ if (!isToolOnly) {
255
+ consolidated.push(entry);
256
+ continue;
257
+ }
258
+ let j = i;
259
+ const merged = [];
260
+ const seen = new Set();
261
+ while (j < working.length) {
262
+ const candidate = working[j];
263
+ if (!(isUserEntry(candidate) && hasToolResults(candidate) && !hasText(candidate)))
264
+ break;
265
+ for (const tr of toolResultsOf(candidate)) {
266
+ if (tr.toolUseId && seen.has(tr.toolUseId))
267
+ continue;
268
+ if (tr.toolUseId)
269
+ seen.add(tr.toolUseId);
270
+ merged.push(tr);
271
+ }
272
+ j++;
273
+ }
274
+ if (j - i === 1) {
275
+ consolidated.push(entry);
276
+ }
277
+ else {
278
+ const uim = entry.userInputMessage;
279
+ consolidated.push({
280
+ userInputMessage: {
281
+ ...uim,
282
+ userInputMessageContext: { ...uim.userInputMessageContext, toolResults: merged },
283
+ },
284
+ });
285
+ }
286
+ i = j - 1;
287
+ }
288
+ working = consolidated;
289
+ // 3 + 4. Walk pairs, fixing tool structure in both directions.
290
+ const repaired = [];
291
+ for (let i = 0; i < working.length; i++) {
292
+ const entry = working[i];
293
+ if (isUserEntry(entry) && hasToolResults(entry)) {
294
+ const prev = repaired[repaired.length - 1];
295
+ const validIds = new Set(toolUseIdsOf(prev));
296
+ const seen = new Set();
297
+ const kept = toolResultsOf(entry).filter((tr) => {
298
+ if (!tr.toolUseId || !validIds.has(tr.toolUseId) || seen.has(tr.toolUseId))
299
+ return false;
300
+ seen.add(tr.toolUseId);
301
+ return true;
302
+ });
303
+ const uim = { ...entry.userInputMessage };
304
+ if (kept.length === 0) {
305
+ const { userInputMessageContext, ...rest } = uim;
306
+ const tools = userInputMessageContext?.tools;
307
+ repaired.push({
308
+ userInputMessage: { ...rest, ...(tools ? { userInputMessageContext: { tools } } : {}) },
309
+ });
310
+ }
311
+ else {
312
+ repaired.push({
313
+ userInputMessage: {
314
+ ...uim,
315
+ userInputMessageContext: { ...uim.userInputMessageContext, toolResults: kept },
316
+ },
317
+ });
318
+ }
319
+ continue;
320
+ }
321
+ repaired.push(entry);
322
+ // 4. Assistant toolUses the next entry does not answer.
323
+ if (isAssistantEntry(entry) && hasToolUses(entry)) {
324
+ const next = working[i + 1];
325
+ const answered = new Set(isUserEntry(next) ? toolResultsOf(next).map((tr) => tr.toolUseId) : /* c8 ignore next */ []);
326
+ const unanswered = toolUseIdsOf(entry).filter((id) => !answered.has(id));
327
+ if (unanswered.length > 0 && !isUserEntry(next)) {
328
+ // No user turn follows at all: insert one carrying every result.
329
+ repaired.push(syntheticToolResultEntry(unanswered, modelId));
330
+ }
331
+ else if (unanswered.length > 0 && isUserEntry(next)) {
332
+ // A user turn follows but under-answers: top it up in place.
333
+ const uim = { ...next.userInputMessage };
334
+ working[i + 1] = {
335
+ userInputMessage: {
336
+ ...uim,
337
+ userInputMessageContext: {
338
+ ...uim.userInputMessageContext,
339
+ toolResults: [...toolResultsOf(next), ...unanswered.map(syntheticFailedToolResult)],
340
+ },
341
+ },
342
+ };
343
+ }
344
+ }
345
+ }
346
+ // 5. Neither text nor tool results — give it the neutral prompt.
347
+ const final = repaired.map((entry) => {
348
+ if (!isUserEntry(entry) || hasText(entry) || hasToolResults(entry))
349
+ return entry;
350
+ const uim = entry.userInputMessage;
351
+ return { userInputMessage: { ...uim, content: EMPTY_CONTENT_PLACEHOLDER } };
352
+ });
353
+ return { entries: final, diagnostics, remaining: validateKiroConversation(final).errors };
354
+ }
355
+ function syntheticFailedToolResult(toolUseId) {
356
+ return { toolUseId, content: [{ text: SYNTHETIC_FAILED_TOOL_RESULT_TEXT }], status: "error" };
357
+ }
358
+ function syntheticToolResultEntry(toolUseIds, modelId) {
359
+ return {
360
+ userInputMessage: {
361
+ // Empty by design: `toolResults` is the payload. Matches kiro-agent's
362
+ // `FAILED_TOOL_USE_MESSAGE`, which also ships `content: ''`.
363
+ content: "",
364
+ modelId,
365
+ origin: "KIRO_CLI",
366
+ userInputMessageContext: { toolResults: toolUseIds.map(syntheticFailedToolResult) },
367
+ },
368
+ };
369
+ }
370
+ //# sourceMappingURL=history-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-validator.js","sourceRoot":"","sources":["../src/history-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { KiroHistoryEntry, KiroToolSpec } from "./transform.js";
2
+ export declare const HISTORY_LIMIT = 850000;
3
+ /** The context window size (in tokens) that HISTORY_LIMIT was calibrated for. */
4
+ export declare const HISTORY_LIMIT_CONTEXT_WINDOW = 200000;
5
+ /** Maximum combined base64 characters retained for one historical image-bearing turn. */
6
+ export declare const HISTORY_IMAGE_BASE64_LIMIT: number;
7
+ /**
8
+ * Keep at most the newest bounded image-bearing history entry.
9
+ *
10
+ * Older images are removed to bound request growth. If the newest image set is
11
+ * itself too large, remove it as well rather than substituting an older image
12
+ * that no longer matches a follow-up such as "look at that image again".
13
+ */
14
+ export declare function stripHistoryImages(history: KiroHistoryEntry[], keepNewestBounded?: boolean): KiroHistoryEntry[];
15
+ export declare function sanitizeHistory(history: KiroHistoryEntry[]): KiroHistoryEntry[];
16
+ export declare function injectSyntheticToolCalls(history: KiroHistoryEntry[]): KiroHistoryEntry[];
17
+ export declare function prepareHistory(history: KiroHistoryEntry[], keepNewestBoundedImage?: boolean): KiroHistoryEntry[];
18
+ /** Fail before sending rather than silently discarding conversation context. */
19
+ export declare function assertHistoryWithinLimit(history: KiroHistoryEntry[], limit: number): void;
20
+ export declare function extractToolNamesFromHistory(history: KiroHistoryEntry[]): Set<string>;
21
+ export declare function addPlaceholderTools(tools: KiroToolSpec[], history: KiroHistoryEntry[]): KiroToolSpec[];