API Reference
This reference is rendered from current signatures and docstrings by mkdocstrings. The public API inventory defines the deliberate stable import surface; conceptual behavior and Google mappings live in the task guides.
Core
Async, typed core event engine for Google Chat applications.
Dispatcher
Bases: Router
Root router and transport-independent event feed.
Source code in src/chattice/dispatcher/dispatcher.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | |
preview_capabilities
property
The immutable Developer Preview enrollment for typed routing.
feed_update(event, **context)
async
Route one domain event and return the handler result unchanged.
Source code in src/chattice/dispatcher/dispatcher.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
lifespan(*resources)
An async context manager starting resources in order and closing
them in reverse (partial-start rollback included). Plug it into
FastAPI via app.router.lifespan_context = dispatcher.lifespan(...).
Source code in src/chattice/dispatcher/dispatcher.py
83 84 85 86 87 88 | |
run_pubsub(subscription, *, bot=None, credentials=None, credentials_provider=None, max_concurrency=10, max_outstanding_messages=100, idempotency_storage=None, max_delivery_attempts=5, stop_event=None)
async
Streaming-pull Pub/Sub ingress: the long-lived subscriber mode.
Runs every delivery through THIS dispatcher's router/filter/
middleware/DI pipeline. Handler answers go outbound through
bot where semantics allow (text -> send_message, Card ->
update_message/send_message); Dialog answers are rejected with
CapabilityNotSupported (dialogs require the synchronous HTTP
transport). Requires the chattice[pubsub] extra.
Blocks until stop_event fires or SIGINT/SIGTERM; drains
in-flight handlers before returning.
Source code in src/chattice/dispatcher/dispatcher.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
Router
A named collection of observers, middleware, and child routers.
Source code in src/chattice/dispatcher/router.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
children
property
Child routers in deterministic inclusion order.
parent
property
The owning parent, or None for a detached/root router.
include_router(router)
Attach one detached router as a child.
Source code in src/chattice/dispatcher/router.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
Public dispatcher, router, and observer API.
Dispatcher
Bases: Router
Root router and transport-independent event feed.
Source code in src/chattice/dispatcher/dispatcher.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | |
preview_capabilities
property
The immutable Developer Preview enrollment for typed routing.
feed_update(event, **context)
async
Route one domain event and return the handler result unchanged.
Source code in src/chattice/dispatcher/dispatcher.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | |
lifespan(*resources)
An async context manager starting resources in order and closing
them in reverse (partial-start rollback included). Plug it into
FastAPI via app.router.lifespan_context = dispatcher.lifespan(...).
Source code in src/chattice/dispatcher/dispatcher.py
83 84 85 86 87 88 | |
run_pubsub(subscription, *, bot=None, credentials=None, credentials_provider=None, max_concurrency=10, max_outstanding_messages=100, idempotency_storage=None, max_delivery_attempts=5, stop_event=None)
async
Streaming-pull Pub/Sub ingress: the long-lived subscriber mode.
Runs every delivery through THIS dispatcher's router/filter/
middleware/DI pipeline. Handler answers go outbound through
bot where semantics allow (text -> send_message, Card ->
update_message/send_message); Dialog answers are rejected with
CapabilityNotSupported (dialogs require the synchronous HTTP
transport). Requires the chattice[pubsub] extra.
Blocks until stop_event fires or SIGINT/SIGTERM; drains
in-flight handlers before returning.
Source code in src/chattice/dispatcher/dispatcher.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
EventObserver
An ordered collection of handlers for one event category.
Source code in src/chattice/dispatcher/observer.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
filters
property
Return the common filters applied before handler filters.
handlers
property
Return a stable registration snapshot.
registered_names
property
Shortcut names registered on this observer (action names etc.).
__call__(*filters)
Create a handler-registration decorator.
Source code in src/chattice/dispatcher/observer.py
57 58 59 60 61 62 63 64 65 | |
filter(*filters)
Append common filters for every handler on this observer.
Source code in src/chattice/dispatcher/observer.py
53 54 55 | |
register(callback, *filters)
Register and return callback for programmatic use.
Source code in src/chattice/dispatcher/observer.py
45 46 47 48 49 50 51 | |
Lifespan
Ordered startup / reverse-order shutdown over async resources.
Source code in src/chattice/dispatcher/lifespan.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
LifespanResource
Bases: Protocol
A resource with ordered async startup and shutdown.
Source code in src/chattice/dispatcher/lifespan.py
25 26 27 28 29 30 | |
Router
A named collection of observers, middleware, and child routers.
Source code in src/chattice/dispatcher/router.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
children
property
Child routers in deterministic inclusion order.
parent
property
The owning parent, or None for a detached/root router.
include_router(router)
Attach one detached router as a child.
Source code in src/chattice/dispatcher/router.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
Public domain events.
ActionEvent
dataclass
Bases: Event
A named action with immutable application parameters.
Source code in src/chattice/events/action.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
function_name
property
Google's normalized invoked function with the compatibility name.
__post_init__()
Take a shallow immutable snapshot of action parameters.
Source code in src/chattice/events/action.py
38 39 40 | |
ActionSource
Bases: StrEnum
The Google Chat surface that produced a card action.
Source code in src/chattice/events/action.py
15 16 17 18 19 20 | |
AddedToSpaceEvent
dataclass
Bases: Event
The Chat app was added to a space.
Source code in src/chattice/events/space.py
10 11 12 13 14 | |
AppHomeEvent
dataclass
Bases: Event
A user opened the Chat app's Home tab.
Source code in src/chattice/events/app_home.py
13 14 15 16 17 | |
CommandEvent
dataclass
Bases: Event
A command identified by configured numeric ID and documented type.
Produced from BOTH wire families:
- slash commands arrive as MESSAGE events with
message.slashCommand + argumentText (source kind
SLASH_COMMAND);
- quick commands / message actions arrive as APP_COMMAND events
with appCommandMetadata (source kind QUICK_COMMAND;
MESSAGE_ACTION for message actions).
Source code in src/chattice/events/command.py
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
CommandKind
Bases: StrEnum
Google-native command families, independent of their wire envelope.
Source code in src/chattice/events/command.py
12 13 14 15 16 17 | |
DateInput
dataclass
A date represented by Google's lossless epoch-millisecond value.
Source code in src/chattice/events/form.py
17 18 19 20 21 | |
DateTimeInput
dataclass
A date/time input with the documented component-presence flags.
Source code in src/chattice/events/form.py
24 25 26 27 28 29 30 | |
DialogEventType
Bases: StrEnum
Stable documented Google Chat dialog interaction types.
Source code in src/chattice/events/common.py
9 10 11 12 13 14 | |
DialogMetadata
dataclass
Incoming dialog state without any response-building behavior.
Source code in src/chattice/events/common.py
17 18 19 20 21 22 | |
ErrorEvent
dataclass
Bases: Event
The original event and exception presented to an error observer.
Source code in src/chattice/events/error.py
10 11 12 13 14 15 16 | |
Event
dataclass
Base class for transport-independent domain events.
Source code in src/chattice/events/base.py
12 13 14 15 16 17 18 19 20 21 22 23 24 | |
FormInputs
dataclass
Bases: Mapping[str, FormValue]
Immutable mapping from widget names to typed submitted values.
Source code in src/chattice/events/form.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
FormSubmitEvent
dataclass
Bases: Event
A form submitted from App Home.
Source code in src/chattice/events/app_home.py
20 21 22 23 24 25 26 27 28 29 30 | |
MessageEvent
dataclass
Bases: Event
A normalized Chat message interaction.
text is Google's raw text; argument_text (when present) is the
documented mention-stripped body — route on it to handle
@MyApp ping as ping without a custom mention parser.
Source code in src/chattice/events/message.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
annotations
property
Lossless snapshots of Google's output-only annotations.
attachment_refs
property
Typed inbound attachment metadata (additive over attachments).
Distinguishes UPLOADED_CONTENT from DRIVE_FILE and exposes the
human-facing thumbnail/download links next to the programmatic
attachmentDataRef.resourceName download handle.
attachments
property
Lossless snapshots of Google's message.attachment entries.
is_private
property
Whether Google marks the message for a private message viewer.
is_silent
property
Whether Google suppressed push notifications for the message.
mentions
property
User-mention annotations, preserving ranges and mention metadata.
quote
property
Lossless quotedMessageMetadata snapshot, when present.
reaction_summaries
property
Lossless snapshots of Google's emoji reaction summaries.
reply(text=None, *, reply_option=None, request_id=None, message_id=None, timeout=None, accessory_widgets=None, card=None, notify=None, private_to=None, attachments=None, bot=None)
async
Reply in this message's known thread through the bound Bot.
Source code in src/chattice/events/message.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
MessageRef
dataclass
Minimal message identity exposed to ordinary handlers.
Source code in src/chattice/events/references.py
204 205 206 207 208 | |
RemovedFromSpaceEvent
dataclass
Bases: Event
The Chat app was removed from a space.
Source code in src/chattice/events/space.py
17 18 19 20 21 | |
SpaceRef
dataclass
Minimal Chat space reference.
space_type (DIRECT_MESSAGE / GROUP_CHAT / SPACE) and
single_user_bot_dm distinguish the personal bot DM (the Home tab
host space) from collaborative spaces — the Home DM
space must never be treated as a publish destination.
Source code in src/chattice/events/references.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
send(text=None, *, thread=None, reply_option=None, request_id=None, message_id=None, timeout=None, accessory_widgets=None, card=None, notify=None, private_to=None, attachments=None, bot=None)
async
Send through the bound Bot without fetching this space.
Source code in src/chattice/events/references.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
StringInput
dataclass
One or more text or selection values.
Source code in src/chattice/events/form.py
10 11 12 13 14 | |
ThreadRef
dataclass
Minimal Chat thread reference with an optional known parent space.
Source code in src/chattice/events/references.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |
send(text=None, *, space=None, reply_option=None, request_id=None, message_id=None, timeout=None, accessory_widgets=None, card=None, notify=None, private_to=None, attachments=None, bot=None)
async
Send in this thread through the bound Bot with zero fetches.
Source code in src/chattice/events/references.py
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |
TimeInput
dataclass
Wall-clock time components.
Source code in src/chattice/events/form.py
33 34 35 36 37 38 | |
TimeZone
dataclass
Locale-independent timezone metadata supplied by Google.
Source code in src/chattice/events/common.py
25 26 27 28 29 30 | |
UnknownEvent
dataclass
Bases: Event
An event whose external type is not understood by the framework.
Source code in src/chattice/events/unknown.py
10 11 12 13 14 15 | |
UnknownFormInput
dataclass
A future input variant retained without claiming its semantics.
Source code in src/chattice/events/form.py
41 42 43 44 45 46 47 48 49 | |
UserRef
dataclass
Stable user identity and optional presentation metadata.
Source code in src/chattice/events/references.py
88 89 90 91 92 93 94 | |
WidgetUpdatedEvent
dataclass
Bases: Event
A widget with an associated action was updated.
Source code in src/chattice/events/widget.py
13 14 15 16 17 18 19 20 21 22 23 | |
Public filtering API.
BaseFilter
Convenience base class for asynchronous custom filters.
Source code in src/chattice/filters/base.py
25 26 27 28 29 30 31 | |
Filter
Bases: Protocol
Structural protocol implemented by asynchronous custom filters.
Source code in src/chattice/filters/base.py
17 18 19 20 21 22 | |
MagicExpression
Bases: BaseFilter
Base class for immutable boolean expression nodes.
Source code in src/chattice/filters/magic.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | |
evaluate(event)
Evaluate this expression against an event.
Source code in src/chattice/filters/magic.py
32 33 34 | |
MagicField
dataclass
Bases: MagicExpression
A safely traversed event attribute/item path.
Source code in src/chattice/filters/magic.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
contains(value)
Match when the resolved field contains value.
Source code in src/chattice/filters/magic.py
81 82 83 | |
endswith(value)
Match when the resolved field ends with value.
Source code in src/chattice/filters/magic.py
89 90 91 | |
exists()
Match when the complete path can be resolved.
Source code in src/chattice/filters/magic.py
101 102 103 | |
in_(value)
Match when the resolved field is a member of value.
Source code in src/chattice/filters/magic.py
93 94 95 | |
is_(value)
Match by object identity.
Source code in src/chattice/filters/magic.py
97 98 99 | |
regexp(pattern, flags=0)
Match a string field with a Python regular expression.
Uses re.match semantics — the pattern must match FROM THE
START of the value. Accepts a pattern string (compiled once, at
filter construction) or a pre-compiled re.Pattern. Invalid
patterns raise ValueError at construction, never at
evaluation time. flags cannot be combined with a compiled
pattern. Missing fields and non-string values never match.
Do not wrap patterns in /.../ — this is Python regex syntax.
Source code in src/chattice/filters/magic.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
resolve(event)
Resolve this path, returning a private missing sentinel on absence.
Source code in src/chattice/filters/magic.py
135 136 137 138 139 140 141 142 143 144 145 146 | |
startswith(value)
Match when the resolved field starts with value.
Source code in src/chattice/filters/magic.py
85 86 87 | |
Transport-independent dispatch middleware.
BaseMiddleware
Convenience base class for asynchronous dispatch middleware.
Source code in src/chattice/middleware.py
26 27 28 29 30 31 32 33 34 35 | |
Middleware
Bases: Protocol
Structural protocol for asynchronous dispatch middleware.
Source code in src/chattice/middleware.py
15 16 17 18 19 20 21 22 23 | |
Actions, Cards, and Forms
Typed action data: a deterministic codec above Google action parameters.
Google card buttons carry action.function (the discriminator — used by
@router.action(...)) plus a flat parameters mapping of string
key/value pairs. ActionData turns those strings into typed Python
fields WITHOUT an aiogram-style packed callback string and WITHOUT a
registry: the action function name IS the discriminator.
Codec (deterministic, no eval):
- str stays as-is; int/float/bool/Enum encode to canonical strings;
- None (optional) fields are OMITTED from parameters and restored from
their default on decode;
- unknown parameters are ignored (forward compatibility with new Google
fields);
- malformed values raise ActionDataDecodeError on explicit decode and
make the filter NOT match (no partial state);
- documented system parameters (e.g. autocomplete_widget_query) are
never interpreted by the codec.
ActionData
Base class for typed action parameter models (dataclass subclasses).
Source code in src/chattice/actions.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | |
__init_subclass__(*, function=None, **kwargs)
Optionally bind the model to Google's action function discriminator.
Source code in src/chattice/actions.py
134 135 136 137 138 139 140 141 142 | |
filter()
classmethod
An async filter matching when parameters decode into this model.
On a match the decoded instance is injected into the handler
context under the name data:
@router.action("deploy.confirm", DeployAction.filter()) async def confirm(event: ActionEvent, data: DeployAction): ...
Source code in src/chattice/actions.py
185 186 187 188 189 190 191 192 193 194 195 | |
from_parameters(parameters)
classmethod
Decode Google action parameters into an instance.
Unknown parameters are ignored (forward compatibility). Missing optional fields fall back to their dataclass defaults; missing REQUIRED fields raise ActionDataDecodeError.
Source code in src/chattice/actions.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | |
to_parameters()
Encode the typed fields into Google action parameters.
Source code in src/chattice/actions.py
155 156 157 158 159 160 161 162 163 | |
ActionDataDecodeError
Bases: ValueError
Action parameters cannot be decoded into the typed model.
Source code in src/chattice/actions.py
48 49 | |
ActionDataFilter
Decode-based filter: returns {"data": instance} or False.
Source code in src/chattice/actions.py
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | |
Typed facade builders for Google Chat Cards v2.
AccessoryWidget
dataclass
A message accessory widget (button list).
Source code in src/chattice/cards/accessory.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
to_dict()
The documented camelCase JSON shape (message.accessoryWidgets entry).
Source code in src/chattice/cards/accessory.py
36 37 38 39 40 | |
Action
dataclass
An action invoked by a card widget (button click, form submit...).
Source code in src/chattice/cards/actions.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
from_proto(proto)
classmethod
Rebuild the facade from an SDK proto.
Source code in src/chattice/cards/actions.py
36 37 38 39 40 41 42 43 44 45 46 47 | |
to_proto()
Build the SDK Action proto (parameters stay strings).
Source code in src/chattice/cards/actions.py
24 25 26 27 28 29 30 31 32 33 34 | |
ActionStatus
dataclass
The outcome of a dialog submit, shown to the user.
Source code in src/chattice/cards/status.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
invalid(message)
classmethod
A validation failure shown to the user.
Source code in src/chattice/cards/status.py
29 30 31 32 | |
ok(message=None)
classmethod
A successful submit (optional success message).
Source code in src/chattice/cards/status.py
24 25 26 27 | |
to_dict()
Serialize to the documented actionStatus JSON.
Source code in src/chattice/cards/status.py
34 35 36 37 38 39 | |
ActionStatusCode
Bases: Enum
Documented ActionStatus.StatusCode values.
Source code in src/chattice/cards/status.py
10 11 12 13 14 | |
Button
dataclass
A clickable button: either an action or a link.
Source code in src/chattice/cards/widgets.py
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 | |
ButtonInteraction
Documented action.interaction values.
Source code in src/chattice/cards/widgets.py
237 238 239 240 | |
ButtonList
dataclass
A horizontal row of buttons.
Source code in src/chattice/cards/widgets.py
364 365 366 367 368 369 370 371 372 373 374 375 376 | |
ButtonType
Documented Button.type values (Google Chat apps only).
https://developers.google.com/workspace/chat/api/reference/rest/v1/cards#button
Source code in src/chattice/cards/widgets.py
265 266 267 268 269 270 271 272 273 274 | |
Card
dataclass
A Google Chat Cards v2 card.
Source code in src/chattice/cards/card.py
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | |
from_dict(data)
classmethod
Rebuild from Cards v2 JSON while preserving unknown fields.
Source code in src/chattice/cards/card.py
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | |
from_proto(proto)
classmethod
Rebuild the facade from an SDK proto.
Source code in src/chattice/cards/card.py
376 377 378 379 380 381 382 383 384 385 386 387 | |
to_dict()
Serialize to the documented camelCase Cards v2 JSON.
Source code in src/chattice/cards/card.py
330 331 332 333 334 335 336 337 | |
to_proto()
Build the SDK Card proto.
Source code in src/chattice/cards/card.py
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | |
CardHeader
dataclass
The card header.
Source code in src/chattice/cards/card.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
to_proto()
Build the header as a proto-plus dict (the SDK class is not exported).
Source code in src/chattice/cards/card.py
82 83 84 85 86 87 88 89 | |
DateTimePicker
dataclass
A date/time picker.
Source code in src/chattice/cards/widgets.py
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | |
Dialog
dataclass
A dialog body displayed to the user who triggered the interaction.
Source code in src/chattice/cards/dialog.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
to_dict()
Serialize to the JSON shape carried under dialogAction.dialog.
The Chat REST API nests the dialog under dialogAction.dialog,
so the payload is returned as {"dialog": {"body": ...}}.
Source code in src/chattice/cards/dialog.py
48 49 50 51 52 53 54 | |
to_proto()
Build the chat SDK Dialog proto.
Source code in src/chattice/cards/dialog.py
44 45 46 | |
Divider
dataclass
A horizontal divider between widgets.
Source code in src/chattice/cards/widgets.py
257 258 259 260 261 262 | |
Image
dataclass
A URL or lazily published local picture rendered inside a Card.
Card Image is a URL-based UI widget — the other Google media surface
(a local file uploaded as a Chat attachment) is
chattice.media.InputFile. from_path and from_bytes require
an AssetPublisher on the Bot that sends or updates the Card.
Source code in src/chattice/cards/widgets.py
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
from_bytes(data, *, filename, content_type=None, namespace=None, alt_text=None, on_click=None)
classmethod
Build an Image from an immutable snapshot of generated bytes.
Source code in src/chattice/cards/widgets.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | |
from_path(path, *, filename=None, content_type=None, namespace=None, alt_text=None, on_click=None)
classmethod
Build a lazy local Image without reading the file.
Source code in src/chattice/cards/widgets.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | |
from_url(image_url, *, alt_text=None, on_click=None)
classmethod
Build an Image from an already published HTTPS URL.
Source code in src/chattice/cards/widgets.py
138 139 140 141 142 143 144 145 146 147 | |
to_proto()
Build the SDK Image proto.
Source code in src/chattice/cards/widgets.py
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | |
OpenLink
dataclass
Opens a URL in a browser.
Source code in src/chattice/cards/actions.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
from_proto(proto)
classmethod
Rebuild the facade from an SDK proto.
Source code in src/chattice/cards/actions.py
64 65 66 67 | |
to_proto()
Build the SDK OpenLink proto.
Source code in src/chattice/cards/actions.py
57 58 59 60 61 62 | |
RawWidget
dataclass
An arbitrary Cards v2 widget as documented camelCase JSON.
The payload is deep-snapshotted at construction — mutating the
caller's mapping (including nested values) afterwards cannot change
the widget, and the snapshot is what to_dict returns.
Source code in src/chattice/cards/raw.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
to_dict()
The documented camelCase widget JSON (lossless snapshot).
Source code in src/chattice/cards/raw.py
53 54 55 | |
Section
dataclass
A card section: optional header plus a widget list.
Source code in src/chattice/cards/card.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
from_proto(proto)
classmethod
Rebuild the facade from an SDK Section proto (oneof dispatch).
Unsupported SDK widget kinds become RawWidget instead of raising
or being silently dropped.
Source code in src/chattice/cards/card.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
to_proto_dict()
Build the section as a proto-plus dict (oneof dispatch).
Source code in src/chattice/cards/card.py
117 118 119 120 121 122 123 | |
SelectionInput
dataclass
A selection field.
NOTE: the installed SDK proto (google-apps-card 0.7.0) has no default- selection field, so the facade models exactly what the SDK supports.
Source code in src/chattice/cards/widgets.py
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 | |
TextInput
dataclass
A text input field.
Source code in src/chattice/cards/widgets.py
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | |
TextInputType
Bases: Enum
Documented Validation inputType values (SDK enum mirror).
Source code in src/chattice/cards/validation.py
16 17 18 19 20 21 22 23 24 25 26 27 | |
to_proto()
Map to the SDK Validation.InputType enum member.
Source code in src/chattice/cards/validation.py
25 26 27 | |
TextParagraph
dataclass
A paragraph of text.
Source code in src/chattice/cards/widgets.py
243 244 245 246 247 248 249 250 251 252 253 254 | |
Validation
dataclass
Validation rules for a form input.
Source code in src/chattice/cards/validation.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
to_dict()
Serialize to the documented camelCase JSON.
Source code in src/chattice/cards/validation.py
46 47 48 | |
to_proto()
Build the SDK Validation proto.
Source code in src/chattice/cards/validation.py
37 38 39 40 41 42 43 44 | |
Typed form decoding: opt-in schemas above the existing typed FormInputs.
Google's common.formInputs values are ALREADY typed by the adapter
(StringInput / DateInput / DateTimeInput / TimeInput / UnknownFormInput).
FormModel adds an opt-in dataclass schema that maps widget names onto
those typed values — no string flattening, no mandatory pydantic domain
model, and no automatic translation of decode errors into dialog errors
(Google's error response rules depend on the surface; the application
decides how to answer).
Usage:
@dataclass
class ContactForm(FormModel):
name: StringInput
birthday: DateInput | None = None
@router.dialog_submit(ContactForm.filter())
async def submit(event: ActionEvent, form: ContactForm): ...
On a match the decoded instance is injected under the name form.
FormDecodeError
Bases: ValueError
Form inputs cannot be decoded into the typed model.
Source code in src/chattice/forms.py
51 52 | |
FormFilter
Decode-based filter: returns {"form": instance} or False.
Accepts the full event union that owns typed form_inputs —
dialog ActionEvent AND App Home FormSubmitEvent — so the
advertised form logic is reusable on App Home submits.
Source code in src/chattice/forms.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
FormModel
Base class for typed form-input models (dataclass subclasses).
Source code in src/chattice/forms.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | |
filter()
classmethod
An async filter matching when form inputs decode into this model.
On a match the decoded instance is injected into the handler
context under the name form.
Source code in src/chattice/forms.py
126 127 128 129 130 131 132 133 | |
from_form_inputs(inputs)
classmethod
Decode typed form inputs into an instance.
Missing optional fields fall back to their dataclass defaults; missing required fields raise FormDecodeError. A present value of the wrong input kind (e.g. DateInput where StringInput was declared) raises FormDecodeError.
Source code in src/chattice/forms.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
Authentication, capabilities, and outbound client
Storage-agnostic publication contract for local Card assets.
AssetPublisher
Bases: Protocol
Publish bytes and return an absolute HTTPS URL for a Card Image.
Source code in src/chattice/assets.py
8 9 10 11 12 13 14 15 16 17 18 19 20 | |
publish(data, *, filename, content_type, namespace=None)
async
Publish one immutable byte snapshot.
Source code in src/chattice/assets.py
11 12 13 14 15 16 17 18 19 20 | |
Outgoing authentication providers (app / user modes).
AuthMode
Bases: Enum
The outgoing authentication identity class.
Source code in src/chattice/auth/providers.py
20 21 22 23 24 25 | |
CredentialsProvider
Bases: Protocol
Callable returning Google credentials valid at call time.
Source code in src/chattice/auth/providers.py
28 29 30 31 32 33 | |
__call__()
Return credentials valid at call time.
Source code in src/chattice/auth/providers.py
31 32 33 | |
DelegatedUserCredentialsProvider
dataclass
User-auth provider via Google Workspace Domain-Wide Delegation.
A service account granted domain-wide delegation impersonates a
Workspace user through with_subject; Google treats the resulting
credentials as USER authentication (media.upload, user-scoped
operations) without per-user consent flows. ONE service-account JSON
therefore serves both identities of a dual-identity Bot: the same
file supplies the app provider directly and this provider with a
subject. Requires the Workspace administrator to configure the
delegation and OAuth scopes.
Source code in src/chattice/auth/providers.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
from_service_account_file(path, subject, *, scopes=None)
classmethod
Build from a service-account JSON file and a delegated subject.
Source code in src/chattice/auth/providers.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | |
ServiceAccountCredentialsProvider
dataclass
App-auth provider: lazy service-account credentials.
The JSON file/info is not read at construction — only when the provider is called (each call re-reads; the Bot calls it once).
Source code in src/chattice/auth/providers.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | |
from_service_account_file(path, scopes=None)
classmethod
Build from a service-account JSON file path (lazily read).
Source code in src/chattice/auth/providers.py
70 71 72 73 74 75 76 77 78 | |
from_service_account_info(info, scopes=None)
classmethod
Build from an in-memory service-account info mapping.
Source code in src/chattice/auth/providers.py
80 81 82 83 84 85 86 87 88 | |
UserCredentialsProvider
dataclass
User-auth provider: authorized-user credentials with lazy refresh.
Token storage and OAuth code acquisition belong to the application. The refresh happens synchronously at call time (once, at lazy client creation in Bot); subsequent refreshes are handled inside the SDK.
Source code in src/chattice/auth/providers.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
Capability model: response channel, outbound operations, preview features.
AuthPath
dataclass
One identity-specific, any-of OAuth scope rule.
identity: the credential identity class (APP or USER). any_scope: any one of these scopes makes the path admissible. variant: execution variant; ADMIN adds the request_flag, IMPORT selects import scopes. request_flag: optional wire flag sent with the request (e.g. "use_admin_access").
Source code in src/chattice/capabilities/operations.py
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
CapabilityNotSupported
Bases: RuntimeError
An operation was attempted without its required capability.
Source code in src/chattice/capabilities/matrix.py
58 59 | |
ExecutionVariant
Bases: StrEnum
Execution variant of an identity for an operation.
Source code in src/chattice/capabilities/operations.py
68 69 70 71 72 73 | |
Operation
Bases: StrEnum
A Google Chat outbound operation.
Source code in src/chattice/capabilities/operations.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
OperationRegistry
Lookup and local preflight over OperationSpecs.
Source code in src/chattice/capabilities/registry.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
preflight(operation, *, identity, scopes=None, variant=ExecutionVariant.NORMAL)
Return whether the local configuration allows an attempt.
Source code in src/chattice/capabilities/registry.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
require(operation, *, identity, scopes=None, variant=ExecutionVariant.NORMAL)
Raise CapabilityNotSupported when preflight fails.
Source code in src/chattice/capabilities/registry.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
OperationSpec
dataclass
Declarative local-preflight description of one operation.
google_method is the discovery-document method id used by the CI
registry verifier. paginated marks SDK pager-backed methods;
preview marks Developer Preview surface (explicit opt-in via
Bot(enable_preview=True)); retry_policy is a human-readable
label — the executor never runs its own retry loop, it passes the
per-call RequestConfig.retry through to GAPIC.
Source code in src/chattice/capabilities/operations.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
PreviewCapabilities
Explicit enrollment set for typed Developer Preview routing.
Source code in src/chattice/capabilities/matrix.py
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
PreviewFeature
Bases: Enum
Developer Preview Google features (stability flags, not auth).
Sources: Google Chat release notes. These exist so documentation and code reference ONE list of preview surfaces.
Source code in src/chattice/capabilities/matrix.py
159 160 161 162 163 164 165 166 167 168 169 170 171 | |
ResponseCapabilities
An immutable response-channel capability set with require() guards.
Source code in src/chattice/capabilities/matrix.py
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
require(capability)
Raise CapabilityNotSupported when the capability is missing.
Source code in src/chattice/capabilities/matrix.py
110 111 112 113 114 115 116 | |
resolve(*, transport='http', event=None)
classmethod
Resolve the response-channel capabilities for a transport + event.
HTTP provides the sync response channel and dialogs; Pub/Sub push provides NO response channel (ack-only). Event-specific response rules are derived from the concrete event, never guessed.
Source code in src/chattice/capabilities/matrix.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | |
ResponseCapability
Bases: Enum
What the synchronous ingress response channel can do.
Source code in src/chattice/capabilities/matrix.py
62 63 64 65 66 67 68 69 70 | |
can_open_dialog(event)
Return whether an event may open a dialog.
Commands always can; actions only when Google delivered them WITH REQUEST_DIALOG metadata. SUBMIT/CANCEL actions cannot return a new dialog, and a plain Message cannot open one either.
Source code in src/chattice/capabilities/matrix.py
41 42 43 44 45 46 47 48 49 50 51 52 | |
scopes(*names)
Build fully qualified Google OAuth scopes from short names.
Source code in src/chattice/capabilities/operations.py
27 28 29 | |
High-level async Chat API client.
Bot
Authenticated outgoing Google Chat operations.
The SDK client is created lazily on the first call so that Bot() can be constructed before credentials are available (e.g. in app factories).
Source code in src/chattice/client/bot.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 | |
app
property
Resource clients bound to the APP identity.
auth_mode
property
The outgoing auth mode: explicit, or classified from credentials.
Synchronous classification; the async Bot methods use
_auth_mode_async so blocking providers never run on the loop.
raw
property
Async raw SDK access split by identity.
user
property
Resource clients bound to the USER identity.
close()
async
Close the underlying SDK transport (idempotent, awaitable).
Close is linearizable with initialization. Once close
begins, NO client may be published; if construction already
completed, its transport is closed exactly once before close
returns. The async gRPC transport's closer is itself awaitable —
it is AWAITED here (a plain sync call would leak the channel).
Safe to call multiple times; after close the client must not be
used. Also available as async with Bot(...).
Source code in src/chattice/client/bot.py
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |
warmup(*, app=True, user=False)
async
Resolve credentials and build clients before the first event.
May resolve credentials and prepare clients/transports; never performs business API calls. Useful to move the slow first outbound request (credential resolution, IAM, gRPC channel) into startup.
Source code in src/chattice/client/bot.py
267 268 269 270 271 272 273 274 275 276 277 278 | |
ChatAPIError
Bases: Exception
An outgoing Chat API call failed.
SDK failures preserve the original error as cause (raise with
from error); framework-raised errors (e.g. missing credentials)
have no SDK cause, and the properties below return None for them.
Source code in src/chattice/client/errors.py
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
cause
property
The original SDK error, or None for framework-raised errors.
code
property
HTTP status code carried by the SDK error, or None.
details
property
Error details carried by the SDK error, or None.
ChatAlreadyExistsError
Bases: ChatAPIError
The requested resource already exists (409 / already-exists).
Source code in src/chattice/client/errors.py
46 47 | |
ChatInvalidArgumentError
Bases: ChatAPIError
The request was rejected by validation.
Source code in src/chattice/client/errors.py
54 55 | |
ChatNotFoundError
Bases: ChatAPIError
The target resource does not exist.
Source code in src/chattice/client/errors.py
42 43 | |
ChatPermissionDeniedError
Bases: ChatAPIError
The app lacks permission (e.g. not a member of the space).
Source code in src/chattice/client/errors.py
50 51 | |
ChatRateLimitError
Bases: ChatAPIError
Quota exhausted or 429 response; retry only per the app's policy.
Source code in src/chattice/client/errors.py
58 59 | |
ChatServiceUnavailableError
Bases: ChatAPIError
Transient Chat API unavailability (5xx).
DeadlineExceeded (a GatewayTimeout subclass) also maps here.
Source code in src/chattice/client/errors.py
62 63 64 65 66 | |
ChatUnauthenticatedError
Bases: ChatAPIError
The credentials were rejected.
Source code in src/chattice/client/errors.py
69 70 | |
CredentialsProvider
Bases: Protocol
Callable returning Google credentials valid at call time.
Source code in src/chattice/auth/providers.py
28 29 30 31 32 33 | |
__call__()
Return credentials valid at call time.
Source code in src/chattice/auth/providers.py
31 32 33 | |
RawClients
Explicit raw client access: APP or USER identity.
Each accessor builds and serves exactly the identity it names, so dual-auth-sensitive operations never depend on an implicit primary identity.
Source code in src/chattice/client/bot.py
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
app()
async
The raw APP-authenticated Chat client.
Source code in src/chattice/client/bot.py
111 112 113 | |
user()
async
The raw USER-authenticated Chat client.
Raises CapabilityNotSupported when no USER credentials are
configured on the Bot.
Source code in src/chattice/client/bot.py
115 116 117 118 119 120 121 | |
wrap_api_error(error)
Map an SDK error to its framework subtype (raise the result with 'from').
Source code in src/chattice/client/errors.py
106 107 108 109 110 111 112 113 114 115 116 117 | |
State and reliability
Finite-state machine primitives.
BaseStorage
Bases: Protocol
Storage contract implemented by MemoryStorage and RedisStorage.
Source code in src/chattice/fsm/storage.py
58 59 60 61 62 63 64 65 66 67 68 | |
BaseStorageFromRecord
Bases: BaseStorage
Serve the six-method BaseStorage contract over a record store.
Transitions use compare-and-set; a concurrent modification raises FSMRecordConflict instead of silently losing data.
Source code in src/chattice/fsm/record.py
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | |
update_data(key, partial)
async
Read/merge/compare-and-set retry loop: concurrent updates never silently overwrite each other (a conflict retries on the new revision instead of losing fields).
Source code in src/chattice/fsm/record.py
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | |
FSMContext
Bound to (storage, key) for one event; injected by the dispatcher.
Source code in src/chattice/fsm/context.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
FSMError
Bases: RuntimeError
FSM operation attempted without a derivable storage key.
Source code in src/chattice/fsm/context.py
14 15 | |
FSMRecord
dataclass
One FSM state+data snapshot under a StorageKey.
data is validated against the recursive JSONValue contract and
defensively copied (MappingProxyType) so callers cannot mutate
stored state without a compare-and-set.
Source code in src/chattice/fsm/record.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
FSMRecordConflict
Bases: RuntimeError
A compare-and-set failed: the stored revision differs from expected.
Source code in src/chattice/fsm/record.py
48 49 | |
FSMRecordStorage
Bases: Protocol
Atomic record contract (optional storage).
Source code in src/chattice/fsm/record.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
compare_and_set(key, expected_revision, replacement)
async
Atomically store replacement iff the current record has
expected_revision (0 = no record). Returns the stored record
with its revision bumped; raises FSMRecordConflict otherwise.
Source code in src/chattice/fsm/record.py
104 105 106 107 108 109 110 111 112 113 | |
get_record(key)
async
Read the record; an expired record reads as None (lazy TTL).
Source code in src/chattice/fsm/record.py
100 101 102 | |
FSMStrategy
Bases: Enum
How the storage key is derived from an event.
Source code in src/chattice/fsm/storage.py
21 22 23 24 25 26 | |
MemoryFSMRecordStorage
In-process record storage: CAS under a per-key asyncio lock.
Source code in src/chattice/fsm/record.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
MemoryStorage
In-process storage.
Concurrency guarantees are process-local: per-key asyncio locks serialize writes within one event loop; nothing here survives across processes.
Source code in src/chattice/fsm/storage.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | |
RedisFSMRecordStorage
Redis record storage: CAS via WATCH/MULTI, whole-record TTL (PX).
One JSON document per StorageKey; compare-and-set is optimistic with retry on watch conflicts (no distributed lock held across I/O).
Source code in src/chattice/fsm/record.py
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | |
aclose()
async
Close the internally created client (idempotent).
An injected client is never closed by the storage.
Source code in src/chattice/fsm/record.py
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | |
RedisStorage
FSM storage over redis.asyncio with a namespaced key layout.
Source code in src/chattice/fsm/redis.py
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | |
aclose()
async
Close the internally created client (idempotent).
An injected client is never closed by the storage.
Source code in src/chattice/fsm/redis.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
State
A named workflow state.
Members of a StatesGroup get <GroupName>:<attr_name> string keys;
standalone states may pass an explicit key.
Source code in src/chattice/fsm/states.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
state
property
The string key used by storages and StateFilter.
StateFilter
Bases: BaseFilter
Matches when the event's current FSM state is one of the given states.
An empty filter matches ANY non-None state. Without an FSM context in the filter context (dispatcher configured without fsm_storage) it never matches.
Source code in src/chattice/fsm/filter.py
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
StatesGroup
Base class for workflow state groups.
Source code in src/chattice/fsm/states.py
54 55 56 57 | |
StorageKey
dataclass
The composite identity an FSM record is stored under.
Source code in src/chattice/fsm/storage.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
build(event, strategy)
classmethod
Derive the key from the event refs; None when refs are missing.
Source code in src/chattice/fsm/storage.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
Owner-safe push idempotency: claimed(owner, lease) -> completed.
A TTL presence bit can acknowledge work that never completed. The contract is a small state machine:
claim(key, owner, lease) -> FIRST | COMPLETED | ACTIVE
complete(key, owner) -> mark done (keeps absorbing duplicates)
release(key, owner) -> drop the claim (only the OWNER may)
renew(key, owner, lease) -> extend a long handler's lease
A second delivery that observes another owner's ACTIVE claim answers 429 ("still processing") so Pub/Sub redelivers later — it is never acknowledged as a completed duplicate. Keys must be namespaced by the caller (subscription/topic + messageId): Google message IDs are unique per topic only.
Memory is process-local; Redis stores one JSON document per key with claim via SET NX and owner-checked release via WATCH/MULTI.
ClaimResult
Bases: Enum
Outcome of claim(): who owns the delivery now.
Source code in src/chattice/idempotency.py
46 47 48 49 50 51 | |
IdempotencyStorage
Bases: Protocol
Owner-safe claim/complete/release contract for push dedupe.
Source code in src/chattice/idempotency.py
59 60 61 62 63 64 65 66 67 68 69 70 | |
MemoryIdempotencyStorage
In-process state machine (per-key asyncio locks).
Source code in src/chattice/idempotency.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
RedisIdempotencyStorage
Redis state machine: SET NX claim, owner-checked WATCH/MULTI ops.
Source code in src/chattice/idempotency.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | |
aclose()
async
Close the internally created client (idempotent).
An injected client is never closed by the storage.
Source code in src/chattice/idempotency.py
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | |
new_owner()
A fresh owner token for one delivery attempt.
Source code in src/chattice/idempotency.py
54 55 56 | |
Extension hooks for observability (application-owned integrations).
The framework ships NO OTel dependency; applications implement these hooks and bridge to their tracer of choice (see docs/architecture/observability.md).
The optional hooks (everything after after_event) are no-ops in the
protocol: an implementation may provide any subset without breaking the
structural contract. Hooks receive the original event and dispatch context,
including access to raw payloads. Applications choose which fields to export.
ObservabilityHooks
Bases: Protocol
Called around each feed_update routing pass.
Source code in src/chattice/observability.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
after_handler(event, data, handler, result)
async
Called after the selected handler returns.
Source code in src/chattice/observability.py
52 53 54 55 | |
after_outbound(event, operation)
async
Called after an outbound Google answer completes.
Source code in src/chattice/observability.py
60 61 | |
before_handler(event, data, handler)
async
Called before the selected handler invokes; handler is the
qualified callback name.
Source code in src/chattice/observability.py
46 47 48 49 50 | |
before_outbound(event, operation)
async
Called before an outbound Google answer (send/update).
Source code in src/chattice/observability.py
57 58 | |
delivery_acked(message_id, event)
async
Called after a Pub/Sub delivery is ACKed.
Source code in src/chattice/observability.py
63 64 | |
delivery_nacked(message_id, event)
async
Called after a Pub/Sub delivery is NACKed.
Source code in src/chattice/observability.py
66 67 | |
RuntimeDiagnostics
dataclass
Configurable thresholds for runtime diagnostics.
None disables the corresponding warning.
Source code in src/chattice/observability.py
20 21 22 23 24 25 26 27 28 | |
Transports and integrations
HTTP interaction transport core.
DoubleResponseError
Bases: HTTPInteractionError
The synchronous response was already set for this interaction.
Source code in src/chattice/transports/http/errors.py
14 15 | |
GoogleTokenVerifier
Verify Chat bearer tokens using google-auth and the documented flows.
One audience string supports both documented Authentication Audience strategies: the HTTP endpoint URL (OIDC ID token via verify_oauth2_token) or the project number (self-signed JWT via the Chat service-account certificates). Signature, exp, aud, and kid-based certificate selection are handled by google-auth; the Google Chat identity (email) and issuer are checked explicitly per strategy (the official samples do the same). Fail-closed: any verification failure answers VerificationError, never a bypass.
Source code in src/chattice/transports/http/verifier.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
HTTPInteractionAdapter
Framework-neutral adapter: HTTP request snapshot -> domain event.
Source code in src/chattice/transports/http/adapter.py
39 40 41 42 43 44 | |
parse(request)
Decode the request body and parse it into a domain event.
Source code in src/chattice/transports/http/adapter.py
42 43 44 | |
HTTPInteractionError
Bases: ValueError
Base class for HTTP transport failures.
Source code in src/chattice/transports/http/errors.py
6 7 | |
IncomingRequest
dataclass
Immutable snapshot of an inbound interaction HTTP request.
Source code in src/chattice/transports/http/request.py
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
header(name)
Case-insensitive header lookup.
Source code in src/chattice/transports/http/request.py
27 28 29 30 31 32 33 | |
json()
Decode the body as a JSON object (lazy, one call per request).
Source code in src/chattice/transports/http/request.py
35 36 37 38 39 40 41 42 43 | |
IncomingRequestVerifier
Bases: Protocol
Contract: prove that an inbound request genuinely came from Google Chat.
Source code in src/chattice/transports/http/verifier.py
37 38 39 40 41 42 | |
verify(request)
Raise VerificationError when the request cannot be verified.
Source code in src/chattice/transports/http/verifier.py
40 41 42 | |
InteractionContext
dataclass
HTTP transport-only request/response state available through DI.
The normalized domain event and its response capabilities are separate DI values; this type deliberately does not claim to be a canonical entity or resource context.
Source code in src/chattice/transports/http/adapter.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
remaining
property
Time left before the documented sync response deadline.
InteractionResponse
dataclass
Request-scoped mutable response plan; guards against double responses.
This is intentionally not frozen: it is per-request mutable state, never shared between requests.
Source code in src/chattice/transports/http/response.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
respond(payload)
Set the synchronous response payload exactly once.
Source code in src/chattice/transports/http/response.py
30 31 32 33 34 35 36 37 | |
MockVerifier
Accepts (or rejects) any request; for tests and local development only.
Source code in src/chattice/transports/http/verifier.py
139 140 141 142 143 144 145 146 147 | |
RawInteractionResponse
dataclass
Explicit raw-response escape hatch: an arbitrary response mapping.
Still validated against event/channel invariants (e.g. a REMOVED_FROM_SPACE event can never receive a response) — only the payload shape is the caller's responsibility.
Source code in src/chattice/transports/http/response.py
40 41 42 43 44 45 46 47 48 49 | |
RequestConfigResponse
dataclass
Typed REQUEST_CONFIG response: ask the user to open an auth URL.
The missing typed DX for a wire shape previously reachable only through RawInteractionResponse.
Source code in src/chattice/transports/http/response.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | |
ResponseState
Bases: Enum
Whether the synchronous response has already been produced.
Source code in src/chattice/transports/http/response.py
12 13 14 15 16 | |
VerificationError
Bases: HTTPInteractionError
Incoming request verification failed.
Source code in src/chattice/transports/http/errors.py
10 11 | |
WidgetAutocomplete
dataclass
Typed UPDATE_WIDGET response: autocomplete suggestions for a widget.
Google's UPDATE_WIDGET response type answers a WIDGET_UPDATED autocomplete query. Each suggestion becomes a SelectionItem with the given text.
Source code in src/chattice/transports/http/response.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | |
Pub/Sub push ingress: envelope -> interaction event, push verification.
The documented push envelope wraps the Chat interaction JSON in message.data (base64). Delivery has NO synchronous response channel — the push router acks with 2xx and ignores handler return values.
Authenticated Pub/Sub push sends an OIDC ID token from the configured
push service account in the Authorization header
(https://cloud.google.com/pubsub/docs/authenticate-push-subscriptions);
GooglePubSubVerifier checks signature, audience, issuer, and the
expected service-account email.
GooglePubSubVerifier
dataclass
Verify authenticated Pub/Sub push requests.
The configured push endpoint receives an OIDC ID token issued for the
Pub/Sub push service account. Signature/exp/aud are validated by
google-auth's verify_token; the issuer must be accounts.google.com and
the token's email claim must match service_account_email (REQUIRED:
an audience match alone does not bind the publisher identity) with
email_verified true.
Source code in src/chattice/transports/pubsub.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | |
MockPubSubVerifier
Accepts (or rejects) any push request; tests and local dev only.
Source code in src/chattice/transports/pubsub.py
151 152 153 154 155 156 157 158 159 | |
PubSubEnvelopeError
Bases: ValueError
The Pub/Sub push envelope is malformed.
Source code in src/chattice/transports/pubsub.py
45 46 | |
PubSubPushAdapter
Decodes a documented Pub/Sub push envelope into a domain event.
Source code in src/chattice/transports/pubsub.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | |
parse_envelope(payload)
Validate the envelope, decode message.data, parse the interaction.
Source code in src/chattice/transports/pubsub.py
82 83 84 85 86 87 88 89 90 91 92 93 | |
PubSubPushVerifier
Bases: Protocol
Contract: prove that an inbound push genuinely came from Pub/Sub.
Source code in src/chattice/transports/pubsub.py
96 97 98 99 100 101 | |
verify(request)
Raise VerificationError when the request cannot be verified.
Source code in src/chattice/transports/pubsub.py
99 100 101 | |
decode_message_data(payload)
Decode a Pub/Sub push envelope into its inner JSON mapping.
Returns None when the payload is not a push envelope (e.g. a raw CloudEvent delivered to an HTTPS endpoint). Raises PubSubEnvelopeError for a malformed envelope.
Source code in src/chattice/transports/pubsub.py
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
FastAPI integration (optional extra chattice[fastapi]).
create_chat_router(dispatcher, verifier, *, path='/')
Build a POST route wiring Google Chat interactions into the dispatcher.
Works under FastAPI via app.include_router(...) and under plain Starlette via Starlette(routes=chat_router.routes).
Source code in src/chattice/integrations/fastapi/router.py
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | |
create_pubsub_router(dispatcher, *, path='/pubsub', idempotency_storage=None, verifier=None, allow_unverified=False)
Push endpoint for Pub/Sub-delivered interactions (ack-only, 204).
Secure by default: pass verifier= (authenticated push) or an
explicit allow_unverified=True (test/local environments). Without
either the router refuses to be created.
Source code in src/chattice/integrations/fastapi/router.py
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | |
create_workspace_events_router(dispatcher, *, path='/workspace-events', idempotency_storage=None, verifier=None, allow_unverified=False)
Push endpoint for Workspace Events (ack-only, 204).
Google delivers Workspace Events exclusively as Pub/Sub push messages:
the CloudEvents context attributes travel in message.attributes
(ce-* keys) and message.data (base64) holds the event resource
data. A structured CloudEvent POSTed directly is NOT a supported
delivery mode and is rejected.
idempotency_storage dedupes redeliveries by the Pub/Sub message id
with the same claim/complete/release semantics as the classic push
router: a failed dispatch releases the claim so a redelivery
re-dispatches.
Secure by default: pass verifier= or an explicit
allow_unverified=True.
Source code in src/chattice/integrations/fastapi/router.py
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | |
Google Cloud Storage AssetPublisher (optional extra chattice[gcs]).
GCSAssetPublisher
Publish non-sensitive Card images to a preconfigured GCS bucket.
The bucket or public_url_base must already expose uploaded objects
over anonymous HTTPS. This integration never changes bucket IAM. Cache
metadata is opt-in and never grants public access to an object.
Source code in src/chattice/integrations/gcs/__init__.py
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
publish(data, *, filename, content_type, namespace=None)
async
Upload bytes off the event loop and return their public HTTPS URL.
Source code in src/chattice/integrations/gcs/__init__.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
Workspace Events
Workspace Events ingress family (separate from Chat interactions).
EventsDispatcher
Bases: EventsRouter
Independent feed for Workspace Events; never accepts interactions.
Source code in src/chattice/workspace_events/runtime.py
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | |
EventsRouter
Router tree dedicated to Workspace resource-change events.
Source code in src/chattice/workspace_events/runtime.py
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | |
WorkspaceEvent
dataclass
A Workspace resource-change event (NOT a Chat interaction).
Source code in src/chattice/workspace_events/parser.py
73 74 75 76 77 78 79 80 81 82 83 84 | |
WorkspaceEventError
Bases: ValueError
The CloudEvent payload is malformed for Workspace Events.
Source code in src/chattice/workspace_events/envelope.py
11 12 | |
WorkspaceEventType
Documented Chat Workspace event type strings (forward-compatible).
Sources: https://developers.google.com/workspace/events/guides/events-chat and https://developers.google.com/workspace/events/guides/events-lifecycle (including batch event types).
Source code in src/chattice/workspace_events/parser.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
parse_workspace_envelope(payload)
Parse an official Pub/Sub push envelope for Workspace Events.
Google's binding (https://developers.google.com/workspace/events):
the CloudEvents context attributes travel in message.attributes
(ce-id, ce-source, ce-specversion, ce-time,
ce-type, optional ce-subject/ce-datacontenttype), while
base64-decoded message.data contains ONLY the event resource data
(or resource names for names-only payloads). The full envelope is
preserved in .raw.
Source code in src/chattice/workspace_events/parser.py
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | |
parse_workspace_event(payload)
Parse a CloudEvents 1.0 Workspace event into a WorkspaceEvent.
Accepts a STRUCTURED CloudEvent (all fields at the top level). This form
is for offline use (fixtures, replays, tests) — Google delivers Workspace
Events exclusively through Pub/Sub push messages; see
:func:parse_workspace_envelope for the wire format.
Source code in src/chattice/workspace_events/parser.py
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | |
Experimental namespace
chattice.experimental carries optional integration contracts (e.g.
chattice.experimental.ai). The namespace has NO compatibility
promise; use it explicitly and pin the package version.
Experimental (Developer Preview) features live here and ONLY here.
Core flows must never depend on this namespace; APIs in this package may change or disappear without notice. See docs/architecture/capabilities.md.
Testing
Testing toolkit: mocks, factories, assertions (first-party testing toolkit use).
EventFactory
Static builders producing frozen domain events directly.
user/space accept either a reference or a Google resource name
string (e.g. "users/user-a"); None uses the test defaults.
Source code in src/chattice/testing/event_factory.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
action(name, parameters=None, *, form_inputs=None, user=None, space=None, thread=None, dialog=None, event_time=None)
staticmethod
Build a named action event.
Source code in src/chattice/testing/event_factory.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
added_to_space(*, user=None, space=None, thread=None, event_time=None)
staticmethod
Build an app-added-to-space event.
Source code in src/chattice/testing/event_factory.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
app_home(*, user=None, space=None, thread=None, event_time=None)
staticmethod
Build an App Home open event.
Source code in src/chattice/testing/event_factory.py
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
form_submit(function_name, *, parameters=None, form_inputs=None, user=None, space=None, thread=None, event_time=None)
staticmethod
Build a form submission event from App Home.
Source code in src/chattice/testing/event_factory.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
message(text, *, user=None, space=None, thread=None, event_time=None)
staticmethod
Build a chat message event.
Source code in src/chattice/testing/event_factory.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
removed_from_space(*, user=None, space=None, thread=None, event_time=None)
staticmethod
Build an app-removed-from-space event.
Source code in src/chattice/testing/event_factory.py
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
unknown_event(original_type, *, user=None, space=None, thread=None, event_time=None)
staticmethod
Build an event of an unrecognized external type.
Source code in src/chattice/testing/event_factory.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
workspace_event(cloud_type, *, event_id='evt-test', source='//chat.googleapis.com/test', subject=None, event_time=None, data=None)
staticmethod
Build a Workspace resource-change event.
Source code in src/chattice/testing/event_factory.py
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
FakeChatTransport
Bases: ChatServiceTransport
Subclass of the SDK transport; only the methods Bot uses are real.
Mirrors the gapic transport contract: the client invokes
self._transport._wrapped_methods[method](request, retry=..., timeout=...,
metadata=...) and reads self._transport.host.
Source code in src/chattice/testing/fake_transport.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | |
MockBot
Records outgoing calls and fabricates SDK proto responses.
No transport, no network. Handlers call the same facade as the real
client (bot.app.messages.create(...), DI-compatible: handlers
receive it by name (feed_update(event, bot=mock_bot))). Recorded
call kinds are the recording layer's names (send_message,
update_message); subclasses may override those recorders.
Source code in src/chattice/testing/mock_bot.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | |
assert_message_sent(text=None, *, count=1)
Assert send_message was called count times (optionally with text).
Source code in src/chattice/testing/mock_bot.py
250 251 252 253 254 255 256 257 258 | |
assert_no_messages()
Assert nothing was sent.
Source code in src/chattice/testing/mock_bot.py
274 275 276 277 278 | |
assert_updated(name, text)
Assert update_message was called with the given name/text.
Source code in src/chattice/testing/mock_bot.py
260 261 262 263 264 265 266 267 268 269 270 271 272 | |
assert_card_has_button(card, *, action=None, text=None)
Assert the card contains a button matching the given action/text.
Source code in src/chattice/testing/assertions.py
19 20 21 22 23 24 25 26 27 28 29 30 31 | |
assert_card_header(card, *, title=None, subtitle=None)
Assert the card header matches the given fields.
Source code in src/chattice/testing/assertions.py
34 35 36 37 38 39 40 41 42 43 44 45 46 | |
set_state_for(storage, key, state)
async
Seed a workflow state for an application test.
Source code in src/chattice/testing/fsm.py
11 12 13 | |