@open-everywhere/provider-google-chat 0.0.0-stage → 0.8.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.
Files changed (76) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +51 -0
  3. package/README.md +40 -2
  4. package/agent/channels/google-chat-auth.ts +145 -0
  5. package/agent/channels/google-chat-front.ts +338 -0
  6. package/agent/channels/google-chat-identity.ts +97 -0
  7. package/agent/channels/google-chat-message-ops.ts +30 -0
  8. package/agent/channels/google-chat-origin-codec.ts +32 -0
  9. package/agent/channels/google-chat-post-arm.ts +36 -0
  10. package/agent/channels/google-chat-rest.ts +87 -0
  11. package/agent/channels/google-chat.ts +194 -0
  12. package/agent/contributions.ts +16 -0
  13. package/agent/docs-generated.ts +120 -0
  14. package/agent/policy.ts +101 -0
  15. package/agent/provider-events.ts +18 -0
  16. package/agent/register.ts +48 -0
  17. package/agent/surface-parity.ts +64 -0
  18. package/dist/agent/channels/google-chat-auth.d.ts +39 -0
  19. package/dist/agent/channels/google-chat-auth.d.ts.map +1 -0
  20. package/dist/agent/channels/google-chat-auth.js +118 -0
  21. package/dist/agent/channels/google-chat-auth.js.map +1 -0
  22. package/dist/agent/channels/google-chat-front.d.ts +102 -0
  23. package/dist/agent/channels/google-chat-front.d.ts.map +1 -0
  24. package/dist/agent/channels/google-chat-front.js +258 -0
  25. package/dist/agent/channels/google-chat-front.js.map +1 -0
  26. package/dist/agent/channels/google-chat-identity.d.ts +28 -0
  27. package/dist/agent/channels/google-chat-identity.d.ts.map +1 -0
  28. package/dist/agent/channels/google-chat-identity.js +70 -0
  29. package/dist/agent/channels/google-chat-identity.js.map +1 -0
  30. package/dist/agent/channels/google-chat-message-ops.d.ts +10 -0
  31. package/dist/agent/channels/google-chat-message-ops.d.ts.map +1 -0
  32. package/dist/agent/channels/google-chat-message-ops.js +25 -0
  33. package/dist/agent/channels/google-chat-message-ops.js.map +1 -0
  34. package/dist/agent/channels/google-chat-origin-codec.d.ts +6 -0
  35. package/dist/agent/channels/google-chat-origin-codec.d.ts.map +1 -0
  36. package/dist/agent/channels/google-chat-origin-codec.js +31 -0
  37. package/dist/agent/channels/google-chat-origin-codec.js.map +1 -0
  38. package/dist/agent/channels/google-chat-post-arm.d.ts +11 -0
  39. package/dist/agent/channels/google-chat-post-arm.d.ts.map +1 -0
  40. package/dist/agent/channels/google-chat-post-arm.js +31 -0
  41. package/dist/agent/channels/google-chat-post-arm.js.map +1 -0
  42. package/dist/agent/channels/google-chat-rest.d.ts +21 -0
  43. package/dist/agent/channels/google-chat-rest.d.ts.map +1 -0
  44. package/dist/agent/channels/google-chat-rest.js +81 -0
  45. package/dist/agent/channels/google-chat-rest.js.map +1 -0
  46. package/dist/agent/channels/google-chat.d.ts +3 -0
  47. package/dist/agent/channels/google-chat.d.ts.map +1 -0
  48. package/dist/agent/channels/google-chat.js +157 -0
  49. package/dist/agent/channels/google-chat.js.map +1 -0
  50. package/dist/agent/contributions.d.ts +12 -0
  51. package/dist/agent/contributions.d.ts.map +1 -0
  52. package/dist/agent/contributions.js +16 -0
  53. package/dist/agent/contributions.js.map +1 -0
  54. package/dist/agent/docs-generated.d.ts +3 -0
  55. package/dist/agent/docs-generated.d.ts.map +1 -0
  56. package/dist/agent/docs-generated.js +118 -0
  57. package/dist/agent/docs-generated.js.map +1 -0
  58. package/dist/agent/policy.d.ts +38 -0
  59. package/dist/agent/policy.d.ts.map +1 -0
  60. package/dist/agent/policy.js +78 -0
  61. package/dist/agent/policy.js.map +1 -0
  62. package/dist/agent/provider-events.d.ts +3 -0
  63. package/dist/agent/provider-events.d.ts.map +1 -0
  64. package/dist/agent/provider-events.js +16 -0
  65. package/dist/agent/provider-events.js.map +1 -0
  66. package/dist/agent/register.d.ts +3 -0
  67. package/dist/agent/register.d.ts.map +1 -0
  68. package/dist/agent/register.js +37 -0
  69. package/dist/agent/register.js.map +1 -0
  70. package/dist/agent/surface-parity.d.ts +3 -0
  71. package/dist/agent/surface-parity.d.ts.map +1 -0
  72. package/dist/agent/surface-parity.js +60 -0
  73. package/dist/agent/surface-parity.js.map +1 -0
  74. package/package.json +116 -4
  75. package/tsconfig.build.json +22 -0
  76. package/tsconfig.json +15 -0
@@ -0,0 +1,118 @@
1
+ // GENERATED by `npx tsx scripts/docs-generate.ts` from docs/deploy/surfaces/google-chat.md — DO NOT HAND-EDIT.
2
+ // Edit the markdown under docs/ and re-run the generator; `npm run lint:docs` fails the
3
+ // build if this file and its sources ever disagree. See scripts/docs-generate.ts for why the
4
+ // manual is compiled in at all (docs/ does not exist on disk in a hosted deployment).
5
+ export const PROVIDER_DOCS = [
6
+ {
7
+ title: "Google Chat",
8
+ path: "docs/deploy/surfaces/google-chat.md",
9
+ summary: "Put the agent in Google Chat as a Chat app. People @mention it in a space or send it a direct message, and it answers in the same thread. Google Chat reaches the same two chiefs of staff as every other chat surface:",
10
+ markdown: [
11
+ "# Google Chat",
12
+ "",
13
+ "Put the agent in Google Chat as a Chat app. People @mention it in a space or send it a direct message, and it",
14
+ "answers in the same thread. Google Chat reaches the same two chiefs of staff as every other chat surface:",
15
+ "",
16
+ "- A **space** belongs to a domain. An @mention of the app in a space wakes that domain's standing seat, exactly as a",
17
+ " message in one of the domain's Slack or Teams channels would.",
18
+ "- A **direct message** with the app wakes the person's own DM seat.",
19
+ "",
20
+ "Google Chat is the surface for an organisation that runs Google Workspace. It ships **off**: until a policy enables",
21
+ "it, the endpoint answers every delivery with `503`.",
22
+ "",
23
+ "## What it does and does not do",
24
+ "",
25
+ "- **Every event is verified before it is read.** Google Chat sends each event with a bearer token. The route checks",
26
+ " the token's signature against Google's published keys, its issuer, its expiry, and its audience against the",
27
+ " policy's `audience`. A token for any other audience, or (in endpoint-URL mode) from any Google account other than",
28
+ " `chat@system.gserviceaccount.com`, is refused `401` and writes no audit row.",
29
+ "- **Addressed only.** The HTTP endpoint gets a space message only when it @-mentions the app, or invokes one of its",
30
+ " slash commands. The surface has no ambient leg: room chatter never reaches it. (A Workspace Events subscription",
31
+ " would deliver the rest; this surface does not use one yet.)",
32
+ "- **Trust comes from the policy, never from a name.** A sender binds `internal` only when Google's event names a",
33
+ " Workspace domain id (`sender.domainId`) that the policy lists in `internalDomainIds`. Everyone else binds",
34
+ " `external`: shared memory routes to the read-only `public` layer, and the turn is marked as carrying a",
35
+ " non-member's words. ⚠ The mapping from your Workspace to its domain id is not documented as stable by Google.",
36
+ " Read the id from a real event: every `google-chat.admitted` and `google-chat.refused` audit row records the",
37
+ " sender's `domainId`. A DM-only deployment can start with an empty list: the first internal person's DM is refused",
38
+ " `external-dm`, and its refused row carries their domain id.",
39
+ "- **Direct messages are for internal people only.** A DM seat reads its person's private layer, so a DM from an",
40
+ " `external` sender is refused (`external-dm`). Set `directMessages: false` to refuse every DM (`dm-off`).",
41
+ "- **Group chats are refused** (`group-chat`). A group chat has no domain to own it and is not one person's DM.",
42
+ "- **A space with no seat is refused**, not dropped in silence (`no-domain`): put its surface key in a domain's",
43
+ " `reach`, or run a standing-seat window that gives an undeclared space its own solo seat.",
44
+ "- **Bots never wake a seat.** A message from any bot, the app's own included, is dropped. That is the loop guard.",
45
+ "- **Replies only, into the conversation that woke the seat.** The reply posts into the trigger's space and thread,",
46
+ " as the app. The space and thread are frozen at the gate from the verified event; the model never names one. The",
47
+ " app can post only into a space it is a member of. A reply longer than one Chat message goes out as consecutive",
48
+ " messages in the same thread.",
49
+ "",
50
+ "## How it fits the planes",
51
+ "",
52
+ "| Plane | What Google Chat uses |",
53
+ "|---|---|",
54
+ "| Surface | The `google-chat` provider bundle (`packages/providers/google-chat`): identity mapper, capability manifest, post arm, wake-origin codec, host-notice transport. A space's surface key is `google-chat/<workspace>/<space id>` and goes in a domain's `reach` like any channel. |",
55
+ "| Seat | A space mention diverts into the domain's standing seat through the same `divertInboundToUnifiedWindow` every chat surface uses; a DM diverts into the person's DM seat (`channels/dm-seat.ts`). Spend caps, the wake ingress row, provider selection and rate-limit retry ride the shared divert. |",
56
+ "| Identity | The principal is the sender's Chat user resource name (`users/<id>`). The workspace is the policy's `workspace` segment. Visibility is always `private`. |",
57
+ "| Audit | `google-chat.admitted` (space, seat kind, trust, the sender's domain id, whether it was a thread reply), `google-chat.refused` (the reason and the sender's domain id), and `google-chat.wake_failed`. The reply itself writes the shared `reply.post` row. |",
58
+ "| Egress | The reply and a host notice (an approval outcome note, the judge-lift notice) are the only outbound calls, to `chat.googleapis.com`, with a `chat.bot` token minted from the app's service-account key at `oauth2.googleapis.com`. The token endpoint is pinned: the key file's own `token_uri` is ignored. |",
59
+ "",
60
+ "## What an operator must provision",
61
+ "",
62
+ "Nothing below is created by Open Everywhere.",
63
+ "",
64
+ "1. **A Google Cloud project** with the Google Chat API enabled.",
65
+ "2. **A service account** in that project, and a JSON key for it. The app posts its replies as this account.",
66
+ "3. **The Chat app configuration** (Google Chat API → Configuration): give the app a name and avatar, turn on",
67
+ " \"Receive 1:1 messages\" and \"Join spaces and group conversations\", choose **HTTP endpoint URL** as the connection",
68
+ " setting, and set it to `https://<your deployment host>/eve/v1/google-chat`. Choose the **Authentication audience**:",
69
+ " \"HTTP endpoint URL\" (recommended) or \"Project number\". Make the app visible to the people or groups who should",
70
+ " use it.",
71
+ "4. **The secret**, in the secret store, never in a file or the environment of a commit:",
72
+ " ```sh",
73
+ " npx oe secret set GOOGLE_CHAT_SERVICE_ACCOUNT_KEY # the service account's JSON key, whole",
74
+ " ```",
75
+ " (The resolver falls back to an environment variable of the same name, and warns when it does.)",
76
+ "5. **The policy**, in `agent/google-chat/policy.ts`, by pull request: set `enabled: true`, the `audience` that",
77
+ " matches step 3 (`{ kind: \"endpoint-url\", url: \"https://<host>/eve/v1/google-chat\" }` or",
78
+ " `{ kind: \"project-number\", projectNumber: \"<number>\" }`), your `workspace` segment, and your",
79
+ " `internalDomainIds`.",
80
+ "6. **The seats.** For each space, add its surface key (`google-chat/<workspace>/<space id>`, the id after",
81
+ " `spaces/` in the space's URL) to the owning domain's `reach` in `agent/memory/config/domains/`. A multi-source",
82
+ " window requires every source vouched, so also declare the space in `agent/identity/surfaces.ts`. 🔴 The vouch",
83
+ " does **not** make an outside sender internal: the mapper states each message's trust itself, from the policy.",
84
+ "7. **Add the app** to each space (`@<app name>` → Add).",
85
+ "",
86
+ "## Settings",
87
+ "",
88
+ "| Field | Meaning |",
89
+ "|---|---|",
90
+ "| `enabled` | The master switch. Off answers `503` to every delivery and refuses every reply. |",
91
+ "| `audience` | The audience every event's token must carry. `null` refuses every delivery; an enabled policy without one fails the boot. |",
92
+ "| `workspace` | The workspace segment of every surface key (lowercase, `a-z`, `0-9`, `-`). |",
93
+ "| `internalDomainIds` | The Workspace domain ids whose people bind `internal`. Empty: everybody binds `external`. |",
94
+ "| `directMessages` | May an internal person wake their own DM seat? |",
95
+ "",
96
+ "## What is not built yet",
97
+ "",
98
+ "- **Cards**: an approval asked from Google Chat takes the venue walk to a card-capable room in the same domain. A",
99
+ " Chat card with a button needs the `CARD_CLICKED` tap answered.",
100
+ "- **Reading a space** (`read_channel`, `read_thread`) and a seat catch-up: listing a space's messages needs user",
101
+ " authentication or the admin-approved `chat.app.messages.readonly` app scope, which the app does not request.",
102
+ "- **Ambient messages, name-drops and edits**: they need a Workspace Events subscription.",
103
+ "- **Edit, reactions, stop, files, proactive posts and routines.** Each is declared, with its reason, in the",
104
+ " [chat-surface contract](../../extending/chat-surface-contract.md)'s parity tables.",
105
+ "- **The Workspace add-on event format.** The route reads the classic Chat app event; an app built as a Google",
106
+ " Workspace add-on wraps its events differently and is not supported.",
107
+ "",
108
+ "## Verification",
109
+ "",
110
+ "The unit packs (`test:google-chat-auth`, `test:google-chat-front`, `test:google-chat-post-arm`) and the app-level",
111
+ "`test:google-chat-integration` drive the token check, the gate, the reply and the binding offline. There is no",
112
+ "live e2e leg yet: one needs a Google Workspace test tenant with the app published to it, a fixture this repository",
113
+ "cannot create.",
114
+ "",
115
+ ].join("\n"),
116
+ },
117
+ ];
118
+ //# sourceMappingURL=docs-generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-generated.js","sourceRoot":"","sources":["../../agent/docs-generated.ts"],"names":[],"mappings":"AAAA,+GAA+G;AAC/G,wFAAwF;AACxF,6FAA6F;AAC7F,sFAAsF;AAItF,MAAM,CAAC,MAAM,aAAa,GAAwB;IAChD;QACE,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,qCAAqC;QAC3C,OAAO,EAAE,yNAAyN;QAClO,QAAQ,EAAE;YACR,eAAe;YACf,EAAE;YACF,+GAA+G;YAC/G,2GAA2G;YAC3G,EAAE;YACF,sHAAsH;YACtH,iEAAiE;YACjE,qEAAqE;YACrE,EAAE;YACF,qHAAqH;YACrH,qDAAqD;YACrD,EAAE;YACF,iCAAiC;YACjC,EAAE;YACF,qHAAqH;YACrH,+GAA+G;YAC/G,qHAAqH;YACrH,gFAAgF;YAChF,qHAAqH;YACrH,mHAAmH;YACnH,+DAA+D;YAC/D,kHAAkH;YAClH,6GAA6G;YAC7G,0GAA0G;YAC1G,iHAAiH;YACjH,+GAA+G;YAC/G,qHAAqH;YACrH,+DAA+D;YAC/D,iHAAiH;YACjH,4GAA4G;YAC5G,gHAAgH;YAChH,gHAAgH;YAChH,4FAA4F;YAC5F,mHAAmH;YACnH,oHAAoH;YACpH,mHAAmH;YACnH,kHAAkH;YAClH,gCAAgC;YAChC,EAAE;YACF,2BAA2B;YAC3B,EAAE;YACF,mCAAmC;YACnC,WAAW;YACX,8RAA8R;YAC9R,+SAA+S;YAC/S,yKAAyK;YACzK,yQAAyQ;YACzQ,0TAA0T;YAC1T,EAAE;YACF,oCAAoC;YACpC,EAAE;YACF,8CAA8C;YAC9C,EAAE;YACF,iEAAiE;YACjE,6GAA6G;YAC7G,8GAA8G;YAC9G,yHAAyH;YACzH,wHAAwH;YACxH,uHAAuH;YACvH,YAAY;YACZ,yFAAyF;YACzF,UAAU;YACV,gGAAgG;YAChG,QAAQ;YACR,mGAAmG;YACnG,gHAAgH;YAChH,gGAAgG;YAChG,qGAAqG;YACrG,yBAAyB;YACzB,2GAA2G;YAC3G,mHAAmH;YACnH,kHAAkH;YAClH,kHAAkH;YAClH,yDAAyD;YACzD,EAAE;YACF,aAAa;YACb,EAAE;YACF,qBAAqB;YACrB,WAAW;YACX,iGAAiG;YACjG,4IAA4I;YAC5I,8FAA8F;YAC9F,qHAAqH;YACrH,uEAAuE;YACvE,EAAE;YACF,0BAA0B;YAC1B,EAAE;YACF,mHAAmH;YACnH,kEAAkE;YAClE,kHAAkH;YAClH,gHAAgH;YAChH,0FAA0F;YAC1F,6GAA6G;YAC7G,sFAAsF;YACtF,+GAA+G;YAC/G,uEAAuE;YACvE,EAAE;YACF,iBAAiB;YACjB,EAAE;YACF,mHAAmH;YACnH,gHAAgH;YAChH,oHAAoH;YACpH,gBAAgB;YAChB,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC;KACb;CACF,CAAC"}
@@ -0,0 +1,38 @@
1
+ /** Which audience Google Chat puts in the bearer token of each event — the app's "Authentication audience"
2
+ * setting in the Google Cloud console. */
3
+ export type GoogleChatAudience =
4
+ /** "Project number": the token is self-signed by `chat@system.gserviceaccount.com` for the project number. */
5
+ {
6
+ readonly kind: "project-number";
7
+ readonly projectNumber: string;
8
+ }
9
+ /** "HTTP endpoint URL": the token is a Google OIDC id token for the exact endpoint URL. */
10
+ | {
11
+ readonly kind: "endpoint-url";
12
+ readonly url: string;
13
+ };
14
+ export interface GoogleChatPolicy {
15
+ /** The master switch. Off answers 503 to every delivery and refuses every reply. */
16
+ readonly enabled: boolean;
17
+ /** The audience every event's token must carry. Null refuses every delivery (fail closed). */
18
+ readonly audience: GoogleChatAudience | null;
19
+ /** The workspace segment of every Google Chat surface key (`google-chat/<workspace>/<space id>`). */
20
+ readonly workspace: string;
21
+ /**
22
+ * The Google Workspace domain ids (`sender.domainId` on a Chat event) whose people bind `internal`. Everyone
23
+ * else binds `external`. Empty: everybody binds external.
24
+ */
25
+ readonly internalDomainIds: readonly string[];
26
+ /** May a person wake their own DM seat by messaging the app directly? An `external` person never can. */
27
+ readonly directMessages: boolean;
28
+ }
29
+ export declare const DEFAULT_GOOGLE_CHAT_POLICY: GoogleChatPolicy;
30
+ /** Every problem with `policy`, or empty when it is valid. Pure. */
31
+ export declare function validateGoogleChatPolicy(policy: GoogleChatPolicy): readonly string[];
32
+ /** Register this deployment's policy. Throws on an invalid policy, so a bad file fails the boot. */
33
+ export declare function registerGoogleChatPolicy(policy: GoogleChatPolicy): void;
34
+ /** The registered policy (the shipped default — off — until the app registers one). */
35
+ export declare function googleChatPolicy(): GoogleChatPolicy;
36
+ /** The surface key of one space: `google-chat/<workspace>/<space id>`. */
37
+ export declare function googleChatSurfaceKey(policy: GoogleChatPolicy, space: string): string;
38
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../agent/policy.ts"],"names":[],"mappings":"AAaA;2CAC2C;AAC3C,MAAM,MAAM,kBAAkB;AAC5B,8GAA8G;AAC5G;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAAE;AACrE,2FAA2F;GACzF;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC7C,qGAAqG;IACrG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,yGAAyG;IACzG,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAMxC,CAAC;AAMF,oEAAoE;AACpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,MAAM,EAAE,CA0BpF;AAID,oGAAoG;AACpG,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAIvE;AAED,uFAAuF;AACvF,wBAAgB,gBAAgB,IAAI,gBAAgB,CAEnD;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpF"}
@@ -0,0 +1,78 @@
1
+ // THE GOOGLE CHAT POLICY (OPE-2442) — the schema, its validation and the registry. The app's own
2
+ // `agent/google-chat/policy.ts` declares the values and calls `registerGoogleChatPolicy` at boot (through
3
+ // `agent/lib/register-config.ts`), so every change is a reviewed pull request.
4
+ //
5
+ // 🔴 THE SURFACE SHIPS OFF. `DEFAULT_GOOGLE_CHAT_POLICY.enabled` is false, and the route answers 503 to every
6
+ // delivery until a policy enables it AND names the audience Google signs each event for. An external ingress
7
+ // that nobody configured must not be reachable.
8
+ //
9
+ // 🔴 TRUST IS TYPED CODE, NEVER AN ENVIRONMENT VARIABLE. `internalDomainIds` is the list of Google Workspace
10
+ // domain ids whose people bind `internal`; it is a trust declaration, so it lives here and changes by pull
11
+ // request. Nothing here is a secret: the app's service-account key lives in the secret store
12
+ // (`npx oe secret set GOOGLE_CHAT_SERVICE_ACCOUNT_KEY`).
13
+ export const DEFAULT_GOOGLE_CHAT_POLICY = {
14
+ enabled: false,
15
+ audience: null,
16
+ workspace: "workspace",
17
+ internalDomainIds: [],
18
+ directMessages: true,
19
+ };
20
+ const WORKSPACE_SEGMENT = /^[a-z0-9][a-z0-9-]{0,62}$/u;
21
+ const PROJECT_NUMBER = /^[0-9]{1,20}$/u;
22
+ const DOMAIN_ID = /^[A-Za-z0-9_-]{1,64}$/u;
23
+ /** Every problem with `policy`, or empty when it is valid. Pure. */
24
+ export function validateGoogleChatPolicy(policy) {
25
+ const problems = [];
26
+ if (!WORKSPACE_SEGMENT.test(policy.workspace)) {
27
+ problems.push(`workspace "${policy.workspace}" must be a lowercase segment (a-z, 0-9, "-"), at most 63 characters.`);
28
+ }
29
+ for (const id of policy.internalDomainIds) {
30
+ if (!DOMAIN_ID.test(id))
31
+ problems.push(`internalDomainIds entry "${id}" is not a Google Workspace domain id.`);
32
+ }
33
+ const a = policy.audience;
34
+ if (a !== null) {
35
+ if (a.kind === "project-number") {
36
+ if (!PROJECT_NUMBER.test(a.projectNumber))
37
+ problems.push("audience.projectNumber must be the numeric Google Cloud project number.");
38
+ }
39
+ else if (a.kind === "endpoint-url") {
40
+ let url;
41
+ try {
42
+ url = new URL(a.url);
43
+ }
44
+ catch {
45
+ url = undefined;
46
+ }
47
+ if (url?.protocol !== "https:")
48
+ problems.push("audience.url must be the app's https endpoint URL.");
49
+ }
50
+ else {
51
+ problems.push(`audience.kind must be "project-number" or "endpoint-url".`);
52
+ }
53
+ }
54
+ if (policy.enabled && a === null)
55
+ problems.push("an enabled policy must name its audience — without it no event can be verified.");
56
+ return problems;
57
+ }
58
+ let registered = DEFAULT_GOOGLE_CHAT_POLICY;
59
+ /** Register this deployment's policy. Throws on an invalid policy, so a bad file fails the boot. */
60
+ export function registerGoogleChatPolicy(policy) {
61
+ const problems = validateGoogleChatPolicy(policy);
62
+ if (problems.length > 0)
63
+ throw new Error(`agent/google-chat/policy.ts is invalid:\n - ${problems.join("\n - ")}`);
64
+ registered = policy;
65
+ }
66
+ /** The registered policy (the shipped default — off — until the app registers one). */
67
+ export function googleChatPolicy() {
68
+ return registered;
69
+ }
70
+ /** The surface key of one space: `google-chat/<workspace>/<space id>`. */
71
+ export function googleChatSurfaceKey(policy, space) {
72
+ return `google-chat/${policy.workspace}/${spaceId(space)}`;
73
+ }
74
+ /** The id after `spaces/`. */
75
+ function spaceId(space) {
76
+ return space.slice(space.indexOf("/") + 1);
77
+ }
78
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../agent/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProviderEventDeclaration } from "@open-everywhere/core/agent/adapter-api.js";
2
+ export declare const GOOGLE_CHAT_PROVIDER_EVENTS: ProviderEventDeclaration;
3
+ //# sourceMappingURL=provider-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-events.d.ts","sourceRoot":"","sources":["../../agent/provider-events.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,2BAA2B,EAAE,wBAQzC,CAAC"}
@@ -0,0 +1,16 @@
1
+ // GOOGLE CHAT's event inventory (OPE-2442). See the core module's header
2
+ // (packages/core/agent/routines/provider-events.ts) for what the three routing states mean.
3
+ //
4
+ // 🔴 THE GOOGLE CHAT BUNDLE REGISTERS NO EVENT NORMALIZER, so every row is `routing: "none"` and the declaration
5
+ // names no `source`. A message event is CONVERSATION — it wakes a seat through the surface's gate — and a routine
6
+ // subscribed to raw Chat events would bypass that gate.
7
+ export const GOOGLE_CHAT_PROVIDER_EVENTS = {
8
+ doc: "https://developers.google.com/workspace/chat/receive-respond-interactions",
9
+ events: [
10
+ { event: "MESSAGE", routing: "none", match: [], scope: [], note: "an @mention in a space or a direct message — the front's conversation leg, through the gate, never a routine" },
11
+ { event: "ADDED_TO_SPACE", routing: "none", match: [], scope: [], note: "the app was added to a space — acknowledged and dropped; a space wakes nothing until a domain's `reach` lists it" },
12
+ { event: "REMOVED_FROM_SPACE", routing: "none", match: [], scope: [], note: "the app was removed from a space — acknowledged and dropped" },
13
+ { event: "CARD_CLICKED", routing: "none", match: [], scope: [], note: "a card button tap — acknowledged and dropped; the surface posts no card yet" },
14
+ ],
15
+ };
16
+ //# sourceMappingURL=provider-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-events.js","sourceRoot":"","sources":["../../agent/provider-events.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,4FAA4F;AAC5F,EAAE;AACF,iHAAiH;AACjH,kHAAkH;AAClH,wDAAwD;AAIxD,MAAM,CAAC,MAAM,2BAA2B,GAA6B;IACnE,GAAG,EAAE,2EAA2E;IAChF,MAAM,EAAE;QACN,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,8GAA8G,EAAE;QACjL,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,kHAAkH,EAAE;QAC5L,EAAE,KAAK,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,6DAA6D,EAAE;QAC3I,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,6EAA6E,EAAE;KACtJ;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Perform ALL of the Google Chat bundle's registrations. Idempotent (each register call replaces). */
2
+ export declare function registerGoogleChatProvider(): void;
3
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"AAoCA,uGAAuG;AACvG,wBAAgB,0BAA0B,IAAI,IAAI,CAUjD"}
@@ -0,0 +1,37 @@
1
+ // registerGoogleChatProvider — the ONE boot entry of @open-everywhere/provider-google-chat (OPE-2442). The app's
2
+ // generated selection table imports it STATICALLY and `registerDefaultAdapters()` calls it once at boot; every
3
+ // seam the bundle implements registers here and nowhere else.
4
+ //
5
+ // What Google Chat registers (and what it deliberately does NOT):
6
+ // • identity mapper — bindGoogleChat (channels/google-chat-identity.ts)
7
+ // • capability manifest — { midTurnPost: true, reactions: false, closingProseDropped: true }: `reply` is the
8
+ // wired verb (the unified dispatch through the post arm), the app sets no reactions,
9
+ // and a seat's turn-final text is dropped, so `reply` is the only way out
10
+ // • post arm — googleChatPostArm: the reply, into the trigger's space and thread
11
+ // • wake-origin codec — the stored-data google-chat arm (channels/google-chat-origin-codec.ts)
12
+ // • surface message ops — googleChatMessageOps: a host notice is one more message in the space
13
+ // • credential probe — "configured" = the policy is enabled (no environment read)
14
+ // • NO read adapter (the app cannot list a space's messages), NO card poster, NO reaction surface, NO routine
15
+ // dispatch — each is declared, with its reason, in surface-parity.ts.
16
+ import { registerCapabilityManifest, registerIdentityMapper, registerPostArm, registerProviderDocs, registerProviderEvents, registerSurfaceCredentialProbe, registerSurfaceMessageOps, registerSurfaceParity, registerWakeOriginCodec, } from "@open-everywhere/core/agent/adapter-api.js";
17
+ import { PROVIDER_DOCS } from "./docs-generated.js";
18
+ import { GOOGLE_CHAT_SURFACE_PARITY } from "./surface-parity.js";
19
+ import { GOOGLE_CHAT_PROVIDER_EVENTS } from "./provider-events.js";
20
+ import { googleChatPolicy } from "./policy.js";
21
+ import { bindGoogleChat } from "./channels/google-chat-identity.js";
22
+ import { googleChatPostArm } from "./channels/google-chat-post-arm.js";
23
+ import { googleChatWakeOriginCodec } from "./channels/google-chat-origin-codec.js";
24
+ import { googleChatMessageOps } from "./channels/google-chat-message-ops.js";
25
+ /** Perform ALL of the Google Chat bundle's registrations. Idempotent (each register call replaces). */
26
+ export function registerGoogleChatProvider() {
27
+ registerIdentityMapper("google-chat", bindGoogleChat);
28
+ registerCapabilityManifest("google-chat", { midTurnPost: true, reactions: false, closingProseDropped: true });
29
+ registerSurfaceParity("google-chat", GOOGLE_CHAT_SURFACE_PARITY);
30
+ registerProviderEvents("google-chat", GOOGLE_CHAT_PROVIDER_EVENTS);
31
+ registerPostArm(googleChatPostArm);
32
+ registerWakeOriginCodec("google-chat", googleChatWakeOriginCodec);
33
+ registerSurfaceMessageOps(googleChatMessageOps);
34
+ registerSurfaceCredentialProbe("google-chat", () => googleChatPolicy().enabled);
35
+ registerProviderDocs("google-chat", PROVIDER_DOCS);
36
+ }
37
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../agent/register.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,+GAA+G;AAC/G,8DAA8D;AAC9D,EAAE;AACF,kEAAkE;AAClE,8EAA8E;AAC9E,+GAA+G;AAC/G,+GAA+G;AAC/G,oGAAoG;AACpG,8FAA8F;AAC9F,mGAAmG;AACnG,iGAAiG;AACjG,uFAAuF;AACvF,gHAAgH;AAChH,0EAA0E;AAE1E,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAE7E,uGAAuG;AACvG,MAAM,UAAU,0BAA0B;IACxC,sBAAsB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IACtD,0BAA0B,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9G,qBAAqB,CAAC,aAAa,EAAE,0BAA0B,CAAC,CAAC;IACjE,sBAAsB,CAAC,aAAa,EAAE,2BAA2B,CAAC,CAAC;IACnE,eAAe,CAAC,iBAAiB,CAAC,CAAC;IACnC,uBAAuB,CAAC,aAAa,EAAE,yBAAyB,CAAC,CAAC;IAClE,yBAAyB,CAAC,oBAAoB,CAAC,CAAC;IAChD,8BAA8B,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAAC,OAAO,CAAC,CAAC;IAChF,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SurfaceParityDeclaration } from "@open-everywhere/core/agent/adapter-api.js";
2
+ export declare const GOOGLE_CHAT_SURFACE_PARITY: SurfaceParityDeclaration;
3
+ //# sourceMappingURL=surface-parity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-parity.d.ts","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAE3F,eAAO,MAAM,0BAA0B,EAAE,wBAkDxC,CAAC"}
@@ -0,0 +1,60 @@
1
+ // GOOGLE CHAT's surface-parity declaration (OPE-2442). See the core module's header
2
+ // (packages/core/agent/identity/surface-parity.ts) for what the three cell shapes mean.
3
+ //
4
+ // The first cut is the addressed path: an @mention in a space or a direct message wakes a seat, and the seat
5
+ // answers in the same thread. Google Chat's HTTP endpoint delivers a space message only when it @-mentions the
6
+ // app. Ambient messages, edits and space reads need a Workspace Events subscription or the admin-approved
7
+ // `chat.app.messages.readonly` scope, which this cut does not request. So every vendor-side gap below is "not
8
+ // built yet": none of them is a platform limit. Two kinds of row are not gaps: `mpim` is a policy refusal (a group
9
+ // chat has no domain to own it and is not one person's DM), and `search`, `origin-placement-carry`,
10
+ // `engaged-row-promotion` and `seat-context-admission` do not apply to this surface by design.
11
+ export const GOOGLE_CHAT_SURFACE_PARITY = {
12
+ // --- registration seams (§7.1) ---------------------------------------------------------------
13
+ "identity-mapper": "supported",
14
+ "capability-manifest": "supported",
15
+ "post-arm": "supported",
16
+ "wake-origin-codec": "supported",
17
+ "origin-placement-carry": {
18
+ unsupported: "the placement is INSIDE the conversation identity: `threadRef` keys on the thread name, the very thread a reply posts into, so two origins of one conversation already agree on placement",
19
+ },
20
+ "read-adapter": { unsupported: "not built yet — listing a space's messages needs user authentication or the admin-approved `chat.app.messages.readonly` app scope, which the app does not request" },
21
+ "reaction-feedback-ingest": { unsupported: "not built yet — the HTTP endpoint carries no reaction event; a Workspace Events subscription would" },
22
+ "ancillary-ops": { supported: "text only — a host notice is one more message in the space; no edit, file or reaction" },
23
+ "ambient-engagement-seam": { unsupported: "not built yet — the HTTP endpoint delivers a space message only on an @mention; a Workspace Events subscription would deliver the rest" },
24
+ "engaged-row-promotion": { unsupported: "no ambient leg — every Google Chat wake is addressed (`direct-mention`)" },
25
+ "owned-thread-ingress": { supported: "the space leg takes the inbound divert; only a reply inside an existing thread (`threadReply`) is thread-scoped" },
26
+ "thread-done-reaction": { unsupported: "not built yet — the app sets no reactions (no `setReaction` in the ancillary ops)" },
27
+ // --- wake legs and conversation shapes -------------------------------------------------------
28
+ "addressed-leg": "supported",
29
+ "ambient-leg": { unsupported: "not built yet — the HTTP endpoint delivers a space message only on an @mention; a Workspace Events subscription would deliver the rest" },
30
+ "seat-catch-up": { unsupported: "not built yet — the app does not list a space's messages (see the read adapter row)" },
31
+ "seat-context-admission": { unsupported: "the wake fills no context-line slot — the seat reads only the addressed message and its carried tail" },
32
+ "approval-card": {
33
+ unsupported: "not built yet — a Chat card with a button needs the CARD_CLICKED tap answered; a governed act asked from Google Chat takes the venue walk to a card-capable room in the same domain",
34
+ },
35
+ "judge-lift-notice": { supported: "the shared text render, posted into the space — no button yet, so the overrule is spelled out in words" },
36
+ "out-of-office-cover": { unsupported: "not built yet — the space route does not call `coverForWake`, and the surface takes no ambient messages" },
37
+ "name-drop-mention": { unsupported: "not built yet — a message that names the app without an @mention never reaches the HTTP endpoint; a Workspace Events subscription would deliver it" },
38
+ "message-edit-wake": { unsupported: "not built yet — the HTTP endpoint sends no event for an edited message; a Workspace Events subscription would" },
39
+ threads: { supported: "a reply posts into the trigger's own thread (`REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`)" },
40
+ rooms: { supported: "a space is a surface a domain's `reach` lists (`google-chat/<workspace>/<space id>`)" },
41
+ dm: { supported: "the person's own direct message with the app wakes their DM seat — internal people only" },
42
+ mpim: { unsupported: "policy: a group chat is refused (`group-chat`) — it has no domain to own it and is not one person's DM" },
43
+ // --- core verbs (§7.2) -----------------------------------------------------------------------
44
+ reply: "supported",
45
+ edit_reply: { unsupported: "not built yet — the arm registers no edit; Chat's `messages.patch` would carry one" },
46
+ react: { unsupported: "not built yet — no outbound reaction transport is wired" },
47
+ no_reply: "supported",
48
+ read_channel: { unsupported: "not built yet — listing a space's messages needs user authentication or the admin-approved `chat.app.messages.readonly` app scope, which the app does not request" },
49
+ read_thread: { unsupported: "not built yet — the same message-list scope as `read_channel`" },
50
+ search: { unsupported: "no work-search adapter — Google Chat is a chat surface, not a work corpus" },
51
+ post_message: { unsupported: "not built yet — no routine dispatch is registered, so the agent answers only in a conversation somebody started" },
52
+ dm_person: { unsupported: "not built yet — the app cannot open a DM a person did not start" },
53
+ set_dm_delivery: { unsupported: "not built yet — a Google Chat DM is never a proactive delivery channel" },
54
+ stop: { unsupported: "not built yet — the app reads no reactions, so there is no stop trigger" },
55
+ ack_stop_glyph: { unsupported: "not built yet — the app sets no reactions" },
56
+ ack_cancel_note: { supported: "a message in the space, through the host-notice transport" },
57
+ stand_down: { unsupported: "not built yet — remove the app from the space instead" },
58
+ post_file: { unsupported: "not built yet — the reply carries text only" },
59
+ };
60
+ //# sourceMappingURL=surface-parity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-parity.js","sourceRoot":"","sources":["../../agent/surface-parity.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,wFAAwF;AACxF,EAAE;AACF,6GAA6G;AAC7G,+GAA+G;AAC/G,0GAA0G;AAC1G,8GAA8G;AAC9G,mHAAmH;AACnH,oGAAoG;AACpG,+FAA+F;AAI/F,MAAM,CAAC,MAAM,0BAA0B,GAA6B;IAClE,gGAAgG;IAChG,iBAAiB,EAAE,WAAW;IAC9B,qBAAqB,EAAE,WAAW;IAClC,UAAU,EAAE,WAAW;IACvB,mBAAmB,EAAE,WAAW;IAChC,wBAAwB,EAAE;QACxB,WAAW,EAAE,2LAA2L;KACzM;IACD,cAAc,EAAE,EAAE,WAAW,EAAE,mKAAmK,EAAE;IACpM,0BAA0B,EAAE,EAAE,WAAW,EAAE,oGAAoG,EAAE;IACjJ,eAAe,EAAE,EAAE,SAAS,EAAE,uFAAuF,EAAE;IACvH,yBAAyB,EAAE,EAAE,WAAW,EAAE,wIAAwI,EAAE;IACpL,uBAAuB,EAAE,EAAE,WAAW,EAAE,yEAAyE,EAAE;IACnH,sBAAsB,EAAE,EAAE,SAAS,EAAE,iHAAiH,EAAE;IACxJ,sBAAsB,EAAE,EAAE,WAAW,EAAE,mFAAmF,EAAE;IAE5H,gGAAgG;IAChG,eAAe,EAAE,WAAW;IAC5B,aAAa,EAAE,EAAE,WAAW,EAAE,wIAAwI,EAAE;IACxK,eAAe,EAAE,EAAE,WAAW,EAAE,qFAAqF,EAAE;IACvH,wBAAwB,EAAE,EAAE,WAAW,EAAE,sGAAsG,EAAE;IACjJ,eAAe,EAAE;QACf,WAAW,EAAE,qLAAqL;KACnM;IACD,mBAAmB,EAAE,EAAE,SAAS,EAAE,wGAAwG,EAAE;IAC5I,qBAAqB,EAAE,EAAE,WAAW,EAAE,yGAAyG,EAAE;IACjJ,mBAAmB,EAAE,EAAE,WAAW,EAAE,oJAAoJ,EAAE;IAC1L,mBAAmB,EAAE,EAAE,WAAW,EAAE,+GAA+G,EAAE;IACrJ,OAAO,EAAE,EAAE,SAAS,EAAE,sFAAsF,EAAE;IAC9G,KAAK,EAAE,EAAE,SAAS,EAAE,sFAAsF,EAAE;IAC5G,EAAE,EAAE,EAAE,SAAS,EAAE,yFAAyF,EAAE;IAC5G,IAAI,EAAE,EAAE,WAAW,EAAE,wGAAwG,EAAE;IAE/H,gGAAgG;IAChG,KAAK,EAAE,WAAW;IAClB,UAAU,EAAE,EAAE,WAAW,EAAE,oFAAoF,EAAE;IACjH,KAAK,EAAE,EAAE,WAAW,EAAE,yDAAyD,EAAE;IACjF,QAAQ,EAAE,WAAW;IACrB,YAAY,EAAE,EAAE,WAAW,EAAE,mKAAmK,EAAE;IAClM,WAAW,EAAE,EAAE,WAAW,EAAE,+DAA+D,EAAE;IAC7F,MAAM,EAAE,EAAE,WAAW,EAAE,2EAA2E,EAAE;IACpG,YAAY,EAAE,EAAE,WAAW,EAAE,iHAAiH,EAAE;IAChJ,SAAS,EAAE,EAAE,WAAW,EAAE,iEAAiE,EAAE;IAC7F,eAAe,EAAE,EAAE,WAAW,EAAE,wEAAwE,EAAE;IAC1G,IAAI,EAAE,EAAE,WAAW,EAAE,yEAAyE,EAAE;IAChG,cAAc,EAAE,EAAE,WAAW,EAAE,2CAA2C,EAAE;IAC5E,eAAe,EAAE,EAAE,SAAS,EAAE,2DAA2D,EAAE;IAC3F,UAAU,EAAE,EAAE,WAAW,EAAE,uDAAuD,EAAE;IACpF,SAAS,EAAE,EAAE,WAAW,EAAE,6CAA6C,EAAE;CAC1E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,118 @@
1
1
  {
2
2
  "name": "@open-everywhere/provider-google-chat",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.8.0",
4
+ "description": "Open Everywhere Google Chat provider — the agent as a Google Chat app: mention and DM wakes, threaded replies.",
5
+ "keywords": [
6
+ "agent",
7
+ "google-chat",
8
+ "google-workspace",
9
+ "chat",
10
+ "eve"
11
+ ],
12
+ "license": "Apache-2.0",
13
+ "type": "module",
14
+ "homepage": "https://github.com/open-everywhere/open-everywhere/tree/main/packages/providers/google-chat",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/open-everywhere/open-everywhere.git",
18
+ "directory": "packages/providers/google-chat"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/open-everywhere/open-everywhere/issues"
22
+ },
23
+ "engines": {
24
+ "node": ">=24"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "files": [
30
+ "agent",
31
+ "dist",
32
+ "tsconfig.json",
33
+ "tsconfig.build.json",
34
+ "LICENSE",
35
+ "NOTICE"
36
+ ],
37
+ "exports": {
38
+ "./package.json": "./package.json",
39
+ "./agent/channels/google-chat-auth.js": {
40
+ "types": "./dist/agent/channels/google-chat-auth.d.ts",
41
+ "default": "./dist/agent/channels/google-chat-auth.js"
42
+ },
43
+ "./agent/channels/google-chat-front.js": {
44
+ "types": "./dist/agent/channels/google-chat-front.d.ts",
45
+ "default": "./dist/agent/channels/google-chat-front.js"
46
+ },
47
+ "./agent/channels/google-chat-identity.js": {
48
+ "types": "./dist/agent/channels/google-chat-identity.d.ts",
49
+ "default": "./dist/agent/channels/google-chat-identity.js"
50
+ },
51
+ "./agent/channels/google-chat-message-ops.js": {
52
+ "types": "./dist/agent/channels/google-chat-message-ops.d.ts",
53
+ "default": "./dist/agent/channels/google-chat-message-ops.js"
54
+ },
55
+ "./agent/channels/google-chat-origin-codec.js": {
56
+ "types": "./dist/agent/channels/google-chat-origin-codec.d.ts",
57
+ "default": "./dist/agent/channels/google-chat-origin-codec.js"
58
+ },
59
+ "./agent/channels/google-chat-post-arm.js": {
60
+ "types": "./dist/agent/channels/google-chat-post-arm.d.ts",
61
+ "default": "./dist/agent/channels/google-chat-post-arm.js"
62
+ },
63
+ "./agent/channels/google-chat-rest.js": {
64
+ "types": "./dist/agent/channels/google-chat-rest.d.ts",
65
+ "default": "./dist/agent/channels/google-chat-rest.js"
66
+ },
67
+ "./agent/channels/google-chat.js": {
68
+ "types": "./dist/agent/channels/google-chat.d.ts",
69
+ "default": "./dist/agent/channels/google-chat.js"
70
+ },
71
+ "./agent/contributions.js": {
72
+ "types": "./dist/agent/contributions.d.ts",
73
+ "default": "./dist/agent/contributions.js"
74
+ },
75
+ "./agent/docs-generated.js": {
76
+ "types": "./dist/agent/docs-generated.d.ts",
77
+ "default": "./dist/agent/docs-generated.js"
78
+ },
79
+ "./agent/policy.js": {
80
+ "types": "./dist/agent/policy.d.ts",
81
+ "default": "./dist/agent/policy.js"
82
+ },
83
+ "./agent/provider-events.js": {
84
+ "types": "./dist/agent/provider-events.d.ts",
85
+ "default": "./dist/agent/provider-events.js"
86
+ },
87
+ "./agent/register.js": {
88
+ "types": "./dist/agent/register.d.ts",
89
+ "default": "./dist/agent/register.js"
90
+ },
91
+ "./agent/surface-parity.js": {
92
+ "types": "./dist/agent/surface-parity.d.ts",
93
+ "default": "./dist/agent/surface-parity.js"
94
+ }
95
+ },
96
+ "scripts": {
97
+ "build": "tsc -p tsconfig.build.json",
98
+ "prepack": "npm run build",
99
+ "typecheck": "tsc --noEmit -p tsconfig.json",
100
+ "test": "npm run test:chain",
101
+ "test:chain": "tsx ../../../scripts/chain/run-chain.ts",
102
+ "test:google-chat-auth": "NODE_NO_WARNINGS=1 tsx scripts/google-chat-auth-test.ts",
103
+ "test:google-chat-front": "NODE_NO_WARNINGS=1 tsx scripts/google-chat-front-test.ts",
104
+ "test:google-chat-post-arm": "NODE_NO_WARNINGS=1 tsx scripts/google-chat-post-arm-test.ts"
105
+ },
106
+ "dependencies": {
107
+ "@open-everywhere/core": "0.8.0",
108
+ "jose": "6.2.3"
109
+ },
110
+ "peerDependencies": {
111
+ "eve": "0.71.0"
112
+ },
113
+ "devDependencies": {
114
+ "@types/node": "latest",
115
+ "tsx": "latest",
116
+ "typescript": "latest"
117
+ }
118
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ // PUBLISH BUILD (OPE-406). See packages/core/tsconfig.build.json for the full rationale: the
3
+ // sibling tsconfig.json stays noEmit (it is the typecheck gate and covers scripts/** too); this
4
+ // config emits ONLY the published surface (agent/**) into dist/, because a registry install
5
+ // cannot execute raw TypeScript and "eve build" evaluates the authored agent modules.
6
+ "extends": "./tsconfig.json",
7
+ "compilerOptions": {
8
+ "noEmit": false,
9
+ // Incremental: these run from every pre-hook (pretypecheck/pretest/prebuild), so a no-op
10
+ // rebuild has to be near-free or the gate chain pays a full tsc on every invocation.
11
+ "incremental": true,
12
+ // OUTSIDE outDir on purpose: a tsbuildinfo left in dist/ gets swept up by the files
13
+ // allowlist and PUBLISHED (caught by the tarball listing, 2026-08-12).
14
+ "tsBuildInfoFile": "./.tsbuildinfo",
15
+ "declaration": true,
16
+ "declarationMap": true,
17
+ "sourceMap": true,
18
+ "outDir": "dist",
19
+ "rootDir": "."
20
+ },
21
+ "include": ["agent/**/*.ts"]
22
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2023"],
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "noEmit": true,
11
+ "resolveJsonModule": true,
12
+ "types": ["node"]
13
+ },
14
+ "include": ["agent/**/*.ts", "scripts/**/*.ts"]
15
+ }