@adaptiqai/opencode 0.1.4 → 0.1.6
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 +166 -41
- package/lib/index.js +4923 -391
- package/lib/tui.js +396 -0
- package/package.json +5 -3
package/lib/tui.js
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
// src/tui.ts
|
|
2
|
+
import { createSignal as createSignal2 } from "solid-js";
|
|
3
|
+
import { createComponent, createElement as createElement2, effect as effect2, insert as insert2, setProp as setProp2 } from "@opentui/solid";
|
|
4
|
+
|
|
5
|
+
// src/routes.ts
|
|
6
|
+
var PACKAGE = "@adaptiqai/opencode";
|
|
7
|
+
var ROUTE = "adaptiqai";
|
|
8
|
+
var CONSOLE_ROUTE = "adaptiq";
|
|
9
|
+
function onAdaptiq(providerID) {
|
|
10
|
+
return providerID === ROUTE || providerID === CONSOLE_ROUTE;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/panel.ts
|
|
14
|
+
var VIEW = "adaptiqai.view:";
|
|
15
|
+
var DO = "adaptiqai.do:";
|
|
16
|
+
var PANEL_RPC = {
|
|
17
|
+
id: "adaptiqai.panel",
|
|
18
|
+
methods: { do: { input: { type: "object" }, output: { type: "object" } } },
|
|
19
|
+
events: { view: { schema: { type: "object" } } }
|
|
20
|
+
};
|
|
21
|
+
var PANEL_VERSION = 1;
|
|
22
|
+
var FLASH_MS = 4e3;
|
|
23
|
+
function encode(prefix, message) {
|
|
24
|
+
return prefix + JSON.stringify({ ...message, v: PANEL_VERSION });
|
|
25
|
+
}
|
|
26
|
+
function decode(prefix, event) {
|
|
27
|
+
if (event?.type !== "tui.command.execute") return void 0;
|
|
28
|
+
const command = event.properties?.command;
|
|
29
|
+
if (typeof command !== "string" || !command.startsWith(prefix)) return void 0;
|
|
30
|
+
try {
|
|
31
|
+
const message = JSON.parse(command.slice(prefix.length));
|
|
32
|
+
return message.v === PANEL_VERSION && typeof message.kind === "string" ? message : void 0;
|
|
33
|
+
} catch {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function eventOf(prefix, message) {
|
|
38
|
+
return { type: "tui.command.execute", properties: { command: encode(prefix, message) } };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/panel-view.ts
|
|
42
|
+
function pillText(session, now) {
|
|
43
|
+
return session.flash !== null && session.button === null && now - session.flash.at < FLASH_MS ? session.flash.text : session.text;
|
|
44
|
+
}
|
|
45
|
+
function optionsOf(items) {
|
|
46
|
+
return items.map((item, value) => ({
|
|
47
|
+
title: item.title,
|
|
48
|
+
value,
|
|
49
|
+
...item.description === void 0 ? {} : { description: item.description },
|
|
50
|
+
...item.category === void 0 ? {} : { category: item.category }
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
function lastProvider(messages) {
|
|
54
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
55
|
+
const message = messages[index];
|
|
56
|
+
const provider = message?.providerID ?? message?.model?.providerID;
|
|
57
|
+
if (typeof provider === "string") return provider;
|
|
58
|
+
}
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
function lastOnAdaptiq(messages) {
|
|
62
|
+
return onAdaptiq(lastProvider(messages));
|
|
63
|
+
}
|
|
64
|
+
function awayLine(session, picked) {
|
|
65
|
+
const away = session?.away;
|
|
66
|
+
if (away == null || picked === void 0 || onAdaptiq(picked.providerID) && picked.modelID === away.model) return null;
|
|
67
|
+
return away.line.replace("{next}", picked.name ?? (onAdaptiq(picked.providerID) ? away.names?.[picked.modelID] : void 0) ?? picked.modelID);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/tui2.ts
|
|
71
|
+
import { createSignal } from "solid-js";
|
|
72
|
+
import { createElement, effect, insert, setProp } from "@opentui/solid";
|
|
73
|
+
var messageOf = (error) => typeof error === "object" && error !== null && "message" in error ? String(error.message) : String(error);
|
|
74
|
+
async function setup(context) {
|
|
75
|
+
const rpc = context.client.rpc(PANEL_RPC);
|
|
76
|
+
const [sessions, setSessions] = createSignal(/* @__PURE__ */ new Map());
|
|
77
|
+
const [now, setNow] = createSignal(Date.now());
|
|
78
|
+
const watched = /* @__PURE__ */ new Set();
|
|
79
|
+
const current = () => {
|
|
80
|
+
const route = context.ui.router.current();
|
|
81
|
+
return route.type === "session" ? route.sessionID : void 0;
|
|
82
|
+
};
|
|
83
|
+
const color = (tone) => {
|
|
84
|
+
const feedback = context.theme.text.feedback;
|
|
85
|
+
if (tone === "warn") return feedback?.warning?.base ?? context.theme.text.base;
|
|
86
|
+
if (tone === "error") return feedback?.error?.base ?? context.theme.text.base;
|
|
87
|
+
if (tone === "success") return feedback?.success?.base ?? context.theme.text.base;
|
|
88
|
+
return tone === "normal" ? context.theme.text.base : context.theme.text.muted;
|
|
89
|
+
};
|
|
90
|
+
const call = async (message) => {
|
|
91
|
+
const sessionId = message.sessionId ?? current();
|
|
92
|
+
try {
|
|
93
|
+
const reply = await rpc.do({ ...message, ...sessionId === void 0 ? {} : { sessionId } });
|
|
94
|
+
return typeof reply?.kind === "string" ? reply : void 0;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
return { v: 1, kind: "answer", to: "", title: "AdaptiqAI", text: messageOf(error) };
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const update = async () => {
|
|
100
|
+
const location = context.location ?? context.data?.location.default();
|
|
101
|
+
try {
|
|
102
|
+
const listed = await context.client.plugin?.list({ location });
|
|
103
|
+
const entries = Array.isArray(listed) ? listed : listed?.data ?? [];
|
|
104
|
+
const target = entries.find((entry) => entry.plugin?.source?.type === "package" && entry.plugin.source.target?.includes(PACKAGE) === true)?.plugin?.source?.target;
|
|
105
|
+
if (target === void 0 || context.client.plugin === void 0) throw new Error("Run opencode plugin update, then restart OpenCode.");
|
|
106
|
+
await context.client.plugin.update({ location, targets: [target] });
|
|
107
|
+
await context.ui.dialog.alert({ title: "AdaptiqAI", message: "AdaptiqAI is updated. Restart OpenCode to use the new version here." });
|
|
108
|
+
} catch (error) {
|
|
109
|
+
await context.ui.dialog.alert({ title: "AdaptiqAI", message: `The update did not install: ${messageOf(error)}` });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const pick = async (item) => {
|
|
113
|
+
if (item.install !== void 0) {
|
|
114
|
+
await update();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const action = item.action;
|
|
118
|
+
if (action === void 0) return;
|
|
119
|
+
let message = action;
|
|
120
|
+
if (item.prompt !== void 0) {
|
|
121
|
+
const value = await context.ui.dialog.prompt({ title: item.prompt.title, ...item.prompt.placeholder === void 0 ? {} : { placeholder: item.prompt.placeholder } });
|
|
122
|
+
if (value === void 0) return;
|
|
123
|
+
message = { ...action, value };
|
|
124
|
+
}
|
|
125
|
+
await show(await call(message));
|
|
126
|
+
};
|
|
127
|
+
const show = async (reply) => {
|
|
128
|
+
if (reply?.kind === "answer") {
|
|
129
|
+
await context.ui.dialog.alert({ title: reply.title, message: reply.text });
|
|
130
|
+
} else if (reply?.kind === "list") {
|
|
131
|
+
const value = await context.ui.dialog.select({ title: reply.title, options: optionsOf(reply.items) });
|
|
132
|
+
const item = value === void 0 ? void 0 : reply.items[value];
|
|
133
|
+
if (item !== void 0) await pick(item);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const watch = (sessionId) => {
|
|
137
|
+
if (watched.has(sessionId)) return;
|
|
138
|
+
watched.add(sessionId);
|
|
139
|
+
void call({ kind: "watch", sessionId });
|
|
140
|
+
};
|
|
141
|
+
const stop = rpc.events.on("view", (event) => {
|
|
142
|
+
const message = event.data;
|
|
143
|
+
if (message.kind === "toast") {
|
|
144
|
+
context.ui.toast.show({ ...message.title === void 0 ? {} : { title: message.title }, message: message.message, variant: message.variant, duration: 1e4 });
|
|
145
|
+
} else if (message.kind === "session") {
|
|
146
|
+
const next = new Map(sessions());
|
|
147
|
+
next.set(message.session.sessionId, message.session);
|
|
148
|
+
setSessions(next);
|
|
149
|
+
const flash = message.session.flash;
|
|
150
|
+
if (flash !== null && Date.now() - flash.at < FLASH_MS) {
|
|
151
|
+
setNow(Date.now());
|
|
152
|
+
setTimeout(() => {
|
|
153
|
+
setNow(Date.now());
|
|
154
|
+
}, FLASH_MS + 50);
|
|
155
|
+
}
|
|
156
|
+
} else if (message.kind === "answer" && message.to === `session:${current() ?? ""}`) {
|
|
157
|
+
void context.ui.dialog.alert({ title: message.title, message: message.text });
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
const unpill = context.ui.slot({
|
|
161
|
+
append: "prompt.footer.status",
|
|
162
|
+
render: (input) => {
|
|
163
|
+
const view = () => input.sessionID === void 0 ? void 0 : sessions().get(input.sessionID);
|
|
164
|
+
const shown = () => {
|
|
165
|
+
const picked = context.ui.model.current();
|
|
166
|
+
return view()?.show === true || picked !== void 0 && onAdaptiq(picked.providerID);
|
|
167
|
+
};
|
|
168
|
+
const box = createElement("box");
|
|
169
|
+
const text = createElement("text");
|
|
170
|
+
insert(text, () => {
|
|
171
|
+
if (input.sessionID !== void 0) watch(input.sessionID);
|
|
172
|
+
if (!shown()) return "";
|
|
173
|
+
const session = view();
|
|
174
|
+
return session === void 0 ? "AdaptiqAI" : pillText(session, now());
|
|
175
|
+
});
|
|
176
|
+
effect(() => {
|
|
177
|
+
setProp(text, "fg", color(view()?.tone ?? "muted"));
|
|
178
|
+
});
|
|
179
|
+
insert(box, text);
|
|
180
|
+
setProp(box, "onMouseUp", () => {
|
|
181
|
+
if (!shown()) return;
|
|
182
|
+
const button = view()?.button ?? null;
|
|
183
|
+
void (button === null ? call({ kind: "menu" }) : call({ kind: "button", button })).then(show);
|
|
184
|
+
});
|
|
185
|
+
return box;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
const unaway = context.ui.slot({
|
|
189
|
+
append: "session.composer.top",
|
|
190
|
+
render: (input) => {
|
|
191
|
+
const line = () => awayLine(input.sessionID === void 0 ? void 0 : sessions().get(input.sessionID), context.ui.model.current());
|
|
192
|
+
const box = createElement("box");
|
|
193
|
+
const text = createElement("text");
|
|
194
|
+
insert(text, () => line() ?? "");
|
|
195
|
+
effect(() => {
|
|
196
|
+
setProp(text, "fg", color("warn"));
|
|
197
|
+
});
|
|
198
|
+
effect(() => {
|
|
199
|
+
setProp(box, "visible", line() !== null);
|
|
200
|
+
});
|
|
201
|
+
insert(box, text);
|
|
202
|
+
return box;
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
context.keymap.layer(() => ({
|
|
206
|
+
commands: [{
|
|
207
|
+
id: "adaptiqai.menu",
|
|
208
|
+
title: "AdaptiqAI",
|
|
209
|
+
description: "AdaptiqAI menu: memory, knowledge, settings",
|
|
210
|
+
group: "AdaptiqAI",
|
|
211
|
+
palette: true,
|
|
212
|
+
slash: { name: "adaptiq", arguments: true },
|
|
213
|
+
run: (input) => {
|
|
214
|
+
const text = input?.trim() ?? "";
|
|
215
|
+
void call(text === "" ? { kind: "menu" } : { kind: "command", text }).then((reply) => show(reply === void 0 || reply.kind !== "answer" || text === "" ? reply : { ...reply, title: `/adaptiq ${text}` }));
|
|
216
|
+
}
|
|
217
|
+
}]
|
|
218
|
+
}));
|
|
219
|
+
void call({ kind: "hello" });
|
|
220
|
+
return () => {
|
|
221
|
+
stop();
|
|
222
|
+
unpill();
|
|
223
|
+
unaway();
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/tui.ts
|
|
228
|
+
var COLORS = { normal: "text", muted: "textMuted", private: "secondary", warn: "warning", error: "error", success: "success" };
|
|
229
|
+
async function tui(api) {
|
|
230
|
+
const me = Math.random().toString(36).slice(2, 10);
|
|
231
|
+
let asked = 0;
|
|
232
|
+
let waiting = null;
|
|
233
|
+
const [sessions, setSessions] = createSignal2(/* @__PURE__ */ new Map());
|
|
234
|
+
const [now, setNow] = createSignal2(Date.now());
|
|
235
|
+
const watched = /* @__PURE__ */ new Set();
|
|
236
|
+
const send = (message) => {
|
|
237
|
+
void Promise.resolve().then(() => api.client.tui.publish({ body: eventOf(DO, message) })).catch(() => {
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const current = () => {
|
|
241
|
+
const route = api.route.current;
|
|
242
|
+
return route.name === "session" && typeof route.params?.sessionID === "string" ? route.params.sessionID : void 0;
|
|
243
|
+
};
|
|
244
|
+
let replacing = false;
|
|
245
|
+
const show = (render) => {
|
|
246
|
+
replacing = true;
|
|
247
|
+
try {
|
|
248
|
+
api.ui.dialog.replace(render, () => {
|
|
249
|
+
if (!replacing) waiting = null;
|
|
250
|
+
});
|
|
251
|
+
} finally {
|
|
252
|
+
replacing = false;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const alert = (title, message) => {
|
|
256
|
+
show(() => createComponent(api.ui.DialogAlert, { title, message, onConfirm: () => {
|
|
257
|
+
api.ui.dialog.clear();
|
|
258
|
+
} }));
|
|
259
|
+
};
|
|
260
|
+
const ask = (message, title = "AdaptiqAI") => {
|
|
261
|
+
asked += 1;
|
|
262
|
+
const to = `${me}:${asked}`;
|
|
263
|
+
alert(title, "One moment\u2026");
|
|
264
|
+
waiting = to;
|
|
265
|
+
send({ ...message, to, ...message.sessionId === void 0 && current() !== void 0 ? { sessionId: current() } : {} });
|
|
266
|
+
};
|
|
267
|
+
const install = async (spec) => {
|
|
268
|
+
alert("AdaptiqAI", `Installing ${spec}\u2026`);
|
|
269
|
+
const result = await api.plugins.install(spec, { global: true }).catch((error) => ({ ok: false, message: error instanceof Error ? error.message : String(error) }));
|
|
270
|
+
alert("AdaptiqAI", result.ok ? `${spec} is installed. It runs from the next start.` : `The update did not install: ${result.message ?? "unknown error"}`);
|
|
271
|
+
};
|
|
272
|
+
const pick = (item) => {
|
|
273
|
+
if (item.install !== void 0) {
|
|
274
|
+
void install(item.install);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const action = item.action;
|
|
278
|
+
if (action === void 0) return;
|
|
279
|
+
if (action.kind === "button" && action.button.id === "sign-in" && current() !== void 0 && !onConsole(current())) {
|
|
280
|
+
api.ui.dialog.clear();
|
|
281
|
+
api.keymap.dispatchCommand("provider.connect");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (item.prompt === void 0) {
|
|
285
|
+
ask(action, item.title);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
show(() => createComponent(api.ui.DialogPrompt, {
|
|
289
|
+
title: item.prompt?.title ?? item.title,
|
|
290
|
+
...item.prompt?.placeholder === void 0 ? {} : { placeholder: item.prompt.placeholder },
|
|
291
|
+
onConfirm: (value) => {
|
|
292
|
+
ask({ ...action, value }, item.title);
|
|
293
|
+
},
|
|
294
|
+
onCancel: () => {
|
|
295
|
+
api.ui.dialog.clear();
|
|
296
|
+
}
|
|
297
|
+
}));
|
|
298
|
+
};
|
|
299
|
+
const list = (title, items) => {
|
|
300
|
+
show(() => createComponent(api.ui.DialogSelect, {
|
|
301
|
+
title,
|
|
302
|
+
options: optionsOf(items),
|
|
303
|
+
onSelect: (option) => {
|
|
304
|
+
const item = items[option.value];
|
|
305
|
+
if (item !== void 0) pick(item);
|
|
306
|
+
}
|
|
307
|
+
}));
|
|
308
|
+
};
|
|
309
|
+
const onConsole = (sessionId) => lastProvider(api.state.session.messages(sessionId)) === CONSOLE_ROUTE;
|
|
310
|
+
api.event.on("tui.command.execute", (event) => {
|
|
311
|
+
const message = decode(VIEW, event);
|
|
312
|
+
if (message === void 0) return;
|
|
313
|
+
if (message.kind === "toast") {
|
|
314
|
+
api.ui.toast({ ...message.title === void 0 ? {} : { title: message.title }, message: message.message, variant: message.variant, duration: 1e4 });
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
if (message.kind === "session") {
|
|
318
|
+
const next = new Map(sessions());
|
|
319
|
+
next.set(message.session.sessionId, message.session);
|
|
320
|
+
setSessions(next);
|
|
321
|
+
const flash = message.session.flash;
|
|
322
|
+
if (flash !== null && Date.now() - flash.at < FLASH_MS) {
|
|
323
|
+
setNow(Date.now());
|
|
324
|
+
setTimeout(() => {
|
|
325
|
+
setNow(Date.now());
|
|
326
|
+
}, FLASH_MS + 50);
|
|
327
|
+
}
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (message.kind === "answer" && message.to === `session:${current() ?? ""}`) {
|
|
331
|
+
alert(message.title, message.text);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (message.to !== waiting) return;
|
|
335
|
+
waiting = null;
|
|
336
|
+
if (message.kind === "answer") alert(message.title, message.text);
|
|
337
|
+
else list(message.title, message.items);
|
|
338
|
+
});
|
|
339
|
+
const pill = (sessionId) => {
|
|
340
|
+
if (!watched.has(sessionId)) {
|
|
341
|
+
watched.add(sessionId);
|
|
342
|
+
send({ kind: "watch", sessionId });
|
|
343
|
+
}
|
|
344
|
+
const view = () => sessions().get(sessionId);
|
|
345
|
+
const shown = () => view()?.show === true || lastOnAdaptiq(api.state.session.messages(sessionId));
|
|
346
|
+
const box = createElement2("box");
|
|
347
|
+
const text = createElement2("text");
|
|
348
|
+
insert2(text, () => {
|
|
349
|
+
const session = view();
|
|
350
|
+
if (!shown()) return "";
|
|
351
|
+
return session === void 0 ? "AdaptiqAI" : pillText(session, now());
|
|
352
|
+
});
|
|
353
|
+
effect2(() => {
|
|
354
|
+
setProp2(text, "fg", api.theme.current[COLORS[view()?.tone ?? "muted"]] ?? api.theme.current.textMuted);
|
|
355
|
+
});
|
|
356
|
+
insert2(box, text);
|
|
357
|
+
setProp2(box, "onMouseUp", () => {
|
|
358
|
+
if (!shown()) return;
|
|
359
|
+
const button = view()?.button ?? null;
|
|
360
|
+
if (button === null) ask({ kind: "menu", sessionId });
|
|
361
|
+
else pick({ title: button.label, action: { kind: "button", button, sessionId } });
|
|
362
|
+
});
|
|
363
|
+
return box;
|
|
364
|
+
};
|
|
365
|
+
api.slots.register({
|
|
366
|
+
order: 50,
|
|
367
|
+
slots: {
|
|
368
|
+
session_prompt_right(_ctx, props) {
|
|
369
|
+
return typeof props.session_id === "string" ? pill(props.session_id) : null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
api.keymap.registerLayer({
|
|
374
|
+
commands: [{
|
|
375
|
+
namespace: "palette",
|
|
376
|
+
name: "adaptiqai.menu",
|
|
377
|
+
title: "AdaptiqAI",
|
|
378
|
+
desc: "AdaptiqAI menu: memory, knowledge, settings",
|
|
379
|
+
category: "AdaptiqAI",
|
|
380
|
+
slashName: "adaptiq",
|
|
381
|
+
run: () => {
|
|
382
|
+
ask({ kind: "menu" });
|
|
383
|
+
}
|
|
384
|
+
}],
|
|
385
|
+
bindings: []
|
|
386
|
+
});
|
|
387
|
+
send({ kind: "hello" });
|
|
388
|
+
}
|
|
389
|
+
var tui_default = { id: "adaptiqai", tui, setup };
|
|
390
|
+
export {
|
|
391
|
+
tui_default as default,
|
|
392
|
+
lastOnAdaptiq,
|
|
393
|
+
optionsOf,
|
|
394
|
+
pillText,
|
|
395
|
+
tui
|
|
396
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adaptiqai/opencode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "AdaptiqAI for OpenCode and Kilo: your workspace's models, conversations AdaptiqAI remembers, and your saved knowledge, in one plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"lib/index.js",
|
|
22
|
+
"lib/tui.js",
|
|
22
23
|
"README.md"
|
|
23
24
|
],
|
|
24
25
|
"main": "./lib/index.js",
|
|
25
26
|
"exports": {
|
|
26
27
|
".": "./lib/index.js",
|
|
27
|
-
"./server": "./lib/index.js"
|
|
28
|
+
"./server": "./lib/index.js",
|
|
29
|
+
"./tui": "./lib/tui.js"
|
|
28
30
|
},
|
|
29
31
|
"engines": {
|
|
30
32
|
"opencode": ">=1.18.29"
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
"typescript": "~5.9.3",
|
|
36
38
|
"vitest": "~3.2.7",
|
|
37
39
|
"zod": "4.1.8",
|
|
38
|
-
"@adaptiqai/core": "0.2.
|
|
40
|
+
"@adaptiqai/core": "0.2.16"
|
|
39
41
|
},
|
|
40
42
|
"scripts": {
|
|
41
43
|
"build": "node scripts/build.mjs",
|