opencode-kiro 0.4.0 → 0.5.0-beta.2
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 +200 -161
- package/dist/chunk-M7OUVABX.js +40 -0
- package/dist/credits-box-view-GLFJSV6M.js +37 -0
- package/dist/credits-chip-view-YP4RPX26.js +20 -0
- package/dist/server.d.ts +5 -18
- package/dist/server.js +391 -227
- package/dist/tui.d.ts +3 -50
- package/dist/tui.js +160 -27
- package/package.json +7 -8
- package/dist/chunk-MQVMKLNA.js +0 -70
- package/dist/credits-box-view-BYKGQHSS.js +0 -40
- package/dist/credits-chip-view-RL5JAEZ5.js +0 -20
package/dist/server.js
CHANGED
|
@@ -1,258 +1,422 @@
|
|
|
1
|
-
// src/server.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{ label: "No", value: "no" }
|
|
15
|
-
]
|
|
16
|
-
}
|
|
17
|
-
];
|
|
1
|
+
// src/server/auth.ts
|
|
2
|
+
var KIRO_INTEGRATION_ID = "kiro";
|
|
3
|
+
var KIRO_INTEGRATION_NAME = "Kiro";
|
|
4
|
+
var KIRO_OAUTH_METHOD_ID = "kiro-cli-login";
|
|
5
|
+
var KIRO_OAUTH_METHOD_LABEL = "Kiro CLI Login";
|
|
6
|
+
var KIRO_DOCS_URL = "https://kiro.dev/docs/cli/";
|
|
7
|
+
var POLL_INTERVAL_MS = 2e3;
|
|
8
|
+
var MAX_WAIT_MS = 12e4;
|
|
9
|
+
var NOT_INSTALLED_MESSAGE = "kiro-cli is not installed. Install it from https://kiro.dev/docs/cli/";
|
|
10
|
+
var TIMEOUT_MESSAGE = "Kiro authentication timed out. Run `kiro-cli login` manually, then re-run `opencode auth login`.";
|
|
11
|
+
var LOGIN_INSTRUCTIONS = "Complete Kiro authentication in the browser window that just opened. Waiting for login...";
|
|
12
|
+
var ALREADY_AUTHENTICATED_INSTRUCTIONS = "Already authenticated with Kiro CLI.";
|
|
13
|
+
function createAuthResources() {
|
|
18
14
|
return {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
void notifyIfTokenExpired(input.client);
|
|
24
|
-
return {
|
|
25
|
-
cwd: input.directory ?? input.worktree,
|
|
26
|
-
agent: "opencode",
|
|
27
|
-
trustAllTools: true,
|
|
28
|
-
mcpTimeout: 45,
|
|
29
|
-
contextWindows: Object.fromEntries(
|
|
30
|
-
Object.values(provider?.models ?? {}).filter((m) => m.api?.id && (m.limit?.context ?? 0) > 0).map((m) => [m.api.id, m.limit.context])
|
|
31
|
-
)
|
|
32
|
-
};
|
|
33
|
-
},
|
|
34
|
-
methods: [
|
|
35
|
-
{
|
|
36
|
-
type: "oauth",
|
|
37
|
-
label: "Kiro CLI Login",
|
|
38
|
-
prompts,
|
|
39
|
-
async authorize(inputs) {
|
|
40
|
-
const { verifyAuth } = await import("kiro-acp-ai-provider");
|
|
41
|
-
const status = verifyAuth();
|
|
42
|
-
if (!status.installed)
|
|
43
|
-
throw new Error(
|
|
44
|
-
"kiro-cli is not installed. Install it from https://kiro.dev/docs/cli/"
|
|
45
|
-
);
|
|
46
|
-
if (inputs?.sidebar === "yes") await enableSidebarConfig(tuiConfigPath(), input);
|
|
47
|
-
if (status.authenticated) {
|
|
48
|
-
return {
|
|
49
|
-
url: "",
|
|
50
|
-
instructions: "",
|
|
51
|
-
method: "auto",
|
|
52
|
-
async callback() {
|
|
53
|
-
return readToken(status.tokenPath);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const { execFile } = await import("child_process");
|
|
58
|
-
const child = execFile("kiro-cli", ["login"], {
|
|
59
|
-
shell: process.platform === "win32"
|
|
60
|
-
});
|
|
61
|
-
return {
|
|
62
|
-
url: "",
|
|
63
|
-
instructions: "Complete Kiro authentication in the browser window that just opened. Waiting for login...",
|
|
64
|
-
method: "auto",
|
|
65
|
-
async callback() {
|
|
66
|
-
const maxWait = 12e4;
|
|
67
|
-
const start = Date.now();
|
|
68
|
-
while (Date.now() - start < maxWait) {
|
|
69
|
-
await new Promise((r) => setTimeout(r, 2e3));
|
|
70
|
-
const check = verifyAuth();
|
|
71
|
-
if (check.authenticated) {
|
|
72
|
-
child.kill();
|
|
73
|
-
return readToken(check.tokenPath);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
child.kill();
|
|
77
|
-
throw new Error(
|
|
78
|
-
"Kiro authentication timed out. Run `kiro-cli login` manually."
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
},
|
|
86
|
-
// crash guard: core derefs an undefined kiro provider during auth init when a cred exists but the catalog lacks kiro.
|
|
87
|
-
// only inject when authed; ??= is idempotent and won't clobber a real catalog entry.
|
|
88
|
-
config: async (input2) => {
|
|
89
|
-
if (!hasStoredKiroCredential()) return;
|
|
90
|
-
input2.provider ??= {};
|
|
91
|
-
input2.provider.kiro ??= {};
|
|
92
|
-
},
|
|
93
|
-
provider: {
|
|
94
|
-
id: "kiro",
|
|
95
|
-
// expose the exact runtime/models.dev intersection with catalog metadata intact
|
|
96
|
-
async models(provider, ctx) {
|
|
97
|
-
if (!ctx.auth) return provider.models;
|
|
98
|
-
try {
|
|
99
|
-
const { listModels } = await import("kiro-acp-ai-provider");
|
|
100
|
-
const discoveredModels = await listModels({
|
|
101
|
-
cwd: input.directory ?? input.worktree
|
|
102
|
-
});
|
|
103
|
-
const runtimeModels = new Map(discoveredModels.map((model) => [model.modelId, model]));
|
|
104
|
-
if (runtimeModels.size !== discoveredModels.length) return provider.models;
|
|
105
|
-
const models = {};
|
|
106
|
-
for (const [catalogKey, catalogModel] of Object.entries(provider.models)) {
|
|
107
|
-
const apiId = catalogModel.api?.id;
|
|
108
|
-
if (typeof apiId !== "string") continue;
|
|
109
|
-
const runtimeModel = runtimeModels.get(apiId);
|
|
110
|
-
if (!runtimeModel) continue;
|
|
111
|
-
if (runtimeModel.runtimeEfforts.length === 0) {
|
|
112
|
-
models[catalogKey] = catalogModel;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
models[catalogKey] = {
|
|
116
|
-
...catalogModel,
|
|
117
|
-
...runtimeModel.baselineEffort === void 0 ? {} : {
|
|
118
|
-
options: {
|
|
119
|
-
...catalogModel.options,
|
|
120
|
-
reasoningEffort: runtimeModel.baselineEffort
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
variants: {
|
|
124
|
-
...catalogModel.variants,
|
|
125
|
-
...Object.fromEntries(
|
|
126
|
-
runtimeModel.runtimeEfforts.map((effort) => [
|
|
127
|
-
effort,
|
|
128
|
-
{
|
|
129
|
-
...catalogModel.variants?.[effort],
|
|
130
|
-
reasoningEffort: effort
|
|
131
|
-
}
|
|
132
|
-
])
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return models;
|
|
138
|
-
} catch {
|
|
139
|
-
return provider.models;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
15
|
+
child: void 0,
|
|
16
|
+
pollTimer: void 0,
|
|
17
|
+
cancelPoll: void 0,
|
|
18
|
+
disposeRegistration: void 0
|
|
143
19
|
};
|
|
144
|
-
};
|
|
145
|
-
function kiroTokenPath() {
|
|
146
|
-
return join(homedir(), ".aws", "sso", "cache", "kiro-auth-token.json");
|
|
147
20
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
21
|
+
function releaseLoginResources(resources) {
|
|
22
|
+
if (resources.pollTimer !== void 0) {
|
|
23
|
+
clearTimeout(resources.pollTimer);
|
|
24
|
+
resources.pollTimer = void 0;
|
|
25
|
+
}
|
|
26
|
+
if (resources.child !== void 0) {
|
|
27
|
+
resources.child.kill();
|
|
28
|
+
resources.child = void 0;
|
|
29
|
+
}
|
|
30
|
+
if (resources.cancelPoll !== void 0) {
|
|
31
|
+
const cancel = resources.cancelPoll;
|
|
32
|
+
resources.cancelPoll = void 0;
|
|
33
|
+
cancel();
|
|
155
34
|
}
|
|
156
35
|
}
|
|
157
|
-
|
|
36
|
+
function kiroCredential() {
|
|
37
|
+
return {
|
|
38
|
+
type: "oauth",
|
|
39
|
+
methodID: KIRO_OAUTH_METHOD_ID,
|
|
40
|
+
refresh: "",
|
|
41
|
+
access: "kiro-cli",
|
|
42
|
+
expires: 0
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function pollForLogin(verifyAuth, resources) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const start = Date.now();
|
|
48
|
+
resources.cancelPoll = () => {
|
|
49
|
+
reject(new Error("Kiro authentication was cancelled."));
|
|
50
|
+
};
|
|
51
|
+
const tick = () => {
|
|
52
|
+
resources.pollTimer = void 0;
|
|
53
|
+
if (verifyAuth().authenticated) {
|
|
54
|
+
resources.cancelPoll = void 0;
|
|
55
|
+
releaseLoginResources(resources);
|
|
56
|
+
resolve(kiroCredential());
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (Date.now() - start >= MAX_WAIT_MS) {
|
|
60
|
+
resources.cancelPoll = void 0;
|
|
61
|
+
releaseLoginResources(resources);
|
|
62
|
+
reject(new Error(TIMEOUT_MESSAGE));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
resources.pollTimer = setTimeout(tick, POLL_INTERVAL_MS);
|
|
66
|
+
};
|
|
67
|
+
resources.pollTimer = setTimeout(tick, POLL_INTERVAL_MS);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function authorize(resources) {
|
|
158
71
|
const { verifyAuth } = await import("kiro-acp-ai-provider");
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
72
|
+
const status = verifyAuth();
|
|
73
|
+
if (!status.installed) throw new Error(NOT_INSTALLED_MESSAGE);
|
|
74
|
+
if (status.authenticated) {
|
|
75
|
+
return {
|
|
76
|
+
url: KIRO_DOCS_URL,
|
|
77
|
+
instructions: ALREADY_AUTHENTICATED_INSTRUCTIONS,
|
|
78
|
+
mode: "auto",
|
|
79
|
+
callback: Promise.resolve(kiroCredential())
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const { execFile } = await import("child_process");
|
|
83
|
+
resources.child = execFile("kiro-cli", ["login"], {
|
|
84
|
+
shell: process.platform === "win32"
|
|
85
|
+
});
|
|
163
86
|
return {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
// cosmetic; opencode-core only needs presence
|
|
169
|
-
// future expiry, refreshed each startup (server() re-runs per session) so core doesn't flag a logged-in user as expired. not the file value.
|
|
170
|
-
expires: Date.now() + 8 * 60 * 60 * 1e3
|
|
87
|
+
url: KIRO_DOCS_URL,
|
|
88
|
+
instructions: LOGIN_INSTRUCTIONS,
|
|
89
|
+
mode: "auto",
|
|
90
|
+
callback: pollForLogin(verifyAuth, resources)
|
|
171
91
|
};
|
|
172
92
|
}
|
|
173
|
-
async function
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const message = "Kiro is not logged in. Run 'kiro-cli login' to authenticate.";
|
|
178
|
-
console.warn(message);
|
|
179
|
-
void client?.tui?.showToast?.({ body: { message, variant: "warning" } })?.catch(() => {
|
|
93
|
+
async function registerAuth(context, resources) {
|
|
94
|
+
const registration = await context.integration.transform((draft) => {
|
|
95
|
+
draft.update(KIRO_INTEGRATION_ID, (integration) => {
|
|
96
|
+
integration.name = KIRO_INTEGRATION_NAME;
|
|
180
97
|
});
|
|
181
|
-
|
|
98
|
+
draft.method.update({
|
|
99
|
+
integrationID: KIRO_INTEGRATION_ID,
|
|
100
|
+
method: {
|
|
101
|
+
id: KIRO_OAUTH_METHOD_ID,
|
|
102
|
+
type: "oauth",
|
|
103
|
+
label: KIRO_OAUTH_METHOD_LABEL
|
|
104
|
+
},
|
|
105
|
+
authorize: async (_answer) => authorize(resources)
|
|
106
|
+
// no refresh callback: kiro-cli owns credential storage and refresh
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
resources.disposeRegistration = registration.dispose;
|
|
110
|
+
return async () => {
|
|
111
|
+
releaseLoginResources(resources);
|
|
112
|
+
resources.disposeRegistration = void 0;
|
|
113
|
+
await registration.dispose();
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/server/discovery.ts
|
|
118
|
+
var KIRO_PROVIDER_ID = "kiro";
|
|
119
|
+
var KIRO_PROVIDER_PACKAGE = "aisdk:kiro-acp-ai-provider";
|
|
120
|
+
function asString(value) {
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
function createDiscoveryResources() {
|
|
124
|
+
return {
|
|
125
|
+
state: void 0,
|
|
126
|
+
disposeTransform: void 0,
|
|
127
|
+
eventIterator: void 0,
|
|
128
|
+
eventTask: void 0
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function effortSettings(effort) {
|
|
132
|
+
return { effort };
|
|
133
|
+
}
|
|
134
|
+
function applyEfforts(model, runtimeModel) {
|
|
135
|
+
if (runtimeModel.runtimeEfforts.length === 0) return;
|
|
136
|
+
if (runtimeModel.baselineEffort !== void 0) {
|
|
137
|
+
model.settings = { ...model.settings, ...effortSettings(runtimeModel.baselineEffort) };
|
|
138
|
+
}
|
|
139
|
+
for (const effort of runtimeModel.runtimeEfforts) {
|
|
140
|
+
const existing = model.variants.find((variant) => asString(variant.id) === effort);
|
|
141
|
+
if (existing !== void 0) {
|
|
142
|
+
existing.settings = { ...existing.settings, ...effortSettings(effort) };
|
|
143
|
+
} else {
|
|
144
|
+
model.variants.push({
|
|
145
|
+
id: effort,
|
|
146
|
+
settings: effortSettings(effort)
|
|
147
|
+
});
|
|
148
|
+
}
|
|
182
149
|
}
|
|
183
150
|
}
|
|
184
|
-
function
|
|
185
|
-
|
|
151
|
+
function applyCatalogSnapshot(draft, state) {
|
|
152
|
+
const snapshot = state.snapshot;
|
|
153
|
+
if (snapshot === void 0 || snapshot.length === 0) return;
|
|
154
|
+
const runtime = new Map(snapshot.map((model) => [model.modelId, model]));
|
|
155
|
+
const record = draft.provider.get(KIRO_PROVIDER_ID);
|
|
156
|
+
const rich = record !== void 0 && record.models.size > 0;
|
|
157
|
+
const contextWindows = {};
|
|
158
|
+
if (rich) {
|
|
159
|
+
for (const [catalogKey, catalogModel] of Array.from(record.models.entries())) {
|
|
160
|
+
const runtimeModel = runtime.get(asString(catalogModel.modelID));
|
|
161
|
+
if (runtimeModel === void 0) {
|
|
162
|
+
draft.model.remove(KIRO_PROVIDER_ID, catalogKey);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
draft.model.update(KIRO_PROVIDER_ID, catalogKey, (model) => {
|
|
166
|
+
applyEfforts(model, runtimeModel);
|
|
167
|
+
if (model.limit.context > 0) contextWindows[asString(model.modelID)] = model.limit.context;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
} else {
|
|
171
|
+
for (const runtimeModel of snapshot) {
|
|
172
|
+
draft.model.update(KIRO_PROVIDER_ID, runtimeModel.modelId, (model) => {
|
|
173
|
+
model.name = runtimeModel.name || runtimeModel.modelId;
|
|
174
|
+
model.modelID = runtimeModel.modelId;
|
|
175
|
+
applyEfforts(model, runtimeModel);
|
|
176
|
+
if (model.limit.context > 0) contextWindows[asString(model.modelID)] = model.limit.context;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
draft.provider.update(KIRO_PROVIDER_ID, (provider) => {
|
|
181
|
+
provider.name = KIRO_INTEGRATION_NAME;
|
|
182
|
+
provider.integrationID = KIRO_INTEGRATION_ID;
|
|
183
|
+
provider.package = KIRO_PROVIDER_PACKAGE;
|
|
184
|
+
provider.settings = {
|
|
185
|
+
...provider.settings,
|
|
186
|
+
cwd: state.cwd,
|
|
187
|
+
agent: "opencode",
|
|
188
|
+
trustAllTools: true,
|
|
189
|
+
mcpTimeout: 45,
|
|
190
|
+
contextWindows
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function createDiscover(context, state) {
|
|
195
|
+
async function runDiscovery(gen) {
|
|
186
196
|
try {
|
|
187
|
-
const
|
|
188
|
-
|
|
197
|
+
const { listModels } = await import("kiro-acp-ai-provider");
|
|
198
|
+
const discovered = await listModels({ cwd: state.cwd });
|
|
199
|
+
if (gen !== state.generation) return;
|
|
200
|
+
const uniqueIds = new Set(discovered.map((model) => model.modelId));
|
|
201
|
+
if (uniqueIds.size !== discovered.length) return;
|
|
202
|
+
state.snapshot = discovered;
|
|
203
|
+
await context.catalog.reload();
|
|
189
204
|
} catch {
|
|
190
|
-
return false;
|
|
191
205
|
}
|
|
192
|
-
}
|
|
206
|
+
}
|
|
207
|
+
return async function discover(_reason) {
|
|
208
|
+
const active = await context.integration.connection.active(KIRO_INTEGRATION_ID);
|
|
209
|
+
if (!active) {
|
|
210
|
+
state.generation += 1;
|
|
211
|
+
state.snapshot = void 0;
|
|
212
|
+
await context.catalog.reload();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (state.inflight !== void 0) return state.inflight;
|
|
216
|
+
const gen = ++state.generation;
|
|
217
|
+
const run = runDiscovery(gen).finally(() => {
|
|
218
|
+
if (state.inflight === run) state.inflight = void 0;
|
|
219
|
+
});
|
|
220
|
+
state.inflight = run;
|
|
221
|
+
return run;
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
async function consumeEvents(iterator, discover) {
|
|
225
|
+
try {
|
|
226
|
+
while (true) {
|
|
227
|
+
const result = await iterator.next();
|
|
228
|
+
if (result.done) return;
|
|
229
|
+
const event = result.value;
|
|
230
|
+
if (event.type === "integration.connection.updated" && event.data.integrationID === KIRO_INTEGRATION_ID) {
|
|
231
|
+
try {
|
|
232
|
+
await discover("connection-updated");
|
|
233
|
+
} catch {
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
193
239
|
}
|
|
194
|
-
function
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
240
|
+
async function registerDiscovery(context, resources) {
|
|
241
|
+
const { location } = await context.integration.list();
|
|
242
|
+
const state = {
|
|
243
|
+
cwd: location.directory,
|
|
244
|
+
snapshot: void 0,
|
|
245
|
+
generation: 0,
|
|
246
|
+
inflight: void 0
|
|
247
|
+
};
|
|
248
|
+
resources.state = state;
|
|
249
|
+
const discover = createDiscover(context, state);
|
|
250
|
+
const registration = await context.catalog.transform(
|
|
251
|
+
(draft) => applyCatalogSnapshot(draft, state)
|
|
252
|
+
);
|
|
253
|
+
resources.disposeTransform = registration.dispose;
|
|
254
|
+
const iterator = context.event.subscribe()[Symbol.asyncIterator]();
|
|
255
|
+
resources.eventIterator = iterator;
|
|
256
|
+
resources.eventTask = consumeEvents(iterator, discover);
|
|
257
|
+
if (await context.integration.connection.active(KIRO_INTEGRATION_ID)) {
|
|
258
|
+
void discover("setup").catch(() => {
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return async () => {
|
|
262
|
+
state.generation += 1;
|
|
263
|
+
const errors = [];
|
|
264
|
+
const eventIterator = resources.eventIterator;
|
|
265
|
+
resources.eventIterator = void 0;
|
|
266
|
+
if (eventIterator?.return !== void 0) {
|
|
267
|
+
try {
|
|
268
|
+
await eventIterator.return();
|
|
269
|
+
} catch (error) {
|
|
270
|
+
errors.push(error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const eventTask = resources.eventTask;
|
|
274
|
+
resources.eventTask = void 0;
|
|
275
|
+
if (eventTask !== void 0) await eventTask;
|
|
276
|
+
const disposeTransform = resources.disposeTransform;
|
|
277
|
+
resources.disposeTransform = void 0;
|
|
278
|
+
if (disposeTransform !== void 0) {
|
|
279
|
+
try {
|
|
280
|
+
await disposeTransform();
|
|
281
|
+
} catch (error) {
|
|
282
|
+
errors.push(error);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (errors.length > 0) throw new AggregateError(errors, "kiro discovery cleanup failures");
|
|
286
|
+
};
|
|
199
287
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
288
|
+
|
|
289
|
+
// src/server/aisdk.ts
|
|
290
|
+
var KIRO_SDK_PACKAGE = "kiro-acp-ai-provider";
|
|
291
|
+
function createAisdkResources() {
|
|
292
|
+
return {
|
|
293
|
+
ownedSdks: /* @__PURE__ */ new Set(),
|
|
294
|
+
cache: /* @__PURE__ */ new Map(),
|
|
295
|
+
disposeHook: void 0
|
|
296
|
+
};
|
|
203
297
|
}
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
const plugin = config.plugin;
|
|
207
|
-
return Array.isArray(plugin) && plugin.includes(KIRO_PLUGIN_NAME);
|
|
298
|
+
function isKiroPackage(pkg) {
|
|
299
|
+
return pkg === KIRO_SDK_PACKAGE || pkg === `aisdk:${KIRO_SDK_PACKAGE}`;
|
|
208
300
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
301
|
+
function isJsonSafe(value) {
|
|
302
|
+
if (value === null) return true;
|
|
303
|
+
const kind = typeof value;
|
|
304
|
+
if (kind === "string" || kind === "number" || kind === "boolean") return true;
|
|
305
|
+
if (Array.isArray(value)) return value.every(isJsonSafe);
|
|
306
|
+
if (kind === "object") {
|
|
307
|
+
const proto = Object.getPrototypeOf(value);
|
|
308
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
309
|
+
return Object.values(value).every(isJsonSafe);
|
|
310
|
+
}
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
function stableStringify(value) {
|
|
314
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
315
|
+
if (typeof value === "object" && value !== null) {
|
|
316
|
+
const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`);
|
|
317
|
+
return `{${entries.join(",")}}`;
|
|
318
|
+
}
|
|
319
|
+
return JSON.stringify(value);
|
|
320
|
+
}
|
|
321
|
+
function stableOptionsKey(options) {
|
|
322
|
+
return isJsonSafe(options) ? stableStringify(options) : void 0;
|
|
323
|
+
}
|
|
324
|
+
async function registerAisdkHook(context, resources) {
|
|
325
|
+
const registration = await context.aisdk.hook(
|
|
326
|
+
"sdk",
|
|
327
|
+
async (event) => {
|
|
328
|
+
if (!isKiroPackage(event.package)) return;
|
|
329
|
+
const { createKiroAcp } = await import("kiro-acp-ai-provider");
|
|
330
|
+
const key = stableOptionsKey(event.options);
|
|
331
|
+
let sdk = key === void 0 ? void 0 : resources.cache.get(key);
|
|
332
|
+
if (sdk === void 0) {
|
|
333
|
+
sdk = createKiroAcp(event.options);
|
|
334
|
+
resources.ownedSdks.add(sdk);
|
|
335
|
+
if (key !== void 0) resources.cache.set(key, sdk);
|
|
336
|
+
}
|
|
337
|
+
event.sdk = sdk;
|
|
338
|
+
},
|
|
339
|
+
{ providerID: KIRO_PROVIDER_ID }
|
|
340
|
+
);
|
|
341
|
+
resources.disposeHook = registration.dispose;
|
|
342
|
+
return async () => {
|
|
343
|
+
const errors = [];
|
|
344
|
+
resources.disposeHook = void 0;
|
|
213
345
|
try {
|
|
214
|
-
|
|
215
|
-
} catch {
|
|
216
|
-
|
|
346
|
+
await registration.dispose();
|
|
347
|
+
} catch (error) {
|
|
348
|
+
errors.push(error);
|
|
217
349
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
350
|
+
const owned = Array.from(resources.ownedSdks);
|
|
351
|
+
resources.ownedSdks.clear();
|
|
352
|
+
resources.cache.clear();
|
|
353
|
+
for (const sdk of owned) {
|
|
222
354
|
try {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
} catch {
|
|
227
|
-
return;
|
|
355
|
+
await sdk.shutdown();
|
|
356
|
+
} catch (error) {
|
|
357
|
+
errors.push(error);
|
|
228
358
|
}
|
|
229
359
|
}
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
360
|
+
if (errors.length > 0) throw new AggregateError(errors, "kiro aisdk cleanup failures");
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// src/server/lifecycle.ts
|
|
365
|
+
function createServerState() {
|
|
366
|
+
return {
|
|
367
|
+
auth: createAuthResources(),
|
|
368
|
+
discovery: createDiscoveryResources(),
|
|
369
|
+
aisdk: createAisdkResources(),
|
|
370
|
+
disposers: [],
|
|
371
|
+
disposed: false,
|
|
372
|
+
cleanup: void 0
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
async function disposeAll(disposers) {
|
|
376
|
+
const errors = [];
|
|
377
|
+
for (const dispose of [...disposers].reverse()) {
|
|
378
|
+
try {
|
|
379
|
+
await dispose();
|
|
380
|
+
} catch (error) {
|
|
381
|
+
if (error instanceof AggregateError) errors.push(...error.errors);
|
|
382
|
+
else errors.push(error);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (errors.length > 0) throw new AggregateError(errors, "kiro server cleanup failures");
|
|
386
|
+
}
|
|
387
|
+
function buildCleanup(state) {
|
|
388
|
+
return () => {
|
|
389
|
+
if (state.cleanup !== void 0) return state.cleanup;
|
|
390
|
+
state.disposed = true;
|
|
391
|
+
state.cleanup = disposeAll(state.disposers);
|
|
392
|
+
return state.cleanup;
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// src/server.ts
|
|
397
|
+
var plugin = {
|
|
398
|
+
id: "kiro",
|
|
399
|
+
// tui: true (dist/promise/plugin.d.ts:40) — the host auto-loads this
|
|
400
|
+
// package's `./tui` entrypoint for npm-channel installs (single config entry)
|
|
401
|
+
tui: true,
|
|
402
|
+
async setup(context) {
|
|
403
|
+
const state = createServerState();
|
|
404
|
+
const cleanup = buildCleanup(state);
|
|
236
405
|
try {
|
|
237
|
-
await
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
406
|
+
state.disposers.push(await registerAuth(context, state.auth));
|
|
407
|
+
state.disposers.push(await registerDiscovery(context, state.discovery));
|
|
408
|
+
state.disposers.push(await registerAisdkHook(context, state.aisdk));
|
|
409
|
+
} catch (error) {
|
|
410
|
+
await Promise.resolve(cleanup()).catch(() => {
|
|
242
411
|
});
|
|
243
|
-
|
|
412
|
+
throw error;
|
|
244
413
|
}
|
|
245
|
-
|
|
246
|
-
console.error("opencode-kiro: failed to enable the Kiro credits sidebar in tui.json:", err);
|
|
414
|
+
return cleanup;
|
|
247
415
|
}
|
|
248
|
-
}
|
|
249
|
-
var
|
|
250
|
-
var
|
|
416
|
+
};
|
|
417
|
+
var server_default = plugin;
|
|
418
|
+
var KiroAuthPlugin = plugin;
|
|
251
419
|
export {
|
|
252
420
|
KiroAuthPlugin,
|
|
253
|
-
server_default as default
|
|
254
|
-
enableSidebarConfig,
|
|
255
|
-
kiroTokenPath,
|
|
256
|
-
notifyIfTokenExpired,
|
|
257
|
-
readToken
|
|
421
|
+
server_default as default
|
|
258
422
|
};
|