@kervnet/opencode-kiro-auth 1.5.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.
- package/README.md +159 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.js +55 -0
- package/dist/core/account/account-selector.d.ts +25 -0
- package/dist/core/account/account-selector.js +84 -0
- package/dist/core/account/usage-tracker.d.ts +17 -0
- package/dist/core/account/usage-tracker.js +39 -0
- package/dist/core/auth/auth-handler.d.ts +15 -0
- package/dist/core/auth/auth-handler.js +43 -0
- package/dist/core/auth/idc-auth-method.d.ts +17 -0
- package/dist/core/auth/idc-auth-method.js +200 -0
- package/dist/core/auth/token-refresher.d.ts +22 -0
- package/dist/core/auth/token-refresher.js +53 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +9 -0
- package/dist/core/request/error-handler.d.ts +30 -0
- package/dist/core/request/error-handler.js +113 -0
- package/dist/core/request/request-handler.d.ts +27 -0
- package/dist/core/request/request-handler.js +199 -0
- package/dist/core/request/response-handler.d.ts +5 -0
- package/dist/core/request/response-handler.js +61 -0
- package/dist/core/request/retry-strategy.d.ts +18 -0
- package/dist/core/request/retry-strategy.js +28 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/infrastructure/database/account-cache.d.ts +14 -0
- package/dist/infrastructure/database/account-cache.js +44 -0
- package/dist/infrastructure/database/account-repository.d.ts +12 -0
- package/dist/infrastructure/database/account-repository.js +64 -0
- package/dist/infrastructure/index.d.ts +7 -0
- package/dist/infrastructure/index.js +7 -0
- package/dist/infrastructure/transformers/event-stream-parser.d.ts +7 -0
- package/dist/infrastructure/transformers/event-stream-parser.js +115 -0
- package/dist/infrastructure/transformers/history-builder.d.ts +5 -0
- package/dist/infrastructure/transformers/history-builder.js +171 -0
- package/dist/infrastructure/transformers/message-transformer.d.ts +6 -0
- package/dist/infrastructure/transformers/message-transformer.js +102 -0
- package/dist/infrastructure/transformers/tool-call-parser.d.ts +4 -0
- package/dist/infrastructure/transformers/tool-call-parser.js +45 -0
- package/dist/infrastructure/transformers/tool-transformer.d.ts +2 -0
- package/dist/infrastructure/transformers/tool-transformer.js +19 -0
- package/dist/kiro/auth.d.ts +4 -0
- package/dist/kiro/auth.js +25 -0
- package/dist/kiro/oauth-idc.d.ts +24 -0
- package/dist/kiro/oauth-idc.js +151 -0
- package/dist/plugin/accounts.d.ts +29 -0
- package/dist/plugin/accounts.js +235 -0
- package/dist/plugin/auth-page.d.ts +3 -0
- package/dist/plugin/auth-page.js +573 -0
- package/dist/plugin/cli.d.ts +8 -0
- package/dist/plugin/cli.js +103 -0
- package/dist/plugin/config/index.d.ts +3 -0
- package/dist/plugin/config/index.js +2 -0
- package/dist/plugin/config/loader.d.ts +6 -0
- package/dist/plugin/config/loader.js +129 -0
- package/dist/plugin/config/schema.d.ts +56 -0
- package/dist/plugin/config/schema.js +36 -0
- package/dist/plugin/errors.d.ts +17 -0
- package/dist/plugin/errors.js +34 -0
- package/dist/plugin/health.d.ts +1 -0
- package/dist/plugin/health.js +9 -0
- package/dist/plugin/image-handler.d.ts +14 -0
- package/dist/plugin/image-handler.js +64 -0
- package/dist/plugin/logger.d.ts +8 -0
- package/dist/plugin/logger.js +63 -0
- package/dist/plugin/models.d.ts +1 -0
- package/dist/plugin/models.js +8 -0
- package/dist/plugin/request.d.ts +2 -0
- package/dist/plugin/request.js +239 -0
- package/dist/plugin/response.d.ts +3 -0
- package/dist/plugin/response.js +95 -0
- package/dist/plugin/server.d.ts +24 -0
- package/dist/plugin/server.js +166 -0
- package/dist/plugin/storage/locked-operations.d.ts +5 -0
- package/dist/plugin/storage/locked-operations.js +91 -0
- package/dist/plugin/storage/migrations.d.ts +2 -0
- package/dist/plugin/storage/migrations.js +109 -0
- package/dist/plugin/storage/sqlite.d.ts +17 -0
- package/dist/plugin/storage/sqlite.js +134 -0
- package/dist/plugin/streaming/index.d.ts +2 -0
- package/dist/plugin/streaming/index.js +2 -0
- package/dist/plugin/streaming/openai-converter.d.ts +2 -0
- package/dist/plugin/streaming/openai-converter.js +68 -0
- package/dist/plugin/streaming/stream-parser.d.ts +5 -0
- package/dist/plugin/streaming/stream-parser.js +136 -0
- package/dist/plugin/streaming/stream-state.d.ts +5 -0
- package/dist/plugin/streaming/stream-state.js +59 -0
- package/dist/plugin/streaming/stream-transformer.d.ts +1 -0
- package/dist/plugin/streaming/stream-transformer.js +248 -0
- package/dist/plugin/streaming/types.d.ts +25 -0
- package/dist/plugin/streaming/types.js +2 -0
- package/dist/plugin/sync/aws-sso.d.ts +2 -0
- package/dist/plugin/sync/aws-sso.js +50 -0
- package/dist/plugin/sync/kiro-cli-parser.d.ts +8 -0
- package/dist/plugin/sync/kiro-cli-parser.js +72 -0
- package/dist/plugin/sync/kiro-cli.d.ts +2 -0
- package/dist/plugin/sync/kiro-cli.js +197 -0
- package/dist/plugin/token.d.ts +2 -0
- package/dist/plugin/token.js +79 -0
- package/dist/plugin/types.d.ts +109 -0
- package/dist/plugin/types.js +0 -0
- package/dist/plugin/usage.d.ts +3 -0
- package/dist/plugin/usage.js +45 -0
- package/dist/plugin.d.ts +32 -0
- package/dist/plugin.js +37 -0
- package/package.json +65 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { decodeRefreshToken, encodeRefreshToken } from '../kiro/auth';
|
|
3
|
+
import { KiroTokenRefreshError } from './errors';
|
|
4
|
+
export async function refreshAccessToken(auth) {
|
|
5
|
+
const p = decodeRefreshToken(auth.refresh);
|
|
6
|
+
const isIdc = auth.authMethod === 'idc';
|
|
7
|
+
const isAwsSso = auth.authMethod === 'aws-sso';
|
|
8
|
+
const url = isIdc || isAwsSso
|
|
9
|
+
? `https://oidc.${auth.region}.amazonaws.com/token`
|
|
10
|
+
: `https://prod.${auth.region}.auth.desktop.kiro.dev/refreshToken`;
|
|
11
|
+
if ((isIdc || isAwsSso) && (!p.clientId || !p.clientSecret)) {
|
|
12
|
+
throw new KiroTokenRefreshError('Missing creds', 'MISSING_CREDENTIALS');
|
|
13
|
+
}
|
|
14
|
+
const requestBody = isIdc || isAwsSso
|
|
15
|
+
? {
|
|
16
|
+
refreshToken: p.refreshToken,
|
|
17
|
+
clientId: p.clientId,
|
|
18
|
+
clientSecret: p.clientSecret,
|
|
19
|
+
grantType: 'refresh_token'
|
|
20
|
+
}
|
|
21
|
+
: {
|
|
22
|
+
refreshToken: p.refreshToken
|
|
23
|
+
};
|
|
24
|
+
const machineId = crypto
|
|
25
|
+
.createHash('sha256')
|
|
26
|
+
.update(auth.profileArn || auth.clientId || 'KIRO_DEFAULT_MACHINE')
|
|
27
|
+
.digest('hex');
|
|
28
|
+
const ua = isIdc || isAwsSso ? 'aws-sdk-js/1.0.0' : `KiroIDE-0.7.45-${machineId}`;
|
|
29
|
+
try {
|
|
30
|
+
const res = await fetch(url, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
Accept: 'application/json',
|
|
35
|
+
'amz-sdk-request': 'attempt=1; max=1',
|
|
36
|
+
'x-amzn-kiro-agent-mode': 'vibe',
|
|
37
|
+
'user-agent': ua,
|
|
38
|
+
Connection: 'close'
|
|
39
|
+
},
|
|
40
|
+
body: JSON.stringify(requestBody)
|
|
41
|
+
});
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
const txt = await res.text();
|
|
44
|
+
let data = {};
|
|
45
|
+
try {
|
|
46
|
+
data = JSON.parse(txt);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
data = { message: txt };
|
|
50
|
+
}
|
|
51
|
+
throw new KiroTokenRefreshError(`Refresh failed: ${data.message || data.error_description || txt}`, data.error || `HTTP_${res.status}`);
|
|
52
|
+
}
|
|
53
|
+
const d = await res.json();
|
|
54
|
+
const acc = d.access_token || d.accessToken;
|
|
55
|
+
if (!acc)
|
|
56
|
+
throw new KiroTokenRefreshError('No access token', 'INVALID_RESPONSE');
|
|
57
|
+
const upP = {
|
|
58
|
+
refreshToken: d.refresh_token || d.refreshToken || p.refreshToken,
|
|
59
|
+
clientId: p.clientId,
|
|
60
|
+
clientSecret: p.clientSecret,
|
|
61
|
+
authMethod: auth.authMethod
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
refresh: encodeRefreshToken(upP),
|
|
65
|
+
access: acc,
|
|
66
|
+
expires: Date.now() + (d.expires_in || d.expiresIn || 3600) * 1000,
|
|
67
|
+
authMethod: auth.authMethod,
|
|
68
|
+
region: auth.region,
|
|
69
|
+
clientId: auth.clientId,
|
|
70
|
+
clientSecret: auth.clientSecret,
|
|
71
|
+
email: auth.email || d.userInfo?.email
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error instanceof KiroTokenRefreshError)
|
|
76
|
+
throw error;
|
|
77
|
+
throw new KiroTokenRefreshError(`Token refresh failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'NETWORK_ERROR', error instanceof Error ? error : undefined);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export type KiroAuthMethod = 'idc' | 'desktop' | 'aws-sso';
|
|
2
|
+
export type KiroRegion = 'us-east-1' | 'us-west-2';
|
|
3
|
+
export interface KiroAuthDetails {
|
|
4
|
+
refresh: string;
|
|
5
|
+
access: string;
|
|
6
|
+
expires: number;
|
|
7
|
+
authMethod: KiroAuthMethod;
|
|
8
|
+
region: KiroRegion;
|
|
9
|
+
clientId?: string;
|
|
10
|
+
clientSecret?: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
profileArn?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RefreshParts {
|
|
15
|
+
refreshToken: string;
|
|
16
|
+
clientId?: string;
|
|
17
|
+
clientSecret?: string;
|
|
18
|
+
profileArn?: string;
|
|
19
|
+
authMethod?: KiroAuthMethod;
|
|
20
|
+
}
|
|
21
|
+
export interface ManagedAccount {
|
|
22
|
+
id: string;
|
|
23
|
+
email: string;
|
|
24
|
+
authMethod: KiroAuthMethod;
|
|
25
|
+
region: KiroRegion;
|
|
26
|
+
clientId?: string;
|
|
27
|
+
clientSecret?: string;
|
|
28
|
+
profileArn?: string;
|
|
29
|
+
refreshToken: string;
|
|
30
|
+
accessToken: string;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
rateLimitResetTime: number;
|
|
33
|
+
isHealthy: boolean;
|
|
34
|
+
unhealthyReason?: string;
|
|
35
|
+
recoveryTime?: number;
|
|
36
|
+
failCount: number;
|
|
37
|
+
usedCount?: number;
|
|
38
|
+
limitCount?: number;
|
|
39
|
+
lastSync?: number;
|
|
40
|
+
lastUsed?: number;
|
|
41
|
+
}
|
|
42
|
+
export interface CodeWhispererMessage {
|
|
43
|
+
userInputMessage?: {
|
|
44
|
+
content: string;
|
|
45
|
+
modelId: string;
|
|
46
|
+
origin: string;
|
|
47
|
+
images?: Array<{
|
|
48
|
+
format: string;
|
|
49
|
+
source: {
|
|
50
|
+
bytes: string;
|
|
51
|
+
};
|
|
52
|
+
}>;
|
|
53
|
+
userInputMessageContext?: {
|
|
54
|
+
toolResults?: Array<{
|
|
55
|
+
toolUseId: string;
|
|
56
|
+
content: Array<{
|
|
57
|
+
text?: string;
|
|
58
|
+
}>;
|
|
59
|
+
status?: string;
|
|
60
|
+
}>;
|
|
61
|
+
tools?: Array<{
|
|
62
|
+
toolSpecification: {
|
|
63
|
+
name: string;
|
|
64
|
+
description: string;
|
|
65
|
+
inputSchema: {
|
|
66
|
+
json: Record<string, unknown>;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
}>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
assistantResponseMessage?: {
|
|
73
|
+
content: string;
|
|
74
|
+
toolUses?: Array<{
|
|
75
|
+
input: any;
|
|
76
|
+
name: string;
|
|
77
|
+
toolUseId: string;
|
|
78
|
+
}>;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export interface CodeWhispererRequest {
|
|
82
|
+
conversationState: {
|
|
83
|
+
chatTriggerType: string;
|
|
84
|
+
conversationId: string;
|
|
85
|
+
history?: CodeWhispererMessage[];
|
|
86
|
+
currentMessage: CodeWhispererMessage;
|
|
87
|
+
};
|
|
88
|
+
profileArn?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface ToolCall {
|
|
91
|
+
toolUseId: string;
|
|
92
|
+
name: string;
|
|
93
|
+
input: string | Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
export interface ParsedResponse {
|
|
96
|
+
content: string;
|
|
97
|
+
toolCalls: ToolCall[];
|
|
98
|
+
stopReason?: string;
|
|
99
|
+
inputTokens?: number;
|
|
100
|
+
outputTokens?: number;
|
|
101
|
+
}
|
|
102
|
+
export interface PreparedRequest {
|
|
103
|
+
url: string;
|
|
104
|
+
init: RequestInit;
|
|
105
|
+
streaming: boolean;
|
|
106
|
+
effectiveModel: string;
|
|
107
|
+
conversationId: string;
|
|
108
|
+
}
|
|
109
|
+
export type AccountSelectionStrategy = 'sticky' | 'round-robin' | 'lowest-usage';
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export async function fetchUsageLimits(auth) {
|
|
2
|
+
const url = `https://q.${auth.region}.amazonaws.com/getUsageLimits?isEmailRequired=true&origin=AI_EDITOR&resourceType=AGENTIC_REQUEST`;
|
|
3
|
+
try {
|
|
4
|
+
const res = await fetch(url, {
|
|
5
|
+
method: 'GET',
|
|
6
|
+
headers: {
|
|
7
|
+
Authorization: `Bearer ${auth.access}`,
|
|
8
|
+
'Content-Type': 'application/json',
|
|
9
|
+
'x-amzn-kiro-agent-mode': 'vibe',
|
|
10
|
+
'amz-sdk-request': 'attempt=1; max=1'
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
if (!res.ok)
|
|
14
|
+
throw new Error(`Status: ${res.status}`);
|
|
15
|
+
const data = await res.json();
|
|
16
|
+
let usedCount = 0, limitCount = 0;
|
|
17
|
+
if (Array.isArray(data.usageBreakdownList)) {
|
|
18
|
+
for (const s of data.usageBreakdownList) {
|
|
19
|
+
if (s.freeTrialInfo) {
|
|
20
|
+
usedCount += s.freeTrialInfo.currentUsage || 0;
|
|
21
|
+
limitCount += s.freeTrialInfo.usageLimit || 0;
|
|
22
|
+
}
|
|
23
|
+
usedCount += s.currentUsage || 0;
|
|
24
|
+
limitCount += s.usageLimit || 0;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return { usedCount, limitCount, email: data.userInfo?.email };
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function updateAccountQuota(account, usage, accountManager) {
|
|
34
|
+
const meta = {
|
|
35
|
+
usedCount: usage.usedCount || 0,
|
|
36
|
+
limitCount: usage.limitCount || 0,
|
|
37
|
+
email: usage.email
|
|
38
|
+
};
|
|
39
|
+
account.usedCount = meta.usedCount;
|
|
40
|
+
account.limitCount = meta.limitCount;
|
|
41
|
+
if (usage.email)
|
|
42
|
+
account.email = usage.email;
|
|
43
|
+
if (accountManager)
|
|
44
|
+
accountManager.updateUsage(account.id, meta);
|
|
45
|
+
}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const createKiroPlugin: (id: string) => ({ client, directory }: any) => Promise<{
|
|
2
|
+
auth: {
|
|
3
|
+
provider: string;
|
|
4
|
+
loader: (getAuth: any) => Promise<{
|
|
5
|
+
apiKey: string;
|
|
6
|
+
baseURL: string;
|
|
7
|
+
fetch: (input: any, init?: any) => Promise<Response>;
|
|
8
|
+
}>;
|
|
9
|
+
methods: {
|
|
10
|
+
id: string;
|
|
11
|
+
label: string;
|
|
12
|
+
type: "oauth";
|
|
13
|
+
authorize: (inputs?: any) => Promise<any>;
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
16
|
+
}>;
|
|
17
|
+
export declare const KiroOAuthPlugin: ({ client, directory }: any) => Promise<{
|
|
18
|
+
auth: {
|
|
19
|
+
provider: string;
|
|
20
|
+
loader: (getAuth: any) => Promise<{
|
|
21
|
+
apiKey: string;
|
|
22
|
+
baseURL: string;
|
|
23
|
+
fetch: (input: any, init?: any) => Promise<Response>;
|
|
24
|
+
}>;
|
|
25
|
+
methods: {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
type: "oauth";
|
|
29
|
+
authorize: (inputs?: any) => Promise<any>;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
}>;
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { KIRO_CONSTANTS } from './constants.js';
|
|
2
|
+
import { AuthHandler } from './core/auth/auth-handler.js';
|
|
3
|
+
import { RequestHandler } from './core/request/request-handler.js';
|
|
4
|
+
import { AccountCache } from './infrastructure/database/account-cache.js';
|
|
5
|
+
import { AccountRepository } from './infrastructure/database/account-repository.js';
|
|
6
|
+
import { AccountManager } from './plugin/accounts.js';
|
|
7
|
+
import { loadConfig } from './plugin/config/index.js';
|
|
8
|
+
const KIRO_PROVIDER_ID = 'kiro';
|
|
9
|
+
export const createKiroPlugin = (id) => async ({ client, directory }) => {
|
|
10
|
+
const config = loadConfig(directory);
|
|
11
|
+
const showToast = (message, variant) => {
|
|
12
|
+
client.tui.showToast({ body: { message, variant } }).catch(() => { });
|
|
13
|
+
};
|
|
14
|
+
const cache = new AccountCache(60000);
|
|
15
|
+
const repository = new AccountRepository(cache);
|
|
16
|
+
const authHandler = new AuthHandler(config, repository);
|
|
17
|
+
const accountManager = await AccountManager.loadFromDisk(config.account_selection_strategy);
|
|
18
|
+
authHandler.setAccountManager(accountManager);
|
|
19
|
+
// Sync AWS SSO before OpenCode checks for accounts
|
|
20
|
+
await authHandler.initialize();
|
|
21
|
+
const requestHandler = new RequestHandler(accountManager, config, repository);
|
|
22
|
+
return {
|
|
23
|
+
auth: {
|
|
24
|
+
provider: id,
|
|
25
|
+
loader: async (getAuth) => {
|
|
26
|
+
await getAuth();
|
|
27
|
+
return {
|
|
28
|
+
apiKey: '',
|
|
29
|
+
baseURL: KIRO_CONSTANTS.BASE_URL.replace('/generateAssistantResponse', '').replace('{{region}}', config.default_region || 'us-east-1'),
|
|
30
|
+
fetch: (input, init) => requestHandler.handle(input, init, showToast)
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
methods: authHandler.getMethods()
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export const KiroOAuthPlugin = createKiroPlugin(KIRO_PROVIDER_ID);
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kervnet/opencode-kiro-auth",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "OpenCode plugin for AWS Kiro (CodeWhisperer) with IAM Identity Center profile support",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.build.json",
|
|
10
|
+
"format": "prettier --write 'src/**/*.ts'",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"prepare": "husky"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"opencode",
|
|
16
|
+
"plugin",
|
|
17
|
+
"kiro",
|
|
18
|
+
"codewhisperer",
|
|
19
|
+
"aws",
|
|
20
|
+
"claude",
|
|
21
|
+
"ai",
|
|
22
|
+
"auth"
|
|
23
|
+
],
|
|
24
|
+
"author": "tickernelz",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/tickernelz/opencode-kiro-auth.git"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@opencode-ai/plugin": "^0.15.30",
|
|
35
|
+
"proper-lockfile": "^4.1.2",
|
|
36
|
+
"zod": "^3.24.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^20.0.0",
|
|
40
|
+
"@types/proper-lockfile": "^4.1.4",
|
|
41
|
+
"bun-types": "^1.3.6",
|
|
42
|
+
"husky": "^9.1.7",
|
|
43
|
+
"lint-staged": "^16.2.7",
|
|
44
|
+
"prettier": "^3.4.2",
|
|
45
|
+
"prettier-plugin-organize-imports": "^4.1.0",
|
|
46
|
+
"typescript": "^5.7.3"
|
|
47
|
+
},
|
|
48
|
+
"opencode": {
|
|
49
|
+
"type": "plugin",
|
|
50
|
+
"hooks": [
|
|
51
|
+
"auth",
|
|
52
|
+
"event"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"package.json",
|
|
58
|
+
"README.md"
|
|
59
|
+
],
|
|
60
|
+
"lint-staged": {
|
|
61
|
+
"*.ts": [
|
|
62
|
+
"prettier --write"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|