@transloadit/node 4.10.8 → 4.11.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.
@@ -3,7 +3,11 @@ import type { Readable } from 'node:stream'
3
3
  import type { StepsInput } from '../../alphalib/types/template.ts'
4
4
  import type { CreateAssemblyParams, ReplayAssemblyParams } from '../../apiTypes.ts'
5
5
  import type { LintFatalLevel } from '../../lintAssemblyInstructions.ts'
6
- import type { CreateAssemblyOptions, Transloadit } from '../../Transloadit.ts'
6
+ import type {
7
+ CompileAssemblyInstructionsFromPromptOptions,
8
+ CreateAssemblyOptions,
9
+ Transloadit,
10
+ } from '../../Transloadit.ts'
7
11
  import type { IOutputCtl } from '../OutputCtl.ts'
8
12
  import type { NormalizedAssemblyResultFile, NormalizedAssemblyResults } from '../resultFiles.ts'
9
13
  import type { ResultUrlRow } from '../resultUrls.ts'
@@ -44,7 +48,7 @@ import {
44
48
  import { formatAPIError, readCliInput } from '../helpers.ts'
45
49
  import { normalizeAssemblyResults } from '../resultFiles.ts'
46
50
  import { collectNormalizedResultUrlRows, printResultUrls } from '../resultUrls.ts'
47
- import { readStepsInputFile } from '../stepsInput.ts'
51
+ import { parseStepsInputJson, readStepsInputFile } from '../stepsInput.ts'
48
52
  import { ensureError, isErrnoException } from '../types.ts'
49
53
  import { AuthenticatedCommand, UnauthenticatedCommand } from './BaseCommand.ts'
50
54
 
@@ -82,6 +86,14 @@ export interface AssemblyLintOptions {
82
86
  json?: boolean
83
87
  }
84
88
 
89
+ export interface AssemblyInstructionsCompileOptions {
90
+ maxAttempts?: number
91
+ mcpServerUrl?: string
92
+ model?: string
93
+ prompt: string
94
+ timeout?: number
95
+ }
96
+
85
97
  function formatAssemblyReference({
86
98
  assemblyId,
87
99
  assemblyUrl,
@@ -325,6 +337,49 @@ export async function lint(
325
337
  return result.success ? 0 : 1
326
338
  }
327
339
 
340
+ function toPositiveInteger(value: number | undefined, optionName: string): number | undefined {
341
+ if (value == null) {
342
+ return undefined
343
+ }
344
+
345
+ if (!Number.isInteger(value) || value < 1) {
346
+ throw new Error(`${optionName} must be a positive integer`)
347
+ }
348
+
349
+ return value
350
+ }
351
+
352
+ function createCompileOptions({
353
+ maxAttempts,
354
+ mcpServerUrl,
355
+ model,
356
+ prompt,
357
+ timeout,
358
+ }: AssemblyInstructionsCompileOptions): CompileAssemblyInstructionsFromPromptOptions {
359
+ return {
360
+ maxAttempts,
361
+ mcpServerUrl,
362
+ model,
363
+ prompt,
364
+ timeout,
365
+ }
366
+ }
367
+
368
+ async function compileAssemblyInstructions(
369
+ output: IOutputCtl,
370
+ client: Transloadit,
371
+ options: AssemblyInstructionsCompileOptions,
372
+ ): Promise<number> {
373
+ try {
374
+ const result = await client.compileAssemblyInstructionsFromPrompt(createCompileOptions(options))
375
+ output.print(result.instructionsJson, result)
376
+ return 0
377
+ } catch (error) {
378
+ output.error(formatAPIError(error))
379
+ return 1
380
+ }
381
+ }
382
+
328
383
  // --- From assemblies-create.ts: Helper classes and functions ---
329
384
  interface NodeWatcher {
330
385
  on(event: 'error', listener: (err: Error) => void): void
@@ -1658,6 +1713,64 @@ export async function create(
1658
1713
  }
1659
1714
 
1660
1715
  // --- Command classes ---
1716
+ export class AssemblyInstructionsCompileCommand extends AuthenticatedCommand {
1717
+ static override paths = [
1718
+ ['assembly-instructions', 'compile'],
1719
+ ['assembly-instruction', 'compile'],
1720
+ ['instructions', 'compile'],
1721
+ ]
1722
+
1723
+ static override usage = Command.Usage({
1724
+ category: 'Assembly Instructions',
1725
+ description: 'Compile a prompt into Assembly Instructions',
1726
+ details: `
1727
+ Compile a natural-language prompt into validated Transloadit Assembly Instructions JSON.
1728
+ `,
1729
+ examples: [
1730
+ [
1731
+ 'Compile instructions',
1732
+ 'transloadit assembly-instructions compile "resize uploaded images to 400px wide"',
1733
+ ],
1734
+ ],
1735
+ })
1736
+
1737
+ prompt = Option.String({ required: true })
1738
+
1739
+ model = Option.String('--model', {
1740
+ description: 'AI model to use for instruction compilation',
1741
+ })
1742
+
1743
+ mcpServerUrl = Option.String('--mcp-server', {
1744
+ description: 'MCP server URL used for Robot docs and instruction linting',
1745
+ })
1746
+
1747
+ maxAttempts = Option.String('--max-attempts', {
1748
+ description: 'Maximum validation attempts',
1749
+ validator: t.applyCascade(t.isNumber(), [t.isAtLeast(1)]),
1750
+ })
1751
+
1752
+ timeout = Option.String('--timeout', {
1753
+ description: 'Compiler Assembly timeout in milliseconds',
1754
+ validator: t.applyCascade(t.isNumber(), [t.isAtLeast(1)]),
1755
+ })
1756
+
1757
+ protected async run(): Promise<number | undefined> {
1758
+ return await compileAssemblyInstructions(this.output, this.client, {
1759
+ maxAttempts: toPositiveInteger(
1760
+ this.maxAttempts == null ? undefined : Number(this.maxAttempts),
1761
+ '--max-attempts',
1762
+ ),
1763
+ mcpServerUrl: this.mcpServerUrl,
1764
+ model: this.model,
1765
+ prompt: this.prompt,
1766
+ timeout: toPositiveInteger(
1767
+ this.timeout == null ? undefined : Number(this.timeout),
1768
+ '--timeout',
1769
+ ),
1770
+ })
1771
+ }
1772
+ }
1773
+
1661
1774
  export class AssembliesCreateCommand extends AuthenticatedCommand {
1662
1775
  static override paths = [
1663
1776
  ['assemblies', 'create'],
@@ -1775,6 +1888,135 @@ export class AssembliesCreateCommand extends AuthenticatedCommand {
1775
1888
  }
1776
1889
  }
1777
1890
 
1891
+ export class RunCommand extends AuthenticatedCommand {
1892
+ static override paths = [['run']]
1893
+
1894
+ static override usage = Command.Usage({
1895
+ category: 'Assemblies',
1896
+ description: 'Compile Assembly Instructions and run them as an Assembly',
1897
+ details: `
1898
+ Compile a natural-language prompt into Assembly Instructions, then run those instructions directly.
1899
+ `,
1900
+ examples: [
1901
+ [
1902
+ 'Compile and run',
1903
+ 'transloadit run "resize uploaded images to 400px wide" -i input.jpg -o output.jpg',
1904
+ ],
1905
+ [
1906
+ 'Print result URLs',
1907
+ 'transloadit run "extract a waveform image from this audio" -i input.mp3 --print-urls',
1908
+ ],
1909
+ ],
1910
+ })
1911
+
1912
+ prompt = Option.String({ required: true })
1913
+
1914
+ model = Option.String('--model', {
1915
+ description: 'AI model to use for instruction compilation',
1916
+ })
1917
+
1918
+ mcpServerUrl = Option.String('--mcp-server', {
1919
+ description: 'MCP server URL used for Robot docs and instruction linting',
1920
+ })
1921
+
1922
+ maxAttempts = Option.String('--max-attempts', {
1923
+ description: 'Maximum validation attempts',
1924
+ validator: t.applyCascade(t.isNumber(), [t.isAtLeast(1)]),
1925
+ })
1926
+
1927
+ timeout = Option.String('--timeout', {
1928
+ description: 'Compiler Assembly timeout in milliseconds',
1929
+ validator: t.applyCascade(t.isNumber(), [t.isAtLeast(1)]),
1930
+ })
1931
+
1932
+ inputs = inputPathsOption()
1933
+
1934
+ outputPath = Option.String('--output,-o', {
1935
+ description: 'Specify an output file or directory',
1936
+ })
1937
+
1938
+ fields = Option.Array('--field,-f', {
1939
+ description: 'Set an Assembly field (KEY=VAL)',
1940
+ })
1941
+
1942
+ watch = watchOption()
1943
+
1944
+ recursive = recursiveOption()
1945
+
1946
+ deleteAfterProcessing = deleteAfterProcessingOption()
1947
+
1948
+ reprocessStale = reprocessStaleOption()
1949
+
1950
+ singleAssembly = singleAssemblyOption()
1951
+
1952
+ concurrency = concurrencyOption()
1953
+
1954
+ printUrls = printUrlsOption()
1955
+
1956
+ protected async run(): Promise<number | undefined> {
1957
+ const inputList = this.inputs ?? []
1958
+
1959
+ if (inputList.length === 0 && !process.stdin.isTTY) {
1960
+ inputList.push('-')
1961
+ }
1962
+
1963
+ const fieldsMap = parseTemplateFieldAssignments(this.output, this.fields)
1964
+ if (this.fields != null && fieldsMap == null) {
1965
+ return 1
1966
+ }
1967
+
1968
+ const sharedValidationError = validateSharedFileProcessingOptions({
1969
+ explicitInputCount: this.inputs?.length ?? 0,
1970
+ singleAssembly: this.singleAssembly,
1971
+ watch: this.watch,
1972
+ watchRequiresInputsMessage: 'run --watch requires at least one input',
1973
+ })
1974
+ if (sharedValidationError != null) {
1975
+ this.output.error(sharedValidationError)
1976
+ return 1
1977
+ }
1978
+
1979
+ let compiled: Awaited<ReturnType<Transloadit['compileAssemblyInstructionsFromPrompt']>>
1980
+ try {
1981
+ compiled = await this.client.compileAssemblyInstructionsFromPrompt(
1982
+ createCompileOptions({
1983
+ maxAttempts: toPositiveInteger(
1984
+ this.maxAttempts == null ? undefined : Number(this.maxAttempts),
1985
+ '--max-attempts',
1986
+ ),
1987
+ mcpServerUrl: this.mcpServerUrl,
1988
+ model: this.model,
1989
+ prompt: this.prompt,
1990
+ timeout: toPositiveInteger(
1991
+ this.timeout == null ? undefined : Number(this.timeout),
1992
+ '--timeout',
1993
+ ),
1994
+ }),
1995
+ )
1996
+ } catch (error) {
1997
+ this.output.error(formatAPIError(error))
1998
+ return 1
1999
+ }
2000
+
2001
+ const { hasFailures, resultUrls } = await create(this.output, this.client, {
2002
+ stepsData: parseStepsInputJson(JSON.stringify(compiled.instructions.steps)),
2003
+ fields: fieldsMap ?? {},
2004
+ watch: this.watch,
2005
+ recursive: this.recursive,
2006
+ inputs: inputList,
2007
+ output: this.outputPath ?? null,
2008
+ del: this.deleteAfterProcessing,
2009
+ reprocessStale: this.reprocessStale,
2010
+ singleAssembly: this.singleAssembly,
2011
+ concurrency: this.concurrency == null ? undefined : Number(this.concurrency),
2012
+ })
2013
+ if (this.printUrls) {
2014
+ printResultUrls(this.output, resultUrls)
2015
+ }
2016
+ return hasFailures ? 1 : undefined
2017
+ }
2018
+ }
2019
+
1778
2020
  export class AssembliesListCommand extends AuthenticatedCommand {
1779
2021
  static override paths = [
1780
2022
  ['assemblies', 'list'],
@@ -9,6 +9,8 @@ import {
9
9
  AssembliesLintCommand,
10
10
  AssembliesListCommand,
11
11
  AssembliesReplayCommand,
12
+ AssemblyInstructionsCompileCommand,
13
+ RunCommand,
12
14
  } from './assemblies.ts'
13
15
  import { SignatureCommand, SmartCdnSignatureCommand, TokenCommand } from './auth.ts'
14
16
  import { BillsGetCommand } from './bills.ts'
@@ -65,6 +67,10 @@ export function createCli(): Cli {
65
67
  // Uploads commands
66
68
  cli.register(UploadCommand)
67
69
 
70
+ // Prompt-to-Assembly-Instructions commands
71
+ cli.register(AssemblyInstructionsCompileCommand)
72
+ cli.register(RunCommand)
73
+
68
74
  // Documentation commands (offline metadata)
69
75
  cli.register(DocsRobotsListCommand)
70
76
  cli.register(DocsRobotsGetCommand)