feat: smarter truncation of method/resource descriptions (#68)

* feat: smarter truncation of method/resource descriptions

- Add shared truncate_description() in src/text.rs with configurable
  limits and optional markdown link stripping
- Named constants: CLI_DESCRIPTION_LIMIT (200), FRONTMATTER_DESCRIPTION_LIMIT (120),
  SKILL_BODY_DESCRIPTION_LIMIT (500)
- CLI help and frontmatter strip markdown links to save space
- Skill body preserves URLs so agents can follow references
- Truncation prefers sentence boundaries, falls back to word boundaries
- Reads full descriptions from discovery doc for skill body text

Fixes #64

* fix: address PR review comments and improve coverage

- Fix sentence boundary detection at exact end of prefix (HIGH)
- Use extend() for link text emission (MEDIUM)
- Idiomatic find_char_from with position/map (MEDIUM)
- Idiomatic rfind_char_boundary with rposition (MEDIUM)
- Add 18 new tests for generate_skills.rs coverage:
  truncate_desc, lookup_method_description, capitalize_first,
  product_name_from_title
- Add sentence_boundary_at_exact_limit and zero_max_chars tests

---------

Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
This commit is contained in:
Justin Poehnelt
2026-03-04 16:03:59 -07:00
committed by GitHub
parent bcc6c8d24e
commit 8fadbd6901
24 changed files with 587 additions and 138 deletions
@@ -0,0 +1,5 @@
---
"@googleworkspace/cli": patch
---
Smarter truncation of method and resource descriptions from discovery docs. Descriptions now truncate at sentence boundaries when possible, fall back to word boundaries with an ellipsis, and strip markdown links to reclaim character budget. Fixes #64.
+4 -4
View File
@@ -22,7 +22,7 @@ gws admin-reports <resource> <method> [flags]
### activities
- `list` — Retrieves a list of activities for a specific customer's account and application such as the Admin console application or the Google Drive application. For more information, see the guides for adminis
- `list` — Retrieves a list of activities for a specific customer's account and application such as the Admin console application or the Google Drive application. For more information, see the guides for administrator and Google Drive activity reports. For more information about the activity report's parameters, see the activity parameters reference guides.
- `watch` — Start receiving notifications for account activities. For more information, see Receiving Push Notifications.
### channels
@@ -31,15 +31,15 @@ gws admin-reports <resource> <method> [flags]
### customerUsageReports
- `get` — Retrieves a report which is a collection of properties and statistics for a specific customer's account. For more information, see the Customers Usage Report guide. For more information about the cust
- `get` — Retrieves a report which is a collection of properties and statistics for a specific customer's account. For more information, see the Customers Usage Report guide. For more information about the customer report's parameters, see the Customers Usage parameters reference guides.
### entityUsageReports
- `get` — Retrieves a report which is a collection of properties and statistics for entities used by users within the account. For more information, see the Entities Usage Report guide. For more information abo
- `get` — Retrieves a report which is a collection of properties and statistics for entities used by users within the account. For more information, see the Entities Usage Report guide. For more information about the entities report's parameters, see the Entities Usage parameters reference guides.
### userUsageReport
- `get` — Retrieves a report which is a collection of properties and statistics for a set of users with the account. For more information, see the User Usage Report guide. For more information about the user re
- `get` — Retrieves a report which is a collection of properties and statistics for a set of users with the account. For more information, see the User Usage Report guide. For more information about the user report's parameters, see the Users Usage parameters reference guides.
## Discovering Commands
+9 -9
View File
@@ -32,11 +32,11 @@ gws admin <resource> <method> [flags]
### chromeosdevices
- `action` — Use [BatchChangeChromeOsDeviceStatus](https://developers.google.com/workspace/admin/directory/reference/rest/v1/customer.devices.chromeos/batchChangeStatus) instead. Takes an action that affects a Chr
- `action` — Use [BatchChangeChromeOsDeviceStatus](https://developers.google.com/workspace/admin/directory/reference/rest/v1/customer.devices.chromeos/batchChangeStatus) instead. Takes an action that affects a Chrome OS Device. This includes deprovisioning, disabling, and re-enabling devices. *Warning:* * Deprovisioning a device will stop device policy syncing and remove device-level printers. After a device is deprovisioned, it must be wiped before it can be re-enrolled.
- `get` — Retrieves a Chrome OS device's properties.
- `list` — Retrieves a paginated list of Chrome OS devices within an account.
- `moveDevicesToOu` — Moves or inserts multiple Chrome OS devices to an organizational unit. You can move up to 50 devices at once.
- `patch` — Updates a device's updatable properties, such as `annotatedUser`, `annotatedLocation`, `notes`, `orgUnitPath`, or `annotatedAssetId`. This method supports [patch semantics](https://developers.google.c
- `patch` — Updates a device's updatable properties, such as `annotatedUser`, `annotatedLocation`, `notes`, `orgUnitPath`, or `annotatedAssetId`. This method supports [patch semantics](https://developers.google.com/workspace/admin/directory/v1/guides/performance#patch).
- `update` — Updates a device's updatable properties, such as `annotatedUser`, `annotatedLocation`, `notes`, `orgUnitPath`, or `annotatedAssetId`.
### customer
@@ -78,9 +78,9 @@ gws admin <resource> <method> [flags]
- `delete` — Removes a member from a group.
- `get` — Retrieves a group member's properties.
- `hasMember` — Checks whether the given user is a member of the group. Membership can be direct or nested, but if nested, the `memberKey` and `groupKey` must be entities in the same domain or an `Invalid input` erro
- `hasMember` — Checks whether the given user is a member of the group. Membership can be direct or nested, but if nested, the `memberKey` and `groupKey` must be entities in the same domain or an `Invalid input` error is returned. To check for nested memberships that include entities outside of the group's domain, use the [`checkTransitiveMembership()`](https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/checkTransitiveMembership) method in the Cloud Identity Groups API.
- `insert` — Adds a user to the specified group.
- `list` — Retrieves a paginated list of all members in a group. This method times out after 60 minutes. For more information, see [Troubleshoot error codes](https://developers.google.com/workspace/admin/directo
- `list` — Retrieves a paginated list of all members in a group. This method times out after 60 minutes. For more information, see [Troubleshoot error codes](https://developers.google.com/workspace/admin/directory/v1/guides/troubleshoot-error-codes).
- `patch` — Updates the membership properties of a user in the specified group. This method supports [patch semantics](https://developers.google.com/workspace/admin/directory/v1/guides/performance#patch).
- `update` — Updates the membership of a user in the specified group.
@@ -89,7 +89,7 @@ gws admin <resource> <method> [flags]
- `action` — Takes an action that affects a mobile device. For example, remotely wiping a device.
- `delete` — Removes a mobile device.
- `get` — Retrieves a mobile device's properties.
- `list` — Retrieves a paginated list of all user-owned mobile devices for an account. To retrieve a list that includes company-owned devices, use the Cloud Identity [Devices API](https://cloud.google.com/identi
- `list` — Retrieves a paginated list of all user-owned mobile devices for an account. To retrieve a list that includes company-owned devices, use the Cloud Identity [Devices API](https://cloud.google.com/identity/docs/concepts/overview-devices) instead. This method times out after 60 minutes. For more information, see [Troubleshoot error codes](https://developers.google.com/workspace/admin/directory/v1/guides/troubleshoot-error-codes).
### orgunits
@@ -147,16 +147,16 @@ gws admin <resource> <method> [flags]
### users
- `createGuest` — Create a guest user with access to a [subset of Workspace capabilities](https://support.google.com/a/answer/16558545). This feature is currently in Alpha. Please reach out to support if you are intere
- `createGuest` — Create a guest user with access to a [subset of Workspace capabilities](https://support.google.com/a/answer/16558545). This feature is currently in Alpha. Please reach out to support if you are interested in trying this feature.
- `delete` — Deletes a user.
- `get` — Retrieves a user.
- `insert` — Creates a user. Mutate calls immediately following user creation might sometimes fail as the user isn't fully created due to propagation delay in our backends. Check the error details for the "User cr
- `insert` — Creates a user. Mutate calls immediately following user creation might sometimes fail as the user isn't fully created due to propagation delay in our backends. Check the error details for the "User creation is not complete" message to see if this is the case. Retrying the calls after some time can help in this case. If `resolveConflictAccount` is set to `true`, a `202` response code means that a conflicting unmanaged account exists and was invited to join the organization.
- `list` — Retrieves a paginated list of either deleted users or all users in a domain.
- `makeAdmin` — Makes a user a super administrator.
- `patch` — Updates a user using patch semantics. The update method should be used instead, because it also supports patch semantics and has better performance. If you're mapping an external identity to a Google
- `patch` — Updates a user using patch semantics. The update method should be used instead, because it also supports patch semantics and has better performance. If you're mapping an external identity to a Google identity, use the [`update`](https://developers.google.com/workspace/admin/directory/v1/reference/users/update) method instead of the `patch` method. This method is unable to clear fields that contain repeated objects (`addresses`, `phones`, etc). Use the update method instead.
- `signOut` — Signs a user out of all web and device sessions and reset their sign-in cookies. User will have to sign in by authenticating again.
- `undelete` — Undeletes a deleted user.
- `update` — Updates a user. This method supports patch semantics, meaning that you only need to include the fields you wish to update. Fields that are not present in the request will be preserved, and fields set
- `update` — Updates a user. This method supports patch semantics, meaning that you only need to include the fields you wish to update. Fields that are not present in the request will be preserved, and fields set to `null` will be cleared. For repeating fields that contain arrays, individual items in the array can't be patched piecemeal; they must be supplied in the request body with the desired values for all items.
- `watch` — Watches for changes in users list.
- `aliases` — Operations on the 'aliases' resource
- `photos` — Operations on the 'photos' resource
+2 -2
View File
@@ -24,11 +24,11 @@ gws alertcenter <resource> <method> [flags]
- `batchDelete` — Performs batch delete operation on alerts.
- `batchUndelete` — Performs batch undelete operation on alerts.
- `delete` — Marks the specified alert for deletion. An alert that has been marked for deletion is removed from Alert Center after 30 days. Marking an alert for deletion has no effect on an alert which has already
- `delete` — Marks the specified alert for deletion. An alert that has been marked for deletion is removed from Alert Center after 30 days. Marking an alert for deletion has no effect on an alert which has already been marked for deletion. Attempting to mark a nonexistent alert for deletion results in a `NOT_FOUND` error.
- `get` — Gets the specified alert. Attempting to get a nonexistent alert returns `NOT_FOUND` error.
- `getMetadata` — Returns the metadata of an alert. Attempting to get metadata for a non-existent alert returns `NOT_FOUND` error.
- `list` — Lists the alerts.
- `undelete` — Restores, or "undeletes", an alert that was marked for deletion within the past 30 days. Attempting to undelete an alert which was marked for deletion over 30 days ago (which has been removed from the
- `undelete` — Restores, or "undeletes", an alert that was marked for deletion within the past 30 days. Attempting to undelete an alert which was marked for deletion over 30 days ago (which has been removed from the Alert Center database) or a nonexistent alert returns a `NOT_FOUND` error. Attempting to undelete an alert which has not been marked for deletion has no effect.
- `feedback` — Operations on the 'feedback' resource
### v1beta1
+1 -1
View File
@@ -37,7 +37,7 @@ gws apps-script <resource> <method> [flags]
- `get` — Gets a script project's metadata.
- `getContent` — Gets the content of the script project, including the code source and metadata for each script file.
- `getMetrics` — Get metrics data for scripts, such as number of executions and active users.
- `updateContent` — Updates the content of the specified script project. This content is stored as the HEAD version, and is used when the script is executed as a trigger, in the script editor, in add-on preview mode, or
- `updateContent` — Updates the content of the specified script project. This content is stored as the HEAD version, and is used when the script is executed as a trigger, in the script editor, in add-on preview mode, or as a web app or Apps Script API in development mode. This clears all the existing files in the project.
- `deployments` — Operations on the 'deployments' resource
- `versions` — Operations on the 'versions' resource
+3 -3
View File
@@ -55,7 +55,7 @@ gws calendar <resource> <method> [flags]
- `insert` — Creates a secondary calendar.
The authenticated user for the request is made the data owner of the new calendar.
Note: We recommend to authenticate as the intended data owner of the calendar. You can
Note: We recommend to authenticate as the intended data owner of the calendar. You can use domain-wide delegation of authority to allow applications to act on behalf of a specific user. Don't use a service account for authentication. If you use a service account for authentication, the service account is the data owner, which can lead to unexpected behavior.
- `patch` — Updates metadata for a calendar. This method supports patch semantics.
- `update` — Updates metadata for a calendar.
@@ -72,11 +72,11 @@ Note: We recommend to authenticate as the intended data owner of the calendar. Y
- `delete` — Deletes an event.
- `get` — Returns an event based on its Google Calendar ID. To retrieve an event using its iCalendar ID, call the events.list method using the iCalUID parameter.
- `import` — Imports an event. This operation is used to add a private copy of an existing event to a calendar. Only events with an eventType of default may be imported.
Deprecated behavior: If a non-default event
Deprecated behavior: If a non-default event is imported, its type will be changed to default and any event-type-specific properties it may have will be dropped.
- `insert` — Creates an event.
- `instances` — Returns instances of the specified recurring event.
- `list` — Returns events on the specified calendar.
- `move` — Moves an event to another calendar, i.e. changes an event's organizer. Note that only default events can be moved; birthday, focusTime, fromGmail, outOfOffice and workingLocation events cannot be move
- `move` — Moves an event to another calendar, i.e. changes an event's organizer. Note that only default events can be moved; birthday, focusTime, fromGmail, outOfOffice and workingLocation events cannot be moved.
- `patch` — Updates an event. This method supports patch semantics.
- `quickAdd` — Creates an event based on a simple text string.
- `update` — Updates an event.
+14 -14
View File
@@ -28,27 +28,27 @@ gws chat <resource> <method> [flags]
### customEmojis
- `create` — Creates a custom emoji. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more information, see [Learn about cu
- `delete` — Deletes a custom emoji. By default, users can only delete custom emoji they created. [Emoji managers](https://support.google.com/a/answer/12850085) assigned by the administrator can delete any custom
- `get` — Returns details about a custom emoji. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more information, see [
- `list` — Lists custom emojis visible to the authenticated user. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more i
- `create` — Creates a custom emoji. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more information, see [Learn about custom emojis in Google Chat](https://support.google.com/chat/answer/12800149) and [Manage custom emoji permissions](https://support.google.com/a/answer/12850085).
- `delete` — Deletes a custom emoji. By default, users can only delete custom emoji they created. [Emoji managers](https://support.google.com/a/answer/12850085) assigned by the administrator can delete any custom emoji in the organization. See [Learn about custom emojis in Google Chat](https://support.google.com/chat/answer/12800149). Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization.
- `get` — Returns details about a custom emoji. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more information, see [Learn about custom emojis in Google Chat](https://support.google.com/chat/answer/12800149) and [Manage custom emoji permissions](https://support.google.com/a/answer/12850085).
- `list` — Lists custom emojis visible to the authenticated user. Custom emojis are only available for Google Workspace accounts, and the administrator must turn custom emojis on for the organization. For more information, see [Learn about custom emojis in Google Chat](https://support.google.com/chat/answer/12800149) and [Manage custom emoji permissions](https://support.google.com/a/answer/12850085).
### media
- `download` — Downloads media. Download is supported on the URI `/v1/media/{+name}?alt=media`.
- `upload` — Uploads an attachment. For an example, see [Upload media as a file attachment](https://developers.google.com/workspace/chat/upload-media-attachments). Requires user [authentication](https://developers
- `upload` — Uploads an attachment. For an example, see [Upload media as a file attachment](https://developers.google.com/workspace/chat/upload-media-attachments).
### spaces
- `completeImport` — Completes the [import process](https://developers.google.com/workspace/chat/import-data) for the specified space and makes it visible to users. Requires [user authentication](https://developers.google
- `create` — Creates a space. Can be used to create a named space, or a group chat in `Import mode`. For an example, see [Create a space](https://developers.google.com/workspace/chat/create-spaces). Supports the f
- `delete` — Deletes a named space. Always performs a cascading delete, which means that the space's child resources—like messages posted in the space and memberships in the space—are also deleted. For an example,
- `findDirectMessage` — Returns the existing direct message with the specified user. If no direct message space is found, returns a `404 NOT_FOUND` error. For an example, see [Find a direct message](/chat/api/guides/v1/space
- `get` — Returns details about a space. For an example, see [Get details about a space](https://developers.google.com/workspace/chat/get-spaces). Supports the following types of [authentication](https://develo
- `list` — Lists spaces the caller is a member of. Group chats and DMs aren't listed until the first message is sent. For an example, see [List spaces](https://developers.google.com/workspace/chat/list-spaces).
- `patch` — Updates a space. For an example, see [Update a space](https://developers.google.com/workspace/chat/update-spaces). If you're updating the `displayName` field and receive the error message `ALREADY_EXI
- `search` — Returns a list of spaces in a Google Workspace organization based on an administrator's search. In the request, set `use_admin_access` to `true`. For an example, see [Search for and manage spaces](htt
- `setup` — Creates a space and adds specified users to it. The calling user is automatically added to the space, and shouldn't be specified as a membership in the request. For an example, see [Set up a space wit
- `completeImport` — Completes the [import process](https://developers.google.com/workspace/chat/import-data) for the specified space and makes it visible to users.
- `create` — Creates a space. Can be used to create a named space, or a group chat in `Import mode`. For an example, see [Create a space](https://developers.google.com/workspace/chat/create-spaces).
- `delete` — Deletes a named space. Always performs a cascading delete, which means that the space's child resources—like messages posted in the space and memberships in the space—are also deleted. For an example, see [Delete a space](https://developers.google.com/workspace/chat/delete-spaces).
- `findDirectMessage` — Returns the existing direct message with the specified user. If no direct message space is found, returns a `404 NOT_FOUND` error. For an example, see [Find a direct message](/chat/api/guides/v1/spaces/find-direct-message). With [app authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-app), returns the direct message space between the specified user and the calling Chat app.
- `get` — Returns details about a space. For an example, see [Get details about a space](https://developers.google.com/workspace/chat/get-spaces).
- `list` — Lists spaces the caller is a member of. Group chats and DMs aren't listed until the first message is sent. For an example, see [List spaces](https://developers.google.com/workspace/chat/list-spaces).
- `patch` — Updates a space. For an example, see [Update a space](https://developers.google.com/workspace/chat/update-spaces). If you're updating the `displayName` field and receive the error message `ALREADY_EXISTS`, try a different display name.. An existing space within the Google Workspace organization might already use this display name.
- `search` — Returns a list of spaces in a Google Workspace organization based on an administrator's search. In the request, set `use_admin_access` to `true`. For an example, see [Search for and manage spaces](https://developers.google.com/workspace/chat/search-manage-admin).
- `setup` — Creates a space and adds specified users to it. The calling user is automatically added to the space, and shouldn't be specified as a membership in the request. For an example, see [Set up a space with initial members](https://developers.google.com/workspace/chat/set-up-spaces). To specify the human members to add, add memberships with the appropriate `membership.member.name`. To add a human user, use `users/{user}`, where `{user}` can be the email address for the user.
- `members` — Operations on the 'members' resource
- `messages` — Operations on the 'messages' resource
- `spaceEvents` — Operations on the 'spaceEvents' resource
+15 -15
View File
@@ -22,14 +22,14 @@ gws classroom <resource> <method> [flags]
### courses
- `create` — Creates a course. The user specified in `ownerId` is the owner of the created course and added as a teacher. A non-admin requesting user can only create a course with themselves as the owner. Domain a
- `delete` — Deletes a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to delete the requested course or for access errors. * `NOT_FOUND` if no
- `get` — Returns a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to access the requested course or for access errors. * `NOT_FOUND` if no
- `getGradingPeriodSettings` — Returns the grading period settings in a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user isn't permitted to access the grading period settings in th
- `list` — Returns a list of courses that the requesting user is permitted to view, restricted to those that match the request. Returned courses are ordered by creation time, with the most recently created comin
- `patch` — Updates one or more fields in a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to modify the requested course or for access errors
- `update` — Updates a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to modify the requested course or for access errors. * `NOT_FOUND` if no
- `updateGradingPeriodSettings` — Updates grading period settings of a course. Individual grading periods can be added, removed, or modified using this method. The requesting user and course owner must be eligible to modify Grading Pe
- `create` — Creates a course. The user specified in `ownerId` is the owner of the created course and added as a teacher. A non-admin requesting user can only create a course with themselves as the owner. Domain admins can create courses owned by any user within their domain. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to create courses or for access errors. * `NOT_FOUND` if the primary teacher is not a valid user.
- `delete` — Deletes a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to delete the requested course or for access errors. * `NOT_FOUND` if no course exists with the requested ID.
- `get` — Returns a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to access the requested course or for access errors. * `NOT_FOUND` if no course exists with the requested ID.
- `getGradingPeriodSettings` — Returns the grading period settings in a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user isn't permitted to access the grading period settings in the requested course or for access errors. * `NOT_FOUND` if the requested course does not exist.
- `list` — Returns a list of courses that the requesting user is permitted to view, restricted to those that match the request. Returned courses are ordered by creation time, with the most recently created coming first. This method returns the following error codes: * `PERMISSION_DENIED` for access errors. * `INVALID_ARGUMENT` if the query argument is malformed. * `NOT_FOUND` if any users specified in the query arguments do not exist.
- `patch` — Updates one or more fields in a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to modify the requested course or for access errors. * `NOT_FOUND` if no course exists with the requested ID. * `INVALID_ARGUMENT` if invalid fields are specified in the update mask or if no update mask is supplied.
- `update` — Updates a course. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to modify the requested course or for access errors. * `NOT_FOUND` if no course exists with the requested ID. * `FAILED_PRECONDITION` for the following request errors: * CourseNotModifiable * CourseTitleCannotContainUrl
- `updateGradingPeriodSettings` — Updates grading period settings of a course. Individual grading periods can be added, removed, or modified using this method. The requesting user and course owner must be eligible to modify Grading Periods. For details, see [licensing requirements](https://developers.google.com/workspace/classroom/grading-periods/manage-grading-periods#licensing_requirements).
- `aliases` — Operations on the 'aliases' resource
- `announcements` — Operations on the 'announcements' resource
- `courseWork` — Operations on the 'courseWork' resource
@@ -42,20 +42,20 @@ gws classroom <resource> <method> [flags]
### invitations
- `accept` — Accepts an invitation, removing it and adding the invited user to the teachers or students (as appropriate) of the specified course. Only the invited user may accept an invitation. This method returns
- `create` — Creates an invitation. Only one invitation for a user and course may exist at a time. Delete and re-create an invitation to make changes. This method returns the following error codes: * `PERMISSION_D
- `delete` — Deletes an invitation. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to delete the requested invitation or for access errors. * `NOT_FOUN
- `get` — Returns an invitation. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to view the requested invitation or for access errors. * `NOT_FOUND`
- `list` — Returns a list of invitations that the requesting user is permitted to view, restricted to those that match the list request. *Note:* At least one of `user_id` or `course_id` must be supplied. Both fi
- `accept` — Accepts an invitation, removing it and adding the invited user to the teachers or students (as appropriate) of the specified course. Only the invited user may accept an invitation. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to accept the requested invitation or for access errors.
- `create` — Creates an invitation. Only one invitation for a user and course may exist at a time. Delete and re-create an invitation to make changes. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to create invitations for this course or for access errors. * `NOT_FOUND` if the course or the user does not exist. * `FAILED_PRECONDITION`: * if the requested user's account is disabled.
- `delete` — Deletes an invitation. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to delete the requested invitation or for access errors. * `NOT_FOUND` if no invitation exists with the requested ID.
- `get` — Returns an invitation. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to view the requested invitation or for access errors. * `NOT_FOUND` if no invitation exists with the requested ID.
- `list` — Returns a list of invitations that the requesting user is permitted to view, restricted to those that match the list request. *Note:* At least one of `user_id` or `course_id` must be supplied. Both fields can be supplied. This method returns the following error codes: * `PERMISSION_DENIED` for access errors.
### registrations
- `create` — Creates a `Registration`, causing Classroom to start sending notifications from the provided `feed` to the destination provided in `cloudPubSubTopic`. Returns the created `Registration`. Currently, th
- `create` — Creates a `Registration`, causing Classroom to start sending notifications from the provided `feed` to the destination provided in `cloudPubSubTopic`. Returns the created `Registration`. Currently, this will be the same as the argument, but with server-assigned fields such as `expiry_time` and `id` filled in. Note that any value specified for the `expiry_time` or `id` fields will be ignored.
- `delete` — Deletes a `Registration`, causing Classroom to stop sending notifications for that `Registration`.
### userProfiles
- `get` — Returns a user profile. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to access this user profile, if no profile exists with the requeste
- `get` — Returns a user profile. This method returns the following error codes: * `PERMISSION_DENIED` if the requesting user is not permitted to access this user profile, if no profile exists with the requested ID, or for access errors.
- `guardianInvitations` — Operations on the 'guardianInvitations' resource
- `guardians` — Operations on the 'guardians' resource
+7 -7
View File
@@ -26,8 +26,8 @@ gws cloudidentity <resource> <method> [flags]
### devices
- `cancelWipe` — Cancels an unfinished device wipe. This operation can be used to cancel device wipe in the gap between the wipe operation returning success and the device being wiped. This operation is possible when
- `create` — Creates a device. Only company-owned device may be created. **Note**: This method is available only to customers who have one of the following SKUs: Enterprise Standard, Enterprise Plus, Enterprise fo
- `cancelWipe` — Cancels an unfinished device wipe. This operation can be used to cancel device wipe in the gap between the wipe operation returning success and the device being wiped. This operation is possible when the device is in a "pending wipe" state. The device enters the "pending wipe" state when a wipe device command is issued, but has not yet been sent to the device. The cancel wipe will fail if the wipe command has already been issued to the device.
- `create` — Creates a device. Only company-owned device may be created. **Note**: This method is available only to customers who have one of the following SKUs: Enterprise Standard, Enterprise Plus, Enterprise for Education, and Cloud Identity Premium
- `delete` — Deletes the specified device.
- `get` — Retrieves the specified device.
- `list` — Lists/Searches devices.
@@ -49,19 +49,19 @@ gws cloudidentity <resource> <method> [flags]
### inboundOidcSsoProfiles
- `create` — Creates an InboundOidcSsoProfile for a customer. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the
- `create` — Creates an InboundOidcSsoProfile for a customer. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will have `"done": false`, it will not have a response, and the metadata will have `"state": "awaiting-multi-party-approval"`.
- `delete` — Deletes an InboundOidcSsoProfile.
- `get` — Gets an InboundOidcSsoProfile.
- `list` — Lists InboundOidcSsoProfile objects for a Google enterprise customer.
- `patch` — Updates an InboundOidcSsoProfile. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will
- `patch` — Updates an InboundOidcSsoProfile. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will have `"done": false`, it will not have a response, and the metadata will have `"state": "awaiting-multi-party-approval"`.
### inboundSamlSsoProfiles
- `create` — Creates an InboundSamlSsoProfile for a customer. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the
- `create` — Creates an InboundSamlSsoProfile for a customer. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will have `"done": false`, it will not have a response, and the metadata will have `"state": "awaiting-multi-party-approval"`.
- `delete` — Deletes an InboundSamlSsoProfile.
- `get` — Gets an InboundSamlSsoProfile.
- `list` — Lists InboundSamlSsoProfiles for a customer.
- `patch` — Updates an InboundSamlSsoProfile. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will
- `patch` — Updates an InboundSamlSsoProfile. When the target customer has enabled [Multi-party approval for sensitive actions](https://support.google.com/a/answer/13790448), the `Operation` in the response will have `"done": false`, it will not have a response, and the metadata will have `"state": "awaiting-multi-party-approval"`.
- `idpCredentials` — Operations on the 'idpCredentials' resource
### inboundSsoAssignments
@@ -70,7 +70,7 @@ gws cloudidentity <resource> <method> [flags]
- `delete` — Deletes an InboundSsoAssignment. To disable SSO, Create (or Update) an assignment that has `sso_mode` == `SSO_OFF`.
- `get` — Gets an InboundSsoAssignment.
- `list` — Lists the InboundSsoAssignments for a `Customer`.
- `patch` — Updates an InboundSsoAssignment. The body of this request is the `inbound_sso_assignment` field and the `update_mask` is relative to that. For example: a PATCH to `/v1/inboundSsoAssignments/0abcdefg12
- `patch` — Updates an InboundSsoAssignment. The body of this request is the `inbound_sso_assignment` field and the `update_mask` is relative to that. For example: a PATCH to `/v1/inboundSsoAssignments/0abcdefg1234567&update_mask=rank` with a body of `{ "rank": 1 }` moves that (presumably group-targeted) SSO assignment to the highest priority and shifts any other group-targeted assignments down in priority.
### policies
+1 -1
View File
@@ -28,7 +28,7 @@ gws docs <resource> <method> [flags]
### documents
- `batchUpdate` — Applies one or more updates to the document. Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied. Some requests h
- `batchUpdate` — Applies one or more updates to the document. Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied. Some requests have replies to give you some information about how they are applied. Other requests do not need to return information; these each return an empty reply. The order of replies matches that of the requests.
- `create` — Creates a blank document using the title given in the request. Other fields in the request, including any provided content, are ignored. Returns the created document.
- `get` — Gets the latest version of the specified document.
+22 -22
View File
@@ -28,12 +28,12 @@ gws drive <resource> <method> [flags]
### about
- `get` — Gets information about the user, the user's Drive, and system capabilities. For more information, see [Return user info](https://developers.google.com/workspace/drive/api/guides/user-info). Required:
- `get` — Gets information about the user, the user's Drive, and system capabilities. For more information, see [Return user info](https://developers.google.com/workspace/drive/api/guides/user-info). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).
### accessproposals
- `get` — Retrieves an access proposal by ID. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access).
- `list` — List the access proposals on a file. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access). Note: Only approvers are able
- `list` — List the access proposals on a file. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access). Note: Only approvers are able to list access proposals on a file. If the user isn't an approver, a 403 error is returned.
- `resolve` — Approves or denies an access proposal. For more information, see [Manage pending access proposals](https://developers.google.com/workspace/drive/api/guides/pending-access).
### approvals
@@ -58,36 +58,36 @@ gws drive <resource> <method> [flags]
### comments
- `create` — Creates a comment on a file. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be
- `create` — Creates a comment on a file. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).
- `delete` — Deletes a comment. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments).
- `get` — Gets a comment by ID. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. T
- `list` — Lists a file's comments. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set
- `update` — Updates a comment with patch semantics. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parame
- `get` — Gets a comment by ID. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).
- `list` — Lists a file's comments. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).
- `update` — Updates a comment with patch semantics. For more information, see [Manage comments and replies](https://developers.google.com/workspace/drive/api/guides/manage-comments). Required: The `fields` parameter must be set. To return the exact fields you need, see [Return specific fields](https://developers.google.com/workspace/drive/api/guides/fields-parameter).
### drives
- `create` — Creates a shared drive. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
- `delete` — Permanently deletes a shared drive for which the user is an `organizer`. The shared drive cannot contain any untrashed items. For more information, see [Manage shared drives](https://developers.google
- `delete` — Permanently deletes a shared drive for which the user is an `organizer`. The shared drive cannot contain any untrashed items. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
- `get` — Gets a shared drive's metadata by ID. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
- `hide` — Hides a shared drive from the default view. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
- `list` Lists the user's shared drives. This method accepts the `q` parameter, which is a search query combining one or more search terms. For more information, see the [Search for shared drives](/workspace/
- `list` — Lists the user's shared drives. This method accepts the `q` parameter, which is a search query combining one or more search terms. For more information, see the [Search for shared drives](/workspace/drive/api/guides/search-shareddrives) guide.
- `unhide` — Restores a shared drive to the default view. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
- `update` — Updates the metadata for a shared drive. For more information, see [Manage shared drives](https://developers.google.com/workspace/drive/api/guides/manage-shareddrives).
### files
- `copy` — Creates a copy of a file and applies any requested updates with patch semantics. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-fil
- `create` Creates a file. For more information, see [Create and manage files](/workspace/drive/api/guides/create-file). This method supports an */upload* URI and accepts uploaded media with the following chara
- `delete` — Permanently deletes a file owned by the user without moving it to the trash. For more information, see [Trash or delete files and folders](https://developers.google.com/workspace/drive/api/guides/dele
- `download` — Downloads the content of a file. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads). Operations are valid for 24 hours fro
- `copy` — Creates a copy of a file and applies any requested updates with patch semantics. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-file).
- `create` — Creates a file. For more information, see [Create and manage files](/workspace/drive/api/guides/create-file). This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:* `*/*` (Specify a valid MIME type, rather than the literal `*/*` value. The literal `*/*` is only used to indicate that any valid MIME type can be uploaded.
- `delete` — Permanently deletes a file owned by the user without moving it to the trash. For more information, see [Trash or delete files and folders](https://developers.google.com/workspace/drive/api/guides/delete). If the file belongs to a shared drive, the user must be an `organizer` on the parent folder. If the target is a folder, all descendants owned by the user are also deleted.
- `download` — Downloads the content of a file. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads). Operations are valid for 24 hours from the time of creation.
- `emptyTrash` — Permanently deletes all of the user's trashed files. For more information, see [Trash or delete files and folders](https://developers.google.com/workspace/drive/api/guides/delete).
- `export` — Exports a Google Workspace document to the requested MIME type and returns exported byte content. For more information, see [Download and export files](https://developers.google.com/workspace/drive/ap
- `export` — Exports a Google Workspace document to the requested MIME type and returns exported byte content. For more information, see [Download and export files](https://developers.google.com/workspace/drive/api/guides/manage-downloads). Note that the exported content is limited to 10 MB.
- `generateIds` — Generates a set of file IDs which can be provided in create or copy requests. For more information, see [Create and manage files](https://developers.google.com/workspace/drive/api/guides/create-file).
- `get` Gets a file's metadata or content by ID. For more information, see [Search for files and folders](/workspace/drive/api/guides/search-files). If you provide the URL parameter `alt=media`, then the res
- `list` Lists the user's files. For more information, see [Search for files and folders](/workspace/drive/api/guides/search-files). This method accepts the `q` parameter, which is a search query combining on
- `get` — Gets a file's metadata or content by ID. For more information, see [Search for files and folders](/workspace/drive/api/guides/search-files). If you provide the URL parameter `alt=media`, then the response includes the file contents in the response body. Downloading content with `alt=media` only works if the file is stored in Drive. To download Google Docs, Sheets, and Slides use [`files.export`](/workspace/drive/api/reference/rest/v3/files/export) instead.
- `list` — Lists the user's files. For more information, see [Search for files and folders](/workspace/drive/api/guides/search-files). This method accepts the `q` parameter, which is a search query combining one or more search terms. This method returns *all* files by default, including trashed files. If you don't want trashed files to appear in the list, use the `trashed=false` query parameter to remove trashed files from the results.
- `listLabels` — Lists the labels on a file. For more information, see [List labels on a file](https://developers.google.com/workspace/drive/api/guides/list-labels).
- `modifyLabels` — Modifies the set of labels applied to a file. For more information, see [Set a label field on a file](https://developers.google.com/workspace/drive/api/guides/set-label). Returns a list of the labels
- `update` Updates a file's metadata, content, or both. When calling this method, only populate fields in the request that you want to modify. When updating fields, some fields might be changed automatically, s
- `modifyLabels` — Modifies the set of labels applied to a file. For more information, see [Set a label field on a file](https://developers.google.com/workspace/drive/api/guides/set-label). Returns a list of the labels that were added or modified.
- `update` — Updates a file's metadata, content, or both. When calling this method, only populate fields in the request that you want to modify. When updating fields, some fields might be changed automatically, such as `modifiedDate`. This method supports patch semantics. This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:* `*/*` (Specify a valid MIME type, rather than the literal `*/*` value.
- `watch` — Subscribes to changes to a file. For more information, see [Notifications for resource changes](https://developers.google.com/workspace/drive/api/guides/push).
### operations
@@ -96,11 +96,11 @@ gws drive <resource> <method> [flags]
### permissions
- `create` — Creates a permission for a file or shared drive. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Con
- `delete` — Deletes a permission. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permissions operati
- `create` — Creates a permission for a file or shared drive. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permissions operations on the same file aren't supported; only the last update is applied.
- `delete` — Deletes a permission. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permissions operations on the same file aren't supported; only the last update is applied.
- `get` — Gets a permission by ID. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing).
- `list` — Lists a file's or shared drive's permissions. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing).
- `update` — Updates a permission with patch semantics. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurren
- `update` — Updates a permission with patch semantics. For more information, see [Share files, folders, and drives](https://developers.google.com/workspace/drive/api/guides/manage-sharing). **Warning:** Concurrent permissions operations on the same file aren't supported; only the last update is applied.
### replies
@@ -112,9 +112,9 @@ gws drive <resource> <method> [flags]
### revisions
- `delete` — Permanently deletes a file version. You can only delete revisions for files with binary content in Google Drive, like images or videos. Revisions for other files, like Google Docs or Sheets, and the l
- `delete` — Permanently deletes a file version. You can only delete revisions for files with binary content in Google Drive, like images or videos. Revisions for other files, like Google Docs or Sheets, and the last remaining file version can't be deleted. For more information, see [Manage file revisions](https://developers.google.com/drive/api/guides/manage-revisions).
- `get` — Gets a revision's metadata or content by ID. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions).
- `list` — Lists a file's revisions. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions). **Important:** The list of revisions returned by
- `list` — Lists a file's revisions. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions). **Important:** The list of revisions returned by this method might be incomplete for files with a large revision history, including frequently edited Google Docs, Sheets, and Slides. Older revisions might be omitted from the response, meaning the first revision returned may not be the oldest existing revision.
- `update` — Updates a revision with patch semantics. For more information, see [Manage file revisions](https://developers.google.com/workspace/drive/api/guides/manage-revisions).
### teamdrives
+5 -5
View File
@@ -37,18 +37,18 @@ gws events <resource> <method> [flags]
### subscriptions
- `create` — Creates a Google Workspace subscription. To learn how to use this method, see [Create a Google Workspace subscription](https://developers.google.com/workspace/events/guides/create-subscription). For a
- `create` — Creates a Google Workspace subscription. To learn how to use this method, see [Create a Google Workspace subscription](https://developers.google.com/workspace/events/guides/create-subscription).
- `delete` — Deletes a Google Workspace subscription. To learn how to use this method, see [Delete a Google Workspace subscription](https://developers.google.com/workspace/events/guides/delete-subscription).
- `get` — Gets details about a Google Workspace subscription. To learn how to use this method, see [Get details about a Google Workspace subscription](https://developers.google.com/workspace/events/guides/get-s
- `get` — Gets details about a Google Workspace subscription. To learn how to use this method, see [Get details about a Google Workspace subscription](https://developers.google.com/workspace/events/guides/get-subscription).
- `list` — Lists Google Workspace subscriptions. To learn how to use this method, see [List Google Workspace subscriptions](https://developers.google.com/workspace/events/guides/list-subscriptions).
- `patch` — Updates or renews a Google Workspace subscription. To learn how to use this method, see [Update or renew a Google Workspace subscription](https://developers.google.com/workspace/events/guides/update-s
- `reactivate` — Reactivates a suspended Google Workspace subscription. This method resets your subscription's `State` field to `ACTIVE`. Before you use this method, you must fix the error that suspended the subscript
- `patch` — Updates or renews a Google Workspace subscription. To learn how to use this method, see [Update or renew a Google Workspace subscription](https://developers.google.com/workspace/events/guides/update-subscription).
- `reactivate` — Reactivates a suspended Google Workspace subscription. This method resets your subscription's `State` field to `ACTIVE`. Before you use this method, you must fix the error that suspended the subscription. This method will ignore or reject any subscription that isn't currently in a suspended state. To learn how to use this method, see [Reactivate a Google Workspace subscription](https://developers.google.com/workspace/events/guides/reactivate-subscription).
### tasks
- `cancel` — Cancel a task from the agent. If supported one should expect no more task updates for the task.
- `get` — Get the current state of a task from the agent.
- `subscribe` — TaskSubscription is a streaming call that will return a stream of task update events. This attaches the stream to an existing in process task. If the task is complete the stream will return the comple
- `subscribe` — TaskSubscription is a streaming call that will return a stream of task update events. This attaches the stream to an existing in process task. If the task is complete the stream will return the completed task (like GetTask) and close the stream.
- `pushNotificationConfigs` — Operations on the 'pushNotificationConfigs' resource
## Discovering Commands
+1 -1
View File
@@ -23,7 +23,7 @@ gws forms <resource> <method> [flags]
### forms
- `batchUpdate` — Change the form with a batch of updates.
- `create` — Create a new form using the title given in the provided form message in the request. *Important:* Only the form.info.title and form.info.document_title fields are copied to the new form. All other fie
- `create` — Create a new form using the title given in the provided form message in the request. *Important:* Only the form.info.title and form.info.document_title fields are copied to the new form. All other fields including the form description, items and settings are disallowed. To create a new form and add items, you must first call forms.create to create an empty form with a title and (optional) document title, and then call forms.update to add the items.
- `get` — Get a form.
- `setPublishSettings` — Updates the publish settings of a form. Legacy forms aren't supported because they don't have the `publish_settings` field.
- `responses` — Operations on the 'responses' resource
+1 -1
View File
@@ -29,7 +29,7 @@ gws keep <resource> <method> [flags]
- `create` — Creates a new note.
- `delete` — Deletes a note. Caller must have the `OWNER` role on the note to delete. Deleting a note removes the resource immediately and cannot be undone. Any collaborators will lose access to the note.
- `get` — Gets a note.
- `list` — Lists notes. Every list call returns a page of results with `page_size` as the upper bound of returned items. A `page_size` of zero allows the server to choose the upper bound. The ListNotesResponse c
- `list` — Lists notes. Every list call returns a page of results with `page_size` as the upper bound of returned items. A `page_size` of zero allows the server to choose the upper bound. The ListNotesResponse contains at most `page_size` entries. If there are more things left to list, it provides a `next_page_token` value. (Page tokens are opaque values.) To get the next page of results, copy the result's `next_page_token` into the next request's `page_token`.
- `permissions` — Operations on the 'permissions' resource
## Discovering Commands
+11 -11
View File
@@ -23,33 +23,33 @@ gws people <resource> <method> [flags]
### contactGroups
- `batchGet` — Get a list of contact groups owned by the authenticated user by specifying a list of contact group resource names.
- `create` — Create a new contact group owned by the authenticated user. Created contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTT
- `delete` — Delete an existing contact group owned by the authenticated user by specifying a contact group resource name. Mutate requests for the same user should be sent sequentially to avoid increased latency a
- `create` — Create a new contact group owned by the authenticated user. Created contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTTP 409 error. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `delete` — Delete an existing contact group owned by the authenticated user by specifying a contact group resource name. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `get` — Get a specific contact group owned by the authenticated user by specifying a contact group resource name.
- `list` — List all contact groups owned by the authenticated user. Members of the contact groups are not populated.
- `update` — Update the name of an existing contact group owned by the authenticated user. Updated contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name
- `update` — Update the name of an existing contact group owned by the authenticated user. Updated contact group names must be unique to the users contact groups. Attempting to create a group with a duplicate name will return a HTTP 409 error. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `members` — Operations on the 'members' resource
### otherContacts
- `copyOtherContactToMyContactsGroup` — Copies an "Other contact" to a new contact in the user's "myContacts" group Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `list` — List all "Other contacts", that is contacts that are not in a contact group. "Other contacts" are typically auto created contacts from interactions. Sync tokens expire 7 days after the full sync. A re
- `search` — Provides a list of contacts in the authenticated user's other contacts that matches the search query. The query matches on a contact's `names`, `emailAddresses`, and `phoneNumbers` fields that are fro
- `list` — List all "Other contacts", that is contacts that are not in a contact group. "Other contacts" are typically auto created contacts from interactions. Sync tokens expire 7 days after the full sync. A request with an expired sync token will get an error with an [google.rpc.ErrorInfo](https://cloud.google.com/apis/design/errors#error_info) with reason "EXPIRED_SYNC_TOKEN". In the case of such an error clients should make a full sync request without a `sync_token`.
- `search` — Provides a list of contacts in the authenticated user's other contacts that matches the search query. The query matches on a contact's `names`, `emailAddresses`, and `phoneNumbers` fields that are from the OTHER_CONTACT source. **IMPORTANT**: Before searching, clients should send a warmup request with an empty query to update the cache. See https://developers.google.com/people/v1/other-contacts#search_the_users_other_contacts
### people
- `batchCreateContacts` — Create a batch of new contacts and return the PersonResponses for the newly Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `batchDeleteContacts` — Delete a batch of contacts. Any non-contact data will not be deleted. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `batchUpdateContacts` — Update a batch of contacts and return a map of resource names to PersonResponses for the updated contacts. Mutate requests for the same user should be sent sequentially to avoid increased latency and
- `createContact` — Create a new contact and return the person resource for that contact. The request returns a 400 error if more than one field is specified on a field that is a singleton for contact sources: * biograph
- `batchUpdateContacts` — Update a batch of contacts and return a map of resource names to PersonResponses for the updated contacts. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `createContact` — Create a new contact and return the person resource for that contact. The request returns a 400 error if more than one field is specified on a field that is a singleton for contact sources: * biographies * birthdays * genders * names Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `deleteContact` — Delete a contact person. Any non-contact data will not be deleted. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `deleteContactPhoto` — Delete a contact's photo. Mutate requests for the same user should be done sequentially to avoid // lock contention.
- `get` — Provides information about a person by specifying a resource name. Use `people/me` to indicate the authenticated user. The request returns a 400 error if 'personFields' is not specified.
- `getBatchGet` — Provides information about a list of specific people by specifying a list of requested resource names. Use `people/me` to indicate the authenticated user. The request returns a 400 error if 'personFie
- `listDirectoryPeople` — Provides a list of domain profiles and domain contacts in the authenticated user's domain directory. When the `sync_token` is specified, resources deleted since the last sync will be returned as a per
- `searchContacts` — Provides a list of contacts in the authenticated user's grouped contacts that matches the search query. The query matches on a contact's `names`, `nickNames`, `emailAddresses`, `phoneNumbers`, and `or
- `getBatchGet` — Provides information about a list of specific people by specifying a list of requested resource names. Use `people/me` to indicate the authenticated user. The request returns a 400 error if 'personFields' is not specified.
- `listDirectoryPeople` — Provides a list of domain profiles and domain contacts in the authenticated user's domain directory. When the `sync_token` is specified, resources deleted since the last sync will be returned as a person with `PersonMetadata.deleted` set to true. When the `page_token` or `sync_token` is specified, all other request parameters must match the first call. Writes may have a propagation delay of several minutes for sync requests. Incremental syncs are not intended for read-after-write use cases.
- `searchContacts` — Provides a list of contacts in the authenticated user's grouped contacts that matches the search query. The query matches on a contact's `names`, `nickNames`, `emailAddresses`, `phoneNumbers`, and `organizations` fields that are from the CONTACT source. **IMPORTANT**: Before searching, clients should send a warmup request with an empty query to update the cache. See https://developers.google.com/people/v1/contacts#search_the_users_contacts
- `searchDirectoryPeople` — Provides a list of domain profiles and domain contacts in the authenticated user's domain directory that match the search query.
- `updateContact` — Update contact data for an existing contact person. Any non-contact data will not be modified. Any non-contact data in the person to update will be ignored. All fields specified in the `update_mask` w
- `updateContact` — Update contact data for an existing contact person. Any non-contact data will not be modified. Any non-contact data in the person to update will be ignored. All fields specified in the `update_mask` will be replaced. The server returns a 400 error if `person.metadata.sources` is not specified for the contact to be updated or if there is no contact source.
- `updateContactPhoto` — Update a contact's photo. Mutate requests for the same user should be sent sequentially to avoid increased latency and failures.
- `connections` — Operations on the 'connections' resource
+13 -13
View File
@@ -22,10 +22,10 @@ gws reseller <resource> <method> [flags]
### customers
- `get` — Gets a customer account. Use this operation to see a customer account already in your reseller management, or to see the minimal account information for an existing customer that you do not manage. Fo
- `insert` — Orders a new customer's account. Before ordering a new customer account, establish whether the customer account already exists using the [`customers.get`](https://developers.google.com/workspace/admin
- `patch` — Updates a customer account's settings. This method supports patch semantics. You cannot update `customerType` via the Reseller API, but a `"team"` customer can verify their domain and become `customer
- `update` — Updates a customer account's settings. You cannot update `customerType` via the Reseller API, but a `"team"` customer can verify their domain and become `customerType = "domain"`. For more information
- `get` — Gets a customer account. Use this operation to see a customer account already in your reseller management, or to see the minimal account information for an existing customer that you do not manage. For more information about the API response for existing customers, see [retrieving a customer account](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_customers#get_customer).
- `insert` — Orders a new customer's account.
- `patch` — Updates a customer account's settings. This method supports patch semantics. You cannot update `customerType` via the Reseller API, but a `"team"` customer can verify their domain and become `customerType = "domain"`. For more information, see [Verify your domain to unlock Essentials features](https://support.google.com/a/answer/9122284).
- `update` — Updates a customer account's settings. You cannot update `customerType` via the Reseller API, but a `"team"` customer can verify their domain and become `customerType = "domain"`. For more information, see [update a customer's settings](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_customers#update_customer).
### resellernotify
@@ -35,16 +35,16 @@ gws reseller <resource> <method> [flags]
### subscriptions
- `activate` — Activates a subscription previously suspended by the reseller. If you did not suspend the customer subscription and it is suspended for any other reason, such as for abuse or a pending ToS acceptance,
- `changePlan` — Updates a subscription plan. Use this method to update a plan for a 30-day trial or a flexible plan subscription to an annual commitment plan with monthly or yearly payments. How a plan is updated dif
- `changeRenewalSettings` — Updates a user license's renewal settings. This is applicable for accounts with annual commitment plans only. For more information, see the description in [manage subscriptions](https://developers.goo
- `changeSeats` — Updates a subscription's user license settings. For more information about updating an annual commitment plan or a flexible plan subscriptions licenses, see [Manage Subscriptions](https://developers.
- `activate` — Activates a subscription previously suspended by the reseller. If you did not suspend the customer subscription and it is suspended for any other reason, such as for abuse or a pending ToS acceptance, this call will not reactivate the customer subscription.
- `changePlan` — Updates a subscription plan. Use this method to update a plan for a 30-day trial or a flexible plan subscription to an annual commitment plan with monthly or yearly payments. How a plan is updated differs depending on the plan and the products. For more information, see the description in [manage subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#update_subscription_plan).
- `changeRenewalSettings` — Updates a user license's renewal settings. This is applicable for accounts with annual commitment plans only. For more information, see the description in [manage subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#update_renewal).
- `changeSeats` — Updates a subscription's user license settings. For more information about updating an annual commitment plan or a flexible plan subscriptions licenses, see [Manage Subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#update_subscription_seat).
- `delete` — Cancels, suspends, or transfers a subscription to direct.
- `get` — Gets a specific subscription. The `subscriptionId` can be found using the [Retrieve all reseller subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#g
- `insert` — Creates or transfer a subscription. Create a subscription for a customer's account that you ordered using the [Order a new customer account](https://developers.google.com/workspace/admin/reseller/v1/r
- `list` — Lists of subscriptions managed by the reseller. The list can be all subscriptions, all of a customer's subscriptions, or all of a customer's transferable subscriptions. Optionally, this method can fil
- `startPaidService` — Immediately move a 30-day free trial subscription to a paid service subscription. This method is only applicable if a payment plan has already been set up for the 30-day trial subscription. For more i
- `suspend` — Suspends an active subscription. You can use this method to suspend a paid subscription that is currently in the `ACTIVE` state. * For `FLEXIBLE` subscriptions, billing is paused. * For `ANNUAL_MONTHL
- `get` — Gets a specific subscription. The `subscriptionId` can be found using the [Retrieve all reseller subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#get_all_subscriptions) method. For more information about retrieving a specific subscription, see the information descrived in [manage subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#get_subscription).
- `insert` — Creates or transfer a subscription. Create a subscription for a customer's account that you ordered using the [Order a new customer account](https://developers.google.com/workspace/admin/reseller/v1/reference/customers/insert.html) method.
- `list` — Lists of subscriptions managed by the reseller. The list can be all subscriptions, all of a customer's subscriptions, or all of a customer's transferable subscriptions. Optionally, this method can filter the response by a `customerNamePrefix`. For more information, see [manage subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions).
- `startPaidService` — Immediately move a 30-day free trial subscription to a paid service subscription. This method is only applicable if a payment plan has already been set up for the 30-day trial subscription. For more information, see [manage subscriptions](https://developers.google.com/workspace/admin/reseller/v1/how-tos/manage_subscriptions#paid_service).
- `suspend` — Suspends an active subscription. You can use this method to suspend a paid subscription that is currently in the `ACTIVE` state. * For `FLEXIBLE` subscriptions, billing is paused. * For `ANNUAL_MONTHLY_PAY` or `ANNUAL_YEARLY_PAY` subscriptions: * Suspending the subscription does not change the renewal date that was originally committed to. * A suspended subscription does not renew.
## Discovering Commands
+3 -3
View File
@@ -29,10 +29,10 @@ gws sheets <resource> <method> [flags]
### spreadsheets
- `batchUpdate` — Applies one or more updates to the spreadsheet. Each request is validated before being applied. If any request is not valid then the entire request will fail and nothing will be applied. Some requests
- `batchUpdate` — Applies one or more updates to the spreadsheet. Each request is validated before being applied. If any request is not valid then the entire request will fail and nothing will be applied. Some requests have replies to give you some information about how they are applied. The replies will mirror the requests. For example, if you applied 4 updates and the 3rd one had a reply, then the response will have 2 empty replies, the actual reply, and another empty reply, in that order.
- `create` — Creates a spreadsheet, returning the newly created spreadsheet.
- `get` — Returns the spreadsheet at the given ID. The caller must specify the spreadsheet ID. By default, data within grids is not returned. You can include grid data in one of 2 ways: * Specify a [field mask]
- `getByDataFilter` — Returns the spreadsheet at the given ID. The caller must specify the spreadsheet ID. For more information, see [Read, write, and search metadata](https://developers.google.com/workspace/sheets/api/gui
- `get` — Returns the spreadsheet at the given ID. The caller must specify the spreadsheet ID. By default, data within grids is not returned. You can include grid data in one of 2 ways: * Specify a [field mask](https://developers.google.com/workspace/sheets/api/guides/field-masks) listing your desired fields using the `fields` URL parameter in HTTP * Set the includeGridData URL parameter to true.
- `getByDataFilter` — Returns the spreadsheet at the given ID. The caller must specify the spreadsheet ID. For more information, see [Read, write, and search metadata](https://developers.google.com/workspace/sheets/api/guides/metadata). This method differs from GetSpreadsheet in that it allows selecting which subsets of spreadsheet data to return by specifying a dataFilters parameter. Multiple DataFilters can be specified.
- `developerMetadata` — Operations on the 'developerMetadata' resource
- `sheets` — Operations on the 'sheets' resource
- `values` — Operations on the 'values' resource
+2 -2
View File
@@ -22,8 +22,8 @@ gws slides <resource> <method> [flags]
### presentations
- `batchUpdate` — Applies one or more updates to the presentation. Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied. Some reques
- `create` — Creates a blank presentation using the title given in the request. If a `presentationId` is provided, it is used as the ID of the new presentation. Otherwise, a new ID is generated. Other fields in th
- `batchUpdate` — Applies one or more updates to the presentation. Each request is validated before being applied. If any request is not valid, then the entire request will fail and nothing will be applied. Some requests have replies to give you some information about how they are applied. Other requests do not need to return information; these each return an empty reply. The order of replies matches that of the requests.
- `create` — Creates a blank presentation using the title given in the request. If a `presentationId` is provided, it is used as the ID of the new presentation. Otherwise, a new ID is generated. Other fields in the request, including any provided content, are ignored. Returns the created presentation.
- `get` — Gets the latest version of the specified presentation.
- `pages` — Operations on the 'pages' resource
+4 -4
View File
@@ -32,11 +32,11 @@ gws tasks <resource> <method> [flags]
### tasks
- `clear` — Clears all completed tasks from the specified task list. The affected tasks will be marked as 'hidden' and no longer be returned by default when retrieving all tasks for a task list.
- `delete` — Deletes the specified task from the task list. If the task is assigned, both the assigned task and the original task (in Docs, Chat Spaces) are deleted. To delete the assigned task only, navigate to t
- `delete` — Deletes the specified task from the task list. If the task is assigned, both the assigned task and the original task (in Docs, Chat Spaces) are deleted. To delete the assigned task only, navigate to the assignment surface and unassign the task from there.
- `get` — Returns the specified task.
- `insert` — Creates a new task on the specified task list. Tasks assigned from Docs or Chat Spaces cannot be inserted from Tasks Public API; they can only be created by assigning them from Docs or Chat Spaces. A
- `list` — Returns all tasks in the specified task list. Doesn't return assigned tasks by default (from Docs, Chat Spaces). A user can have up to 20,000 non-hidden tasks per list and up to 100,000 tasks in total
- `move` — Moves the specified task to another position in the destination task list. If the destination list is not specified, the task is moved within its current list. This can include putting it as a child t
- `insert` — Creates a new task on the specified task list. Tasks assigned from Docs or Chat Spaces cannot be inserted from Tasks Public API; they can only be created by assigning them from Docs or Chat Spaces. A user can have up to 20,000 non-hidden tasks per list and up to 100,000 tasks in total at a time.
- `list` — Returns all tasks in the specified task list. Doesn't return assigned tasks by default (from Docs, Chat Spaces). A user can have up to 20,000 non-hidden tasks per list and up to 100,000 tasks in total at a time.
- `move` — Moves the specified task to another position in the destination task list. If the destination list is not specified, the task is moved within its current list. This can include putting it as a child task under a new parent and/or move it to a different position among its sibling tasks. A user can have up to 2,000 subtasks per task.
- `patch` — Updates the specified task. This method supports patch semantics.
- `update` — Updates the specified task.
+2 -2
View File
@@ -39,8 +39,8 @@ gws vault <resource> <method> [flags]
### operations
- `cancel` — Starts asynchronous cancellation on a long-running operation. The server makes a best effort to cancel the operation, but success is not guaranteed. If the server doesn't support this method, it retur
- `delete` — Deletes a long-running operation. This method indicates that the client is no longer interested in the operation result. It does not cancel the operation. If the server doesn't support this method, it
- `cancel` — Starts asynchronous cancellation on a long-running operation. The server makes a best effort to cancel the operation, but success is not guaranteed. If the server doesn't support this method, it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or other methods to check whether the cancellation succeeded or whether the operation completed despite cancellation.
- `delete` — Deletes a long-running operation. This method indicates that the client is no longer interested in the operation result. It does not cancel the operation. If the server doesn't support this method, it returns `google.rpc.Code.UNIMPLEMENTED`.
- `get` — Gets the latest state of a long-running operation. Clients can use this method to poll the operation result at intervals as recommended by the API service.
- `list` — Lists operations that match the specified filter in the request. If the server doesn't support this method, it returns `UNIMPLEMENTED`.
+5 -8
View File
@@ -88,14 +88,11 @@ fn build_resource_command(name: &str, resource: &RestResource) -> Option<Command
has_children = true;
let about = method
.description
.as_deref()
.unwrap_or("")
// Truncate long descriptions for help text
.chars()
.take(200)
.collect::<String>();
let about = crate::text::truncate_description(
method.description.as_deref().unwrap_or(""),
crate::text::CLI_DESCRIPTION_LIMIT,
true,
);
let mut method_cmd = Command::new(method_name.to_string())
.about(about)
+191 -10
View File
@@ -144,7 +144,7 @@ pub async fn handle_generate_skills(args: &[String]) -> Result<(), GwsError> {
};
if emit_service {
let service_md =
render_service_skill(alias, entry, &helpers, &resources, &product_name);
render_service_skill(alias, entry, &helpers, &resources, &product_name, &doc);
write_skill(output_path, &skill_name, &service_md)?;
index.push(SkillIndexEntry {
name: skill_name.clone(),
@@ -353,6 +353,7 @@ fn render_service_skill(
helpers: &[&Command],
resources: &[&Command],
product_name: &str,
doc: &crate::discovery::RestDescription,
) -> String {
let mut out = String::new();
@@ -414,7 +415,12 @@ metadata:
.get_subcommands()
.map(|m| {
let mname = m.get_name().to_string();
let mabout = m.get_about().map(|s| s.to_string()).unwrap_or_default();
// Use full description from discovery doc (with higher limit)
// instead of the CLI-truncated about text.
let mabout =
lookup_method_description(doc, res_name, &mname).unwrap_or_else(|| {
m.get_about().map(|s| s.to_string()).unwrap_or_default()
});
format!(" - `{mname}` — {mabout}")
})
.collect();
@@ -844,20 +850,38 @@ fn truncate_desc(desc: &str) -> String {
if let Some(first) = s.get(0..1) {
s = format!("{}{}", first.to_uppercase(), &s[1..]);
}
if s.len() > 120 {
if let Some(idx) = s[..120].rfind(' ') {
s = format!("{}...", &s[..idx]);
} else {
s = format!("{}...", &s[..117]);
}
}
// Delegate to shared truncation logic
s = crate::text::truncate_description(&s, crate::text::FRONTMATTER_DESCRIPTION_LIMIT, true);
// Ensure trailing period
if !s.ends_with('.') && !s.ends_with("...") {
if !s.ends_with('.') && !s.ends_with('…') {
s.push('.');
}
s
}
/// Looks up a method's full description from the Discovery Document and
/// truncates it at the skill-body limit (longer than CLI help).
fn lookup_method_description(
doc: &crate::discovery::RestDescription,
resource_name: &str,
method_name: &str,
) -> Option<String> {
let resource = doc.resources.get(resource_name)?;
// Try direct method lookup first
if let Some(method) = resource.methods.get(method_name) {
if let Some(desc) = &method.description {
return Some(crate::text::truncate_description(
desc,
crate::text::SKILL_BODY_DESCRIPTION_LIMIT,
false,
));
}
}
// For sub-resources listed as methods in the clap tree, return None
// (they show as "Operations on the 'X' resource" which is fine)
None
}
fn capitalize_first(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
@@ -968,4 +992,161 @@ mod tests {
}
}
}
#[test]
fn test_truncate_desc_short() {
assert_eq!(truncate_desc("hello world"), "Hello world.");
}
#[test]
fn test_truncate_desc_capitalizes() {
assert_eq!(truncate_desc("lists all files."), "Lists all files.");
}
#[test]
fn test_truncate_desc_replaces_quotes() {
assert_eq!(
truncate_desc(r#"Returns a "File" resource."#),
"Returns a 'File' resource."
);
}
#[test]
fn test_truncate_desc_truncates_long() {
let long = "A ".repeat(100); // 200 chars
let result = truncate_desc(&long);
assert!(
result.chars().count() <= crate::text::FRONTMATTER_DESCRIPTION_LIMIT + 2,
"should respect limit"
);
}
#[test]
fn test_truncate_desc_adds_period() {
assert_eq!(truncate_desc("no period"), "No period.");
}
#[test]
fn test_truncate_desc_preserves_existing_period() {
assert_eq!(truncate_desc("has one."), "Has one.");
}
#[test]
fn test_truncate_desc_ellipsis_no_period() {
// When truncation produces an ellipsis, don't add a period
let long = "word ".repeat(50);
let result = truncate_desc(&long);
assert!(result.ends_with('…'));
assert!(!result.ends_with(".…"));
}
#[test]
fn test_lookup_method_description_found() {
let mut methods = std::collections::HashMap::new();
methods.insert(
"list".to_string(),
crate::discovery::RestMethod {
description: Some(
"Lists all the files. For more details see the docs.".to_string(),
),
http_method: "GET".to_string(),
path: "files".to_string(),
..Default::default()
},
);
let mut resources = std::collections::HashMap::new();
resources.insert(
"files".to_string(),
crate::discovery::RestResource {
methods,
..Default::default()
},
);
let doc = crate::discovery::RestDescription {
name: "drive".to_string(),
resources,
..Default::default()
};
let result = lookup_method_description(&doc, "files", "list");
assert!(result.is_some());
assert!(result.unwrap().contains("Lists all the files"));
}
#[test]
fn test_lookup_method_description_missing_resource() {
let doc = crate::discovery::RestDescription {
name: "drive".to_string(),
..Default::default()
};
assert!(lookup_method_description(&doc, "missing", "list").is_none());
}
#[test]
fn test_lookup_method_description_missing_method() {
let mut resources = std::collections::HashMap::new();
resources.insert(
"files".to_string(),
crate::discovery::RestResource::default(),
);
let doc = crate::discovery::RestDescription {
name: "drive".to_string(),
resources,
..Default::default()
};
assert!(lookup_method_description(&doc, "files", "missing").is_none());
}
#[test]
fn test_lookup_method_description_no_description() {
let mut methods = std::collections::HashMap::new();
methods.insert(
"list".to_string(),
crate::discovery::RestMethod {
description: None,
http_method: "GET".to_string(),
path: "files".to_string(),
..Default::default()
},
);
let mut resources = std::collections::HashMap::new();
resources.insert(
"files".to_string(),
crate::discovery::RestResource {
methods,
..Default::default()
},
);
let doc = crate::discovery::RestDescription {
name: "drive".to_string(),
resources,
..Default::default()
};
assert!(lookup_method_description(&doc, "files", "list").is_none());
}
#[test]
fn test_capitalize_first_empty() {
assert_eq!(capitalize_first(""), "");
}
#[test]
fn test_capitalize_first_basic() {
assert_eq!(capitalize_first("hello"), "Hello");
}
#[test]
fn test_product_name_from_title_strips_api() {
assert_eq!(product_name_from_title("Google Drive API"), "Google Drive");
}
#[test]
fn test_product_name_from_title_no_api_suffix() {
// product_name_from_title prepends "Google" if not already present
assert_eq!(product_name_from_title("Workspace"), "Google Workspace");
}
#[test]
fn test_product_name_from_title_adds_google() {
assert_eq!(product_name_from_title("Drive API"), "Google Drive");
}
}
+1
View File
@@ -37,6 +37,7 @@ mod schema;
mod services;
mod setup;
mod setup_tui;
mod text;
mod token_storage;
pub(crate) mod validate;
+265
View File
@@ -0,0 +1,265 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Max chars for CLI `--help` method descriptions (terminal-width friendly).
pub const CLI_DESCRIPTION_LIMIT: usize = 200;
/// Max chars for YAML frontmatter / skill index descriptions (compact metadata).
pub const FRONTMATTER_DESCRIPTION_LIMIT: usize = 120;
/// Max chars for skill body method descriptions (markdown, agents benefit from detail).
pub const SKILL_BODY_DESCRIPTION_LIMIT: usize = 500;
/// Truncates a description string to `max_chars` using smart boundaries.
///
/// When `strip_links` is true, markdown links `[text](url)` are replaced with
/// just `text` to reclaim character budget (useful for CLI help / frontmatter).
/// When false, links are preserved (useful for skill body text where agents can
/// follow URLs).
///
/// Truncation strategy:
/// 1. If a complete sentence (ending in `. `) fits within the limit, truncate there.
/// 2. Otherwise, break at the last word boundary (space) and append `…`.
/// 3. If no space exists, hard-cut at `max_chars - 1` and append `…`.
pub fn truncate_description(desc: &str, max_chars: usize, strip_links: bool) -> String {
if max_chars == 0 {
return String::new();
}
let cleaned = if strip_links {
strip_markdown_links(desc)
} else {
desc.to_string()
};
let trimmed = cleaned.trim();
// Count chars (UTF-8 safe)
let char_count = trimmed.chars().count();
if char_count <= max_chars {
return trimmed.to_string();
}
// Collect the first `max_chars` characters as a string to search within.
let prefix: String = trimmed.chars().take(max_chars).collect();
// Try to find the last complete sentence within the limit.
// A sentence ends with ". " followed by more text, or "." at the end of
// the prefix. We look for the last ". " to find a sentence boundary.
if let Some(sentence_end) = find_last_sentence_boundary(&prefix) {
let truncated: String = trimmed.chars().take(sentence_end).collect();
return truncated;
}
// Fall back to last word boundary (space) within the limit.
if let Some(last_space) = rfind_char_boundary(&prefix, ' ') {
let truncated: String = trimmed.chars().take(last_space).collect();
return format!("{truncated}");
}
// Hard cut — no spaces at all
let truncated: String = trimmed.chars().take(max_chars - 1).collect();
format!("{truncated}")
}
/// Strips markdown-style links `[text](url)` and replaces them with just `text`.
fn strip_markdown_links(s: &str) -> String {
let mut result = String::with_capacity(s.len());
let chars: Vec<char> = s.chars().collect();
let len = chars.len();
let mut i = 0;
while i < len {
if chars[i] == '[' {
// Look for the closing ] followed by (
if let Some(close_bracket) = find_char_from(&chars, ']', i + 1) {
if close_bracket + 1 < len && chars[close_bracket + 1] == '(' {
if let Some(close_paren) = find_char_from(&chars, ')', close_bracket + 2) {
// Found a complete [text](url) — emit just the text
result.extend(&chars[i + 1..close_bracket]);
i = close_paren + 1;
continue;
}
}
}
}
result.push(chars[i]);
i += 1;
}
result
}
/// Finds the character-index of `target` starting from position `from`.
fn find_char_from(chars: &[char], target: char, from: usize) -> Option<usize> {
chars[from..]
.iter()
.position(|&c| c == target)
.map(|p| from + p)
}
/// Finds the last sentence boundary within a char-indexed string.
/// A sentence boundary is a position right after ". " where we can cleanly cut.
/// Returns the char-count to include (up to and including the period).
fn find_last_sentence_boundary(prefix: &str) -> Option<usize> {
let chars: Vec<char> = prefix.chars().collect();
let mut last_boundary = None;
for (i, _) in chars.iter().enumerate() {
if chars[i] == '.' {
let after_period = i + 1;
// Sentence boundary: period followed by a space, or period at end of prefix
if after_period == chars.len()
|| (after_period < chars.len() && chars[after_period] == ' ')
{
last_boundary = Some(after_period);
}
}
}
last_boundary
}
/// Finds the last occurrence of `target` in a string, returning its char-index.
fn rfind_char_boundary(s: &str, target: char) -> Option<usize> {
let chars: Vec<char> = s.chars().collect();
chars.iter().rposition(|&c| c == target)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn short_desc_unchanged() {
let desc = "Lists all files.";
assert_eq!(truncate_description(desc, 200, true), "Lists all files.");
}
#[test]
fn truncate_at_sentence_boundary() {
let desc = "Creates a file in Drive. This method supports multipart upload. See the guide for details on how to use it.";
// At limit 30, only the first sentence fits before the sentence boundary.
let result = truncate_description(desc, 30, true);
assert_eq!(result, "Creates a file in Drive.");
// At limit 70, both first and second sentences fit.
let result = truncate_description(desc, 70, true);
assert_eq!(
result,
"Creates a file in Drive. This method supports multipart upload."
);
}
#[test]
fn truncate_at_word_boundary() {
let desc = "Create a guest user with access to a subset of Workspace capabilities";
let result = truncate_description(desc, 50, true);
// Should cut at the last space before char 50
assert!(result.ends_with('…'));
assert!(result.len() <= 55); // 50 chars + ellipsis
assert!(!result.contains("capabil")); // Should not cut mid-word
}
#[test]
fn hard_cut_no_spaces() {
let desc = "abcdefghijklmnopqrstuvwxyz";
let result = truncate_description(desc, 10, true);
assert_eq!(result, "abcdefghi…");
}
#[test]
fn strips_markdown_links() {
let desc = "Create a guest user with access to a [subset of Workspace capabilities](https://support.google.com/a/answer/16558545). This feature is in Alpha.";
let result = truncate_description(desc, 200, true);
assert_eq!(
result,
"Create a guest user with access to a subset of Workspace capabilities. This feature is in Alpha."
);
assert!(!result.contains("https://"));
assert!(!result.contains('['));
}
#[test]
fn preserves_links_when_strip_links_false() {
let desc = "Create a guest user with access to a [subset of Workspace capabilities](https://support.google.com/a/answer/16558545). This feature is in Alpha.";
let result = truncate_description(desc, 500, false);
assert!(result.contains("https://support.google.com"));
assert!(result.contains("[subset of Workspace capabilities]"));
}
#[test]
fn strips_markdown_links_and_truncates() {
let desc = "Create a guest user with access to a [subset of Workspace capabilities](https://support.google.com/a/answer/16558545). This feature is currently in Alpha. Please reach out to support if you are interested in enabling this feature.";
let result = truncate_description(desc, 120, true);
// After stripping the link, the sentence boundary should work.
assert!(result.contains("subset of Workspace capabilities."));
assert!(!result.contains("https://"));
}
#[test]
fn multibyte_safe() {
let desc = "Résumé création für Ñoño — a long description that should be safely truncated at word boundaries without panicking on multi-byte chars";
let result = truncate_description(desc, 30, true);
assert!(result.ends_with('…') || result.chars().count() <= 30);
}
#[test]
fn empty_and_whitespace() {
assert_eq!(truncate_description("", 100, true), "");
assert_eq!(truncate_description(" ", 100, true), "");
assert_eq!(truncate_description("", 0, true), "");
}
#[test]
fn test_strip_markdown_links() {
assert_eq!(strip_markdown_links("[text](http://example.com)"), "text");
assert_eq!(
strip_markdown_links("Use [this link](http://a.com) and [that](http://b.com) too"),
"Use this link and that too"
);
assert_eq!(strip_markdown_links("no links here"), "no links here");
// Incomplete link syntax should be left alone
assert_eq!(strip_markdown_links("[broken"), "[broken");
assert_eq!(strip_markdown_links("[text]no-parens"), "[text]no-parens");
}
#[test]
fn preserves_sentence_ending_at_limit() {
let desc = "Deletes a user.";
assert_eq!(truncate_description(desc, 15, true), "Deletes a user.");
}
#[test]
fn does_not_cut_url_looking_periods() {
// Periods in URLs or abbreviations like "v1." shouldn't be treated as sentence ends
// unless followed by a space
let desc = "See the docs at developers.google.com for more details on this API endpoint";
let result = truncate_description(desc, 50, true);
// Should truncate at word boundary, not at "developers."
assert!(result.ends_with('…'));
}
#[test]
fn sentence_boundary_at_exact_limit() {
// Period falls exactly at the end of the prefix — should still detect it
let desc = "This is a complete sentence. And more text follows here.";
let result = truncate_description(desc, 28, true);
assert_eq!(result, "This is a complete sentence.");
}
#[test]
fn zero_max_chars() {
assert_eq!(truncate_description("anything", 0, true), "");
}
}