@joe-broadhead/opencode-gws 0.0.2 → 0.0.4
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 +39 -0
- package/README.md +24 -6
- package/assets/icon.svg +1 -0
- package/dist/index.js +975 -352
- package/dist/tui.js +10 -9
- package/package.json +15 -7
- package/skills/opencode-gws/SKILL.md +3 -1
- package/skills/opencode-gws-recipes/SKILL.md +3 -1
- package/views/jelly-view.d.ts +0 -73
package/dist/tui.js
CHANGED
|
@@ -19,6 +19,7 @@ var object = (properties, required) => ({ type: "object", properties, required }
|
|
|
19
19
|
var MODES = ["interactive", "credentials_file", "access_token"];
|
|
20
20
|
var ACCESS = ["read", "write"];
|
|
21
21
|
var CLIENT_SOURCES = ["account", "plugin", "pasted"];
|
|
22
|
+
var STATES = ["connected", "sign_in_required", "not_configured", "host_untested"];
|
|
22
23
|
var account = object(
|
|
23
24
|
{
|
|
24
25
|
alias: text,
|
|
@@ -38,9 +39,9 @@ var account = object(
|
|
|
38
39
|
);
|
|
39
40
|
var status = object(
|
|
40
41
|
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
version: text,
|
|
43
|
+
host: object({ version: { type: ["string", "null"] }, range: text, tested: { type: "boolean" } }, ["version", "range", "tested"]),
|
|
44
|
+
state: { enum: STATES },
|
|
44
45
|
gws: object({ path: text, version: text }, ["path", "version"]),
|
|
45
46
|
services: texts,
|
|
46
47
|
accounts: { type: "array", items: account },
|
|
@@ -49,7 +50,7 @@ var status = object(
|
|
|
49
50
|
permissionsBlock: text,
|
|
50
51
|
nextStep: text
|
|
51
52
|
},
|
|
52
|
-
["
|
|
53
|
+
["version", "host", "state", "gws", "services", "accounts", "unguardedAgents", "nextStep"]
|
|
53
54
|
);
|
|
54
55
|
var Gws = Rpc.define({
|
|
55
56
|
id: RPC_ID,
|
|
@@ -69,15 +70,15 @@ function isAccount(value) {
|
|
|
69
70
|
return isRecord(value) && isText(value["alias"]) && MODES.includes(value["mode"]) && isStrings(value["services"]) && typeof value["connected"] === "boolean" && optional(value["integrationID"], isText) && optional(value["needsAuth"], (entry) => entry === true) && optional(value["access"], (entry) => ACCESS.includes(entry)) && optional(value["clientSource"], (entry) => CLIENT_SOURCES.includes(entry)) && optional(value["grantedScopes"], isStrings) && optional(value["missingScopes"], isStrings) && optional(value["delegationRequired"], isStrings) && optional(value["nextStep"], isText);
|
|
70
71
|
}
|
|
71
72
|
function isStatus(value) {
|
|
72
|
-
return isRecord(value) && isText(value["
|
|
73
|
+
return isRecord(value) && isText(value["version"]) && isRecord(value["host"]) && (value["host"]["version"] === null || isText(value["host"]["version"])) && isText(value["host"]["range"]) && typeof value["host"]["tested"] === "boolean" && STATES.includes(value["state"]) && isRecord(value["gws"]) && isText(value["gws"]["path"]) && isText(value["gws"]["version"]) && isStrings(value["services"]) && Array.isArray(value["accounts"]) && value["accounts"].every(isAccount) && optional(value["auditDegraded"], (entry) => typeof entry === "boolean") && isStrings(value["unguardedAgents"]) && optional(value["permissionsBlock"], isText) && isText(value["nextStep"]);
|
|
73
74
|
}
|
|
74
|
-
var NOTHING_TO_DO = "Nothing to do.";
|
|
75
75
|
function connectionLabel(account2) {
|
|
76
76
|
if (account2.connected) return "connected";
|
|
77
77
|
return account2.mode === "interactive" ? "sign-in required" : "not configured";
|
|
78
78
|
}
|
|
79
79
|
function openCodeLabel(status2) {
|
|
80
|
-
|
|
80
|
+
const version = status2.host.version ?? "unknown";
|
|
81
|
+
return status2.host.tested ? `${version} (tested)` : `${version} (host untested; supported range ${status2.host.range})`;
|
|
81
82
|
}
|
|
82
83
|
var DELEGATION_LABEL = "Needs domain-wide delegation";
|
|
83
84
|
function delegationText(account2) {
|
|
@@ -397,7 +398,7 @@ function StatusBody(props) {
|
|
|
397
398
|
return openCodeLabel(props.status);
|
|
398
399
|
},
|
|
399
400
|
get fg() {
|
|
400
|
-
return tone(props.status.
|
|
401
|
+
return tone(props.status.host.tested ? "success" : "warning");
|
|
401
402
|
},
|
|
402
403
|
get muted() {
|
|
403
404
|
return muted();
|
|
@@ -406,7 +407,7 @@ function StatusBody(props) {
|
|
|
406
407
|
_$insert(_el$6, _$createComponent(Row, {
|
|
407
408
|
label: "Next step",
|
|
408
409
|
get value() {
|
|
409
|
-
return props.status.nextStep
|
|
410
|
+
return props.status.nextStep;
|
|
410
411
|
},
|
|
411
412
|
get fg() {
|
|
412
413
|
return base();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joe-broadhead/opencode-gws",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Unofficial OpenCode plugin for Google Workspace (gws CLI)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
|
+
"assets/icon.svg",
|
|
29
30
|
"skills",
|
|
30
31
|
"manifest/generated.json",
|
|
31
|
-
"views",
|
|
32
|
+
"views/gmail-thread.html",
|
|
33
|
+
"views/jelly-view.js",
|
|
32
34
|
"README.md",
|
|
33
35
|
"LICENSE",
|
|
34
36
|
"NOTICE",
|
|
@@ -50,10 +52,10 @@
|
|
|
50
52
|
"docs:coverage": "node scripts/generate-docs.mjs"
|
|
51
53
|
},
|
|
52
54
|
"optionalDependencies": {
|
|
53
|
-
"@joe-broadhead/opencode-gws-bin-darwin-arm64": "0.0.
|
|
54
|
-
"@joe-broadhead/opencode-gws-bin-darwin-x64": "0.0.
|
|
55
|
-
"@joe-broadhead/opencode-gws-bin-linux-arm64-gnu": "0.0.
|
|
56
|
-
"@joe-broadhead/opencode-gws-bin-linux-x64-gnu": "0.0.
|
|
55
|
+
"@joe-broadhead/opencode-gws-bin-darwin-arm64": "0.0.4",
|
|
56
|
+
"@joe-broadhead/opencode-gws-bin-darwin-x64": "0.0.4",
|
|
57
|
+
"@joe-broadhead/opencode-gws-bin-linux-arm64-gnu": "0.0.4",
|
|
58
|
+
"@joe-broadhead/opencode-gws-bin-linux-x64-gnu": "0.0.4"
|
|
57
59
|
},
|
|
58
60
|
"devDependencies": {
|
|
59
61
|
"@babel/core": "7.29.7",
|
|
@@ -75,6 +77,8 @@
|
|
|
75
77
|
},
|
|
76
78
|
"jelly": {
|
|
77
79
|
"title": "Google Workspace",
|
|
80
|
+
"summary": "Gmail, Calendar, Drive, Docs and Sheets.",
|
|
81
|
+
"icon": "assets/icon.svg",
|
|
78
82
|
"tools": [
|
|
79
83
|
{
|
|
80
84
|
"name": "gws.status",
|
|
@@ -168,7 +172,11 @@
|
|
|
168
172
|
{
|
|
169
173
|
"id": "google",
|
|
170
174
|
"label": "Google Workspace",
|
|
171
|
-
"integration": "gws-*"
|
|
175
|
+
"integration": "gws-*",
|
|
176
|
+
"relay": {
|
|
177
|
+
"redirectField": "redirectUri",
|
|
178
|
+
"portField": "callbackPort"
|
|
179
|
+
}
|
|
172
180
|
}
|
|
173
181
|
],
|
|
174
182
|
"contributes": {
|
|
@@ -47,7 +47,7 @@ A change is two calls.
|
|
|
47
47
|
| export | `gws_export` |
|
|
48
48
|
| admin | `gws_admin` |
|
|
49
49
|
|
|
50
|
-
The plan's category wins over the manifest. A Drive update whose body sets `trashed` to true is a delete: commit with `gws_delete`. A Calendar event write whose `sendUpdates` is `
|
|
50
|
+
The plan's category wins over the manifest. A Drive update whose body sets `trashed` to true is a delete: commit with `gws_delete`. A Calendar event write whose `sendUpdates` is not `none`, or whose `sendNotifications` is true, emails the guests and is a send: commit with `gws_send`. A read with `download.path` is an export: commit with `gws_export`.
|
|
51
51
|
|
|
52
52
|
Plans are single-use and bound to this session, agent, and account. `PLAN_EXPIRED`, `PLAN_ALREADY_USED`, and `PLAN_CALLER_MISMATCH` mean: read the current state, plan again, and show the new preview. `CATEGORY_MISMATCH` means you called the wrong commit tool.
|
|
53
53
|
|
|
@@ -120,6 +120,8 @@ An error is `CODE: What happened. Next step: What to do.` Do the next step once.
|
|
|
120
120
|
| `OPERATION_UNKNOWN` | The id is not in the catalog. Search again with `gws_catalog`. |
|
|
121
121
|
| `HELPER_UNSUPPORTED` | The helper cannot run. Use the method `gws_catalog` names as `alternative`. |
|
|
122
122
|
| `POLICY_DENIED` | Stop. Tell the user. Do not rephrase the call to get around the deny. |
|
|
123
|
+
| `RECIPIENTS_UNKNOWN` | A recipient rule applies and the plugin could not tell who the send or share reaches. Name the recipients in `to`, `cc` and `bcc` (or the `To`, `Cc` and `Bcc` headers of `raw`) once; otherwise tell the user. |
|
|
124
|
+
| `ACCOUNT_DOMAIN_UNKNOWN` | A rule refuses external recipients and the account's own domain is unknown. Tell the user the message's next step. |
|
|
123
125
|
| `GWS_VALIDATION_ERROR` | Fix the request. `gws_schema` shows the parameters. List and search need `fields`. |
|
|
124
126
|
| `CANCELLED` | Do not retry unless the user asks. A commit that was already running may have been applied. Check with `gws_read` before planning again. |
|
|
125
127
|
| `SESSION_UNKNOWN` | A script named a session that does not exist. Have it create a session and keep that id. |
|
|
@@ -83,6 +83,8 @@ Reply. Same commit tool, `gws_send`:
|
|
|
83
83
|
}
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
The preview lists who the reply reaches: the sender, and for `gmail.reply-all` everyone else on the message. `to`, `cc` and `bcc` add recipients; `remove` leaves people out of a reply-all. `gmail.forward` takes `to`, `cc`, `bcc`, `body`, `attachments` and `noOriginalAttachments`. `gws_schema` lists every helper flag.
|
|
87
|
+
|
|
86
88
|
## Drive
|
|
87
89
|
|
|
88
90
|
Recent files, read:
|
|
@@ -169,7 +171,7 @@ Create an event that does not email anyone. Plan category is write. Commit with
|
|
|
169
171
|
}
|
|
170
172
|
```
|
|
171
173
|
|
|
172
|
-
Create or move an event that emails attendees (`sendUpdates` of `all` or `externalOnly`). The plan category is **send**. Commit with `gws_send`.
|
|
174
|
+
Create or move an event that emails attendees (`sendUpdates` of `all` or `externalOnly`; prefer it to the deprecated `sendNotifications`, which counts as a send too). The plan category is **send**. Commit with `gws_send`.
|
|
173
175
|
|
|
174
176
|
```json
|
|
175
177
|
{
|
package/views/jelly-view.d.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The types of `jelly-view.js`, for a page written or checked with TypeScript:
|
|
3
|
-
* `/// <reference path="./jelly-view.d.ts" />`. They mirror the bridge envelopes
|
|
4
|
-
* in Jelly's contracts (`protocol/contracts/src/view-bridge.ts`); the page itself
|
|
5
|
-
* carries only the JavaScript.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
type JellyViewPlace = "tool-result" | "home-widget" | "settings-section";
|
|
9
|
-
type JellyViewGrant = "data" | "state" | "rpc" | "open-agent";
|
|
10
|
-
|
|
11
|
-
/** The fixed theme token set; the helper sets each as `--jelly-<name>` on the page. */
|
|
12
|
-
interface JellyViewTheme {
|
|
13
|
-
text: string;
|
|
14
|
-
muted: string;
|
|
15
|
-
surface: string;
|
|
16
|
-
raised: string;
|
|
17
|
-
border: string;
|
|
18
|
-
accent: string;
|
|
19
|
-
"on-accent": string;
|
|
20
|
-
danger: string;
|
|
21
|
-
font: string;
|
|
22
|
-
radius: string;
|
|
23
|
-
scheme: "light" | "dark";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface JellyViewHello {
|
|
27
|
-
v: 1;
|
|
28
|
-
kind: "hello";
|
|
29
|
-
/** `package` is null for a Home app an agent made. */
|
|
30
|
-
view: { package: string | null; id: string; title: string; place: JellyViewPlace };
|
|
31
|
-
grants: JellyViewGrant[];
|
|
32
|
-
/** The methods `call` may name. */
|
|
33
|
-
rpc: string[];
|
|
34
|
-
theme: JellyViewTheme;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** A view's state: JSON of at most 64 KB, and the revision a write must name. */
|
|
38
|
-
interface JellyViewState {
|
|
39
|
-
revision: number;
|
|
40
|
-
data: unknown;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
type JellyViewPush =
|
|
44
|
-
| { v: 1; kind: "data.changed"; data: unknown }
|
|
45
|
-
| ({ v: 1; kind: "state.changed" } & JellyViewState)
|
|
46
|
-
| { v: 1; kind: "theme.changed"; theme: JellyViewTheme }
|
|
47
|
-
| { v: 1; kind: "visibility"; visible: boolean }
|
|
48
|
-
/** The call with request id `re` waits for the person, at most until `until` (ISO time). */
|
|
49
|
-
| { v: 1; kind: "rpc.waiting"; re: string; until: string };
|
|
50
|
-
|
|
51
|
-
interface JellyView {
|
|
52
|
-
hello: JellyViewHello;
|
|
53
|
-
/** Hear pushes; returns the way to stop. */
|
|
54
|
-
on(listener: (push: JellyViewPush) => void): () => void;
|
|
55
|
-
/** Any request by its op, for one the helper has no name for. */
|
|
56
|
-
request(op: string, fields?: Record<string, unknown>): Promise<unknown>;
|
|
57
|
-
/** The place's data (the `data` grant). */
|
|
58
|
-
data(): Promise<unknown>;
|
|
59
|
-
/** The view's state (the `state` grant). */
|
|
60
|
-
state(): Promise<JellyViewState>;
|
|
61
|
-
/** Replace the state if `revision` is still the stored one; rejects on a conflict. */
|
|
62
|
-
setState(revision: number, data: unknown): Promise<JellyViewState>;
|
|
63
|
-
/** One of the methods the hello lists (the `rpc` grant). */
|
|
64
|
-
call(method: string, input?: unknown): Promise<unknown>;
|
|
65
|
-
/** Start a message for the person to send; it is never sent (the `open-agent` grant). */
|
|
66
|
-
openAgent(prefill?: string): Promise<null>;
|
|
67
|
-
/** The height the page needs, in CSS pixels, up to 1200: a hint the app may draw shorter. */
|
|
68
|
-
resize(height: number): Promise<null>;
|
|
69
|
-
/** Not mine: the app closes the frame and keeps its ordinary look. */
|
|
70
|
-
decline(): Promise<null>;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
declare function jellyView(): Promise<JellyView>;
|