@qvac/skills 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +198 -0
- package/README.md +40 -0
- package/index.d.ts +4 -0
- package/index.js +9 -0
- package/package.json +87 -1
- package/skills/apple-notes/SKILL.md +92 -0
- package/skills/apple-notes/append-note.applescript +9 -0
- package/skills/apple-notes/cli.schema.json +32 -0
- package/skills/apple-notes/create-note.applescript +15 -0
- package/skills/apple-notes/delete-note.applescript +10 -0
- package/skills/apple-notes/edit-note.applescript +10 -0
- package/skills/apple-notes/read-note.applescript +28 -0
- package/skills/apple-notes/references/read.md +65 -0
- package/skills/apple-notes/references/write.md +105 -0
- package/skills/apple-notes/search-notes.applescript +21 -0
- package/skills/apple-reminders/SKILL.md +129 -0
- package/skills/apple-reminders/cli.schema.json +201 -0
- package/skills/apple-reminders/references/edit.md +69 -0
- package/skills/apple-reminders/references/view.md +58 -0
- package/skills/asana/SKILL.md +59 -0
- package/skills/diagrams/SKILL.md +107 -0
- package/skills/diagrams/references/class.md +29 -0
- package/skills/diagrams/references/er.md +27 -0
- package/skills/diagrams/references/flowchart.md +33 -0
- package/skills/diagrams/references/gantt.md +38 -0
- package/skills/diagrams/references/mindmap.md +35 -0
- package/skills/diagrams/references/pie.md +27 -0
- package/skills/diagrams/references/sequence.md +32 -0
- package/skills/diagrams/references/state.md +30 -0
- package/skills/diagrams/references/timeline.md +28 -0
- package/skills/excel/SKILL.md +120 -0
- package/skills/excel/references/create.md +374 -0
- package/skills/excel/references/edit.md +353 -0
- package/skills/excel/references/read.md +99 -0
- package/skills/github/SKILL.md +42 -0
- package/skills/gmail/SKILL.md +142 -0
- package/skills/gmail/operations.json +71 -0
- package/skills/google-calendar/SKILL.md +139 -0
- package/skills/google-calendar/operations.json +62 -0
- package/skills/google-docs/SKILL.md +74 -0
- package/skills/google-docs/operations.json +61 -0
- package/skills/google-docs/references/create.md +97 -0
- package/skills/google-docs/references/edit.md +146 -0
- package/skills/google-docs/references/read.md +49 -0
- package/skills/google-drive/SKILL.md +118 -0
- package/skills/google-drive/operations.json +40 -0
- package/skills/google-sheets/SKILL.md +71 -0
- package/skills/google-sheets/operations.json +85 -0
- package/skills/google-sheets/references/create.md +54 -0
- package/skills/google-sheets/references/edit.md +124 -0
- package/skills/google-sheets/references/read.md +74 -0
- package/skills/image-generation/SKILL.md +48 -0
- package/skills/music-generation/SKILL.md +76 -0
- package/skills/notion/SKILL.md +61 -0
- package/skills/notion/operations.json +53 -0
- package/skills/notion/references/comments.md +65 -0
- package/skills/notion/references/databases.md +68 -0
- package/skills/notion/references/pages.md +119 -0
- package/skills/notion/references/tasks.md +28 -0
- package/skills/obsidian/SKILL.md +122 -0
- package/skills/obsidian/cli.schema.json +392 -0
- package/skills/obsidian/references/read.md +79 -0
- package/skills/obsidian/references/write.md +67 -0
- package/skills/pdf/SKILL.md +110 -0
- package/skills/pdf/references/create.md +169 -0
- package/skills/pdf/references/transform.md +270 -0
- package/skills/pdf/scripts/decrypt.py +26 -0
- package/skills/pdf/scripts/encrypt.py +25 -0
- package/skills/pdf/scripts/extract_text.py +25 -0
- package/skills/pdf/scripts/merge.py +21 -0
- package/skills/pdf/scripts/rotate.py +27 -0
- package/skills/presentations/SKILL.md +118 -0
- package/skills/presentations/references/create.md +399 -0
- package/skills/presentations/references/edit.md +314 -0
- package/skills/presentations/references/read.md +127 -0
- package/skills/spotify/SKILL.md +86 -0
- package/skills/weather/SKILL.md +33 -0
- package/skills/word/SKILL.md +141 -0
- package/skills/word/references/create.md +368 -0
- package/skills/word/references/edit.md +704 -0
- package/skills/word/references/read.md +141 -0
- package/skills/word/references/replace.md +86 -0
- package/skills/word/scripts/list_paragraphs.py +19 -0
- package/skills/word/scripts/replace_paragraphs.py +58 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"operations": [
|
|
3
|
+
{
|
|
4
|
+
"tool": "gmail_send",
|
|
5
|
+
"description": "Send an email through Gmail, or reply in a thread when threadId and inReplyTo are given. Pass the message as plain fields — never build the RFC 2822 message or base64 yourself. Confirm the recipient and body with the user before sending.",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"to": {
|
|
10
|
+
"type": "array",
|
|
11
|
+
"items": { "type": "string" },
|
|
12
|
+
"description": "Recipient email addresses"
|
|
13
|
+
},
|
|
14
|
+
"subject": { "type": "string", "description": "Subject line" },
|
|
15
|
+
"text": { "type": "string", "description": "Plain-text body" },
|
|
16
|
+
"html": { "type": "string", "description": "HTML body, used when text is absent" },
|
|
17
|
+
"cc": { "type": "array", "items": { "type": "string" } },
|
|
18
|
+
"bcc": { "type": "array", "items": { "type": "string" } },
|
|
19
|
+
"replyTo": { "type": "string" },
|
|
20
|
+
"threadId": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Thread to reply in, from a previous messages.list or messages.get"
|
|
23
|
+
},
|
|
24
|
+
"inReplyTo": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Message-ID header of the message being replied to"
|
|
27
|
+
},
|
|
28
|
+
"references": { "type": "string", "description": "References header of the thread" }
|
|
29
|
+
},
|
|
30
|
+
"required": ["to", "subject"]
|
|
31
|
+
},
|
|
32
|
+
"request": {
|
|
33
|
+
"method": "POST",
|
|
34
|
+
"url": "https://gmail.googleapis.com/gmail/v1/users/me/messages/send",
|
|
35
|
+
"builder": "gmail-send"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"tool": "gmail_draft",
|
|
40
|
+
"description": "Create a Gmail draft without sending it. Pass the message as plain fields — never build the RFC 2822 message or base64 yourself.",
|
|
41
|
+
"parameters": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"to": {
|
|
45
|
+
"type": "array",
|
|
46
|
+
"items": { "type": "string" },
|
|
47
|
+
"description": "Recipient email addresses"
|
|
48
|
+
},
|
|
49
|
+
"subject": { "type": "string", "description": "Subject line" },
|
|
50
|
+
"text": { "type": "string", "description": "Plain-text body" },
|
|
51
|
+
"html": { "type": "string", "description": "HTML body, used when text is absent" },
|
|
52
|
+
"cc": { "type": "array", "items": { "type": "string" } },
|
|
53
|
+
"bcc": { "type": "array", "items": { "type": "string" } },
|
|
54
|
+
"replyTo": { "type": "string" },
|
|
55
|
+
"threadId": { "type": "string", "description": "Thread the draft replies in" },
|
|
56
|
+
"inReplyTo": {
|
|
57
|
+
"type": "string",
|
|
58
|
+
"description": "Message-ID header of the message being replied to"
|
|
59
|
+
},
|
|
60
|
+
"references": { "type": "string", "description": "References header of the thread" }
|
|
61
|
+
},
|
|
62
|
+
"required": ["to", "subject"]
|
|
63
|
+
},
|
|
64
|
+
"request": {
|
|
65
|
+
"method": "POST",
|
|
66
|
+
"url": "https://gmail.googleapis.com/gmail/v1/users/me/drafts",
|
|
67
|
+
"builder": "gmail-draft"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: google-calendar
|
|
3
|
+
description: List, create, update, and delete Google Calendar events via the Google Calendar REST API.
|
|
4
|
+
aliases: [calendar, meeting+create, meeting+schedule, meeting+book, meeting+move, meeting+cancel, event+create]
|
|
5
|
+
tools: [http_request, calendar_create_meet_event, calendar_add_meet]
|
|
6
|
+
platform: [darwin, linux, win32]
|
|
7
|
+
credentials: [google_calendar_access_token]
|
|
8
|
+
allow_list: [https://www.googleapis.com/calendar/v3/]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Google Calendar
|
|
12
|
+
|
|
13
|
+
Use `calendar_create_meet_event` and `calendar_add_meet` for Google Meet links, and `http_request` for everything else (list, plain create/update/delete, free/busy). The Google Calendar credential is attached automatically to every `www.googleapis.com/calendar/v3/` request — **never include an `auth` block**.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Google Calendar must be connected. Each Google skill is connected separately, with its
|
|
18
|
+
own app and its own approval — connecting one grants nothing to the others. If
|
|
19
|
+
credentials are missing, tell the user to connect Google Calendar from Settings, or to
|
|
20
|
+
set the `google_calendar_access_token` credential.
|
|
21
|
+
|
|
22
|
+
## Base URL
|
|
23
|
+
|
|
24
|
+
`https://www.googleapis.com/calendar/v3` — default `calendarId` is `primary` unless the user names another calendar.
|
|
25
|
+
|
|
26
|
+
## Temporal Accuracy (Critical)
|
|
27
|
+
|
|
28
|
+
- Resolve relative dates ("today", "tomorrow", "next week", "in 2 hours") to absolute ISO 8601 timestamps **with timezone offset** before calling the API.
|
|
29
|
+
- Never infer "now" from memory when building `timeMin`, `timeMax`, or event start/end values.
|
|
30
|
+
- If the date or time is ambiguous, ask the user instead of guessing.
|
|
31
|
+
|
|
32
|
+
Example: annotation `[Current local time: 2026-08-12 14:00:00 (UTC-03:00)]`, user asks "in 30 minutes for 1 hour" -> `start.dateTime` = `2026-08-12T14:30:00-03:00`, `end.dateTime` = `2026-08-12T15:30:00-03:00`.
|
|
33
|
+
|
|
34
|
+
## Common Operations
|
|
35
|
+
|
|
36
|
+
### List upcoming events
|
|
37
|
+
|
|
38
|
+
Always use `singleEvents=true` and `orderBy=startTime` so recurring events expand and sort correctly.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
43
|
+
"method": "GET",
|
|
44
|
+
"query": {
|
|
45
|
+
"timeMin": "<resolved ISO 8601 with offset>",
|
|
46
|
+
"maxResults": 10,
|
|
47
|
+
"singleEvents": true,
|
|
48
|
+
"orderBy": "startTime"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Create an event
|
|
54
|
+
|
|
55
|
+
Ask for missing required fields (summary, start, end) before creating.
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/primary/events",
|
|
60
|
+
"method": "POST",
|
|
61
|
+
"body": {
|
|
62
|
+
"summary": "Design review",
|
|
63
|
+
"start": { "dateTime": "2026-06-10T14:00:00-03:00" },
|
|
64
|
+
"end": { "dateTime": "2026-06-10T15:00:00-03:00" },
|
|
65
|
+
"attendees": [{ "email": "colleague@example.com" }]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Create an event with a Google Meet link
|
|
71
|
+
|
|
72
|
+
Use `calendar_create_meet_event` with `summary`, `start`, `end` (ISO 8601 with offset), and optionally `timeZone`, `description`, `location`, `attendees`, `calendarId`.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"summary": "Sync call",
|
|
77
|
+
"start": "2026-06-10T14:00:00-03:00",
|
|
78
|
+
"end": "2026-06-10T14:30:00-03:00"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To add a Meet link to an event that already exists, use `calendar_add_meet` with `eventId` (and `calendarId` if not `primary`).
|
|
83
|
+
|
|
84
|
+
### Update an event
|
|
85
|
+
|
|
86
|
+
`PATCH` with only the fields to change.
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/primary/events/{eventId}",
|
|
91
|
+
"method": "PATCH",
|
|
92
|
+
"body": { "summary": "Updated title" }
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Delete an event
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/primary/events/{eventId}",
|
|
101
|
+
"method": "DELETE"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Free/busy query
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"url": "https://www.googleapis.com/calendar/v3/freeBusy",
|
|
110
|
+
"method": "POST",
|
|
111
|
+
"body": {
|
|
112
|
+
"timeMin": "2026-06-10T00:00:00Z",
|
|
113
|
+
"timeMax": "2026-06-11T00:00:00Z",
|
|
114
|
+
"items": [{ "id": "primary" }]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### List calendars
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"url": "https://www.googleapis.com/calendar/v3/users/me/calendarList",
|
|
124
|
+
"method": "GET"
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Output Policy
|
|
129
|
+
|
|
130
|
+
- Present events with title, date/time (with timezone), location, and attendees when available.
|
|
131
|
+
- For create/update, report the event `id`, start/end time, and `htmlLink` rendered as a Markdown link — e.g. `[event title](htmlLink)`. Never present the URL bare or wrapped in backticks, or it won't be clickable.
|
|
132
|
+
- Confirm before deleting events; show the event title and time so the user can verify.
|
|
133
|
+
|
|
134
|
+
## Common Mistakes
|
|
135
|
+
|
|
136
|
+
- Sending natural-language dates instead of absolute ISO 8601 with timezone offset.
|
|
137
|
+
- Listing without `singleEvents=true` — recurring events come back collapsed and unsorted.
|
|
138
|
+
- Calling get/patch/delete without a real `eventId` — list/search first.
|
|
139
|
+
- Including an `auth` block by hand — credentials attach automatically; a mistyped key breaks the request.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"operations": [
|
|
3
|
+
{
|
|
4
|
+
"tool": "calendar_create_meet_event",
|
|
5
|
+
"description": "Create a Google Calendar event that has a Google Meet link. Use this whenever the user asks for a meeting with a video call; a plain event without a call stays on http_request.",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"summary": { "type": "string", "description": "Event title" },
|
|
10
|
+
"start": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Start time, ISO 8601 with a UTC offset, e.g. 2026-03-04T15:00:00-03:00"
|
|
13
|
+
},
|
|
14
|
+
"end": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "End time, ISO 8601 with a UTC offset"
|
|
17
|
+
},
|
|
18
|
+
"timeZone": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "IANA time zone, e.g. America/Sao_Paulo"
|
|
21
|
+
},
|
|
22
|
+
"description": { "type": "string" },
|
|
23
|
+
"location": { "type": "string" },
|
|
24
|
+
"attendees": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": { "type": "string" },
|
|
27
|
+
"description": "Attendee email addresses"
|
|
28
|
+
},
|
|
29
|
+
"calendarId": { "type": "string", "description": "Defaults to primary" }
|
|
30
|
+
},
|
|
31
|
+
"required": ["summary", "start", "end"]
|
|
32
|
+
},
|
|
33
|
+
"request": {
|
|
34
|
+
"method": "POST",
|
|
35
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events",
|
|
36
|
+
"urlDefaults": { "calendarId": "primary" },
|
|
37
|
+
"builder": "calendar-meet-event"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"tool": "calendar_add_meet",
|
|
42
|
+
"description": "Add a Google Meet link to an existing Google Calendar event.",
|
|
43
|
+
"parameters": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"properties": {
|
|
46
|
+
"eventId": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "Event id, from a previous events.list or events.insert"
|
|
49
|
+
},
|
|
50
|
+
"calendarId": { "type": "string", "description": "Defaults to primary" }
|
|
51
|
+
},
|
|
52
|
+
"required": ["eventId"]
|
|
53
|
+
},
|
|
54
|
+
"request": {
|
|
55
|
+
"method": "PATCH",
|
|
56
|
+
"url": "https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events/{eventId}",
|
|
57
|
+
"urlDefaults": { "calendarId": "primary" },
|
|
58
|
+
"builder": "calendar-add-meet"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: google-docs
|
|
3
|
+
description: Create, read, and edit Google Docs documents via the Google Docs REST API.
|
|
4
|
+
tools: [http_request, docs_create, docs_append_text]
|
|
5
|
+
platform: [darwin, linux, win32]
|
|
6
|
+
credentials: [google_docs_access_token]
|
|
7
|
+
allow_list: [https://docs.googleapis.com/v1/documents, https://www.googleapis.com/drive/v3/files]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Google Docs
|
|
11
|
+
|
|
12
|
+
Use `docs_create` to create a document and `docs_append_text` to add text or
|
|
13
|
+
pages to it; use `http_request` for everything else (get, replace, insert at a
|
|
14
|
+
position, delete ranges, Drive search, trash). For each `http_request`, set
|
|
15
|
+
`auth.tokenCredentialKey` to `google_docs_access_token`.
|
|
16
|
+
|
|
17
|
+
Never use `exec`, Python, curl, shell flags such as `-H`/`-d`, or a JSON string
|
|
18
|
+
to make a Google Docs request. Call one tool per operation with one complete
|
|
19
|
+
structured object. In particular, `body` must be an object, not a serialized
|
|
20
|
+
JSON string; the tool JSON-encodes it and sets `Content-Type: application/json`
|
|
21
|
+
automatically.
|
|
22
|
+
|
|
23
|
+
## Load the Recipe File First
|
|
24
|
+
|
|
25
|
+
This file carries no requests. The working request shapes live in three
|
|
26
|
+
reference files — load the one for the job with the `skill` tool BEFORE calling
|
|
27
|
+
`http_request`, then copy its request and change only the values:
|
|
28
|
+
|
|
29
|
+
Each load is a real `skill` tool call — printing the call as JSON or text in
|
|
30
|
+
your reply loads nothing.
|
|
31
|
+
|
|
32
|
+
- **Reading or finding documents** — "what does document X say", "summarize
|
|
33
|
+
my doc", "find / list my documents": call the `skill` tool with
|
|
34
|
+
`name: "google-docs"` and `file: "references/read.md"`.
|
|
35
|
+
- **Creating a new document** (no existing document involved; one page or
|
|
36
|
+
many): call the `skill` tool with `name: "google-docs"` and
|
|
37
|
+
`file: "references/create.md"` — it covers `docs_create` and filling the
|
|
38
|
+
document with `docs_append_text`.
|
|
39
|
+
- **Changing an existing document** — append or insert text, find and
|
|
40
|
+
replace, delete a passage, move it to the trash: call the `skill` tool with
|
|
41
|
+
`name: "google-docs"` and `file: "references/edit.md"`.
|
|
42
|
+
|
|
43
|
+
Never write a request from memory. The recipes carry the exact request shapes
|
|
44
|
+
(`batchUpdate` request names, index rules, page limits) that fail in
|
|
45
|
+
non-obvious ways when improvised; loading the file is one cheap read-only call.
|
|
46
|
+
|
|
47
|
+
## Prerequisites
|
|
48
|
+
|
|
49
|
+
Google Docs must be connected. Each Google skill is connected separately, with its
|
|
50
|
+
own app and its own approval — connecting one grants nothing to the others. If
|
|
51
|
+
credentials are missing, tell the user to connect Google Docs from Settings, or to
|
|
52
|
+
set the `google_docs_access_token` credential.
|
|
53
|
+
|
|
54
|
+
If Google returns `403 PERMISSION_DENIED` with reason `SERVICE_DISABLED`, the
|
|
55
|
+
credential is working but the OAuth client's Google Cloud project has not
|
|
56
|
+
enabled the Google Docs API. Do not ask the user to reconnect. Tell the project
|
|
57
|
+
owner to open the response's `activationUrl`, enable the API, and retry after
|
|
58
|
+
propagation.
|
|
59
|
+
|
|
60
|
+
## Identifiers
|
|
61
|
+
|
|
62
|
+
Documents are identified by `documentId` — the alphanumeric string in the URL
|
|
63
|
+
`docs.google.com/document/d/{documentId}/...`, and the `documentId` field of a
|
|
64
|
+
create response. Listing and searching documents go through the Google Drive
|
|
65
|
+
API (`references/read.md`), never the Docs API.
|
|
66
|
+
|
|
67
|
+
## Output Policy
|
|
68
|
+
|
|
69
|
+
- For document reads, extract and present the text content clearly — do not
|
|
70
|
+
echo the raw JSON structure.
|
|
71
|
+
- For edits, confirm the change with the user first (what text is being
|
|
72
|
+
inserted, replaced, or deleted) unless they already spelled it out.
|
|
73
|
+
- Report success only when the `batchUpdate` response contains `replies` with
|
|
74
|
+
no errors, and name the document (title or link) in the answer.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"operations": [
|
|
3
|
+
{
|
|
4
|
+
"tool": "docs_create",
|
|
5
|
+
"description": "Create an empty Google Doc with a title. Call it exactly once per requested document, then append content with docs_append_text using the returned documentId.",
|
|
6
|
+
"parameters": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"title": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Document title"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"required": [
|
|
15
|
+
"title"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"request": {
|
|
19
|
+
"method": "POST",
|
|
20
|
+
"url": "https://docs.googleapis.com/v1/documents",
|
|
21
|
+
"builder": "docs-create"
|
|
22
|
+
},
|
|
23
|
+
"response": {
|
|
24
|
+
"pick": [
|
|
25
|
+
"documentId",
|
|
26
|
+
"title"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"tool": "docs_append_text",
|
|
32
|
+
"description": "Append text to the end of a Google Doc, optionally followed by a page break. One page (80 words or fewer) per call; set pageBreak on every page except the last. Never compute indexes yourself.",
|
|
33
|
+
"parameters": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"properties": {
|
|
36
|
+
"documentId": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Document id, from docs_create or the docs.google.com/document/d/{id} URL"
|
|
39
|
+
},
|
|
40
|
+
"text": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Text to append; end it with a newline"
|
|
43
|
+
},
|
|
44
|
+
"pageBreak": {
|
|
45
|
+
"type": "boolean",
|
|
46
|
+
"description": "Insert a page break after the text"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"required": [
|
|
50
|
+
"documentId",
|
|
51
|
+
"text"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"request": {
|
|
55
|
+
"method": "POST",
|
|
56
|
+
"url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
|
|
57
|
+
"builder": "docs-append-text"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Creating a Google Doc
|
|
2
|
+
|
|
3
|
+
Two typed tools do the whole job: `docs_create` makes the document,
|
|
4
|
+
`docs_append_text` fills it. Typed tools select their own credential. For each fallback `http_request`,
|
|
5
|
+
set `auth.tokenCredentialKey` to `google_docs_access_token`.
|
|
6
|
+
|
|
7
|
+
## Create the document
|
|
8
|
+
|
|
9
|
+
Call `docs_create` with the title:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{ "title": "My Document" }
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The result contains the `documentId`. Capture it and keep using it.
|
|
16
|
+
Create the document exactly once. Do not follow a successful create with a
|
|
17
|
+
Drive search, a GET, or another create just to rediscover the ID. If the result has no
|
|
18
|
+
`documentId`, stop and report that response problem; never append without the
|
|
19
|
+
ID.
|
|
20
|
+
|
|
21
|
+
## Add the content
|
|
22
|
+
|
|
23
|
+
Call `docs_append_text` once per page. Put the document title as the first
|
|
24
|
+
line of the first page instead of spending a call on a heading, end the text
|
|
25
|
+
with a newline, and keep each call at 80 words or fewer. The 80-word limit
|
|
26
|
+
applies even when the user asks for only one page. Never expand a one-page
|
|
27
|
+
request into a long list in one call.
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"documentId": "<id from docs_create>",
|
|
32
|
+
"text": "My Document\n\nConcise content.\n",
|
|
33
|
+
"pageBreak": false
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Multi-page documents
|
|
38
|
+
|
|
39
|
+
One requested page per `docs_append_text` call, in order, each 80 words or
|
|
40
|
+
fewer, with `"pageBreak": true` on every page except the last — five requested
|
|
41
|
+
pages therefore take five append calls. Wait for a successful result before
|
|
42
|
+
appending the next page. Do not place several pages of text in one call: if
|
|
43
|
+
the tool reports the arguments are not valid JSON, the call was too large or
|
|
44
|
+
incomplete, so retry only that page with shorter text.
|
|
45
|
+
|
|
46
|
+
## Finishing
|
|
47
|
+
|
|
48
|
+
Report success only when every append result came back without an error.
|
|
49
|
+
Answer with the document title and the link
|
|
50
|
+
`https://docs.google.com/document/d/{documentId}/edit`; do not read the
|
|
51
|
+
document back to "confirm".
|
|
52
|
+
|
|
53
|
+
## Without the typed tools
|
|
54
|
+
|
|
55
|
+
The typed tools wrap these two Docs API requests; use them only if the typed
|
|
56
|
+
tools are missing from this chat:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"url": "https://docs.googleapis.com/v1/documents",
|
|
61
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
62
|
+
"method": "POST",
|
|
63
|
+
"body": { "title": "My Document" }
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
|
|
70
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
71
|
+
"method": "POST",
|
|
72
|
+
"body": {
|
|
73
|
+
"requests": [
|
|
74
|
+
{
|
|
75
|
+
"insertText": {
|
|
76
|
+
"endOfSegmentLocation": {},
|
|
77
|
+
"text": "Page heading\n\nConcise page content.\n"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{ "insertPageBreak": { "endOfSegmentLocation": {} } }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then it is one requested page per `batchUpdate` call, the same 80-word limit,
|
|
87
|
+
and the `insertPageBreak` request omitted on the last page;
|
|
88
|
+
never call `/v1/documents:batchUpdate` without the ID.
|
|
89
|
+
|
|
90
|
+
## Common Mistakes
|
|
91
|
+
|
|
92
|
+
- Recreating or searching for a document after a successful create instead of
|
|
93
|
+
using the returned `documentId` — this produces duplicates and wastes rounds.
|
|
94
|
+
- Sending a whole multi-page document in one call — one page of at most 80
|
|
95
|
+
words per call, `pageBreak` on every page except the last.
|
|
96
|
+
- Computing indexes yourself — `docs_append_text` and `endOfSegmentLocation`
|
|
97
|
+
never need one.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Editing an Existing Google Doc
|
|
2
|
+
|
|
3
|
+
Every request is one `http_request` call with a structured object. For each request, set `auth.tokenCredentialKey` to `google_docs_access_token`. All content edits go through
|
|
4
|
+
`batchUpdate` — there is no PATCH endpoint for document body changes.
|
|
5
|
+
|
|
6
|
+
Get the `documentId` from the URL the user gave, from an earlier create
|
|
7
|
+
response, or from a Drive search (`references/read.md`).
|
|
8
|
+
|
|
9
|
+
Every `http_request` edit is ONE `POST …:batchUpdate` whose body is `{ "requests": [ … ] }` —
|
|
10
|
+
a bare request object without the `requests` array is rejected with 400. Copy
|
|
11
|
+
the request shapes below exactly: the field names are fixed by Google, and any
|
|
12
|
+
other name (`searchText`, `replacementText`, `find`, `replace`, `newText`) fails
|
|
13
|
+
with `Unknown name`. One edit per user request — an edit never needs a
|
|
14
|
+
preceding insert of text that is already in the document.
|
|
15
|
+
|
|
16
|
+
## Append text
|
|
17
|
+
|
|
18
|
+
Call `docs_append_text` — it appends at the end of the document with no index
|
|
19
|
+
arithmetic and no preliminary GET. End the text with a newline; keep it at 80
|
|
20
|
+
words or fewer per call.
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"documentId": "<documentId>",
|
|
25
|
+
"text": "\nNew paragraph.\n",
|
|
26
|
+
"pageBreak": false
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The raw equivalent, for when the typed tool is missing from this chat, is a
|
|
31
|
+
`batchUpdate` with `"insertText": { "endOfSegmentLocation": {}, "text": "…" }`.
|
|
32
|
+
|
|
33
|
+
## Insert text at a position
|
|
34
|
+
|
|
35
|
+
Use an explicit `location.index` only when editing at a known position. A new
|
|
36
|
+
blank document's first valid insertion point is index 1; index 2 is outside its
|
|
37
|
+
empty paragraph. Indexes count UTF-16 code units and change with every edit, so
|
|
38
|
+
`GET` the document first when you need one.
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
|
|
43
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
44
|
+
"method": "POST",
|
|
45
|
+
"body": {
|
|
46
|
+
"requests": [
|
|
47
|
+
{
|
|
48
|
+
"insertText": {
|
|
49
|
+
"location": { "index": 1 },
|
|
50
|
+
"text": "Hello, World!"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Replace all text matching a pattern
|
|
59
|
+
|
|
60
|
+
Use `replaceAllText` to find and replace — exactly these keys:
|
|
61
|
+
`containsText` (with `text` and optional `matchCase`) and `replaceText`.
|
|
62
|
+
`containsText.text` is a regex — escape special characters (`.`, `*`, `+`,
|
|
63
|
+
`?`, `[`, `]`, `(`, `)`, `{`, `}`, `^`, `$`, `|`, `\`). No `GET` is needed
|
|
64
|
+
first, and no `insertText` belongs in the same request.
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
|
|
69
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
70
|
+
"method": "POST",
|
|
71
|
+
"body": {
|
|
72
|
+
"requests": [
|
|
73
|
+
{
|
|
74
|
+
"replaceAllText": {
|
|
75
|
+
"containsText": { "text": "old text", "matchCase": true },
|
|
76
|
+
"replaceText": "new text"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The reply's `occurrencesChanged` says how many matches were replaced; `0` means
|
|
85
|
+
the text was not found — tell the user instead of retrying with guesses.
|
|
86
|
+
|
|
87
|
+
## Delete a range of text
|
|
88
|
+
|
|
89
|
+
Fetch the document first, then specify the start and exclusive end index.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
|
|
94
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
95
|
+
"method": "POST",
|
|
96
|
+
"body": {
|
|
97
|
+
"requests": [
|
|
98
|
+
{
|
|
99
|
+
"deleteContentRange": {
|
|
100
|
+
"range": { "startIndex": 10, "endIndex": 20 }
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Move a document to the trash
|
|
109
|
+
|
|
110
|
+
Trashing goes through the Drive API; the user can restore it from Drive's
|
|
111
|
+
trash. Only do this when the user explicitly asks to delete or remove the
|
|
112
|
+
document.
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"url": "https://www.googleapis.com/drive/v3/files/{documentId}",
|
|
117
|
+
"auth": { "tokenCredentialKey": "google_docs_access_token" },
|
|
118
|
+
"method": "PATCH",
|
|
119
|
+
"body": { "trashed": true }
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Finishing
|
|
124
|
+
|
|
125
|
+
Report success only when the `batchUpdate` response contains `replies` with no
|
|
126
|
+
errors. Do not read the document back to confirm an edit.
|
|
127
|
+
|
|
128
|
+
## Common Mistakes
|
|
129
|
+
|
|
130
|
+
- Using PATCH on the document body instead of `batchUpdate` — PATCH only
|
|
131
|
+
updates metadata like title, not content.
|
|
132
|
+
- Treating indexes like array offsets — they count UTF-16 code units, range
|
|
133
|
+
ends are exclusive, and a blank document's first usable body index is 1.
|
|
134
|
+
- Using `insertionIndex` or placing `location.index` directly under
|
|
135
|
+
`insertText` — the supported shape is `insertText.location.index`; for
|
|
136
|
+
appends, prefer `insertText.endOfSegmentLocation`.
|
|
137
|
+
- Attempting a numeric-position edit without fetching the document first — you
|
|
138
|
+
won't know the current indexes.
|
|
139
|
+
- Not escaping regex special characters in `containsText` patterns.
|
|
140
|
+
- Renaming the fields — `searchText`, `replacementText`, `replacement`, `find`
|
|
141
|
+
all return 400 `Unknown name`; only `containsText` + `replaceText` exist.
|
|
142
|
+
- Sending a request object without the `{ "requests": [ … ] }` wrapper.
|
|
143
|
+
- Inserting text that is already in the document before an edit — a replace or
|
|
144
|
+
delete works on the existing content directly.
|
|
145
|
+
- Passing curl/Python text or serialized JSON to `http_request` instead of one
|
|
146
|
+
structured tool-call object.
|