@mvriu5/payload-ai 0.5.8 → 0.5.10

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.
Files changed (65) hide show
  1. package/README.md +62 -6
  2. package/dist/ai/{proposals.d.ts → proposalSigning.d.ts} +1 -1
  3. package/dist/ai/{proposals.js → proposalSigning.js} +6 -11
  4. package/dist/ai/providerOptions.d.ts +17 -1
  5. package/dist/ai/providerOptions.js +35 -7
  6. package/dist/ai/providerRuntime.d.ts +2 -2
  7. package/dist/ai/providerRuntime.js +50 -16
  8. package/dist/ai/sensitiveData.js +2 -6
  9. package/dist/components/AIInput.d.ts +2 -1
  10. package/dist/components/AIInput.js +327 -41
  11. package/dist/components/AIInput.module.css +41 -6
  12. package/dist/components/APIKeyField.d.ts +3 -0
  13. package/dist/components/{AIApiKeyField.js → APIKeyField.js} +3 -4
  14. package/dist/components/ActionToast.d.ts +30 -0
  15. package/dist/components/{AIActionProposalList.js → ActionToast.js} +78 -8
  16. package/dist/components/{AIActionProposalList.module.css → ActionToast.module.css} +49 -5
  17. package/dist/components/AuditLogList.d.ts +32 -0
  18. package/dist/components/AuditLogList.js +67 -0
  19. package/dist/components/AuditLogList.module.css +152 -0
  20. package/dist/components/DiffDialog.d.ts +19 -0
  21. package/dist/components/DiffDialog.js +396 -0
  22. package/dist/components/DiffDialog.module.css +333 -0
  23. package/dist/components/Icons.d.ts +9 -0
  24. package/dist/components/Icons.js +193 -0
  25. package/dist/components/MentionPopover.d.ts +19 -0
  26. package/dist/components/{CollectionMentionPopover.js → MentionPopover.js} +11 -4
  27. package/dist/components/{CollectionMentionPopover.module.css → MentionPopover.module.css} +0 -2
  28. package/dist/components/hooks/useAISettings.d.ts +6 -4
  29. package/dist/components/hooks/useAISettings.js +18 -3
  30. package/dist/components/hooks/useDocumentMentionSuggestions.d.ts +3 -3
  31. package/dist/components/hooks/useDocumentMentionSuggestions.js +2 -2
  32. package/dist/exports/client.d.ts +4 -2
  33. package/dist/exports/client.js +4 -2
  34. package/dist/handlers/applyActionHandler.d.ts +8 -0
  35. package/dist/handlers/applyActionHandler.js +563 -0
  36. package/dist/handlers/auditLogHandler.d.ts +6 -0
  37. package/dist/handlers/auditLogHandler.js +39 -0
  38. package/dist/handlers/chatHandler.d.ts +42 -0
  39. package/dist/handlers/chatHandler.js +634 -0
  40. package/dist/handlers/mentionSuggestionHandler.d.ts +7 -0
  41. package/dist/handlers/mentionSuggestionHandler.js +97 -0
  42. package/dist/handlers/proposalDiffHandler.d.ts +7 -0
  43. package/dist/handlers/proposalDiffHandler.js +208 -0
  44. package/dist/index.d.ts +6 -6
  45. package/dist/index.js +151 -8
  46. package/dist/payload/collectionPermissions.d.ts +14 -13
  47. package/dist/payload/collectionPermissions.js +3 -2
  48. package/dist/payload/normalizeData.d.ts +8 -0
  49. package/dist/payload/normalizeData.js +25 -3
  50. package/dist/payload/schemaContext.d.ts +79 -9
  51. package/dist/payload/schemaContext.js +231 -22
  52. package/dist/payload/shared.d.ts +33 -0
  53. package/dist/payload/shared.js +114 -0
  54. package/package.json +7 -2
  55. package/dist/components/AIActionProposalList.d.ts +0 -25
  56. package/dist/components/AIApiKeyField.d.ts +0 -2
  57. package/dist/components/CollectionMentionPopover.d.ts +0 -16
  58. package/dist/components/hooks/utils.d.ts +0 -1
  59. package/dist/components/hooks/utils.js +0 -3
  60. package/dist/endpoints/aiApplyActionEndpointHandler.d.ts +0 -7
  61. package/dist/endpoints/aiApplyActionEndpointHandler.js +0 -169
  62. package/dist/endpoints/aiChatEndpointHandler.d.ts +0 -35
  63. package/dist/endpoints/aiChatEndpointHandler.js +0 -321
  64. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.d.ts +0 -7
  65. package/dist/endpoints/aiMentionSuggestionsEndpointHandler.js +0 -63
@@ -0,0 +1,30 @@
1
+ export type ActionProposal = {
2
+ _aiSignature?: {
3
+ expiresAt: string;
4
+ value: string;
5
+ };
6
+ action: "create" | "delete" | "update" | "updateGlobal";
7
+ collection?: string;
8
+ id?: string;
9
+ label: string;
10
+ slug?: string;
11
+ };
12
+ type ActionToastProps = {
13
+ apiRoute: string;
14
+ appliedProposalIndexes: number[];
15
+ description?: string;
16
+ error?: string;
17
+ getViewURL?: (proposal: ActionProposal) => string | null;
18
+ isApplying: boolean;
19
+ onDismiss?: () => void;
20
+ onDismissError?: () => void;
21
+ onApply: (proposal: ActionProposal, index: number) => void;
22
+ proposals: ActionProposal[];
23
+ tokenUsage?: {
24
+ inputTokens?: number;
25
+ outputTokens?: number;
26
+ totalTokens?: number;
27
+ } | null;
28
+ };
29
+ export declare const ActionToast: ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals, tokenUsage, }: ActionToastProps) => import("react").JSX.Element | null;
30
+ export {};
@@ -1,5 +1,9 @@
1
- import styles from "./AIActionProposalList.module.css";
1
+ import styles from "./ActionToast.module.css";
2
2
  import { redactSensitiveData } from "../ai/sensitiveData.js";
3
+ import { formatAdminURL } from "payload/shared";
4
+ import { useState } from "react";
5
+ import { DiffDialog } from "./DiffDialog.js";
6
+ import { Apply, FileDiff, Reject } from "./Icons.js";
3
7
  const maxDescriptionLength = 220;
4
8
  const getDescriptionPreview = (description)=>{
5
9
  if (description.length <= maxDescriptionLength) return description;
@@ -15,10 +19,47 @@ const getSafeProposalDetails = (proposal)=>{
15
19
  }
16
20
  return redactedProposal;
17
21
  };
18
- export const AIActionProposalList = ({ appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals })=>{
22
+ export const ActionToast = ({ apiRoute, appliedProposalIndexes, description, error, getViewURL, isApplying, onDismiss, onDismissError, onApply, proposals, tokenUsage })=>{
23
+ const [activeDiff, setActiveDiff] = useState(null);
24
+ const [diffError, setDiffError] = useState("");
25
+ const [loadingDiffIndex, setLoadingDiffIndex] = useState(null);
19
26
  if (proposals.length === 0 && !error && !description) return null;
20
27
  const descriptionPreview = description ? getDescriptionPreview(description) : "";
21
28
  const isDescriptionTruncated = Boolean(description) && descriptionPreview !== description;
29
+ const openDiff = async (proposal, index)=>{
30
+ setDiffError("");
31
+ setLoadingDiffIndex(index);
32
+ try {
33
+ const res = await fetch(formatAdminURL({
34
+ apiRoute,
35
+ path: "/ai-proposal-diff"
36
+ }), {
37
+ body: JSON.stringify({
38
+ proposal
39
+ }),
40
+ headers: {
41
+ "Content-Type": "application/json"
42
+ },
43
+ method: "POST"
44
+ });
45
+ const result = await res.json().catch(()=>null);
46
+ if (!res.ok || !result) {
47
+ throw new Error(result?.error || "Could not load proposal diff.");
48
+ }
49
+ setActiveDiff({
50
+ change: null,
51
+ diff: {
52
+ after: result.after,
53
+ before: result.before
54
+ },
55
+ proposal
56
+ });
57
+ } catch (err) {
58
+ setDiffError(err instanceof Error ? err.message : "Could not load proposal diff.");
59
+ } finally{
60
+ setLoadingDiffIndex(null);
61
+ }
62
+ };
22
63
  return /*#__PURE__*/ React.createElement("div", {
23
64
  className: styles.list
24
65
  }, error && /*#__PURE__*/ React.createElement("div", {
@@ -37,13 +78,13 @@ export const AIActionProposalList = ({ appliedProposalIndexes, description, erro
37
78
  className: styles.label
38
79
  }, "AI response"), /*#__PURE__*/ React.createElement("div", {
39
80
  className: styles.description
40
- }, descriptionPreview), isDescriptionTruncated ? /*#__PURE__*/ React.createElement("details", {
81
+ }, descriptionPreview), isDescriptionTruncated && /*#__PURE__*/ React.createElement("details", {
41
82
  className: styles.details
42
83
  }, /*#__PURE__*/ React.createElement("summary", {
43
84
  className: styles.summary
44
85
  }, "Full response"), /*#__PURE__*/ React.createElement("pre", {
45
86
  className: styles.proposalDetails
46
- }, description)) : null)), proposals.map((proposal, index)=>{
87
+ }, description)))), proposals.map((proposal, index)=>{
47
88
  const isApplied = appliedProposalIndexes.includes(index);
48
89
  const viewURL = getViewURL?.(proposal);
49
90
  return /*#__PURE__*/ React.createElement("div", {
@@ -73,22 +114,51 @@ export const AIActionProposalList = ({ appliedProposalIndexes, description, erro
73
114
  className: styles.footer
74
115
  }, /*#__PURE__*/ React.createElement("div", {
75
116
  className: styles.viewAction
76
- }, viewURL && /*#__PURE__*/ React.createElement("a", {
117
+ }, /*#__PURE__*/ React.createElement("button", {
77
118
  className: styles.secondaryButton,
119
+ disabled: loadingDiffIndex === index,
120
+ onClick: ()=>void openDiff(proposal, index),
121
+ type: "button"
122
+ }, /*#__PURE__*/ React.createElement(FileDiff, {
123
+ height: 16,
124
+ width: 16
125
+ }), loadingDiffIndex === index ? "Loading" : "Review"), viewURL && /*#__PURE__*/ React.createElement("a", {
126
+ className: styles.ghostButton,
78
127
  href: viewURL,
79
128
  rel: "noreferrer noopener",
80
129
  target: "_blank"
81
- }, "View")), /*#__PURE__*/ React.createElement("div", {
130
+ }, "Go to source")), /*#__PURE__*/ React.createElement("div", {
82
131
  className: styles.actions
83
132
  }, onDismiss && /*#__PURE__*/ React.createElement("button", {
84
133
  className: styles.secondaryButton,
85
134
  onClick: onDismiss,
86
135
  type: "button"
87
- }, "Dismiss"), /*#__PURE__*/ React.createElement("button", {
136
+ }, /*#__PURE__*/ React.createElement(Reject, {
137
+ height: 16,
138
+ width: 16
139
+ })), /*#__PURE__*/ React.createElement("button", {
88
140
  className: styles.button,
89
141
  disabled: isApplying || isApplied,
90
142
  onClick: ()=>onApply(proposal, index),
91
143
  type: "button"
92
- }, isApplied ? "Applied" : "Apply"))));
144
+ }, /*#__PURE__*/ React.createElement(Apply, {
145
+ height: 16,
146
+ width: 16
147
+ })))));
148
+ }), diffError && /*#__PURE__*/ React.createElement("div", {
149
+ className: `${styles.item} ${styles.errorItem}`
150
+ }, /*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement("div", {
151
+ className: styles.label
152
+ }, "Diff review failed"), /*#__PURE__*/ React.createElement("div", {
153
+ className: styles.description
154
+ }, diffError)), /*#__PURE__*/ React.createElement("button", {
155
+ className: styles.button,
156
+ onClick: ()=>setDiffError(""),
157
+ type: "button"
158
+ }, "Dismiss")), activeDiff && /*#__PURE__*/ React.createElement(DiffDialog, {
159
+ diff: activeDiff.diff,
160
+ onClose: ()=>setActiveDiff(null),
161
+ proposal: activeDiff.proposal,
162
+ tokenUsage: tokenUsage || undefined
93
163
  }));
94
164
  };
@@ -94,6 +94,7 @@
94
94
  .viewAction {
95
95
  align-items: center;
96
96
  display: flex;
97
+ gap: 8px;
97
98
  min-width: 0;
98
99
  }
99
100
 
@@ -106,37 +107,74 @@
106
107
  }
107
108
 
108
109
  .button {
110
+ align-items: center;
109
111
  background: var(--theme-text);
110
112
  border: 0;
111
113
  border-radius: 4px;
112
114
  color: var(--theme-bg);
113
115
  cursor: pointer;
116
+ display: inline-flex;
114
117
  flex: 0 0 auto;
115
118
  font: inherit;
116
- min-height: 34px;
119
+ gap: 6px;
120
+ justify-content: center;
121
+ line-height: 24px;
122
+ min-height: 24px;
117
123
  padding: 0 14px;
118
124
  }
119
125
 
120
126
  .secondaryButton {
127
+ align-items: center;
121
128
  background: transparent;
122
129
  border: 1px solid var(--theme-elevation-150);
123
130
  border-radius: 4px;
124
131
  color: var(--theme-text);
125
132
  cursor: pointer;
133
+ display: inline-flex;
126
134
  flex: 0 0 auto;
127
135
  font: inherit;
128
- line-height: 34px;
129
- min-height: 34px;
136
+ gap: 6px;
137
+ justify-content: center;
138
+ line-height: 24px;
139
+ min-height: 24px;
130
140
  padding: 0 14px;
131
141
  text-decoration: none;
132
142
  }
133
143
 
144
+ .secondaryButton svg {
145
+ color: var(--theme-elevation-500);
146
+ flex: 0 0 auto;
147
+ }
148
+
149
+ .button svg {
150
+ flex: 0 0 auto;
151
+ }
152
+
153
+ .ghostButton {
154
+ background: transparent;
155
+ border: 0;
156
+ border-radius: 4px;
157
+ color: var(--theme-elevation-600);
158
+ cursor: pointer;
159
+ flex: 0 0 auto;
160
+ font: inherit;
161
+ line-height: 24px;
162
+ min-height: 24px;
163
+ padding: 0 10px;
164
+ text-decoration: none;
165
+ }
166
+
167
+ .ghostButton:hover {
168
+ text-decoration: underline;
169
+ }
170
+
134
171
  .button:disabled {
135
172
  cursor: not-allowed;
136
173
  opacity: 0.45;
137
174
  }
138
175
 
139
- .secondaryButton:disabled {
176
+ .secondaryButton:disabled,
177
+ .ghostButton:disabled {
140
178
  cursor: not-allowed;
141
179
  opacity: 0.45;
142
180
  }
@@ -163,13 +201,19 @@
163
201
  flex-direction: column;
164
202
  }
165
203
 
204
+ .viewAction {
205
+ align-self: stretch;
206
+ flex-direction: column;
207
+ }
208
+
166
209
  .footer {
167
210
  align-items: stretch;
168
211
  flex-direction: column;
169
212
  }
170
213
 
171
214
  .button,
172
- .secondaryButton {
215
+ .secondaryButton,
216
+ .ghostButton {
173
217
  width: 100%;
174
218
  }
175
219
  }
@@ -0,0 +1,32 @@
1
+ import type { ActionProposal } from "./ActionToast.js";
2
+ import { type ProposalDiff } from "./DiffDialog.js";
3
+ export type AppliedChange = {
4
+ action?: ActionProposal["action"] | null;
5
+ additions: number;
6
+ after?: unknown;
7
+ before?: unknown;
8
+ collection?: string | null;
9
+ createdAt?: string | null;
10
+ documentID?: string | null;
11
+ inputTokens?: number | null;
12
+ outputTokens?: number | null;
13
+ removals: number;
14
+ slug?: string | null;
15
+ targetType?: string | null;
16
+ totalTokens?: number | null;
17
+ title: string;
18
+ userID?: string | null;
19
+ userLabel?: string | null;
20
+ url?: string | null;
21
+ };
22
+ type AuditLogListProps = {
23
+ allChangesURL?: string;
24
+ changes: AppliedChange[];
25
+ };
26
+ export type ActiveDiff = {
27
+ change: AppliedChange | null;
28
+ diff: ProposalDiff;
29
+ proposal: ActionProposal;
30
+ };
31
+ export declare const RecentChangesList: ({ allChangesURL, changes }: AuditLogListProps) => import("react").JSX.Element;
32
+ export {};
@@ -0,0 +1,67 @@
1
+ import { useState } from "react";
2
+ import { ExternalLinkIcon } from "@payloadcms/ui";
3
+ import { DiffDialog } from "./DiffDialog.js";
4
+ import styles from "./AuditLogList.module.css";
5
+ const getChangeProposal = (change)=>({
6
+ action: change.action || "update",
7
+ collection: change.collection || undefined,
8
+ id: change.documentID || undefined,
9
+ label: change.title,
10
+ slug: change.slug || undefined
11
+ });
12
+ export const RecentChangesList = ({ allChangesURL, changes })=>{
13
+ const [activeDiff, setActiveDiff] = useState(null);
14
+ return /*#__PURE__*/ React.createElement("aside", {
15
+ className: styles.recentChanges
16
+ }, /*#__PURE__*/ React.createElement("div", {
17
+ className: styles.header
18
+ }, /*#__PURE__*/ React.createElement("h3", {
19
+ className: styles.title
20
+ }, "Recent changes"), allChangesURL && /*#__PURE__*/ React.createElement("a", {
21
+ className: styles.headerGhostButton,
22
+ href: allChangesURL
23
+ }, "View all")), /*#__PURE__*/ React.createElement("div", {
24
+ className: styles.list
25
+ }, changes.length === 0 ? /*#__PURE__*/ React.createElement("div", {
26
+ className: styles.empty
27
+ }, "No changes yet.") : changes.map((change, index)=>/*#__PURE__*/ React.createElement("div", {
28
+ className: styles.item,
29
+ key: `${change.title}-${index}`
30
+ }, /*#__PURE__*/ React.createElement("div", {
31
+ className: styles.titleRow
32
+ }, /*#__PURE__*/ React.createElement("div", {
33
+ className: styles.itemTitle
34
+ }, change.title), change.url && /*#__PURE__*/ React.createElement("a", {
35
+ className: styles.ghostButton,
36
+ href: change.url,
37
+ rel: "noreferrer noopener",
38
+ target: "_blank"
39
+ }, /*#__PURE__*/ React.createElement(ExternalLinkIcon, null))), /*#__PURE__*/ React.createElement("div", {
40
+ className: styles.stats
41
+ }, /*#__PURE__*/ React.createElement("code", {
42
+ className: styles.additions
43
+ }, "+", change.additions), /*#__PURE__*/ React.createElement("code", {
44
+ className: styles.removals
45
+ }, "-", change.removals)), /*#__PURE__*/ React.createElement("button", {
46
+ className: styles.button,
47
+ onClick: ()=>{
48
+ if (change.before === undefined || change.after === undefined) {
49
+ return;
50
+ }
51
+ setActiveDiff({
52
+ change,
53
+ diff: {
54
+ after: change.after,
55
+ before: change.before
56
+ },
57
+ proposal: getChangeProposal(change)
58
+ });
59
+ },
60
+ type: "button"
61
+ }, "Review")))), activeDiff && activeDiff.change && /*#__PURE__*/ React.createElement(DiffDialog, {
62
+ change: activeDiff.change,
63
+ diff: activeDiff.diff,
64
+ onClose: ()=>setActiveDiff(null),
65
+ proposal: activeDiff.proposal
66
+ }));
67
+ };
@@ -0,0 +1,152 @@
1
+ .recentChanges {
2
+ border: 1px solid var(--theme-elevation-150);
3
+ border-radius: 8px;
4
+ display: flex;
5
+ flex-direction: column;
6
+ min-height: 0;
7
+ padding: 16px;
8
+ }
9
+
10
+ .header {
11
+ align-items: center;
12
+ display: flex;
13
+ flex: 0 0 auto;
14
+ gap: 10px;
15
+ justify-content: space-between;
16
+ margin-bottom: 10px;
17
+ }
18
+
19
+ .headerGhostButton {
20
+ color: var(--theme-elevation-500);
21
+ flex: 0 0 auto;
22
+ font-size: 12px;
23
+ line-height: 24px;
24
+ min-height: 24px;
25
+ text-decoration: none;
26
+ }
27
+
28
+ .headerGhostButton:hover {
29
+ text-decoration: underline;
30
+ }
31
+
32
+ .title {
33
+ font-size: 14px;
34
+ line-height: 1.3;
35
+ margin: 0;
36
+ }
37
+
38
+ .list {
39
+ display: flex;
40
+ flex: 1 1 auto;
41
+ flex-direction: column;
42
+ gap: 8px;
43
+ max-height: 260px;
44
+ min-height: 0;
45
+ overflow: auto;
46
+ padding-right: 2px;
47
+ }
48
+
49
+ .empty {
50
+ color: var(--theme-elevation-500);
51
+ font-size: 12px;
52
+ line-height: 1.4;
53
+ }
54
+
55
+ .item {
56
+ align-items: center;
57
+ border: 1px solid var(--theme-elevation-100);
58
+ border-radius: 4px;
59
+ display: grid;
60
+ gap: 8px;
61
+ grid-template-columns: minmax(0, 1fr) auto auto;
62
+ padding: 4px 4px 4px 8px;
63
+ }
64
+
65
+ .titleRow {
66
+ align-items: center;
67
+ display: flex;
68
+ gap: 8px;
69
+ min-width: 0;
70
+ }
71
+
72
+ .itemTitle {
73
+ color: var(--theme-text);
74
+ flex: 0 1 auto;
75
+ font-size: 12px;
76
+ font-weight: 600;
77
+ line-height: 1.4;
78
+ min-width: 0;
79
+ overflow: hidden;
80
+ text-overflow: ellipsis;
81
+ white-space: nowrap;
82
+ }
83
+
84
+ .stats {
85
+ display: flex;
86
+ gap: 6px;
87
+ justify-content: flex-end;
88
+ }
89
+
90
+ .additions,
91
+ .removals {
92
+ border-radius: 3px;
93
+ font-size: 11px;
94
+ line-height: 18px;
95
+ padding: 0 5px;
96
+ }
97
+
98
+ .additions {
99
+ background: rgba(39, 132, 90, 0.16);
100
+ color: #27845a;
101
+ }
102
+
103
+ .removals {
104
+ background: rgba(160, 26, 26, 0.16);
105
+ color: #a01a1a;
106
+ }
107
+
108
+ .button {
109
+ align-items: center;
110
+ background: var(--theme-elevation-0);
111
+ border: 1px solid var(--theme-elevation-150);
112
+ border-radius: 4px;
113
+ color: var(--theme-text);
114
+ cursor: pointer;
115
+ display: inline-flex;
116
+ font-size: 12px;
117
+ gap: 6px;
118
+ justify-content: center;
119
+ line-height: 24px;
120
+ min-height: 24px;
121
+ padding: 0 10px;
122
+ text-align: center;
123
+ text-decoration: none;
124
+ }
125
+
126
+ .button:disabled {
127
+ color: var(--theme-elevation-400);
128
+ cursor: not-allowed;
129
+ }
130
+
131
+ .button svg {
132
+ color: var(--theme-elevation-500);
133
+ flex: 0 0 auto;
134
+ }
135
+
136
+ .ghostButton {
137
+ color: var(--theme-elevation-500);
138
+ flex: 0 0 auto;
139
+ font-size: 12px;
140
+ line-height: 18px;
141
+ text-decoration: none;
142
+ }
143
+
144
+ .ghostButton:hover {
145
+ text-decoration: underline;
146
+ }
147
+
148
+ @media (max-width: 768px) {
149
+ .list {
150
+ max-height: 220px;
151
+ }
152
+ }
@@ -0,0 +1,19 @@
1
+ import type { ActionProposal } from "./ActionToast.js";
2
+ import type { AppliedChange } from "./AuditLogList.js";
3
+ export type ProposalDiff = {
4
+ after: unknown;
5
+ before: unknown;
6
+ };
7
+ type DiffDialogProps = {
8
+ change?: AppliedChange;
9
+ diff: ProposalDiff;
10
+ onClose: () => void;
11
+ proposal: ActionProposal;
12
+ tokenUsage?: {
13
+ inputTokens?: number;
14
+ outputTokens?: number;
15
+ totalTokens?: number;
16
+ };
17
+ };
18
+ export declare const DiffDialog: ({ change, diff, onClose, proposal, tokenUsage }: DiffDialogProps) => import("react").JSX.Element;
19
+ export {};