@zhafron/opencode-kiro-auth 1.0.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 (110) hide show
  1. package/README.md +85 -0
  2. package/dist/constants.d.ts +26 -0
  3. package/dist/constants.js +60 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.js +1 -0
  6. package/dist/kiro/auth.d.ts +5 -0
  7. package/dist/kiro/auth.js +24 -0
  8. package/dist/kiro/oauth-idc.d.ts +24 -0
  9. package/dist/kiro/oauth-idc.js +132 -0
  10. package/dist/kiro/oauth-social.d.ts +17 -0
  11. package/dist/kiro/oauth-social.js +51 -0
  12. package/dist/plugin/accounts.d.ts +28 -0
  13. package/dist/plugin/accounts.js +156 -0
  14. package/dist/plugin/auth-page.d.ts +3 -0
  15. package/dist/plugin/auth-page.js +568 -0
  16. package/dist/plugin/cli.d.ts +6 -0
  17. package/dist/plugin/cli.js +98 -0
  18. package/dist/plugin/config/index.d.ts +3 -0
  19. package/dist/plugin/config/index.js +2 -0
  20. package/dist/plugin/config/loader.d.ts +6 -0
  21. package/dist/plugin/config/loader.js +125 -0
  22. package/dist/plugin/config/schema.d.ts +44 -0
  23. package/dist/plugin/config/schema.js +28 -0
  24. package/dist/plugin/debug.d.ts +2 -0
  25. package/dist/plugin/debug.js +9 -0
  26. package/dist/plugin/errors.d.ts +17 -0
  27. package/dist/plugin/errors.js +34 -0
  28. package/dist/plugin/logger.d.ts +4 -0
  29. package/dist/plugin/logger.js +37 -0
  30. package/dist/plugin/models.d.ts +3 -0
  31. package/dist/plugin/models.js +14 -0
  32. package/dist/plugin/oauth-parser.d.ts +5 -0
  33. package/dist/plugin/oauth-parser.js +23 -0
  34. package/dist/plugin/quota.d.ts +15 -0
  35. package/dist/plugin/quota.js +68 -0
  36. package/dist/plugin/recovery.d.ts +19 -0
  37. package/dist/plugin/recovery.js +302 -0
  38. package/dist/plugin/refresh-queue.d.ts +14 -0
  39. package/dist/plugin/refresh-queue.js +69 -0
  40. package/dist/plugin/request.d.ts +4 -0
  41. package/dist/plugin/request.js +240 -0
  42. package/dist/plugin/response.d.ts +6 -0
  43. package/dist/plugin/response.js +246 -0
  44. package/dist/plugin/server.d.ts +24 -0
  45. package/dist/plugin/server.js +96 -0
  46. package/dist/plugin/storage.d.ts +7 -0
  47. package/dist/plugin/storage.js +75 -0
  48. package/dist/plugin/streaming.d.ts +3 -0
  49. package/dist/plugin/streaming.js +503 -0
  50. package/dist/plugin/token.d.ts +2 -0
  51. package/dist/plugin/token.js +56 -0
  52. package/dist/plugin/types.d.ts +148 -0
  53. package/dist/plugin/types.js +0 -0
  54. package/dist/plugin/usage.d.ts +3 -0
  55. package/dist/plugin/usage.js +36 -0
  56. package/dist/plugin.d.ts +32 -0
  57. package/dist/plugin.js +222 -0
  58. package/dist/src/constants.d.ts +22 -0
  59. package/dist/src/constants.js +35 -0
  60. package/dist/src/kiro/auth.d.ts +5 -0
  61. package/dist/src/kiro/auth.js +69 -0
  62. package/dist/src/kiro/oauth-idc.d.ts +22 -0
  63. package/dist/src/kiro/oauth-idc.js +99 -0
  64. package/dist/src/kiro/oauth-social.d.ts +17 -0
  65. package/dist/src/kiro/oauth-social.js +69 -0
  66. package/dist/src/plugin/accounts.d.ts +23 -0
  67. package/dist/src/plugin/accounts.js +265 -0
  68. package/dist/src/plugin/cli.d.ts +6 -0
  69. package/dist/src/plugin/cli.js +98 -0
  70. package/dist/src/plugin/config/index.d.ts +3 -0
  71. package/dist/src/plugin/config/index.js +2 -0
  72. package/dist/src/plugin/config/loader.d.ts +7 -0
  73. package/dist/src/plugin/config/loader.js +143 -0
  74. package/dist/src/plugin/config/schema.d.ts +68 -0
  75. package/dist/src/plugin/config/schema.js +44 -0
  76. package/dist/src/plugin/debug.d.ts +2 -0
  77. package/dist/src/plugin/debug.js +9 -0
  78. package/dist/src/plugin/errors.d.ts +17 -0
  79. package/dist/src/plugin/errors.js +34 -0
  80. package/dist/src/plugin/logger.d.ts +4 -0
  81. package/dist/src/plugin/logger.js +17 -0
  82. package/dist/src/plugin/models.d.ts +3 -0
  83. package/dist/src/plugin/models.js +14 -0
  84. package/dist/src/plugin/oauth-parser.d.ts +5 -0
  85. package/dist/src/plugin/oauth-parser.js +23 -0
  86. package/dist/src/plugin/quota.d.ts +25 -0
  87. package/dist/src/plugin/quota.js +175 -0
  88. package/dist/src/plugin/recovery.d.ts +19 -0
  89. package/dist/src/plugin/recovery.js +302 -0
  90. package/dist/src/plugin/refresh-queue.d.ts +14 -0
  91. package/dist/src/plugin/refresh-queue.js +69 -0
  92. package/dist/src/plugin/request.d.ts +35 -0
  93. package/dist/src/plugin/request.js +411 -0
  94. package/dist/src/plugin/response.d.ts +6 -0
  95. package/dist/src/plugin/response.js +246 -0
  96. package/dist/src/plugin/server.d.ts +10 -0
  97. package/dist/src/plugin/server.js +203 -0
  98. package/dist/src/plugin/storage.d.ts +5 -0
  99. package/dist/src/plugin/storage.js +106 -0
  100. package/dist/src/plugin/streaming.d.ts +12 -0
  101. package/dist/src/plugin/streaming.js +444 -0
  102. package/dist/src/plugin/token.d.ts +8 -0
  103. package/dist/src/plugin/token.js +130 -0
  104. package/dist/src/plugin/types.d.ts +144 -0
  105. package/dist/src/plugin/types.js +0 -0
  106. package/dist/src/plugin/usage.d.ts +28 -0
  107. package/dist/src/plugin/usage.js +159 -0
  108. package/dist/src/plugin.d.ts +2 -0
  109. package/dist/src/plugin.js +341 -0
  110. package/package.json +57 -0
@@ -0,0 +1,203 @@
1
+ import { createServer } from 'node:http';
2
+ import { parse as parseUrl } from 'node:url';
3
+ import * as logger from './logger';
4
+ const DEFAULT_PORT = 8080;
5
+ const CALLBACK_TIMEOUT = 5 * 60 * 1000;
6
+ function parseQueryParams(url) {
7
+ const params = {};
8
+ try {
9
+ const parsed = parseUrl(url, true);
10
+ const query = parsed.query;
11
+ for (const [key, value] of Object.entries(query)) {
12
+ if (typeof value === 'string') {
13
+ params[key] = value;
14
+ }
15
+ else if (Array.isArray(value) && value.length > 0) {
16
+ params[key] = value[0];
17
+ }
18
+ }
19
+ }
20
+ catch (error) {
21
+ logger.error('Failed to parse query params', error);
22
+ }
23
+ return params;
24
+ }
25
+ function sendHtmlResponse(res, html) {
26
+ res.writeHead(200, {
27
+ 'Content-Type': 'text/html; charset=utf-8',
28
+ 'Content-Length': Buffer.byteLength(html),
29
+ });
30
+ res.end(html);
31
+ }
32
+ function sendErrorResponse(res, statusCode, message) {
33
+ const html = `
34
+ <!DOCTYPE html>
35
+ <html>
36
+ <head>
37
+ <meta charset="utf-8">
38
+ <title>Error</title>
39
+ <style>
40
+ body {
41
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
42
+ display: flex;
43
+ justify-content: center;
44
+ align-items: center;
45
+ height: 100vh;
46
+ margin: 0;
47
+ background: #f5f5f5;
48
+ }
49
+ .container {
50
+ text-align: center;
51
+ padding: 2rem;
52
+ background: white;
53
+ border-radius: 8px;
54
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
55
+ }
56
+ h1 {
57
+ color: #e74c3c;
58
+ margin: 0 0 1rem 0;
59
+ }
60
+ p {
61
+ color: #666;
62
+ margin: 0;
63
+ }
64
+ </style>
65
+ </head>
66
+ <body>
67
+ <div class="container">
68
+ <h1>Error</h1>
69
+ <p>${message}</p>
70
+ </div>
71
+ </body>
72
+ </html>
73
+ `.trim();
74
+ res.writeHead(statusCode, {
75
+ 'Content-Type': 'text/html; charset=utf-8',
76
+ 'Content-Length': Buffer.byteLength(html),
77
+ });
78
+ res.end(html);
79
+ }
80
+ function sendSuccessResponse(res) {
81
+ const html = `
82
+ <!DOCTYPE html>
83
+ <html>
84
+ <head>
85
+ <meta charset="utf-8">
86
+ <title>Authentication Successful</title>
87
+ <style>
88
+ body {
89
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
90
+ display: flex;
91
+ justify-content: center;
92
+ align-items: center;
93
+ height: 100vh;
94
+ margin: 0;
95
+ background: #f5f5f5;
96
+ }
97
+ .container {
98
+ text-align: center;
99
+ padding: 2rem;
100
+ background: white;
101
+ border-radius: 8px;
102
+ box-shadow: 0 2px 8px rgba(0,0,0,0.1);
103
+ }
104
+ h1 {
105
+ color: #27ae60;
106
+ margin: 0 0 1rem 0;
107
+ }
108
+ p {
109
+ color: #666;
110
+ margin: 0;
111
+ }
112
+ </style>
113
+ </head>
114
+ <body>
115
+ <div class="container">
116
+ <h1>Authentication Successful</h1>
117
+ <p>You can close this window and return to the terminal.</p>
118
+ </div>
119
+ </body>
120
+ </html>
121
+ `.trim();
122
+ sendHtmlResponse(res, html);
123
+ }
124
+ export async function startCallbackServer(port = DEFAULT_PORT) {
125
+ return new Promise((resolve, reject) => {
126
+ let server = null;
127
+ let timeoutId = null;
128
+ let callbackResolver = null;
129
+ let callbackRejector = null;
130
+ const cleanup = () => {
131
+ if (timeoutId) {
132
+ clearTimeout(timeoutId);
133
+ timeoutId = null;
134
+ }
135
+ if (server) {
136
+ server.close((err) => {
137
+ if (err) {
138
+ logger.error('Error closing callback server', err);
139
+ }
140
+ });
141
+ server = null;
142
+ }
143
+ };
144
+ const handleRequest = (req, res) => {
145
+ const url = req.url || '';
146
+ if (!url.startsWith('/callback')) {
147
+ sendErrorResponse(res, 404, 'Not Found');
148
+ return;
149
+ }
150
+ const params = parseQueryParams(url);
151
+ const code = params.code;
152
+ const state = params.state;
153
+ if (!code) {
154
+ sendErrorResponse(res, 400, 'Missing authorization code');
155
+ if (callbackRejector) {
156
+ callbackRejector(new Error('Missing authorization code'));
157
+ }
158
+ cleanup();
159
+ return;
160
+ }
161
+ if (!state) {
162
+ sendErrorResponse(res, 400, 'Missing state parameter');
163
+ if (callbackRejector) {
164
+ callbackRejector(new Error('Missing state parameter'));
165
+ }
166
+ cleanup();
167
+ return;
168
+ }
169
+ sendSuccessResponse(res);
170
+ if (callbackResolver) {
171
+ callbackResolver({ code, state });
172
+ }
173
+ cleanup();
174
+ };
175
+ server = createServer(handleRequest);
176
+ server.on('error', (error) => {
177
+ logger.error('Callback server error', error);
178
+ cleanup();
179
+ reject(error);
180
+ });
181
+ server.listen(port, 'localhost', () => {
182
+ const url = `http://localhost:${port}/callback`;
183
+ logger.log('Callback server started', { url });
184
+ timeoutId = setTimeout(() => {
185
+ logger.warn('Callback server timeout');
186
+ if (callbackRejector) {
187
+ callbackRejector(new Error('Callback timeout'));
188
+ }
189
+ cleanup();
190
+ }, CALLBACK_TIMEOUT);
191
+ const waitForCallback = () => {
192
+ return new Promise((resolveCallback, rejectCallback) => {
193
+ callbackResolver = resolveCallback;
194
+ callbackRejector = rejectCallback;
195
+ });
196
+ };
197
+ resolve({
198
+ url,
199
+ waitForCallback,
200
+ });
201
+ });
202
+ });
203
+ }
@@ -0,0 +1,5 @@
1
+ import type { AccountStorage } from './types';
2
+ export declare function getStoragePath(): string;
3
+ export declare function withFileLock<T>(path: string, fn: () => Promise<T>): Promise<T>;
4
+ export declare function loadAccounts(): Promise<AccountStorage>;
5
+ export declare function saveAccounts(storage: AccountStorage): Promise<void>;
@@ -0,0 +1,106 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ import { randomBytes } from 'node:crypto';
4
+ import lockfile from 'proper-lockfile';
5
+ import { xdgConfig } from 'xdg-basedir';
6
+ import * as logger from './logger';
7
+ export function getStoragePath() {
8
+ const configDir = xdgConfig || `${process.env.HOME}/.config`;
9
+ return `${configDir}/opencode/kiro-accounts.json`;
10
+ }
11
+ const LOCK_OPTIONS = {
12
+ stale: 10000,
13
+ retries: {
14
+ retries: 5,
15
+ minTimeout: 100,
16
+ maxTimeout: 1000,
17
+ factor: 2,
18
+ },
19
+ };
20
+ async function ensureFileExists(path) {
21
+ try {
22
+ await fs.access(path);
23
+ }
24
+ catch {
25
+ await fs.mkdir(dirname(path), { recursive: true });
26
+ const defaultStorage = {
27
+ version: 1,
28
+ accounts: [],
29
+ activeIndex: -1,
30
+ };
31
+ await fs.writeFile(path, JSON.stringify(defaultStorage, null, 2), 'utf-8');
32
+ }
33
+ }
34
+ export async function withFileLock(path, fn) {
35
+ await ensureFileExists(path);
36
+ let release = null;
37
+ try {
38
+ release = await lockfile.lock(path, LOCK_OPTIONS);
39
+ return await fn();
40
+ }
41
+ catch (error) {
42
+ logger.error('File lock operation failed', error);
43
+ throw error;
44
+ }
45
+ finally {
46
+ if (release) {
47
+ try {
48
+ await release();
49
+ }
50
+ catch (unlockError) {
51
+ logger.warn('Failed to release lock', unlockError);
52
+ }
53
+ }
54
+ }
55
+ }
56
+ export async function loadAccounts() {
57
+ const path = getStoragePath();
58
+ try {
59
+ await ensureFileExists(path);
60
+ const content = await fs.readFile(path, 'utf-8');
61
+ const data = JSON.parse(content);
62
+ if (data.version !== 1) {
63
+ logger.warn('Unknown storage version, returning default');
64
+ return {
65
+ version: 1,
66
+ accounts: [],
67
+ activeIndex: -1,
68
+ };
69
+ }
70
+ if (!Array.isArray(data.accounts)) {
71
+ logger.warn('Invalid accounts array, returning default');
72
+ return {
73
+ version: 1,
74
+ accounts: [],
75
+ activeIndex: -1,
76
+ };
77
+ }
78
+ return data;
79
+ }
80
+ catch (error) {
81
+ const code = error.code;
82
+ if (code === 'ENOENT') {
83
+ return {
84
+ version: 1,
85
+ accounts: [],
86
+ activeIndex: -1,
87
+ };
88
+ }
89
+ logger.error('Failed to load accounts', error);
90
+ return {
91
+ version: 1,
92
+ accounts: [],
93
+ activeIndex: -1,
94
+ };
95
+ }
96
+ }
97
+ export async function saveAccounts(storage) {
98
+ const path = getStoragePath();
99
+ await withFileLock(path, async () => {
100
+ const tempPath = `${path}.${randomBytes(6).toString('hex')}.tmp`;
101
+ const content = JSON.stringify(storage, null, 2);
102
+ await fs.mkdir(dirname(path), { recursive: true });
103
+ await fs.writeFile(tempPath, content, 'utf-8');
104
+ await fs.rename(tempPath, path);
105
+ });
106
+ }
@@ -0,0 +1,12 @@
1
+ interface StreamEvent {
2
+ type: string;
3
+ message?: any;
4
+ content_block?: any;
5
+ delta?: any;
6
+ index?: number;
7
+ usage?: any;
8
+ }
9
+ export declare function transformKiroStream(response: Response, model: string, conversationId: string): AsyncGenerator<StreamEvent>;
10
+ export declare function findRealTag(buffer: string, tag: string): number;
11
+ export declare function estimateTokens(text: string): number;
12
+ export {};