@adapt-toolkit/a2adapt 0.3.0 → 0.4.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.
- package/dist/cli.js +228 -2
- package/dist/hooks/runner.js +115 -17
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
// src/cli.ts
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
5
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
6
6
|
import { connect } from "node:net";
|
|
7
|
-
import { homedir } from "node:os";
|
|
7
|
+
import { homedir, userInfo } from "node:os";
|
|
8
8
|
import { resolve, join, dirname } from "node:path";
|
|
9
9
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
10
|
import * as fs from "node:fs";
|
|
@@ -133,6 +133,11 @@ async function cmdStop() {
|
|
|
133
133
|
async function cmdStatus() {
|
|
134
134
|
const pid = runningPid();
|
|
135
135
|
if (!pid) {
|
|
136
|
+
if (await portOpen(PORT)) {
|
|
137
|
+
out("a2adapt-mcp: running (no pidfile \u2014 likely a stale process or external launcher)");
|
|
138
|
+
out(` url: http://localhost:${PORT}/mcp (reachable)`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
136
141
|
out("a2adapt-mcp: stopped");
|
|
137
142
|
process.exitCode = 1;
|
|
138
143
|
return;
|
|
@@ -145,6 +150,196 @@ async function cmdStatus() {
|
|
|
145
150
|
out(` state: ${STATE_DIR}`);
|
|
146
151
|
out(` logs: ${LOG_PATH}`);
|
|
147
152
|
}
|
|
153
|
+
function cmdWatch(which) {
|
|
154
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
155
|
+
const scan = (initial) => {
|
|
156
|
+
let names;
|
|
157
|
+
try {
|
|
158
|
+
names = fs.readdirSync(STATE_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
159
|
+
} catch {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
for (const name of names) {
|
|
163
|
+
if (which && name !== which) continue;
|
|
164
|
+
const logPath = join(STATE_DIR, name, "inbox.log");
|
|
165
|
+
let size;
|
|
166
|
+
try {
|
|
167
|
+
size = fs.statSync(logPath).size;
|
|
168
|
+
} catch {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
let seen = offsets.get(logPath);
|
|
172
|
+
if (seen === void 0) {
|
|
173
|
+
seen = initial ? size : 0;
|
|
174
|
+
offsets.set(logPath, seen);
|
|
175
|
+
if (initial) continue;
|
|
176
|
+
}
|
|
177
|
+
if (size <= seen) {
|
|
178
|
+
if (size < seen) offsets.set(logPath, size);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
let chunk;
|
|
182
|
+
try {
|
|
183
|
+
const fd = fs.openSync(logPath, "r");
|
|
184
|
+
const buf = Buffer.alloc(size - seen);
|
|
185
|
+
fs.readSync(fd, buf, 0, buf.length, seen);
|
|
186
|
+
fs.closeSync(fd);
|
|
187
|
+
chunk = buf.toString("utf8");
|
|
188
|
+
} catch {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
offsets.set(logPath, size);
|
|
192
|
+
for (const line of chunk.split("\n")) {
|
|
193
|
+
if (!line.trim()) continue;
|
|
194
|
+
let msg;
|
|
195
|
+
try {
|
|
196
|
+
msg = JSON.parse(line);
|
|
197
|
+
} catch {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
out(
|
|
201
|
+
`[${name}] new message from ${msg.sender ?? "?"}: ${msg.text ?? ""}` + (msg.date ? ` (${msg.date})` : "")
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
err(
|
|
207
|
+
`a2adapt-mcp watch: watching ${which ? `identity "${which}"` : "all identities"} under ${STATE_DIR} (Ctrl-C to stop)`
|
|
208
|
+
);
|
|
209
|
+
scan(true);
|
|
210
|
+
const timer = setInterval(() => scan(false), 1e3);
|
|
211
|
+
const stop = () => {
|
|
212
|
+
clearInterval(timer);
|
|
213
|
+
process.exit(0);
|
|
214
|
+
};
|
|
215
|
+
process.on("SIGINT", stop);
|
|
216
|
+
process.on("SIGTERM", stop);
|
|
217
|
+
}
|
|
218
|
+
var SYSTEMD_UNIT = "a2adapt.service";
|
|
219
|
+
var LAUNCHD_LABEL = "solutions.adaptframework.a2adapt";
|
|
220
|
+
function systemdUnitPath() {
|
|
221
|
+
return join(homedir(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
222
|
+
}
|
|
223
|
+
function launchdPlistPath() {
|
|
224
|
+
return join(homedir(), "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`);
|
|
225
|
+
}
|
|
226
|
+
function run(cmd, args) {
|
|
227
|
+
const r = spawnSync(cmd, args, { stdio: "inherit" });
|
|
228
|
+
return r.status === 0;
|
|
229
|
+
}
|
|
230
|
+
function installSystemd() {
|
|
231
|
+
const unitPath = systemdUnitPath();
|
|
232
|
+
fs.mkdirSync(dirname(unitPath), { recursive: true });
|
|
233
|
+
const unit = `[Unit]
|
|
234
|
+
Description=a2adapt MCP daemon (secure agent-to-agent messaging over ADAPT)
|
|
235
|
+
After=network-online.target
|
|
236
|
+
Wants=network-online.target
|
|
237
|
+
|
|
238
|
+
[Service]
|
|
239
|
+
Type=simple
|
|
240
|
+
ExecStart=${process.execPath} ${SELF} serve
|
|
241
|
+
Environment=A2ADAPT_TRANSPORT=http
|
|
242
|
+
Environment=A2ADAPT_PORT=${PORT}
|
|
243
|
+
Environment=A2ADAPT_BROKER_URL=${BROKER_URL}
|
|
244
|
+
Environment=A2ADAPT_STATE_DIR=${STATE_DIR}
|
|
245
|
+
Restart=on-failure
|
|
246
|
+
RestartSec=2
|
|
247
|
+
|
|
248
|
+
[Install]
|
|
249
|
+
WantedBy=default.target
|
|
250
|
+
`;
|
|
251
|
+
fs.writeFileSync(unitPath, unit);
|
|
252
|
+
out(`wrote ${unitPath}`);
|
|
253
|
+
run("systemctl", ["--user", "daemon-reload"]);
|
|
254
|
+
if (!run("systemctl", ["--user", "enable", "--now", SYSTEMD_UNIT])) {
|
|
255
|
+
err("failed to enable/start the service via systemctl --user.");
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
if (!run("loginctl", ["enable-linger", userInfo().username])) {
|
|
259
|
+
err("warning: could not enable linger \u2014 the daemon may not start until you log in.");
|
|
260
|
+
err(` run manually: loginctl enable-linger ${userInfo().username}`);
|
|
261
|
+
}
|
|
262
|
+
out("");
|
|
263
|
+
out(`a2adapt-mcp installed as a systemd user service and started.`);
|
|
264
|
+
out(` status: systemctl --user status ${SYSTEMD_UNIT}`);
|
|
265
|
+
out(` logs: journalctl --user -u ${SYSTEMD_UNIT} -f`);
|
|
266
|
+
out(` remove: a2adapt-mcp uninstall-service`);
|
|
267
|
+
}
|
|
268
|
+
function uninstallSystemd() {
|
|
269
|
+
run("systemctl", ["--user", "disable", "--now", SYSTEMD_UNIT]);
|
|
270
|
+
const unitPath = systemdUnitPath();
|
|
271
|
+
try {
|
|
272
|
+
fs.rmSync(unitPath, { force: true });
|
|
273
|
+
out(`removed ${unitPath}`);
|
|
274
|
+
} catch (e) {
|
|
275
|
+
err(`failed to remove ${unitPath}: ${String(e)}`);
|
|
276
|
+
}
|
|
277
|
+
run("systemctl", ["--user", "daemon-reload"]);
|
|
278
|
+
out("a2adapt-mcp service uninstalled.");
|
|
279
|
+
}
|
|
280
|
+
function installLaunchd() {
|
|
281
|
+
const plistPath = launchdPlistPath();
|
|
282
|
+
fs.mkdirSync(dirname(plistPath), { recursive: true });
|
|
283
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
284
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
285
|
+
<plist version="1.0">
|
|
286
|
+
<dict>
|
|
287
|
+
<key>Label</key><string>${LAUNCHD_LABEL}</string>
|
|
288
|
+
<key>ProgramArguments</key>
|
|
289
|
+
<array>
|
|
290
|
+
<string>${process.execPath}</string>
|
|
291
|
+
<string>${SELF}</string>
|
|
292
|
+
<string>serve</string>
|
|
293
|
+
</array>
|
|
294
|
+
<key>EnvironmentVariables</key>
|
|
295
|
+
<dict>
|
|
296
|
+
<key>A2ADAPT_TRANSPORT</key><string>http</string>
|
|
297
|
+
<key>A2ADAPT_PORT</key><string>${PORT}</string>
|
|
298
|
+
<key>A2ADAPT_BROKER_URL</key><string>${BROKER_URL}</string>
|
|
299
|
+
<key>A2ADAPT_STATE_DIR</key><string>${STATE_DIR}</string>
|
|
300
|
+
</dict>
|
|
301
|
+
<key>RunAtLoad</key><true/>
|
|
302
|
+
<key>KeepAlive</key><true/>
|
|
303
|
+
<key>StandardOutPath</key><string>${LOG_PATH}</string>
|
|
304
|
+
<key>StandardErrorPath</key><string>${LOG_PATH}</string>
|
|
305
|
+
</dict>
|
|
306
|
+
</plist>
|
|
307
|
+
`;
|
|
308
|
+
fs.writeFileSync(plistPath, plist);
|
|
309
|
+
out(`wrote ${plistPath}`);
|
|
310
|
+
run("launchctl", ["unload", plistPath]);
|
|
311
|
+
if (!run("launchctl", ["load", "-w", plistPath])) {
|
|
312
|
+
err("failed to load the launchd agent.");
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
out("");
|
|
316
|
+
out("a2adapt-mcp installed as a launchd agent and started.");
|
|
317
|
+
out(` remove: a2adapt-mcp uninstall-service`);
|
|
318
|
+
}
|
|
319
|
+
function uninstallLaunchd() {
|
|
320
|
+
const plistPath = launchdPlistPath();
|
|
321
|
+
run("launchctl", ["unload", plistPath]);
|
|
322
|
+
try {
|
|
323
|
+
fs.rmSync(plistPath, { force: true });
|
|
324
|
+
out(`removed ${plistPath}`);
|
|
325
|
+
} catch (e) {
|
|
326
|
+
err(`failed to remove ${plistPath}: ${String(e)}`);
|
|
327
|
+
}
|
|
328
|
+
out("a2adapt-mcp service uninstalled.");
|
|
329
|
+
}
|
|
330
|
+
async function cmdInstallService() {
|
|
331
|
+
await cmdStop();
|
|
332
|
+
if (process.platform === "linux") return installSystemd();
|
|
333
|
+
if (process.platform === "darwin") return installLaunchd();
|
|
334
|
+
err(`install-service: unsupported platform "${process.platform}" (only linux/systemd and macOS/launchd).`);
|
|
335
|
+
process.exit(1);
|
|
336
|
+
}
|
|
337
|
+
function cmdUninstallService() {
|
|
338
|
+
if (process.platform === "linux") return uninstallSystemd();
|
|
339
|
+
if (process.platform === "darwin") return uninstallLaunchd();
|
|
340
|
+
err(`uninstall-service: unsupported platform "${process.platform}".`);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
148
343
|
function usage() {
|
|
149
344
|
out("a2adapt-mcp \u2014 daemon for the a2adapt MCP server");
|
|
150
345
|
out("");
|
|
@@ -154,8 +349,13 @@ function usage() {
|
|
|
154
349
|
out(" restart stop then start");
|
|
155
350
|
out(" status show whether the daemon is running");
|
|
156
351
|
out(" serve run in the foreground (used by start; handy for debugging)");
|
|
352
|
+
out(" watch [identity] stream one line per new inbound message (wake source for a Monitor)");
|
|
353
|
+
out("");
|
|
354
|
+
out(" install-service install + start a boot-persistent service (systemd/launchd)");
|
|
355
|
+
out(" uninstall-service stop + remove that service");
|
|
157
356
|
out("");
|
|
158
357
|
out("Config (env): A2ADAPT_BROKER_URL, A2ADAPT_PORT (3030), A2ADAPT_STATE_DIR (~/.a2adapt)");
|
|
358
|
+
out("(install-service bakes the current config values into the service definition.)");
|
|
159
359
|
}
|
|
160
360
|
async function main() {
|
|
161
361
|
const cmd = process.argv[2] ?? "help";
|
|
@@ -163,6 +363,23 @@ async function main() {
|
|
|
163
363
|
case "serve":
|
|
164
364
|
case "run":
|
|
165
365
|
if (!process.env.A2ADAPT_TRANSPORT) process.env.A2ADAPT_TRANSPORT = "http";
|
|
366
|
+
fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
367
|
+
fs.writeFileSync(PID_PATH, String(process.pid));
|
|
368
|
+
{
|
|
369
|
+
const cleanup = () => {
|
|
370
|
+
try {
|
|
371
|
+
fs.rmSync(PID_PATH, { force: true });
|
|
372
|
+
} catch {
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
process.on("exit", cleanup);
|
|
376
|
+
for (const sig of ["SIGTERM", "SIGINT"]) {
|
|
377
|
+
process.on(sig, () => {
|
|
378
|
+
cleanup();
|
|
379
|
+
process.exit(0);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
166
383
|
await import(pathToFileURL(join(dirname(SELF), "index.js")).href);
|
|
167
384
|
break;
|
|
168
385
|
case "start":
|
|
@@ -178,6 +395,15 @@ async function main() {
|
|
|
178
395
|
case "status":
|
|
179
396
|
await cmdStatus();
|
|
180
397
|
break;
|
|
398
|
+
case "watch":
|
|
399
|
+
cmdWatch(process.argv[3]);
|
|
400
|
+
break;
|
|
401
|
+
case "install-service":
|
|
402
|
+
await cmdInstallService();
|
|
403
|
+
break;
|
|
404
|
+
case "uninstall-service":
|
|
405
|
+
cmdUninstallService();
|
|
406
|
+
break;
|
|
181
407
|
case "help":
|
|
182
408
|
case "--help":
|
|
183
409
|
case "-h":
|
package/dist/hooks/runner.js
CHANGED
|
@@ -2,24 +2,122 @@
|
|
|
2
2
|
import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
|
|
3
3
|
|
|
4
4
|
// src/hooks/runner.ts
|
|
5
|
-
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { resolve, join } from "node:path";
|
|
8
|
+
var STATE_DIR = resolve(
|
|
9
|
+
process.env.A2ADAPT_STATE_DIR ?? resolve(homedir(), ".a2adapt")
|
|
10
|
+
);
|
|
11
|
+
function readStdin() {
|
|
12
|
+
try {
|
|
13
|
+
return fs.readFileSync(0, "utf8");
|
|
14
|
+
} catch {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function emit(payload) {
|
|
19
|
+
process.stdout.write(JSON.stringify(payload));
|
|
6
20
|
}
|
|
7
|
-
|
|
21
|
+
function noop() {
|
|
22
|
+
emit({ continue: true });
|
|
8
23
|
}
|
|
9
|
-
|
|
24
|
+
function readCursor(dir) {
|
|
25
|
+
try {
|
|
26
|
+
return parseInt(fs.readFileSync(join(dir, "inbox_cursor"), "utf8").trim(), 10) || 0;
|
|
27
|
+
} catch {
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function readInboxLog(dir) {
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = fs.readFileSync(join(dir, "inbox.log"), "utf8");
|
|
35
|
+
} catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const msgs = [];
|
|
39
|
+
for (const line of raw.split("\n")) {
|
|
40
|
+
if (!line.trim()) continue;
|
|
41
|
+
try {
|
|
42
|
+
const m = JSON.parse(line);
|
|
43
|
+
msgs.push({
|
|
44
|
+
sender: String(m.sender ?? "?"),
|
|
45
|
+
text: String(m.text ?? ""),
|
|
46
|
+
date: String(m.date ?? "")
|
|
47
|
+
});
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return msgs;
|
|
52
|
+
}
|
|
53
|
+
function collectUnread() {
|
|
54
|
+
let names;
|
|
55
|
+
try {
|
|
56
|
+
names = fs.readdirSync(STATE_DIR, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
57
|
+
} catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const name of names) {
|
|
62
|
+
const dir = join(STATE_DIR, name);
|
|
63
|
+
const all = readInboxLog(dir);
|
|
64
|
+
if (all.length === 0) continue;
|
|
65
|
+
const unread = all.slice(readCursor(dir));
|
|
66
|
+
if (unread.length === 0) continue;
|
|
67
|
+
out.push({ name, count: unread.length, messages: unread });
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
function renderContext(unread) {
|
|
72
|
+
const total = unread.reduce((n, u) => n + u.count, 0);
|
|
73
|
+
const lines = [];
|
|
74
|
+
for (const u of unread) {
|
|
75
|
+
lines.push(`\u2022 ${u.name} \u2014 ${u.count} unread:`);
|
|
76
|
+
for (const m of u.messages.slice(-5)) {
|
|
77
|
+
lines.push(` [${m.sender}] ${m.text}${m.date ? ` (${m.date})` : ""}`);
|
|
78
|
+
}
|
|
79
|
+
if (u.count > 5) lines.push(` \u2026and ${u.count - 5} earlier`);
|
|
80
|
+
}
|
|
81
|
+
return `a2adapt \u2014 ${total} unread message(s) across ${unread.length} identit${unread.length === 1 ? "y" : "ies"} (arrived while you were away):
|
|
82
|
+
${lines.join("\n")}
|
|
83
|
+
|
|
84
|
+
To read & clear: choose_identity({ name }) then process_incoming_message(). To wait for live replies, arm a Monitor on the wake source \`a2adapt-mcp watch\` (each new-mail line wakes you).`;
|
|
85
|
+
}
|
|
86
|
+
function sessionStart() {
|
|
87
|
+
const raw = readStdin();
|
|
88
|
+
let source = "";
|
|
89
|
+
if (raw) {
|
|
90
|
+
try {
|
|
91
|
+
source = JSON.parse(raw).source ?? "";
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (source === "compact") return noop();
|
|
96
|
+
const unread = collectUnread();
|
|
97
|
+
if (unread.length === 0) return noop();
|
|
98
|
+
emit({
|
|
99
|
+
continue: true,
|
|
100
|
+
hookSpecificOutput: {
|
|
101
|
+
hookEventName: "SessionStart",
|
|
102
|
+
additionalContext: renderContext(unread)
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function main() {
|
|
10
107
|
const kind = process.argv[2] ?? "";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
main().catch((err) => {
|
|
23
|
-
process.stderr.write(`a2adapt hook: ${err?.stack ?? err}
|
|
108
|
+
try {
|
|
109
|
+
switch (kind) {
|
|
110
|
+
case "session-start":
|
|
111
|
+
sessionStart();
|
|
112
|
+
return;
|
|
113
|
+
default:
|
|
114
|
+
noop();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
} catch (err) {
|
|
118
|
+
process.stderr.write(`a2adapt hook: ${err?.stack ?? err}
|
|
24
119
|
`);
|
|
25
|
-
|
|
120
|
+
noop();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
main();
|
package/dist/index.js
CHANGED
|
@@ -22436,7 +22436,7 @@ import * as fs from "node:fs";
|
|
|
22436
22436
|
import { adapt_wrapper } from "@adapt-toolkit/sdk/executables";
|
|
22437
22437
|
import { PacketWrapperConfigurator } from "@adapt-toolkit/sdk/wrappers";
|
|
22438
22438
|
import { object_to_adapt_value } from "@adapt-toolkit/sdk/wrapper";
|
|
22439
|
-
var VERSION = true ? "0.
|
|
22439
|
+
var VERSION = true ? "0.4.0" : "0.0.0-dev";
|
|
22440
22440
|
var STATE_DIR = resolve(
|
|
22441
22441
|
process.env.A2ADAPT_STATE_DIR ?? resolve(homedir(), ".a2adapt")
|
|
22442
22442
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adapt-toolkit/a2adapt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "MCP server daemon for a2adapt — one native ADAPT wrapper hosting N self-sovereign identities, exposing secure agent-to-agent messaging tools over HTTP (Streamable HTTP). Run `a2adapt-mcp start`.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@adapt-toolkit/sdk": "^0.2.
|
|
52
|
+
"@adapt-toolkit/sdk": "^0.2.2",
|
|
53
53
|
"@adapt-toolkit/sdk-native": "^0.2.1"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|