@arvoretech/pi-kiro-provider 0.8.1

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 (74) hide show
  1. package/README.md +121 -0
  2. package/dist/bracket-tool-parser.d.ts +12 -0
  3. package/dist/bracket-tool-parser.d.ts.map +1 -0
  4. package/dist/bracket-tool-parser.js +78 -0
  5. package/dist/bracket-tool-parser.js.map +1 -0
  6. package/dist/debug.d.ts +3 -0
  7. package/dist/debug.d.ts.map +1 -0
  8. package/dist/debug.js +49 -0
  9. package/dist/debug.js.map +1 -0
  10. package/dist/event-parser.d.ts +44 -0
  11. package/dist/event-parser.d.ts.map +1 -0
  12. package/dist/event-parser.js +66 -0
  13. package/dist/event-parser.js.map +1 -0
  14. package/dist/history.d.ts +13 -0
  15. package/dist/history.d.ts.map +1 -0
  16. package/dist/history.js +121 -0
  17. package/dist/history.js.map +1 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +44 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/kiro-cli.d.ts +32 -0
  23. package/dist/kiro-cli.d.ts.map +1 -0
  24. package/dist/kiro-cli.js +271 -0
  25. package/dist/kiro-cli.js.map +1 -0
  26. package/dist/kiro-ide.d.ts +13 -0
  27. package/dist/kiro-ide.d.ts.map +1 -0
  28. package/dist/kiro-ide.js +74 -0
  29. package/dist/kiro-ide.js.map +1 -0
  30. package/dist/login-ui.d.ts +18 -0
  31. package/dist/login-ui.d.ts.map +1 -0
  32. package/dist/login-ui.js +124 -0
  33. package/dist/login-ui.js.map +1 -0
  34. package/dist/login.d.ts +16 -0
  35. package/dist/login.d.ts.map +1 -0
  36. package/dist/login.js +217 -0
  37. package/dist/login.js.map +1 -0
  38. package/dist/models.d.ts +72 -0
  39. package/dist/models.d.ts.map +1 -0
  40. package/dist/models.js +461 -0
  41. package/dist/models.js.map +1 -0
  42. package/dist/oauth.d.ts +30 -0
  43. package/dist/oauth.d.ts.map +1 -0
  44. package/dist/oauth.js +226 -0
  45. package/dist/oauth.js.map +1 -0
  46. package/dist/retry.d.ts +21 -0
  47. package/dist/retry.d.ts.map +1 -0
  48. package/dist/retry.js +51 -0
  49. package/dist/retry.js.map +1 -0
  50. package/dist/stream.d.ts +5 -0
  51. package/dist/stream.d.ts.map +1 -0
  52. package/dist/stream.js +858 -0
  53. package/dist/stream.js.map +1 -0
  54. package/dist/thinking-parser.d.ts +24 -0
  55. package/dist/thinking-parser.d.ts.map +1 -0
  56. package/dist/thinking-parser.js +205 -0
  57. package/dist/thinking-parser.js.map +1 -0
  58. package/dist/tokenizer.d.ts +2 -0
  59. package/dist/tokenizer.d.ts.map +1 -0
  60. package/dist/tokenizer.js +16 -0
  61. package/dist/tokenizer.js.map +1 -0
  62. package/dist/transform.d.ts +63 -0
  63. package/dist/transform.d.ts.map +1 -0
  64. package/dist/transform.js +200 -0
  65. package/dist/transform.js.map +1 -0
  66. package/dist/truncation.d.ts +4 -0
  67. package/dist/truncation.d.ts.map +1 -0
  68. package/dist/truncation.js +13 -0
  69. package/dist/truncation.js.map +1 -0
  70. package/dist/usage.d.ts +90 -0
  71. package/dist/usage.d.ts.map +1 -0
  72. package/dist/usage.js +169 -0
  73. package/dist/usage.js.map +1 -0
  74. package/package.json +61 -0
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @arvoretech/pi-kiro-provider
2
+
3
+ A [pi](https://github.com/earendil-works/pi-coding-agent) provider extension that connects pi to the **Kiro API** (AWS CodeWhisperer/Q), exposing kiro-cli-verified models through one provider surface.
4
+
5
+ ## Why this exists
6
+
7
+ Kiro gives you a strong free model menu, but pi needs a provider that speaks Kiro's auth, model catalog, and streaming protocol cleanly. `@arvoretech/pi-kiro-provider` handles that bridge, including:
8
+
9
+ - AWS Builder ID, IAM Identity Center, Google, and GitHub login flows
10
+ - shared credentials from an existing `kiro-cli` session when available
11
+ - reasoning-aware streaming
12
+ - region-aware model filtering so pi only shows models your Kiro region can actually use
13
+
14
+ ## Quick start
15
+
16
+ Add to `.pi/settings.json`:
17
+
18
+ ```json
19
+ {
20
+ "packages": ["npm:@arvoretech/pi-kiro-provider"]
21
+ }
22
+ ```
23
+
24
+ Or reference the local dist path for project-local development:
25
+
26
+ ```json
27
+ {
28
+ "extensions": ["./arvore-pi-extensions/packages/kiro-provider/dist/index.js"]
29
+ }
30
+ ```
31
+
32
+ Then log in from pi:
33
+
34
+ ```text
35
+ /login kiro
36
+ ```
37
+
38
+ The login flow supports:
39
+ - **AWS Builder ID** — native device-code flow, works well over SSH/remotes
40
+ - **Your organization** — IAM Identity Center start URL
41
+ - **Google** — social login via `kiro-cli`
42
+ - **GitHub** — social login via `kiro-cli`
43
+
44
+ If you already use [kiro-cli](https://kiro.dev), the provider can reuse those credentials instead of forcing a second login.
45
+
46
+ ## Models
47
+
48
+ | Family | Models | Context | Reasoning |
49
+ |--------|--------|---------|-----------|
50
+ | Claude Opus | `claude-opus-4-7`, `claude-opus-4-6` | 1M | ✓ |
51
+ | Claude Sonnet 5 | `claude-sonnet-5` | 1M | ✓ |
52
+ | Claude Sonnet 4.6 | `claude-sonnet-4-6` | 1M | ✓ |
53
+ | Claude Sonnet 4.5 | `claude-sonnet-4-5` | 200K | ✓ |
54
+ | Claude Sonnet 4 | `claude-sonnet-4` | 200K | ✓ |
55
+ | Claude Haiku 4.5 | `claude-haiku-4-5` | 200K | ✗ |
56
+ | Claude Fable 5 | `claude-fable-5` | 1M | ✓ |
57
+ | DeepSeek 3.2 | `deepseek-3-2` | 164K | ✓ |
58
+ | MiniMax | `minimax-m2-1`, `minimax-m2-5` | 196K | ✗ |
59
+ | GLM 5 | `glm-5` | 200K | ✓ |
60
+ | Qwen3 Coder | `qwen3-coder-next` | 256K | ✓ |
61
+ | Auto | `auto` | 1M | ✓ |
62
+
63
+ All listed models are free to use through Kiro.
64
+
65
+ ## Usage
66
+
67
+ Once logged in, select any Kiro model in pi:
68
+
69
+ ```text
70
+ /model claude-sonnet-4-6
71
+ ```
72
+
73
+ Or let Kiro pick automatically:
74
+
75
+ ```text
76
+ /model auto
77
+ ```
78
+
79
+ Reasoning is automatically enabled for supported models. Use `/reasoning` to adjust the thinking budget.
80
+
81
+ ## Retry Behavior
82
+
83
+ Generic transient retries such as HTTP `429` and `5xx` are handled by `pi-coding-agent` at the session layer.
84
+
85
+ This provider only keeps local recovery for Kiro-specific cases:
86
+ - `403` auth races, where it can refresh credentials from `kiro-cli`
87
+ - first-token / stalled-stream recovery
88
+ - empty-stream retries
89
+ - non-retryable Kiro body markers like `MONTHLY_REQUEST_COUNT` and `INSUFFICIENT_MODEL_CAPACITY`
90
+
91
+ ## Development
92
+
93
+ ```bash
94
+ pnpm build # Compile TypeScript
95
+ pnpm check # Type check (no emit)
96
+ pnpm test # Run the Vitest suite
97
+ pnpm test:watch # Watch mode
98
+ ```
99
+
100
+ ## Architecture
101
+
102
+ The extension is organized as one feature per file:
103
+
104
+ ```
105
+ src/
106
+ ├── index.ts # Extension registration
107
+ ├── models.ts # 12 model definitions + ID resolution
108
+ ├── oauth.ts # Multi-provider auth (Builder ID / Google / GitHub)
109
+ ├── kiro-cli.ts # kiro-cli credential sharing
110
+ ├── transform.ts # Message format conversion
111
+ ├── history.ts # Conversation history management
112
+ ├── thinking-parser.ts # Streaming <thinking> tag parser
113
+ ├── event-parser.ts # Kiro stream event parser
114
+ └── stream.ts # Main streaming orchestrator
115
+ ```
116
+
117
+ See [src/](src/) — each file owns one feature (extension registration, model catalog, OAuth, kiro-cli credential sharing, message transform, history management, thinking-tag parsing, event parsing, and the streaming orchestrator).
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,12 @@
1
+ export declare function findJsonEnd(text: string, start: number): number;
2
+ export interface BracketToolCall {
3
+ toolUseId: string;
4
+ name: string;
5
+ arguments: Record<string, unknown>;
6
+ }
7
+ export interface BracketParseResult {
8
+ toolCalls: BracketToolCall[];
9
+ cleanedText: string;
10
+ }
11
+ export declare function parseBracketToolCalls(text: string): BracketParseResult;
12
+ //# sourceMappingURL=bracket-tool-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bracket-tool-parser.d.ts","sourceRoot":"","sources":["../src/bracket-tool-parser.ts"],"names":[],"mappings":"AAGA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA2B/D;AAED,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,kBAAkB;IAClC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACpB;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CA8CtE"}
@@ -0,0 +1,78 @@
1
+ // ABOUTME: Extracts bracket-style tool calls from content text as a fallback.
2
+ // ABOUTME: Parses [Called func_name with args: {...}] patterns from model output.
3
+ export function findJsonEnd(text, start) {
4
+ let braceCount = 0;
5
+ let inString = false;
6
+ let escapeNext = false;
7
+ for (let i = start; i < text.length; i++) {
8
+ const char = text[i];
9
+ if (escapeNext) {
10
+ escapeNext = false;
11
+ continue;
12
+ }
13
+ if (char === "\\") {
14
+ escapeNext = true;
15
+ continue;
16
+ }
17
+ if (char === '"') {
18
+ inString = !inString;
19
+ continue;
20
+ }
21
+ if (!inString) {
22
+ if (char === "{")
23
+ braceCount++;
24
+ else if (char === "}") {
25
+ braceCount--;
26
+ if (braceCount === 0)
27
+ return i;
28
+ }
29
+ }
30
+ }
31
+ return -1;
32
+ }
33
+ const BRACKET_PATTERN = /\[Called\s+([\w-]+)\s+with\s+args:\s*/g;
34
+ export function parseBracketToolCalls(text) {
35
+ const toolCalls = [];
36
+ const removals = [];
37
+ // Reset the regex lastIndex to ensure consistent behavior
38
+ BRACKET_PATTERN.lastIndex = 0;
39
+ let match = BRACKET_PATTERN.exec(text);
40
+ while (match !== null) {
41
+ const name = match[1];
42
+ const jsonStart = match.index + match[0].length;
43
+ const braceIdx = text.indexOf("{", jsonStart);
44
+ if (braceIdx >= 0 && braceIdx === jsonStart) {
45
+ const jsonEndIdx = findJsonEnd(text, braceIdx);
46
+ if (jsonEndIdx >= 0) {
47
+ const afterJson = text.indexOf("]", jsonEndIdx + 1);
48
+ if (afterJson >= 0) {
49
+ const between = text.substring(jsonEndIdx + 1, afterJson).trim();
50
+ if (between.length === 0) {
51
+ const jsonStr = text.substring(braceIdx, jsonEndIdx + 1);
52
+ try {
53
+ const args = JSON.parse(jsonStr);
54
+ toolCalls.push({
55
+ toolUseId: crypto.randomUUID(),
56
+ name,
57
+ arguments: args,
58
+ });
59
+ removals.push({ start: match.index, end: afterJson + 1 });
60
+ }
61
+ catch {
62
+ // Malformed JSON — skip this match
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ match = BRACKET_PATTERN.exec(text);
69
+ }
70
+ // Build cleaned text by removing matched bracket patterns (reverse order to preserve indices)
71
+ let cleanedText = text;
72
+ for (let i = removals.length - 1; i >= 0; i--) {
73
+ const { start, end } = removals[i];
74
+ cleanedText = cleanedText.substring(0, start) + cleanedText.substring(end);
75
+ }
76
+ return { toolCalls, cleanedText };
77
+ }
78
+ //# sourceMappingURL=bracket-tool-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bracket-tool-parser.js","sourceRoot":"","sources":["../src/bracket-tool-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function debugEnabled(): boolean;
2
+ export declare function debugLog(section: string, data?: unknown): void;
3
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAcA,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAkB9D"}
package/dist/debug.js ADDED
@@ -0,0 +1,49 @@
1
+ // ABOUTME: Debug logging — dumps requests, responses, stream events, and errors
2
+ // ABOUTME: to a log file when KIRO_DEBUG=1. Custom path via KIRO_DEBUG_LOG.
3
+ import { appendFileSync, mkdirSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { dirname, join } from "node:path";
6
+ const ENABLED = !!process.env.KIRO_DEBUG && process.env.KIRO_DEBUG !== "0";
7
+ const LOG_FILE = process.env.KIRO_DEBUG_LOG ||
8
+ join(homedir(), ".pi", "logs", "kiro-debug.log");
9
+ let dirReady = false;
10
+ export function debugEnabled() {
11
+ return ENABLED;
12
+ }
13
+ export function debugLog(section, data) {
14
+ if (!ENABLED)
15
+ return;
16
+ try {
17
+ if (!dirReady) {
18
+ mkdirSync(dirname(LOG_FILE), { recursive: true });
19
+ dirReady = true;
20
+ }
21
+ const ts = new Date().toISOString();
22
+ const body = data === undefined
23
+ ? ""
24
+ : typeof data === "string"
25
+ ? ` ${data}`
26
+ : ` ${JSON.stringify(data, redact, 2)}`;
27
+ appendFileSync(LOG_FILE, `${ts} [${section}]${body}\n`);
28
+ }
29
+ catch {
30
+ // best-effort; never break the provider
31
+ }
32
+ }
33
+ /** Redact auth tokens in JSON output. */
34
+ function redact(key, value) {
35
+ if (typeof value !== "string")
36
+ return value;
37
+ const k = key.toLowerCase();
38
+ if (k === "authorization" ||
39
+ k === "access" ||
40
+ k === "refresh" ||
41
+ k.includes("token") ||
42
+ k.includes("secret")) {
43
+ return value.length > 8
44
+ ? `${value.slice(0, 4)}…${value.slice(-4)}(${value.length})`
45
+ : "<redacted>";
46
+ }
47
+ return value;
48
+ }
49
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4EAA4E;AAE5E,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,GAAG,CAAC;AAC3E,MAAM,QAAQ,GACb,OAAO,CAAC,GAAG,CAAC,cAAc;IAC1B,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAElD,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,MAAM,UAAU,YAAY;IAC3B,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,IAAc;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,IAAI,CAAC;QACJ,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClD,QAAQ,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,IAAI,GACT,IAAI,KAAK,SAAS;YACjB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,OAAO,IAAI,KAAK,QAAQ;gBACzB,CAAC,CAAC,IAAI,IAAI,EAAE;gBACZ,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;QAC3C,cAAc,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACR,wCAAwC;IACzC,CAAC;AACF,CAAC;AAED,yCAAyC;AACzC,SAAS,MAAM,CAAC,GAAW,EAAE,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC5B,IACC,CAAC,KAAK,eAAe;QACrB,CAAC,KAAK,QAAQ;QACd,CAAC,KAAK,SAAS;QACf,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QACnB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EACnB,CAAC;QACF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC;YACtB,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG;YAC5D,CAAC,CAAC,YAAY,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,44 @@
1
+ export type KiroStreamEvent = {
2
+ type: "content";
3
+ data: string;
4
+ } | {
5
+ type: "toolUse";
6
+ data: {
7
+ name: string;
8
+ toolUseId: string;
9
+ input: string;
10
+ stop?: boolean;
11
+ };
12
+ } | {
13
+ type: "toolUseInput";
14
+ data: {
15
+ input: string;
16
+ };
17
+ } | {
18
+ type: "toolUseStop";
19
+ data: {
20
+ stop: boolean;
21
+ };
22
+ } | {
23
+ type: "contextUsage";
24
+ data: {
25
+ contextUsagePercentage: number;
26
+ };
27
+ } | {
28
+ type: "followupPrompt";
29
+ data: string;
30
+ } | {
31
+ type: "usage";
32
+ data: {
33
+ inputTokens?: number;
34
+ outputTokens?: number;
35
+ };
36
+ } | {
37
+ type: "error";
38
+ data: {
39
+ error: string;
40
+ message?: string;
41
+ };
42
+ };
43
+ export declare function parseKiroEvent(parsed: Record<string, unknown>): KiroStreamEvent | null;
44
+ //# sourceMappingURL=event-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-parser.d.ts","sourceRoot":"","sources":["../src/event-parser.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,eAAe,GACxB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IACA,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxE,GACD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,sBAAsB,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEhE,wBAAgB,cAAc,CAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,eAAe,GAAG,IAAI,CAkExB"}
@@ -0,0 +1,66 @@
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
+ export function parseKiroEvent(parsed) {
4
+ if (parsed.content !== undefined)
5
+ return { type: "content", data: parsed.content };
6
+ if (parsed.name && parsed.toolUseId) {
7
+ const input = typeof parsed.input === "string"
8
+ ? parsed.input
9
+ : parsed.input &&
10
+ typeof parsed.input === "object" &&
11
+ Object.keys(parsed.input).length > 0
12
+ ? JSON.stringify(parsed.input)
13
+ : "";
14
+ return {
15
+ type: "toolUse",
16
+ data: {
17
+ name: parsed.name,
18
+ toolUseId: parsed.toolUseId,
19
+ input,
20
+ stop: parsed.stop,
21
+ },
22
+ };
23
+ }
24
+ if (parsed.input !== undefined && !parsed.name) {
25
+ return {
26
+ type: "toolUseInput",
27
+ data: {
28
+ input: typeof parsed.input === "string"
29
+ ? parsed.input
30
+ : JSON.stringify(parsed.input),
31
+ },
32
+ };
33
+ }
34
+ if (parsed.stop !== undefined && parsed.contextUsagePercentage === undefined)
35
+ return { type: "toolUseStop", data: { stop: parsed.stop } };
36
+ if (parsed.contextUsagePercentage !== undefined)
37
+ return {
38
+ type: "contextUsage",
39
+ data: { contextUsagePercentage: parsed.contextUsagePercentage },
40
+ };
41
+ if (parsed.followupPrompt !== undefined)
42
+ return { type: "followupPrompt", data: parsed.followupPrompt };
43
+ if (parsed.error !== undefined || parsed.Error !== undefined) {
44
+ const error = (parsed.error || parsed.Error || "unknown");
45
+ const message = (parsed.message || parsed.Message || parsed.reason);
46
+ return {
47
+ type: "error",
48
+ data: {
49
+ error: typeof error === "string" ? error : JSON.stringify(error),
50
+ message,
51
+ },
52
+ };
53
+ }
54
+ if (parsed.usage !== undefined) {
55
+ const u = parsed.usage;
56
+ return {
57
+ type: "usage",
58
+ data: {
59
+ inputTokens: u.inputTokens,
60
+ outputTokens: u.outputTokens,
61
+ },
62
+ };
63
+ }
64
+ return null;
65
+ }
66
+ //# 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,13 @@
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
+ /** Remove images from history entries — they've already been processed by the
6
+ * model in previous turns and re-sending them wastes context / causes 413s. */
7
+ export declare function stripHistoryImages(history: KiroHistoryEntry[]): KiroHistoryEntry[];
8
+ export declare function sanitizeHistory(history: KiroHistoryEntry[]): KiroHistoryEntry[];
9
+ export declare function injectSyntheticToolCalls(history: KiroHistoryEntry[]): KiroHistoryEntry[];
10
+ export declare function truncateHistory(history: KiroHistoryEntry[], limit: number): KiroHistoryEntry[];
11
+ export declare function extractToolNamesFromHistory(history: KiroHistoryEntry[]): Set<string>;
12
+ export declare function addPlaceholderTools(tools: KiroToolSpec[], history: KiroHistoryEntry[]): KiroToolSpec[];
13
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAErE,eAAO,MAAM,aAAa,SAAS,CAAC;AACpC,iFAAiF;AACjF,eAAO,MAAM,4BAA4B,SAAS,CAAC;AAEnD;gFACgF;AAChF,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,gBAAgB,EAAE,GACzB,gBAAgB,EAAE,CAMpB;AAED,wBAAgB,eAAe,CAC9B,OAAO,EAAE,gBAAgB,EAAE,GACzB,gBAAgB,EAAE,CAgCpB;AAED,wBAAgB,wBAAwB,CACvC,OAAO,EAAE,gBAAgB,EAAE,GACzB,gBAAgB,EAAE,CA8BpB;AAED,wBAAgB,eAAe,CAC9B,OAAO,EAAE,gBAAgB,EAAE,EAC3B,KAAK,EAAE,MAAM,GACX,gBAAgB,EAAE,CAWpB;AAED,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,gBAAgB,EAAE,GACzB,GAAG,CAAC,MAAM,CAAC,CAQb;AAED,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,YAAY,EAAE,EACrB,OAAO,EAAE,gBAAgB,EAAE,GACzB,YAAY,EAAE,CAkBhB"}
@@ -0,0 +1,121 @@
1
+ // Feature 6: History Management
2
+ export const HISTORY_LIMIT = 850000;
3
+ /** The context window size (in tokens) that HISTORY_LIMIT was calibrated for. */
4
+ export const HISTORY_LIMIT_CONTEXT_WINDOW = 200000;
5
+ /** Remove images from history entries — they've already been processed by the
6
+ * model in previous turns and re-sending them wastes context / causes 413s. */
7
+ export function stripHistoryImages(history) {
8
+ return history.map((entry) => {
9
+ if (!entry.userInputMessage?.images)
10
+ return entry;
11
+ const { images, ...rest } = entry.userInputMessage;
12
+ return { ...entry, userInputMessage: { ...rest } };
13
+ });
14
+ }
15
+ export function sanitizeHistory(history) {
16
+ // Strip leading entries that would make the history invalid
17
+ while (history.length > 0 &&
18
+ (!history[0]?.userInputMessage ||
19
+ history[0].userInputMessage.userInputMessageContext?.toolResults))
20
+ history = history.slice(1);
21
+ const result = [];
22
+ for (let i = 0; i < history.length; i++) {
23
+ const m = history[i];
24
+ if (!m)
25
+ continue;
26
+ // Skip assistant messages with no content and no tool uses (e.g. from API errors)
27
+ if (m.assistantResponseMessage &&
28
+ !m.assistantResponseMessage.toolUses &&
29
+ !m.assistantResponseMessage.content)
30
+ continue;
31
+ if (m.assistantResponseMessage?.toolUses) {
32
+ const next = history[i + 1];
33
+ if (next?.userInputMessage?.userInputMessageContext?.toolResults)
34
+ result.push(m);
35
+ }
36
+ else if (m.userInputMessage?.userInputMessageContext?.toolResults) {
37
+ const prev = result[result.length - 1];
38
+ if (prev?.assistantResponseMessage?.toolUses)
39
+ result.push(m);
40
+ }
41
+ else {
42
+ result.push(m);
43
+ }
44
+ }
45
+ // Leading invalid entries already stripped above
46
+ return result;
47
+ }
48
+ export function injectSyntheticToolCalls(history) {
49
+ const validIds = new Set();
50
+ for (const entry of history) {
51
+ for (const tu of entry.assistantResponseMessage?.toolUses ?? []) {
52
+ if (tu.toolUseId)
53
+ validIds.add(tu.toolUseId);
54
+ }
55
+ }
56
+ const result = [];
57
+ for (const entry of history) {
58
+ const toolResults = entry.userInputMessage?.userInputMessageContext?.toolResults;
59
+ if (toolResults) {
60
+ const orphaned = toolResults.filter((tr) => !validIds.has(tr.toolUseId));
61
+ if (orphaned.length > 0) {
62
+ result.push({
63
+ assistantResponseMessage: {
64
+ content: "Tool calls were made.",
65
+ toolUses: orphaned.map((tr) => ({
66
+ name: "unknown_tool",
67
+ toolUseId: tr.toolUseId,
68
+ input: {},
69
+ })),
70
+ },
71
+ });
72
+ for (const tr of orphaned)
73
+ validIds.add(tr.toolUseId);
74
+ }
75
+ }
76
+ result.push(entry);
77
+ }
78
+ return result;
79
+ }
80
+ export function truncateHistory(history, limit) {
81
+ let sanitized = sanitizeHistory(stripHistoryImages(history));
82
+ let historySize = JSON.stringify(sanitized).length;
83
+ while (historySize > limit && sanitized.length > 2) {
84
+ sanitized.shift();
85
+ while (sanitized.length > 0 && !sanitized[0]?.userInputMessage)
86
+ sanitized.shift();
87
+ sanitized = sanitizeHistory(sanitized);
88
+ historySize = JSON.stringify(sanitized).length;
89
+ }
90
+ return injectSyntheticToolCalls(sanitized);
91
+ }
92
+ export function extractToolNamesFromHistory(history) {
93
+ const names = new Set();
94
+ for (const entry of history) {
95
+ for (const tu of entry.assistantResponseMessage?.toolUses ?? []) {
96
+ if (tu.name)
97
+ names.add(tu.name);
98
+ }
99
+ }
100
+ return names;
101
+ }
102
+ export function addPlaceholderTools(tools, history) {
103
+ const historyNames = extractToolNamesFromHistory(history);
104
+ if (historyNames.size === 0)
105
+ return tools;
106
+ const existing = new Set(tools.map((t) => t.toolSpecification?.name).filter(Boolean));
107
+ const missing = Array.from(historyNames).filter((n) => !existing.has(n));
108
+ if (missing.length === 0)
109
+ return tools;
110
+ return [
111
+ ...tools,
112
+ ...missing.map((name) => ({
113
+ toolSpecification: {
114
+ name,
115
+ description: "Tool",
116
+ inputSchema: { json: { type: "object", properties: {} } },
117
+ },
118
+ })),
119
+ ];
120
+ }
121
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export type { KiroStreamEvent } from "./event-parser.js";
3
+ export { KIRO_MODEL_IDS, kiroModels, resolveApiRegion, resolveKiroModel, } from "./models.js";
4
+ export { streamKiro } from "./stream.js";
5
+ export default function (pi: ExtensionAPI): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AASpE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EACN,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAgCxC"}
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ // Feature 1: Extension Registration
2
+ //
3
+ // Entry point that wires all features together via pi.registerProvider().
4
+ import { getKiroCliCredentials } from "./kiro-cli.js";
5
+ import { setExtensionContext } from "./login-ui.js";
6
+ import { getCachedModels, kiroModels, resolveApiRegion } from "./models.js";
7
+ import { loginKiro, refreshKiroToken } from "./oauth.js";
8
+ import { streamKiro } from "./stream.js";
9
+ import { fetchKiroUsage } from "./usage.js";
10
+ export { KIRO_MODEL_IDS, kiroModels, resolveApiRegion, resolveKiroModel, } from "./models.js";
11
+ export { streamKiro } from "./stream.js";
12
+ export default function (pi) {
13
+ // Capture ctx for the custom TUI login component
14
+ pi.on("session_start", async (_event, ctx) => {
15
+ setExtensionContext(ctx);
16
+ });
17
+ pi.registerProvider("kiro", {
18
+ baseUrl: "https://q.us-east-1.amazonaws.com/generateAssistantResponse",
19
+ api: "kiro-api",
20
+ models: kiroModels,
21
+ oauth: {
22
+ // Name reflects all supported auth methods: AWS Builder ID, Google, GitHub
23
+ name: "Kiro (Builder ID / Google / GitHub)",
24
+ login: loginKiro,
25
+ refreshToken: refreshKiroToken,
26
+ getApiKey: (cred) => cred.access,
27
+ getCliCredentials: getKiroCliCredentials,
28
+ modifyModels: (models, cred) => {
29
+ const apiRegion = resolveApiRegion(cred.region);
30
+ const cachedKiro = getCachedModels(apiRegion);
31
+ const nonKiro = models.filter((m) => m.provider !== "kiro");
32
+ const modifiedKiro = cachedKiro.map((m) => ({
33
+ ...m,
34
+ baseUrl: `https://q.${apiRegion}.amazonaws.com/generateAssistantResponse`,
35
+ }));
36
+ return [...nonKiro, ...modifiedKiro];
37
+ },
38
+ fetchUsage: fetchKiroUsage,
39
+ // biome-ignore lint/suspicious/noExplicitAny: ProviderConfig.oauth doesn't include getCliCredentials but OAuthProviderInterface does
40
+ },
41
+ streamSimple: streamKiro,
42
+ });
43
+ }
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,0EAA0E;AAI1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EACN,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,OAAO,WAAW,EAAgB;IACxC,iDAAiD;IACjD,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC5C,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE;QAC3B,OAAO,EAAE,6DAA6D;QACtE,GAAG,EAAE,UAAU;QACf,MAAM,EAAE,UAAU;QAClB,KAAK,EAAE;YACN,2EAA2E;YAC3E,IAAI,EAAE,qCAAqC;YAC3C,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,gBAAgB;YAC9B,SAAS,EAAE,CAAC,IAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM;YAClD,iBAAiB,EAAE,qBAAqB;YACxC,YAAY,EAAE,CAAC,MAAoB,EAAE,IAAsB,EAAE,EAAE;gBAC9D,MAAM,SAAS,GAAG,gBAAgB,CAAE,IAAwB,CAAC,MAAM,CAAC,CAAC;gBACrE,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;gBACxE,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC;oBACvD,GAAG,CAAC;oBACJ,OAAO,EAAE,aAAa,SAAS,0CAA0C;iBACzE,CAAC,CAAC,CAAC;gBAEJ,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,YAAY,CAAC,CAAC;YACtC,CAAC;YACD,UAAU,EAAE,cAAc;YAC1B,qIAAqI;SAC9H;QACR,YAAY,EAAE,UAAU;KACxB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { KiroAuthMethod, KiroCredentials } from "./oauth.js";
2
+ export declare function getKiroCliDbPath(): string | undefined;
3
+ export declare function getKiroCliCredentials(): KiroCredentials | undefined;
4
+ /**
5
+ * Like getKiroCliCredentials but returns credentials even when the access token
6
+ * is expired, as long as a refresh token exists. Used to attempt a token refresh
7
+ * before falling back to the full device code login flow.
8
+ */
9
+ export declare function getKiroCliCredentialsAllowExpired(): KiroCredentials | undefined;
10
+ declare function tryKiroCliToken(dbPath: string, tokenKey: string, authMethod: KiroAuthMethod, allowExpired?: boolean): KiroCredentials | undefined;
11
+ export { tryKiroCliToken };
12
+ /**
13
+ * Get the social token (Google/GitHub) from kiro-cli if available.
14
+ * Returns undefined if no valid social token exists.
15
+ * This is used to prefer social login when the user has logged in that way.
16
+ */
17
+ export declare function getKiroCliSocialToken(): KiroCredentials | undefined;
18
+ /**
19
+ * Like getKiroCliSocialToken but returns credentials even when the access token
20
+ * is expired, as long as a refresh token exists.
21
+ */
22
+ export declare function getKiroCliSocialTokenAllowExpired(): KiroCredentials | undefined;
23
+ export declare function saveKiroCliCredentials(creds: KiroCredentials): void;
24
+ /**
25
+ * Ask kiro-cli to refresh its own tokens via `kiro-cli debug refresh-auth-token`,
26
+ * then re-read the SQLite DB for fresh credentials.
27
+ *
28
+ * Returns refreshed credentials on success, or undefined if kiro-cli is not
29
+ * installed, the command fails, or the DB still has no valid tokens afterward.
30
+ */
31
+ export declare function refreshViaKiroCli(): KiroCredentials | undefined;
32
+ //# sourceMappingURL=kiro-cli.d.ts.map