pxengine 0.1.105 → 0.1.107

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/index.cjs CHANGED
@@ -39301,7 +39301,7 @@ var ExportModal = ({ formats, title, onClose }) => {
39301
39301
  );
39302
39302
  })
39303
39303
  ] }),
39304
- /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("p", { className: "text-xs text-zinc-600 mt-4 text-center", children: "Download links expire in 7 days" })
39304
+ /* @__PURE__ */ (0, import_jsx_runtime147.jsx)("p", { className: "text-xs text-zinc-600 mt-4 text-center", children: "Download links expire in 90 days" })
39305
39305
  ] })
39306
39306
  ] });
39307
39307
  };
@@ -39559,7 +39559,7 @@ var PresentationJobCard = ({
39559
39559
  }
39560
39560
  }, [isTerminal]);
39561
39561
  const handleShare = async () => {
39562
- const link = shareUrl ?? formats.html_url;
39562
+ const link = shareUrl ?? (typeof window !== "undefined" && _job_id ? `${window.location.origin}/p/${_job_id}` : formats.html_url);
39563
39563
  if (!link) return;
39564
39564
  try {
39565
39565
  await navigator.clipboard.writeText(link);
@@ -39871,6 +39871,19 @@ var ExpandIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", {
39871
39871
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
39872
39872
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
39873
39873
  ] });
39874
+ var ShareIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
39875
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
39876
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
39877
+ ] });
39878
+ var CheckIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "20 6 9 17 4 12" }) });
39879
+ var RefreshIcon = () => /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
39880
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("polyline", { points: "23 4 23 10 17 10" }),
39881
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })
39882
+ ] });
39883
+ function formatTemplateLabel(templateId) {
39884
+ if (!templateId) return null;
39885
+ return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
39886
+ }
39874
39887
  var FullscreenPreviewModal = ({ url, title, onClose }) => {
39875
39888
  (0, import_react78.useEffect)(() => {
39876
39889
  const onKey = (e) => {
@@ -39916,7 +39929,7 @@ var FullscreenPreviewModal = ({ url, title, onClose }) => {
39916
39929
  };
39917
39930
  var ResearchReportJobCard = (props) => {
39918
39931
  const {
39919
- job_id: _job_id,
39932
+ job_id,
39920
39933
  title: initialTitle,
39921
39934
  status: initialStatus,
39922
39935
  topic: _initialTopic,
@@ -39927,11 +39940,18 @@ var ResearchReportJobCard = (props) => {
39927
39940
  executive_summary: initialSummary,
39928
39941
  key_findings: _initialFindings,
39929
39942
  html_url: initialHtmlUrl,
39943
+ generation_mode: initialGenerationMode,
39944
+ template_id: initialTemplateId,
39945
+ template_version_id: initialTemplateVersionId,
39946
+ review_status: initialReviewStatus,
39930
39947
  theme: initialTheme,
39931
39948
  error: initialError,
39932
39949
  progress: initialProgress,
39933
39950
  pollUrl,
39934
39951
  authToken,
39952
+ shareUrl,
39953
+ approveUrl,
39954
+ regenerateUrl,
39935
39955
  className,
39936
39956
  onComplete,
39937
39957
  onFailed,
@@ -39946,11 +39966,23 @@ var ResearchReportJobCard = (props) => {
39946
39966
  const [wordCount, setWordCount] = (0, import_react78.useState)(initialWordCount ?? 0);
39947
39967
  const [summary, setSummary] = (0, import_react78.useState)(initialSummary || "");
39948
39968
  const [htmlUrl, setHtmlUrl] = (0, import_react78.useState)(initialHtmlUrl || "");
39969
+ const [generationMode, setGenerationMode] = (0, import_react78.useState)(
39970
+ initialGenerationMode || (initialHtmlUrl ? "template" : "")
39971
+ );
39972
+ const [templateId, setTemplateId] = (0, import_react78.useState)(initialTemplateId || "");
39973
+ const [templateVersionId, setTemplateVersionId] = (0, import_react78.useState)(initialTemplateVersionId || "");
39974
+ const [reviewStatus, setReviewStatus] = (0, import_react78.useState)(
39975
+ initialReviewStatus || (initialHtmlUrl ? "pending_review" : "")
39976
+ );
39949
39977
  const [theme, setTheme] = (0, import_react78.useState)(initialTheme || DEFAULT_THEME);
39950
39978
  const [error, setError] = (0, import_react78.useState)(initialError);
39951
39979
  const [progress, setProgress] = (0, import_react78.useState)(initialProgress);
39952
39980
  const [showPreview, setShowPreview] = (0, import_react78.useState)(false);
39953
39981
  const [previewScale, setPreviewScale] = (0, import_react78.useState)(1);
39982
+ const [copied, setCopied] = (0, import_react78.useState)(false);
39983
+ const [approving, setApproving] = (0, import_react78.useState)(false);
39984
+ const [regenerating, setRegenerating] = (0, import_react78.useState)(false);
39985
+ const [approveError, setApproveError] = (0, import_react78.useState)(null);
39954
39986
  const previewRef = (0, import_react78.useRef)(null);
39955
39987
  const intervalRef = (0, import_react78.useRef)(null);
39956
39988
  const onCompleteRef = (0, import_react78.useRef)(onComplete);
@@ -39968,6 +40000,18 @@ var ResearchReportJobCard = (props) => {
39968
40000
  (0, import_react78.useEffect)(() => {
39969
40001
  if (initialHtmlUrl) setHtmlUrl(initialHtmlUrl);
39970
40002
  }, [initialHtmlUrl]);
40003
+ (0, import_react78.useEffect)(() => {
40004
+ if (initialGenerationMode) setGenerationMode(initialGenerationMode);
40005
+ }, [initialGenerationMode]);
40006
+ (0, import_react78.useEffect)(() => {
40007
+ if (initialTemplateId) setTemplateId(initialTemplateId);
40008
+ }, [initialTemplateId]);
40009
+ (0, import_react78.useEffect)(() => {
40010
+ if (initialTemplateVersionId) setTemplateVersionId(initialTemplateVersionId);
40011
+ }, [initialTemplateVersionId]);
40012
+ (0, import_react78.useEffect)(() => {
40013
+ if (initialReviewStatus) setReviewStatus(initialReviewStatus);
40014
+ }, [initialReviewStatus]);
39971
40015
  (0, import_react78.useEffect)(() => {
39972
40016
  if (initialDepth) setDepth(initialDepth);
39973
40017
  }, [initialDepth]);
@@ -40035,6 +40079,10 @@ var ResearchReportJobCard = (props) => {
40035
40079
  setWordCount(output.word_count || 0);
40036
40080
  setSummary(output.executive_summary || "");
40037
40081
  setHtmlUrl(output.html_url || "");
40082
+ if (output.generation_mode) setGenerationMode(output.generation_mode);
40083
+ if (output.template_id) setTemplateId(output.template_id);
40084
+ if (output.template_version_id) setTemplateVersionId(output.template_version_id);
40085
+ if (output.review_status) setReviewStatus(output.review_status);
40038
40086
  if (output.theme) {
40039
40087
  setTheme(output.theme);
40040
40088
  }
@@ -40216,6 +40264,120 @@ var ResearchReportJobCard = (props) => {
40216
40264
  window.open(htmlUrl, "_blank", "noopener,noreferrer");
40217
40265
  }
40218
40266
  };
40267
+ const resolveShareLink = () => {
40268
+ if (shareUrl) return shareUrl;
40269
+ if (typeof window !== "undefined" && job_id) {
40270
+ return `${window.location.origin}/r/${job_id}`;
40271
+ }
40272
+ return htmlUrl;
40273
+ };
40274
+ const handleShare = async () => {
40275
+ const link = resolveShareLink();
40276
+ if (!link) return;
40277
+ try {
40278
+ await navigator.clipboard.writeText(link);
40279
+ setCopied(true);
40280
+ setTimeout(() => setCopied(false), 2e3);
40281
+ } catch {
40282
+ window.open(link, "_blank", "noopener,noreferrer");
40283
+ }
40284
+ };
40285
+ const canApprove = generationMode === "template" && reviewStatus === "pending_review" && Boolean(job_id);
40286
+ const canRegenerate = generationMode === "template" && reviewStatus === "pending_review" && Boolean(job_id);
40287
+ const canShare = Boolean(hasHTML || job_id) && (generationMode !== "template" || reviewStatus !== "pending_review");
40288
+ const handleApprove = async () => {
40289
+ if (!job_id || approving) return;
40290
+ const endpoint = approveUrl || `/api/reports/${job_id}/approve`;
40291
+ setApproving(true);
40292
+ setApproveError(null);
40293
+ try {
40294
+ const headers = { "Content-Type": "application/json" };
40295
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
40296
+ const res = await fetch(endpoint, {
40297
+ method: "POST",
40298
+ headers,
40299
+ body: JSON.stringify({ label: title })
40300
+ });
40301
+ if (!res.ok) {
40302
+ const err = await res.json().catch(() => ({}));
40303
+ throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
40304
+ }
40305
+ const data = await res.json();
40306
+ const newStatus = data.review_status || "approved";
40307
+ setReviewStatus(newStatus);
40308
+ if (data.template_version_id) setTemplateVersionId(data.template_version_id);
40309
+ if (data.template_id) setTemplateId(data.template_id);
40310
+ if (onCompleteRef.current) {
40311
+ onCompleteRef.current({
40312
+ title,
40313
+ depth,
40314
+ section_count: sectionCount,
40315
+ source_count: sourceCount,
40316
+ word_count: wordCount,
40317
+ executive_summary: summary,
40318
+ html_url: htmlUrl,
40319
+ generation_mode: generationMode,
40320
+ template_id: data.template_id || templateId,
40321
+ template_version_id: data.template_version_id || templateVersionId,
40322
+ review_status: newStatus,
40323
+ theme
40324
+ });
40325
+ }
40326
+ } catch (e) {
40327
+ setApproveError(e instanceof Error ? e.message : "Could not save report version");
40328
+ } finally {
40329
+ setApproving(false);
40330
+ }
40331
+ };
40332
+ const handleRegenerate = async () => {
40333
+ if (!job_id || regenerating) return;
40334
+ const endpoint = regenerateUrl || `/api/reports/${job_id}/regenerate`;
40335
+ setRegenerating(true);
40336
+ setApproveError(null);
40337
+ try {
40338
+ const headers = { "Content-Type": "application/json" };
40339
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
40340
+ const res = await fetch(endpoint, {
40341
+ method: "POST",
40342
+ headers,
40343
+ body: JSON.stringify({})
40344
+ });
40345
+ if (!res.ok) {
40346
+ const err = await res.json().catch(() => ({}));
40347
+ throw new Error(err.detail || err.error || `Regenerate failed (${res.status})`);
40348
+ }
40349
+ const data = await res.json();
40350
+ const out = data.output || data;
40351
+ if (out.html_url) setHtmlUrl(out.html_url);
40352
+ if (data.template_id || out.template_id) setTemplateId(data.template_id || out.template_id);
40353
+ setReviewStatus("pending_review");
40354
+ setTemplateVersionId("");
40355
+ if (out.section_count !== void 0) setSectionCount(out.section_count);
40356
+ if (out.title) setTitle(out.title);
40357
+ if (onCompleteRef.current) {
40358
+ onCompleteRef.current({
40359
+ title: out.title || title,
40360
+ depth,
40361
+ section_count: out.section_count ?? sectionCount,
40362
+ source_count: sourceCount,
40363
+ word_count: wordCount,
40364
+ executive_summary: summary,
40365
+ html_url: out.html_url || htmlUrl,
40366
+ generation_mode: "template",
40367
+ template_id: data.template_id || out.template_id || templateId,
40368
+ template_version_id: void 0,
40369
+ review_status: "pending_review",
40370
+ theme
40371
+ });
40372
+ }
40373
+ } catch (e) {
40374
+ setApproveError(e instanceof Error ? e.message : "Could not switch template");
40375
+ } finally {
40376
+ setRegenerating(false);
40377
+ }
40378
+ };
40379
+ const templateLabel = formatTemplateLabel(templateId);
40380
+ const isApproved = reviewStatus === "approved";
40219
40381
  return /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(import_jsx_runtime148.Fragment, { children: [
40220
40382
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: cn("w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden", children: [
40221
40383
  /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
@@ -40249,10 +40411,53 @@ var ResearchReportJobCard = (props) => {
40249
40411
  depth && sectionCount > 0 && " \xB7 ",
40250
40412
  sectionCount > 0 && `${sectionCount} sections`,
40251
40413
  sourceCount > 0 && ` \xB7 ${sourceCount} sources`,
40252
- wordCount > 0 && ` \xB7 ${formatWordCount(wordCount)} words`
40253
- ] })
40414
+ wordCount > 0 && ` \xB7 ${formatWordCount(wordCount)} words`,
40415
+ templateLabel && ` \xB7 ${templateLabel}`
40416
+ ] }),
40417
+ generationMode === "template" && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "text-xs mt-1", children: isApproved ? /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "text-emerald-400/90", children: "Approved \u2014 future reports use this format" }) : reviewStatus === "pending_review" ? /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "text-amber-400/90", children: "Review this report, then approve to lock the layout" }) : null })
40254
40418
  ] }),
40255
- /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
40419
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)("div", { className: "flex items-center gap-1.5 flex-shrink-0 flex-wrap justify-end", children: [
40420
+ canRegenerate && /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
40421
+ "button",
40422
+ {
40423
+ onClick: handleRegenerate,
40424
+ disabled: regenerating || approving,
40425
+ title: "Try another report template with the same data",
40426
+ className: "flex items-center gap-1.5 px-2.5 h-7 rounded-lg border border-zinc-700 bg-zinc-800 hover:border-zinc-500 text-zinc-300 text-xs font-medium transition-colors disabled:opacity-50",
40427
+ children: [
40428
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(RefreshIcon, {}),
40429
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { children: regenerating ? "Switching..." : "Regenerate" })
40430
+ ]
40431
+ }
40432
+ ),
40433
+ canApprove && /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
40434
+ "button",
40435
+ {
40436
+ onClick: handleApprove,
40437
+ disabled: approving,
40438
+ title: "Approve and save this report format for future runs",
40439
+ className: "flex items-center gap-1.5 px-2.5 h-7 rounded-lg border border-emerald-700/50 bg-emerald-950/40 hover:border-emerald-500 text-emerald-300 text-xs font-medium transition-colors disabled:opacity-50",
40440
+ children: [
40441
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(CheckIcon2, {}),
40442
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { children: approving ? "Saving..." : "Approve" })
40443
+ ]
40444
+ }
40445
+ ),
40446
+ isApproved && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("span", { className: "flex items-center justify-center w-7 h-7 rounded-lg border border-emerald-500/40 bg-emerald-500/10 text-emerald-400", title: "Format saved", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(CheckIcon2, {}) }),
40447
+ /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(
40448
+ "button",
40449
+ {
40450
+ onClick: handleShare,
40451
+ disabled: !canShare,
40452
+ title: !canShare && reviewStatus === "pending_review" ? "Approve the report to enable sharing" : copied ? "Copied!" : "Copy shareable link",
40453
+ className: cn(
40454
+ "w-7 h-7 rounded-lg border flex items-center justify-center transition-all",
40455
+ copied ? "border-green-500/40 bg-green-500/10 text-green-400" : "border-zinc-700 bg-zinc-800 text-zinc-400 hover:border-zinc-500 hover:text-zinc-200",
40456
+ "disabled:opacity-30 disabled:cursor-not-allowed"
40457
+ ),
40458
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(CheckIcon2, {}) : /* @__PURE__ */ (0, import_jsx_runtime148.jsx)(ShareIcon2, {})
40459
+ }
40460
+ ),
40256
40461
  /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
40257
40462
  "button",
40258
40463
  {
@@ -40283,6 +40488,7 @@ var ResearchReportJobCard = (props) => {
40283
40488
  )
40284
40489
  ] })
40285
40490
  ] }),
40491
+ approveError && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
40286
40492
  hasHTML && !compact && /* @__PURE__ */ (0, import_jsx_runtime148.jsx)("div", { className: "mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime148.jsxs)(
40287
40493
  "div",
40288
40494
  {
@@ -43756,7 +43962,7 @@ function PlatformMetricsBanner({
43756
43962
  return /* @__PURE__ */ (0, import_jsx_runtime173.jsxs)(
43757
43963
  "div",
43758
43964
  {
43759
- className: "\n grid grid-cols-1 gap-3 rounded-xl py-4 px-4 shadow-sm\n md:flex md:overflow-x-auto md:gap-6 md:rounded-l-xl md:py-4 md:px-4 md:items-center md:gap-0 md:px-0 md:ml-8\n ",
43965
+ className: "\r\n grid grid-cols-1 gap-3 rounded-xl py-4 px-4 shadow-sm\r\n md:flex md:overflow-x-auto md:gap-6 md:rounded-l-xl md:py-4 md:px-4 md:items-center md:gap-0 md:px-0 md:ml-8\r\n ",
43760
43966
  style: { backgroundColor: bgColor },
43761
43967
  children: [
43762
43968
  /* @__PURE__ */ (0, import_jsx_runtime173.jsxs)("div", { className: "flex flex-col items-center md:min-w-0", children: [