synthos 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +215 -65
  2. package/default-pages/application.json +1 -0
  3. package/default-pages/json_tools.json +1 -1
  4. package/default-pages/oregon_trail.html +321 -0
  5. package/default-pages/oregon_trail.json +12 -0
  6. package/default-pages/sidebar_page.json +1 -0
  7. package/default-pages/solar_explorer.html +10 -18
  8. package/default-pages/solar_explorer.json +2 -2
  9. package/default-pages/two-panel_page.json +1 -0
  10. package/default-pages/us_map.html +192 -0
  11. package/default-pages/us_map.json +12 -0
  12. package/default-pages/us_map_1850.html +325 -0
  13. package/default-pages/us_map_1850.json +12 -0
  14. package/default-pages/western_cities_1850.html +526 -0
  15. package/default-pages/western_cities_1850.json +12 -0
  16. package/default-themes/{nebula-dawn.css → nebula-dawn.v2.css} +24 -0
  17. package/default-themes/{nebula-dusk.css → nebula-dusk.v2.css} +24 -0
  18. package/dist/agents/a2a/a2aProvider.d.ts +3 -0
  19. package/dist/agents/a2a/a2aProvider.d.ts.map +1 -0
  20. package/dist/agents/a2a/a2aProvider.js +126 -0
  21. package/dist/agents/a2a/a2aProvider.js.map +1 -0
  22. package/dist/agents/discovery.d.ts +30 -0
  23. package/dist/agents/discovery.d.ts.map +1 -0
  24. package/dist/agents/discovery.js +52 -0
  25. package/dist/agents/discovery.js.map +1 -0
  26. package/dist/agents/index.d.ts +7 -0
  27. package/dist/agents/index.d.ts.map +1 -0
  28. package/dist/agents/index.js +19 -0
  29. package/dist/agents/index.js.map +1 -0
  30. package/dist/agents/openclaw/gatewayManager.d.ts +113 -0
  31. package/dist/agents/openclaw/gatewayManager.d.ts.map +1 -0
  32. package/dist/agents/openclaw/gatewayManager.js +470 -0
  33. package/dist/agents/openclaw/gatewayManager.js.map +1 -0
  34. package/dist/agents/openclaw/openclawProvider.d.ts +3 -0
  35. package/dist/agents/openclaw/openclawProvider.d.ts.map +1 -0
  36. package/dist/agents/openclaw/openclawProvider.js +239 -0
  37. package/dist/agents/openclaw/openclawProvider.js.map +1 -0
  38. package/dist/agents/openclaw/sshTunnelManager.d.ts +23 -0
  39. package/dist/agents/openclaw/sshTunnelManager.d.ts.map +1 -0
  40. package/dist/agents/openclaw/sshTunnelManager.js +340 -0
  41. package/dist/agents/openclaw/sshTunnelManager.js.map +1 -0
  42. package/dist/agents/types.d.ts +64 -0
  43. package/dist/agents/types.d.ts.map +1 -0
  44. package/dist/agents/types.js +6 -0
  45. package/dist/agents/types.js.map +1 -0
  46. package/dist/connectors/airtable/connector.json +27 -0
  47. package/dist/connectors/alpha-vantage/connector.json +26 -0
  48. package/dist/connectors/brave-search/connector.json +26 -0
  49. package/dist/connectors/cloudinary/connector.json +27 -0
  50. package/dist/connectors/deepl/connector.json +28 -0
  51. package/dist/connectors/elevenlabs/connector.json +30 -0
  52. package/dist/connectors/giphy/connector.json +27 -0
  53. package/dist/connectors/github/connector.json +29 -0
  54. package/dist/connectors/huggingface/connector.json +27 -0
  55. package/dist/connectors/imgur/connector.json +29 -0
  56. package/dist/connectors/index.d.ts +1 -1
  57. package/dist/connectors/index.d.ts.map +1 -1
  58. package/dist/connectors/instagram/connector.json +43 -0
  59. package/dist/connectors/jira/connector.json +28 -0
  60. package/dist/connectors/mapbox/connector.json +26 -0
  61. package/dist/connectors/nasa/connector.json +27 -0
  62. package/dist/connectors/newsapi/connector.json +27 -0
  63. package/dist/connectors/notion/connector.json +28 -0
  64. package/dist/connectors/open-exchange-rates/connector.json +27 -0
  65. package/dist/connectors/openweathermap/connector.json +26 -0
  66. package/dist/connectors/pexels/connector.json +27 -0
  67. package/dist/connectors/registry.d.ts.map +1 -1
  68. package/dist/connectors/registry.js +42 -96
  69. package/dist/connectors/registry.js.map +1 -1
  70. package/dist/connectors/resend/connector.json +29 -0
  71. package/dist/connectors/rss2json/connector.json +27 -0
  72. package/dist/connectors/sendgrid/connector.json +27 -0
  73. package/dist/connectors/spoonacular/connector.json +28 -0
  74. package/dist/connectors/stability-ai/connector.json +27 -0
  75. package/dist/connectors/twilio/connector.json +28 -0
  76. package/dist/connectors/types.d.ts +23 -0
  77. package/dist/connectors/types.d.ts.map +1 -1
  78. package/dist/connectors/unsplash/connector.json +27 -0
  79. package/dist/connectors/wolfram-alpha/connector.json +26 -0
  80. package/dist/connectors/youtube-data/connector.json +30 -0
  81. package/dist/files.d.ts +1 -0
  82. package/dist/files.d.ts.map +1 -1
  83. package/dist/files.js +16 -1
  84. package/dist/files.js.map +1 -1
  85. package/dist/init.d.ts.map +1 -1
  86. package/dist/init.js +28 -0
  87. package/dist/init.js.map +1 -1
  88. package/dist/migrations.d.ts +3 -2
  89. package/dist/migrations.d.ts.map +1 -1
  90. package/dist/migrations.js +122 -138
  91. package/dist/migrations.js.map +1 -1
  92. package/dist/models/anthropic.d.ts +22 -0
  93. package/dist/models/anthropic.d.ts.map +1 -0
  94. package/dist/models/anthropic.js +76 -0
  95. package/dist/models/anthropic.js.map +1 -0
  96. package/dist/models/chainOfThought.d.ts +12 -0
  97. package/dist/models/chainOfThought.d.ts.map +1 -0
  98. package/dist/models/chainOfThought.js +45 -0
  99. package/dist/models/chainOfThought.js.map +1 -0
  100. package/dist/models/fireworksai.d.ts +30 -0
  101. package/dist/models/fireworksai.d.ts.map +1 -0
  102. package/dist/models/fireworksai.js +133 -0
  103. package/dist/models/fireworksai.js.map +1 -0
  104. package/dist/models/index.d.ts +7 -1
  105. package/dist/models/index.d.ts.map +1 -1
  106. package/dist/models/index.js +19 -1
  107. package/dist/models/index.js.map +1 -1
  108. package/dist/models/logCompletePrompt.d.ts +3 -0
  109. package/dist/models/logCompletePrompt.d.ts.map +1 -0
  110. package/dist/models/logCompletePrompt.js +23 -0
  111. package/dist/models/logCompletePrompt.js.map +1 -0
  112. package/dist/models/openai.d.ts +24 -0
  113. package/dist/models/openai.d.ts.map +1 -0
  114. package/dist/models/openai.js +80 -0
  115. package/dist/models/openai.js.map +1 -0
  116. package/dist/models/providers.d.ts +1 -0
  117. package/dist/models/providers.d.ts.map +1 -1
  118. package/dist/models/providers.js +12 -4
  119. package/dist/models/providers.js.map +1 -1
  120. package/dist/models/types.d.ts +34 -2
  121. package/dist/models/types.d.ts.map +1 -1
  122. package/dist/models/types.js +16 -0
  123. package/dist/models/types.js.map +1 -1
  124. package/dist/models/utils.d.ts +6 -0
  125. package/dist/models/utils.d.ts.map +1 -0
  126. package/dist/models/utils.js +21 -0
  127. package/dist/models/utils.js.map +1 -0
  128. package/dist/scripts.d.ts +2 -1
  129. package/dist/scripts.d.ts.map +1 -1
  130. package/dist/scripts.js +4 -3
  131. package/dist/scripts.js.map +1 -1
  132. package/dist/service/createCompletePrompt.d.ts +1 -1
  133. package/dist/service/createCompletePrompt.d.ts.map +1 -1
  134. package/dist/service/createCompletePrompt.js +9 -6
  135. package/dist/service/createCompletePrompt.js.map +1 -1
  136. package/dist/service/generateImage.d.ts +1 -1
  137. package/dist/service/generateImage.d.ts.map +1 -1
  138. package/dist/service/generateImage.js +3 -3
  139. package/dist/service/generateImage.js.map +1 -1
  140. package/dist/service/server.d.ts.map +1 -1
  141. package/dist/service/server.js +3 -0
  142. package/dist/service/server.js.map +1 -1
  143. package/dist/service/transformPage.d.ts +4 -2
  144. package/dist/service/transformPage.d.ts.map +1 -1
  145. package/dist/service/transformPage.js +74 -6
  146. package/dist/service/transformPage.js.map +1 -1
  147. package/dist/service/useAgentRoutes.d.ts +4 -0
  148. package/dist/service/useAgentRoutes.d.ts.map +1 -0
  149. package/dist/service/useAgentRoutes.js +389 -0
  150. package/dist/service/useAgentRoutes.js.map +1 -0
  151. package/dist/service/useApiRoutes.d.ts.map +1 -1
  152. package/dist/service/useApiRoutes.js +157 -16
  153. package/dist/service/useApiRoutes.js.map +1 -1
  154. package/dist/service/useConnectorRoutes.d.ts.map +1 -1
  155. package/dist/service/useConnectorRoutes.js +14 -3
  156. package/dist/service/useConnectorRoutes.js.map +1 -1
  157. package/dist/service/useGatewayRoutes.d.ts +4 -0
  158. package/dist/service/useGatewayRoutes.d.ts.map +1 -0
  159. package/dist/service/useGatewayRoutes.js +168 -0
  160. package/dist/service/useGatewayRoutes.js.map +1 -0
  161. package/dist/service/usePageRoutes.d.ts.map +1 -1
  162. package/dist/service/usePageRoutes.js +16 -5
  163. package/dist/service/usePageRoutes.js.map +1 -1
  164. package/dist/settings.d.ts +2 -1
  165. package/dist/settings.d.ts.map +1 -1
  166. package/dist/settings.js +4 -8
  167. package/dist/settings.js.map +1 -1
  168. package/dist/themes.d.ts +14 -0
  169. package/dist/themes.d.ts.map +1 -1
  170. package/dist/themes.js +86 -13
  171. package/dist/themes.js.map +1 -1
  172. package/package.json +8 -5
  173. package/page-scripts/helpers-v2.js +101 -0
  174. package/page-scripts/page-v2.js +47 -6
  175. package/required-pages/builder.html +1 -27
  176. package/required-pages/pages.html +745 -22
  177. package/required-pages/settings.html +819 -21
  178. package/required-pages/synthos_apis.html +56 -1
  179. package/src/agents/a2a/a2aProvider.ts +110 -0
  180. package/src/agents/discovery.ts +74 -0
  181. package/src/agents/index.ts +6 -0
  182. package/src/agents/openclaw/gatewayManager.ts +559 -0
  183. package/src/agents/openclaw/openclawProvider.ts +261 -0
  184. package/src/agents/openclaw/sshTunnelManager.ts +385 -0
  185. package/src/agents/types.ts +82 -0
  186. package/src/connectors/airtable/connector.json +27 -0
  187. package/src/connectors/alpha-vantage/connector.json +26 -0
  188. package/src/connectors/brave-search/connector.json +26 -0
  189. package/src/connectors/cloudinary/connector.json +27 -0
  190. package/src/connectors/deepl/connector.json +28 -0
  191. package/src/connectors/elevenlabs/connector.json +30 -0
  192. package/src/connectors/giphy/connector.json +27 -0
  193. package/src/connectors/github/connector.json +29 -0
  194. package/src/connectors/huggingface/connector.json +27 -0
  195. package/src/connectors/imgur/connector.json +29 -0
  196. package/src/connectors/index.ts +2 -0
  197. package/src/connectors/instagram/connector.json +43 -0
  198. package/src/connectors/jira/connector.json +28 -0
  199. package/src/connectors/mapbox/connector.json +26 -0
  200. package/src/connectors/nasa/connector.json +27 -0
  201. package/src/connectors/newsapi/connector.json +27 -0
  202. package/src/connectors/notion/connector.json +28 -0
  203. package/src/connectors/open-exchange-rates/connector.json +27 -0
  204. package/src/connectors/openweathermap/connector.json +26 -0
  205. package/src/connectors/pexels/connector.json +27 -0
  206. package/src/connectors/registry.ts +21 -97
  207. package/src/connectors/resend/connector.json +29 -0
  208. package/src/connectors/rss2json/connector.json +27 -0
  209. package/src/connectors/sendgrid/connector.json +27 -0
  210. package/src/connectors/spoonacular/connector.json +28 -0
  211. package/src/connectors/stability-ai/connector.json +27 -0
  212. package/src/connectors/twilio/connector.json +28 -0
  213. package/src/connectors/types.ts +25 -0
  214. package/src/connectors/unsplash/connector.json +27 -0
  215. package/src/connectors/wolfram-alpha/connector.json +26 -0
  216. package/src/connectors/youtube-data/connector.json +30 -0
  217. package/src/files.ts +14 -0
  218. package/src/init.ts +27 -0
  219. package/src/migrations.ts +121 -138
  220. package/src/models/anthropic.ts +89 -0
  221. package/src/models/chainOfThought.ts +56 -0
  222. package/src/models/fireworksai.ts +136 -0
  223. package/src/models/index.ts +7 -1
  224. package/src/models/logCompletePrompt.ts +25 -0
  225. package/src/models/openai.ts +90 -0
  226. package/src/models/providers.ts +12 -3
  227. package/src/models/types.ts +67 -2
  228. package/src/models/utils.ts +16 -0
  229. package/src/scripts.ts +2 -2
  230. package/src/service/createCompletePrompt.ts +3 -1
  231. package/src/service/generateImage.ts +2 -2
  232. package/src/service/server.ts +4 -0
  233. package/src/service/transformPage.ts +81 -8
  234. package/src/service/useAgentRoutes.ts +423 -0
  235. package/src/service/useApiRoutes.ts +173 -18
  236. package/src/service/useConnectorRoutes.ts +14 -3
  237. package/src/service/usePageRoutes.ts +20 -6
  238. package/src/settings.ts +6 -10
  239. package/src/themes.ts +84 -12
  240. package/tests/anthropic.spec.ts +84 -0
  241. package/tests/chainOfThought.spec.ts +108 -0
  242. package/tests/ensureScripts.spec.ts +82 -0
  243. package/tests/files.spec.ts +233 -0
  244. package/tests/fireworksai.spec.ts +92 -0
  245. package/tests/logCompletePrompt.spec.ts +74 -0
  246. package/tests/migrations.spec.ts +79 -1
  247. package/tests/openai.spec.ts +71 -0
  248. package/tests/pages.spec.ts +226 -1
  249. package/tests/providers.spec.ts +144 -0
  250. package/tests/scripts.spec.ts +209 -0
  251. package/tests/transformPage.spec.ts +517 -0
  252. package/tests/types.spec.ts +23 -0
  253. package/default-pages/app_builder.json +0 -1
  254. package/default-pages/sidebar_builder.json +0 -1
  255. package/default-pages/two-panel_builder.json +0 -1
  256. package/images/home.png +0 -0
  257. package/images/page-management.png +0 -0
  258. package/images/settings.png +0 -0
  259. package/images/synthos-square.png +0 -0
  260. /package/default-pages/{app_builder.html → application.html} +0 -0
  261. /package/default-pages/{sidebar_builder.html → sidebar_page.html} +0 -0
  262. /package/default-pages/{two-panel_builder.html → two-panel_page.html} +0 -0
@@ -0,0 +1,64 @@
1
+ export interface AgentConfig {
2
+ id: string;
3
+ url: string;
4
+ name: string;
5
+ description: string;
6
+ iconUrl?: string;
7
+ enabled: boolean;
8
+ provider: 'a2a' | 'openclaw';
9
+ /** Auth token (openclaw only) */
10
+ token?: string;
11
+ /** Default session key for chat (openclaw only, e.g. "agent:main:main") */
12
+ sessionKey?: string;
13
+ capabilities?: {
14
+ streaming?: boolean;
15
+ pushNotifications?: boolean;
16
+ };
17
+ skills?: {
18
+ id: string;
19
+ name: string;
20
+ description: string;
21
+ tags: string[];
22
+ }[];
23
+ /** SSH tunnel config (openclaw only) — spawns an SSH tunnel before WebSocket connection */
24
+ sshTunnel?: {
25
+ enabled: boolean;
26
+ /** Full SSH command, e.g. "ssh -p 22 -N -L 18789:127.0.0.1:43901 root@1.2.3.4" */
27
+ command: string;
28
+ /** Password to pipe when prompted */
29
+ password: string;
30
+ };
31
+ }
32
+ export interface Attachment {
33
+ fileName: string;
34
+ mimeType: string;
35
+ /** base64 for binary, plain string for text */
36
+ content: string;
37
+ }
38
+ export interface ChatMessage {
39
+ role: 'user' | 'assistant';
40
+ content: string;
41
+ timestamp?: number;
42
+ /** Raw provider-specific payload for debugging */
43
+ raw?: unknown;
44
+ }
45
+ export interface AgentResponse {
46
+ kind: 'message' | 'task';
47
+ text?: string;
48
+ raw: unknown;
49
+ taskId?: string;
50
+ status?: string;
51
+ }
52
+ export interface AgentEvent {
53
+ kind: 'text' | 'status' | 'artifact' | 'done' | 'error';
54
+ data: unknown;
55
+ }
56
+ export interface AgentProvider {
57
+ send(agent: AgentConfig, message: string, attachments?: Attachment[]): Promise<AgentResponse>;
58
+ sendStream(agent: AgentConfig, message: string, attachments?: Attachment[]): AsyncIterable<AgentEvent>;
59
+ supportsStreaming(agent: AgentConfig): boolean;
60
+ getHistory?(agent: AgentConfig): Promise<ChatMessage[]>;
61
+ abortChat?(agent: AgentConfig): Promise<void>;
62
+ clearSession?(agent: AgentConfig): Promise<void>;
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,GAAG,UAAU,CAAC;IAC7B,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACpE,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAC7E,2FAA2F;IAC3F,SAAS,CAAC,EAAE;QACR,OAAO,EAAE,OAAO,CAAC;QACjB,kFAAkF;QAClF,OAAO,EAAE,MAAM,CAAC;QAChB,qCAAqC;QACrC,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAMD,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,GAAG,CAAC,EAAE,OAAO,CAAC;CACjB;AAMD,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;IACxD,IAAI,EAAE,OAAO,CAAC;CACjB;AAMD,MAAM,WAAW,aAAa;IAC1B,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9F,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,UAAU,EAAE,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IACvG,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAG/C,UAAU,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,SAAS,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,YAAY,CAAC,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ // ---------------------------------------------------------------------------
3
+ // Agent configuration
4
+ // ---------------------------------------------------------------------------
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":";AAAA,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E"}
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "airtable",
3
+ "name": "Airtable",
4
+ "category": "Productivity",
5
+ "description": "Cloud database and spreadsheet hybrid. Create, read, update, and manage structured data in Airtable bases.",
6
+ "baseUrl": "https://api.airtable.com",
7
+ "authStrategy": "bearer",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Personal Access Token", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "List records: GET /v0/{baseId}/{tableName}",
14
+ "Create record: POST /v0/{baseId}/{tableName} with body: { fields: { ... } }",
15
+ "Update record: PATCH /v0/{baseId}/{tableName}/{recordId} with body: { fields: { ... } }",
16
+ "Response: { records: [{ id, fields: { ... } }] }",
17
+ "Get your base ID from the Airtable API docs page for your base."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://airtable.com/create/tokens",
21
+ "steps": [
22
+ "Log in to your Airtable account",
23
+ "Go to airtable.com/create/tokens",
24
+ "Create a personal access token with the scopes you need and copy it"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "alpha-vantage",
3
+ "name": "Alpha Vantage",
4
+ "category": "Finance",
5
+ "description": "Stock market data, forex, crypto, and technical indicators. Real-time and historical financial data.",
6
+ "baseUrl": "https://www.alphavantage.co",
7
+ "authStrategy": "query",
8
+ "authKey": "apikey",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Stock quote: GET /query?function=GLOBAL_QUOTE&symbol={SYMBOL}",
14
+ "Daily time series: GET /query?function=TIME_SERIES_DAILY&symbol={SYMBOL}",
15
+ "Forex rate: GET /query?function=CURRENCY_EXCHANGE_RATE&from_currency=USD&to_currency=EUR",
16
+ "Free tier: 25 requests/day. Response is JSON with nested objects keyed by metadata labels."
17
+ ],
18
+ "onboarding": {
19
+ "url": "https://www.alphavantage.co/support/#api-key",
20
+ "steps": [
21
+ "Visit the Alpha Vantage API key page",
22
+ "Fill in your details and click Get Free API Key",
23
+ "Copy the API key shown on the page"
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "brave-search",
3
+ "name": "Brave Search",
4
+ "category": "Search",
5
+ "description": "Web search powered by the Brave Search API. Provides real-time search results from the web.",
6
+ "baseUrl": "https://api.search.brave.com",
7
+ "authStrategy": "header",
8
+ "authKey": "X-Subscription-Token",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Endpoint: GET /res/v1/web/search",
14
+ "Query params: q (required), count (1-20, default 10), country, freshness",
15
+ "Response: { web: { results: [{ title, url, description }] } }",
16
+ "Note: synthos.search.web() is a convenience wrapper — prefer it over raw connector calls for basic web search."
17
+ ],
18
+ "onboarding": {
19
+ "url": "https://brave.com/search/api/",
20
+ "steps": [
21
+ "Create an account at brave.com/search/api/",
22
+ "Subscribe to the Free plan (2,000 queries/mo)",
23
+ "Go to your dashboard and copy your API key"
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "cloudinary",
3
+ "name": "Cloudinary",
4
+ "category": "Media",
5
+ "description": "Cloud-based image and video management. Upload, transform, optimize, and deliver media assets.",
6
+ "baseUrl": "https://api.cloudinary.com",
7
+ "authStrategy": "header",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Auth (Base64 key:secret)", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Upload image: POST /v1_1/{cloud_name}/image/upload",
14
+ " Body: { file: \"<url or base64>\", upload_preset: \"...\" }",
15
+ "List resources: GET /v1_1/{cloud_name}/resources/image",
16
+ "IMPORTANT: Cloudinary uses Basic auth. Save your key as 'Basic base64(API_KEY:API_SECRET)'.",
17
+ "Replace {cloud_name} in paths with your Cloudinary cloud name."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://cloudinary.com/users/register_free",
21
+ "steps": [
22
+ "Create a free Cloudinary account",
23
+ "Go to Settings > Access Keys",
24
+ "Base64-encode 'API_KEY:API_SECRET' and paste as your key"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "deepl",
3
+ "name": "DeepL",
4
+ "category": "Translation",
5
+ "description": "High-quality AI translation for 30+ languages. Translate text and documents with state-of-the-art neural machine translation.",
6
+ "baseUrl": "https://api-free.deepl.com",
7
+ "authStrategy": "header",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Translate text: POST /v2/translate",
14
+ " Body: { text: [\"Hello\"], target_lang: \"DE\" }",
15
+ " Response: { translations: [{ detected_source_language: \"EN\", text: \"Hallo\" }] }",
16
+ "Supported languages: GET /v2/languages",
17
+ "IMPORTANT: The auth header value must be: DeepL-Auth-Key YOUR_KEY. The proxy sends raw apiKey — prepend 'DeepL-Auth-Key ' when saving your key.",
18
+ "Free tier: 500,000 characters/month."
19
+ ],
20
+ "onboarding": {
21
+ "url": "https://www.deepl.com/pro-api",
22
+ "steps": [
23
+ "Sign up for a DeepL API Free account",
24
+ "Go to your Account > API Keys",
25
+ "Copy your Authentication Key"
26
+ ]
27
+ }
28
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "id": "elevenlabs",
3
+ "name": "ElevenLabs",
4
+ "category": "Audio",
5
+ "description": "AI-powered text-to-speech and voice synthesis. Generate natural-sounding audio from text.",
6
+ "baseUrl": "https://api.elevenlabs.io",
7
+ "authStrategy": "header",
8
+ "authKey": "xi-api-key",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "List voices: GET /v1/voices → { voices: [{ voice_id, name, category }] }",
14
+ "Text-to-speech: POST /v1/text-to-speech/{voice_id}?output_format=mp3_44100_128",
15
+ " Request headers: Accept: audio/mpeg, Content-Type: application/json",
16
+ " Request body: { text: string, model_id: \"eleven_multilingual_v2\" }",
17
+ " Response: raw audio/mpeg binary — use resp.arrayBuffer() then new Blob([buf], {type:\"audio/mpeg\"}) and URL.createObjectURL() to play",
18
+ " IMPORTANT: The proxy returns raw binary, NOT JSON. Call fetch(\"/api/connectors\", ...) directly instead of synthos.connectors.call() for TTS, since the helper parses JSON.",
19
+ "Default voice: \"Rachel\" (voice_id: 21m00Tcm4TlvDq8ikWAM) is a good general-purpose voice.",
20
+ "Max text length: 5000 characters per request."
21
+ ],
22
+ "onboarding": {
23
+ "url": "https://elevenlabs.io/",
24
+ "steps": [
25
+ "Create an account at elevenlabs.io",
26
+ "Go to your Profile settings",
27
+ "Copy your API key from the API Key section"
28
+ ]
29
+ }
30
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "giphy",
3
+ "name": "Giphy",
4
+ "category": "Media",
5
+ "description": "Search and discover GIFs, stickers, and animated content. The world's largest GIF library.",
6
+ "baseUrl": "https://api.giphy.com",
7
+ "authStrategy": "query",
8
+ "authKey": "api_key",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Search GIFs: GET /v1/gifs/search?q={term}&limit=10",
14
+ "Trending: GET /v1/gifs/trending?limit=10",
15
+ "Random: GET /v1/gifs/random?tag={term}",
16
+ "Response: { data: [{ images: { original: { url }, fixed_height: { url } }, title }] }",
17
+ "Display with: <img src=\"{images.fixed_height.url}\">"
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://developers.giphy.com/dashboard/",
21
+ "steps": [
22
+ "Create a GIPHY developer account",
23
+ "Create a new app on the dashboard",
24
+ "Copy the API key from your app settings"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": "github",
3
+ "name": "GitHub",
4
+ "category": "Developer",
5
+ "description": "Access GitHub repositories, issues, pull requests, and more via the GitHub REST API.",
6
+ "baseUrl": "https://api.github.com",
7
+ "authStrategy": "bearer",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Personal Access Token", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Get user: GET /user",
14
+ "List repos: GET /user/repos?sort=updated&per_page=10",
15
+ "Get repo: GET /repos/{owner}/{repo}",
16
+ "List issues: GET /repos/{owner}/{repo}/issues",
17
+ "Create issue: POST /repos/{owner}/{repo}/issues with body: { title, body }",
18
+ "All requests should include header Accept: application/vnd.github+json."
19
+ ],
20
+ "onboarding": {
21
+ "url": "https://github.com/settings/tokens",
22
+ "steps": [
23
+ "Go to github.com/settings/tokens",
24
+ "Generate a new token (classic or fine-grained)",
25
+ "Select the scopes you need (e.g. repo, read:user)",
26
+ "Copy the generated token"
27
+ ]
28
+ }
29
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "huggingface",
3
+ "name": "Hugging Face",
4
+ "category": "AI",
5
+ "description": "Access thousands of AI models for text generation, image classification, NLP, and more via the Inference API.",
6
+ "baseUrl": "https://api-inference.huggingface.co",
7
+ "authStrategy": "bearer",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Token", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Run inference: POST /models/{model-id}",
14
+ " Example (text generation): POST /models/gpt2 with body: { inputs: \"Hello world\" }",
15
+ " Example (sentiment): POST /models/distilbert-base-uncased-finetuned-sst-2-english with body: { inputs: \"I love this!\" }",
16
+ "Response format varies by model task type.",
17
+ "Free tier: rate-limited, models may need to warm up (first request may be slow)."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://huggingface.co/join",
21
+ "steps": [
22
+ "Create an account at huggingface.co",
23
+ "Go to Settings > Access Tokens",
24
+ "Create a new token with read permissions and copy it"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "id": "imgur",
3
+ "name": "Imgur",
4
+ "category": "Image",
5
+ "description": "Image hosting and sharing. Upload images, create albums, and browse the Imgur gallery.",
6
+ "baseUrl": "https://api.imgur.com",
7
+ "authStrategy": "header",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Client ID", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Upload image: POST /3/image with body: { image: \"<base64 or URL>\", title: \"...\" }",
14
+ "Get image: GET /3/image/{imageHash}",
15
+ "Get album: GET /3/album/{albumHash}",
16
+ "Response (upload): { data: { id, link, deletehash, width, height } }",
17
+ "IMPORTANT: Save your key as 'Client-ID YOUR_CLIENT_ID' (the proxy sends raw header value).",
18
+ "Free tier: 1,250 uploads/day, 12,500 requests/day."
19
+ ],
20
+ "onboarding": {
21
+ "url": "https://api.imgur.com/oauth2/addclient",
22
+ "steps": [
23
+ "Create an Imgur account if you don't have one",
24
+ "Register an application at api.imgur.com/oauth2/addclient",
25
+ "Select 'OAuth 2 authorization without a callback URL'",
26
+ "Copy your Client ID from the confirmation page"
27
+ ]
28
+ }
29
+ }
@@ -1,3 +1,3 @@
1
1
  export { CONNECTOR_REGISTRY } from './registry';
2
- export type { AuthStrategy, ConnectorField, ConnectorDefinition, ConnectorConfig, ConnectorOAuthConfig, ConnectorsConfig, ConnectorSummary, ConnectorDetail, ConnectorCallRequest } from './types';
2
+ export type { AuthStrategy, ConnectorField, ConnectorOnboarding, ConnectorJson, ConnectorDefinition, ConnectorConfig, ConnectorOAuthConfig, ConnectorsConfig, ConnectorSummary, ConnectorDetail, ConnectorCallRequest } from './types';
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connectors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EACR,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACvB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connectors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EACR,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACvB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,43 @@
1
+ {
2
+ "id": "instagram",
3
+ "name": "Instagram",
4
+ "category": "Social",
5
+ "description": "Post photos and videos to Instagram via the Instagram Graph API.",
6
+ "baseUrl": "https://graph.facebook.com/v21.0",
7
+ "authStrategy": "oauth2",
8
+ "authKey": "access_token",
9
+ "authorizationUrl": "https://www.facebook.com/v21.0/dialog/oauth",
10
+ "tokenUrl": "https://graph.facebook.com/v21.0/oauth/access_token",
11
+ "scopes": [
12
+ "instagram_basic",
13
+ "instagram_content_publish",
14
+ "pages_show_list",
15
+ "pages_read_engagement"
16
+ ],
17
+ "fields": [
18
+ { "name": "clientId", "label": "App ID", "type": "text" },
19
+ { "name": "clientSecret", "label": "App Secret", "type": "password" }
20
+ ],
21
+ "hints": [
22
+ "Publishing flow (two-step):",
23
+ " 1. Create media container: POST /{ig-user-id}/media",
24
+ " Body (photo): { image_url, caption }",
25
+ " Body (reel/video): { video_url, caption, media_type: \"REELS\" }",
26
+ " Response: { id: \"<container-id>\" }",
27
+ " 2. Publish container: POST /{ig-user-id}/media_publish",
28
+ " Body: { creation_id: \"<container-id>\" }",
29
+ " Response: { id: \"<media-id>\" }",
30
+ "IMPORTANT: Do NOT include access_token in body or query params — the proxy attaches it automatically.",
31
+ "IMPORTANT: Images must be publicly accessible URLs. Use a hosting service or the data API to serve local images.",
32
+ "Rate limit: 25 posts per 24-hour period.",
33
+ "Requires a Business or Creator Instagram account linked to a Facebook Page."
34
+ ],
35
+ "onboarding": {
36
+ "url": "https://developers.facebook.com/",
37
+ "steps": [
38
+ "Create a Meta developer account at developers.facebook.com",
39
+ "Create a new app and add the Instagram Graph API product",
40
+ "Get your App ID and App Secret from Settings > Basic"
41
+ ]
42
+ }
43
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "jira",
3
+ "name": "Jira",
4
+ "category": "Developer",
5
+ "description": "Project management and issue tracking. Search, create, and update Jira issues via the REST API.",
6
+ "baseUrl": "https://your-domain.atlassian.net",
7
+ "authStrategy": "header",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Auth (Base64 email:token)", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Search issues: GET /rest/api/3/search?jql={JQL}",
14
+ "Get issue: GET /rest/api/3/issue/{issueKey}",
15
+ "Create issue: POST /rest/api/3/issue with body: { fields: { project: { key }, summary, issuetype: { name } } }",
16
+ "IMPORTANT: Jira uses Basic auth. Save your key as 'Basic base64(email:api_token)'.",
17
+ "IMPORTANT: Update baseUrl to your Atlassian domain (e.g. https://mycompany.atlassian.net)."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://id.atlassian.com/manage-profile/security/api-tokens",
21
+ "steps": [
22
+ "Log in to your Atlassian account",
23
+ "Go to Account Settings > Security > API tokens",
24
+ "Create a new API token and copy it",
25
+ "Base64-encode 'your-email@example.com:api-token' and paste as your key"
26
+ ]
27
+ }
28
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "mapbox",
3
+ "name": "Mapbox",
4
+ "category": "Geo",
5
+ "description": "Maps, geocoding, directions, and location search. Build location-aware applications.",
6
+ "baseUrl": "https://api.mapbox.com",
7
+ "authStrategy": "query",
8
+ "authKey": "access_token",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Access Token", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Geocoding: GET /geocoding/v5/mapbox.places/{query}.json",
14
+ "Directions: GET /directions/v5/mapbox/driving/{lon1},{lat1};{lon2},{lat2}",
15
+ "Static map image: GET /styles/v1/mapbox/streets-v12/static/{lon},{lat},{zoom}/600x400",
16
+ "Response (geocoding): { features: [{ place_name, center: [lon, lat] }] }"
17
+ ],
18
+ "onboarding": {
19
+ "url": "https://account.mapbox.com/auth/signup/",
20
+ "steps": [
21
+ "Create an account at mapbox.com",
22
+ "Go to your Account page",
23
+ "Copy your default public token or create a new one"
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "nasa",
3
+ "name": "NASA",
4
+ "category": "Science",
5
+ "description": "Access NASA's open data APIs including astronomy photos, Mars rover images, and asteroid tracking.",
6
+ "baseUrl": "https://api.nasa.gov",
7
+ "authStrategy": "query",
8
+ "authKey": "api_key",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Astronomy Picture of the Day: GET /planetary/apod",
14
+ "Mars Rover Photos: GET /mars-photos/api/v1/rovers/curiosity/photos?sol=1000",
15
+ "Asteroids NeoWS: GET /neo/rest/v1/feed?start_date=2024-01-01&end_date=2024-01-07",
16
+ "Response (APOD): { title, explanation, url, hdurl, media_type }",
17
+ "Free tier: 1,000 requests/hour. DEMO_KEY works for testing (30 req/hr)."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://api.nasa.gov/",
21
+ "steps": [
22
+ "Visit api.nasa.gov",
23
+ "Fill in the sign-up form to get an API key",
24
+ "Check your email for the API key"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "newsapi",
3
+ "name": "NewsAPI",
4
+ "category": "News",
5
+ "description": "Search and retrieve news articles from thousands of sources worldwide. Headlines, everything search, and source discovery.",
6
+ "baseUrl": "https://newsapi.org",
7
+ "authStrategy": "header",
8
+ "authKey": "X-Api-Key",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Top headlines: GET /v2/top-headlines?country=us&category=technology",
14
+ "Everything search: GET /v2/everything?q={query}&sortBy=publishedAt",
15
+ "Sources: GET /v2/top-headlines/sources",
16
+ "Response: { articles: [{ title, description, url, urlToImage, publishedAt, source: { name } }] }",
17
+ "Free tier: 100 requests/day, 1-month-old articles only."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://newsapi.org/register",
21
+ "steps": [
22
+ "Create an account at newsapi.org",
23
+ "After registering, your API key is shown on the dashboard",
24
+ "Copy the API key"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "notion",
3
+ "name": "Notion",
4
+ "category": "Productivity",
5
+ "description": "Workspace API for pages, databases, and blocks. Read and write Notion content programmatically.",
6
+ "baseUrl": "https://api.notion.com",
7
+ "authStrategy": "bearer",
8
+ "authKey": "Authorization",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "Integration Token", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Search: POST /v1/search with body: { query: \"...\", filter: { property: \"object\", value: \"page\" } }",
14
+ "Get page: GET /v1/pages/{page_id}",
15
+ "Query database: POST /v1/databases/{database_id}/query",
16
+ "IMPORTANT: All requests must include header Notion-Version: 2022-06-28.",
17
+ "Pages must be shared with your integration before they can be accessed."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://www.notion.so/my-integrations",
21
+ "steps": [
22
+ "Go to notion.so/my-integrations",
23
+ "Create a new internal integration",
24
+ "Copy the Internal Integration Token",
25
+ "Share your Notion pages/databases with the integration"
26
+ ]
27
+ }
28
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "open-exchange-rates",
3
+ "name": "Open Exchange Rates",
4
+ "category": "Finance",
5
+ "description": "Currency exchange rates and conversion. Real-time and historical forex data for 170+ currencies.",
6
+ "baseUrl": "https://openexchangerates.org",
7
+ "authStrategy": "query",
8
+ "authKey": "app_id",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "App ID", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Latest rates: GET /api/latest.json",
14
+ "Historical: GET /api/historical/{YYYY-MM-DD}.json",
15
+ "Currencies list: GET /api/currencies.json",
16
+ "Response: { base: \"USD\", rates: { EUR: 0.92, GBP: 0.79, ... } }",
17
+ "Free tier: 1,000 requests/month, USD base only."
18
+ ],
19
+ "onboarding": {
20
+ "url": "https://openexchangerates.org/signup/free",
21
+ "steps": [
22
+ "Create a free account at openexchangerates.org",
23
+ "Go to your App IDs page in the dashboard",
24
+ "Copy your App ID"
25
+ ]
26
+ }
27
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "id": "openweathermap",
3
+ "name": "OpenWeatherMap",
4
+ "category": "Weather",
5
+ "description": "Real-time weather data, forecasts, and historical weather information for any location worldwide.",
6
+ "baseUrl": "https://api.openweathermap.org",
7
+ "authStrategy": "query",
8
+ "authKey": "appid",
9
+ "fields": [
10
+ { "name": "apiKey", "label": "API Key", "type": "password" }
11
+ ],
12
+ "hints": [
13
+ "Current weather: GET /data/2.5/weather?q={city}&units=metric",
14
+ "5-day forecast: GET /data/2.5/forecast?q={city}&units=metric",
15
+ "Response: { main: { temp, humidity }, weather: [{ description }], wind: { speed } }",
16
+ "Use units=metric for Celsius or units=imperial for Fahrenheit."
17
+ ],
18
+ "onboarding": {
19
+ "url": "https://home.openweathermap.org/users/sign_up",
20
+ "steps": [
21
+ "Create an account at openweathermap.org",
22
+ "Go to API Keys in your account dashboard",
23
+ "Copy your default API key (or generate a new one)"
24
+ ]
25
+ }
26
+ }