transloadit 6.5.0 → 6.6.1
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/alphalib/renderSimpleValue.d.ts +14 -0
- package/dist/alphalib/renderSimpleValue.d.ts.map +1 -0
- package/dist/alphalib/renderSimpleValue.js +87 -0
- package/dist/alphalib/renderSimpleValue.js.map +1 -0
- package/dist/alphalib/truncateString.d.ts +5 -0
- package/dist/alphalib/truncateString.d.ts.map +1 -0
- package/dist/alphalib/truncateString.js +19 -0
- package/dist/alphalib/truncateString.js.map +1 -0
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts +6 -0
- package/dist/alphalib/types/robots/_instructions-primitives.d.ts.map +1 -1
- package/dist/alphalib/types/robots/_instructions-primitives.js +29 -7
- package/dist/alphalib/types/robots/_instructions-primitives.js.map +1 -1
- package/dist/alphalib/types/robots/_video-generate.d.ts +34 -0
- package/dist/alphalib/types/robots/_video-generate.d.ts.map +1 -0
- package/dist/alphalib/types/robots/_video-generate.js +157 -0
- package/dist/alphalib/types/robots/_video-generate.js.map +1 -0
- package/dist/alphalib/types/robots/ai-chat.d.ts +2 -0
- package/dist/alphalib/types/robots/ai-chat.d.ts.map +1 -1
- package/dist/alphalib/types/robots/ai-chat.js +7 -5
- package/dist/alphalib/types/robots/ai-chat.js.map +1 -1
- package/dist/alphalib/types/robots/audio-concat.d.ts.map +1 -1
- package/dist/alphalib/types/robots/audio-concat.js +5 -5
- package/dist/alphalib/types/robots/audio-concat.js.map +1 -1
- package/dist/alphalib/types/robots/azure-import.d.ts.map +1 -1
- package/dist/alphalib/types/robots/azure-import.js +3 -3
- package/dist/alphalib/types/robots/azure-import.js.map +1 -1
- package/dist/alphalib/types/robots/document-convert.d.ts.map +1 -1
- package/dist/alphalib/types/robots/document-convert.js +7 -5
- package/dist/alphalib/types/robots/document-convert.js.map +1 -1
- package/dist/alphalib/types/robots/document-extract.d.ts +8 -8
- package/dist/alphalib/types/robots/document-extract.d.ts.map +1 -1
- package/dist/alphalib/types/robots/document-extract.js +18 -2
- package/dist/alphalib/types/robots/document-extract.js.map +1 -1
- package/dist/alphalib/types/robots/document-split.d.ts +12 -0
- package/dist/alphalib/types/robots/document-split.d.ts.map +1 -1
- package/dist/alphalib/types/robots/document-split.js +15 -2
- package/dist/alphalib/types/robots/document-split.js.map +1 -1
- package/dist/alphalib/types/robots/file-decompress.d.ts.map +1 -1
- package/dist/alphalib/types/robots/file-decompress.js +2 -0
- package/dist/alphalib/types/robots/file-decompress.js.map +1 -1
- package/dist/alphalib/types/robots/file-preview.d.ts +22 -0
- package/dist/alphalib/types/robots/file-preview.d.ts.map +1 -1
- package/dist/alphalib/types/robots/file-preview.js +43 -26
- package/dist/alphalib/types/robots/file-preview.js.map +1 -1
- package/dist/alphalib/types/robots/http-request.d.ts.map +1 -1
- package/dist/alphalib/types/robots/http-request.js +9 -14
- package/dist/alphalib/types/robots/http-request.js.map +1 -1
- package/dist/alphalib/types/robots/image-enhance.d.ts +8 -8
- package/dist/alphalib/types/robots/image-enhance.js +2 -2
- package/dist/alphalib/types/robots/image-resize.d.ts.map +1 -1
- package/dist/alphalib/types/robots/image-resize.js +3 -1
- package/dist/alphalib/types/robots/image-resize.js.map +1 -1
- package/dist/alphalib/types/robots/image-upscale.js +1 -1
- package/dist/alphalib/types/robots/image-upscale.js.map +1 -1
- package/dist/alphalib/types/robots/s3-import.d.ts.map +1 -1
- package/dist/alphalib/types/robots/s3-import.js +14 -15
- package/dist/alphalib/types/robots/s3-import.js.map +1 -1
- package/dist/alphalib/types/robots/supabase-store.d.ts +16 -6
- package/dist/alphalib/types/robots/supabase-store.d.ts.map +1 -1
- package/dist/alphalib/types/robots/supabase-store.js +23 -1
- package/dist/alphalib/types/robots/supabase-store.js.map +1 -1
- package/dist/alphalib/types/robots/tigris-store.d.ts.map +1 -1
- package/dist/alphalib/types/robots/tigris-store.js +3 -4
- package/dist/alphalib/types/robots/tigris-store.js.map +1 -1
- package/dist/alphalib/types/robots/transloadit-import.d.ts +2 -2
- package/dist/alphalib/types/robots/transloadit-import.d.ts.map +1 -1
- package/dist/alphalib/types/robots/transloadit-import.js +4 -1
- package/dist/alphalib/types/robots/transloadit-import.js.map +1 -1
- package/dist/alphalib/types/robots/transloadit-store.d.ts +2 -3
- package/dist/alphalib/types/robots/transloadit-store.d.ts.map +1 -1
- package/dist/alphalib/types/robots/transloadit-store.js +19 -0
- package/dist/alphalib/types/robots/transloadit-store.js.map +1 -1
- package/dist/alphalib/types/robots/video-adaptive.d.ts.map +1 -1
- package/dist/alphalib/types/robots/video-adaptive.js +12 -0
- package/dist/alphalib/types/robots/video-adaptive.js.map +1 -1
- package/dist/alphalib/types/robots/video-concat.d.ts.map +1 -1
- package/dist/alphalib/types/robots/video-concat.js +9 -9
- package/dist/alphalib/types/robots/video-concat.js.map +1 -1
- package/dist/alphalib/types/robots/video-thumbs.d.ts +8 -8
- package/dist/alphalib/types/robots/video-thumbs.js +8 -8
- package/dist/alphalib/types/robots/video-thumbs.js.map +1 -1
- package/dist/alphalib/types/robots/vimeo-store.js +1 -1
- package/dist/alphalib/types/template.d.ts +3 -3
- package/dist/alphalib/types/templateValues.d.ts +83 -0
- package/dist/alphalib/types/templateValues.d.ts.map +1 -0
- package/dist/alphalib/types/templateValues.js +117 -0
- package/dist/alphalib/types/templateValues.js.map +1 -0
- package/dist/cli/stepsInput.d.ts +1 -1
- package/dist/cli/stepsInput.d.ts.map +1 -1
- package/dist/cli/stepsInput.js +31 -2
- package/dist/cli/stepsInput.js.map +1 -1
- package/package.json +2 -2
- package/src/alphalib/renderSimpleValue.ts +120 -0
- package/src/alphalib/truncateString.ts +23 -0
- package/src/alphalib/types/robots/_instructions-primitives.ts +34 -7
- package/src/alphalib/types/robots/_video-generate.ts +211 -0
- package/src/alphalib/types/robots/ai-chat.ts +8 -5
- package/src/alphalib/types/robots/audio-concat.ts +5 -4
- package/src/alphalib/types/robots/azure-import.ts +3 -4
- package/src/alphalib/types/robots/document-convert.ts +8 -5
- package/src/alphalib/types/robots/document-extract.ts +18 -2
- package/src/alphalib/types/robots/document-split.ts +17 -2
- package/src/alphalib/types/robots/file-decompress.ts +2 -0
- package/src/alphalib/types/robots/file-preview.ts +44 -25
- package/src/alphalib/types/robots/http-request.ts +9 -13
- package/src/alphalib/types/robots/image-enhance.ts +2 -2
- package/src/alphalib/types/robots/image-resize.ts +3 -1
- package/src/alphalib/types/robots/image-upscale.ts +1 -1
- package/src/alphalib/types/robots/s3-import.ts +14 -15
- package/src/alphalib/types/robots/supabase-store.ts +23 -1
- package/src/alphalib/types/robots/tigris-store.ts +2 -3
- package/src/alphalib/types/robots/transloadit-import.ts +4 -1
- package/src/alphalib/types/robots/transloadit-store.ts +19 -0
- package/src/alphalib/types/robots/video-adaptive.ts +12 -0
- package/src/alphalib/types/robots/video-concat.ts +9 -8
- package/src/alphalib/types/robots/video-thumbs.ts +8 -8
- package/src/alphalib/types/robots/vimeo-store.ts +1 -1
- package/src/alphalib/types/templateValues.ts +157 -0
- package/src/cli/stepsInput.ts +35 -2
|
@@ -472,6 +472,9 @@ export const vendorModelSchema = z.enum([firstSupportedModel, ...remainingSuppor
|
|
|
472
472
|
|
|
473
473
|
export type VendorModel = z.infer<typeof vendorModelSchema>
|
|
474
474
|
|
|
475
|
+
/** Reasoning effort used when the caller leaves the model on automatic selection. */
|
|
476
|
+
export const AI_CHAT_AUTO_REASONING_EFFORT = 'xhigh'
|
|
477
|
+
|
|
475
478
|
export const robotAiChatInstructionsSchema = robotBase
|
|
476
479
|
.merge(robotUse)
|
|
477
480
|
.extend({
|
|
@@ -485,7 +488,7 @@ export const robotAiChatInstructionsSchema = robotBase
|
|
|
485
488
|
.union([vendorModelSchema, z.literal('auto')])
|
|
486
489
|
.default('auto')
|
|
487
490
|
.describe(
|
|
488
|
-
'The model to use. Transloadit
|
|
491
|
+
'The model to use. The default, "auto", uses Transloadit\'s configured default model; it does not select a model based on the attached file. Choose a model that supports your input files.',
|
|
489
492
|
),
|
|
490
493
|
format: z.enum(['json', 'text', 'meta']).default('json'),
|
|
491
494
|
return_messages: z.enum(['all', 'last']).default('last'),
|
|
@@ -503,19 +506,19 @@ export const robotAiChatInstructionsSchema = robotBase
|
|
|
503
506
|
.enum(['xhigh', 'high', 'medium', 'low'])
|
|
504
507
|
.optional()
|
|
505
508
|
.describe(
|
|
506
|
-
|
|
509
|
+
`Controls how much effort the model spends on reasoning. Higher values produce more thorough responses but cost more tokens. Applies to models that support extended thinking (OpenAI o-series, GPT-5.x, GPT-6, Anthropic Claude with thinking). If omitted with model: "auto" (the default), Transloadit uses "${AI_CHAT_AUTO_REASONING_EFFORT}". With an explicitly selected model, omitting this parameter leaves reasoning effort to that model's default.`,
|
|
507
510
|
),
|
|
508
511
|
credentials: z
|
|
509
512
|
.union([z.string(), z.array(z.string())])
|
|
510
513
|
.optional()
|
|
511
514
|
.describe(
|
|
512
|
-
'Names of
|
|
515
|
+
'Names of Template Credentials to make available to the Robot. When using your own AI provider keys, you pay the provider directly and Transloadit charges a fee equal to 30% of the provider cost, with a minimum fee of $0.0005 per request.',
|
|
513
516
|
),
|
|
514
517
|
test_credentials: z
|
|
515
518
|
.boolean()
|
|
516
519
|
.optional()
|
|
517
520
|
.describe(
|
|
518
|
-
'Use Transloadit-provided credentials for testing.
|
|
521
|
+
'Use Transloadit-provided credentials for testing. Transloadit bills the provider cost plus a 30% markup, with a minimum markup of $0.0005 per request.',
|
|
519
522
|
),
|
|
520
523
|
mcp_servers: z
|
|
521
524
|
.array(
|
|
@@ -534,7 +537,7 @@ export const robotAiChatInstructionsSchema = robotBase
|
|
|
534
537
|
)
|
|
535
538
|
.optional()
|
|
536
539
|
.describe(
|
|
537
|
-
'The MCP servers to use for tool calling.
|
|
540
|
+
'The MCP servers to use for tool calling. The servers must be reachable from Transloadit\'s workers, not just from your own network. Use `headers` to pass server-specific auth (for example `Authorization: Bearer <token>`). For Transloadit\'s MCP server: Bearer tokens minted via `/token` satisfy Signature Authentication (signature checks apply only to key/secret requests). `auth: "transloadit"` is reserved for Transloadit-managed auth to Transloadit-hosted MCP servers.',
|
|
538
541
|
),
|
|
539
542
|
})
|
|
540
543
|
.strict()
|
|
@@ -5,6 +5,7 @@ import { z } from 'zod'
|
|
|
5
5
|
import { stackVersions } from '../stackVersions.ts'
|
|
6
6
|
import {
|
|
7
7
|
bitrateSchema,
|
|
8
|
+
getConcatFadeDescription,
|
|
8
9
|
inputSortBySchema,
|
|
9
10
|
interpolateRobot,
|
|
10
11
|
robotAudioEncodingMeta,
|
|
@@ -73,11 +74,11 @@ This Robot can concatenate an almost infinite number of audio files.
|
|
|
73
74
|
.describe(robotParameterDocs.audio_sample_rate.description),
|
|
74
75
|
audio_fade_seconds: z
|
|
75
76
|
.number()
|
|
76
|
-
.default(
|
|
77
|
+
.default(0)
|
|
77
78
|
.describe(`
|
|
78
|
-
|
|
79
|
+
${getConcatFadeDescription('audio')}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
When \`crossfade\` is \`true\`, this parameter controls the overlap between inputs instead of these separate fades. To add a fade-in at the beginning of the output, use an additional [audio encoding Step](/docs/robots/audio-encode/) with the \`ffmpeg\` parameter, as shown in the [fade-in and fade-out demo](/demos/audio-encoding/ffmpeg-fade-in-and-out/).
|
|
81
82
|
`),
|
|
82
83
|
crossfade: z
|
|
83
84
|
.boolean()
|
|
@@ -85,7 +86,7 @@ This parameter does not add an audio fade effect at the beginning or end of your
|
|
|
85
86
|
.describe(`
|
|
86
87
|
When set to \`true\`, this parameter enables crossfading between concatenated audio files using FFmpeg's \`acrossfade\` filter. This creates a smooth transition where the end of one audio file overlaps and blends with the beginning of the next file.
|
|
87
88
|
|
|
88
|
-
The
|
|
89
|
+
The \`audio_fade_seconds\` parameter controls the overlap duration. Omitting it or setting it to \`0\` uses a 1-second crossfade. Each overlap shortens the output by that duration; this mode does not add a fade-in at the beginning or a fade-out at the end.
|
|
89
90
|
|
|
90
91
|
Note: This parameter requires at least 2 audio files to concatenate and only works with audio files, not video files.
|
|
91
92
|
`),
|
|
@@ -22,8 +22,7 @@ import {
|
|
|
22
22
|
export const meta: RobotMetaInput = {
|
|
23
23
|
...robotImportMeta,
|
|
24
24
|
example_code: createStorageImportExample('/azure/import', 'YOUR_AZURE_CREDENTIALS', false),
|
|
25
|
-
example_code_description:
|
|
26
|
-
'Import files from the `path/to/files` directory and its subdirectories:',
|
|
25
|
+
example_code_description: 'Import files from the `path/to/files` directory:',
|
|
27
26
|
has_small_icon: true,
|
|
28
27
|
purpose_sentence: 'imports whole directories of files from your Azure container',
|
|
29
28
|
purpose_word: 'Azure',
|
|
@@ -41,14 +40,14 @@ export const robotAzureImportInstructionsSchema = robotBase
|
|
|
41
40
|
path: path.describe(`
|
|
42
41
|
The path in your container to the specific file or directory. If the path points to a file, only this file will be imported. For example: \`images/avatar.jpg\`.
|
|
43
42
|
|
|
44
|
-
If it points to a directory, indicated by a trailing slash (\`/\`), then
|
|
43
|
+
If it points to a directory, indicated by a trailing slash (\`/\`), then files directly inside this directory are imported. For example: \`images/\`. Set \`recursive: true\` to include subdirectories.
|
|
45
44
|
|
|
46
45
|
If you want to import all files from the root directory, please use \`/\` as the value here.
|
|
47
46
|
|
|
48
47
|
You can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.
|
|
49
48
|
`),
|
|
50
49
|
recursive: recursive.describe(`
|
|
51
|
-
Setting this to \`true\` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path.
|
|
50
|
+
Setting this to \`true\` will enable importing files from subdirectories and sub-subdirectories (etc.) of the given path. By default, only files directly inside the given directory are imported.
|
|
52
51
|
`),
|
|
53
52
|
next_page_token: next_page_token.describe(`
|
|
54
53
|
A string token used for pagination. The returned files of one paginated call have the next page token inside of their meta data, which needs to be used for the subsequent paging call.
|
|
@@ -38,6 +38,11 @@ A generic LibreOffice load refusal returns \`USER_COMMAND_ERROR\` with the reaso
|
|
|
38
38
|
When diagnostics identify a problem in the conversion service, the load failure returns \`INTERNAL_COMMAND_ERROR\` with the reason “${documentConvertLoadInternalErrorReason}” Private diagnostics are not included in either response.
|
|
39
39
|
`
|
|
40
40
|
|
|
41
|
+
const pdfAlternativesDocumentation = `
|
|
42
|
+
> [!Note]
|
|
43
|
+
> This <dfn>Robot</dfn> converts supported files to PDF, but does not convert PDF input to other formats. To render PDF pages as images, use [🤖/image/resize](/docs/robots/image-resize/). For native text extraction or OCR of PDF documents, use [🤖/document/extract](/docs/robots/document-extract/) and review its provider and input requirements. For OCR of images, use [🤖/image/ocr](/docs/robots/image-ocr/). These extraction Robots return recognized text; they do not add a searchable text layer to the original PDF.
|
|
44
|
+
`
|
|
45
|
+
|
|
41
46
|
export const meta: RobotMetaInput = {
|
|
42
47
|
...robotDocumentProcessingMeta,
|
|
43
48
|
example_code: createProcessingExample('converted', '/document/convert', {
|
|
@@ -45,14 +50,13 @@ export const meta: RobotMetaInput = {
|
|
|
45
50
|
}),
|
|
46
51
|
example_code_description: 'Convert uploaded files to PDF documents:',
|
|
47
52
|
extended_description: `
|
|
48
|
-
|
|
49
|
-
> This <dfn>Robot</dfn> can convert files to PDF, but cannot convert PDFs to different formats. If you want to convert PDFs to say, JPEG or TIFF, use [🤖/image/resize](/docs/robots/image-resize/). If you want to turn them into text files or recognize (OCR) them to make them searchable, reach out, as we have a new <dfn>Robot</dfn> in the works for this.
|
|
53
|
+
${pdfAlternativesDocumentation}
|
|
50
54
|
|
|
51
55
|
Sometimes, a certain file type might not support what you are trying to accomplish. Perhaps your company is trying to automate document formatting, but it only works with docx, so all your docs need to be converted. Or maybe your stored jpg files are taking up too much space and you want a lighter format. Whatever the case, we have you covered.
|
|
52
56
|
|
|
53
57
|
Using this <dfn>Robot</dfn>, you can bypass the issues that certain file types may bring, by converting your file into the most suitable format. This also works in conjunction with our other <dfn>Robots</dfn>, allowing for even greater versatility when using our services.
|
|
54
58
|
|
|
55
|
-
> !
|
|
59
|
+
> [!Warning]
|
|
56
60
|
> A general rule of this <dfn>Robot</dfn> is that converting files into an alien format category will result in an error. For example, SRT files can be converted into the VTT format, but not to an image.
|
|
57
61
|
|
|
58
62
|
${documentLoadErrorDocumentation}
|
|
@@ -122,8 +126,7 @@ export const robotDocumentConvertInstructionsSchema = robotBase
|
|
|
122
126
|
robot: z.literal('/document/convert').describe(`
|
|
123
127
|
${htmlPdfReadinessDescription}
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
> This Robot can convert files to PDF, but cannot convert PDFs to different formats. If you want to convert PDFs to say, JPEG or TIFF, use [🤖/image/resize](/docs/robots/image-resize/). If you want to turn them into text files or recognize (OCR) them to make them searchable, reach out, as we have a new Robot in the works for this.
|
|
129
|
+
${pdfAlternativesDocumentation}
|
|
127
130
|
|
|
128
131
|
Sometimes, a certain file type might not support what you are trying to accomplish. Perhaps your company is trying to automate document formatting, but it only works with docx, so all your docs need to be converted. Or maybe your stored jpg files are taking up too much space and you want a lighter format. Whatever the case, we have you covered.
|
|
129
132
|
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
const extractTargets = z.enum(['text', 'images'])
|
|
20
20
|
const imageFormats = z.enum(['auto', 'original', 'png', 'jpg'])
|
|
21
21
|
const ocrProviders = z.enum(['aws', 'gcp'])
|
|
22
|
-
const textFormats = z.enum(['txt', 'json'])
|
|
22
|
+
const textFormats = z.enum(['txt', 'json', 'md', 'html'])
|
|
23
23
|
const textGranularities = z.enum(['document', 'page'])
|
|
24
24
|
const textMethods = z.enum(['native', 'ocr', 'auto'])
|
|
25
25
|
|
|
@@ -120,6 +120,10 @@ export const robotDocumentExtractInstructionsSchema = robotBase
|
|
|
120
120
|
robot: z.literal('/document/extract').describe(`
|
|
121
121
|
Extracts native/selectable text and embedded raster image assets from PDF documents.
|
|
122
122
|
|
|
123
|
+
For DOCX files, first use \`/document/convert\` with \`format: "pdf"\`, then pass its output to this Robot.
|
|
124
|
+
|
|
125
|
+
Markdown and HTML output are in beta and aim for readable structure, not a pixel-perfect copy. Native extraction detects paragraphs, larger-font headings, simple lists and aligned tables where possible. Multi-column text can interleave, prose can be mistaken for tables, and merged cells may need adjustment. HTML escapes extracted text and omits source scripts, links and event handlers.
|
|
126
|
+
|
|
123
127
|
This robot does not render full pages. If you need page images, use \`/document/thumbs\`. Vector graphics, charts, and page backgrounds are not always embedded raster images and may therefore not be returned by this robot.
|
|
124
128
|
`),
|
|
125
129
|
extract: z
|
|
@@ -163,7 +167,19 @@ OCR modes currently cannot be combined with \`password\`.
|
|
|
163
167
|
OCR provider to use when \`text_method\` is \`"ocr"\` or \`"auto"\`. Valid values are \`"aws"\` and \`"gcp"\`.
|
|
164
168
|
`),
|
|
165
169
|
text_format: textFormats.default('txt').describe(`
|
|
166
|
-
Output format for extracted text.
|
|
170
|
+
Output format for extracted text. Plain text and JSON retain the existing extraction behavior. Markdown and HTML output are in beta and infer basic structure from native text positions and font sizes.
|
|
171
|
+
|
|
172
|
+
Native Markdown and HTML extraction limits layout data to 8 MiB per input document, summed across its selected page ranges. For larger documents, use separate extraction Steps with fewer pages in each Step’s \`page_range\`.
|
|
173
|
+
|
|
174
|
+
If native extraction cannot confirm the reading order of bidirectional text, it returns a validation error. Try fewer pages or use \`text_method: "ocr"\` with an OCR provider.
|
|
175
|
+
|
|
176
|
+
When \`extract\` includes images, Markdown and HTML reference retained image results inline using relative, URL-encoded filenames matching each image result’s \`name\`. Save the text and image results together to resolve the references. Filtered images have no references; repeated images can reference the same deduplicated result. Images with unavailable or inconsistent positions, including retained image masks, are appended after their page’s text. Embedded base64 images are not produced.
|
|
177
|
+
|
|
178
|
+
When exporting, preserve result names in a shared directory per input document. For example, set \`/s3/store\`’s \`path\` to \`"\${assembly.id}/\${file.original_id}/\${file.name}"\`. Default storage paths using \`\${unique_prefix}/\${file.url_name}\` separate and rename files, so they do not preserve these relative image links.
|
|
179
|
+
|
|
180
|
+
Some native image encodings cannot be displayed by browsers or Markdown viewers. Set \`image_format\` to \`"png"\` or \`"jpg"\` for broadly viewable image results.
|
|
181
|
+
|
|
182
|
+
OCR Markdown and HTML preserve readable text with minimal structure detection and append extracted images in source order, since reliable text positions are unavailable.
|
|
167
183
|
`),
|
|
168
184
|
text_granularity: textGranularities.default('document').describe(`
|
|
169
185
|
Controls text output grouping for native extraction.
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
|
|
7
7
|
import { z } from 'zod'
|
|
8
8
|
|
|
9
|
+
import { expressionEvaluationUsageMebibytes } from '../templateValues.ts'
|
|
9
10
|
import {
|
|
10
11
|
createProcessingExample,
|
|
11
12
|
defineRobot,
|
|
@@ -32,13 +33,27 @@ export const meta: RobotMetaInput = {
|
|
|
32
33
|
export const robotDocumentSplitInstructionsSchema = robotBase
|
|
33
34
|
.merge(robotUse)
|
|
34
35
|
.extend({
|
|
35
|
-
robot: z.literal('/document/split')
|
|
36
|
+
robot: z.literal('/document/split').describe(`
|
|
37
|
+
By default, this Robot returns one PDF containing the selected pages and keeps the input file name. If \`pages\` is omitted, that PDF contains every page.
|
|
38
|
+
|
|
39
|
+
Set \`split: true\` to return separate PDFs. Without \`pages\`, each page becomes its own PDF. With \`pages\`, each entry becomes one PDF: \`pages: ["1", "2-3"]\` returns a one-page PDF and a two-page PDF. For an input named \`document.pdf\`, these files are named \`document_page_1.pdf\` and \`document_pages_2-3.pdf\`. Repeated selections receive an additional numeric suffix to keep file names unique, such as \`document_page_1_2.pdf\`.
|
|
40
|
+
|
|
41
|
+
Page numbers start at 1. When the page count is known, ranges are clamped to it and selections entirely beyond it are skipped. Split file names use the resulting page or range. An empty \`pages\` array is invalid in split mode; omit \`pages\` to split every page. If all selections exceed the page count, processing fails with a validation error.
|
|
42
|
+
`),
|
|
36
43
|
pages: z
|
|
37
44
|
.union([z.string(), z.array(z.string())])
|
|
38
45
|
.describe(
|
|
39
|
-
|
|
46
|
+
`The pages to select from the input PDF. Each entry can be a single page number (e.g. \`5\`) or a range (e.g. \`5-10\`). Page numbers start at 1. Accepts an array or a comma-separated string. By default, all selected pages are combined into one PDF; with \`split: true\`, each entry produces a separate PDF. If omitted, selects all pages.
|
|
47
|
+
|
|
48
|
+
For a PDF with at least three pages, \`pages: ["\${file.meta.page_count - 2}-\${file.meta.page_count}"]\` selects the last three pages. Each dynamically evaluated expression adds ${expressionEvaluationUsageMebibytes} MiB of usage per input file; simple variable references such as \`\${file.meta.page_count}\` are free.`,
|
|
40
49
|
)
|
|
41
50
|
.optional(),
|
|
51
|
+
split: z
|
|
52
|
+
.boolean()
|
|
53
|
+
.default(false)
|
|
54
|
+
.describe(
|
|
55
|
+
'Return one PDF per `pages` entry, or one PDF per page when `pages` is omitted. File names include a page or range suffix, such as `document_page_1.pdf` or `document_pages_2-3.pdf`. Split selections and output PDFs are subject to the service’s per-Job file limit. By default, returns one PDF containing all selected pages and keeps the input file name.',
|
|
56
|
+
),
|
|
42
57
|
})
|
|
43
58
|
.strict()
|
|
44
59
|
|
|
@@ -69,6 +69,8 @@ This <dfn>Robot</dfn> also detects and handles any of the following before evalu
|
|
|
69
69
|
|
|
70
70
|
For security reasons, archives containing symlinks that point outside the archived directory will cause the <dfn>Assembly</dfn> to fail.
|
|
71
71
|
|
|
72
|
+
Extracted file and directory names are transliterated for supported accented Latin and Cyrillic characters. For example, \`café.pdf\` becomes \`cafe.pdf\`.
|
|
73
|
+
|
|
72
74
|
Password-protected archives (ZIP with ZipCrypto or AES encryption, RAR encrypted, 7z with AES-256) are supported via the \`password\` parameter.
|
|
73
75
|
`),
|
|
74
76
|
ignore_errors:
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
complexWidthSchema,
|
|
13
13
|
createProcessingExample,
|
|
14
14
|
defineRobot,
|
|
15
|
+
imageQualityValueSchema,
|
|
15
16
|
optimize_priority,
|
|
16
17
|
resize_strategy,
|
|
17
18
|
robotBase,
|
|
@@ -19,6 +20,17 @@ import {
|
|
|
19
20
|
robotUse,
|
|
20
21
|
} from './_instructions-primitives.ts'
|
|
21
22
|
|
|
23
|
+
/** Fallback order shared by schema defaults, published examples and worker normalization. */
|
|
24
|
+
export const filePreviewStrategyDefaults = {
|
|
25
|
+
archive: ['icon'],
|
|
26
|
+
audio: ['artwork', 'waveform', 'icon'],
|
|
27
|
+
document: ['page', 'icon'],
|
|
28
|
+
image: ['image', 'embedded-preview', 'icon'],
|
|
29
|
+
unknown: ['icon'],
|
|
30
|
+
video: ['artwork', 'frame', 'icon'],
|
|
31
|
+
webpage: ['render', 'icon'],
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
export const meta: RobotMetaInput = {
|
|
23
35
|
...robotMediaCatalogingMeta,
|
|
24
36
|
example_code: createProcessingExample('previewed', '/file/preview', {
|
|
@@ -44,17 +56,20 @@ export const robotFilePreviewInstructionsSchema = robotBase
|
|
|
44
56
|
.merge(robotUse)
|
|
45
57
|
.extend({
|
|
46
58
|
robot: z.literal('/file/preview').describe(`
|
|
47
|
-
This <dfn>Robot</dfn>'s purpose is to generate a meaningful preview image for any file, in such a way that the resulting thumbnail highlights the file's content. The goal is not to losslessly present the original media in a smaller way. Instead, it is to maximize the chance of a person recognizing the media at a glance, while being visually pleasing and consistent with other previews. The generation process depends on the file type. For example, the <dfn>Robot</dfn> can extract artwork from media files, frames from videos, generate a waveform for audio files, and preview the content of documents and images. The
|
|
59
|
+
This <dfn>Robot</dfn>'s purpose is to generate a meaningful preview image for any file, in such a way that the resulting thumbnail highlights the file's content. The goal is not to losslessly present the original media in a smaller way. Instead, it is to maximize the chance of a person recognizing the media at a glance, while being visually pleasing and consistent with other previews. The generation process depends on the file type. For example, the <dfn>Robot</dfn> can extract artwork from media files, frames from videos, generate a waveform for audio files, and preview the content of documents and images. The [\`strategy\` parameter](#strategy) lists the available strategies and controls their fallback order.
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
With the default strategy configuration, a generic icon is the fallback when no file-specific thumbnail can be generated. The default \`with-text\` icon style includes the file extension; \`icon_style\` and \`icon_text_content\` control its appearance.
|
|
50
62
|
|
|
51
|
-
The default parameters
|
|
63
|
+
The default parameters produce still previews at the configured dimensions and format for integration into your application's UI. The optional \`clip\` strategy produces animated previews using \`clip_format\`. Preview images are optimized by default to reduce their file size while maintaining visual quality.
|
|
52
64
|
`),
|
|
53
65
|
format: z
|
|
54
66
|
.enum(['avif', 'gif', 'jpeg', 'jpg', 'png', 'webp'])
|
|
55
67
|
.default('png')
|
|
56
68
|
.describe(`
|
|
57
|
-
The output format for the generated thumbnail image.
|
|
69
|
+
The output format for the generated thumbnail image. If a short video clip is generated using the \`clip\` strategy, its format is defined by \`clip_format\`.
|
|
70
|
+
`),
|
|
71
|
+
quality: imageQualityValueSchema.optional().describe(`
|
|
72
|
+
Compression quality for still previews, from 1 to 100. When specified, the final image resize encodes directly into the requested format at this quality and strips embedded metadata. Omit it to retain the default encoding behavior. Animated clips use their own encoding settings. If \`optimize\` is enabled, optimization runs after this encoding.
|
|
58
73
|
`),
|
|
59
74
|
width: complexWidthSchema.default(300).describe(`
|
|
60
75
|
Width of the thumbnail, in pixels.
|
|
@@ -80,32 +95,36 @@ Note that this parameter only affects strategies that produce a still image. Ani
|
|
|
80
95
|
`),
|
|
81
96
|
strategy: z
|
|
82
97
|
.object({
|
|
83
|
-
archive: z.array(z.string()).default(
|
|
84
|
-
audio: z.array(z.string()).default(
|
|
85
|
-
document: z.array(z.string()).default(
|
|
86
|
-
image: z.array(z.string()).default(
|
|
87
|
-
unknown: z.array(z.string()).default(
|
|
88
|
-
video: z.array(z.string()).default(
|
|
89
|
-
webpage: z.array(z.string()).default(
|
|
98
|
+
archive: z.array(z.string()).default(filePreviewStrategyDefaults.archive),
|
|
99
|
+
audio: z.array(z.string()).default(filePreviewStrategyDefaults.audio),
|
|
100
|
+
document: z.array(z.string()).default(filePreviewStrategyDefaults.document),
|
|
101
|
+
image: z.array(z.string()).default(filePreviewStrategyDefaults.image),
|
|
102
|
+
unknown: z.array(z.string()).default(filePreviewStrategyDefaults.unknown),
|
|
103
|
+
video: z.array(z.string()).default(filePreviewStrategyDefaults.video),
|
|
104
|
+
webpage: z.array(z.string()).default(filePreviewStrategyDefaults.webpage),
|
|
90
105
|
})
|
|
91
106
|
.optional()
|
|
92
107
|
.describe(`
|
|
93
|
-
Definition of the thumbnail generation process per file category.
|
|
108
|
+
Definition of the thumbnail generation process per file category. Each key selects a file category and its value is an ordered array of strategies:
|
|
109
|
+
|
|
110
|
+
| File category | Available strategies |
|
|
111
|
+
|---------------|----------------------|
|
|
112
|
+
| \`audio\` | \`artwork\`, \`waveform\`, \`icon\` |
|
|
113
|
+
| \`video\` | \`artwork\`, \`frame\`, \`clip\`, \`icon\` |
|
|
114
|
+
| \`image\` | \`image\`, \`embedded-preview\`, \`icon\` |
|
|
115
|
+
| \`document\` | \`page\`, \`icon\` |
|
|
116
|
+
| \`archive\` | \`icon\` |
|
|
117
|
+
| \`webpage\` | \`render\`, \`icon\` |
|
|
118
|
+
| \`unknown\` | \`icon\` |
|
|
119
|
+
|
|
120
|
+
\`artwork\` extracts embedded artwork, \`waveform\` draws an audio waveform, \`frame\` extracts a video frame, and \`clip\` creates an animated video preview. For images, \`image\` resizes the original and \`embedded-preview\` extracts an embedded preview when available. \`page\` renders the first document page, \`render\` captures a webpage, and \`icon\` generates a file-type icon.
|
|
94
121
|
|
|
95
122
|
For each file, the <dfn>Robot</dfn> will attempt to use the first strategy to generate the thumbnail. If this process fails (e.g., because no artwork is available in a video file), the next strategy is attempted. This is repeated until either a thumbnail is generated or the list is exhausted. Selecting the \`icon\` strategy as the last entry provides a fallback mechanism to ensure that an appropriate strategy is always available.
|
|
96
123
|
|
|
97
124
|
The parameter defaults to the following definition:
|
|
98
125
|
|
|
99
126
|
\`\`\`json
|
|
100
|
-
{
|
|
101
|
-
"audio": ["artwork", "waveform", "icon"],
|
|
102
|
-
"video": ["artwork", "frame", "icon"],
|
|
103
|
-
"document": ["page", "icon"],
|
|
104
|
-
"image": ["image", "icon"],
|
|
105
|
-
"webpage": ["render", "icon"],
|
|
106
|
-
"archive": ["icon"],
|
|
107
|
-
"unknown": ["icon"]
|
|
108
|
-
}
|
|
127
|
+
${JSON.stringify(filePreviewStrategyDefaults, null, 2)}
|
|
109
128
|
\`\`\`
|
|
110
129
|
`),
|
|
111
130
|
artwork_outer_color: color_with_alpha.optional().describe(`
|
|
@@ -163,13 +182,13 @@ The font family of the text used in the icon. Only used if the \`icon\` strategy
|
|
|
163
182
|
.enum(['extension', 'none'])
|
|
164
183
|
.default('extension')
|
|
165
184
|
.describe(`
|
|
166
|
-
The content of the text box in generated icons. Only used if the \`icon_style\` parameter is set to \`with-text\`. The default value, \`extension\`, adds the file extension (e.g. MP4, JPEG) to the icon. The value \`none\`
|
|
185
|
+
The content of the text box in generated icons. Only used if the \`icon_style\` parameter is set to \`with-text\`. The default value, \`extension\`, adds the file extension (e.g. MP4, JPEG) to the icon. The value \`none\` leaves the text box empty while reserving space for a custom text overlay, for example using HTML in your application.
|
|
167
186
|
`),
|
|
168
187
|
optimize: z
|
|
169
188
|
.boolean()
|
|
170
189
|
.default(true)
|
|
171
190
|
.describe(`
|
|
172
|
-
Specifies whether the generated preview image should be optimized to reduce
|
|
191
|
+
Specifies whether the generated preview image should be optimized to reduce its file size while maintaining visual quality. If enabled, the image will be optimized using [🤖/image/optimize](/docs/robots/image-optimize/).
|
|
173
192
|
`),
|
|
174
193
|
optimize_priority: optimize_priority.default('conversion-speed').describe(`
|
|
175
194
|
Specifies whether conversion speed or compression ratio is prioritized when optimizing images. Only used if \`optimize\` is enabled. Please see the [🤖/image/optimize documentation](/docs/robots/image-optimize/#priority) for more details.
|
|
@@ -186,14 +205,14 @@ Specifies whether images should be interlaced, which makes the result image load
|
|
|
186
205
|
.describe(`
|
|
187
206
|
The animated image format for the generated video clip. Only used if the \`clip\` strategy for video files is applied.
|
|
188
207
|
|
|
189
|
-
Please consult the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types) for detailed information about the image formats and their characteristics. GIF enjoys
|
|
208
|
+
Please consult the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types) for detailed information about the image formats and their characteristics. GIF enjoys broad support in software, but only supports a limited color palette. APNG supports a variety of color depths, but its lossless compression produces large images for videos. AVIF offers efficient compression, but animation support varies between browsers. WebP offers a balance between small file sizes and visual quality and is the default clip format.
|
|
190
209
|
`),
|
|
191
210
|
clip_offset: z
|
|
192
211
|
.number()
|
|
193
212
|
.min(0)
|
|
194
213
|
.default(1)
|
|
195
214
|
.describe(`
|
|
196
|
-
The start position in seconds of where the clip is cut. Only used if the \`clip\` strategy for video files is applied.
|
|
215
|
+
The start position in seconds of where the clip is cut. Only used if the \`clip\` strategy for video files is applied. For large videos, only portions of the file may be imported to improve speed. An offset outside the available media data can prevent clip generation.
|
|
197
216
|
`),
|
|
198
217
|
clip_duration: z
|
|
199
218
|
.number()
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
import { z } from 'zod'
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
|
+
createProcessingExample,
|
|
10
11
|
defineRobot,
|
|
11
12
|
httpHeaderSafetyDescription,
|
|
12
13
|
httpUrlSchema,
|
|
@@ -17,17 +18,11 @@ import {
|
|
|
17
18
|
|
|
18
19
|
export const meta: RobotMetaInput = {
|
|
19
20
|
...robotCodeEvaluationMeta,
|
|
20
|
-
example_code: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
payload: 'metadata',
|
|
26
|
-
url: 'https://example.com/transloadit/files',
|
|
27
|
-
use: [],
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
},
|
|
21
|
+
example_code: createProcessingExample('request', '/http/request', {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
payload: 'metadata',
|
|
24
|
+
url: 'https://example.com/transloadit/files',
|
|
25
|
+
}),
|
|
31
26
|
example_code_description: 'Ask your application which input files should continue:',
|
|
32
27
|
extended_description: `
|
|
33
28
|
Use this <dfn>Robot</dfn> when your application should inspect the current Assembly state or input
|
|
@@ -56,7 +51,7 @@ in the Assembly Template and use this Step as their input.
|
|
|
56
51
|
`,
|
|
57
52
|
override_lvl1: 'Workflow Automation',
|
|
58
53
|
purpose_sentence:
|
|
59
|
-
'calls your application during an Assembly and emits
|
|
54
|
+
'calls your application during an Assembly and emits selected input files or downloads returned result-file URLs',
|
|
60
55
|
purpose_verb: 'run',
|
|
61
56
|
purpose_word: 'HTTP endpoint',
|
|
62
57
|
purpose_words: 'Call HTTP endpoints',
|
|
@@ -100,7 +95,8 @@ Controls what is sent to your endpoint.
|
|
|
100
95
|
- \`file\`: Send multipart form data with a \`payload\` JSON field and the first input file as a
|
|
101
96
|
\`file\` part.
|
|
102
97
|
- \`files\`: Send multipart form data with a \`payload\` JSON field and all input files as repeated
|
|
103
|
-
\`files[]\` parts.
|
|
98
|
+
\`files[]\` parts. To send several input files in one request, set \`bundle_steps: true\` in the
|
|
99
|
+
advanced [\`use\` options](/docs/topics/use-parameter/#step-bundling).
|
|
104
100
|
|
|
105
101
|
The \`payload\` JSON object contains \`assembly\`, \`fields\`, \`previous_step\`, \`file\`, and
|
|
106
102
|
\`files\`. \`file\` is the first input file’s metadata or \`null\`; \`files\` is an array of input
|
|
@@ -77,11 +77,11 @@ export const robotImageEnhanceInstructionsSchema = robotBase
|
|
|
77
77
|
.merge(robotImagemagick)
|
|
78
78
|
.extend({
|
|
79
79
|
robot: z.literal('/image/enhance').describe(`
|
|
80
|
-
With this <dfn>Robot</dfn> you can automatically enhance images
|
|
80
|
+
With this <dfn>Robot</dfn> you can automatically enhance images by adjusting levels, gamma, and sharpness. The selected enhancement mode determines which adjustments are applied. It also supports named photo filter presets (e.g. \`warm\`, \`cool\`, \`vintage\`, \`vivid\`) for color grading and tone adjustments.
|
|
81
81
|
|
|
82
82
|
It works well together with [🤖/image/resize](/docs/robots/image-resize/) — you can enhance first, then resize, or vice versa.
|
|
83
83
|
|
|
84
|
-
This <dfn>Robot</dfn> accepts all image types supported by ImageMagick and passes unsupported types through unchanged. \`engine: "classic"\` uses \`enhance\`, \`preset\`, \`sharpen\`, and \`denoise\`, while \`engine: "ai"\` uses \`ai_preset
|
|
84
|
+
This <dfn>Robot</dfn> accepts all image types supported by ImageMagick and passes unsupported image types through unchanged. \`engine: "classic"\` uses \`enhance\`, \`preset\`, \`sharpen\`, and \`denoise\`, while \`engine: "ai"\` uses \`ai_preset\`; classic controls are ignored in AI mode. Both engines use \`quality\` for the output image. Output keeps the original file extension when possible. In AI mode, if the target extension is not writable by the selected \`imagemagick_stack\`, the file is passed through unchanged.
|
|
85
85
|
`),
|
|
86
86
|
enhance: enhanceModeSchema.describe(`
|
|
87
87
|
The auto-enhancement mode. \`"auto"\` applies balanced auto-levels, gamma correction, and subtle sharpening. \`"auto_gentle"\` is more conservative (good for already-decent photos). \`"auto_aggressive"\` applies stronger normalization and contrast. \`"none"\` skips auto-enhance (useful when only applying a preset filter).
|
|
@@ -443,7 +443,7 @@ Changes the hue by rotating the color of the image. The value \`100\` would prod
|
|
|
443
443
|
.max(2)
|
|
444
444
|
.default(1)
|
|
445
445
|
.describe(`
|
|
446
|
-
Adjusts the contrast of the image. A value of \`1\` produces no change. Values below \`1\` decrease contrast
|
|
446
|
+
Adjusts the contrast of the image. A value of \`1\` produces no change. Values below \`1\` decrease contrast, and values above \`1\` increase it. Start with small adjustments, such as \`0.9\` or \`1.1\`. Larger increases can clip shadows and highlights.
|
|
447
447
|
`),
|
|
448
448
|
watermark_url: httpUrlSchema.optional().describe(`
|
|
449
449
|
A URL indicating a PNG image to be overlaid above this image. Please note that you can also [supply the watermark via another Assembly Step](/docs/topics/use-parameter/#supplying-the-watermark-via-an-assembly-step). With watermarking you can add an image onto another image. This is usually used for logos.
|
|
@@ -480,6 +480,8 @@ Values can be both positive and negative and yield different results depending o
|
|
|
480
480
|
The size of the watermark, as a percentage.
|
|
481
481
|
|
|
482
482
|
For example, a value of \`"50%"\` means that size of the watermark will be 50% of the size of image on which it is placed. The exact sizing depends on \`watermark_resize_strategy\`, too.
|
|
483
|
+
|
|
484
|
+
With \`watermark_repeat_x\` or \`watermark_repeat_y\`, this sizes each tile relative to the output image, before repeating it. It does not set the percentage of the image covered by the whole pattern. Smaller values produce more, smaller tiles. If omitted, the watermark keeps its original pixel dimensions.
|
|
483
485
|
`),
|
|
484
486
|
watermark_resize_strategy: z
|
|
485
487
|
.enum(['area', 'fit', 'min_fit', 'stretch'])
|
|
@@ -70,7 +70,7 @@ export const robotImageUpscaleInstructionsSchema = robotBase
|
|
|
70
70
|
face_enhance: upscaleFaceEnhanceSchema
|
|
71
71
|
.optional()
|
|
72
72
|
.describe(
|
|
73
|
-
`Enable face enhancement
|
|
73
|
+
`Enable face enhancement with Real-ESRGAN or face upsampling with CodeFormer. GFPGAN always performs face restoration and ignores this parameter. Defaults to ${upscaleFaceEnhanceSchema.parse(undefined)}.`,
|
|
74
74
|
),
|
|
75
75
|
})
|
|
76
76
|
.strict()
|
|
@@ -43,40 +43,39 @@ export const robotS3ImportInstructionsSchema = robotBase
|
|
|
43
43
|
robot: z.literal('/s3/import').describe(`
|
|
44
44
|
If you are new to Amazon S3, see our tutorial on [using your own S3 bucket](/docs/faq/how-to-set-up-an-amazon-s3-bucket/).
|
|
45
45
|
|
|
46
|
-
The URL to the result file in your S3 bucket will be returned in the <dfn>Assembly Status JSON</dfn>.
|
|
47
|
-
|
|
48
|
-
> [!Warning]
|
|
49
|
-
> **Use DNS-compliant bucket names**. Your bucket name [must be DNS-compliant](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html) and must not contain uppercase letters. Any non-alphanumeric characters in the file names will be replaced with an underscore, and spaces will be replaced with dashes. If your existing S3 bucket contains uppercase letters or is otherwise not DNS-compliant, rewrite the result URLs using the <dfn>Robot</dfn>’s \`url_prefix\` parameter.
|
|
50
|
-
|
|
51
46
|
<span id="minimum-s3-iam-permissions" aria-hidden="true"></span>
|
|
52
47
|
|
|
53
48
|
## Limit access
|
|
54
49
|
|
|
55
|
-
|
|
50
|
+
Use dedicated AWS credentials in your <dfn>Template Credentials</dfn> and grant that IAM identity access only to the bucket and objects it needs. The following example is an **identity-based IAM policy** for reading current objects from one general purpose S3 bucket. Attach it to the IAM user or role whose credentials you supply to Transloadit, not to the bucket. An identity-based policy has no \`Principal\` element: it applies to the identity it is attached to.
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
Replace \`{BUCKET_NAME}\` in both \`Resource\` values with your bucket name. The bucket-level statement permits listing objects and discovering the bucket's region; the object-level statement permits downloading them. See [AWS's S3 operation permissions](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-policy-actions.html) and [identity-based versus resource-based policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html).
|
|
58
53
|
|
|
59
54
|
\`\`\`json
|
|
60
55
|
{
|
|
61
56
|
"Version": "2012-10-17",
|
|
62
57
|
"Statement": [
|
|
63
58
|
{
|
|
64
|
-
"Sid": "
|
|
59
|
+
"Sid": "ReadBucketMetadata",
|
|
65
60
|
"Effect": "Allow",
|
|
66
61
|
"Action": ["s3:GetBucketLocation", "s3:ListBucket"],
|
|
67
|
-
"Resource":
|
|
62
|
+
"Resource": "arn:aws:s3:::{BUCKET_NAME}"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"Sid": "ReadBucketObjects",
|
|
66
|
+
"Effect": "Allow",
|
|
67
|
+
"Action": "s3:GetObject",
|
|
68
|
+
"Resource": "arn:aws:s3:::{BUCKET_NAME}/*"
|
|
68
69
|
}
|
|
69
70
|
]
|
|
70
71
|
}
|
|
71
72
|
\`\`\`
|
|
72
73
|
|
|
73
|
-
The \`Sid\`
|
|
74
|
-
|
|
75
|
-
The policy needs to be separated into two parts, because the \`ListBucket\` action requires permissions on the bucket while the other actions require permissions on the objects in the bucket. When targeting the objects there's a trailing slash and an asterisk in the \`Resource\` parameter, whereas when the policy targets the bucket, the slash and the asterisk are omitted.
|
|
74
|
+
The \`Sid\` values are labels for recognizing statements. Supplying the correct \`bucket_region\` avoids automatic region discovery and its \`s3:GetBucketLocation\` permission. The example still grants bucket-wide listing and reads: narrow its object resources and listing conditions when your workflow needs only a specific prefix.
|
|
76
75
|
|
|
77
|
-
|
|
76
|
+
This example is not a guarantee of access. Explicit denies, organization policies, permission boundaries, cross-account bucket policies, and object ownership can affect the result. For cross-account access, review [AWS's policy evaluation guidance](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html).
|
|
78
77
|
|
|
79
|
-
|
|
78
|
+
For SSE-KMS-encrypted objects, also configure the IAM identity and KMS key policy with the key permissions required by [AWS's GetObject documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html), scoped to the intended key. KMS actions belong in IAM identity policies and KMS key policies, **not S3 bucket policies**. Do not grant broad \`sts:*\` or \`kms:*\` permissions as a workaround.
|
|
80
79
|
`),
|
|
81
80
|
path: path.describe(`
|
|
82
81
|
The path in your bucket to the specific file or directory. If the path points to a file, only this file will be imported. For example: \`images/avatar.jpg\`.
|
|
@@ -85,7 +84,7 @@ If it points to a directory, indicated by a trailing slash (\`/\`), then all fil
|
|
|
85
84
|
|
|
86
85
|
Directories are **not** imported recursively. If you want to import files from subdirectories and sub-subdirectories, enable the \`recursive\` parameter.
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
Use \`/\` to import files from the bucket root. Object keys do not need a leading slash. Enable \`recursive\` to include files under nested prefixes.
|
|
89
88
|
|
|
90
89
|
You can also use an array of path strings here to import multiple paths in the same <dfn>Robot</dfn>'s <dfn>Step</dfn>.
|
|
91
90
|
`),
|
|
@@ -33,8 +33,30 @@ export const robotSupabaseStoreInstructionsSchema = robotBase
|
|
|
33
33
|
.merge(robotUse)
|
|
34
34
|
.merge(supabaseBase)
|
|
35
35
|
.extend({
|
|
36
|
-
robot: z.literal('/supabase/store')
|
|
36
|
+
robot: z.literal('/supabase/store').describe(`
|
|
37
|
+
## Upload as a Supabase user
|
|
38
|
+
|
|
39
|
+
For [Supabase session-token authentication](https://supabase.com/docs/guides/storage/s3/authentication#session-token), supply your project ref as \`key\`, your project’s anon key as \`secret\`, and the user’s access-token JWT as \`session_token\`. Supabase applies the authenticated user’s Row Level Security (RLS) policies to these uploads. Choose a \`path\` those policies permit, and use the endpoint and region from your project’s S3 connection settings.
|
|
40
|
+
|
|
41
|
+
Send the user’s JWT with each Assembly from your trusted backend. It must remain valid through queuing, processing, and upload retries; the Robot does not refresh it. Without \`session_token\`, continue using your generated Supabase S3 access key and secret. Those generated S3 access keys bypass RLS.
|
|
42
|
+
|
|
43
|
+
Supply \`session_token\` inline in the Step. Assembly Status returns \`fields\` unchanged, so passing the JWT through Assembly \`fields\` exposes it in the status response.
|
|
44
|
+
|
|
45
|
+
The result URL uses Supabase’s public-object URL format. It does not grant read access to a private bucket; use Supabase’s download authorization for private objects.
|
|
46
|
+
`),
|
|
47
|
+
credentials: supabaseBase.shape.credentials.describe(`
|
|
48
|
+
The name of your Supabase <dfn>Template Credentials</dfn>, containing the bucket, host, key, secret, and bucket region. You can instead supply those parameters directly in the Step.
|
|
49
|
+
|
|
50
|
+
For generated S3 access-key authentication, use the endpoint and S3 access keys from your Supabase project’s S3 connection settings. For user-scoped session-token authentication, use the project ref as \`key\` and the project’s anon key as \`secret\`, then supply the user’s access-token JWT as \`session_token\` with each Assembly.
|
|
51
|
+
`),
|
|
37
52
|
path: storeFilePath,
|
|
53
|
+
session_token: z
|
|
54
|
+
.string()
|
|
55
|
+
.min(1)
|
|
56
|
+
.optional()
|
|
57
|
+
.describe(`
|
|
58
|
+
The user’s Supabase access-token JWT for [session-token authentication](https://supabase.com/docs/guides/storage/s3/authentication#session-token). Use the Supabase project ref as \`key\` and the project’s anon key as \`secret\` so Supabase applies that user’s RLS policies. The JWT must remain valid through queuing, processing, and upload retries; the Robot does not refresh it. Supply this value directly in the Step; Assembly Status exposes values in \`fields\`.
|
|
59
|
+
`),
|
|
38
60
|
headers: z
|
|
39
61
|
.record(z.string())
|
|
40
62
|
.default({ 'Content-Type': '${file.mime}' })
|