Skip to content

feat(google_docs): new Google Docs tool plugin (1.0.0); fix: short sign-in link for Each user signs in (1.0.1) - #4186

Closed
ForeignKeyCN wants to merge 2 commits into
langgenius:mainfrom
ForeignKeyCN:main
Closed

ForeignKeyCN wants to merge 2 commits into
langgenius:mainfrom
ForeignKeyCN:main

Conversation

@ForeignKeyCN

Copy link
Copy Markdown
Contributor

This PR has two parts:

  1. Google Docs: a new tool plugin (tools/google_docs, 1.0.0).
  2. Short sign-in link: a fix for Each user signs in in 10 plugins (1.0.1).

It replaces #4183 and #4184.

Part 1: Google Docs tool plugin (1.0.0)

Summary

A new Google Docs tool plugin (tools/google_docs). It reads, creates and edits documents from workflows and agents. Content goes in and comes out as Markdown, so an agent can write a formatted document and read it back. It is built like the other Google plugins: Calendar (#4173), Gmail (#4180), Drive (#4181) and Sheets (#4182).

Auth

  • OAuth from the Dify console: one Google account for the workspace.
  • Each user signs in: every chat user signs in with their own Google account.
    • Uses authorization code + PKCE through a plugin endpoint (GET /google_docs/callback) that only stores the one-time code.
    • The agent hands out a short link to that endpoint (?start=<id>), which redirects to Google. Agents retype links, and a long random state does not always survive that.
    • Per-user tokens are Fernet-encrypted in plugin storage, keyed by a hash of client_id | Dify user ID, and never appear in tool output.
    • After sign-in, the agent reports which account was used.
    • An unticked permission, invalid_grant or a 401 leads to a new sign-in.
    • The callback page warns about forwarded links.
    • google_docs_sign_out forgets the sign-in.
  • Scopes:
    • documents: read and write documents.
    • drive.metadata.readonly: only to find documents by name.

Tools (prefixed google_docs_: the new Agent rejects duplicate tool names across plugins)

Tool What it does
google_docs_find_documents Find documents by name (newest first, across shared drives)
google_docs_get_document A document as Markdown: headings, bullet and numbered lists (nested), tables, bold/italic, links. Also returns its title and headings
google_docs_create_document Create a document, optionally with Markdown content
google_docs_append_content Add Markdown content at the end (optionally on a new page) or at the start
google_docs_replace_text Replace every occurrence of a text, or several at once from a JSON object (template filling); optional match case; reports how many were changed
google_docs_insert_table Add a table at the end from a JSON grid, with an optional bold header row
  • Markdown written:

    • #/##/### headings;
    • -/* bullets and 1. numbered lists;
    • **bold**, *italic* and [text](https://link).

    Everything else becomes normal paragraphs.

  • Writing: one batchUpdate per call. The inserted text is reset to normal style first, so it doesn't inherit the style around it.

  • Tables: cells are filled bottom-up, so earlier indexes stay valid (limit 2000 cells).

  • Document IDs: tools accept an ID or a URL.

  • Output variables: every tool returns typed output variables (success / error plus its fields).

Release Notes

  • New plugin: Google Docs tools.
    • Find, read (as Markdown) and create documents.
    • Append formatted content.
    • Replace text, for example to fill a template.
    • Insert tables.
  • Two ways to authorize: OAuth (one shared account), and Each user signs in for chat agents, where each person works on their own documents.

Change Type

  • Documentation / non-plugin change
  • Non-LLM plugin (tools, extensions, datasource, etc.)
  • LLM plugin

Screenshots / Videos

None yet; the README describes the setup and what users see.

Testing

  • Unit tests: 31 passed (pytest tests). They cover:
    • The sign-in flow, including the short link (redirect, mistyped, expired).
    • The Markdown parser and the request indexes when writing at the end or at the start.
    • Reading back as Markdown: headings, lists, links and tables.
    • The document URL accepted as an ID.
    • Each tool:
      • create with content;
      • append with a page break;
      • replace pairs;
      • insert a table filled bottom-up;
      • find.
    • Every tool's output variables, the manifest and provider.
  • Self-hosted Dify (Community), Each user signs in, real Google account, in an agent chat:
    • signed in through the short link;
    • created a document with Markdown content;
    • appended a section;
    • replaced text;
    • inserted a table;
    • read the document back;
    • found it by name.
  • Not run against Google: google_docs_sign_out and OAuth mode (unit tests only).

Part 2: give the agent a short sign-in link (1.0.1)

Problem

In Each user signs in mode, the tool returns a sign-in link and the agent passes it on to the user in its reply. The agent retypes the link rather than copying it, and a long random value does not always survive that. In a real chat, one character of the state parameter changed case (...X3FQ became ...X3fQ), so the callback endpoint showed "Sign-in link not recognized".

Fix

  • The tool now returns a short link to the plugin's own sign-in endpoint: <sign-in endpoint>?start=<id>.
    • The id is 12 lowercase characters without look-alikes (0/o, 1/l).
  • The endpoint redirects (302) to the provider's sign-in page that the tool stored.
    • The state and PKCE values go to the provider and come back without passing through the agent.
  • A mistyped, unknown, used or expired short link shows a page that asks the user to get a new link from the chat.
  • The agent is told to hand out "this exact link".

Nothing changes for administrators: same endpoint, same redirect URI, same credential.

Plugins (1.0.0 → 1.0.1)

outlook, teams, onedrive, microsoft_excel_365, microsoft_todo, sharepoint, jira, confluence, trello, google_calendar

The open PRs for gmail (#4180), google_drive_tool (#4181) and google_sheets (#4182) already include the same change.

Tests

  • Unit tests pass for every plugin.
  • New tests check that:
    • the tool returns the short link;
    • the short link redirects to the sign-in page;
    • a mistyped or unknown short link is refused.
  • End to end on a test Dify instance: a chat agent handed out the short link, the endpoint redirected it to Google (302), the callback accepted the sign-in (200), and the tools then ran as the signed-in user.

Checklist

  • I have read the contribution guidelines
  • New plugin google_docs 1.0.0; the other plugins move to 1.0.1

Applies to outlook, teams, onedrive, microsoft_excel_365, microsoft_todo,
sharepoint, jira, confluence, trello and google_calendar.

In "Each user signs in" mode the agent retypes the sign-in link in its
reply, and a long random state does not always survive that: in a real
chat one character changed case, so the callback endpoint could not
recognize the sign-in.

The tool now returns <sign-in endpoint>?start=<12 lowercase characters
without look-alikes>, and the endpoint redirects to the sign-in page it
stored. The state and PKCE values go to the provider and back without
passing through the agent.
@ForeignKeyCN

Copy link
Copy Markdown
Contributor Author

Split into one PR per plugin: #4187-#4196 (short sign-in link fix) and #4197 (Google Docs).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant