@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.
@@ -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
 
@@ -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;
@@ -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.0",
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": {