Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/docs-suggest-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@googleworkspace/cli": minor
---

Add `gws docs +suggest` for creating and managing Google Docs suggestions,
including suggested insertions, exact replacements, range deletions, and
accept, reject, or delete actions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ For example, Docs suggestions and comments require a Cloud project enrolled in t
Google still enforces API availability, OAuth scopes, document permissions and
server-side validation. This flag grants no additional access.

### Docs suggestions

On `develop`, `gws docs +suggest` provides a guided workflow for Google Docs
suggestions. It can insert text, replace one exact text run, propose a range
deletion, list the structured document with suggestion context, and accept,
reject, or delete an existing suggestion:

```bash
gws docs +suggest insert --document DOC_ID --text 'Suggested text'
gws docs +suggest replace --document DOC_ID --find 'old text' --text 'new text'
gws docs +suggest delete-text --document DOC_ID --start-index 10 --end-index 20
gws docs +suggest list --document DOC_ID
gws docs +suggest accept --document DOC_ID --suggestion-id SUGGESTION_ID
```

The helper applies the preview-only `writeMode` request fields internally, so
these commands do not need `--allow-unknown-fields`. Suggestion writes remain
subject to Google Workspace Developer Preview access and document permissions.

```bash
# Preview a suggested insertion (Docs Developer Preview).
gws docs documents batchUpdate \
Expand Down Expand Up @@ -438,6 +457,7 @@ gws drive --help # shows +upload …
| `sheets` | `+append` | Append a row to a spreadsheet |
| `sheets` | `+read` | Read values from a spreadsheet |
| `docs` | `+write` | Append text to a document |
| `docs` | `+suggest` | Create and manage document suggestions |
| `chat` | `+send` | Send a message to a space |
| `drive` | `+upload` | Upload a file with automatic metadata |
| `calendar` | `+insert` | Create a new event |
Expand Down
6 changes: 6 additions & 0 deletions crates/google-workspace-cli/src/helpers/docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use std::future::Future;
use std::pin::Pin;

mod read;
mod suggest;

pub struct DocsHelper;

Expand All @@ -36,6 +37,7 @@ impl Helper for DocsHelper {
_doc: &crate::discovery::RestDescription,
) -> Command {
cmd = cmd.subcommand(read::command());
cmd = cmd.subcommand(suggest::command());
cmd = cmd.subcommand(
Command::new("+write")
.about("[Helper] Append text to a document")
Expand Down Expand Up @@ -77,6 +79,10 @@ TIPS:
read::handle(doc, matches, sanitize_config).await?;
return Ok(true);
}
if let Some(matches) = matches.subcommand_matches("+suggest") {
suggest::handle(doc, matches, sanitize_config).await?;
return Ok(true);
}
if let Some(matches) = matches.subcommand_matches("+write") {
let (params_str, body_str, scopes) = build_write_request(matches, doc)?;

Expand Down
6 changes: 4 additions & 2 deletions crates/google-workspace-cli/src/helpers/docs/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(super) async fn handle(

/// Token acquisition is lazy so local validation and dry-run never read
/// credentials. The executor remains responsible for HTTP and sanitization.
pub(super) async fn run(
pub(crate) async fn run(
doc: &RestDescription,
matches: &ArgMatches,
sanitize: &SanitizeConfig,
Expand All @@ -94,7 +94,9 @@ pub(super) async fn run(
let dry_run = matches.get_flag("dry-run");
let token = if dry_run { None } else { Some(token.await?) };
let format = matches
.get_one::<String>("format")
.try_get_one::<String>("format")
.ok()
.flatten()
.map(|f| OutputFormat::from_str(f))
.unwrap_or_default();
let result = executor::execute_method(
Expand Down
Loading
Loading