@agent-native/core 0.167.0 → 0.167.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/corpus/templates/clips/CHANGELOG.md +1 -0
- package/dist/changelog/parse.js +219 -8
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/secrets/routes.d.ts +9 -9
- package/package.json +1 -1
|
@@ -7,6 +7,7 @@ from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
7
7
|
|
|
8
8
|
### Improved
|
|
9
9
|
|
|
10
|
+
- Recording preparation now uses a centered full-screen overlay that transitions smoothly into the 3-2-1 countdown.
|
|
10
11
|
- Clip viewers now make Share the primary action and keep the overflow control compact and vertical.
|
|
11
12
|
- Recording controls now follow you across browser tabs and page navigations.
|
|
12
13
|
|
package/dist/changelog/parse.js
CHANGED
|
@@ -237,6 +237,213 @@ function normalizedChangelogText(value) {
|
|
|
237
237
|
.replace(/\s+/g, " ")
|
|
238
238
|
.trim();
|
|
239
239
|
}
|
|
240
|
+
function stripHtmlComments(line, inComment, initialInlineCodeMarker) {
|
|
241
|
+
let cursor = 0;
|
|
242
|
+
let visibleLine = "";
|
|
243
|
+
const comments = [];
|
|
244
|
+
let inlineCodeMarker = initialInlineCodeMarker;
|
|
245
|
+
while (cursor < line.length) {
|
|
246
|
+
if (inComment) {
|
|
247
|
+
const commentEnd = line.indexOf("-->", cursor);
|
|
248
|
+
if (commentEnd === -1) {
|
|
249
|
+
return {
|
|
250
|
+
line: visibleLine,
|
|
251
|
+
inComment: true,
|
|
252
|
+
inlineCodeMarker,
|
|
253
|
+
comments,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
cursor = commentEnd + 3;
|
|
257
|
+
inComment = false;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (inlineCodeMarker) {
|
|
261
|
+
const codeEnd = line.indexOf(inlineCodeMarker, cursor);
|
|
262
|
+
if (codeEnd === -1) {
|
|
263
|
+
visibleLine += line.slice(cursor);
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
visibleLine += line.slice(cursor, codeEnd + inlineCodeMarker.length);
|
|
267
|
+
cursor = codeEnd + inlineCodeMarker.length;
|
|
268
|
+
inlineCodeMarker = undefined;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const commentStart = line.indexOf("<!--", cursor);
|
|
272
|
+
const codeStartIndex = line.indexOf("`", cursor);
|
|
273
|
+
if (codeStartIndex !== -1 &&
|
|
274
|
+
(commentStart === -1 || codeStartIndex < commentStart)) {
|
|
275
|
+
visibleLine += line.slice(cursor, codeStartIndex);
|
|
276
|
+
const codeStart = /^`+/.exec(line.slice(codeStartIndex))?.[0] ?? "`";
|
|
277
|
+
visibleLine += codeStart;
|
|
278
|
+
cursor = codeStartIndex + codeStart.length;
|
|
279
|
+
inlineCodeMarker = codeStart;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (commentStart === -1) {
|
|
283
|
+
visibleLine += line.slice(cursor);
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
visibleLine += line.slice(cursor, commentStart);
|
|
287
|
+
const commentEnd = line.indexOf("-->", commentStart + 4);
|
|
288
|
+
if (commentEnd !== -1) {
|
|
289
|
+
comments.push(line.slice(commentStart, commentEnd + 3));
|
|
290
|
+
}
|
|
291
|
+
cursor = commentStart + 4;
|
|
292
|
+
inComment = true;
|
|
293
|
+
}
|
|
294
|
+
return { line: visibleLine, inComment, inlineCodeMarker, comments };
|
|
295
|
+
}
|
|
296
|
+
function splitChangelogBodyGroups(body) {
|
|
297
|
+
const matches = [];
|
|
298
|
+
let offset = 0;
|
|
299
|
+
let fenceMarker;
|
|
300
|
+
let htmlComment = false;
|
|
301
|
+
let inlineCodeMarker;
|
|
302
|
+
for (const line of body.split(/\r?\n/)) {
|
|
303
|
+
const lineEnd = offset + line.length;
|
|
304
|
+
if (fenceMarker) {
|
|
305
|
+
const fence = /^\s*(`{3,}|~{3,})(.*)$/.exec(line)?.[1];
|
|
306
|
+
const closingFence = /^\s*(`{3,}|~{3,})\s*$/.exec(line)?.[1];
|
|
307
|
+
if (fence &&
|
|
308
|
+
closingFence &&
|
|
309
|
+
fenceMarker.character === fence[0] &&
|
|
310
|
+
closingFence.length >= fenceMarker.length) {
|
|
311
|
+
fenceMarker = undefined;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
let visibleLine;
|
|
316
|
+
let headingComments = [];
|
|
317
|
+
if (!htmlComment && !inlineCodeMarker) {
|
|
318
|
+
const fence = /^\s*(`{3,}|~{3,})(.*)$/.exec(line)?.[1];
|
|
319
|
+
if (fence) {
|
|
320
|
+
fenceMarker = { character: fence[0], length: fence.length };
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
const commentResult = stripHtmlComments(line, false, inlineCodeMarker);
|
|
324
|
+
htmlComment = commentResult.inComment;
|
|
325
|
+
inlineCodeMarker = commentResult.inlineCodeMarker;
|
|
326
|
+
visibleLine = commentResult.line;
|
|
327
|
+
headingComments = commentResult.comments;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
const commentResult = stripHtmlComments(line, htmlComment, inlineCodeMarker);
|
|
332
|
+
htmlComment = commentResult.inComment;
|
|
333
|
+
inlineCodeMarker = commentResult.inlineCodeMarker;
|
|
334
|
+
visibleLine = commentResult.line;
|
|
335
|
+
headingComments = commentResult.comments;
|
|
336
|
+
}
|
|
337
|
+
if (visibleLine !== undefined && !fenceMarker) {
|
|
338
|
+
const fence = /^\s*(`{3,}|~{3,})(.*)$/.exec(visibleLine)?.[1];
|
|
339
|
+
if (fence) {
|
|
340
|
+
fenceMarker = { character: fence[0], length: fence.length };
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
const heading = /^ {0,3}###\s+(.+?)(?:\s+#+)?\s*$/.exec(visibleLine);
|
|
344
|
+
if (heading &&
|
|
345
|
+
CHANGELOG_GROUP_ORDER.some((type) => GROUP_LABELS[type].toLowerCase() ===
|
|
346
|
+
heading[1].trim().toLowerCase())) {
|
|
347
|
+
matches.push({
|
|
348
|
+
title: heading[1].trim(),
|
|
349
|
+
headingComments,
|
|
350
|
+
start: offset,
|
|
351
|
+
headingEnd: lineEnd,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const newlineLength = body.startsWith("\r\n", lineEnd)
|
|
358
|
+
? 2
|
|
359
|
+
: lineEnd < body.length
|
|
360
|
+
? 1
|
|
361
|
+
: 0;
|
|
362
|
+
offset = lineEnd + newlineLength;
|
|
363
|
+
}
|
|
364
|
+
if (matches.length === 0)
|
|
365
|
+
return { prefix: body.trim(), groups: [] };
|
|
366
|
+
const prefix = body.slice(0, matches[0].start).trim();
|
|
367
|
+
const groups = matches.map((match, index) => {
|
|
368
|
+
const end = matches[index + 1]?.start ?? body.length;
|
|
369
|
+
return {
|
|
370
|
+
title: match.title,
|
|
371
|
+
headingComments: match.headingComments,
|
|
372
|
+
body: body.slice(match.headingEnd, end).trim(),
|
|
373
|
+
index,
|
|
374
|
+
};
|
|
375
|
+
});
|
|
376
|
+
return { prefix, groups };
|
|
377
|
+
}
|
|
378
|
+
function changelogBodyGroupOrder(title) {
|
|
379
|
+
const normalizedTitle = title.toLowerCase();
|
|
380
|
+
const index = CHANGELOG_GROUP_ORDER.findIndex((type) => GROUP_LABELS[type].toLowerCase() === normalizedTitle);
|
|
381
|
+
return index === -1 ? CHANGELOG_GROUP_ORDER.length : index;
|
|
382
|
+
}
|
|
383
|
+
function normalizeChangelogBody(body) {
|
|
384
|
+
const { prefix, groups } = splitChangelogBodyGroups(body);
|
|
385
|
+
if (groups.length < 2)
|
|
386
|
+
return body.trim();
|
|
387
|
+
const uniqueGroups = new Map();
|
|
388
|
+
for (const group of groups) {
|
|
389
|
+
const key = group.title.toLowerCase();
|
|
390
|
+
const current = uniqueGroups.get(key);
|
|
391
|
+
const headingComments = current
|
|
392
|
+
? [
|
|
393
|
+
...current.headingComments,
|
|
394
|
+
...group.headingComments.filter((comment) => !current.headingComments.includes(comment)),
|
|
395
|
+
]
|
|
396
|
+
: group.headingComments;
|
|
397
|
+
uniqueGroups.set(key, {
|
|
398
|
+
title: current?.title ?? group.title,
|
|
399
|
+
headingComments,
|
|
400
|
+
body: [current?.body, group.body].filter(Boolean).join("\n"),
|
|
401
|
+
index: current?.index ?? group.index,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const renderedGroups = [...uniqueGroups.values()]
|
|
405
|
+
.sort((a, b) => changelogBodyGroupOrder(a.title) - changelogBodyGroupOrder(b.title) ||
|
|
406
|
+
a.index - b.index)
|
|
407
|
+
.map((group) => `### ${group.title}${group.headingComments.length ? ` ${group.headingComments.join(" ")}` : ""}\n\n${group.body}`);
|
|
408
|
+
return [prefix, ...renderedGroups].filter(Boolean).join("\n\n");
|
|
409
|
+
}
|
|
410
|
+
function mergeChangelogBodies(pendingBody, existingBody) {
|
|
411
|
+
const pending = splitChangelogBodyGroups(pendingBody);
|
|
412
|
+
const existing = splitChangelogBodyGroups(existingBody);
|
|
413
|
+
if (pending.groups.length === 0) {
|
|
414
|
+
return normalizeChangelogBody(existingBody);
|
|
415
|
+
}
|
|
416
|
+
if (existing.groups.length === 0) {
|
|
417
|
+
return [pendingBody, existingBody]
|
|
418
|
+
.map((body) => body.trim())
|
|
419
|
+
.filter(Boolean)
|
|
420
|
+
.join("\n\n");
|
|
421
|
+
}
|
|
422
|
+
const groups = new Map();
|
|
423
|
+
for (const group of [...pending.groups, ...existing.groups]) {
|
|
424
|
+
const key = group.title.toLowerCase();
|
|
425
|
+
const current = groups.get(key);
|
|
426
|
+
const headingComments = current
|
|
427
|
+
? [
|
|
428
|
+
...current.headingComments,
|
|
429
|
+
...group.headingComments.filter((comment) => !current.headingComments.includes(comment)),
|
|
430
|
+
]
|
|
431
|
+
: group.headingComments;
|
|
432
|
+
groups.set(key, {
|
|
433
|
+
title: current?.title ?? group.title,
|
|
434
|
+
headingComments,
|
|
435
|
+
body: [current?.body, group.body].filter(Boolean).join("\n"),
|
|
436
|
+
index: current?.index ?? group.index,
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
const prefix = [pending.prefix, existing.prefix].filter(Boolean).join("\n\n");
|
|
440
|
+
return normalizeChangelogBody([
|
|
441
|
+
prefix,
|
|
442
|
+
...[...groups.values()].map((group) => `### ${group.title}${group.headingComments.length ? ` ${group.headingComments.join(" ")}` : ""}\n\n${group.body}`),
|
|
443
|
+
]
|
|
444
|
+
.filter(Boolean)
|
|
445
|
+
.join("\n\n"));
|
|
446
|
+
}
|
|
240
447
|
/**
|
|
241
448
|
* Render an app-facing changelog that includes both released CHANGELOG.md
|
|
242
449
|
* sections and adjacent folder-backed `changelog/*.md` entries. This is pure
|
|
@@ -246,10 +453,19 @@ function normalizedChangelogText(value) {
|
|
|
246
453
|
export function mergePendingChangelog(existing, pending) {
|
|
247
454
|
const cleanExisting = stripChangelogArchiveNotes(existing);
|
|
248
455
|
const existingEntries = parseChangelog(cleanExisting);
|
|
456
|
+
const pendingSeen = new Set();
|
|
249
457
|
const pendingWithText = pending.filter((entry) => {
|
|
250
458
|
const text = entry.text.trim();
|
|
251
459
|
if (!text)
|
|
252
460
|
return false;
|
|
461
|
+
const pendingKey = [
|
|
462
|
+
entry.date ?? "",
|
|
463
|
+
entry.type,
|
|
464
|
+
normalizedChangelogText(text),
|
|
465
|
+
].join("\u0000");
|
|
466
|
+
if (pendingSeen.has(pendingKey))
|
|
467
|
+
return false;
|
|
468
|
+
pendingSeen.add(pendingKey);
|
|
253
469
|
return !existingEntries.some((existingEntry) => {
|
|
254
470
|
if (entry.date &&
|
|
255
471
|
existingEntry.date &&
|
|
@@ -261,7 +477,7 @@ export function mergePendingChangelog(existing, pending) {
|
|
|
261
477
|
});
|
|
262
478
|
if (pendingWithText.length === 0) {
|
|
263
479
|
const sections = existingEntries
|
|
264
|
-
.map((entry) => `## ${entry.title}\n\n${cleanChangelogBody(entry.body)}`)
|
|
480
|
+
.map((entry) => `## ${entry.title}\n\n${normalizeChangelogBody(cleanChangelogBody(entry.body))}`)
|
|
265
481
|
.join("\n\n");
|
|
266
482
|
return `${changelogHeader(cleanExisting)}${sections ? `\n\n${sections}` : ""}\n\n${CHANGELOG_ARCHIVE_NOTE}\n`;
|
|
267
483
|
}
|
|
@@ -273,7 +489,7 @@ export function mergePendingChangelog(existing, pending) {
|
|
|
273
489
|
const sections = existingEntries.map((entry) => ({
|
|
274
490
|
title: entry.title,
|
|
275
491
|
date: entry.date,
|
|
276
|
-
body: cleanChangelogBody(entry.body),
|
|
492
|
+
body: normalizeChangelogBody(cleanChangelogBody(entry.body)),
|
|
277
493
|
}));
|
|
278
494
|
for (const title of [...pendingByTitle.keys()].sort(pendingSectionSort)) {
|
|
279
495
|
const body = renderReleaseBody(pendingByTitle.get(title) ?? []);
|
|
@@ -283,12 +499,7 @@ export function mergePendingChangelog(existing, pending) {
|
|
|
283
499
|
return entry.date === title || entry.title === title;
|
|
284
500
|
});
|
|
285
501
|
if (existingIndex !== -1) {
|
|
286
|
-
sections[existingIndex].body = [
|
|
287
|
-
body,
|
|
288
|
-
cleanChangelogBody(sections[existingIndex].body),
|
|
289
|
-
]
|
|
290
|
-
.filter(Boolean)
|
|
291
|
-
.join("\n\n");
|
|
502
|
+
sections[existingIndex].body = mergeChangelogBodies(body, cleanChangelogBody(sections[existingIndex].body));
|
|
292
503
|
continue;
|
|
293
504
|
}
|
|
294
505
|
const newSection = { title, date: title.match(ISO_DATE)?.[1], body };
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
-
error?: undefined;
|
|
66
65
|
states: {
|
|
67
66
|
clientId: number;
|
|
68
67
|
state: string;
|
|
69
68
|
}[];
|
|
69
|
+
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
-
error?: undefined;
|
|
81
80
|
users: {
|
|
82
81
|
clientId: number;
|
|
83
82
|
lastSeen: number;
|
|
84
83
|
}[];
|
|
84
|
+
error?: undefined;
|
|
85
85
|
}>>;
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
|
|
14
14
|
*/
|
|
15
15
|
export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
16
|
-
ok?: undefined;
|
|
17
16
|
error: string;
|
|
17
|
+
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
19
|
error?: undefined;
|
|
20
20
|
ok: boolean;
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
-
error?: undefined;
|
|
15
14
|
count: number;
|
|
16
15
|
updated?: undefined;
|
|
16
|
+
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
-
error?: undefined;
|
|
20
19
|
count?: undefined;
|
|
21
20
|
updated: number;
|
|
21
|
+
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,8 +26,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
-
error?: undefined;
|
|
30
29
|
count?: undefined;
|
|
31
30
|
updated?: undefined;
|
|
31
|
+
error?: undefined;
|
|
32
32
|
ok: boolean;
|
|
33
33
|
}>>;
|
|
@@ -41,23 +41,23 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
-
ok?: undefined;
|
|
45
44
|
error?: undefined;
|
|
46
45
|
summary: import("./types.js").TraceSummary;
|
|
47
46
|
spans: import("./types.js").TraceSpan[];
|
|
48
47
|
id?: undefined;
|
|
49
|
-
} | {
|
|
50
48
|
ok?: undefined;
|
|
49
|
+
} | {
|
|
51
50
|
error?: undefined;
|
|
52
51
|
summary?: undefined;
|
|
53
52
|
spans?: undefined;
|
|
54
53
|
id: string;
|
|
55
|
-
} | {
|
|
56
54
|
ok?: undefined;
|
|
55
|
+
} | {
|
|
57
56
|
summary?: undefined;
|
|
58
57
|
spans?: undefined;
|
|
59
58
|
id?: undefined;
|
|
60
59
|
error: any;
|
|
60
|
+
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
62
|
error?: undefined;
|
|
63
63
|
summary?: undefined;
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
|
|
|
34
34
|
/** POST /_agent-native/secrets/:key — write a secret. */
|
|
35
35
|
export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
36
36
|
error: string;
|
|
37
|
-
ok?: undefined;
|
|
38
37
|
status?: undefined;
|
|
38
|
+
ok?: undefined;
|
|
39
39
|
} | {
|
|
40
|
-
error?: undefined;
|
|
41
40
|
ok: boolean;
|
|
42
41
|
status: string;
|
|
42
|
+
error?: undefined;
|
|
43
43
|
} | {
|
|
44
|
-
ok?: undefined;
|
|
45
44
|
error: string;
|
|
46
45
|
removed?: undefined;
|
|
46
|
+
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
|
-
error?: undefined;
|
|
49
48
|
ok: boolean;
|
|
50
49
|
removed: boolean;
|
|
50
|
+
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — validate an optional candidate value
|
|
54
54
|
* or the current stored value without changing anything.
|
|
55
55
|
*/
|
|
56
56
|
export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
57
|
-
ok?: undefined;
|
|
58
57
|
error: string;
|
|
59
58
|
note?: undefined;
|
|
59
|
+
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
|
-
error?: undefined;
|
|
62
61
|
ok: boolean;
|
|
63
62
|
note?: undefined;
|
|
64
|
-
} | {
|
|
65
63
|
error?: undefined;
|
|
64
|
+
} | {
|
|
66
65
|
ok: boolean;
|
|
67
66
|
note: string;
|
|
67
|
+
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
-
error?: undefined;
|
|
99
98
|
ok: boolean;
|
|
100
99
|
key: string;
|
|
101
|
-
} | {
|
|
102
100
|
error?: undefined;
|
|
101
|
+
} | {
|
|
103
102
|
ok: boolean;
|
|
104
103
|
removed: boolean;
|
|
104
|
+
error?: undefined;
|
|
105
105
|
}>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.167.
|
|
3
|
+
"version": "0.167.1",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|