pxengine 0.1.105 → 0.1.106

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.d.cts CHANGED
@@ -3514,6 +3514,14 @@ interface ResearchReportJobCardProps {
3514
3514
  key_findings?: string[];
3515
3515
  /** HTML report URL */
3516
3516
  html_url?: string;
3517
+ /** How the report was generated: template (default) or legacy */
3518
+ generation_mode?: "template" | "legacy" | string;
3519
+ /** Built-in template id used to render the report */
3520
+ template_id?: string;
3521
+ /** Saved version id after user approval */
3522
+ template_version_id?: string;
3523
+ /** User review state for template-based reports */
3524
+ review_status?: "pending_review" | "approved" | "auto" | string;
3517
3525
  /** Dynamic theme colors generated based on topic */
3518
3526
  theme?: ReportTheme;
3519
3527
  /** Error message if job failed */
@@ -3524,6 +3532,17 @@ interface ResearchReportJobCardProps {
3524
3532
  pollUrl?: string;
3525
3533
  /** Auth token for polling requests */
3526
3534
  authToken?: string;
3535
+ /**
3536
+ * Shareable link copied when the user clicks Share.
3537
+ * Falls back to `/r/{job_id}` on the current origin when not provided.
3538
+ */
3539
+ shareUrl?: string;
3540
+ /**
3541
+ * Approve endpoint (POST). Defaults to `/api/reports/{job_id}/approve`.
3542
+ */
3543
+ approveUrl?: string;
3544
+ /** Regenerate endpoint (POST). Defaults to `/api/reports/{job_id}/regenerate`. */
3545
+ regenerateUrl?: string;
3527
3546
  /** Additional CSS classes */
3528
3547
  className?: string;
3529
3548
  /** Callback when job completes */
@@ -3548,6 +3567,10 @@ interface ResearchReportJobOutput {
3548
3567
  key_findings?: string[];
3549
3568
  theme?: ReportTheme;
3550
3569
  html_url?: string;
3570
+ generation_mode?: string;
3571
+ template_id?: string;
3572
+ template_version_id?: string;
3573
+ review_status?: string;
3551
3574
  }
3552
3575
 
3553
3576
  declare const ResearchReportJobCard: React__default.FC<ResearchReportJobCardProps>;
package/dist/index.d.ts CHANGED
@@ -3514,6 +3514,14 @@ interface ResearchReportJobCardProps {
3514
3514
  key_findings?: string[];
3515
3515
  /** HTML report URL */
3516
3516
  html_url?: string;
3517
+ /** How the report was generated: template (default) or legacy */
3518
+ generation_mode?: "template" | "legacy" | string;
3519
+ /** Built-in template id used to render the report */
3520
+ template_id?: string;
3521
+ /** Saved version id after user approval */
3522
+ template_version_id?: string;
3523
+ /** User review state for template-based reports */
3524
+ review_status?: "pending_review" | "approved" | "auto" | string;
3517
3525
  /** Dynamic theme colors generated based on topic */
3518
3526
  theme?: ReportTheme;
3519
3527
  /** Error message if job failed */
@@ -3524,6 +3532,17 @@ interface ResearchReportJobCardProps {
3524
3532
  pollUrl?: string;
3525
3533
  /** Auth token for polling requests */
3526
3534
  authToken?: string;
3535
+ /**
3536
+ * Shareable link copied when the user clicks Share.
3537
+ * Falls back to `/r/{job_id}` on the current origin when not provided.
3538
+ */
3539
+ shareUrl?: string;
3540
+ /**
3541
+ * Approve endpoint (POST). Defaults to `/api/reports/{job_id}/approve`.
3542
+ */
3543
+ approveUrl?: string;
3544
+ /** Regenerate endpoint (POST). Defaults to `/api/reports/{job_id}/regenerate`. */
3545
+ regenerateUrl?: string;
3527
3546
  /** Additional CSS classes */
3528
3547
  className?: string;
3529
3548
  /** Callback when job completes */
@@ -3548,6 +3567,10 @@ interface ResearchReportJobOutput {
3548
3567
  key_findings?: string[];
3549
3568
  theme?: ReportTheme;
3550
3569
  html_url?: string;
3570
+ generation_mode?: string;
3571
+ template_id?: string;
3572
+ template_version_id?: string;
3573
+ review_status?: string;
3551
3574
  }
3552
3575
 
3553
3576
  declare const ResearchReportJobCard: React__default.FC<ResearchReportJobCardProps>;
package/dist/index.mjs CHANGED
@@ -38973,7 +38973,7 @@ var ExportModal = ({ formats, title, onClose }) => {
38973
38973
  );
38974
38974
  })
38975
38975
  ] }),
38976
- /* @__PURE__ */ jsx147("p", { className: "text-xs text-zinc-600 mt-4 text-center", children: "Download links expire in 7 days" })
38976
+ /* @__PURE__ */ jsx147("p", { className: "text-xs text-zinc-600 mt-4 text-center", children: "Download links expire in 90 days" })
38977
38977
  ] })
38978
38978
  ] });
38979
38979
  };
@@ -39543,6 +39543,19 @@ var ExpandIcon2 = () => /* @__PURE__ */ jsxs109("svg", { width: "14", height: "1
39543
39543
  /* @__PURE__ */ jsx148("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
39544
39544
  /* @__PURE__ */ jsx148("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
39545
39545
  ] });
39546
+ var ShareIcon2 = () => /* @__PURE__ */ jsxs109("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
39547
+ /* @__PURE__ */ jsx148("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
39548
+ /* @__PURE__ */ jsx148("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
39549
+ ] });
39550
+ var CheckIcon2 = () => /* @__PURE__ */ jsx148("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx148("polyline", { points: "20 6 9 17 4 12" }) });
39551
+ var RefreshIcon = () => /* @__PURE__ */ jsxs109("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: [
39552
+ /* @__PURE__ */ jsx148("polyline", { points: "23 4 23 10 17 10" }),
39553
+ /* @__PURE__ */ jsx148("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })
39554
+ ] });
39555
+ function formatTemplateLabel(templateId) {
39556
+ if (!templateId) return null;
39557
+ return templateId.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
39558
+ }
39546
39559
  var FullscreenPreviewModal = ({ url, title, onClose }) => {
39547
39560
  useEffect7(() => {
39548
39561
  const onKey = (e) => {
@@ -39588,7 +39601,7 @@ var FullscreenPreviewModal = ({ url, title, onClose }) => {
39588
39601
  };
39589
39602
  var ResearchReportJobCard = (props) => {
39590
39603
  const {
39591
- job_id: _job_id,
39604
+ job_id,
39592
39605
  title: initialTitle,
39593
39606
  status: initialStatus,
39594
39607
  topic: _initialTopic,
@@ -39599,11 +39612,18 @@ var ResearchReportJobCard = (props) => {
39599
39612
  executive_summary: initialSummary,
39600
39613
  key_findings: _initialFindings,
39601
39614
  html_url: initialHtmlUrl,
39615
+ generation_mode: initialGenerationMode,
39616
+ template_id: initialTemplateId,
39617
+ template_version_id: initialTemplateVersionId,
39618
+ review_status: initialReviewStatus,
39602
39619
  theme: initialTheme,
39603
39620
  error: initialError,
39604
39621
  progress: initialProgress,
39605
39622
  pollUrl,
39606
39623
  authToken,
39624
+ shareUrl,
39625
+ approveUrl,
39626
+ regenerateUrl,
39607
39627
  className,
39608
39628
  onComplete,
39609
39629
  onFailed,
@@ -39618,11 +39638,23 @@ var ResearchReportJobCard = (props) => {
39618
39638
  const [wordCount, setWordCount] = useState11(initialWordCount ?? 0);
39619
39639
  const [summary, setSummary] = useState11(initialSummary || "");
39620
39640
  const [htmlUrl, setHtmlUrl] = useState11(initialHtmlUrl || "");
39641
+ const [generationMode, setGenerationMode] = useState11(
39642
+ initialGenerationMode || (initialHtmlUrl ? "template" : "")
39643
+ );
39644
+ const [templateId, setTemplateId] = useState11(initialTemplateId || "");
39645
+ const [templateVersionId, setTemplateVersionId] = useState11(initialTemplateVersionId || "");
39646
+ const [reviewStatus, setReviewStatus] = useState11(
39647
+ initialReviewStatus || (initialHtmlUrl ? "pending_review" : "")
39648
+ );
39621
39649
  const [theme, setTheme] = useState11(initialTheme || DEFAULT_THEME);
39622
39650
  const [error, setError] = useState11(initialError);
39623
39651
  const [progress, setProgress] = useState11(initialProgress);
39624
39652
  const [showPreview, setShowPreview] = useState11(false);
39625
39653
  const [previewScale, setPreviewScale] = useState11(1);
39654
+ const [copied, setCopied] = useState11(false);
39655
+ const [approving, setApproving] = useState11(false);
39656
+ const [regenerating, setRegenerating] = useState11(false);
39657
+ const [approveError, setApproveError] = useState11(null);
39626
39658
  const previewRef = useRef6(null);
39627
39659
  const intervalRef = useRef6(null);
39628
39660
  const onCompleteRef = useRef6(onComplete);
@@ -39640,6 +39672,18 @@ var ResearchReportJobCard = (props) => {
39640
39672
  useEffect7(() => {
39641
39673
  if (initialHtmlUrl) setHtmlUrl(initialHtmlUrl);
39642
39674
  }, [initialHtmlUrl]);
39675
+ useEffect7(() => {
39676
+ if (initialGenerationMode) setGenerationMode(initialGenerationMode);
39677
+ }, [initialGenerationMode]);
39678
+ useEffect7(() => {
39679
+ if (initialTemplateId) setTemplateId(initialTemplateId);
39680
+ }, [initialTemplateId]);
39681
+ useEffect7(() => {
39682
+ if (initialTemplateVersionId) setTemplateVersionId(initialTemplateVersionId);
39683
+ }, [initialTemplateVersionId]);
39684
+ useEffect7(() => {
39685
+ if (initialReviewStatus) setReviewStatus(initialReviewStatus);
39686
+ }, [initialReviewStatus]);
39643
39687
  useEffect7(() => {
39644
39688
  if (initialDepth) setDepth(initialDepth);
39645
39689
  }, [initialDepth]);
@@ -39707,6 +39751,10 @@ var ResearchReportJobCard = (props) => {
39707
39751
  setWordCount(output.word_count || 0);
39708
39752
  setSummary(output.executive_summary || "");
39709
39753
  setHtmlUrl(output.html_url || "");
39754
+ if (output.generation_mode) setGenerationMode(output.generation_mode);
39755
+ if (output.template_id) setTemplateId(output.template_id);
39756
+ if (output.template_version_id) setTemplateVersionId(output.template_version_id);
39757
+ if (output.review_status) setReviewStatus(output.review_status);
39710
39758
  if (output.theme) {
39711
39759
  setTheme(output.theme);
39712
39760
  }
@@ -39888,6 +39936,120 @@ var ResearchReportJobCard = (props) => {
39888
39936
  window.open(htmlUrl, "_blank", "noopener,noreferrer");
39889
39937
  }
39890
39938
  };
39939
+ const resolveShareLink = () => {
39940
+ if (shareUrl) return shareUrl;
39941
+ if (typeof window !== "undefined" && job_id) {
39942
+ return `${window.location.origin}/r/${job_id}`;
39943
+ }
39944
+ return htmlUrl;
39945
+ };
39946
+ const handleShare = async () => {
39947
+ const link = resolveShareLink();
39948
+ if (!link) return;
39949
+ try {
39950
+ await navigator.clipboard.writeText(link);
39951
+ setCopied(true);
39952
+ setTimeout(() => setCopied(false), 2e3);
39953
+ } catch {
39954
+ window.open(link, "_blank", "noopener,noreferrer");
39955
+ }
39956
+ };
39957
+ const canApprove = generationMode === "template" && reviewStatus === "pending_review" && Boolean(job_id);
39958
+ const canRegenerate = generationMode === "template" && reviewStatus === "pending_review" && Boolean(job_id);
39959
+ const canShare = Boolean(hasHTML || job_id) && (generationMode !== "template" || reviewStatus !== "pending_review");
39960
+ const handleApprove = async () => {
39961
+ if (!job_id || approving) return;
39962
+ const endpoint = approveUrl || `/api/reports/${job_id}/approve`;
39963
+ setApproving(true);
39964
+ setApproveError(null);
39965
+ try {
39966
+ const headers = { "Content-Type": "application/json" };
39967
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
39968
+ const res = await fetch(endpoint, {
39969
+ method: "POST",
39970
+ headers,
39971
+ body: JSON.stringify({ label: title })
39972
+ });
39973
+ if (!res.ok) {
39974
+ const err = await res.json().catch(() => ({}));
39975
+ throw new Error(err.detail || err.error || `Approve failed (${res.status})`);
39976
+ }
39977
+ const data = await res.json();
39978
+ const newStatus = data.review_status || "approved";
39979
+ setReviewStatus(newStatus);
39980
+ if (data.template_version_id) setTemplateVersionId(data.template_version_id);
39981
+ if (data.template_id) setTemplateId(data.template_id);
39982
+ if (onCompleteRef.current) {
39983
+ onCompleteRef.current({
39984
+ title,
39985
+ depth,
39986
+ section_count: sectionCount,
39987
+ source_count: sourceCount,
39988
+ word_count: wordCount,
39989
+ executive_summary: summary,
39990
+ html_url: htmlUrl,
39991
+ generation_mode: generationMode,
39992
+ template_id: data.template_id || templateId,
39993
+ template_version_id: data.template_version_id || templateVersionId,
39994
+ review_status: newStatus,
39995
+ theme
39996
+ });
39997
+ }
39998
+ } catch (e) {
39999
+ setApproveError(e instanceof Error ? e.message : "Could not save report version");
40000
+ } finally {
40001
+ setApproving(false);
40002
+ }
40003
+ };
40004
+ const handleRegenerate = async () => {
40005
+ if (!job_id || regenerating) return;
40006
+ const endpoint = regenerateUrl || `/api/reports/${job_id}/regenerate`;
40007
+ setRegenerating(true);
40008
+ setApproveError(null);
40009
+ try {
40010
+ const headers = { "Content-Type": "application/json" };
40011
+ if (authToken) headers.Authorization = `Bearer ${authToken}`;
40012
+ const res = await fetch(endpoint, {
40013
+ method: "POST",
40014
+ headers,
40015
+ body: JSON.stringify({})
40016
+ });
40017
+ if (!res.ok) {
40018
+ const err = await res.json().catch(() => ({}));
40019
+ throw new Error(err.detail || err.error || `Regenerate failed (${res.status})`);
40020
+ }
40021
+ const data = await res.json();
40022
+ const out = data.output || data;
40023
+ if (out.html_url) setHtmlUrl(out.html_url);
40024
+ if (data.template_id || out.template_id) setTemplateId(data.template_id || out.template_id);
40025
+ setReviewStatus("pending_review");
40026
+ setTemplateVersionId("");
40027
+ if (out.section_count !== void 0) setSectionCount(out.section_count);
40028
+ if (out.title) setTitle(out.title);
40029
+ if (onCompleteRef.current) {
40030
+ onCompleteRef.current({
40031
+ title: out.title || title,
40032
+ depth,
40033
+ section_count: out.section_count ?? sectionCount,
40034
+ source_count: sourceCount,
40035
+ word_count: wordCount,
40036
+ executive_summary: summary,
40037
+ html_url: out.html_url || htmlUrl,
40038
+ generation_mode: "template",
40039
+ template_id: data.template_id || out.template_id || templateId,
40040
+ template_version_id: void 0,
40041
+ review_status: "pending_review",
40042
+ theme
40043
+ });
40044
+ }
40045
+ } catch (e) {
40046
+ setApproveError(e instanceof Error ? e.message : "Could not switch template");
40047
+ } finally {
40048
+ setRegenerating(false);
40049
+ }
40050
+ };
40051
+ const templateLabel = formatTemplateLabel(templateId);
40052
+ const isApproved = reviewStatus === "approved";
39891
40053
  return /* @__PURE__ */ jsxs109(Fragment6, { children: [
39892
40054
  /* @__PURE__ */ jsx148("div", { className: cn("w-full", className), children: /* @__PURE__ */ jsxs109("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl overflow-hidden", children: [
39893
40055
  /* @__PURE__ */ jsx148(
@@ -39921,10 +40083,53 @@ var ResearchReportJobCard = (props) => {
39921
40083
  depth && sectionCount > 0 && " \xB7 ",
39922
40084
  sectionCount > 0 && `${sectionCount} sections`,
39923
40085
  sourceCount > 0 && ` \xB7 ${sourceCount} sources`,
39924
- wordCount > 0 && ` \xB7 ${formatWordCount(wordCount)} words`
39925
- ] })
40086
+ wordCount > 0 && ` \xB7 ${formatWordCount(wordCount)} words`,
40087
+ templateLabel && ` \xB7 ${templateLabel}`
40088
+ ] }),
40089
+ generationMode === "template" && /* @__PURE__ */ jsx148("p", { className: "text-xs mt-1", children: isApproved ? /* @__PURE__ */ jsx148("span", { className: "text-emerald-400/90", children: "Approved \u2014 future reports use this format" }) : reviewStatus === "pending_review" ? /* @__PURE__ */ jsx148("span", { className: "text-amber-400/90", children: "Review this report, then approve to lock the layout" }) : null })
39926
40090
  ] }),
39927
- /* @__PURE__ */ jsxs109("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
40091
+ /* @__PURE__ */ jsxs109("div", { className: "flex items-center gap-1.5 flex-shrink-0 flex-wrap justify-end", children: [
40092
+ canRegenerate && /* @__PURE__ */ jsxs109(
40093
+ "button",
40094
+ {
40095
+ onClick: handleRegenerate,
40096
+ disabled: regenerating || approving,
40097
+ title: "Try another report template with the same data",
40098
+ 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",
40099
+ children: [
40100
+ /* @__PURE__ */ jsx148(RefreshIcon, {}),
40101
+ /* @__PURE__ */ jsx148("span", { children: regenerating ? "Switching..." : "Regenerate" })
40102
+ ]
40103
+ }
40104
+ ),
40105
+ canApprove && /* @__PURE__ */ jsxs109(
40106
+ "button",
40107
+ {
40108
+ onClick: handleApprove,
40109
+ disabled: approving,
40110
+ title: "Approve and save this report format for future runs",
40111
+ 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",
40112
+ children: [
40113
+ /* @__PURE__ */ jsx148(CheckIcon2, {}),
40114
+ /* @__PURE__ */ jsx148("span", { children: approving ? "Saving..." : "Approve" })
40115
+ ]
40116
+ }
40117
+ ),
40118
+ isApproved && /* @__PURE__ */ jsx148("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__ */ jsx148(CheckIcon2, {}) }),
40119
+ /* @__PURE__ */ jsx148(
40120
+ "button",
40121
+ {
40122
+ onClick: handleShare,
40123
+ disabled: !canShare,
40124
+ title: !canShare && reviewStatus === "pending_review" ? "Approve the report to enable sharing" : copied ? "Copied!" : "Copy shareable link",
40125
+ className: cn(
40126
+ "w-7 h-7 rounded-lg border flex items-center justify-center transition-all",
40127
+ 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",
40128
+ "disabled:opacity-30 disabled:cursor-not-allowed"
40129
+ ),
40130
+ children: copied ? /* @__PURE__ */ jsx148(CheckIcon2, {}) : /* @__PURE__ */ jsx148(ShareIcon2, {})
40131
+ }
40132
+ ),
39928
40133
  /* @__PURE__ */ jsxs109(
39929
40134
  "button",
39930
40135
  {
@@ -39955,6 +40160,7 @@ var ResearchReportJobCard = (props) => {
39955
40160
  )
39956
40161
  ] })
39957
40162
  ] }),
40163
+ approveError && /* @__PURE__ */ jsx148("p", { className: "mt-3 text-xs text-red-400/90", children: approveError }),
39958
40164
  hasHTML && !compact && /* @__PURE__ */ jsx148("div", { className: "mt-4", children: /* @__PURE__ */ jsxs109(
39959
40165
  "div",
39960
40166
  {
@@ -43428,7 +43634,7 @@ function PlatformMetricsBanner({
43428
43634
  return /* @__PURE__ */ jsxs132(
43429
43635
  "div",
43430
43636
  {
43431
- 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 ",
43637
+ 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 ",
43432
43638
  style: { backgroundColor: bgColor },
43433
43639
  children: [
43434
43640
  /* @__PURE__ */ jsxs132("div", { className: "flex flex-col items-center md:min-w-0", children: [