Docs do Nodaro
DocumentaçãoReferência de nósModelosAgentes de IA (MCP)DesenvolvedoresSelf-hostingPesquisa
SDK para TypeScript

Workflows e projetos

Crie, atualize, compartilhe, exporte, importe e execute workflows do Nodaro em TypeScript com client.workflows e agrupe-os em projetos com client.projects.

client.workflows lê, grava, compartilha e executa workflows do Nodaro, e client.projects gerencia os projetos que os contêm. Um workflow é um canvas de nós conectados, e todo workflow pertence a um projeto. Os métodos chamam os mesmos endpoints da API REST de workflows. Veja Workflows e projetos para os conceitos.

Métodos

MétodoO que faz
workflows.list(params)Lista os workflows de um projeto, sem os grafos deles
workflows.get(id)Lê um workflow com os nós, as conexões e as configurações dele
workflows.getPublic(id)Lê um workflow compartilhado por link, sem token
workflows.create(input)Cria um workflow em um projeto
workflows.update(id, input)Altera quaisquer campos de um workflow
workflows.delete(id)Exclui um workflow
workflows.run(id, params?)Inicia uma execução do workflow
workflows.export(workflowId, opts?)Exporta um workflow como um pacote JSON portátil
workflows.import(input)Importa um pacote para um projeto
workflows.setVisibility(id, visibility)Torna um workflow privado ou visível para o espaço de trabalho dele
workflows.move(id, params)Move um workflow para outro projeto
workflows.sharedWithMe()Lista os workflows que outras pessoas compartilharam com você
workflows.collaborators.*Lista, adiciona, altera e remove as pessoas com quem um workflow é compartilhado
projects.list() e outrosLista, lê, cria, atualiza e exclui projetos

client.workflows

list(params)

Lista os workflows de um projeto. A lista retorna só metadados: nodes, edges, settings e sourcePrompt ficam de fora. Leia um workflow com get() para obter o grafo completo dele.

list(params: { projectId: string }): Promise<{ data: Workflow[] }>

Prop

Type

const { data: workflows } = await client.workflows.list({ projectId })
for (const wf of workflows) console.log(wf.id, wf.name, wf.updatedAt)

Lança NotFoundError quando o projeto não está visível para você.

get(id)

Lê um workflow, incluindo nodes, edges e settings completos.

get(id: string): Promise<{ data: Workflow }>

Prop

Type

const { data: wf } = await client.workflows.get(workflowId)
console.log(`${wf.name}: ${wf.nodes?.length ?? 0} nodes, version ${wf.version}`)

Guarde a version se você pretende atualizar o workflow: ela torna a atualização segura contra outras pessoas que também gravam nele.

getPublic(id)

Lê um workflow que o dono compartilhou por link (GET /v1/public/workflows/:id). Não é preciso token. O workflow só é retornado enquanto o compartilhamento dele estiver ativado; caso contrário, o método lança NotFoundError.

getPublic(id: string): Promise<{ data: Workflow }>

Prop

Type

const { data: shared } = await client.workflows.getPublic(workflowId)

Quando o provedor de autenticação não retorna nenhum token, a requisição é enviada sem token.

create(input)

Cria um workflow em um projeto e retorna o registro completo. Só projectId e name são necessários; os outros campos usam os padrões do servidor.

create(input: CreateWorkflowInput): Promise<{ data: Workflow }>

Prop

Type

const { data: wf } = await client.workflows.create({
  projectId,
  name: "Product launch video",
  nodes: [],
  edges: [],
})

Para obter um grafo pronto, exporte um workflow que você montou no editor e leia os nodes e edges dele, ou clone um template.

update(id, input)

Altera qualquer subconjunto dos campos de um workflow e retorna o registro completo atualizado (PATCH /v1/workflows/:id). Os campos que você deixa de fora continuam como estão.

update(id: string, input: UpdateWorkflowInput): Promise<{ data: Workflow }>

Prop

Type

await client.workflows.update(workflowId, { name: "Renamed", expectedVersion: 7 })

Atualizações seguras. Sem expectedVersion ou expectedUpdatedAt, a última gravação prevalece. Com um deles, a atualização só é aplicada se ninguém tiver alterado o workflow desde que você o leu. Caso contrário, ela lança WorkflowConflictError, cujo currentRecord contém o workflow atual para que você possa mesclar sem uma nova leitura:

import { WorkflowConflictError } from "@nodaro/sdk"

try {
  await client.workflows.update(workflowId, { settings, expectedVersion: wf.version })
} catch (err) {
  if (err instanceof WorkflowConflictError && err.currentRecord) {
    const merged = mergeSettings(err.currentRecord.settings, settings)
    await client.workflows.update(workflowId, {
      settings: merged,
      expectedVersion: err.currentVersion,
    })
  } else {
    throw err
  }
}

Os valores de estado de execução nos dados dos nós, como o status de execução ou o ID do job atual, são removidos pelo servidor e nunca são salvos.

delete(id)

Exclui um workflow.

delete(id: string): Promise<{ success: true }>

Prop

Type

await client.workflows.delete(workflowId)

Lança NotFoundError quando o ID não existe ou não é seu; assim, uma exclusão nunca falha em silêncio.

run(id, params?)

Inicia uma execução do workflow e retorna na hora com { executionId, status }. A execução continua no servidor. Consulte client.executions.get() periodicamente para acompanhar o progresso e o resultado.

run(id: string, params?: { nodeIds?: string[] }): Promise<{ executionId: string; status: "pending" | "running" }>

Prop

Type

const { executionId } = await client.workflows.run(workflowId, {
  nodeIds: ["text-prompt-1", "image-gen-2"],
})
const { data: execution } = await client.executions.get(executionId)
  • Lança InsufficientCreditsError quando a conta não consegue cobrir o maior custo possível da execução.
  • Um token OAuth precisa do escopo workflows:execute.
  • Para executar um workflow em um espaço de trabalho, chame run em um cliente obtido com client.withWorkspace().

export(workflowId, opts?)

Exporta a versão salva de um workflow como um pacote JSON portátil, o formato de arquivo que o menu Exportar do editor grava. Com assets: true, o pacote também leva as entidades que o workflow usa, como Com mídias no editor.

export(workflowId: string, opts?: { assets?: boolean }): Promise<{ data: WorkflowExport }>

Prop

Type

const { data: bundle } = await client.workflows.export(workflowId, { assets: true })

Portabilidade. Um pacote só pode apontar para mídias que outra instância consiga buscar. Quando os nós usam URLs que outras instâncias não conseguem acessar, como o armazenamento próprio de uma instalação self-hosted em localhost, um endereço de rede local ou um nome .internal, o pacote lista essas URLs em portability.unreachableMedia:

bundle.portability?.unreachableMedia
// [{ nodeId: "n1", nodeLabel: "Video URL", field: "videoUrl", url: "http://localhost:3000/storage/..." }]

O campo não aparece quando todas as URLs de mídia são públicas. Um pacote assim ainda pode ser importado, mas esses nós não podem ser executados na outra instância até que as mídias sejam enviadas para lá de novo. Veja Importação e exportação.

import(input)

Importa um pacote exportado para um dos seus projetos e retorna o novo workflow.

import(input: WorkflowExport & { projectId: string }): Promise<{
  data: Workflow
  importReport?: WorkflowImportReport
}>

Prop

Type

const { data: wf, importReport } = await client.workflows.import({ ...bundle, projectId })

O que a importação faz:

  • As entidades são recriadas. Os personagens, objetos, criaturas e locais do pacote viram novos itens na sua conta. O workflow passa a apontar para eles nos nós de entidade, em cada menção com @ nos dados dos nós e nas configurações do workflow.
  • As mídias são copiadas. As mídias em outros hosts são copiadas para o armazenamento desta instância quando podem ser acessadas; assim, o workflow não depende do servidor de outra pessoa. Os limites são 25 arquivos para as mídias do workflow e mais 25 para as entidades do pacote, com imagens de até 20 MB e vídeo ou áudio de até 50 MB.
  • As cópias contam no seu armazenamento. Quando o armazenamento acaba, o workflow ainda é importado, e as entidades que não couberam são listadas no relatório.

O importReport informa o que aconteceu:

importReport
// {
//   rehosted: 3,                                    // files copied to this instance
//   unreachable: [{ nodeId, nodeLabel, field, url }], // private hosts, left as they were
//   skipped: [{ nodeId, field, url, reason: "HTTP 404" }],
//   assetIdMap: { "<bundled asset id>": "<new asset id>" },
//   assetsSkipped: [{ kind: "character", id, name: "Kira", reason: "Storage limit exceeded" }],
// }

assetIdMap está presente sempre que o pacote trouxe entidades. O servidor já atualizou todas as menções dentro do workflow. Use o mapa só para referências que você guarda fora dele. assetsSkipped só aparece quando algo ficou de fora.

setVisibility(id, visibility)

Torna um workflow "private", visível para quem o criou e para os colaboradores que você adicionar, ou "workspace", visível para todos no espaço de trabalho dele.

setVisibility(id: string, visibility: "private" | "workspace"): Promise<{ data: Workflow }>

Prop

Type

await client.workflows.setVisibility(workflowId, "workspace")

Só quem criou o workflow ou um administrador do espaço de trabalho pode mudar isso; qualquer outra pessoa recebe ForbiddenError. Os espaços de trabalho existem nas organizações do Nodaro Cloud.

move(id, params)

Move um workflow para outro projeto (POST /v1/workflows/:id/move). O workflow sai da pasta em que estava.

move(id: string, params: { projectId: string }): Promise<{
  data: Workflow
  droppedCollaborators: { userId: string; name: string | null }[]
}>

Prop

Type

const { droppedCollaborators } = await client.workflows.move(workflowId, { projectId: archiveProjectId })

Quando a mudança tira o workflow de um espaço de trabalho, o acesso que vinha desse espaço de trabalho termina. Essas pessoas são retornadas em droppedCollaborators.

sharedWithMe()

Lista os workflows que outras pessoas compartilharam diretamente com você. O que está em um espaço de trabalho do qual você faz parte não é incluído, porque já aparece nas listas desse espaço de trabalho. Cada workflow traz o grantedRole que você tem nele.

sharedWithMe(): Promise<{ data: (Workflow & { grantedRole: "viewer" | "editor" })[] }>
const { data: shared } = await client.workflows.sharedWithMe()
for (const wf of shared) console.log(wf.name, wf.grantedRole)

A lista fica vazia em instâncias sem organizações.

collaborators

As pessoas com quem um workflow é compartilhado, acessadas como client.workflows.collaborators. Estes métodos existem em instâncias com organizações; nas outras, eles lançam NotFoundError.

collaborators.list(workflowId: string): Promise<{ data: Collaborator[] }>
collaborators.add(workflowId: string, input: { userId?: string; email?: string; role: "viewer" | "editor" }): Promise<{ data: { userId: string; role: "viewer" | "editor" } }>
collaborators.update(workflowId: string, userId: string, input: { role: "viewer" | "editor" }): Promise<{ data: { userId: string; role: "viewer" | "editor" } }>
collaborators.remove(workflowId: string, userId: string): Promise<{ success: true }>

Prop

Type

await client.workflows.collaborators.add(workflowId, { email: "editor@example.com", role: "editor" })

const { data: people } = await client.workflows.collaborators.list(workflowId)
// [{ userId, name, avatar, role }]: email addresses are never returned

Um colaborador pode chamar remove() com o próprio ID de usuário para sair de um workflow.

client.projects

Um projeto agrupa workflows. Todo workflow pertence a exatamente um projeto.

projects.list()

Lista seus projetos.

list(): Promise<{ data: Project[] }>
const { data: projects } = await client.projects.list()

projects.get(id)

Lê um projeto.

get(id: string): Promise<{ data: Project }>

Prop

Type

const { data: project } = await client.projects.get(projectId)

projects.create(input)

Cria um projeto.

create(input: { name: string; description?: string; settings?: Record<string, unknown> }): Promise<{ data: Project }>

Prop

Type

const { data: project } = await client.projects.create({ name: "Spring campaign" })

projects.update(id, input)

Altera um projeto. Passe pelo menos um campo.

update(id: string, input: { name?: string; description?: string; settings?: Record<string, unknown> }): Promise<{ data: Project }>

Prop

Type

await client.projects.update(projectId, { description: "Assets for the spring launch" })

projects.delete(id)

Exclui um projeto.

delete(id: string): Promise<{ success: true }>

Prop

Type

await client.projects.delete(projectId)

Tipos

TipoFormato
Workflowid, projectId, userId, name, description?, folderId?, version?, thumbnailUrl?, nodes?, edges?, settings?, sourcePrompt?, createdAt, updatedAt. Os campos do grafo só aparecem em registros completos.
Projectid, userId, name, description?, settings?, createdAt, updatedAt
CollaboratoruserId, name?, avatar?, role
WorkflowExportO pacote portátil que export() retorna e import() aceita
GenericNode, GenericEdgeOs formatos de nó e de conexão usados em nodes e edges

Todos eles são exportados de @nodaro/sdk. Veja Tipos.

Perguntas frequentes

Última atualização

Nesta página