Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

4 dezembro 2025Por Klaibson

O plug-in ONLYOFFICE AI introduziu uma nova arquitetura fácil de usar para desenvolvedores. Se você deseja ampliar os recursos do plug-in, por exemplo, para adicionar uma função específica de IA, não é mais necessário editar um arquivo monolítico enorme.

Em vez disso, o plug-in agora possui um espaço de trabalho dedicado localizado na pasta .dev.

Este guia mostrará exatamente como usar esse espaço de trabalho para adicionar uma nova função personalizada. Vamos criar o recurso Descrever imagem para o Editor de documentos como nosso exemplo.

Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

O fluxo de trabalho de desenvolvimento

O conceito central é simples: você trabalha no .dev e um script cria o código de produção.

  • .dev/helpers/: Esta é a sua área de testes. É aqui que você cria novos arquivos.
  • helpers.js: Este é o arquivo de produção que o plug-in realmente lê. Não edite diretamente. Ele é gerado automaticamente.

Passo 1: Escolha o escopo do seu editor

Por dentro .dev/helpers/, você encontrará três pastas correspondentes ao ONLYOFFICE editors:

  • word/ (Document Editor)
  • cell/ (Spreadsheet Editor)
  • slide/ (Presentation Editor)

Como nossa função de descrição de imagem é para documentos de texto, trabalharemos em .dev/helpers/word/.

Passo 2: Crie sua própria função

Crie um novo arquivo chamado describe-image.js dentro .dev/helpers/word/.

O plugin usa uma classe específica chamada RegisteredFunction para definir capacidades. Essa estrutura informa à IA o que a função faz e como chamá-la.

Dica: Certifique-se de que sua sintaxe esteja correta (verifique se não há colchetes de fechamento faltando).

O código:

(function () {
  let func = new RegisteredFunction({
    name: "describeImage",
    description:
      "Allows users to select an image and generate a meaningful title, description, caption, or alt text for it using AI.",
    // Define parameters so the AI knows what to ask for
    parameters: {
      type: "object",
      properties: {
        prompt: {
          type: "string",
          description:
            "instruction for the AI (e.g., 'Add a short title for this chart.')",
        },
      },
      required: ["prompt"],
    },
    // Provide examples to train the AI on usage
    examples: [
      {
        prompt: "Add a short title for this chart.",
        arguments: { prompt: "Add a short title for this chart." },
      },
      {
        prompt: "Write me a 1–2 sentence description of this photo.",
        arguments: {
          prompt: "Write me a 1–2 sentence description of this photo.",
        },
      },
      {
        prompt: "Generate a descriptive caption for this organizational chart.",
        arguments: {
          prompt:
            "Generate a descriptive caption for this organizational chart.",
        },
      },
      {
        prompt: "Provide accessibility-friendly alt text for this infographic.",
        arguments: {
          prompt:
            "Provide accessibility-friendly alt text for this infographic.",
        },
      },
    ],
  });

   // The actual logic executed inside the editor
  func.call = async function (params) {
    let prompt = params.prompt;

    async function insertMessage(message) {
      Asc.scope._message = String(message || "");
      // 3. Insert the result into the document
      await Asc.Editor.callCommand(function () {
        const msg = Asc.scope._message || "";
        const doc = Api.GetDocument();
        const selected =
          (doc.GetSelectedDrawings && doc.GetSelectedDrawings()) || [];
        if (selected.length > 0) {
          for (let i = 0; i < selected.length; i++) {
            const drawing = selected[i];
            const para = Api.CreateParagraph();
            para.AddText(msg);
            drawing.InsertParagraph(para, "after", true);
          }
        } else {
          const para = Api.CreateParagraph();
          para.AddText(msg);
          let range = doc.GetCurrentParagraph();
          range.InsertParagraph(para, "after", true);
        }
        Asc.scope._message = "";
      }, true);
    }

    try {
    // 1. Get the selected image
      let imageData = await new Promise((resolve) => {
        window.Asc.plugin.executeMethod(
          "GetImageDataFromSelection",
          [],
          function (result) {
            resolve(result);
          }
        );
      });

      if (!imageData || !imageData.src) {
        await insertMessage("Please select a valid image first.");
        return;
      }

      const whiteRectangleBase64 =
        "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";
      if (imageData.src === whiteRectangleBase64) {
        await insertMessage("Please select a valid image first.");
        return;
      }

      let argPrompt = prompt + " (for the selected image)";
      // 2. Send image + prompt to the AI engine
      let requestEngine = AI.Request.create(AI.ActionType.Chat);
      if (!requestEngine) {
        await insertMessage("AI request engine not available.");
        return;
      }

      const allowVision = /(vision|gemini|gpt-4o|gpt-4v|gpt-4-vision)/i;
      if (!allowVision.test(requestEngine.modelUI.name)) {
        await insertMessage(
          "⚠ This model may not support images. Please choose a vision-capable model (e.g. GPT-4V, Gemini, etc.)."
        );
        return;
      }

      await Asc.Editor.callMethod("StartAction", [
        "Block",
        "AI (" + requestEngine.modelUI.name + ")",
      ]);
      await Asc.Editor.callMethod("StartAction", ["GroupActions"]);

      let messages = [
        {
          role: "user",
          content: [
            { type: "text", text: argPrompt },
            {
              type: "image_url",
              image_url: { url: imageData.src, detail: "high" },
            },
          ],
        },
      ];

      let resultText = "";
      await requestEngine.chatRequest(messages, false, async function (data) {
        if (data) {
          resultText += data;
        }
      });

      await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
      await Asc.Editor.callMethod("EndAction", [
        "Block",
        "AI (" + requestEngine.modelUI.name + ")",
      ]);

      Asc.scope.text = resultText || "";

      if (!Asc.scope.text.trim()) {
        await insertMessage(
          "⚠ AI request failed (maybe the model cannot handle images)."
        );
        return;
      }
      await insertMessage(Asc.scope.text);
    } catch (e) {
      try {
        await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
        await Asc.Editor.callMethod("EndAction", [
          "Block",
          "AI (describeImage)",
        ]);
      } catch (ee) {
        /* ignore */
      }
      console.error("describeImage error:", e);
      await insertMessage(
        "An unexpected error occurred while describing the image."
      );
    }
  };

  return func;
})();

Passo 3: Atualize a versão do plugin

Antes de compilar e testar suas alterações, é uma boa prática atualizar a versão do plugin. Isso garante que o ONLYOFFICE trate sua compilação como um novo plugin, evita problemas de cache e ajuda a rastrear as alterações ao longo do tempo.

Abra o arquivo config.json na pasta do seu plugin.

Aumente a versão em um nível de patch, por exemplo:

"version": "3.0.0" to "3.1.0"

Isso é recomendado tanto para editores de desktop quanto para editores web:

Versão para computador: Garante que o aplicativo recarregue o plugin atualizado.

Web (incluindo links personalizados para lojas): Impede que o cache ignore suas alterações em helpers.js.

Passo 4: Compile suas alterações

Esta é a etapa mais importante do novo fluxo de trabalho. O plugin ainda não consegue ler seu novo arquivo diretamente. Você deve executar o script auxiliar para mesclar seu novo arquivo à lógica principal do plugin.

  1. Abra seu terminal.
  2. Navegue até o diretório helpers:
  3. cd .dev/helpers
  4. Execute o script de compilação Python:
  5. python3 helpers.py

O helpers.py o script irá verificar o word/, cell/, e slide/ pastas, encontre o seu novo describe-image.js, e o mesclei no arquivo principal helpers.js.

Passo 5: Criando o arquivo .plugin

  • Selecione todo o conteúdo do plugin.
  • Compacte-o em um arquivo ZIP.
  • Renomeie o arquivo de .zip para .plugin.
  • Coloque-o em uma pasta chamada deploy dentro da pasta do seu plugin.

Passo 6: Substitua o plugin em ONLYOFFICE

Desktop Editor

Nas versões mais recentes do ONLYOFFICE Desktop Editors, o plugin de IA já está incluído por padrão. Se você estiver usando uma versão mais antiga em que o plugin ainda não estava incluído, o processo de instalação depende da sua situação e segue dois caminhos possíveis:

A) Instalando o plugin de IA pela primeira vez

Caso o plugin de IA esteja faltando no seu diretório de plugins local:

  1. Abra o ONLYOFFICE Desktop Editors.
  2. Vá para Plugins → Gerenciador de Plugins → Plugins Disponíveis → Instalar plugin manualmente.
  3. Quando solicitado a selecionar um arquivo, escolha o arquivo .plugin compilado.

B) Atualizando uma cópia local existente do plugin de IA

Se o plugin já estiver presente no seu sistema:

  1. Vá para ~/.local/share/onlyoffice/desktopeditors/sdkjs-plugins
  2. Encontre a pasta cujo nome corresponde ao GUID do plugin config.json – {9DC93CDB-B576-4F0C-B55E-FCC9C48DD007}
  3. Substitua a pasta pelo plugin que você acabou de criar.
  4. Reinicie o aplicativo de desktop.

Editor Web (via link personalizado da loja)

Link personalizado da loja

Habilite o GitHub Pages para o seu fork.

Certifique-se de incrementar a versão no arquivo config.json para evitar problemas de cache.

  1. Faça um fork do repositório do ONLYOFFICE Plugin Marketplace. Você encontrará uma cópia em: https://github.com/YOUR-USERNAME/ONLYOFFICE/onlyoffice.github.io
  2. Certifique-se de que sua pasta de plugins inclua uma pasta deploy contendo o arquivo .plugin.
  3. Adicione sua pasta de plugins a: onlyoffice.github.io/sdkjs-plugins/content/ai/
  4. Crie seu site do GitHub Pages a partir deste repositório (consulte a documentação do GitHub Pages)
  5. Prepare um link para sua loja personalizada adicionando /store/index.html ao seu URL do GitHub Pages: https://YOUR-USERNAME.github.io/onlyoffice.github.io/store/index.html
  6. Incremente a versão do plugin em config.json (conforme descrito na Etapa 3) para ignorar o cache.

Atualizar plugin

Antes de atualizar para a sua versão personalizada, talvez seja necessário remover a versão pré-instalada, dependendo da sua configuração.

  • Verifique se o plugin de IA já está instalado

Abra o Editor Web e acesse Plugins → Gerenciador de Plugins.

Se o plugin de IA estiver instalado, remova-o:

Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

Se não estiver instalado, prossiga para o próximo passo.

Isso garante que a versão personalizada possa ser instalada ou atualizada sem conflitos.

  • Adicione sua loja personalizada

Clique no ícone da loja no canto superior direito do Gerenciador de Plugins:

Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

Insira o URL da sua loja personalizada:

https://YOUR-USERNAME.github.io/onlyoffice.github.io/store/index.html

Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

Sua loja personalizada agora aparecerá no Gerenciador de Plugins.

  • Instale o plugin de IA

Após o carregamento da sua loja personalizada, encontre o Assistente de IA na lista e clique em Instalar.

Como adicionar recursos personalizados ao plug-in ONLYOFFICE AI

Passo 7: Teste seu recurso

  1. Recarregue o plugin no ONLYOFFICE.
  2. Selecione uma imagem no seu documento.
  3. Pergunte à IA: “Descreva esta imagem” ou “Escreva uma legenda para esta imagem”

A IA agora reconhecerá sua nova função personalizada e executará a lógica que você acabou de escrever.

Crie sua conta gratuita no ONLYOFFICE

Visualize, edite e colabore em documentos, planilhas, slides, formulários e arquivos PDF online.