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étodo | O 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 outros | Lista, 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
InsufficientCreditsErrorquando 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
runem um cliente obtido comclient.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 returnedUm 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
| Tipo | Formato |
|---|---|
Workflow | id, projectId, userId, name, description?, folderId?, version?, thumbnailUrl?, nodes?, edges?, settings?, sourcePrompt?, createdAt, updatedAt. Os campos do grafo só aparecem em registros completos. |
Project | id, userId, name, description?, settings?, createdAt, updatedAt |
Collaborator | userId, name?, avatar?, role |
WorkflowExport | O pacote portátil que export() retorna e import() aceita |
GenericNode, GenericEdge | Os formatos de nó e de conexão usados em nodes e edges |
Todos eles são exportados de @nodaro/sdk. Veja Tipos.
Perguntas frequentes
Páginas relacionadas
Jobs e execuções
Executar nós
Workflows
Workflows e projetos
Importação e exportação
Última atualização
Erros
Todos os erros do SDK do Nodaro para TypeScript, com status HTTP, código e campos, e o que fazer com créditos, limites de taxa, conflitos e jobs com falha.
Jobs e execuções
Consulte periodicamente, liste, cancele e exclua execuções do Nodaro em TypeScript: client.jobs para gerações avulsas e client.executions para workflows.