@joe-broadhead/opencode-gws 0.0.0-stage → 0.0.0
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/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/NOTICE +31 -0
- package/README.md +118 -2
- package/dist/index.js +11388 -0
- package/dist/tui.js +589 -0
- package/manifest/generated.json +1 -0
- package/package.json +73 -4
- package/skills/opencode-gws/SKILL.md +104 -0
- package/skills/opencode-gws-admin/SKILL.md +97 -0
- package/skills/opencode-gws-recipes/SKILL.md +241 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opencode-gws-admin
|
|
3
|
+
description: Load only when the user asks for admin reports, Apps Script, Workspace Events, Model Armor, or a workflow helper.
|
|
4
|
+
opencode/autoinvoke: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# High-risk Workspace services
|
|
8
|
+
|
|
9
|
+
This skill is not loaded automatically. Use it only when the user asked for admin reports, Apps Script, Workspace Events, Model Armor, or a workflow helper.
|
|
10
|
+
|
|
11
|
+
Search with `gws_catalog` and check `gws_schema` before you call. If `executable` is false, do not call that id. Deploy and watch never run. A helper with no adapter cannot run; use `alternative` when the catalog names one.
|
|
12
|
+
|
|
13
|
+
## Admin gate
|
|
14
|
+
|
|
15
|
+
An operation whose category is `admin` needs all of these before `gws_plan` will accept it:
|
|
16
|
+
|
|
17
|
+
1. `admin.enabled` is true.
|
|
18
|
+
2. The service is in `admin.allowedServices` (the default list is the services that have an admin-class entry).
|
|
19
|
+
3. The plan includes a non-empty `reason` when `admin.requireReason` is true, which is the default.
|
|
20
|
+
|
|
21
|
+
Then commit with `gws_admin` and only `{ "planId": "<planId>" }`. `gws_admin` asks every time. It does not offer Always. A user deny hides the tool.
|
|
22
|
+
|
|
23
|
+
A read on one of these services is still a read: `gws_read`, no admin gate. A write that is not category `admin` still uses `gws_write` and the normal ask.
|
|
24
|
+
|
|
25
|
+
Plugin policy cannot allow an admin call. A policy rule can only deny.
|
|
26
|
+
|
|
27
|
+
## Admin reports
|
|
28
|
+
|
|
29
|
+
Read-only at both access levels. The sign-in still needs the admin report scopes from the auth doc.
|
|
30
|
+
|
|
31
|
+
Activity list, read. `fields` is required because this is a list:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"operation": "admin-reports.activities.list",
|
|
36
|
+
"params": { "userKey": "all", "applicationName": "login" },
|
|
37
|
+
"fields": "items(id,actor,events),nextPageToken"
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Watching an activity feed is category `admin`, not a read. Plan it only when the user asked, with a reason, then commit with `gws_admin`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"operation": "admin-reports.activities.watch",
|
|
46
|
+
"params": { "userKey": "all", "applicationName": "login" },
|
|
47
|
+
"reason": "The user asked to watch login activity."
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`gws_schema` shows the watch body. Do not invent a channel.
|
|
52
|
+
|
|
53
|
+
## Apps Script
|
|
54
|
+
|
|
55
|
+
Read a project:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"operation": "script.projects.get",
|
|
60
|
+
"params": { "scriptId": "SCRIPT_ID" }
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Creating a project is a write. Plan, then `gws_write`. Deployments and running a script never run. If catalog marks an id not executable, stop and tell the user.
|
|
65
|
+
|
|
66
|
+
## Workspace Events
|
|
67
|
+
|
|
68
|
+
Most subscription methods never run. A status read can:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"operation": "events.operations.get",
|
|
73
|
+
"params": { "name": "operations/OPERATION_ID" }
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Model Armor
|
|
78
|
+
|
|
79
|
+
No access level requests Model Armor scopes. The account needs `https://www.googleapis.com/auth/cloud-platform` in `scopes`, and the user must sign in again so the grant is on the token. The Model Armor helpers cannot run. Do not invent a call. Tell the user, and use `gws_catalog` if they still want a Discovery method.
|
|
80
|
+
|
|
81
|
+
## Workflow
|
|
82
|
+
|
|
83
|
+
These three helpers are reads. They need the account to enable `workflow`, which uses the Gmail, Calendar, Tasks, and Drive scopes.
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{ "operation": "workflow.meeting-prep", "input": {} }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{ "operation": "workflow.standup-report", "input": {} }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{ "operation": "workflow.weekly-digest", "input": {} }
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Other workflow helpers cannot run. Use the alternative `gws_catalog` names, and commit with that method's category tool.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opencode-gws-recipes
|
|
3
|
+
description: Use when building a Gmail, Drive, Calendar, Docs, or Sheets request for gws_read or gws_plan.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Recipes
|
|
7
|
+
|
|
8
|
+
These are exact requests for the everyday Gmail, Drive, Calendar, Docs, and Sheets tasks. Copy the shape. Replace the placeholder ids and text. Confirm the parameters with `gws_schema` when the task is not one of these.
|
|
9
|
+
|
|
10
|
+
Pass `account` only when `gws_status` shows more than one account. `fields` is required on list and search. A change is `gws_plan`, then the commit tool of the **returned** category, with only `{ "planId": "<planId>" }`. Show the preview first.
|
|
11
|
+
|
|
12
|
+
If `gws_catalog` says `executable` is false, do not call that id. Use `alternative`.
|
|
13
|
+
|
|
14
|
+
## Gmail
|
|
15
|
+
|
|
16
|
+
Unread inbox, read:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"operation": "gmail.users.messages.list",
|
|
21
|
+
"params": { "userId": "me", "q": "is:unread", "maxResults": 10 },
|
|
22
|
+
"fields": "messages(id,threadId),nextPageToken"
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
One message, read. Prefer the helper when you want the text, not the raw payload:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"operation": "gmail.read",
|
|
31
|
+
"input": { "id": "MESSAGE_ID", "format": "text" }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Triage, read:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"operation": "gmail.triage",
|
|
40
|
+
"input": { "max": 10, "query": "is:unread" }
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Send. Plan, show the preview, then `gws_send`. Send does not offer Always.
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"operation": "gmail.send",
|
|
49
|
+
"input": {
|
|
50
|
+
"to": "person@example.com",
|
|
51
|
+
"subject": "Hello",
|
|
52
|
+
"body": "Hello"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Reply. Same commit tool, `gws_send`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"operation": "gmail.reply",
|
|
62
|
+
"input": { "messageId": "MESSAGE_ID", "body": "Thanks" }
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Drive
|
|
67
|
+
|
|
68
|
+
Recent files, read:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"operation": "drive.files.list",
|
|
73
|
+
"params": { "q": "trashed = false", "pageSize": 20, "orderBy": "modifiedTime desc" },
|
|
74
|
+
"fields": "files(id,name,mimeType,modifiedTime),nextPageToken"
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
One file's metadata, read:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"operation": "drive.files.get",
|
|
83
|
+
"params": { "fileId": "FILE_ID" },
|
|
84
|
+
"fields": "id,name,mimeType,modifiedTime"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Create a file, write. Plan, then `gws_write`. An upload path must be absolute and inside an allowed read root. `gws_schema` shows the upload field.
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"operation": "drive.files.create",
|
|
93
|
+
"body": { "name": "Notes.txt", "mimeType": "text/plain" }
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Move to trash. The plan category is **delete**, even if the manifest says write. Commit with `gws_delete`, not `gws_write`.
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"operation": "drive.files.update",
|
|
102
|
+
"params": { "fileId": "FILE_ID" },
|
|
103
|
+
"body": { "trashed": true }
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Share with one person. Plan category is share. Commit with `gws_share`. Share does not offer Always.
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"operation": "drive.permissions.create",
|
|
112
|
+
"params": { "fileId": "FILE_ID" },
|
|
113
|
+
"body": { "type": "user", "role": "reader", "emailAddress": "person@example.com" }
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Calendar
|
|
118
|
+
|
|
119
|
+
Today's agenda, read:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"operation": "calendar.agenda",
|
|
124
|
+
"input": { "today": true }
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Events on the primary calendar, read:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"operation": "calendar.events.list",
|
|
133
|
+
"params": { "calendarId": "primary", "maxResults": 10, "singleEvents": true, "orderBy": "startTime" },
|
|
134
|
+
"fields": "items(id,summary,start,end),nextPageToken"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Create an event that does not email anyone. Plan category is write. Commit with `gws_write`.
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"operation": "calendar.events.insert",
|
|
143
|
+
"params": { "calendarId": "primary" },
|
|
144
|
+
"body": {
|
|
145
|
+
"summary": "Standup",
|
|
146
|
+
"start": { "dateTime": "2026-11-02T09:00:00+01:00" },
|
|
147
|
+
"end": { "dateTime": "2026-11-02T09:15:00+01:00" }
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Create or move an event that emails attendees (`sendUpdates` of `all` or `externalOnly`). The plan category is **send**. Commit with `gws_send`.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"operation": "calendar.events.insert",
|
|
157
|
+
"params": { "calendarId": "primary", "sendUpdates": "all" },
|
|
158
|
+
"body": {
|
|
159
|
+
"summary": "Standup",
|
|
160
|
+
"start": { "dateTime": "2026-11-02T09:00:00+01:00" },
|
|
161
|
+
"end": { "dateTime": "2026-11-02T09:15:00+01:00" }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Docs
|
|
167
|
+
|
|
168
|
+
Read a document:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"operation": "docs.documents.get",
|
|
173
|
+
"params": { "documentId": "DOCUMENT_ID" }
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Create a document, write. Plan, then `gws_write`.
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"operation": "docs.documents.create",
|
|
182
|
+
"body": { "title": "Notes" }
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Insert text, write. Plan, then `gws_write`.
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"operation": "docs.documents.batchUpdate",
|
|
191
|
+
"params": { "documentId": "DOCUMENT_ID" },
|
|
192
|
+
"body": {
|
|
193
|
+
"requests": [
|
|
194
|
+
{ "insertText": { "location": { "index": 1 }, "text": "Hello" } }
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Sheets
|
|
201
|
+
|
|
202
|
+
Read a range. The helper is enough for a rectangular range:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"operation": "sheets.read",
|
|
207
|
+
"input": { "spreadsheet": "SPREADSHEET_ID", "range": "Sheet1!A1:D20" }
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The method, when you need the raw values resource:
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{
|
|
215
|
+
"operation": "sheets.spreadsheets.values.get",
|
|
216
|
+
"params": { "spreadsheetId": "SPREADSHEET_ID", "range": "Sheet1!A1:D20" }
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Append rows, write. Plan, then `gws_write`.
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"operation": "sheets.spreadsheets.values.append",
|
|
225
|
+
"params": {
|
|
226
|
+
"spreadsheetId": "SPREADSHEET_ID",
|
|
227
|
+
"range": "Sheet1!A1",
|
|
228
|
+
"valueInputOption": "USER_ENTERED"
|
|
229
|
+
},
|
|
230
|
+
"body": { "values": [["a", "b"]] }
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Create a spreadsheet, write. Plan, then `gws_write`.
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"operation": "sheets.spreadsheets.create",
|
|
239
|
+
"body": { "properties": { "title": "Notes" } }
|
|
240
|
+
}
|
|
241
|
+
```
|