@humaan/payload-plugin-ai-assistant 0.0.0-stage → 0.1.0

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 (190) hide show
  1. package/README.md +277 -2
  2. package/dist/admin/AiAssistantControl.d.ts +11 -0
  3. package/dist/admin/AiAssistantControl.js +31 -0
  4. package/dist/admin/AiAssistantControl.js.map +1 -0
  5. package/dist/admin/AiAssistantPanel.d.ts +10 -0
  6. package/dist/admin/AiAssistantPanel.js +208 -0
  7. package/dist/admin/AiAssistantPanel.js.map +1 -0
  8. package/dist/admin/AiAssistantPanel.module.scss +689 -0
  9. package/dist/admin/AiSourceSwitch.d.ts +13 -0
  10. package/dist/admin/AiSourceSwitch.js +14 -0
  11. package/dist/admin/AiSourceSwitch.js.map +1 -0
  12. package/dist/admin/BudgetField.d.ts +8 -0
  13. package/dist/admin/BudgetField.js +145 -0
  14. package/dist/admin/BudgetField.js.map +1 -0
  15. package/dist/admin/BudgetField.module.scss +47 -0
  16. package/dist/admin/Conversation.d.ts +12 -0
  17. package/dist/admin/Conversation.js +469 -0
  18. package/dist/admin/Conversation.js.map +1 -0
  19. package/dist/admin/Markdown.d.ts +9 -0
  20. package/dist/admin/Markdown.js +63 -0
  21. package/dist/admin/Markdown.js.map +1 -0
  22. package/dist/admin/PageContextBridge.d.ts +5 -0
  23. package/dist/admin/PageContextBridge.js +72 -0
  24. package/dist/admin/PageContextBridge.js.map +1 -0
  25. package/dist/admin/Pill.d.ts +11 -0
  26. package/dist/admin/Pill.js +27 -0
  27. package/dist/admin/Pill.js.map +1 -0
  28. package/dist/admin/PlanCard.d.ts +14 -0
  29. package/dist/admin/PlanCard.js +465 -0
  30. package/dist/admin/PlanCard.js.map +1 -0
  31. package/dist/admin/SettingsAlerts.d.ts +7 -0
  32. package/dist/admin/SettingsAlerts.js +37 -0
  33. package/dist/admin/SettingsAlerts.js.map +1 -0
  34. package/dist/admin/UsageSummary.d.ts +11 -0
  35. package/dist/admin/UsageSummary.js +129 -0
  36. package/dist/admin/UsageSummary.js.map +1 -0
  37. package/dist/admin/attachmentUpload.d.ts +25 -0
  38. package/dist/admin/attachmentUpload.js +76 -0
  39. package/dist/admin/attachmentUpload.js.map +1 -0
  40. package/dist/admin/openDocument.d.ts +13 -0
  41. package/dist/admin/openDocument.js +34 -0
  42. package/dist/admin/openDocument.js.map +1 -0
  43. package/dist/admin/percent.d.ts +10 -0
  44. package/dist/admin/percent.js +21 -0
  45. package/dist/admin/percent.js.map +1 -0
  46. package/dist/admin/threads.d.ts +21 -0
  47. package/dist/admin/threads.js +92 -0
  48. package/dist/admin/threads.js.map +1 -0
  49. package/dist/admin/toolSteps.d.ts +12 -0
  50. package/dist/admin/toolSteps.js +57 -0
  51. package/dist/admin/toolSteps.js.map +1 -0
  52. package/dist/admin/transport.d.ts +24 -0
  53. package/dist/admin/transport.js +75 -0
  54. package/dist/admin/transport.js.map +1 -0
  55. package/dist/admin/useAttachments.d.ts +32 -0
  56. package/dist/admin/useAttachments.js +91 -0
  57. package/dist/admin/useAttachments.js.map +1 -0
  58. package/dist/admin/useEntityLabel.d.ts +3 -0
  59. package/dist/admin/useEntityLabel.js +23 -0
  60. package/dist/admin/useEntityLabel.js.map +1 -0
  61. package/dist/attachments/collection.d.ts +15 -0
  62. package/dist/attachments/collection.js +90 -0
  63. package/dist/attachments/collection.js.map +1 -0
  64. package/dist/attachments/conversation.d.ts +25 -0
  65. package/dist/attachments/conversation.js +105 -0
  66. package/dist/attachments/conversation.js.map +1 -0
  67. package/dist/attachments/rules.d.ts +9 -0
  68. package/dist/attachments/rules.js +17 -0
  69. package/dist/attachments/rules.js.map +1 -0
  70. package/dist/attachments/store.d.ts +27 -0
  71. package/dist/attachments/store.js +187 -0
  72. package/dist/attachments/store.js.map +1 -0
  73. package/dist/billing.d.ts +60 -0
  74. package/dist/billing.js +116 -0
  75. package/dist/billing.js.map +1 -0
  76. package/dist/chat/history.d.ts +37 -0
  77. package/dist/chat/history.js +165 -0
  78. package/dist/chat/history.js.map +1 -0
  79. package/dist/chat/messages.d.ts +5 -0
  80. package/dist/chat/messages.js +3 -0
  81. package/dist/chat/messages.js.map +1 -0
  82. package/dist/chat/threads.d.ts +33 -0
  83. package/dist/chat/threads.js +77 -0
  84. package/dist/chat/threads.js.map +1 -0
  85. package/dist/chat/tools.d.ts +76 -0
  86. package/dist/chat/tools.js +596 -0
  87. package/dist/chat/tools.js.map +1 -0
  88. package/dist/chat/usage.d.ts +66 -0
  89. package/dist/chat/usage.js +219 -0
  90. package/dist/chat/usage.js.map +1 -0
  91. package/dist/collectionAccess.d.ts +6 -0
  92. package/dist/collectionAccess.js +32 -0
  93. package/dist/collectionAccess.js.map +1 -0
  94. package/dist/constants.d.ts +64 -0
  95. package/dist/constants.js +51 -0
  96. package/dist/constants.js.map +1 -0
  97. package/dist/endpoints/access.d.ts +4 -0
  98. package/dist/endpoints/access.js +28 -0
  99. package/dist/endpoints/access.js.map +1 -0
  100. package/dist/endpoints/allowance.d.ts +22 -0
  101. package/dist/endpoints/allowance.js +37 -0
  102. package/dist/endpoints/allowance.js.map +1 -0
  103. package/dist/endpoints/applyEndpoint.d.ts +12 -0
  104. package/dist/endpoints/applyEndpoint.js +170 -0
  105. package/dist/endpoints/applyEndpoint.js.map +1 -0
  106. package/dist/endpoints/budget.d.ts +30 -0
  107. package/dist/endpoints/budget.js +153 -0
  108. package/dist/endpoints/budget.js.map +1 -0
  109. package/dist/endpoints/chatEndpoint.d.ts +12 -0
  110. package/dist/endpoints/chatEndpoint.js +295 -0
  111. package/dist/endpoints/chatEndpoint.js.map +1 -0
  112. package/dist/endpoints/form.d.ts +23 -0
  113. package/dist/endpoints/form.js +95 -0
  114. package/dist/endpoints/form.js.map +1 -0
  115. package/dist/endpoints/usageEndpoint.d.ts +13 -0
  116. package/dist/endpoints/usageEndpoint.js +70 -0
  117. package/dist/endpoints/usageEndpoint.js.map +1 -0
  118. package/dist/index.d.ts +4 -0
  119. package/dist/index.js +5 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/lexical/editorConfig.d.ts +4 -0
  122. package/dist/lexical/editorConfig.js +19 -0
  123. package/dist/lexical/editorConfig.js.map +1 -0
  124. package/dist/lexical/lexicalToMarkdown.d.ts +10 -0
  125. package/dist/lexical/lexicalToMarkdown.js +10 -0
  126. package/dist/lexical/lexicalToMarkdown.js.map +1 -0
  127. package/dist/lexical/markdownToLexical.d.ts +7 -0
  128. package/dist/lexical/markdownToLexical.js +10 -0
  129. package/dist/lexical/markdownToLexical.js.map +1 -0
  130. package/dist/plan/allowed.d.ts +7 -0
  131. package/dist/plan/allowed.js +19 -0
  132. package/dist/plan/allowed.js.map +1 -0
  133. package/dist/plan/applyPlan.d.ts +16 -0
  134. package/dist/plan/applyPlan.js +353 -0
  135. package/dist/plan/applyPlan.js.map +1 -0
  136. package/dist/plan/catalogue.d.ts +37 -0
  137. package/dist/plan/catalogue.js +157 -0
  138. package/dist/plan/catalogue.js.map +1 -0
  139. package/dist/plan/diff.d.ts +13 -0
  140. package/dist/plan/diff.js +87 -0
  141. package/dist/plan/diff.js.map +1 -0
  142. package/dist/plan/parsePlan.d.ts +27 -0
  143. package/dist/plan/parsePlan.js +322 -0
  144. package/dist/plan/parsePlan.js.map +1 -0
  145. package/dist/plan/prompt.d.ts +1 -0
  146. package/dist/plan/prompt.js +45 -0
  147. package/dist/plan/prompt.js.map +1 -0
  148. package/dist/plan/stored.d.ts +53 -0
  149. package/dist/plan/stored.js +3 -0
  150. package/dist/plan/stored.js.map +1 -0
  151. package/dist/plan/tokens.d.ts +8 -0
  152. package/dist/plan/tokens.js +79 -0
  153. package/dist/plan/tokens.js.map +1 -0
  154. package/dist/plan/view.d.ts +4 -0
  155. package/dist/plan/view.js +43 -0
  156. package/dist/plan/view.js.map +1 -0
  157. package/dist/plugin.d.ts +3 -0
  158. package/dist/plugin.js +464 -0
  159. package/dist/plugin.js.map +1 -0
  160. package/dist/read/outline.d.ts +7 -0
  161. package/dist/read/outline.js +70 -0
  162. package/dist/read/outline.js.map +1 -0
  163. package/dist/read/readTarget.d.ts +4 -0
  164. package/dist/read/readTarget.js +13 -0
  165. package/dist/read/readTarget.js.map +1 -0
  166. package/dist/read/readable.d.ts +8 -0
  167. package/dist/read/readable.js +131 -0
  168. package/dist/read/readable.js.map +1 -0
  169. package/dist/runtime.d.ts +15 -0
  170. package/dist/runtime.js +14 -0
  171. package/dist/runtime.js.map +1 -0
  172. package/dist/schema/fields.d.ts +113 -0
  173. package/dist/schema/fields.js +1036 -0
  174. package/dist/schema/fields.js.map +1 -0
  175. package/dist/schema/listingFields.d.ts +9 -0
  176. package/dist/schema/listingFields.js +95 -0
  177. package/dist/schema/listingFields.js.map +1 -0
  178. package/dist/schema/slugify.d.ts +2 -0
  179. package/dist/schema/slugify.js +5 -0
  180. package/dist/schema/slugify.js.map +1 -0
  181. package/dist/settings.d.ts +10 -0
  182. package/dist/settings.js +54 -0
  183. package/dist/settings.js.map +1 -0
  184. package/dist/types.d.ts +198 -0
  185. package/dist/types.js +6 -0
  186. package/dist/types.js.map +1 -0
  187. package/dist/uploads/routeAsset.d.ts +27 -0
  188. package/dist/uploads/routeAsset.js +127 -0
  189. package/dist/uploads/routeAsset.js.map +1 -0
  190. package/package.json +122 -3
@@ -0,0 +1,165 @@
1
+ import { isToolUIPart } from 'ai';
2
+ import { maxThreadTitleCharacters } from '../constants.js';
3
+ const omitted = {
4
+ omitted: 'This older result was removed to save space. Call the tool again if you need it.'
5
+ };
6
+ /**
7
+ * Read results from older turns are the bulk of a long conversation. Plans stay, because later turns refer to them.
8
+ */ export function pruneToolResults(messages, keepTurns) {
9
+ const userIndexes = messages.flatMap((message, index)=>message.role === 'user' ? [
10
+ index
11
+ ] : []);
12
+ if (userIndexes.length <= keepTurns) {
13
+ return messages;
14
+ }
15
+ const cutoff = userIndexes[userIndexes.length - keepTurns];
16
+ return messages.map((message, index)=>{
17
+ if (index >= cutoff || message.role !== 'assistant') {
18
+ return message;
19
+ }
20
+ return {
21
+ ...message,
22
+ parts: message.parts.map((part)=>isToolUIPart(part) && part.type !== 'tool-submitPlan' && part.state === 'output-available' ? {
23
+ ...part,
24
+ output: omitted
25
+ } : part)
26
+ };
27
+ });
28
+ }
29
+ /**
30
+ * The JSON field stores an undefined property as null. The message schema allows a missing property but not null,
31
+ * so a stored thread would fail validation on the next turn. Values inside tool inputs and outputs are left alone.
32
+ * Empty assistant replies are dropped.
33
+ */ export function restoreStoredMessages(messages) {
34
+ return messages.flatMap((message)=>{
35
+ if (!isRecord(message) || !Array.isArray(message.parts)) {
36
+ return [];
37
+ }
38
+ // A reply that failed before it said anything has no parts, and the model API rejects an empty turn.
39
+ if (message.role === 'assistant' && message.parts.length === 0) {
40
+ return [];
41
+ }
42
+ const restored = withoutNulls(message);
43
+ restored.parts = message.parts.filter(isRecord).map(withoutNulls);
44
+ if (isRecord(message.metadata)) {
45
+ restored.metadata = withoutNulls(message.metadata);
46
+ }
47
+ return [
48
+ restored
49
+ ];
50
+ });
51
+ }
52
+ /**
53
+ * Adds what the model needs to know about each user message: the open document and its attachments.
54
+ * This is added for the model run only. The stored thread keeps what the editor typed.
55
+ */ export function withTurnContext(messages, context) {
56
+ const lastUser = messages.map((message)=>message.role).lastIndexOf('user');
57
+ return messages.map((message, index)=>{
58
+ if (message.role !== 'user') {
59
+ return message;
60
+ }
61
+ const notes = [];
62
+ if (message.metadata?.context) {
63
+ notes.push(contextNote(message.metadata.context));
64
+ }
65
+ const attachments = message.metadata?.attachments ?? [];
66
+ const fileParts = [];
67
+ for (const attachment of attachments){
68
+ const file = context.files.find((item)=>item.index === attachment.index);
69
+ notes.push(file ? attachmentNote(file) : `Attachment index ${attachment.index}: ${attachment.name}. No longer available.`);
70
+ const part = file ? context.fileParts.get(file.index) : undefined;
71
+ if (part) {
72
+ fileParts.push(part);
73
+ }
74
+ }
75
+ if (index === lastUser && context.openDocument) {
76
+ notes.push(`Outline of the open document, including unsaved changes. Text is cut and each block is one line. Call readDocument with a path for full values:\n${context.openDocument}`);
77
+ }
78
+ if (notes.length === 0 && fileParts.length === 0) {
79
+ return message;
80
+ }
81
+ const note = {
82
+ type: 'text',
83
+ text: `<editor-context>\n${notes.join('\n')}\n</editor-context>`
84
+ };
85
+ return {
86
+ ...message,
87
+ parts: [
88
+ note,
89
+ ...message.parts,
90
+ ...fileParts
91
+ ]
92
+ };
93
+ });
94
+ }
95
+ /** Records what the editor did with a plan, so the card and the model both see it. */ export function markPlan(messages, planId, update) {
96
+ let changed = false;
97
+ const next = messages.map((message)=>{
98
+ if (message.role !== 'assistant') {
99
+ return message;
100
+ }
101
+ let touched = false;
102
+ const parts = message.parts.map((part)=>{
103
+ if (part.type !== 'tool-submitPlan' || part.state !== 'output-available') {
104
+ return part;
105
+ }
106
+ if (!part.output.ok || part.output.plan.id !== planId) {
107
+ return part;
108
+ }
109
+ touched = true;
110
+ return {
111
+ ...part,
112
+ output: {
113
+ ...part.output,
114
+ ...update
115
+ }
116
+ };
117
+ });
118
+ if (!touched) {
119
+ return message;
120
+ }
121
+ changed = true;
122
+ return {
123
+ ...message,
124
+ parts
125
+ };
126
+ });
127
+ return {
128
+ messages: next,
129
+ changed
130
+ };
131
+ }
132
+ export function messageText(message) {
133
+ return message.parts.flatMap((part)=>part.type === 'text' ? [
134
+ part.text
135
+ ] : []).join('\n').trim();
136
+ }
137
+ export function threadTitle(text) {
138
+ const line = text.replace(/\s+/g, ' ').trim();
139
+ if (!line) {
140
+ return 'Attached files';
141
+ }
142
+ if (line.length <= maxThreadTitleCharacters) {
143
+ return line;
144
+ }
145
+ return `${line.slice(0, maxThreadTitleCharacters - 1).trimEnd()}…`;
146
+ }
147
+ function contextNote(context) {
148
+ const id = context.id ? `, id ${context.id}` : '';
149
+ return `Open in the editor when this was sent: ${context.label} (${context.kind} ${context.slug}${id}).`;
150
+ }
151
+ function attachmentNote(file) {
152
+ if (!file.collection) {
153
+ return `Attachment index ${file.index}: ${file.name} (${file.type}). It can be read, but not saved: no upload collection the assistant may change accepts it.`;
154
+ }
155
+ const saves = file.savesImmediately ? 'saves immediately' : 'saves as a draft';
156
+ return `Attachment index ${file.index}: ${file.name} (${file.type}). If a plan lists it, it ${saves} to ${file.collection}.`;
157
+ }
158
+ function withoutNulls(value) {
159
+ return Object.fromEntries(Object.entries(value).filter(([, item])=>item !== null));
160
+ }
161
+ function isRecord(value) {
162
+ return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
163
+ }
164
+
165
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chat/history.ts"],"sourcesContent":["import type { FileUIPart } from 'ai'\n\nimport { isToolUIPart } from 'ai'\n\nimport type { IncomingFile } from '../plan/parsePlan.js'\nimport type { AssistantChange, PageContext, PlanStatus } from '../types.js'\nimport type { AssistantUIMessage } from './messages.js'\n\nimport { maxThreadTitleCharacters } from '../constants.js'\n\ntype Part = AssistantUIMessage['parts'][number]\n\nconst omitted = {\n omitted: 'This older result was removed to save space. Call the tool again if you need it.',\n}\n\n/**\n * Read results from older turns are the bulk of a long conversation. Plans stay, because later turns refer to them.\n */\nexport function pruneToolResults(\n messages: AssistantUIMessage[],\n keepTurns: number,\n): AssistantUIMessage[] {\n const userIndexes = messages.flatMap((message, index) => (message.role === 'user' ? [index] : []))\n if (userIndexes.length <= keepTurns) {\n return messages\n }\n const cutoff = userIndexes[userIndexes.length - keepTurns]\n\n return messages.map((message, index) => {\n if (index >= cutoff || message.role !== 'assistant') {\n return message\n }\n return {\n ...message,\n parts: message.parts.map((part) =>\n isToolUIPart(part) && part.type !== 'tool-submitPlan' && part.state === 'output-available'\n ? ({ ...part, output: omitted } as Part)\n : part,\n ),\n }\n })\n}\n\n/**\n * The JSON field stores an undefined property as null. The message schema allows a missing property but not null,\n * so a stored thread would fail validation on the next turn. Values inside tool inputs and outputs are left alone.\n * Empty assistant replies are dropped.\n */\nexport function restoreStoredMessages(messages: unknown[]): AssistantUIMessage[] {\n return messages.flatMap((message) => {\n if (!isRecord(message) || !Array.isArray(message.parts)) {\n return []\n }\n // A reply that failed before it said anything has no parts, and the model API rejects an empty turn.\n if (message.role === 'assistant' && message.parts.length === 0) {\n return []\n }\n const restored = withoutNulls(message)\n restored.parts = message.parts.filter(isRecord).map(withoutNulls)\n if (isRecord(message.metadata)) {\n restored.metadata = withoutNulls(message.metadata)\n }\n return [restored as unknown as AssistantUIMessage]\n })\n}\n\nexport interface TurnContext {\n /** Images and PDFs the model can look at, by conversation index. */\n fileParts: ReadonlyMap<number, FileUIPart>\n /** Files this request uploaded, by conversation index. An earlier file missing here is no longer available. */\n files: readonly IncomingFile[]\n /** The open document's current values, added to the newest message only. */\n openDocument?: string\n}\n\n/**\n * Adds what the model needs to know about each user message: the open document and its attachments.\n * This is added for the model run only. The stored thread keeps what the editor typed.\n */\nexport function withTurnContext(\n messages: AssistantUIMessage[],\n context: TurnContext,\n): AssistantUIMessage[] {\n const lastUser = messages.map((message) => message.role).lastIndexOf('user')\n\n return messages.map((message, index) => {\n if (message.role !== 'user') {\n return message\n }\n const notes: string[] = []\n if (message.metadata?.context) {\n notes.push(contextNote(message.metadata.context))\n }\n const attachments = message.metadata?.attachments ?? []\n const fileParts: FileUIPart[] = []\n for (const attachment of attachments) {\n const file = context.files.find((item) => item.index === attachment.index)\n notes.push(\n file\n ? attachmentNote(file)\n : `Attachment index ${attachment.index}: ${attachment.name}. No longer available.`,\n )\n const part = file ? context.fileParts.get(file.index) : undefined\n if (part) {\n fileParts.push(part)\n }\n }\n if (index === lastUser && context.openDocument) {\n notes.push(\n `Outline of the open document, including unsaved changes. Text is cut and each block is one line. Call readDocument with a path for full values:\\n${context.openDocument}`,\n )\n }\n if (notes.length === 0 && fileParts.length === 0) {\n return message\n }\n\n const note: Part = {\n type: 'text',\n text: `<editor-context>\\n${notes.join('\\n')}\\n</editor-context>`,\n }\n return { ...message, parts: [note, ...message.parts, ...fileParts] }\n })\n}\n\n/** Records what the editor did with a plan, so the card and the model both see it. */\nexport function markPlan(\n messages: AssistantUIMessage[],\n planId: string,\n update: { changes?: AssistantChange[]; status: PlanStatus },\n): { changed: boolean; messages: AssistantUIMessage[] } {\n let changed = false\n const next = messages.map((message) => {\n if (message.role !== 'assistant') {\n return message\n }\n let touched = false\n const parts = message.parts.map((part) => {\n if (part.type !== 'tool-submitPlan' || part.state !== 'output-available') {\n return part\n }\n if (!part.output.ok || part.output.plan.id !== planId) {\n return part\n }\n touched = true\n return { ...part, output: { ...part.output, ...update } }\n })\n if (!touched) {\n return message\n }\n changed = true\n return { ...message, parts }\n })\n return { messages: next, changed }\n}\n\nexport function messageText(message: AssistantUIMessage): string {\n return message.parts\n .flatMap((part) => (part.type === 'text' ? [part.text] : []))\n .join('\\n')\n .trim()\n}\n\nexport function threadTitle(text: string): string {\n const line = text.replace(/\\s+/g, ' ').trim()\n if (!line) {\n return 'Attached files'\n }\n if (line.length <= maxThreadTitleCharacters) {\n return line\n }\n return `${line.slice(0, maxThreadTitleCharacters - 1).trimEnd()}…`\n}\n\nfunction contextNote(context: PageContext): string {\n const id = context.id ? `, id ${context.id}` : ''\n return `Open in the editor when this was sent: ${context.label} (${context.kind} ${context.slug}${id}).`\n}\n\nfunction attachmentNote(file: IncomingFile): string {\n if (!file.collection) {\n return `Attachment index ${file.index}: ${file.name} (${file.type}). It can be read, but not saved: no upload collection the assistant may change accepts it.`\n }\n const saves = file.savesImmediately ? 'saves immediately' : 'saves as a draft'\n return `Attachment index ${file.index}: ${file.name} (${file.type}). If a plan lists it, it ${saves} to ${file.collection}.`\n}\n\nfunction withoutNulls(value: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== null))\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === 'object' && !Array.isArray(value)\n}\n"],"names":["isToolUIPart","maxThreadTitleCharacters","omitted","pruneToolResults","messages","keepTurns","userIndexes","flatMap","message","index","role","length","cutoff","map","parts","part","type","state","output","restoreStoredMessages","isRecord","Array","isArray","restored","withoutNulls","filter","metadata","withTurnContext","context","lastUser","lastIndexOf","notes","push","contextNote","attachments","fileParts","attachment","file","files","find","item","attachmentNote","name","get","undefined","openDocument","note","text","join","markPlan","planId","update","changed","next","touched","ok","plan","id","messageText","trim","threadTitle","line","replace","slice","trimEnd","label","kind","slug","collection","saves","savesImmediately","value","Object","fromEntries","entries","Boolean"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { InferUITools, UIDataTypes, UIMessage } from 'ai';
2
+ import type { AssistantMessageMetadata } from '../types.js';
3
+ import type { AssistantTools } from './tools.js';
4
+ /** A message in an assistant conversation. Shared by the chat endpoint, the stored thread, and the drawer. */
5
+ export type AssistantUIMessage = UIMessage<AssistantMessageMetadata, UIDataTypes, InferUITools<AssistantTools>>;
@@ -0,0 +1,3 @@
1
+ /** A message in an assistant conversation. Shared by the chat endpoint, the stored thread, and the drawer. */ export { };
2
+
3
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chat/messages.ts"],"sourcesContent":["import type { InferUITools, UIDataTypes, UIMessage } from 'ai'\n\nimport type { AssistantMessageMetadata } from '../types.js'\nimport type { AssistantTools } from './tools.js'\n\n/** A message in an assistant conversation. Shared by the chat endpoint, the stored thread, and the drawer. */\nexport type AssistantUIMessage = UIMessage<\n AssistantMessageMetadata,\n UIDataTypes,\n InferUITools<AssistantTools>\n>\n"],"names":[],"mappings":"AAKA,4GAA4G,GAC5G,WAIC"}
@@ -0,0 +1,33 @@
1
+ import type { PayloadRequest } from 'payload';
2
+ import type { AssistantChange, PlanStatus } from '../types.js';
3
+ import type { AssistantUIMessage } from './messages.js';
4
+ /**
5
+ * A file attached in the conversation, stored in the attachments collection. Conversations from before
6
+ * attachments were stored have no id, and their files can no longer be read.
7
+ */
8
+ export interface ThreadFile {
9
+ id?: string;
10
+ name: string;
11
+ size: number;
12
+ type: string;
13
+ }
14
+ export interface StoredThread {
15
+ chatId: string;
16
+ files: ThreadFile[];
17
+ id: string;
18
+ messages: AssistantUIMessage[];
19
+ title: string;
20
+ }
21
+ /** The editor's own thread. Read access on the collection is limited to the owner. */
22
+ export declare function findThread(req: PayloadRequest, chatId: string): Promise<StoredThread | undefined>;
23
+ /**
24
+ * Threads are written only by these endpoints, never through the REST API, so a thread's
25
+ * history cannot be edited to put words in the assistant's mouth. Callers check ownership first.
26
+ */
27
+ export declare function saveThread(req: PayloadRequest, thread: {
28
+ id?: string;
29
+ } & Omit<StoredThread, 'id'>): Promise<string>;
30
+ export declare function markPlanInThread(req: PayloadRequest, chatId: string, planId: string, update: {
31
+ changes?: AssistantChange[];
32
+ status: PlanStatus;
33
+ }): Promise<void>;
@@ -0,0 +1,77 @@
1
+ import { aiAssistantThreadSlug } from '../constants.js';
2
+ import { userIdOf } from '../settings.js';
3
+ import { markPlan, restoreStoredMessages } from './history.js';
4
+ /** The editor's own thread. Read access on the collection is limited to the owner. */ export async function findThread(req, chatId) {
5
+ const found = await req.payload.find({
6
+ collection: aiAssistantThreadSlug,
7
+ where: {
8
+ chatId: {
9
+ equals: chatId
10
+ }
11
+ },
12
+ limit: 1,
13
+ depth: 0,
14
+ pagination: false,
15
+ overrideAccess: false,
16
+ req,
17
+ user: req.user
18
+ });
19
+ const doc = found.docs[0];
20
+ if (!doc) {
21
+ return undefined;
22
+ }
23
+ return {
24
+ id: String(doc.id),
25
+ chatId,
26
+ title: typeof doc.title === 'string' ? doc.title : '',
27
+ messages: Array.isArray(doc.messages) ? restoreStoredMessages(doc.messages) : [],
28
+ files: Array.isArray(doc.files) ? doc.files : []
29
+ };
30
+ }
31
+ /**
32
+ * Threads are written only by these endpoints, never through the REST API, so a thread's
33
+ * history cannot be edited to put words in the assistant's mouth. Callers check ownership first.
34
+ */ export async function saveThread(req, thread) {
35
+ const data = {
36
+ chatId: thread.chatId,
37
+ title: thread.title,
38
+ messages: thread.messages,
39
+ files: thread.files
40
+ };
41
+ if (thread.id) {
42
+ await req.payload.update({
43
+ collection: aiAssistantThreadSlug,
44
+ id: thread.id,
45
+ data: data,
46
+ depth: 0,
47
+ req
48
+ });
49
+ return thread.id;
50
+ }
51
+ const created = await req.payload.create({
52
+ collection: aiAssistantThreadSlug,
53
+ data: {
54
+ ...data,
55
+ owner: userIdOf(req.user)
56
+ },
57
+ depth: 0,
58
+ req
59
+ });
60
+ return String(created.id);
61
+ }
62
+ export async function markPlanInThread(req, chatId, planId, update) {
63
+ const thread = await findThread(req, chatId);
64
+ if (!thread) {
65
+ return;
66
+ }
67
+ const marked = markPlan(thread.messages, planId, update);
68
+ if (!marked.changed) {
69
+ return;
70
+ }
71
+ await saveThread(req, {
72
+ ...thread,
73
+ messages: marked.messages
74
+ });
75
+ }
76
+
77
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/chat/threads.ts"],"sourcesContent":["import type { CollectionSlug, PayloadRequest } from 'payload'\n\nimport type { AssistantChange, PlanStatus } from '../types.js'\nimport type { AssistantUIMessage } from './messages.js'\n\nimport { aiAssistantThreadSlug } from '../constants.js'\nimport { userIdOf } from '../settings.js'\nimport { markPlan, restoreStoredMessages } from './history.js'\n\n/**\n * A file attached in the conversation, stored in the attachments collection. Conversations from before\n * attachments were stored have no id, and their files can no longer be read.\n */\nexport interface ThreadFile {\n id?: string\n name: string\n size: number\n type: string\n}\n\nexport interface StoredThread {\n chatId: string\n files: ThreadFile[]\n id: string\n messages: AssistantUIMessage[]\n title: string\n}\n\n/** The editor's own thread. Read access on the collection is limited to the owner. */\nexport async function findThread(\n req: PayloadRequest,\n chatId: string,\n): Promise<StoredThread | undefined> {\n const found = await req.payload.find({\n collection: aiAssistantThreadSlug as CollectionSlug,\n where: { chatId: { equals: chatId } },\n limit: 1,\n depth: 0,\n pagination: false,\n overrideAccess: false,\n req,\n user: req.user,\n })\n const doc = found.docs[0] as unknown as Record<string, unknown> | undefined\n if (!doc) {\n return undefined\n }\n return {\n id: String(doc.id),\n chatId,\n title: typeof doc.title === 'string' ? doc.title : '',\n messages: Array.isArray(doc.messages) ? restoreStoredMessages(doc.messages) : [],\n files: Array.isArray(doc.files) ? (doc.files as ThreadFile[]) : [],\n }\n}\n\n/**\n * Threads are written only by these endpoints, never through the REST API, so a thread's\n * history cannot be edited to put words in the assistant's mouth. Callers check ownership first.\n */\nexport async function saveThread(\n req: PayloadRequest,\n thread: { id?: string } & Omit<StoredThread, 'id'>,\n): Promise<string> {\n const data = {\n chatId: thread.chatId,\n title: thread.title,\n messages: thread.messages,\n files: thread.files,\n }\n if (thread.id) {\n await req.payload.update({\n collection: aiAssistantThreadSlug as CollectionSlug,\n id: thread.id,\n data: data as never,\n depth: 0,\n req,\n })\n return thread.id\n }\n const created = await req.payload.create({\n collection: aiAssistantThreadSlug as CollectionSlug,\n data: { ...data, owner: userIdOf(req.user) } as never,\n depth: 0,\n req,\n })\n return String((created as { id: unknown }).id)\n}\n\nexport async function markPlanInThread(\n req: PayloadRequest,\n chatId: string,\n planId: string,\n update: { changes?: AssistantChange[]; status: PlanStatus },\n): Promise<void> {\n const thread = await findThread(req, chatId)\n if (!thread) {\n return\n }\n const marked = markPlan(thread.messages, planId, update)\n if (!marked.changed) {\n return\n }\n await saveThread(req, { ...thread, messages: marked.messages })\n}\n"],"names":["aiAssistantThreadSlug","userIdOf","markPlan","restoreStoredMessages","findThread","req","chatId","found","payload","find","collection","where","equals","limit","depth","pagination","overrideAccess","user","doc","docs","undefined","id","String","title","messages","Array","isArray","files","saveThread","thread","data","update","created","create","owner","markPlanInThread","planId","marked","changed"],"mappings":"AAKA,SAASA,qBAAqB,QAAQ,kBAAiB;AACvD,SAASC,QAAQ,QAAQ,iBAAgB;AACzC,SAASC,QAAQ,EAAEC,qBAAqB,QAAQ,eAAc;AAqB9D,oFAAoF,GACpF,OAAO,eAAeC,WACpBC,GAAmB,EACnBC,MAAc;IAEd,MAAMC,QAAQ,MAAMF,IAAIG,OAAO,CAACC,IAAI,CAAC;QACnCC,YAAYV;QACZW,OAAO;YAAEL,QAAQ;gBAAEM,QAAQN;YAAO;QAAE;QACpCO,OAAO;QACPC,OAAO;QACPC,YAAY;QACZC,gBAAgB;QAChBX;QACAY,MAAMZ,IAAIY,IAAI;IAChB;IACA,MAAMC,MAAMX,MAAMY,IAAI,CAAC,EAAE;IACzB,IAAI,CAACD,KAAK;QACR,OAAOE;IACT;IACA,OAAO;QACLC,IAAIC,OAAOJ,IAAIG,EAAE;QACjBf;QACAiB,OAAO,OAAOL,IAAIK,KAAK,KAAK,WAAWL,IAAIK,KAAK,GAAG;QACnDC,UAAUC,MAAMC,OAAO,CAACR,IAAIM,QAAQ,IAAIrB,sBAAsBe,IAAIM,QAAQ,IAAI,EAAE;QAChFG,OAAOF,MAAMC,OAAO,CAACR,IAAIS,KAAK,IAAKT,IAAIS,KAAK,GAAoB,EAAE;IACpE;AACF;AAEA;;;CAGC,GACD,OAAO,eAAeC,WACpBvB,GAAmB,EACnBwB,MAAkD;IAElD,MAAMC,OAAO;QACXxB,QAAQuB,OAAOvB,MAAM;QACrBiB,OAAOM,OAAON,KAAK;QACnBC,UAAUK,OAAOL,QAAQ;QACzBG,OAAOE,OAAOF,KAAK;IACrB;IACA,IAAIE,OAAOR,EAAE,EAAE;QACb,MAAMhB,IAAIG,OAAO,CAACuB,MAAM,CAAC;YACvBrB,YAAYV;YACZqB,IAAIQ,OAAOR,EAAE;YACbS,MAAMA;YACNhB,OAAO;YACPT;QACF;QACA,OAAOwB,OAAOR,EAAE;IAClB;IACA,MAAMW,UAAU,MAAM3B,IAAIG,OAAO,CAACyB,MAAM,CAAC;QACvCvB,YAAYV;QACZ8B,MAAM;YAAE,GAAGA,IAAI;YAAEI,OAAOjC,SAASI,IAAIY,IAAI;QAAE;QAC3CH,OAAO;QACPT;IACF;IACA,OAAOiB,OAAO,AAACU,QAA4BX,EAAE;AAC/C;AAEA,OAAO,eAAec,iBACpB9B,GAAmB,EACnBC,MAAc,EACd8B,MAAc,EACdL,MAA2D;IAE3D,MAAMF,SAAS,MAAMzB,WAAWC,KAAKC;IACrC,IAAI,CAACuB,QAAQ;QACX;IACF;IACA,MAAMQ,SAASnC,SAAS2B,OAAOL,QAAQ,EAAEY,QAAQL;IACjD,IAAI,CAACM,OAAOC,OAAO,EAAE;QACnB;IACF;IACA,MAAMV,WAAWvB,KAAK;QAAE,GAAGwB,MAAM;QAAEL,UAAUa,OAAOb,QAAQ;IAAC;AAC/D"}
@@ -0,0 +1,76 @@
1
+ import type { JSONValue } from 'ai';
2
+ import type { PayloadRequest } from 'payload';
3
+ import type { IncomingFile } from '../plan/parsePlan.js';
4
+ import type { AiAssistantPluginOptions, PageContext, SubmitPlanOutput } from '../types.js';
5
+ export interface AssistantToolsOptions {
6
+ /** The conversation a submitted plan belongs to, so applying it can update the plan card. */
7
+ chatId: string;
8
+ collectionRules?: AiAssistantPluginOptions['collectionRules'];
9
+ /** Files attached to the conversation that this request uploaded again. */
10
+ files: IncomingFile[];
11
+ /** Called once a plan is saved, so the model run can stop. */
12
+ onPlan: () => void;
13
+ /** The document open in the editor, read from its form, so reads include unsaved changes. */
14
+ openDocument?: OpenDocument;
15
+ req: PayloadRequest;
16
+ }
17
+ export interface OpenDocument {
18
+ context: PageContext;
19
+ /** The form values as the assistant reads them. */
20
+ document: unknown;
21
+ }
22
+ export type PlanInput = Record<string, JSONValue>;
23
+ /**
24
+ * Every tool reads with the editor's access. Only submitPlan writes, and it writes a plan, not the documents.
25
+ */
26
+ export declare function assistantTools({ req, chatId, collectionRules, files, onPlan, openDocument, }: AssistantToolsOptions): {
27
+ listTargets: import("ai").Tool<Record<string, never>, {
28
+ targets: {
29
+ slug: string;
30
+ kind: import("../types.js").PlanTargetKind;
31
+ label: string;
32
+ drafts: boolean;
33
+ upload: boolean;
34
+ canChange: boolean;
35
+ }[];
36
+ }>;
37
+ describeTarget: import("ai").Tool<{
38
+ kind: "collection" | "global";
39
+ slug: string;
40
+ blocks?: string[] | undefined;
41
+ }, {
42
+ blocks?: string;
43
+ drafts: boolean;
44
+ guide: string;
45
+ note?: string;
46
+ rules?: string;
47
+ upload: boolean;
48
+ } | {
49
+ error: string;
50
+ }>;
51
+ searchDocuments: import("ai").Tool<{
52
+ collection: string;
53
+ query: string;
54
+ filters?: {
55
+ field: string;
56
+ operator: "equals" | "not_equals" | "in" | "exists" | "like";
57
+ value: string | number | boolean | (string | number)[];
58
+ }[] | undefined;
59
+ limit?: number | undefined;
60
+ }, unknown>;
61
+ readDocument: import("ai").Tool<{
62
+ kind: "collection" | "global";
63
+ slug: string;
64
+ id?: string | undefined;
65
+ path?: string | undefined;
66
+ }, unknown>;
67
+ submitPlan: import("ai").Tool<PlanInput, SubmitPlanOutput>;
68
+ };
69
+ export type AssistantTools = ReturnType<typeof assistantTools>;
70
+ /** Reads with the editor's access, so the assistant sees only what the editor can see. */
71
+ export declare function readDocument(req: PayloadRequest, kind: 'collection' | 'global', slug: string, id: string | undefined): Promise<{
72
+ document: unknown;
73
+ label: string;
74
+ } | {
75
+ error: string;
76
+ }>;