@agent-native/core 0.157.8 → 0.157.9
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/README.md +1 -1
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +26 -8
- package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +258 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +59 -27
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +4 -1
- package/corpus/templates/slides/actions/export-pptx.ts +261 -71
- package/corpus/templates/slides/actions/import-file.ts +12 -0
- package/corpus/templates/slides/actions/import-pptx.ts +9 -0
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +45 -5
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +69 -1
- package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +316 -64
- package/corpus/templates/slides/server/lib/source-import.ts +10 -1
- package/dist/agent/harness/migrations.d.ts +4 -0
- package/dist/agent/harness/migrations.js +39 -0
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.js +4 -0
- package/dist/agent/run-loop-with-resume.d.ts +1 -0
- package/dist/agent/run-loop-with-resume.js +45 -30
- package/dist/agent/run-migrations.d.ts +8 -0
- package/dist/agent/run-migrations.js +61 -0
- package/dist/chat-threads/migrations.d.ts +1 -0
- package/dist/chat-threads/migrations.js +1 -0
- package/dist/chat-threads/schema-migrations.d.ts +8 -0
- package/dist/chat-threads/schema-migrations.js +60 -0
- package/dist/client/AssistantChat.js +4 -0
- package/dist/client/chat/message-components.d.ts +2 -0
- package/dist/client/chat/message-components.js +11 -1
- package/dist/client/observability/ThumbsFeedback.js +35 -22
- package/dist/client/observability/useObservability.d.ts +1 -1
- package/dist/client/observability/useObservability.js +6 -3
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/feature-flags/a2a-action-route.js +4 -2
- package/dist/feature-flags/permissions.d.ts +2 -0
- package/dist/feature-flags/permissions.js +6 -1
- package/dist/ingestion/pptx.d.ts +14 -1
- package/dist/ingestion/pptx.js +222 -41
- package/dist/localization/core-messages/ar-SA.js +4 -0
- package/dist/localization/core-messages/de-DE.js +4 -0
- package/dist/localization/core-messages/en-US.d.ts +4 -0
- package/dist/localization/core-messages/en-US.js +4 -0
- package/dist/localization/core-messages/es-ES.js +4 -0
- package/dist/localization/core-messages/fr-FR.js +4 -0
- package/dist/localization/core-messages/hi-IN.js +4 -0
- package/dist/localization/core-messages/ja-JP.js +4 -0
- package/dist/localization/core-messages/ko-KR.js +4 -0
- package/dist/localization/core-messages/pt-BR.js +4 -0
- package/dist/localization/core-messages/zh-CN.js +4 -0
- package/dist/localization/core-messages/zh-TW.js +4 -0
- package/dist/localization/core-messages.d.ts +4 -0
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/feedback.js +40 -16
- package/dist/observability/routes.d.ts +6 -6
- package/dist/observability/routes.js +15 -3
- package/dist/observability/store.js +2 -0
- package/dist/observability/traces.js +5 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +10 -10
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts +7 -5
- package/dist/server/action-routes.js +9 -4
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.js +4 -0
- package/dist/server/realtime-voice.js +2 -1
- package/dist/server/release-migrations.js +16 -0
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/usage/migrations.d.ts +4 -0
- package/dist/usage/migrations.js +45 -0
- package/package.json +3 -3
|
@@ -100,6 +100,7 @@ export async function importPptxBufferToDeck(args: {
|
|
|
100
100
|
imported: true;
|
|
101
101
|
url: string;
|
|
102
102
|
imagesSkipped?: number;
|
|
103
|
+
tablesDegraded?: number;
|
|
103
104
|
}> {
|
|
104
105
|
const {
|
|
105
106
|
fileBuffer,
|
|
@@ -156,6 +157,7 @@ export async function importPptxBufferToDeck(args: {
|
|
|
156
157
|
sourceText: parsedSlide.texts.map((text) => text.content).join("\n"),
|
|
157
158
|
imageUrls: Object.values(uploadedImages.urls),
|
|
158
159
|
imageSkippedCount: uploadedImages.imageSkippedCount,
|
|
160
|
+
tablesDegraded: parsedSlide.tablesDegraded ?? 0,
|
|
159
161
|
};
|
|
160
162
|
}),
|
|
161
163
|
),
|
|
@@ -165,6 +167,10 @@ export async function importPptxBufferToDeck(args: {
|
|
|
165
167
|
(total, r) => total + r.imageSkippedCount,
|
|
166
168
|
0,
|
|
167
169
|
);
|
|
170
|
+
const tablesDegraded = results.reduce(
|
|
171
|
+
(total, r) => total + r.tablesDegraded,
|
|
172
|
+
0,
|
|
173
|
+
);
|
|
168
174
|
if (imagesSkipped > 0) {
|
|
169
175
|
throw new Error(
|
|
170
176
|
`Source-faithful PPTX import could not preserve ${imagesSkipped} image(s). No deck was written. Retry with browser-renderable images or use a PDF export for page-faithful preservation.`,
|
|
@@ -180,6 +186,7 @@ export async function importPptxBufferToDeck(args: {
|
|
|
180
186
|
editableText: true,
|
|
181
187
|
})),
|
|
182
188
|
imagesSkipped,
|
|
189
|
+
tablesDegraded,
|
|
183
190
|
});
|
|
184
191
|
const aspectRatio = nearestAspectRatio(
|
|
185
192
|
presentation.slides[0]?.widthEmu,
|
|
@@ -234,6 +241,7 @@ export async function importPptxBufferToDeck(args: {
|
|
|
234
241
|
imported: true,
|
|
235
242
|
url: getDeckUrl(deckId),
|
|
236
243
|
...(imagesSkipped > 0 ? { imagesSkipped } : {}),
|
|
244
|
+
...(tablesDegraded > 0 ? { tablesDegraded } : {}),
|
|
237
245
|
};
|
|
238
246
|
}
|
|
239
247
|
|
|
@@ -269,6 +277,7 @@ export async function importPptxBufferToDeck(args: {
|
|
|
269
277
|
imported: true,
|
|
270
278
|
url: getDeckUrl(id),
|
|
271
279
|
...(imagesSkipped > 0 ? { imagesSkipped } : {}),
|
|
280
|
+
...(tablesDegraded > 0 ? { tablesDegraded } : {}),
|
|
272
281
|
};
|
|
273
282
|
}
|
|
274
283
|
|
|
@@ -56,6 +56,9 @@ function waitForImageToSettle(image: HTMLImageElement): Promise<void> {
|
|
|
56
56
|
if (decodeStarted) return;
|
|
57
57
|
decodeStarted = true;
|
|
58
58
|
if (!image.complete || image.naturalWidth <= 0) {
|
|
59
|
+
console.warn(
|
|
60
|
+
`[export-pptx] image could not be loaded for export: ${image.src}`,
|
|
61
|
+
);
|
|
59
62
|
finish();
|
|
60
63
|
return;
|
|
61
64
|
}
|
|
@@ -141,9 +144,12 @@ const NOTES_MASTER_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?
|
|
|
141
144
|
const NOTES_MASTER_RELS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
142
145
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/></Relationships>`;
|
|
143
146
|
|
|
147
|
+
const EMU_PER_INCH = 914_400;
|
|
148
|
+
|
|
144
149
|
export async function addSpeakerNotesToPptxBlob(
|
|
145
150
|
blob: Blob,
|
|
146
151
|
slides: PptxExportSlide[],
|
|
152
|
+
pptxInches: { w: number; h: number },
|
|
147
153
|
): Promise<Blob> {
|
|
148
154
|
const hasNotes = slides.some((slide) => slide.notes?.trim());
|
|
149
155
|
if (!hasNotes) return blob;
|
|
@@ -194,9 +200,14 @@ export async function addSpeakerNotesToPptxBlob(
|
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
if (!presentationXml.includes("<p:notesSz")) {
|
|
203
|
+
// The notes page is a portrait rotation of the slide, so its cx/cy swap
|
|
204
|
+
// the slide's own width/height (matches PowerPoint's own notesMaster
|
|
205
|
+
// output, e.g. a 13.33x7.5in 16:9 slide gets a 7.5x13.33in notes page).
|
|
206
|
+
const notesCx = Math.round(pptxInches.h * EMU_PER_INCH);
|
|
207
|
+
const notesCy = Math.round(pptxInches.w * EMU_PER_INCH);
|
|
197
208
|
presentationXml = presentationXml.replace(
|
|
198
209
|
"<p:defaultTextStyle>",
|
|
199
|
-
|
|
210
|
+
`<p:notesSz cx="${notesCx}" cy="${notesCy}"/><p:defaultTextStyle>`,
|
|
200
211
|
);
|
|
201
212
|
}
|
|
202
213
|
|
|
@@ -667,13 +678,36 @@ function normalizeSingleLineText(
|
|
|
667
678
|
}
|
|
668
679
|
}
|
|
669
680
|
|
|
681
|
+
const CSS_PX_PER_INCH = 96;
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* dom-to-pptx fits the rendered clone into the requested slide size and
|
|
685
|
+
* scales every measurement it takes by this same factor (dist/dom-to-pptx.mjs
|
|
686
|
+
* `processSlide`). The bullet indent patched in afterward must match that
|
|
687
|
+
* scale or it drifts off the deck's actual aspect ratio.
|
|
688
|
+
*/
|
|
689
|
+
export function pptxExportScale(dims: {
|
|
690
|
+
width: number;
|
|
691
|
+
height: number;
|
|
692
|
+
pptxInches: { w: number; h: number };
|
|
693
|
+
}) {
|
|
694
|
+
return Math.min(
|
|
695
|
+
dims.pptxInches.w / (dims.width / CSS_PX_PER_INCH),
|
|
696
|
+
dims.pptxInches.h / (dims.height / CSS_PX_PER_INCH),
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
670
700
|
/**
|
|
671
701
|
* CSS markers live outside the LI box, so dom-to-pptx cannot infer the gap
|
|
672
702
|
* between a bullet and its text from getBoundingClientRect alone. Add that
|
|
673
703
|
* source-visible gap only on the export clone; the source DOM stays editable.
|
|
674
704
|
*/
|
|
675
|
-
function normalizeListsForPptx(
|
|
705
|
+
function normalizeListsForPptx(
|
|
706
|
+
root: HTMLElement,
|
|
707
|
+
dims: { width: number; height: number; pptxInches: { w: number; h: number } },
|
|
708
|
+
) {
|
|
676
709
|
const bulletIndents: number[] = [];
|
|
710
|
+
const scale = pptxExportScale(dims);
|
|
677
711
|
|
|
678
712
|
for (const list of root.querySelectorAll<HTMLElement>("ul,ol")) {
|
|
679
713
|
const listStyle = window.getComputedStyle(list);
|
|
@@ -711,7 +745,9 @@ function normalizeListsForPptx(root: HTMLElement) {
|
|
|
711
745
|
if (!listRect.width || !itemRect.width) continue;
|
|
712
746
|
|
|
713
747
|
const visualIndentPx = itemRect.left - listRect.left;
|
|
714
|
-
bulletIndents.push(
|
|
748
|
+
bulletIndents.push(
|
|
749
|
+
Math.max(0, (visualIndentPx - paddingLeft) * 0.75 * scale),
|
|
750
|
+
);
|
|
715
751
|
}
|
|
716
752
|
|
|
717
753
|
return bulletIndents;
|
|
@@ -1041,7 +1077,7 @@ export async function buildDeckPptxBlob(
|
|
|
1041
1077
|
exportClones.push(clone);
|
|
1042
1078
|
await preloadImagesWithCors(clone.element);
|
|
1043
1079
|
resetAutofitTransforms(clone.element);
|
|
1044
|
-
slideBulletIndents.push(normalizeListsForPptx(clone.element));
|
|
1080
|
+
slideBulletIndents.push(normalizeListsForPptx(clone.element, dims));
|
|
1045
1081
|
restorePositionedGeometry(
|
|
1046
1082
|
clone.element,
|
|
1047
1083
|
clone.sourceRect,
|
|
@@ -1083,7 +1119,11 @@ export async function buildDeckPptxBlob(
|
|
|
1083
1119
|
initialBlob,
|
|
1084
1120
|
slideBulletIndents,
|
|
1085
1121
|
);
|
|
1086
|
-
const blob = await addSpeakerNotesToPptxBlob(
|
|
1122
|
+
const blob = await addSpeakerNotesToPptxBlob(
|
|
1123
|
+
bulletPatchedBlob,
|
|
1124
|
+
slides,
|
|
1125
|
+
dims.pptxInches,
|
|
1126
|
+
);
|
|
1087
1127
|
return { blob, filename: safePptxName(deckTitle) };
|
|
1088
1128
|
} finally {
|
|
1089
1129
|
for (const clone of exportClones) {
|
|
@@ -167,7 +167,11 @@ export function convertToSlideHtml(
|
|
|
167
167
|
|
|
168
168
|
const DEFAULT_SLIDE_WIDTH_EMU = 9144000;
|
|
169
169
|
const DEFAULT_SLIDE_HEIGHT_EMU = 5143500;
|
|
170
|
-
|
|
170
|
+
// PowerPoint's own default slide background (no `<p:bg>` declared) is white,
|
|
171
|
+
// not black — defaulting to black here made an undecorated slide's own
|
|
172
|
+
// (often dark, theme-default) text unreadable or fully invisible against a
|
|
173
|
+
// background the source file never actually specified.
|
|
174
|
+
const DEFAULT_PPTX_BACKGROUND = "#ffffff"; // guard:allow-raw-color - PPTX's own white default when no background is declared
|
|
171
175
|
const DEFAULT_PPTX_FOREGROUND = "#ffffff"; // guard:allow-raw-color - preserve PPTX white when no run color is declared
|
|
172
176
|
|
|
173
177
|
/**
|
|
@@ -250,6 +254,18 @@ function buildFidelityElement(
|
|
|
250
254
|
return `<div class="fmd-pptx-image" data-pptx-element-kind="image" data-pptx-image-name="${esc(element.image?.name ?? "image")}"${objectId} style="${position}${rotation} overflow: hidden;">${url ? `<img src="${esc(url)}" alt="" style="${imageStyle}" />` : `<div class="fmd-img-placeholder" style="width:100%;height:100%;">Imported image: ${esc(element.image?.name ?? "image")}</div>`}</div>`;
|
|
251
255
|
}
|
|
252
256
|
|
|
257
|
+
if (element.kind === "table") {
|
|
258
|
+
return buildFidelityTable(
|
|
259
|
+
element,
|
|
260
|
+
widthEmu,
|
|
261
|
+
refBox.width,
|
|
262
|
+
themeFont,
|
|
263
|
+
position,
|
|
264
|
+
rotation,
|
|
265
|
+
objectId,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
253
269
|
const decoration = shapeDecoration(element, widthEmu, refBox.width);
|
|
254
270
|
if (element.kind === "shape") {
|
|
255
271
|
return `<div class="fmd-pptx-shape" data-pptx-element-kind="shape"${objectId} style="${position}${rotation}${decoration}"></div>`;
|
|
@@ -331,6 +347,58 @@ function imageRenderStyle(element: ParsedElement): string {
|
|
|
331
347
|
return `display:block;position:absolute;left:${(-crop.left / visibleWidth) * 100}%;top:${(-crop.top / visibleHeight) * 100}%;width:${(1 / visibleWidth) * 100}%;height:${(1 / visibleHeight) * 100}%;object-fit:fill;`;
|
|
332
348
|
}
|
|
333
349
|
|
|
350
|
+
type ParsedTableCell = NonNullable<
|
|
351
|
+
ParsedElement["table"]
|
|
352
|
+
>["rows"][number][number];
|
|
353
|
+
|
|
354
|
+
const DEFAULT_PPTX_TABLE_BORDER = "rgba(255,255,255,0.25)"; // guard:allow-raw-color - imported PPTX table cell border approximation, same fixed-contrast convention as the rest of this fidelity renderer
|
|
355
|
+
|
|
356
|
+
/** Render a parsed `"table"` element (a PPTX `graphicFrame`'s `a:tbl`) as a real HTML `<table>`, sized/positioned the same way every other fidelity element is. */
|
|
357
|
+
function buildFidelityTable(
|
|
358
|
+
element: ParsedElement,
|
|
359
|
+
widthEmu: number,
|
|
360
|
+
refWidthPx: number,
|
|
361
|
+
themeFont: string | undefined,
|
|
362
|
+
position: string,
|
|
363
|
+
rotation: string,
|
|
364
|
+
objectId: string,
|
|
365
|
+
): string {
|
|
366
|
+
const rows = element.table?.rows ?? [];
|
|
367
|
+
const rowsHtml = rows
|
|
368
|
+
.map(
|
|
369
|
+
(row) =>
|
|
370
|
+
`<tr>${row
|
|
371
|
+
.map((cell) =>
|
|
372
|
+
buildFidelityTableCell(cell, widthEmu, refWidthPx, themeFont),
|
|
373
|
+
)
|
|
374
|
+
.join("")}</tr>`,
|
|
375
|
+
)
|
|
376
|
+
.join("");
|
|
377
|
+
return `<div class="fmd-pptx-table" data-pptx-element-kind="table"${objectId} style="${position}${rotation} overflow: hidden;"><table style="width:100%;height:100%;border-collapse:collapse;table-layout:fixed;font-family:${cssFontFamily(themeFont)};">${rowsHtml}</table></div>`;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function buildFidelityTableCell(
|
|
381
|
+
cell: ParsedTableCell,
|
|
382
|
+
widthEmu: number,
|
|
383
|
+
refWidthPx: number,
|
|
384
|
+
themeFont: string | undefined,
|
|
385
|
+
): string {
|
|
386
|
+
const fill = cell.fill ? `background:${esc(cell.fill)};` : "";
|
|
387
|
+
const paragraphsHtml = cell.paragraphs
|
|
388
|
+
.map((paragraph, paragraphIndex) =>
|
|
389
|
+
buildFidelityParagraph(
|
|
390
|
+
paragraph,
|
|
391
|
+
paragraphIndex,
|
|
392
|
+
widthEmu,
|
|
393
|
+
refWidthPx,
|
|
394
|
+
themeFont,
|
|
395
|
+
400,
|
|
396
|
+
),
|
|
397
|
+
)
|
|
398
|
+
.join("");
|
|
399
|
+
return `<td colspan="${cell.colSpan ?? 1}" rowspan="${cell.rowSpan ?? 1}" style="border:1px solid ${DEFAULT_PPTX_TABLE_BORDER};padding:4px 8px;vertical-align:top;${fill}">${paragraphsHtml}</td>`;
|
|
400
|
+
}
|
|
401
|
+
|
|
334
402
|
function shapeDecoration(
|
|
335
403
|
element: ParsedElement,
|
|
336
404
|
widthEmu: number,
|