@mvriu5/payload-ai 1.5.0 → 1.6.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.
- package/README.md +34 -0
- package/dist/ai/promptCaching.d.ts +23 -0
- package/dist/ai/promptCaching.js +120 -0
- package/dist/ai/proposalRepair.d.ts +30 -0
- package/dist/ai/proposalRepair.js +76 -0
- package/dist/ai/sensitiveData.d.ts +1 -0
- package/dist/ai/sensitiveData.js +3 -1
- package/dist/components/translate-document/TranslateDocumentButton.d.ts +2 -0
- package/dist/components/translate-document/TranslateDocumentButton.js +111 -0
- package/dist/components/translate-document/TranslateDocumentButton.module.css +11 -0
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.js +2 -0
- package/dist/handlers/chatHandler.d.ts +1 -0
- package/dist/handlers/chatHandler.js +464 -138
- package/dist/handlers/translateDocumentHandler.d.ts +14 -0
- package/dist/handlers/translateDocumentHandler.js +186 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +62 -3
- package/dist/payload/documentTranslation.d.ts +15 -0
- package/dist/payload/documentTranslation.js +120 -0
- package/dist/payload/toolFieldSelection.d.ts +25 -0
- package/dist/payload/toolFieldSelection.js +118 -0
- package/dist/payload/toolSchemas.d.ts +7 -0
- package/dist/payload/toolSchemas.js +117 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -101,6 +101,8 @@ const options: PayloadAIPluginOptions = {
|
|
|
101
101
|
},
|
|
102
102
|
],
|
|
103
103
|
maxOutputTokens: 1200,
|
|
104
|
+
promptCaching: true,
|
|
105
|
+
translate: true,
|
|
104
106
|
maxTokenUsage: {
|
|
105
107
|
type: "user",
|
|
106
108
|
perDay: 50_000,
|
|
@@ -135,6 +137,26 @@ payloadAiPlugin({
|
|
|
135
137
|
|
|
136
138
|
Generate controls are added to `text`, `textarea`, `richText`, and `json` fields in collection and global edit views. When disabled, the plugin also omits the `/ai-generate-field` endpoint. The embedded AI Assistant and dashboard remain available.
|
|
137
139
|
|
|
140
|
+
### `translate`
|
|
141
|
+
|
|
142
|
+
Controls document translation for localized collections and globals. It defaults to `true`.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
payloadAiPlugin({
|
|
146
|
+
translate: false,
|
|
147
|
+
})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
When enabled, the plugin adds a `Translate` action to the document header. It is shown only when:
|
|
151
|
+
|
|
152
|
+
- a non-default locale is selected
|
|
153
|
+
- at least one localized field is empty in that locale
|
|
154
|
+
- the corresponding field in the default locale contains source content
|
|
155
|
+
|
|
156
|
+
Translation fills only empty localized fields in the current Payload form and marks it as modified. Existing translated values are never overwritten. It does not save the document or global, so the generated values can be reviewed and validated before saving.
|
|
157
|
+
|
|
158
|
+
When disabled, the plugin does not register the header control or the `/ai-translate-document` endpoint.
|
|
159
|
+
|
|
138
160
|
### `collections`
|
|
139
161
|
|
|
140
162
|
Restricts AI read and write proposals to enabled collection slugs. If omitted, all non-internal Payload collections are available.
|
|
@@ -276,6 +298,18 @@ Use `type: "user"` to enforce separate budgets per authenticated user, or `type:
|
|
|
276
298
|
|
|
277
299
|
Completed model usage is stored in the hidden `payload-ai-usage` collection. Requests made after a limit is reached return HTTP `429`. Because providers report token usage after completion, the request that crosses a limit is allowed to finish and subsequent requests are blocked.
|
|
278
300
|
|
|
301
|
+
### `promptCaching`
|
|
302
|
+
|
|
303
|
+
Enables provider prompt-caching hints and defaults to `true`. The chat endpoint keeps static instructions and Payload schemas in a stable prompt prefix, adds Anthropic cache-control breakpoints, and supplies a stable OpenAI prompt cache key. Gemini uses the same stable prefix with its implicit caching.
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
payloadAiPlugin({
|
|
307
|
+
promptCaching: false,
|
|
308
|
+
})
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Disable it when explicit provider-side caching is not desired. Dynamic document data and user prompts are never placed in the cacheable schema section. Managed providers with a custom `baseURL` receive the stable prefix but no provider-specific cache parameters, preserving compatibility with Ollama, vLLM, and other OpenAI-compatible endpoints.
|
|
312
|
+
|
|
279
313
|
### `allowUserApiKeys`
|
|
280
314
|
|
|
281
315
|
Controls whether the plugin adds an `aiApiKey` field to the admin user collection.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SystemModelMessage } from "ai";
|
|
2
|
+
import type { AIProvider } from "./providerOptions.js";
|
|
3
|
+
type PromptCacheContext = {
|
|
4
|
+
cacheable: Record<string, unknown>[];
|
|
5
|
+
dynamic: Record<string, unknown>[];
|
|
6
|
+
};
|
|
7
|
+
type PromptCacheProviderOptions = NonNullable<SystemModelMessage["providerOptions"]>;
|
|
8
|
+
export declare const splitPromptCacheContext: (mentionContext: Record<string, unknown>[]) => PromptCacheContext;
|
|
9
|
+
export declare const createCachedSystemMessages: ({ cacheableContext, cacheableInstructions, dynamicInstructions, enabled, provider, staticInstructions, }: {
|
|
10
|
+
cacheableContext: Record<string, unknown>[];
|
|
11
|
+
cacheableInstructions: string[];
|
|
12
|
+
dynamicInstructions: string[];
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
provider: AIProvider;
|
|
15
|
+
staticInstructions: string[];
|
|
16
|
+
}) => SystemModelMessage[];
|
|
17
|
+
export declare const createPromptCacheProviderOptions: ({ cacheKeyParts, enabled, model, provider, }: {
|
|
18
|
+
cacheKeyParts: unknown[];
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
model: string;
|
|
21
|
+
provider: AIProvider;
|
|
22
|
+
}) => PromptCacheProviderOptions | undefined;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
const getContextKey = (context)=>{
|
|
3
|
+
return [
|
|
4
|
+
context.type,
|
|
5
|
+
context.parent,
|
|
6
|
+
context.collection,
|
|
7
|
+
context.slug
|
|
8
|
+
].filter(Boolean).join(":") || JSON.stringify(context);
|
|
9
|
+
};
|
|
10
|
+
export const splitPromptCacheContext = (mentionContext)=>{
|
|
11
|
+
const cacheable = [];
|
|
12
|
+
const dynamic = [];
|
|
13
|
+
const cacheableKeys = new Set();
|
|
14
|
+
const addCacheable = (context)=>{
|
|
15
|
+
const key = getContextKey(context);
|
|
16
|
+
if (cacheableKeys.has(key)) return;
|
|
17
|
+
cacheableKeys.add(key);
|
|
18
|
+
cacheable.push(context);
|
|
19
|
+
};
|
|
20
|
+
for (const context of mentionContext){
|
|
21
|
+
if ([
|
|
22
|
+
"block",
|
|
23
|
+
"collection"
|
|
24
|
+
].includes(String(context.type))) {
|
|
25
|
+
addCacheable(context);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (context.type === "global" && "doc" in context) {
|
|
29
|
+
const { doc, ...schema } = context;
|
|
30
|
+
addCacheable(schema);
|
|
31
|
+
dynamic.push({
|
|
32
|
+
doc,
|
|
33
|
+
slug: context.slug,
|
|
34
|
+
type: "globalDocument"
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (context.type === "global") {
|
|
39
|
+
addCacheable(context);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (context.type === "mediaAttachment" && context.schema && typeof context.schema === "object") {
|
|
43
|
+
addCacheable(context.schema);
|
|
44
|
+
const { schema: _schema, ...attachmentContext } = context;
|
|
45
|
+
dynamic.push(attachmentContext);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
dynamic.push(context);
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
cacheable,
|
|
52
|
+
dynamic
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const withAnthropicCacheControl = (message, enabled, provider)=>{
|
|
56
|
+
if (!enabled || provider !== "claude") return message;
|
|
57
|
+
return {
|
|
58
|
+
...message,
|
|
59
|
+
providerOptions: {
|
|
60
|
+
anthropic: {
|
|
61
|
+
cacheControl: {
|
|
62
|
+
type: "ephemeral"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
export const createCachedSystemMessages = ({ cacheableContext, cacheableInstructions, dynamicInstructions, enabled, provider, staticInstructions })=>{
|
|
69
|
+
const messages = [
|
|
70
|
+
withAnthropicCacheControl({
|
|
71
|
+
content: staticInstructions.join("\n"),
|
|
72
|
+
role: "system"
|
|
73
|
+
}, enabled, provider)
|
|
74
|
+
];
|
|
75
|
+
const scopedContent = [
|
|
76
|
+
...cacheableContext.length ? [
|
|
77
|
+
"Payload schema references JSON. Use exact field names and values:",
|
|
78
|
+
JSON.stringify(cacheableContext)
|
|
79
|
+
] : [],
|
|
80
|
+
...cacheableInstructions
|
|
81
|
+
];
|
|
82
|
+
if (scopedContent.length > 0) {
|
|
83
|
+
messages.push(withAnthropicCacheControl({
|
|
84
|
+
content: scopedContent.join("\n"),
|
|
85
|
+
role: "system"
|
|
86
|
+
}, enabled, provider));
|
|
87
|
+
}
|
|
88
|
+
if (dynamicInstructions.length > 0) {
|
|
89
|
+
messages.push({
|
|
90
|
+
content: dynamicInstructions.join("\n"),
|
|
91
|
+
role: "system"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return messages;
|
|
95
|
+
};
|
|
96
|
+
export const createPromptCacheProviderOptions = ({ cacheKeyParts, enabled, model, provider })=>{
|
|
97
|
+
if (!enabled) return undefined;
|
|
98
|
+
if (provider === "openai") {
|
|
99
|
+
const digest = createHash("sha256").update(JSON.stringify([
|
|
100
|
+
"payload-ai-v1",
|
|
101
|
+
model,
|
|
102
|
+
...cacheKeyParts
|
|
103
|
+
])).digest("hex").slice(0, 32);
|
|
104
|
+
return {
|
|
105
|
+
openai: {
|
|
106
|
+
promptCacheKey: `payload-ai-${digest}`
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (provider === "openrouter" && model.toLowerCase().startsWith("anthropic/")) {
|
|
111
|
+
return {
|
|
112
|
+
openrouter: {
|
|
113
|
+
cache_control: {
|
|
114
|
+
type: "ephemeral"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return undefined;
|
|
120
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ProposalValidationIssue } from "../payload/proposalData.js";
|
|
2
|
+
export declare const maxProposalRepairAttempts = 1;
|
|
3
|
+
export type CompactProposalRepairIssue = {
|
|
4
|
+
code: string;
|
|
5
|
+
hint: string;
|
|
6
|
+
path: string;
|
|
7
|
+
};
|
|
8
|
+
type ProposalRepairTarget = {
|
|
9
|
+
collection?: string;
|
|
10
|
+
id?: string;
|
|
11
|
+
slug?: string;
|
|
12
|
+
tool: string;
|
|
13
|
+
};
|
|
14
|
+
export declare const compactProposalRepairIssues: (issues: ProposalValidationIssue[]) => CompactProposalRepairIssue[];
|
|
15
|
+
export declare const createProposalRepairKey: ({ collection, id, slug, tool }: ProposalRepairTarget) => string;
|
|
16
|
+
export declare const createProposalRepairTracker: () => {
|
|
17
|
+
beginCall(target: ProposalRepairTarget): "initial" | "blocked" | "repair";
|
|
18
|
+
registerFailure(target: ProposalRepairTarget): {
|
|
19
|
+
attempt: number;
|
|
20
|
+
errorCode: "REPAIR_EXHAUSTED";
|
|
21
|
+
maxAttempts: number;
|
|
22
|
+
retryable: boolean;
|
|
23
|
+
} | {
|
|
24
|
+
attempt: number;
|
|
25
|
+
errorCode: "INVALID_PROPOSAL_DATA";
|
|
26
|
+
maxAttempts: number;
|
|
27
|
+
retryable: boolean;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export const maxProposalRepairAttempts = 1;
|
|
2
|
+
const getIssueHint = (issue)=>{
|
|
3
|
+
switch(issue.code){
|
|
4
|
+
case "invalid_array":
|
|
5
|
+
return "Use an array of complete objects matching the child fields.";
|
|
6
|
+
case "invalid_block_type":
|
|
7
|
+
return "Use an exact blockType from the schema.";
|
|
8
|
+
case "invalid_blocks":
|
|
9
|
+
return "Use an array of block objects with blockType and exact field names.";
|
|
10
|
+
case "invalid_checkbox":
|
|
11
|
+
return "Use true or false.";
|
|
12
|
+
case "invalid_container":
|
|
13
|
+
return "Use an object matching the nested field schema.";
|
|
14
|
+
case "invalid_date":
|
|
15
|
+
return "Use a valid date string.";
|
|
16
|
+
case "invalid_option":
|
|
17
|
+
return issue.message;
|
|
18
|
+
case "invalid_relationship":
|
|
19
|
+
return "Use an existing document ID or { relationTo, value } for polymorphic relationships.";
|
|
20
|
+
case "missing_required_field":
|
|
21
|
+
return "Add the required field with a schema-compatible value.";
|
|
22
|
+
case "non_localized_field_in_secondary_locale":
|
|
23
|
+
return "Move this field to the primary locale data.";
|
|
24
|
+
case "unknown_field":
|
|
25
|
+
return "Remove it and use exact schema field names only.";
|
|
26
|
+
default:
|
|
27
|
+
return issue.message;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export const compactProposalRepairIssues = (issues)=>{
|
|
31
|
+
return issues.slice(0, 6).map((issue)=>({
|
|
32
|
+
code: issue.code,
|
|
33
|
+
hint: getIssueHint(issue).slice(0, 180),
|
|
34
|
+
path: issue.path
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
37
|
+
export const createProposalRepairKey = ({ collection, id, slug, tool })=>{
|
|
38
|
+
return [
|
|
39
|
+
tool,
|
|
40
|
+
collection || slug || "",
|
|
41
|
+
id || ""
|
|
42
|
+
].join(":");
|
|
43
|
+
};
|
|
44
|
+
export const createProposalRepairTracker = ()=>{
|
|
45
|
+
const statesByTarget = new Map();
|
|
46
|
+
return {
|
|
47
|
+
beginCall (target) {
|
|
48
|
+
const state = statesByTarget.get(createProposalRepairKey(target));
|
|
49
|
+
if (!state) return "initial";
|
|
50
|
+
if (state.repairCallConsumed) return "blocked";
|
|
51
|
+
state.repairCallConsumed = true;
|
|
52
|
+
return "repair";
|
|
53
|
+
},
|
|
54
|
+
registerFailure (target) {
|
|
55
|
+
const key = createProposalRepairKey(target);
|
|
56
|
+
const state = statesByTarget.get(key);
|
|
57
|
+
if (state) {
|
|
58
|
+
return {
|
|
59
|
+
attempt: maxProposalRepairAttempts,
|
|
60
|
+
errorCode: "REPAIR_EXHAUSTED",
|
|
61
|
+
maxAttempts: maxProposalRepairAttempts,
|
|
62
|
+
retryable: false
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
statesByTarget.set(key, {
|
|
66
|
+
repairCallConsumed: false
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
attempt: 1,
|
|
70
|
+
errorCode: "INVALID_PROPOSAL_DATA",
|
|
71
|
+
maxAttempts: maxProposalRepairAttempts,
|
|
72
|
+
retryable: true
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
};
|
package/dist/ai/sensitiveData.js
CHANGED
|
@@ -5,10 +5,12 @@ const sensitiveKeyPatterns = [
|
|
|
5
5
|
/^aiApiKey$/i,
|
|
6
6
|
/^authorization$/i,
|
|
7
7
|
/^accessToken$/i,
|
|
8
|
+
/^password$/i,
|
|
9
|
+
/^privateKey$/i,
|
|
8
10
|
/^refreshToken$/i,
|
|
9
11
|
/^secret$/i
|
|
10
12
|
];
|
|
11
|
-
const isSensitiveKey = (key)=>sensitiveKeyPatterns.some((pattern)=>pattern.test(key));
|
|
13
|
+
export const isSensitiveKey = (key)=>sensitiveKeyPatterns.some((pattern)=>pattern.test(key));
|
|
12
14
|
export const containsSensitiveData = (value)=>{
|
|
13
15
|
if (Array.isArray(value)) return value.some(containsSensitiveData);
|
|
14
16
|
if (!isRecord(value)) return false;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Button, useConfig, useDocumentForm, useDocumentInfo, useLocale } from "@payloadcms/ui";
|
|
4
|
+
import { formatAdminURL } from "payload/shared";
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import styles from "./TranslateDocumentButton.module.css";
|
|
7
|
+
const TranslateDocumentButton = ()=>{
|
|
8
|
+
const configContext = useConfig();
|
|
9
|
+
const documentForm = useDocumentForm();
|
|
10
|
+
const documentInfo = useDocumentInfo();
|
|
11
|
+
const locale = useLocale();
|
|
12
|
+
const [available, setAvailable] = useState(false);
|
|
13
|
+
const [error, setError] = useState("");
|
|
14
|
+
const [isChecking, setIsChecking] = useState(true);
|
|
15
|
+
const [isTranslating, setIsTranslating] = useState(false);
|
|
16
|
+
const scope = documentInfo.collectionSlug ? {
|
|
17
|
+
slug: documentInfo.collectionSlug,
|
|
18
|
+
type: "collection"
|
|
19
|
+
} : documentInfo.globalSlug ? {
|
|
20
|
+
slug: documentInfo.globalSlug,
|
|
21
|
+
type: "global"
|
|
22
|
+
} : null;
|
|
23
|
+
const apiRoute = configContext?.config?.routes?.api;
|
|
24
|
+
const request = async (action)=>{
|
|
25
|
+
if (!apiRoute || !scope) return null;
|
|
26
|
+
const response = await fetch(formatAdminURL({
|
|
27
|
+
apiRoute,
|
|
28
|
+
path: "/ai-translate-document"
|
|
29
|
+
}), {
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
action,
|
|
32
|
+
id: documentInfo.id,
|
|
33
|
+
locale: locale.code,
|
|
34
|
+
scope
|
|
35
|
+
}),
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json"
|
|
38
|
+
},
|
|
39
|
+
method: "POST"
|
|
40
|
+
});
|
|
41
|
+
const result = await response.json().catch(()=>null);
|
|
42
|
+
if (!response.ok || !result) throw new Error(result?.error || "Could not translate this locale.");
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
useEffect(()=>{
|
|
46
|
+
let active = true;
|
|
47
|
+
setAvailable(false);
|
|
48
|
+
setError("");
|
|
49
|
+
setIsChecking(true);
|
|
50
|
+
void request("status").then((result)=>{
|
|
51
|
+
if (active) setAvailable(Boolean(result?.available));
|
|
52
|
+
}).catch(()=>{
|
|
53
|
+
if (active) setAvailable(false);
|
|
54
|
+
}).finally(()=>{
|
|
55
|
+
if (active) setIsChecking(false);
|
|
56
|
+
});
|
|
57
|
+
return ()=>{
|
|
58
|
+
active = false;
|
|
59
|
+
};
|
|
60
|
+
}, [
|
|
61
|
+
apiRoute,
|
|
62
|
+
documentInfo.id,
|
|
63
|
+
locale.code,
|
|
64
|
+
scope?.slug,
|
|
65
|
+
scope?.type
|
|
66
|
+
]);
|
|
67
|
+
const translate = async ()=>{
|
|
68
|
+
if (isTranslating) return;
|
|
69
|
+
setError("");
|
|
70
|
+
setIsTranslating(true);
|
|
71
|
+
try {
|
|
72
|
+
const result = await request("translate");
|
|
73
|
+
for (const entry of result?.values || []){
|
|
74
|
+
documentForm.dispatchFields({
|
|
75
|
+
...entry.fieldType === "richText" ? {
|
|
76
|
+
initialValue: entry.value
|
|
77
|
+
} : {},
|
|
78
|
+
path: entry.path,
|
|
79
|
+
type: "UPDATE",
|
|
80
|
+
value: entry.value
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
documentForm.setModified(true);
|
|
84
|
+
setAvailable(false);
|
|
85
|
+
} catch (translationError) {
|
|
86
|
+
setError(translationError instanceof Error ? translationError.message : "Could not translate this locale.");
|
|
87
|
+
} finally{
|
|
88
|
+
setIsTranslating(false);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
if (isChecking || !available) return null;
|
|
92
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
93
|
+
className: styles.wrapper,
|
|
94
|
+
children: [
|
|
95
|
+
error && /*#__PURE__*/ _jsx("span", {
|
|
96
|
+
className: styles.error,
|
|
97
|
+
role: "alert",
|
|
98
|
+
children: error
|
|
99
|
+
}),
|
|
100
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
101
|
+
buttonStyle: "subtle",
|
|
102
|
+
disabled: isTranslating,
|
|
103
|
+
margin: false,
|
|
104
|
+
onClick: ()=>void translate(),
|
|
105
|
+
size: "medium",
|
|
106
|
+
children: isTranslating ? "Translating..." : "Translate"
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
export default TranslateDocumentButton;
|
package/dist/exports/client.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ import Dashboard from "../components/dashboard/Dashboard.js";
|
|
|
2
2
|
import APIKeyField from "../components/APIKeyField.js";
|
|
3
3
|
import AIInput from "../components/ai-input/AIInput.js";
|
|
4
4
|
import GenerateField from "../components/generate-field/GenerateField.js";
|
|
5
|
+
import TranslateDocumentButton from "../components/translate-document/TranslateDocumentButton.js";
|
|
5
6
|
export { Dashboard };
|
|
6
7
|
export { APIKeyField as AIApiKeyField };
|
|
7
8
|
export { AIInput };
|
|
8
9
|
export { GenerateField };
|
|
10
|
+
export { TranslateDocumentButton };
|
package/dist/exports/client.js
CHANGED
|
@@ -2,7 +2,9 @@ import Dashboard from "../components/dashboard/Dashboard.js";
|
|
|
2
2
|
import APIKeyField from "../components/APIKeyField.js";
|
|
3
3
|
import AIInput from "../components/ai-input/AIInput.js";
|
|
4
4
|
import GenerateField from "../components/generate-field/GenerateField.js";
|
|
5
|
+
import TranslateDocumentButton from "../components/translate-document/TranslateDocumentButton.js";
|
|
5
6
|
export { Dashboard };
|
|
6
7
|
export { APIKeyField as AIApiKeyField };
|
|
7
8
|
export { AIInput };
|
|
8
9
|
export { GenerateField };
|
|
10
|
+
export { TranslateDocumentButton };
|
|
@@ -39,6 +39,7 @@ type ChatOptions = {
|
|
|
39
39
|
maxOutputTokens?: number;
|
|
40
40
|
maxTokenUsage?: ResolvedMaxTokenUsageOptions;
|
|
41
41
|
models?: AIModelConfig;
|
|
42
|
+
promptCaching?: boolean;
|
|
42
43
|
providers?: ResolvedAIProviderConfig[];
|
|
43
44
|
};
|
|
44
45
|
export declare const createChatHandler: (options?: ChatOptions) => PayloadHandler;
|