@zackbart/connecta 0.28.1 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +855 -5
- package/README.md +125 -116
- package/bin/connecta.mjs +121 -139
- package/bin/meta-tool-names.d.mts +2 -0
- package/bin/meta-tool-names.mjs +9 -0
- package/bin/version.mjs +3 -0
- package/dist/access-tokens.js +53 -63
- package/dist/activity-request.js +8 -0
- package/dist/activity.d.ts +76 -42
- package/dist/activity.js +110 -42
- package/dist/argument-redaction.js +230 -0
- package/dist/auth/clerk-sdk/client.d.ts +65 -0
- package/dist/auth/clerk-sdk/client.js +5 -0
- package/dist/auth/clerk-sdk/generated.js +1845 -0
- package/dist/auth/clerk-transport.js +19 -0
- package/dist/auth/clerk.d.ts +17 -7
- package/dist/auth/clerk.js +189 -107
- package/dist/auth/cloudflare-access.js +25 -26
- package/dist/auth/downstream-client-metadata.d.ts +29 -0
- package/dist/auth/downstream-client-metadata.js +133 -0
- package/dist/auth/downstream-oauth.js +1584 -1580
- package/dist/auth/downstream-revocation.js +106 -0
- package/dist/auth/oauth-token-response.js +231 -0
- package/dist/auth/oauth-v2-migration.js +116 -0
- package/dist/auth/static-oauth.js +93 -71
- package/dist/auth-elicitation.js +288 -0
- package/dist/authorization-handoff.js +111 -0
- package/dist/branding.d.ts +8 -16
- package/dist/branding.js +26 -59
- package/dist/byte-read-response.js +39 -0
- package/dist/call-admission.js +12 -16
- package/dist/catalog-cache.js +739 -0
- package/dist/catalog-drift.d.ts +50 -15
- package/dist/catalog-drift.js +365 -128
- package/dist/catalog-fingerprint.js +2 -4
- package/dist/catalog-freshness.js +13 -0
- package/dist/catalog-limits.js +2 -2
- package/dist/catalog-service.js +409 -225
- package/dist/catalog.js +43 -84
- package/dist/concurrency.js +3 -4
- package/dist/config-defaults.d.ts +39 -0
- package/dist/config-defaults.js +46 -0
- package/dist/config-schema.d.ts +181 -0
- package/dist/config-schema.js +435 -0
- package/dist/config-value-sources.js +102 -0
- package/dist/config.d.ts +633 -0
- package/dist/config.js +508 -0
- package/dist/connector-access.d.ts +1 -0
- package/dist/connector-access.js +13 -15
- package/dist/connector-caller.d.ts +8 -0
- package/dist/connector-caller.js +15 -6
- package/dist/connector-scope.js +1 -1
- package/dist/connectors/api-connector.d.ts +59 -7
- package/dist/connectors/api-connector.js +106 -19
- package/dist/connectors/api.js +4 -1
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +87 -38
- package/dist/connectors/negotiation-cache.js +46 -0
- package/dist/connectors/option-shapes.js +27 -0
- package/dist/connectors/remote-mcp.d.ts +30 -4
- package/dist/connectors/remote-mcp.js +1774 -320
- package/dist/connectors/resource-uri.js +335 -0
- package/dist/credential-contract.d.ts +10 -0
- package/dist/credential-rules.js +1 -3
- package/dist/credential-url.js +108 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +27 -18
- package/dist/d1.d.ts +130 -0
- package/dist/d1.js +290 -0
- package/dist/describe-config.d.ts +165 -0
- package/dist/describe-config.js +315 -0
- package/dist/described.js +106 -0
- package/dist/downstream-input-context.js +128 -0
- package/dist/downstream-input.js +325 -0
- package/dist/errors.d.ts +132 -31
- package/dist/errors.js +175 -87
- package/dist/execute.js +798 -318
- package/dist/executor-admission.d.ts +1 -0
- package/dist/executor-admission.js +11 -15
- package/dist/executor-contract.d.ts +20 -0
- package/dist/executor-contract.js +48 -0
- package/dist/executor-result.js +30 -13
- package/dist/executors/quickjs-child.js +15 -9
- package/dist/executors/quickjs-protocol.js +5 -6
- package/dist/executors/quickjs-runtime.js +152 -59
- package/dist/executors/quickjs.js +49 -39
- package/dist/favicon.js +1 -2
- package/dist/fix-prompt.js +1 -3
- package/dist/guest-runtime.js +238 -0
- package/dist/guest-types.d.ts +218 -0
- package/dist/guest-types.js +1 -0
- package/dist/html-security.js +24 -0
- package/dist/identity.js +1 -3
- package/dist/inbound-credential.js +52 -0
- package/dist/index.d.ts +24 -256
- package/dist/index.js +65 -478
- package/dist/invocation-auth.js +69 -0
- package/dist/invocation.js +262 -79
- package/dist/json-schema.d.ts +1 -1
- package/dist/mcp-client-context.js +35 -0
- package/dist/mcp-result.js +11 -7
- package/dist/meta-output.js +61 -0
- package/dist/meta-tool-names.d.ts +2 -0
- package/dist/meta-tool-names.js +3 -0
- package/dist/meta-tools.js +419 -272
- package/dist/module-contracts.d.ts +8 -23
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -2
- package/dist/oauth-callback-outcome.js +1 -3
- package/dist/oauth-handoff.js +194 -0
- package/dist/oauth-sealing.js +20 -0
- package/dist/operator-record.d.ts +137 -0
- package/dist/operator-record.js +420 -0
- package/dist/operator-ui/assets.js +31 -0
- package/dist/operator-ui/contract.d.ts +72 -0
- package/dist/operator-ui/contract.js +1 -0
- package/dist/operator-ui/fix-prompts.d.ts +18 -0
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/model.d.ts +12 -87
- package/dist/operator-ui/model.js +2 -9
- package/dist/operator-ui/setup-commands.js +1 -3
- package/dist/operator-ui/view.d.ts +323 -0
- package/dist/operator-ui/view.js +62 -189
- package/dist/page-styles.js +2 -3
- package/dist/program-result.js +5 -0
- package/dist/program-source.js +14 -2
- package/dist/{exempt-writes.js → program-writes.js} +60 -19
- package/dist/provider.d.ts +142 -0
- package/dist/provider.js +187 -0
- package/dist/providers/_shared/google/result-size.js +57 -0
- package/dist/providers/_shared/google/service-account.d.ts +58 -0
- package/dist/providers/_shared/google/service-account.js +500 -0
- package/dist/providers/_shared/google/workspace.d.ts +276 -0
- package/dist/providers/_shared/google/workspace.js +518 -0
- package/dist/providers/_shared/request-token.js +83 -0
- package/dist/providers/{basecamp.d.ts → basecamp/index.d.ts} +6 -28
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/{breeze.d.ts → breeze/index.d.ts} +2 -2
- package/dist/providers/{breeze.js → breeze/index.js} +184 -140
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/{ccb.d.ts → ccb/index.d.ts} +2 -2
- package/dist/providers/{ccb.js → ccb/index.js} +271 -116
- package/dist/providers/ccb/skill.generated.js +9 -0
- package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
- package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
- package/dist/providers/cloudflare/skill.generated.js +10 -0
- package/dist/providers/docs/index.d.ts +54 -0
- package/dist/providers/docs/index.js +1237 -0
- package/dist/providers/docs/skill.generated.js +9 -0
- package/dist/providers/drive/index.d.ts +53 -0
- package/dist/providers/drive/index.js +1523 -0
- package/dist/providers/drive/skill.generated.js +9 -0
- package/dist/providers/forms/index.d.ts +54 -0
- package/dist/providers/forms/index.js +1217 -0
- package/dist/providers/forms/skill.generated.js +11 -0
- package/dist/providers/github/auth.d.ts +32 -0
- package/dist/providers/github/auth.js +361 -0
- package/dist/providers/github/hosted.js +218 -0
- package/dist/providers/github/index.d.ts +13 -0
- package/dist/providers/github/index.js +140 -0
- package/dist/providers/github/key.js +100 -0
- package/dist/providers/github/rest.js +321 -0
- package/dist/providers/github/scope.d.ts +29 -0
- package/dist/providers/github/scope.js +124 -0
- package/dist/providers/github/skill.generated.js +8 -0
- package/dist/providers/gmail/index.d.ts +51 -0
- package/dist/providers/gmail/index.js +1436 -0
- package/dist/providers/gmail/skill.generated.js +9 -0
- package/dist/providers/infisical/index.d.ts +7 -0
- package/dist/providers/infisical/index.js +713 -0
- package/dist/providers/infisical/skill.generated.js +8 -0
- package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
- package/dist/providers/linear/index.js +352 -0
- package/dist/providers/linear/skill.generated.js +8 -0
- package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
- package/dist/providers/mixpanel/index.js +416 -0
- package/dist/providers/mixpanel/skill.generated.js +9 -0
- package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
- package/dist/providers/{notion.js → notion/index.js} +226 -239
- package/dist/providers/notion/skill.generated.js +10 -0
- package/dist/providers/{overflow.d.ts → overflow/index.d.ts} +2 -2
- package/dist/providers/{overflow.js → overflow/index.js} +74 -111
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/{planning-center.d.ts → planning-center/index.d.ts} +2 -2
- package/dist/providers/{planning-center.js → planning-center/index.js} +264 -104
- package/dist/providers/planning-center/skill.generated.js +10 -0
- package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
- package/dist/providers/revenuecat/index.js +557 -0
- package/dist/providers/revenuecat/skill.generated.js +11 -0
- package/dist/providers/sheets/index.d.ts +54 -0
- package/dist/providers/sheets/index.js +1237 -0
- package/dist/providers/sheets/skill.generated.js +10 -0
- package/dist/providers/slides/index.d.ts +53 -0
- package/dist/providers/slides/index.js +2645 -0
- package/dist/providers/slides/skill.generated.js +9 -0
- package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
- package/dist/providers/stripe/index.js +266 -0
- package/dist/providers/stripe/skill.generated.js +11 -0
- package/dist/providers/{tithely.d.ts → tithely/index.d.ts} +2 -2
- package/dist/providers/{tithely.js → tithely/index.js} +60 -91
- package/dist/providers/tithely/skill.generated.js +8 -0
- package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
- package/dist/providers/vercel/index.js +1038 -0
- package/dist/providers/vercel/mcp-ownership.js +212 -0
- package/dist/providers/vercel/skill.generated.js +11 -0
- package/dist/registry.d.ts +110 -171
- package/dist/registry.js +588 -927
- package/dist/request-state.js +21 -0
- package/dist/resource-read.js +103 -0
- package/dist/result-shapes.js +17 -49
- package/dist/retired-toolkits.js +1 -1
- package/dist/routes/access-tokens.js +3 -6
- package/dist/routes/activity-context.js +21 -0
- package/dist/routes/activity-disclosure.js +40 -0
- package/dist/routes/activity.js +59 -21
- package/dist/routes/actor-labels.js +3 -50
- package/dist/routes/connect.js +221 -0
- package/dist/routes/credentials.js +15 -27
- package/dist/routes/mcp.js +365 -130
- package/dist/routes/oauth-client-metadata.js +15 -0
- package/dist/routes/oauth-management.js +45 -107
- package/dist/routes/oauth.js +110 -57
- package/dist/routes/operator.js +3 -3
- package/dist/routes/shared.d.ts +25 -64
- package/dist/routes/shared.js +160 -80
- package/dist/routes/skills.js +30 -0
- package/dist/routes/ui-config.js +225 -0
- package/dist/routes/ui-data.js +40 -35
- package/dist/routes/ui.js +66 -56
- package/dist/runtime/admission.js +4 -2
- package/dist/runtime/call-admission.js +3 -1
- package/dist/runtime/connector-scope.js +1 -4
- package/dist/runtime/run.js +10 -39
- package/dist/runtime/services.js +12 -117
- package/dist/runtime/shared-read.js +1 -3
- package/dist/runtime/storage.js +8 -1
- package/dist/sent-secrets.d.ts +93 -0
- package/dist/sent-secrets.js +1013 -0
- package/dist/server.js +28 -71
- package/dist/skills.js +416 -174
- package/dist/sqlite.d.ts +48 -0
- package/dist/sqlite.js +181 -0
- package/dist/storage/keys.js +443 -0
- package/dist/storage/memory.js +16 -4
- package/dist/storage/sql.d.ts +66 -0
- package/dist/storage/sql.js +543 -0
- package/dist/timeout.js +4 -2
- package/dist/tool-name.js +17 -0
- package/dist/tool-safety.d.ts +9 -35
- package/dist/tool-safety.js +20 -40
- package/dist/types.d.ts +336 -56
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +7 -19
- package/dist/ui.js +76 -90
- package/dist/url-safety.js +3 -6
- package/dist/usage-guide.js +146 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +309 -47
- package/dist/version.d.ts +1 -7
- package/dist/version.js +3 -7
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +435 -0
- package/documentation/README.md +63 -0
- package/documentation/architecture.md +696 -231
- package/documentation/auth.md +1069 -546
- package/documentation/code-mode.md +662 -356
- package/documentation/deploying.md +146 -0
- package/documentation/integrating.md +159 -0
- package/documentation/meta-tools.md +570 -216
- package/documentation/operating.md +135 -0
- package/documentation/operator-tests.md +97 -0
- package/documentation/operator-ui.md +132 -0
- package/documentation/provider-migration-0.29.md +65 -0
- package/examples/worker/AGENTS.md +34 -12
- package/examples/worker/README.md +293 -255
- package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
- package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
- package/examples/worker/src/connecta.config.ts +151 -0
- package/examples/worker/src/index.ts +14 -197
- package/examples/worker/wrangler.jsonc +15 -35
- package/package.json +126 -54
- package/templates/node/.dockerignore +1 -2
- package/templates/node/.env.example +20 -21
- package/templates/node/AGENTS.md +21 -17
- package/templates/node/Dockerfile +3 -5
- package/templates/node/README.md +140 -58
- package/templates/node/docker-compose.yml +11 -12
- package/templates/node/package.json +4 -2
- package/templates/node/src/connecta.config.ts +119 -0
- package/templates/node/src/index.ts +9 -154
- package/templates/node/src/provision-token.ts +17 -0
- package/AGENTS.md +0 -170
- package/dist/artifacts/connector.d.ts +0 -58
- package/dist/artifacts/connector.js +0 -730
- package/dist/artifacts/document.js +0 -86
- package/dist/artifacts/guide.js +0 -140
- package/dist/artifacts/html-scan.js +0 -329
- package/dist/artifacts/json.js +0 -78
- package/dist/artifacts/kv-store.d.ts +0 -20
- package/dist/artifacts/kv-store.js +0 -140
- package/dist/artifacts/markdown.js +0 -478
- package/dist/artifacts/module.d.ts +0 -37
- package/dist/artifacts/module.js +0 -66
- package/dist/artifacts/operations.d.ts +0 -197
- package/dist/artifacts/operations.js +0 -1002
- package/dist/artifacts/refresh.d.ts +0 -55
- package/dist/artifacts/refresh.js +0 -236
- package/dist/artifacts/routes.js +0 -206
- package/dist/artifacts/types.d.ts +0 -214
- package/dist/artifacts/types.js +0 -22
- package/dist/artifacts/validate.d.ts +0 -62
- package/dist/artifacts/validate.js +0 -651
- package/dist/artifacts.d.ts +0 -6
- package/dist/artifacts.js +0 -9
- package/dist/auth/bearer.d.ts +0 -11
- package/dist/auth/bearer.js +0 -50
- package/dist/providers/basecamp.js +0 -445
- package/dist/providers/linear.js +0 -217
- package/dist/providers/mixpanel.js +0 -247
- package/dist/providers/revenuecat.js +0 -317
- package/dist/providers/stripe.js +0 -253
- package/dist/providers/vercel.js +0 -1253
- package/dist/storage/file.d.ts +0 -15
- package/dist/storage/file.js +0 -455
- package/ethos.md +0 -93
- package/examples/worker/src/cloudflare-kv.ts +0 -43
- package/examples/worker/src/d1-activity-row.ts +0 -155
- package/examples/worker/src/d1-activity.ts +0 -147
- package/examples/worker/src/d1-storage.ts +0 -138
- package/examples/worker/src/r2-artifact-blobs.ts +0 -29
- package/templates/node/src/file-activity.ts +0 -182
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Generated by scripts/generate-providers.mjs; do not edit.
|
|
2
|
+
export const skill = {
|
|
3
|
+
"content": ".breezechms.com (Breeze ChMS, now Tithely Church Management): people, tags, events, attendance, forms, volunteers, and giving.\n\nChurch purpose: \n\n## Sensitive data: reduce in code\n\nPeople records carry home addresses, phones, birthdates, and family ties, and\ngiving records reveal who gives and how much — religious affiliation by proxy.\nRead them inside `execute_code` and return only the counts, totals, or the\nfew fields the task needs. Never echo whole profiles or donor lists.\n\n## Ids and profile fields\n\n- Ids are numeric strings. Read them from a list tool; never guess one.\n- Events have two ids: an instance id (`list_events` `id`) for one\n occurrence, and a series `eventId`. Attendance, volunteers, and\n check-in take the instance id.\n- Person `details` are keyed by profile `fieldId`, not by name. Call\n `list_profile_fields` once and map ids to names in code. Multiple-choice\n values and `list_people` filters use option ids from the same call;\n join several with `-`.\n- `list_people` has no name search. List without details and match names\n in code, then `get_person` the hits.\n- Projections rename Breeze's snake_case fields to camelCase and drop photo\n paths and internal columns; `raw: true` returns Breeze's rows.\n\n## Pagination\n\n`list_people` pages by `cursor`: continue while `page.hasMore`. Breeze\nreports no total, so a full page sets `hasMore` and the next may be empty.\n`list_events` and `list_account_log` do not page: `truncated: true`\nmeans narrow the date range. Other lists return everything.\n\n## Giving\n\n`list_contributions` and `list_funds` call endpoints Breeze removed from\nits public reference in 2023 but still serves. They may change or vanish\nwithout notice; a failure there is not your argument's fault. Amounts are\ndecimal strings; `totalAmount` is an exact sum. Online gifts processed by\nTithe.ly arrive through its sync, batched per deposit, so the latest days\nmay be missing. Read the currency from `get_account_summary`.\n\n## Writes and the hatches\n\n- Every write, `add_person`, `assign_tag`, and `record_check_in`\n included, follows the routing in the `usage` skill. Fetch it with\n `skills({ name: \"usage\" })` for guest API and trust rules.\n Those three only add, and `add_person` never deduplicates.\n- `update_person` field values: text, date (M/D/YYYY), or option id in\n `response`; email, phone, address, and family_role values in `details`.\n- Every Breeze call is a GET, writes included, so the hatches split by\n endpoint. `breeze_api_get` admits only reviewed read endpoints and their\n documented parameters, such as `/tags/list_folders`,\n `/events/list_event`, `/events/attendance/eligible`, `/giving/view`,\n and `/pledges/list_campaigns`; it refuses anything else. Everything else\n — event, family, volunteer, and form writes, giving writes, check-out,\n undocumented parameters — is `breeze_api_mutate`. Paths are below\n `/api`; `*_json` values may be passed as objects.\n- `list_account_log` actions include person_created, person_updated,\n person_deleted, tag_assign, tag_unassign, event_created,\n attendance_deleted, form_entry_updated, contribution_added,\n contribution_updated, contribution_deleted, and batch_updated.\n\n## Rate limits\n\nBreeze publishes no limit and sends no rate headers; a third party reports\nabout 20 requests per minute. Keep loops sequential and prefer one list call\nover many single reads.\n",
|
|
4
|
+
"instructionsHeading": "Church instructions",
|
|
5
|
+
"fragments": {
|
|
6
|
+
"guide_0": ".breezechms.com (Breeze ChMS, now Tithely Church Management): people, tags, events, attendance, forms, volunteers, and giving.\n\nChurch purpose: ",
|
|
7
|
+
"guide_1": "\n\n## Sensitive data: reduce in code\n\nPeople records carry home addresses, phones, birthdates, and family ties, and\ngiving records reveal who gives and how much — religious affiliation by proxy.\nRead them inside `execute_code` and return only the counts, totals, or the\nfew fields the task needs. Never echo whole profiles or donor lists.\n\n## Ids and profile fields\n\n- Ids are numeric strings. Read them from a list tool; never guess one.\n- Events have two ids: an instance id (`list_events` `id`) for one\n occurrence, and a series `eventId`. Attendance, volunteers, and\n check-in take the instance id.\n- Person `details` are keyed by profile `fieldId`, not by name. Call\n `list_profile_fields` once and map ids to names in code. Multiple-choice\n values and `list_people` filters use option ids from the same call;\n join several with `-`.\n- `list_people` has no name search. List without details and match names\n in code, then `get_person` the hits.\n- Projections rename Breeze's snake_case fields to camelCase and drop photo\n paths and internal columns; `raw: true` returns Breeze's rows.\n\n## Pagination\n\n`list_people` pages by `cursor`: continue while `page.hasMore`. Breeze\nreports no total, so a full page sets `hasMore` and the next may be empty.\n`list_events` and `list_account_log` do not page: `truncated: true`\nmeans narrow the date range. Other lists return everything.\n\n## Giving\n\n`list_contributions` and `list_funds` call endpoints Breeze removed from\nits public reference in 2023 but still serves. They may change or vanish\nwithout notice; a failure there is not your argument's fault. Amounts are\ndecimal strings; `totalAmount` is an exact sum. Online gifts processed by\nTithe.ly arrive through its sync, batched per deposit, so the latest days\nmay be missing. Read the currency from `get_account_summary`.\n\n## Writes and the hatches\n\n- Every write, `add_person`, `assign_tag`, and `record_check_in`\n included, follows the routing in the `usage` skill. Fetch it with\n `skills({ name: \"usage\" })` for guest API and trust rules.\n Those three only add, and `add_person` never deduplicates.\n- `update_person` field values: text, date (M/D/YYYY), or option id in\n `response`; email, phone, address, and family_role values in `details`.\n- Every Breeze call is a GET, writes included, so the hatches split by\n endpoint. `breeze_api_get` admits only reviewed read endpoints and their\n documented parameters, such as `/tags/list_folders`,\n `/events/list_event`, `/events/attendance/eligible`, `/giving/view`,\n and `/pledges/list_campaigns`; it refuses anything else. Everything else\n — event, family, volunteer, and form writes, giving writes, check-out,\n undocumented parameters — is `breeze_api_mutate`. Paths are below\n `/api`; `*_json` values may be passed as objects.\n- `list_account_log` actions include person_created, person_updated,\n person_deleted, tag_assign, tag_unassign, event_created,\n attendance_deleted, form_entry_updated, contribution_added,\n contribution_updated, contribution_deleted, and batch_updated.\n\n## Rate limits\n\nBreeze publishes no limit and sends no rate headers; a third party reports\nabout 20 requests per minute. Keep loops sequential and prefer one list call\nover many single reads.\n"
|
|
8
|
+
}
|
|
9
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConnectorCallAdmissionPolicy } from "../../types.js";
|
|
2
2
|
/** CCB's v2 media type. The API and its token endpoint both require it. */
|
|
3
3
|
export declare const CCB_MEDIA_TYPE = "application/vnd.ccbchurch.v2+json";
|
|
4
4
|
/**
|
|
@@ -100,4 +100,4 @@ export interface CcbOptions {
|
|
|
100
100
|
maxResultBytes?: number;
|
|
101
101
|
}
|
|
102
102
|
/** A maintained Church Community Builder (Pushpay ChMS) v2 connection. */
|
|
103
|
-
export declare
|
|
103
|
+
export declare const ccb: import("../../provider.js").ProviderFactory<CcbOptions>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { skill } from "./skill.generated.js";
|
|
1
2
|
/**
|
|
2
3
|
* Church Community Builder — sold today as Pushpay ChMS — through its v2 JSON
|
|
3
4
|
* REST API, hand-written over `api()`'s downstream OAuth grant.
|
|
@@ -22,16 +23,19 @@
|
|
|
22
23
|
* pledges, scheduled gifts, and financial settings, and that is all this
|
|
23
24
|
* connector reaches.
|
|
24
25
|
*
|
|
25
|
-
* Drift is handled the Vercel way: `
|
|
26
|
+
* Drift is handled the Vercel way: `src/providers/ccb/drift.json` records
|
|
26
27
|
* every endpoint a named tool touches, and
|
|
27
28
|
* `npm run providers:check -- --provider ccb` compares those rows with the
|
|
28
29
|
* published, credential-free OpenAPI document at
|
|
29
30
|
* https://docs.pushpay.io/chms-v2/openapi/chms-api-specs.json.
|
|
30
31
|
*/
|
|
31
|
-
import { api } from "
|
|
32
|
-
import { defined } from "
|
|
33
|
-
import { guardedFetch, oauthBearer, retryAfterMs, } from "
|
|
34
|
-
import { ConnectorCallError } from "
|
|
32
|
+
import { api } from "../../connectors/api.js";
|
|
33
|
+
import { defined } from "../../connectors/api-connector.js";
|
|
34
|
+
import { guardedFetch, oauthBearer, retryAfterMs, } from "../../connectors/guarded-fetch.js";
|
|
35
|
+
import { ConnectorCallError } from "../../errors.js";
|
|
36
|
+
import { keys, optionsOf } from "../../config-schema.js";
|
|
37
|
+
import { CALL_ADMISSION } from "../../connectors/option-shapes.js";
|
|
38
|
+
import { asProviderFactory } from "../../provider.js";
|
|
35
39
|
/** CCB's v2 media type. The API and its token endpoint both require it. */
|
|
36
40
|
export const CCB_MEDIA_TYPE = "application/vnd.ccbchurch.v2+json";
|
|
37
41
|
/**
|
|
@@ -138,9 +142,7 @@ const CCB_ADMISSION = {
|
|
|
138
142
|
],
|
|
139
143
|
};
|
|
140
144
|
function asRecord(value) {
|
|
141
|
-
return value && typeof value === "object" && !Array.isArray(value)
|
|
142
|
-
? value
|
|
143
|
-
: {};
|
|
145
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
144
146
|
}
|
|
145
147
|
function asArray(value) {
|
|
146
148
|
return Array.isArray(value) ? value : [];
|
|
@@ -179,9 +181,7 @@ const NAMED_ENDPOINTS = {
|
|
|
179
181
|
list_schedules: "GET /scheduling/categories/{id}/schedules",
|
|
180
182
|
list_individual_assignments: "GET /individuals/{id}/assignments",
|
|
181
183
|
list_individual_notes: "GET /individuals/{id}/notes",
|
|
182
|
-
get_giving_metrics: (args) => args["familyId"] !== undefined
|
|
183
|
-
? "GET /families/{id}/metrics/giving"
|
|
184
|
-
: "GET /individuals/{id}/metrics/giving",
|
|
184
|
+
get_giving_metrics: (args) => args["familyId"] !== undefined ? "GET /families/{id}/metrics/giving" : "GET /individuals/{id}/metrics/giving",
|
|
185
185
|
list_individual_pledges: "GET /individuals/{id}/pledges",
|
|
186
186
|
ccb_api_search: (args) => `POST /search/${typeof args["domain"] === "string" ? args["domain"] : "?"}/results`,
|
|
187
187
|
};
|
|
@@ -208,17 +208,16 @@ function endpointPartition(toolName, raw) {
|
|
|
208
208
|
else if (named)
|
|
209
209
|
key = named(args);
|
|
210
210
|
else {
|
|
211
|
-
const method = toolName === "ccb_api_get"
|
|
212
|
-
? "GET"
|
|
213
|
-
: typeof args["method"] === "string"
|
|
214
|
-
? args["method"]
|
|
215
|
-
: "?";
|
|
211
|
+
const method = toolName === "ccb_api_get" ? "GET" : typeof args["method"] === "string" ? args["method"] : "?";
|
|
216
212
|
const path = typeof args["path"] === "string" ? args["path"] : "";
|
|
217
213
|
key = `${method} ${pathTemplate(path)}`;
|
|
218
214
|
}
|
|
219
215
|
// ASCII-only after templating in every realistic case; the slice keeps an
|
|
220
216
|
// absurd path inside the admission controller's 128-byte key limit anyway.
|
|
221
|
-
return [...key]
|
|
217
|
+
return [...key]
|
|
218
|
+
.filter((c) => c.charCodeAt(0) < 128)
|
|
219
|
+
.join("")
|
|
220
|
+
.slice(0, MAX_PARTITION_KEY_CHARS);
|
|
222
221
|
}
|
|
223
222
|
// ---------------------------------------------------------------------------
|
|
224
223
|
// Transport and typed failures
|
|
@@ -278,7 +277,7 @@ function ccbFailure(status, headers, payload) {
|
|
|
278
277
|
return new ConnectorCallError("auth_required", `${detail} CCB rejected the connection's access token. Call authorize_connector for this connector, then retry.`);
|
|
279
278
|
}
|
|
280
279
|
if (status === 403) {
|
|
281
|
-
return new ConnectorCallError("
|
|
280
|
+
return new ConnectorCallError("provider_permission_denied", `${detail} The grant lacks this endpoint's scope, or (Identity Auth) the signed-in person lacks the permission in CCB. Ask the CCB administrator to grant this endpoint's scope or the signed-in person's permission. Re-authorizing alone will not fix it.`, { retryable: false });
|
|
282
281
|
}
|
|
283
282
|
if (status === 404) {
|
|
284
283
|
return new ConnectorCallError("not_found", `${detail} Re-read the id from its list tool; CCB reports a permission gap as 403, so this record does not exist.`);
|
|
@@ -310,7 +309,9 @@ async function callCcb(send, request, ctx) {
|
|
|
310
309
|
throw ccbFailure(response.status, response.headers, "value" in parsed ? parsed.value : undefined);
|
|
311
310
|
}
|
|
312
311
|
if (!("value" in parsed)) {
|
|
313
|
-
throw new ConnectorCallError("connector_call_failed", "CCB returned a successful response that is not JSON.", {
|
|
312
|
+
throw new ConnectorCallError("connector_call_failed", "CCB returned a successful response that is not JSON.", {
|
|
313
|
+
retryable: false,
|
|
314
|
+
});
|
|
314
315
|
}
|
|
315
316
|
return { body: parsed.value, headers: response.headers };
|
|
316
317
|
});
|
|
@@ -569,9 +570,7 @@ function projectProcess(value) {
|
|
|
569
570
|
ownerId: row["owner_id"],
|
|
570
571
|
hidden: row["hidden"],
|
|
571
572
|
archived: row["archived"],
|
|
572
|
-
managers: Array.isArray(row["process_managers"])
|
|
573
|
-
? row["process_managers"].map(ref).filter(Boolean)
|
|
574
|
-
: undefined,
|
|
573
|
+
managers: Array.isArray(row["process_managers"]) ? row["process_managers"].map(ref).filter(Boolean) : undefined,
|
|
575
574
|
});
|
|
576
575
|
}
|
|
577
576
|
function projectQueue(value) {
|
|
@@ -732,88 +731,220 @@ function input(properties, required = []) {
|
|
|
732
731
|
}
|
|
733
732
|
const PHONES = obj({ mobile: STR, home: STR, work: STR });
|
|
734
733
|
const PERSON_SCHEMA = obj({
|
|
735
|
-
id: INT,
|
|
736
|
-
|
|
737
|
-
|
|
734
|
+
id: INT,
|
|
735
|
+
name: STR,
|
|
736
|
+
firstName: STR,
|
|
737
|
+
lastName: STR,
|
|
738
|
+
email: STR,
|
|
739
|
+
phones: PHONES,
|
|
740
|
+
birthday: STR,
|
|
741
|
+
familyId: INT,
|
|
742
|
+
familyPosition: STR,
|
|
743
|
+
campusId: INT,
|
|
744
|
+
membershipTypeId: INT,
|
|
745
|
+
active: BOOL,
|
|
746
|
+
deceased: STR,
|
|
738
747
|
});
|
|
739
748
|
const ADDRESS = obj({ street: STR, city: STR, state: STR, zip: STR, country: STR });
|
|
740
749
|
const INDIVIDUAL_SCHEMA = obj({
|
|
741
750
|
...PERSON_SCHEMA.properties,
|
|
742
|
-
gender: STR,
|
|
743
|
-
|
|
744
|
-
|
|
751
|
+
gender: STR,
|
|
752
|
+
maritalStatus: STR,
|
|
753
|
+
homeAddress: ADDRESS,
|
|
754
|
+
mailingAddress: ADDRESS,
|
|
755
|
+
campusName: STR,
|
|
756
|
+
membershipTypeName: STR,
|
|
757
|
+
membershipDate: STR,
|
|
758
|
+
baptized: BOOL,
|
|
759
|
+
lastAttendedDate: STR,
|
|
760
|
+
listed: BOOL,
|
|
761
|
+
customFields: { type: "object" },
|
|
762
|
+
});
|
|
763
|
+
const FAMILY_SCHEMA = obj({
|
|
764
|
+
id: INT,
|
|
765
|
+
lastName: STR,
|
|
766
|
+
address: ADDRESS,
|
|
767
|
+
members: { type: "array", items: PERSON_SCHEMA },
|
|
745
768
|
});
|
|
746
|
-
const FAMILY_SCHEMA = obj({ id: INT, lastName: STR, address: ADDRESS, members: { type: "array", items: PERSON_SCHEMA } });
|
|
747
769
|
const REF = obj({ id: INT, name: STR });
|
|
748
770
|
const GROUP_SCHEMA = obj({
|
|
749
|
-
id: INT,
|
|
750
|
-
|
|
771
|
+
id: INT,
|
|
772
|
+
name: STR,
|
|
773
|
+
campusId: INT,
|
|
774
|
+
inactive: BOOL,
|
|
775
|
+
groupType: STR,
|
|
776
|
+
interactionType: STR,
|
|
777
|
+
membershipType: STR,
|
|
778
|
+
mainLeader: REF,
|
|
779
|
+
departmentId: INT,
|
|
751
780
|
});
|
|
752
781
|
const GROUP_DETAIL_SCHEMA = obj({
|
|
753
782
|
...GROUP_SCHEMA.properties,
|
|
754
|
-
description: STR,
|
|
755
|
-
|
|
783
|
+
description: STR,
|
|
784
|
+
memberCount: INT,
|
|
785
|
+
childcare: BOOL,
|
|
786
|
+
listed: BOOL,
|
|
787
|
+
full: BOOL,
|
|
788
|
+
meetDay: STR,
|
|
789
|
+
meetTime: STR,
|
|
790
|
+
area: STR,
|
|
791
|
+
address: ADDRESS,
|
|
756
792
|
});
|
|
757
793
|
const MEMBERSHIP_SCHEMA = obj({
|
|
758
|
-
groupId: INT,
|
|
759
|
-
|
|
794
|
+
groupId: INT,
|
|
795
|
+
individualId: INT,
|
|
796
|
+
status: STR,
|
|
797
|
+
dateAdded: STR,
|
|
798
|
+
name: STR,
|
|
799
|
+
email: STR,
|
|
800
|
+
phones: PHONES,
|
|
801
|
+
groupName: STR,
|
|
802
|
+
groupType: STR,
|
|
803
|
+
groupInactive: BOOL,
|
|
760
804
|
});
|
|
761
805
|
const OCCURRENCE_SCHEMA = obj({
|
|
762
|
-
eventId: INT,
|
|
763
|
-
|
|
806
|
+
eventId: INT,
|
|
807
|
+
occurrence: STR,
|
|
808
|
+
start: STR,
|
|
809
|
+
end: STR,
|
|
810
|
+
name: STR,
|
|
811
|
+
campusId: INT,
|
|
812
|
+
recurs: BOOL,
|
|
813
|
+
groupId: INT,
|
|
814
|
+
groupName: STR,
|
|
764
815
|
});
|
|
765
816
|
const EVENT_SCHEMA = obj({
|
|
766
|
-
id: INT,
|
|
767
|
-
|
|
768
|
-
|
|
817
|
+
id: INT,
|
|
818
|
+
name: STR,
|
|
819
|
+
description: STR,
|
|
820
|
+
campusId: INT,
|
|
821
|
+
start: STR,
|
|
822
|
+
end: STR,
|
|
823
|
+
recurs: BOOL,
|
|
824
|
+
recurEndDate: STR,
|
|
825
|
+
approvalStatus: STR,
|
|
826
|
+
address: ADDRESS,
|
|
827
|
+
guestCounts: { type: "object" },
|
|
828
|
+
group: REF,
|
|
769
829
|
attendance: obj({ status: STR, totalAttendance: INT, visitors: INT }),
|
|
770
830
|
});
|
|
771
831
|
const ATTENDANCE_SCHEMA = obj({
|
|
772
|
-
eventId: INT,
|
|
832
|
+
eventId: INT,
|
|
833
|
+
occurrence: STR,
|
|
834
|
+
status: STR,
|
|
835
|
+
totalAttendance: INT,
|
|
836
|
+
visitors: INT,
|
|
837
|
+
topic: STR,
|
|
773
838
|
});
|
|
774
839
|
const ATTENDEE_SCHEMA = obj({ individualId: INT, name: STR, familyId: INT, occurrenceDate: STR });
|
|
775
840
|
const FORM_SCHEMA = obj({
|
|
776
|
-
id: INT,
|
|
841
|
+
id: INT,
|
|
842
|
+
title: STR,
|
|
843
|
+
status: STR,
|
|
844
|
+
campusId: INT,
|
|
845
|
+
start: STR,
|
|
846
|
+
end: STR,
|
|
847
|
+
public: BOOL,
|
|
848
|
+
url: STR,
|
|
777
849
|
});
|
|
778
850
|
const RESPONSE_SCHEMA = obj({
|
|
779
|
-
id: INT,
|
|
851
|
+
id: INT,
|
|
852
|
+
formId: INT,
|
|
853
|
+
individualId: INT,
|
|
854
|
+
created: STR,
|
|
855
|
+
paymentStatus: STR,
|
|
780
856
|
answers: { type: "array", items: obj({ questionId: INT, answer: STR }) },
|
|
781
857
|
});
|
|
782
858
|
const PROCESS_SCHEMA = obj({
|
|
783
|
-
id: INT,
|
|
859
|
+
id: INT,
|
|
860
|
+
name: STR,
|
|
861
|
+
campusId: INT,
|
|
862
|
+
ownerId: INT,
|
|
863
|
+
hidden: BOOL,
|
|
864
|
+
archived: BOOL,
|
|
784
865
|
managers: { type: "array", items: REF },
|
|
785
866
|
});
|
|
786
867
|
const QUEUE_SCHEMA = obj({
|
|
787
|
-
id: INT,
|
|
788
|
-
|
|
868
|
+
id: INT,
|
|
869
|
+
name: STR,
|
|
870
|
+
processId: INT,
|
|
871
|
+
processName: STR,
|
|
872
|
+
description: STR,
|
|
873
|
+
assignedCount: INT,
|
|
874
|
+
unassignedCount: INT,
|
|
789
875
|
});
|
|
790
876
|
const QUEUE_INDIVIDUAL_SCHEMA = obj({
|
|
791
|
-
queueIndividualId: INT,
|
|
792
|
-
|
|
877
|
+
queueIndividualId: INT,
|
|
878
|
+
queueId: INT,
|
|
879
|
+
queueName: STR,
|
|
880
|
+
processId: INT,
|
|
881
|
+
processName: STR,
|
|
882
|
+
individualId: INT,
|
|
883
|
+
name: STR,
|
|
884
|
+
status: STR,
|
|
885
|
+
due: STR,
|
|
886
|
+
created: STR,
|
|
887
|
+
completed: STR,
|
|
793
888
|
});
|
|
794
889
|
const CATEGORY_SCHEMA = obj({
|
|
795
|
-
id: INT,
|
|
890
|
+
id: INT,
|
|
891
|
+
name: STR,
|
|
892
|
+
campus: REF,
|
|
893
|
+
organizer: REF,
|
|
894
|
+
archived: BOOL,
|
|
796
895
|
teams: { type: "array", items: REF },
|
|
797
896
|
});
|
|
798
897
|
const SCHEDULE_SCHEMA = obj({
|
|
799
|
-
id: INT,
|
|
898
|
+
id: INT,
|
|
899
|
+
categoryId: INT,
|
|
900
|
+
name: STR,
|
|
901
|
+
start: STR,
|
|
902
|
+
end: STR,
|
|
903
|
+
needed: INT,
|
|
800
904
|
events: { type: "array", items: obj({ id: INT, name: STR, start: STR, end: STR }) },
|
|
801
905
|
metrics: { type: "object" },
|
|
802
906
|
});
|
|
803
907
|
const ASSIGNMENT_SCHEMA = obj({
|
|
804
|
-
id: INT,
|
|
805
|
-
|
|
908
|
+
id: INT,
|
|
909
|
+
categoryId: INT,
|
|
910
|
+
scheduleId: INT,
|
|
911
|
+
eventId: INT,
|
|
912
|
+
eventPositionId: INT,
|
|
913
|
+
status: STR,
|
|
914
|
+
statusReason: STR,
|
|
915
|
+
dateNotified: STR,
|
|
916
|
+
individualId: INT,
|
|
917
|
+
name: STR,
|
|
806
918
|
});
|
|
807
919
|
const NOTE_SCHEMA = obj({
|
|
808
|
-
id: INT,
|
|
809
|
-
|
|
920
|
+
id: INT,
|
|
921
|
+
individualId: INT,
|
|
922
|
+
note: STR,
|
|
923
|
+
date: STR,
|
|
924
|
+
sharingLevel: STR,
|
|
925
|
+
context: STR,
|
|
926
|
+
contextId: INT,
|
|
927
|
+
creator: REF,
|
|
810
928
|
});
|
|
811
929
|
const PLEDGE_SCHEMA = obj({
|
|
812
|
-
id: INT,
|
|
813
|
-
|
|
930
|
+
id: INT,
|
|
931
|
+
campusId: INT,
|
|
932
|
+
fund: STR,
|
|
933
|
+
pledged: { type: "number" },
|
|
934
|
+
paid: { type: "number" },
|
|
935
|
+
expected: { type: "number" },
|
|
936
|
+
total: { type: "number" },
|
|
937
|
+
frequency: STR,
|
|
938
|
+
start: STR,
|
|
939
|
+
end: STR,
|
|
814
940
|
});
|
|
815
941
|
const ME_SCHEMA = obj({
|
|
816
|
-
id: INT,
|
|
942
|
+
id: INT,
|
|
943
|
+
name: STR,
|
|
944
|
+
email: STR,
|
|
945
|
+
username: STR,
|
|
946
|
+
familyId: INT,
|
|
947
|
+
campusId: INT,
|
|
817
948
|
userTypes: { type: "array", items: STR },
|
|
818
949
|
});
|
|
819
950
|
/** Domains with a `POST /search/{domain}/results` endpoint in the v2 spec. */
|
|
@@ -952,10 +1083,19 @@ function tools(send, defaultPerPage, writable) {
|
|
|
952
1083
|
description: "Find CCB individuals by partial name, phone, or email. Returns lean profiles with family and campus ids; not the advanced search.",
|
|
953
1084
|
annotations: readOnly,
|
|
954
1085
|
inputSchema: input({
|
|
955
|
-
query: {
|
|
1086
|
+
query: {
|
|
1087
|
+
type: "string",
|
|
1088
|
+
minLength: 1,
|
|
1089
|
+
maxLength: 200,
|
|
1090
|
+
description: "Partial name, phone number, or email. Omit to page everyone.",
|
|
1091
|
+
},
|
|
956
1092
|
includeInactive: { type: "boolean", description: "Include inactive individuals." },
|
|
957
1093
|
includeDeceased: { type: "boolean", description: "Include deceased individuals." },
|
|
958
|
-
campusScope: {
|
|
1094
|
+
campusScope: {
|
|
1095
|
+
type: "string",
|
|
1096
|
+
enum: ["all", "current", "other"],
|
|
1097
|
+
description: "Campuses to search relative to the connection's own.",
|
|
1098
|
+
},
|
|
959
1099
|
page: PAGE,
|
|
960
1100
|
perPage,
|
|
961
1101
|
raw: RAW,
|
|
@@ -972,7 +1112,9 @@ function tools(send, defaultPerPage, writable) {
|
|
|
972
1112
|
name: "get_individual",
|
|
973
1113
|
description: "Get one CCB individual's profile: contact, addresses, membership, and custom fields. CCB allows one call a second; prefer list_individuals for many people.",
|
|
974
1114
|
annotations: readOnly,
|
|
975
|
-
inputSchema: input({ individualId: idProperty("Individual id from list_individuals."), raw: RAW }, [
|
|
1115
|
+
inputSchema: input({ individualId: idProperty("Individual id from list_individuals."), raw: RAW }, [
|
|
1116
|
+
"individualId",
|
|
1117
|
+
]),
|
|
976
1118
|
outputSchema: INDIVIDUAL_SCHEMA,
|
|
977
1119
|
handler: (args, ctx) => one(`/individuals/${id(args["individualId"])}`, args, ctx, projectIndividual),
|
|
978
1120
|
},
|
|
@@ -1076,7 +1218,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1076
1218
|
annotations: readOnly,
|
|
1077
1219
|
inputSchema: input({
|
|
1078
1220
|
name: { type: "string", minLength: 1, maxLength: 200, description: "Partial event name." },
|
|
1079
|
-
range: {
|
|
1221
|
+
range: {
|
|
1222
|
+
type: "string",
|
|
1223
|
+
enum: ["ALL", "PAST", "CURRENT", "FUTURE"],
|
|
1224
|
+
description: "Time range relative to now.",
|
|
1225
|
+
},
|
|
1080
1226
|
page: PAGE,
|
|
1081
1227
|
perPage,
|
|
1082
1228
|
raw: RAW,
|
|
@@ -1107,7 +1253,10 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1107
1253
|
name: "get_event_attendance",
|
|
1108
1254
|
description: "Get one CCB event occurrence's attendance summary: met or not, totals, visitors, topic. Drops leader notes and prayer requests unless raw.",
|
|
1109
1255
|
annotations: readOnly,
|
|
1110
|
-
inputSchema: input({ eventId: idProperty("Event id from list_events."), occurrence: OCCURRENCE, raw: RAW }, [
|
|
1256
|
+
inputSchema: input({ eventId: idProperty("Event id from list_events."), occurrence: OCCURRENCE, raw: RAW }, [
|
|
1257
|
+
"eventId",
|
|
1258
|
+
"occurrence",
|
|
1259
|
+
]),
|
|
1111
1260
|
outputSchema: ATTENDANCE_SCHEMA,
|
|
1112
1261
|
handler: (args, ctx) => one(`/events/${id(args["eventId"])}/attendance/${compactDate(args["occurrence"])}`, args, ctx, projectAttendance),
|
|
1113
1262
|
},
|
|
@@ -1125,7 +1274,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1125
1274
|
annotations: readOnly,
|
|
1126
1275
|
inputSchema: input({
|
|
1127
1276
|
title: { type: "string", minLength: 1, maxLength: 200, description: "Partial form title." },
|
|
1128
|
-
status: {
|
|
1277
|
+
status: {
|
|
1278
|
+
type: "string",
|
|
1279
|
+
enum: ["ACTIVE", "SCHEDULED", "UNPUBLISHED", "EXPIRED", "ARCHIVED"],
|
|
1280
|
+
description: "Form status.",
|
|
1281
|
+
},
|
|
1129
1282
|
campusId: idProperty("Only forms at this campus."),
|
|
1130
1283
|
page: PAGE,
|
|
1131
1284
|
perPage,
|
|
@@ -1187,7 +1340,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1187
1340
|
description: "List people in CCB process queues the connection can see, by status or assignment. CCB offers no per-queue filter here; filter on queueId.",
|
|
1188
1341
|
annotations: readOnly,
|
|
1189
1342
|
inputSchema: input({
|
|
1190
|
-
status: {
|
|
1343
|
+
status: {
|
|
1344
|
+
type: "string",
|
|
1345
|
+
enum: ["NOT_STARTED", "WAITING", "IN_PROCESS", "DONE"],
|
|
1346
|
+
description: "Queue status.",
|
|
1347
|
+
},
|
|
1191
1348
|
assignment: { type: "string", enum: ["ASSIGNED_TO_ME", "UNASSIGNED"], description: "Omit for both." },
|
|
1192
1349
|
page: PAGE,
|
|
1193
1350
|
perPage,
|
|
@@ -1205,12 +1362,20 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1205
1362
|
annotations: readOnly,
|
|
1206
1363
|
inputSchema: input({
|
|
1207
1364
|
search: { type: "string", minLength: 1, maxLength: 200, description: "Category name search." },
|
|
1208
|
-
status: {
|
|
1365
|
+
status: {
|
|
1366
|
+
type: "string",
|
|
1367
|
+
enum: ["ACTIVE", "ARCHIVED", "ACTIVE_AND_ARCHIVED"],
|
|
1368
|
+
description: "Defaults to CCB's own (active).",
|
|
1369
|
+
},
|
|
1209
1370
|
raw: RAW,
|
|
1210
1371
|
}),
|
|
1211
1372
|
outputSchema: rowsOutput("categories", CATEGORY_SCHEMA),
|
|
1212
1373
|
handler: async (args, ctx) => {
|
|
1213
|
-
const { body } = await callCcb(send, {
|
|
1374
|
+
const { body } = await callCcb(send, {
|
|
1375
|
+
method: "GET",
|
|
1376
|
+
path: "/scheduling/categories",
|
|
1377
|
+
query: { search_term: args["search"], status: args["status"] },
|
|
1378
|
+
}, ctx);
|
|
1214
1379
|
const rows = Array.isArray(body) ? body : body && typeof body === "object" ? [body] : [];
|
|
1215
1380
|
return { categories: args["raw"] === true ? rows : rows.map(projectCategory) };
|
|
1216
1381
|
},
|
|
@@ -1261,7 +1426,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1261
1426
|
annotations: readOnly,
|
|
1262
1427
|
inputSchema: input({
|
|
1263
1428
|
individualId: idProperty("Individual id."),
|
|
1264
|
-
context: {
|
|
1429
|
+
context: {
|
|
1430
|
+
type: "string",
|
|
1431
|
+
enum: ["GROUP", "DEPARTMENT", "PROCESS_QUEUE", "GENERAL"],
|
|
1432
|
+
description: "Only notes in this context.",
|
|
1433
|
+
},
|
|
1265
1434
|
page: PAGE,
|
|
1266
1435
|
perPage,
|
|
1267
1436
|
raw: RAW,
|
|
@@ -1286,7 +1455,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1286
1455
|
outputSchema: obj({
|
|
1287
1456
|
periods: {
|
|
1288
1457
|
type: "array",
|
|
1289
|
-
items: obj({
|
|
1458
|
+
items: obj({
|
|
1459
|
+
start: STR,
|
|
1460
|
+
count: INT,
|
|
1461
|
+
members: { type: "array", items: obj({ individualId: INT, count: INT }) },
|
|
1462
|
+
}),
|
|
1290
1463
|
},
|
|
1291
1464
|
}),
|
|
1292
1465
|
handler: async (args, ctx) => {
|
|
@@ -1327,7 +1500,9 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1327
1500
|
name: "list_individual_pledges",
|
|
1328
1501
|
description: "List one CCB individual's pledges: fund, pledged, paid, and expected amounts, and recurrence.",
|
|
1329
1502
|
annotations: readOnly,
|
|
1330
|
-
inputSchema: input({ individualId: idProperty("Individual id."), page: PAGE, perPage, raw: RAW }, [
|
|
1503
|
+
inputSchema: input({ individualId: idProperty("Individual id."), page: PAGE, perPage, raw: RAW }, [
|
|
1504
|
+
"individualId",
|
|
1505
|
+
]),
|
|
1331
1506
|
outputSchema: listOutput("pledges", PLEDGE_SCHEMA),
|
|
1332
1507
|
handler: (args, ctx) => list(`/individuals/${id(args["individualId"])}/pledges`, args, ctx, "pledges", projectPledge),
|
|
1333
1508
|
},
|
|
@@ -1392,7 +1567,11 @@ function tools(send, defaultPerPage, writable) {
|
|
|
1392
1567
|
description: "Call any CCB v2 JSON POST, PUT, PATCH, or DELETE endpoint. The approval-gated hatch for every write; no file uploads.",
|
|
1393
1568
|
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
1394
1569
|
inputSchema: input({
|
|
1395
|
-
method: {
|
|
1570
|
+
method: {
|
|
1571
|
+
type: "string",
|
|
1572
|
+
enum: ["POST", "PUT", "PATCH", "DELETE"],
|
|
1573
|
+
description: "HTTP method the endpoint documents.",
|
|
1574
|
+
},
|
|
1396
1575
|
path: HATCH_PATH,
|
|
1397
1576
|
query: QUERY,
|
|
1398
1577
|
body: {
|
|
@@ -1430,52 +1609,9 @@ function usageGuide(purpose, environment, mode, scopes, writable, instructions)
|
|
|
1430
1609
|
const extra = instructions?.trim();
|
|
1431
1610
|
return `# Church Community Builder (Pushpay ChMS)
|
|
1432
1611
|
|
|
1433
|
-
${routingLine(environment, mode, writable)}: ${purpose}
|
|
1434
|
-
|
|
1435
|
-
## Resolve ids before acting
|
|
1436
|
-
|
|
1437
|
-
- Every record is addressed by an integer id. Read it from a list tool and
|
|
1438
|
-
pass it back; never guess one. \`list_individuals\` finds people by partial
|
|
1439
|
-
name, phone, or email; \`familyId\`, \`groupId\`, \`eventId\`, form, process,
|
|
1440
|
-
queue, and category ids come from their own list tools.
|
|
1441
|
-
- Events are series with dated occurrences. \`list_events\` returns
|
|
1442
|
-
\`eventId\` plus \`occurrence\`; the attendance tools need both.
|
|
1443
|
-
- Campus and membership-type ids resolve through \`ccb_api_get\` on
|
|
1444
|
-
\`/campuses\` and \`/church/membership_types\`.
|
|
1445
|
-
${mode === "identity" ? "- Results are what the signed-in person may see in CCB. A 403 means that person lacks the permission, not that the connection is broken.\n" : ""}
|
|
1446
|
-
## Sensitive data stays out of results
|
|
1447
|
-
|
|
1448
|
-
Projections drop allergies, giving numbers and dates, attendance prayer
|
|
1449
|
-
requests and leader notes, and form payment details; \`raw: true\` returns
|
|
1450
|
-
CCB's full row. Notes, pledges, giving metrics, background checks, and
|
|
1451
|
-
financial settings are pastoral or financial: read them inside
|
|
1452
|
-
\`execute_code\` and return only the reduced answer the task needs.
|
|
1453
|
-
|
|
1454
|
-
Giving in v2 is counts per period (\`get_giving_metrics\`), pledges, scheduled
|
|
1455
|
-
gifts, and financial settings. Transactions, batches, and amounts per gift
|
|
1456
|
-
live only in CCB's legacy v1 XML API, which this connector does not reach.
|
|
1457
|
-
|
|
1458
|
-
## Paging
|
|
1459
|
-
|
|
1460
|
-
Lists take \`page\` (1-based) and \`perPage\` (25, 50, 75, or 100 only) and
|
|
1461
|
-
return \`page.hasMore\`, \`page.nextPage\`, and \`page.total\`. Field names are
|
|
1462
|
-
CCB's snake_case turned camelCase.
|
|
1463
|
-
|
|
1464
|
-
## Rate limits
|
|
1465
|
-
|
|
1466
|
-
CCB allows each endpoint about one call a second after a burst of 60, per API
|
|
1467
|
-
client. This connector keeps a per-runtime 60-per-minute window per endpoint
|
|
1468
|
-
— an approximation, not an enforcement. \`get_individual\` (1/s),
|
|
1469
|
-
\`list_schedules\` (1 per 2 s), and individuals advanced search (1 per 5 s)
|
|
1470
|
-
allow no burst: page a list instead of looping a get, and space those calls.
|
|
1471
|
-
A \`rate_limited\` failure carries CCB's wait.
|
|
1472
|
-
|
|
1473
|
-
## Raw access
|
|
1474
|
-
|
|
1475
|
-
\`ccb_api_get\` reaches any GET path; \`ccb_api_search\` runs advanced searches,
|
|
1476
|
-
which CCB serves as POST but are reads.${writable ? " `ccb_api_mutate` reaches every POST, PUT, PATCH, and DELETE and always needs approval." : " This connection is read-only, so it ships no write tool."} Paths are below the API origin, such as \`/church/membership_types\`.
|
|
1612
|
+
${routingLine(environment, mode, writable)}: ${purpose}${skill.fragments.guide_0}${mode === "identity" ? "- Results are what the signed-in person may see in CCB. A 403 means that person lacks the permission, not that the connection is broken.\n" : ""}${skill.fragments.guide_1}${writable ? " `ccb_api_mutate` reaches every POST, PUT, PATCH, and DELETE and always needs approval." : " This connection is read-only, so it ships no write tool."} Paths are below the API origin, such as \`/church/membership_types\`.
|
|
1477
1613
|
Granted scopes: ${scopes.join(" ")}. A call outside them fails with 403.
|
|
1478
|
-
${extra ? `\n##
|
|
1614
|
+
${extra ? `\n## ${skill.instructionsHeading}\n\n${extra}\n` : ""}`;
|
|
1479
1615
|
}
|
|
1480
1616
|
// ---------------------------------------------------------------------------
|
|
1481
1617
|
// Constructor
|
|
@@ -1513,8 +1649,27 @@ function defaultTitle(environment, mode, writable) {
|
|
|
1513
1649
|
];
|
|
1514
1650
|
return `Pushpay ChMS (CCB)${qualifiers.length ? ` — ${qualifiers.join(", ")}` : ""}`;
|
|
1515
1651
|
}
|
|
1652
|
+
/** The closed options ccb() accepts; see `assertKnownOptions`. */
|
|
1653
|
+
const CCB_OPTIONS = optionsOf()({
|
|
1654
|
+
...keys("purpose", "title", "instructions", "environment", "mode", "clientId", "clientSecret", "access", "scopes", "subdomain", "defaultPerPage", "maxResultBytes"),
|
|
1655
|
+
callAdmission: CALL_ADMISSION,
|
|
1656
|
+
});
|
|
1516
1657
|
/** A maintained Church Community Builder (Pushpay ChMS) v2 connection. */
|
|
1517
|
-
export
|
|
1658
|
+
export const ccb = asProviderFactory({
|
|
1659
|
+
name: "ccb",
|
|
1660
|
+
title: "Church Community Builder",
|
|
1661
|
+
kind: "api",
|
|
1662
|
+
readme: "Church Community Builder",
|
|
1663
|
+
bundle: {
|
|
1664
|
+
"baselineGzip": 120479,
|
|
1665
|
+
"maxGzip": 180479,
|
|
1666
|
+
"note": "./providers/ccb starts at 120,479 B gzip: the hand-written surface plus api()'s static OAuth grant over the SDK's auth client, with no remoteMcp() transport. The cap uses the baseline + 60,000 B policy.",
|
|
1667
|
+
},
|
|
1668
|
+
skill,
|
|
1669
|
+
options: CCB_OPTIONS,
|
|
1670
|
+
create: ccbConnector,
|
|
1671
|
+
});
|
|
1672
|
+
function ccbConnector(id, options) {
|
|
1518
1673
|
const purpose = typeof options.purpose === "string" ? options.purpose.trim() : "";
|
|
1519
1674
|
if (!purpose)
|
|
1520
1675
|
throw new Error("ccb() requires a non-empty church purpose.");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Generated by scripts/generate-providers.mjs; do not edit.
|
|
2
|
+
export const skill = {
|
|
3
|
+
"content": "\n\n## Resolve ids before acting\n\n- Every record is addressed by an integer id. Read it from a list tool and\n pass it back; never guess one. `list_individuals` finds people by partial\n name, phone, or email; `familyId`, `groupId`, `eventId`, form, process,\n queue, and category ids come from their own list tools.\n- Events are series with dated occurrences. `list_events` returns\n `eventId` plus `occurrence`; the attendance tools need both.\n- Campus and membership-type ids resolve through `ccb_api_get` on\n `/campuses` and `/church/membership_types`.\n\n## Sensitive data stays out of results\n\nProjections drop allergies, giving numbers and dates, attendance prayer\nrequests and leader notes, and form payment details; `raw: true` returns\nCCB's full row. Notes, pledges, giving metrics, background checks, and\nfinancial settings are pastoral or financial: read them inside\n`execute_code` and return only the reduced answer the task needs.\n\nGiving in v2 is counts per period (`get_giving_metrics`), pledges, scheduled\ngifts, and financial settings. Transactions, batches, and amounts per gift\nlive only in CCB's legacy v1 XML API, which this connector does not reach.\n\n## Paging\n\nLists take `page` (1-based) and `perPage` (25, 50, 75, or 100 only) and\nreturn `page.hasMore`, `page.nextPage`, and `page.total`. Field names are\nCCB's snake_case turned camelCase.\n\n## Rate limits\n\nCCB allows each endpoint about one call a second after a burst of 60, per API\nclient. This connector keeps a per-runtime 60-per-minute window per endpoint\n— an approximation, not an enforcement. `get_individual` (1/s),\n`list_schedules` (1 per 2 s), and individuals advanced search (1 per 5 s)\nallow no burst: page a list instead of looping a get, and space those calls.\nA `rate_limited` failure carries CCB's wait.\n\n## Raw access\n\n`ccb_api_get` reaches any GET path; `ccb_api_search` runs advanced searches,\nwhich CCB serves as POST but are reads.",
|
|
4
|
+
"instructionsHeading": "Church instructions",
|
|
5
|
+
"fragments": {
|
|
6
|
+
"guide_0": "\n\n## Resolve ids before acting\n\n- Every record is addressed by an integer id. Read it from a list tool and\n pass it back; never guess one. `list_individuals` finds people by partial\n name, phone, or email; `familyId`, `groupId`, `eventId`, form, process,\n queue, and category ids come from their own list tools.\n- Events are series with dated occurrences. `list_events` returns\n `eventId` plus `occurrence`; the attendance tools need both.\n- Campus and membership-type ids resolve through `ccb_api_get` on\n `/campuses` and `/church/membership_types`.\n",
|
|
7
|
+
"guide_1": "\n## Sensitive data stays out of results\n\nProjections drop allergies, giving numbers and dates, attendance prayer\nrequests and leader notes, and form payment details; `raw: true` returns\nCCB's full row. Notes, pledges, giving metrics, background checks, and\nfinancial settings are pastoral or financial: read them inside\n`execute_code` and return only the reduced answer the task needs.\n\nGiving in v2 is counts per period (`get_giving_metrics`), pledges, scheduled\ngifts, and financial settings. Transactions, batches, and amounts per gift\nlive only in CCB's legacy v1 XML API, which this connector does not reach.\n\n## Paging\n\nLists take `page` (1-based) and `perPage` (25, 50, 75, or 100 only) and\nreturn `page.hasMore`, `page.nextPage`, and `page.total`. Field names are\nCCB's snake_case turned camelCase.\n\n## Rate limits\n\nCCB allows each endpoint about one call a second after a burst of 60, per API\nclient. This connector keeps a per-runtime 60-per-minute window per endpoint\n— an approximation, not an enforcement. `get_individual` (1/s),\n`list_schedules` (1 per 2 s), and individuals advanced search (1 per 5 s)\nallow no burst: page a list instead of looping a get, and space those calls.\nA `rate_limited` failure carries CCB's wait.\n\n## Raw access\n\n`ccb_api_get` reaches any GET path; `ccb_api_search` runs advanced searches,\nwhich CCB serves as POST but are reads."
|
|
8
|
+
}
|
|
9
|
+
};
|