@synap-core/workspace-templates 0.11.0 → 0.23.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/README.md +483 -0
- package/automations/bookmark-enrichment.automation.json +321 -0
- package/automations/github-pr-events.automation.json +505 -0
- package/automations/mail-feed.automation.json +86 -0
- package/automations/ship-a-change-checks-green.automation.json +106 -0
- package/automations/ship-a-change-checks-red.automation.json +106 -0
- package/automations/ship-a-change-deployed.automation.json +56 -0
- package/automations/ship-a-change-pr-merged.automation.json +110 -0
- package/automations/ship-a-change-pr-opened.automation.json +104 -0
- package/automations/url-bookmark-capture.automation.json +132 -0
- package/capabilities/agency-skills.capability.json +157 -0
- package/capabilities/apify.capability.json +265 -0
- package/capabilities/apollo.capability.json +120 -0
- package/capabilities/arch-backend.capability.json +97 -0
- package/capabilities/arch-client-intelligence.capability.json +401 -0
- package/capabilities/backblaze-b2.capability.json +205 -0
- package/capabilities/cal-com.capability.json +266 -0
- package/capabilities/canva.capability.json +274 -0
- package/capabilities/claude-code-routines.capability.json +172 -0
- package/capabilities/claude-managed-agents.capability.json +215 -0
- package/capabilities/client-comms-report.capability.json +246 -0
- package/capabilities/content-idea-to-production.capability.json +29 -0
- package/capabilities/datagouv.capability.json +315 -0
- package/capabilities/discord-bot.capability.json +157 -0
- package/capabilities/dropbox.capability.json +281 -0
- package/capabilities/exa.capability.json +109 -0
- package/capabilities/fal-ai.capability.json +83 -0
- package/capabilities/fal-media-lab.capability.json +158 -0
- package/capabilities/fireflies.capability.json +191 -0
- package/capabilities/freellmapi.capability.json +114 -0
- package/capabilities/generic-apikey.capability.json +92 -0
- package/capabilities/github-merge.capability.json +99 -0
- package/capabilities/github-read.capability.json +325 -0
- package/capabilities/governance-tighten-recommender.capability.json +81 -0
- package/capabilities/jev.capability.json +226 -0
- package/capabilities/lead-conversion-enrollment.capability.json +246 -0
- package/capabilities/mail-feed.capability.json +277 -0
- package/capabilities/mailgun.capability.json +52 -0
- package/capabilities/nango-google.capability.json +639 -0
- package/capabilities/notion.capability.json +417 -0
- package/capabilities/omniroute.capability.json +137 -0
- package/capabilities/posthog-analytics.capability.json +258 -0
- package/capabilities/postiz.capability.json +467 -0
- package/capabilities/proactive-digest.capability.json +190 -0
- package/capabilities/proton.capability.json +288 -0
- package/capabilities/replicate-rvm.capability.json +97 -0
- package/capabilities/research-methods.capability.json +57 -0
- package/capabilities/shopify.capability.json +395 -0
- package/capabilities/slack.capability.json +369 -0
- package/capabilities/stripe.capability.json +420 -0
- package/capabilities/telegram-bridge.capability.json +56 -0
- package/capabilities/treg.capability.json +102 -0
- package/capabilities/unipile-linkedin.capability.json +471 -0
- package/capabilities/vercel.capability.json +424 -0
- package/dist/define-CPS0n8BV.d.ts +1331 -0
- package/dist/index.d.ts +189 -900
- package/dist/index.js +24654 -21639
- package/dist/index.js.map +1 -1
- package/dist/wire.d.ts +222 -0
- package/dist/wire.js +77 -0
- package/dist/wire.js.map +1 -0
- package/package.json +41 -27
- package/packs/bookmark-views-pack.json +33 -0
- package/packs/crm-pack.json +76 -0
- package/packs/customer-profile.json +28 -0
- package/packs/deep-research.playbook.json +30 -0
- package/packs/event-views-pack.json +33 -0
- package/packs/habit-profile.json +27 -0
- package/packs/hr-pack.json +54 -0
- package/packs/invoice-profile.json +28 -0
- package/packs/knowledge-base-pack.json +56 -0
- package/packs/meeting-profile.json +29 -0
- package/packs/product-profile.json +30 -0
- package/packs/project-management-pack.json +49 -0
- package/packs/recipe-profile.json +29 -0
- package/packs/task-views-pack.json +39 -0
- package/retired.yaml +136 -0
- package/skills/app-factory-build-slice/SKILL.md +70 -0
- package/skills/app-factory-build-slice.catalog.json +17 -0
- package/skills/app-factory-design-canvas/SKILL.md +96 -0
- package/skills/app-factory-design-canvas.catalog.json +17 -0
- package/skills/app-factory-design-review/SKILL.md +99 -0
- package/skills/app-factory-design-review.catalog.json +18 -0
- package/skills/app-factory-research/SKILL.md +123 -0
- package/skills/app-factory-research.catalog.json +17 -0
- package/skills/bookmark-enrichment/SKILL.md +40 -0
- package/skills/carousel-format/carousel-format.skill.json +18 -0
- package/skills/collage-broll/collage-broll.skill.json +20 -0
- package/skills/content-taste/content-taste.skill.json +18 -0
- package/skills/creative-director/creative-director.skill.json +18 -0
- package/skills/design-critique/SKILL.md +135 -0
- package/skills/design-critique.catalog.json +12 -0
- package/skills/designing-with-real-components/SKILL.md +140 -0
- package/skills/designing-with-real-components.catalog.json +12 -0
- package/skills/edit-loop/edit-loop.skill.json +25 -0
- package/skills/facecam-edit/facecam-edit.skill.json +24 -0
- package/skills/mapping-the-server/SKILL.md +54 -0
- package/skills/math-explainer-manimgx/math-explainer-manimgx.skill.json +20 -0
- package/skills/motion-quality-gates/motion-quality-gates.skill.json +20 -0
- package/skills/open-design-edit/open-design-edit.skill.json +24 -0
- package/skills/reading-client-progress/SKILL.md +65 -0
- package/skills/routing-to-channels/SKILL.md +54 -0
- package/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
- package/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
- package/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
- package/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
- package/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
- package/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
- package/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
- package/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
- package/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
- package/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
- package/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
- package/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
- package/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
- package/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
- package/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
- package/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
- package/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
- package/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
- package/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
- package/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
- package/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
- package/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
- package/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
- package/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
- package/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
- package/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
- package/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
- package/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
- package/skills/video-direction/video-direction.skill.json +20 -0
- package/skills/video-style-vocabulary/video-style-vocabulary.skill.json +20 -0
- package/skills/video-toolbox/video-toolbox.skill.json +20 -0
- package/src/__fixtures__/lifecycle-presets.flat-before.json +205 -0
- package/src/agency-os.yaml +122 -0
- package/src/agent-os-skill-slugs.test.ts +65 -0
- package/src/apify-social-reader.test.ts +317 -0
- package/src/base.template.test.ts +25 -19
- package/src/base.yaml +95 -39
- package/src/blockchain-ecosystem.yaml +1 -0
- package/src/brand-library.yaml +525 -14
- package/src/builder-dev-fold.template.test.ts +113 -0
- package/src/builder.yaml +798 -92
- package/src/business-model-catalog-description.test.ts +47 -0
- package/src/business-model-grp.template.test.ts +214 -0
- package/src/business-model.yaml +598 -0
- package/src/catalog-safety.test.ts +198 -0
- package/src/catalog.template-items.test.ts +75 -0
- package/src/catalog.ts +85 -2
- package/src/civic-france.yaml +102 -0
- package/src/concept-guard.test.ts +28 -8
- package/src/concept-guard.ts +2 -2
- package/src/content-creation.template.test.ts +52 -0
- package/src/content-creation.yaml +192 -0
- package/src/content-os.edit-loop.template.test.ts +210 -0
- package/src/content-os.publish-due-posts.template.test.ts +261 -0
- package/src/content-os.template.test.ts +322 -0
- package/src/content-os.video-takes.template.test.ts +338 -0
- package/src/content-os.work-a-take.template.test.ts +125 -0
- package/src/content-os.yaml +1830 -39
- package/src/content-studio-retired.template.test.ts +82 -0
- package/src/corpus-flow-validity.test.ts +4 -5
- package/src/crm-absorbs-outreach.template.test.ts +117 -0
- package/src/crm-build-plan.template.test.ts +128 -0
- package/src/crm-lists.template.test.ts +96 -0
- package/src/crm-messages-cadence.template.test.ts +164 -0
- package/src/crm-one-send-door.template.test.ts +65 -0
- package/src/crm.yaml +1456 -181
- package/src/decisions-wave.template.test.ts +186 -0
- package/src/define.ts +130 -17
- package/src/design-to-implementation.template.test.ts +94 -0
- package/src/dist-freshness.test.ts +97 -0
- package/src/domain-template-type.test.ts +75 -0
- package/src/ecosystem.yaml +27 -66
- package/src/enterprise-os.yaml +10 -134
- package/src/facecam-edit.audio-studio.test.ts +188 -0
- package/src/fal-generate-image.test.ts +200 -0
- package/src/fal-media-lab-pod-files.test.ts +180 -0
- package/src/finance.yaml +254 -1
- package/src/foundation.yaml +130 -28
- package/src/frame-host-modules.d.mts +6 -0
- package/src/frame-host-modules.mjs +58 -0
- package/src/generate.mjs +9 -3
- package/src/github-merge.test.ts +210 -0
- package/src/grants.yaml +57 -17
- package/src/hr.yaml +39 -6
- package/src/index.ts +36 -1
- package/src/intent.test.ts +161 -0
- package/src/internal-runbook.yaml +19 -1
- package/src/jev.test.ts +356 -0
- package/src/legal.yaml +33 -1
- package/src/life-os.yaml +65 -240
- package/src/lifecycle-coverage.test.ts +124 -0
- package/src/lifecycle-declarations.test.ts +252 -0
- package/src/lifecycle-presets.test.ts +468 -0
- package/src/lifecycle-presets.ts +494 -0
- package/src/lifecycle-stuck.test.ts +46 -0
- package/src/lifecycle-waits.parity.test.ts +319 -0
- package/src/marketing.yaml +108 -4
- package/src/meetings-knowledge.yaml +18 -0
- package/src/networking.yaml +23 -2
- package/src/operations.yaml +304 -4
- package/src/pipeline-views.template.test.ts +88 -0
- package/src/playbook-goal-placeholders.test.ts +57 -0
- package/src/postiz-contract.test.ts +134 -0
- package/src/presentation-declarations.test.ts +174 -0
- package/src/process-contract.validate.test.ts +352 -0
- package/src/project-management.yaml +39 -740
- package/src/publish-body.d.mts +29 -0
- package/src/publish-body.mjs +74 -0
- package/src/publish-body.test.ts +74 -0
- package/src/publish-official-lib.test.ts +176 -0
- package/src/replicate-rvm.test.ts +504 -0
- package/src/research-base.yaml +119 -20
- package/src/research-decision.yaml +60 -3
- package/src/reserved-profile-slugs.test.ts +83 -0
- package/src/retired-goal-kinds.test.ts +58 -0
- package/src/role-reference-and-step-domain.test.ts +192 -0
- package/src/seed-obligation.test.ts +176 -0
- package/src/send-message-maps.test.ts +227 -0
- package/src/shared-role-ssot.test.ts +42 -1
- package/src/ship-a-change.template.test.ts +177 -0
- package/src/skills.test.ts +170 -0
- package/src/social.yaml +85 -27
- package/src/space-packages.freshness.test.ts +97 -0
- package/src/space-packages.generated.ts +40 -0
- package/src/space-packages.test.ts +125 -0
- package/src/space-packages.ts +73 -0
- package/src/start.test.ts +188 -0
- package/src/task-intents.test.ts +293 -0
- package/src/templates.ts +21639 -21522
- package/src/types.ts +443 -60
- package/src/unipile-publish-post.test.ts +162 -0
- package/src/validate-flow.drift.test.ts +2 -3
- package/src/validate-flow.ts +32 -2
- package/src/validate-onboarding.test.ts +59 -0
- package/src/validate.test.ts +156 -3
- package/src/validate.ts +1384 -7
- package/src/wire-core.ts +231 -0
- package/src/wire.test.ts +159 -0
- package/src/wire.ts +107 -0
- package/src/__fixtures__/report-automation-flow.json +0 -393
- package/src/agent-fleet.yaml +0 -1645
- package/src/business-developer.template.test.ts +0 -351
- package/src/business-developer.yaml +0 -860
- package/src/content-studio.yaml +0 -361
- package/src/dev-dashboard.yaml +0 -990
- package/src/outreach-comms.yaml +0 -486
- package/src/the-arch.yaml +0 -201
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiVersion": "synap/v1",
|
|
3
|
+
"kind": "capability",
|
|
4
|
+
"meta": {
|
|
5
|
+
"slug": "stripe",
|
|
6
|
+
"name": "Stripe — Payments & Billing",
|
|
7
|
+
"description": "Read your Stripe account: list customers, invoices, subscriptions, charges, products and payouts, and read your current balance. Read-only by design — it cannot move money. Needs a Stripe RESTRICTED read-only key, never a full secret key.",
|
|
8
|
+
"tags": [
|
|
9
|
+
"capability"
|
|
10
|
+
],
|
|
11
|
+
"isPublic": true,
|
|
12
|
+
"syncByDefault": true
|
|
13
|
+
},
|
|
14
|
+
"spec": {
|
|
15
|
+
"key": "stripe",
|
|
16
|
+
"name": "Stripe — Payments & Billing",
|
|
17
|
+
"description": "READ-ONLY Stripe access for the user's OWN account (not Connect/marketplace). Authenticates with a Stripe RESTRICTED API key (rk_live_… / rk_test_…) resolved server-side from the vault (vault://stripe) and injected as `Authorization: Bearer <key>` against https://api.stripe.com. List verbs default their limit (20, max 100). Covers customers, charges, invoices, subscriptions, products, payouts and the account balance. This capability deliberately contains NO create/update/refund/cancel verbs — it can read money state but can never move it; a restricted key scoped to read-only (or read + the specific list resources) is the correct credential and a full sk_live secret key should NOT be used. PRECONDITION: a Stripe account with a RESTRICTED API key created in the Dashboard (Developers -> API keys -> Create restricted key); pass it at connect time, it is stored server-encrypted in the vault and never persisted in the template. All endpoints are GET and return data inline, so reads auto-run. NOTE: paths are absolute against baseUrl https://api.stripe.com; response-field shaping (snake_case keys, `.data[]` list envelopes) is verified against Stripe's published API reference (customers/charges/invoices/subscriptions/products/payouts/balance list+retrieve) rather than the live account, and Stripe applies the account's default API version when no `Stripe-Version` header is pinned — so a shape check at first run is prudent. Stripe's top-level list envelope carries `has_more` (there is no `total_count` on the top-level list object), which is surfaced as `hasMore`.",
|
|
18
|
+
"params": [
|
|
19
|
+
{
|
|
20
|
+
"name": "stripeApiKey",
|
|
21
|
+
"label": "Stripe restricted API key",
|
|
22
|
+
"type": "text",
|
|
23
|
+
"required": true,
|
|
24
|
+
"description": "A Stripe RESTRICTED API key (Developers -> API keys -> Create restricted key; starts with rk_live_ or rk_test_). Grant only Read (or the specific list/read resources) — never use a full sk_live secret key. Stored server-encrypted in the vault; never persisted in the template."
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"vault": [
|
|
28
|
+
{
|
|
29
|
+
"ref": "stripe",
|
|
30
|
+
"name": "{{name}} Stripe restricted API key",
|
|
31
|
+
"value": "{{stripeApiKey}}",
|
|
32
|
+
"type": "api_key",
|
|
33
|
+
"service": "stripe",
|
|
34
|
+
"description": "Stripe restricted API key for the stripe connector. Resolved as vault://<id> at apply time and injected as `Authorization: Bearer <key>` against https://api.stripe.com."
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"tools": [
|
|
38
|
+
{
|
|
39
|
+
"name": "stripe",
|
|
40
|
+
"kind": "provider",
|
|
41
|
+
"description": "Authenticated READ access to the user's own Stripe REST API (https://api.stripe.com). credentialRef vault://stripe resolves the user's restricted key from the vault, and the dispatcher injects it as `Authorization: Bearer <key>` (Stripe accepts Bearer auth as well as Basic) into a fixed host — a call-time path can never redirect the credentialed request elsewhere. Its credentialRef is remapped to the runtime vault://<id> at apply time.",
|
|
42
|
+
"credentialRef": "stripe",
|
|
43
|
+
"executor": "is-agent",
|
|
44
|
+
"config": {
|
|
45
|
+
"serviceId": "stripe",
|
|
46
|
+
"baseUrl": "https://api.stripe.com",
|
|
47
|
+
"auth": {
|
|
48
|
+
"in": "header",
|
|
49
|
+
"name": "Authorization",
|
|
50
|
+
"prefix": "Bearer "
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"skills": [
|
|
56
|
+
{
|
|
57
|
+
"name": "stripe_list_customers",
|
|
58
|
+
"intent": "list_records",
|
|
59
|
+
"kind": "declarative",
|
|
60
|
+
"scope": "pod",
|
|
61
|
+
"description": "Lists the user's Stripe customers, most recently created first. Args: { limit?: number (default 20, max 100) }.",
|
|
62
|
+
"requires": [
|
|
63
|
+
"stripe"
|
|
64
|
+
],
|
|
65
|
+
"executionMode": "sync",
|
|
66
|
+
"timeoutSeconds": 30,
|
|
67
|
+
"parameters": {
|
|
68
|
+
"limit": "number?"
|
|
69
|
+
},
|
|
70
|
+
"providerSpec": {
|
|
71
|
+
"tool": "stripe",
|
|
72
|
+
"method": "GET",
|
|
73
|
+
"pathTemplate": "/v1/customers",
|
|
74
|
+
"query": {
|
|
75
|
+
"limit": "{{limit}}"
|
|
76
|
+
},
|
|
77
|
+
"paramMapping": {
|
|
78
|
+
"limit": {
|
|
79
|
+
"default": 20,
|
|
80
|
+
"clampMin": 1,
|
|
81
|
+
"clampMax": 100
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"responseShape": {
|
|
85
|
+
"collectionPath": "data",
|
|
86
|
+
"collectionAs": "customers",
|
|
87
|
+
"item": {
|
|
88
|
+
"id": "id",
|
|
89
|
+
"name": "name",
|
|
90
|
+
"email": "email",
|
|
91
|
+
"created": "created",
|
|
92
|
+
"currency": "currency",
|
|
93
|
+
"description": "description",
|
|
94
|
+
"delinquent": "delinquent"
|
|
95
|
+
},
|
|
96
|
+
"scalar": {
|
|
97
|
+
"count": "@count",
|
|
98
|
+
"hasMore": "has_more"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "stripe_get_customer",
|
|
105
|
+
"intent": "fetch_record",
|
|
106
|
+
"kind": "declarative",
|
|
107
|
+
"scope": "pod",
|
|
108
|
+
"description": "Gets one Stripe customer by id. Args: { customerId: string (a cus_… id) }.",
|
|
109
|
+
"requires": [
|
|
110
|
+
"stripe"
|
|
111
|
+
],
|
|
112
|
+
"executionMode": "sync",
|
|
113
|
+
"timeoutSeconds": 30,
|
|
114
|
+
"parameters": {
|
|
115
|
+
"customerId": "string"
|
|
116
|
+
},
|
|
117
|
+
"providerSpec": {
|
|
118
|
+
"tool": "stripe",
|
|
119
|
+
"method": "GET",
|
|
120
|
+
"pathTemplate": "/v1/customers/{{customerId}}",
|
|
121
|
+
"paramMapping": {
|
|
122
|
+
"customerId": {
|
|
123
|
+
"required": true,
|
|
124
|
+
"encode": "uri"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"responseShape": {
|
|
128
|
+
"scalar": {
|
|
129
|
+
"id": "id",
|
|
130
|
+
"name": "name",
|
|
131
|
+
"email": "email",
|
|
132
|
+
"created": "created",
|
|
133
|
+
"currency": "currency",
|
|
134
|
+
"description": "description",
|
|
135
|
+
"delinquent": "delinquent",
|
|
136
|
+
"balance": "balance"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "stripe_list_charges",
|
|
143
|
+
"intent": "list_records",
|
|
144
|
+
"kind": "declarative",
|
|
145
|
+
"scope": "pod",
|
|
146
|
+
"description": "Lists the user's Stripe charges (payments), most recent first. Args: { limit?: number (default 20, max 100) }.",
|
|
147
|
+
"requires": [
|
|
148
|
+
"stripe"
|
|
149
|
+
],
|
|
150
|
+
"executionMode": "sync",
|
|
151
|
+
"timeoutSeconds": 30,
|
|
152
|
+
"parameters": {
|
|
153
|
+
"limit": "number?"
|
|
154
|
+
},
|
|
155
|
+
"providerSpec": {
|
|
156
|
+
"tool": "stripe",
|
|
157
|
+
"method": "GET",
|
|
158
|
+
"pathTemplate": "/v1/charges",
|
|
159
|
+
"query": {
|
|
160
|
+
"limit": "{{limit}}"
|
|
161
|
+
},
|
|
162
|
+
"paramMapping": {
|
|
163
|
+
"limit": {
|
|
164
|
+
"default": 20,
|
|
165
|
+
"clampMin": 1,
|
|
166
|
+
"clampMax": 100
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"responseShape": {
|
|
170
|
+
"collectionPath": "data",
|
|
171
|
+
"collectionAs": "charges",
|
|
172
|
+
"item": {
|
|
173
|
+
"id": "id",
|
|
174
|
+
"amount": "amount",
|
|
175
|
+
"currency": "currency",
|
|
176
|
+
"status": "status",
|
|
177
|
+
"paid": "paid",
|
|
178
|
+
"refunded": "refunded",
|
|
179
|
+
"created": "created",
|
|
180
|
+
"description": "description",
|
|
181
|
+
"customer": "customer",
|
|
182
|
+
"receiptUrl": "receipt_url"
|
|
183
|
+
},
|
|
184
|
+
"scalar": {
|
|
185
|
+
"count": "@count",
|
|
186
|
+
"hasMore": "has_more"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "stripe_list_invoices",
|
|
193
|
+
"intent": "list_records",
|
|
194
|
+
"kind": "declarative",
|
|
195
|
+
"scope": "pod",
|
|
196
|
+
"description": "Lists the user's Stripe invoices, most recently created first. Args: { limit?: number (default 20, max 100) }.",
|
|
197
|
+
"requires": [
|
|
198
|
+
"stripe"
|
|
199
|
+
],
|
|
200
|
+
"executionMode": "sync",
|
|
201
|
+
"timeoutSeconds": 30,
|
|
202
|
+
"parameters": {
|
|
203
|
+
"limit": "number?"
|
|
204
|
+
},
|
|
205
|
+
"providerSpec": {
|
|
206
|
+
"tool": "stripe",
|
|
207
|
+
"method": "GET",
|
|
208
|
+
"pathTemplate": "/v1/invoices",
|
|
209
|
+
"query": {
|
|
210
|
+
"limit": "{{limit}}"
|
|
211
|
+
},
|
|
212
|
+
"paramMapping": {
|
|
213
|
+
"limit": {
|
|
214
|
+
"default": 20,
|
|
215
|
+
"clampMin": 1,
|
|
216
|
+
"clampMax": 100
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"responseShape": {
|
|
220
|
+
"collectionPath": "data",
|
|
221
|
+
"collectionAs": "invoices",
|
|
222
|
+
"item": {
|
|
223
|
+
"id": "id",
|
|
224
|
+
"number": "number",
|
|
225
|
+
"customer": "customer",
|
|
226
|
+
"customerEmail": "customer_email",
|
|
227
|
+
"status": "status",
|
|
228
|
+
"currency": "currency",
|
|
229
|
+
"amountDue": "amount_due",
|
|
230
|
+
"amountPaid": "amount_paid",
|
|
231
|
+
"created": "created",
|
|
232
|
+
"dueDate": "due_date",
|
|
233
|
+
"hostedInvoiceUrl": "hosted_invoice_url",
|
|
234
|
+
"invoicePdf": "invoice_pdf"
|
|
235
|
+
},
|
|
236
|
+
"scalar": {
|
|
237
|
+
"count": "@count",
|
|
238
|
+
"hasMore": "has_more"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "stripe_list_subscriptions",
|
|
245
|
+
"intent": "list_records",
|
|
246
|
+
"kind": "declarative",
|
|
247
|
+
"scope": "pod",
|
|
248
|
+
"description": "Lists the user's Stripe subscriptions. Stripe returns only non-canceled subscriptions by default; canceled ones are omitted unless a status filter is passed. Args: { limit?: number (default 20, max 100) }.",
|
|
249
|
+
"requires": [
|
|
250
|
+
"stripe"
|
|
251
|
+
],
|
|
252
|
+
"executionMode": "sync",
|
|
253
|
+
"timeoutSeconds": 30,
|
|
254
|
+
"parameters": {
|
|
255
|
+
"limit": "number?"
|
|
256
|
+
},
|
|
257
|
+
"providerSpec": {
|
|
258
|
+
"tool": "stripe",
|
|
259
|
+
"method": "GET",
|
|
260
|
+
"pathTemplate": "/v1/subscriptions",
|
|
261
|
+
"query": {
|
|
262
|
+
"limit": "{{limit}}"
|
|
263
|
+
},
|
|
264
|
+
"paramMapping": {
|
|
265
|
+
"limit": {
|
|
266
|
+
"default": 20,
|
|
267
|
+
"clampMin": 1,
|
|
268
|
+
"clampMax": 100
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
"responseShape": {
|
|
272
|
+
"collectionPath": "data",
|
|
273
|
+
"collectionAs": "subscriptions",
|
|
274
|
+
"item": {
|
|
275
|
+
"id": "id",
|
|
276
|
+
"customer": "customer",
|
|
277
|
+
"status": "status",
|
|
278
|
+
"currency": "currency",
|
|
279
|
+
"created": "created",
|
|
280
|
+
"latestInvoice": "latest_invoice",
|
|
281
|
+
"cancelAtPeriodEnd": "cancel_at_period_end"
|
|
282
|
+
},
|
|
283
|
+
"scalar": {
|
|
284
|
+
"count": "@count",
|
|
285
|
+
"hasMore": "has_more"
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
"name": "stripe_list_products",
|
|
292
|
+
"intent": "list_records",
|
|
293
|
+
"kind": "declarative",
|
|
294
|
+
"scope": "pod",
|
|
295
|
+
"description": "Lists the user's Stripe products, most recently created first. Args: { limit?: number (default 20, max 100) }.",
|
|
296
|
+
"requires": [
|
|
297
|
+
"stripe"
|
|
298
|
+
],
|
|
299
|
+
"executionMode": "sync",
|
|
300
|
+
"timeoutSeconds": 30,
|
|
301
|
+
"parameters": {
|
|
302
|
+
"limit": "number?"
|
|
303
|
+
},
|
|
304
|
+
"providerSpec": {
|
|
305
|
+
"tool": "stripe",
|
|
306
|
+
"method": "GET",
|
|
307
|
+
"pathTemplate": "/v1/products",
|
|
308
|
+
"query": {
|
|
309
|
+
"limit": "{{limit}}"
|
|
310
|
+
},
|
|
311
|
+
"paramMapping": {
|
|
312
|
+
"limit": {
|
|
313
|
+
"default": 20,
|
|
314
|
+
"clampMin": 1,
|
|
315
|
+
"clampMax": 100
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
"responseShape": {
|
|
319
|
+
"collectionPath": "data",
|
|
320
|
+
"collectionAs": "products",
|
|
321
|
+
"item": {
|
|
322
|
+
"id": "id",
|
|
323
|
+
"name": "name",
|
|
324
|
+
"active": "active",
|
|
325
|
+
"description": "description",
|
|
326
|
+
"created": "created",
|
|
327
|
+
"updated": "updated",
|
|
328
|
+
"defaultPrice": "default_price"
|
|
329
|
+
},
|
|
330
|
+
"scalar": {
|
|
331
|
+
"count": "@count",
|
|
332
|
+
"hasMore": "has_more"
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"name": "stripe_list_payouts",
|
|
339
|
+
"intent": "list_records",
|
|
340
|
+
"kind": "declarative",
|
|
341
|
+
"scope": "pod",
|
|
342
|
+
"description": "Lists the user's Stripe payouts to bank accounts, most recently created first. Args: { limit?: number (default 20, max 100) }.",
|
|
343
|
+
"requires": [
|
|
344
|
+
"stripe"
|
|
345
|
+
],
|
|
346
|
+
"executionMode": "sync",
|
|
347
|
+
"timeoutSeconds": 30,
|
|
348
|
+
"parameters": {
|
|
349
|
+
"limit": "number?"
|
|
350
|
+
},
|
|
351
|
+
"providerSpec": {
|
|
352
|
+
"tool": "stripe",
|
|
353
|
+
"method": "GET",
|
|
354
|
+
"pathTemplate": "/v1/payouts",
|
|
355
|
+
"query": {
|
|
356
|
+
"limit": "{{limit}}"
|
|
357
|
+
},
|
|
358
|
+
"paramMapping": {
|
|
359
|
+
"limit": {
|
|
360
|
+
"default": 20,
|
|
361
|
+
"clampMin": 1,
|
|
362
|
+
"clampMax": 100
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
"responseShape": {
|
|
366
|
+
"collectionPath": "data",
|
|
367
|
+
"collectionAs": "payouts",
|
|
368
|
+
"item": {
|
|
369
|
+
"id": "id",
|
|
370
|
+
"amount": "amount",
|
|
371
|
+
"currency": "currency",
|
|
372
|
+
"status": "status",
|
|
373
|
+
"created": "created",
|
|
374
|
+
"arrivalDate": "arrival_date",
|
|
375
|
+
"description": "description",
|
|
376
|
+
"method": "method",
|
|
377
|
+
"type": "type"
|
|
378
|
+
},
|
|
379
|
+
"scalar": {
|
|
380
|
+
"count": "@count",
|
|
381
|
+
"hasMore": "has_more"
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "stripe_get_balance",
|
|
388
|
+
"intent": "fetch_record",
|
|
389
|
+
"kind": "declarative",
|
|
390
|
+
"scope": "pod",
|
|
391
|
+
"description": "Gets the account's current Stripe balance: `available` and `pending` are per-currency lists of { amount, currency, source_types }, plus any connect_reserved. No args.",
|
|
392
|
+
"requires": [
|
|
393
|
+
"stripe"
|
|
394
|
+
],
|
|
395
|
+
"executionMode": "sync",
|
|
396
|
+
"timeoutSeconds": 30,
|
|
397
|
+
"parameters": {},
|
|
398
|
+
"providerSpec": {
|
|
399
|
+
"tool": "stripe",
|
|
400
|
+
"method": "GET",
|
|
401
|
+
"pathTemplate": "/v1/balance",
|
|
402
|
+
"responseShape": {
|
|
403
|
+
"scalar": {
|
|
404
|
+
"object": "object",
|
|
405
|
+
"livemode": "livemode",
|
|
406
|
+
"available": "available",
|
|
407
|
+
"pending": "pending",
|
|
408
|
+
"connectReserved": "connect_reserved"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
],
|
|
414
|
+
"provides": [
|
|
415
|
+
"list_records",
|
|
416
|
+
"fetch_record"
|
|
417
|
+
]
|
|
418
|
+
},
|
|
419
|
+
"dependencies": []
|
|
420
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiVersion": "synap/v1",
|
|
3
|
+
"kind": "capability",
|
|
4
|
+
"meta": {
|
|
5
|
+
"slug": "telegram-bridge",
|
|
6
|
+
"name": "Telegram Bridge",
|
|
7
|
+
"description": "Two-way Telegram messaging with clients: group messages arrive in each client's channel in Synap, and replies go back through the bridge. Needs a Telegram bot token and the Synap messaging bridge set up with it.",
|
|
8
|
+
"tags": [
|
|
9
|
+
"capability"
|
|
10
|
+
],
|
|
11
|
+
"isPublic": true,
|
|
12
|
+
"syncByDefault": true
|
|
13
|
+
},
|
|
14
|
+
"spec": {
|
|
15
|
+
"key": "telegram-bridge",
|
|
16
|
+
"name": "Telegram Bridge",
|
|
17
|
+
"description": "Telegram two-way messaging via an EXTERNAL bridge gateway (the Telegram/Discord/WhatsApp bridge worker that lives OUTSIDE this repo). This template represents the bridge connection: it stores the bridge bot token in the vault and registers one external tool whose credentialRef is remapped to the runtime vault://<id> at apply time. Inbound Telegram messages are delivered by the bridge into the client's entity-bound channel (inbound-recorder substrate, shipped); outbound sends are dispatched by the bridge against this connection. PRECONDITION: a Telegram bot (BotFather) added to the target groups, and the external bridge gateway configured with this same token. Pass the bot token as telegramBotToken. Outbound send code skills are NOT seeded here — the bridge owns delivery; this template establishes the connection + auth.",
|
|
18
|
+
"metadata": {
|
|
19
|
+
"mode": "standing"
|
|
20
|
+
},
|
|
21
|
+
"params": [
|
|
22
|
+
{
|
|
23
|
+
"name": "telegramBotToken",
|
|
24
|
+
"label": "Telegram bridge bot token",
|
|
25
|
+
"type": "text",
|
|
26
|
+
"required": true,
|
|
27
|
+
"description": "The Telegram bot token (BotFather) used by the external bridge gateway. Stored server-encrypted in the vault; never persisted in the template."
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"vault": [
|
|
31
|
+
{
|
|
32
|
+
"ref": "telegramBotTokenSecret",
|
|
33
|
+
"name": "{{name}} Telegram bridge bot token",
|
|
34
|
+
"value": "{{telegramBotToken}}",
|
|
35
|
+
"type": "api_key",
|
|
36
|
+
"description": "Telegram bot token for the external bridge gateway (telegram connector)."
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
"tools": [
|
|
40
|
+
{
|
|
41
|
+
"name": "telegram",
|
|
42
|
+
"kind": "external",
|
|
43
|
+
"description": "Telegram messaging via the external bridge gateway. The bridge holds the connection; this tool's credentialRef is remapped to the runtime vault://<id> at apply time so the bridge token resolves server-side. Inbound is delivered by the bridge into the client's channel; outbound sends are dispatched by the bridge.",
|
|
44
|
+
"credentialRef": "telegramBotTokenSecret",
|
|
45
|
+
"executor": "external-agent",
|
|
46
|
+
"config": {
|
|
47
|
+
"transport": "bridge",
|
|
48
|
+
"externalSource": "telegram"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"skills": [],
|
|
53
|
+
"provides": []
|
|
54
|
+
},
|
|
55
|
+
"dependencies": []
|
|
56
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"apiVersion": "synap/v1",
|
|
3
|
+
"kind": "capability",
|
|
4
|
+
"meta": {
|
|
5
|
+
"slug": "treg",
|
|
6
|
+
"name": "treg — Tool catalog",
|
|
7
|
+
"description": "Find a provider endpoint on treg.to by the job you need, then run it with your treg token. Search is free and shows the price. Running an endpoint spends prepaid balance and waits for your approval. Sign up at treg.to yourself and paste one token.",
|
|
8
|
+
"tags": [
|
|
9
|
+
"capability",
|
|
10
|
+
"search_external",
|
|
11
|
+
"run_external_job"
|
|
12
|
+
],
|
|
13
|
+
"isPublic": true,
|
|
14
|
+
"syncByDefault": true
|
|
15
|
+
},
|
|
16
|
+
"spec": {
|
|
17
|
+
"key": "treg",
|
|
18
|
+
"name": "treg — Tool catalog",
|
|
19
|
+
"description": "Call provider endpoints through treg (https://treg.to) with one token the user pastes. The user signs up at https://treg.to themselves; Synap does not host signup and this is not a messaging bridge. Verified against https://treg.to/docs and https://treg.to/llms.txt (2026-09-29): base https://treg.to, auth header X-Treg-Token with an empty prefix. Do not send the token as Authorization: Bearer — REST ignores Bearer (401) and /call/ would relay that header to the provider. GET /catalog/search?q= finds endpoints and already includes price (cost.usd). GET /call/{endpoint_id} with a query string runs a catalog endpoint and spends prepaid balance, so that verb is not read-only. A catalog entry whose input is a JSON body (method POST) is a different shape; this pack's call verb sends the query object as the query string only.",
|
|
20
|
+
"params": [
|
|
21
|
+
{
|
|
22
|
+
"name": "tregToken",
|
|
23
|
+
"label": "treg token",
|
|
24
|
+
"type": "text",
|
|
25
|
+
"required": true,
|
|
26
|
+
"description": "Token from the user's own treg.to account (https://treg.to). Sent as the X-Treg-Token header, not as Authorization. Stored server-encrypted in the vault; never persisted in the template."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"vault": [
|
|
30
|
+
{
|
|
31
|
+
"ref": "tregTokenSecret",
|
|
32
|
+
"name": "{{name}} treg token",
|
|
33
|
+
"value": "{{tregToken}}",
|
|
34
|
+
"type": "api_key",
|
|
35
|
+
"description": "treg token for the treg_api connector. The applier remaps this template-local ref to vault://<id>."
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"tools": [
|
|
39
|
+
{
|
|
40
|
+
"name": "treg_api",
|
|
41
|
+
"kind": "api",
|
|
42
|
+
"description": "Authenticated HTTP access to treg (https://treg.to). The applier injects the vaulted token into the X-Treg-Token header with an empty prefix — treg REST does not use Authorization: Bearer. credentialRef is remapped to vault://<id> at apply.",
|
|
43
|
+
"credentialRef": "tregTokenSecret",
|
|
44
|
+
"executor": "is-agent",
|
|
45
|
+
"config": {
|
|
46
|
+
"baseUrl": "https://treg.to",
|
|
47
|
+
"auth": {
|
|
48
|
+
"in": "header",
|
|
49
|
+
"name": "X-Treg-Token",
|
|
50
|
+
"prefix": ""
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"skills": [
|
|
56
|
+
{
|
|
57
|
+
"name": "treg_search",
|
|
58
|
+
"intent": "search_external",
|
|
59
|
+
"kind": "code",
|
|
60
|
+
"scope": "pod",
|
|
61
|
+
"description": "Finds treg catalog endpoints for a job. Read-only: GET /catalog/search (the catalog does not spend balance). Returns at most 5 rows of { id, name, price }, where price is cost.usd (else cost.value) from the search payload. Args: { query: string }.",
|
|
62
|
+
"requires": [
|
|
63
|
+
"treg_api"
|
|
64
|
+
],
|
|
65
|
+
"executionMode": "sync",
|
|
66
|
+
"timeoutSeconds": 30,
|
|
67
|
+
"parameters": {
|
|
68
|
+
"query": "string"
|
|
69
|
+
},
|
|
70
|
+
"code": "// Catalog search. Executor wraps this body as (async (args, context) => { <code> }).\n// callProvider('treg_api','GET', path) injects X-Treg-Token. GET /catalog/search\n// is open and already includes price on each result (cost.usd) — no second get.\nconst query = String(args?.query ?? '').trim();\nif (!query) throw new Error('treg_search: query is required');\n\nconst res = await callProvider('treg_api', 'GET', '/catalog/search?q=' + encodeURIComponent(query) + '&limit=5');\nconst payload = res?.body ?? res;\nconst rows = Array.isArray(payload?.results) ? payload.results : [];\nconst results = rows.slice(0, 5).map((r) => {\n const cost = r?.cost;\n let price = null;\n if (cost && typeof cost === 'object') {\n if (typeof cost.usd === 'number') price = cost.usd;\n else if (typeof cost.value === 'number') price = cost.value;\n }\n return { id: r?.id ?? null, name: r?.name ?? null, price };\n});\nreturn { query, count: results.length, results };",
|
|
71
|
+
"metadata": {
|
|
72
|
+
"readOnly": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "treg_call",
|
|
77
|
+
"intent": "run_external_job",
|
|
78
|
+
"kind": "code",
|
|
79
|
+
"scope": "pod",
|
|
80
|
+
"description": "Runs one treg catalog endpoint and spends prepaid balance. Not read-only: the run is proposal-gated. HTTP shape verified at https://treg.to/docs: GET /call/{endpoint_id} with the query object as the query string (example: /call/tikhub.tiktok.user.profile?uniqueId=tiktok). Does not send a JSON body and does not poll async generation tasks. Returns the upstream body, plus chargedMicro (X-Treg-Cost-Micro, else _treg.charged_micro) and callId (X-Treg-Call-Id) when the response has them. Args: { endpointId: string, query?: object }.",
|
|
81
|
+
"requires": [
|
|
82
|
+
"treg_api"
|
|
83
|
+
],
|
|
84
|
+
"executionMode": "sync",
|
|
85
|
+
"timeoutSeconds": 60,
|
|
86
|
+
"parameters": {
|
|
87
|
+
"endpointId": "string",
|
|
88
|
+
"query": "object?"
|
|
89
|
+
},
|
|
90
|
+
"code": "// Catalog call. Executor wraps this body as (async (args, context) => { <code> }).\n// callProvider('treg_api','GET', path) injects X-Treg-Token (empty prefix, not Bearer).\n// Docs: GET https://treg.to/call/{endpoint_id}?... — method and query string pass through.\n// This verb is not metadata.readOnly, so the skill gate proposes before the spend.\nconst endpointId = String(args?.endpointId ?? '').trim();\nif (!endpointId) throw new Error('treg_call: endpointId is required');\nif (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(endpointId)) {\n throw new Error('treg_call: endpointId must be a catalog id, not a URL');\n}\n\nlet qs = '';\nif (args?.query !== undefined && args?.query !== null) {\n if (typeof args.query !== 'object' || Array.isArray(args.query)) {\n throw new Error('treg_call: query must be an object of parameters');\n }\n const parts = [];\n for (const [key, value] of Object.entries(args.query)) {\n if (value === undefined || value === null) continue;\n const encoded = typeof value === 'object' ? JSON.stringify(value) : String(value);\n parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(encoded));\n }\n qs = parts.join('&');\n}\n\nconst path = '/call/' + encodeURIComponent(endpointId) + (qs ? '?' + qs : '');\nconst res = await callProvider('treg_api', 'GET', path);\nif (res?.proposed === true) {\n return { success: false, proposed: true, proposalId: res?.proposalId ?? null, endpointId };\n}\nconst payload = res?.body !== undefined ? res.body : res;\nconst headers = res?.headers && typeof res.headers === 'object' ? res.headers : {};\nconst header = (name) => {\n const want = name.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (String(k).toLowerCase() === want && v != null) return String(v);\n }\n return null;\n};\nconst costHeader = header('x-treg-cost-micro');\nconst chargedFromHeader = costHeader != null && /^-?\\d+$/.test(costHeader) ? Number(costHeader) : null;\nconst tregMeta = payload && typeof payload === 'object' && !Array.isArray(payload) ? payload._treg : null;\nconst chargedFromBody = tregMeta && typeof tregMeta.charged_micro === 'number' ? tregMeta.charged_micro : null;\nconst chargedMicro = chargedFromHeader != null ? chargedFromHeader : chargedFromBody;\nconst callId = header('x-treg-call-id');\nconst out = { endpointId, status: res?.status ?? null, body: payload };\nif (chargedMicro != null) out.chargedMicro = chargedMicro;\nif (callId) out.callId = callId;\nreturn out;",
|
|
91
|
+
"metadata": {
|
|
92
|
+
"verbType": "write"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"provides": [
|
|
97
|
+
"search_external",
|
|
98
|
+
"run_external_job"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"dependencies": []
|
|
102
|
+
}
|