adaria-ai 0.1.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 (337) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +21 -0
  3. package/apps.example.yaml +65 -0
  4. package/dist/agent/audit.d.ts +16 -0
  5. package/dist/agent/audit.d.ts.map +1 -0
  6. package/dist/agent/audit.js +42 -0
  7. package/dist/agent/audit.js.map +1 -0
  8. package/dist/agent/claude.d.ts +62 -0
  9. package/dist/agent/claude.d.ts.map +1 -0
  10. package/dist/agent/claude.js +297 -0
  11. package/dist/agent/claude.js.map +1 -0
  12. package/dist/agent/conversation-summary.d.ts +29 -0
  13. package/dist/agent/conversation-summary.d.ts.map +1 -0
  14. package/dist/agent/conversation-summary.js +221 -0
  15. package/dist/agent/conversation-summary.js.map +1 -0
  16. package/dist/agent/core.d.ts +81 -0
  17. package/dist/agent/core.d.ts.map +1 -0
  18. package/dist/agent/core.js +527 -0
  19. package/dist/agent/core.js.map +1 -0
  20. package/dist/agent/mcp-launcher.d.ts +42 -0
  21. package/dist/agent/mcp-launcher.d.ts.map +1 -0
  22. package/dist/agent/mcp-launcher.js +38 -0
  23. package/dist/agent/mcp-launcher.js.map +1 -0
  24. package/dist/agent/mcp-manager.d.ts +81 -0
  25. package/dist/agent/mcp-manager.d.ts.map +1 -0
  26. package/dist/agent/mcp-manager.js +136 -0
  27. package/dist/agent/mcp-manager.js.map +1 -0
  28. package/dist/agent/memory.d.ts +10 -0
  29. package/dist/agent/memory.d.ts.map +1 -0
  30. package/dist/agent/memory.js +95 -0
  31. package/dist/agent/memory.js.map +1 -0
  32. package/dist/agent/safety.d.ts +45 -0
  33. package/dist/agent/safety.d.ts.map +1 -0
  34. package/dist/agent/safety.js +71 -0
  35. package/dist/agent/safety.js.map +1 -0
  36. package/dist/agent/session.d.ts +27 -0
  37. package/dist/agent/session.d.ts.map +1 -0
  38. package/dist/agent/session.js +124 -0
  39. package/dist/agent/session.js.map +1 -0
  40. package/dist/agent/tool-descriptions.d.ts +8 -0
  41. package/dist/agent/tool-descriptions.d.ts.map +1 -0
  42. package/dist/agent/tool-descriptions.js +26 -0
  43. package/dist/agent/tool-descriptions.js.map +1 -0
  44. package/dist/cli/analyze.d.ts +8 -0
  45. package/dist/cli/analyze.d.ts.map +1 -0
  46. package/dist/cli/analyze.js +114 -0
  47. package/dist/cli/analyze.js.map +1 -0
  48. package/dist/cli/daemon.d.ts +2 -0
  49. package/dist/cli/daemon.d.ts.map +1 -0
  50. package/dist/cli/daemon.js +91 -0
  51. package/dist/cli/daemon.js.map +1 -0
  52. package/dist/cli/doctor.d.ts +2 -0
  53. package/dist/cli/doctor.d.ts.map +1 -0
  54. package/dist/cli/doctor.js +198 -0
  55. package/dist/cli/doctor.js.map +1 -0
  56. package/dist/cli/init.d.ts +3 -0
  57. package/dist/cli/init.d.ts.map +1 -0
  58. package/dist/cli/init.js +459 -0
  59. package/dist/cli/init.js.map +1 -0
  60. package/dist/cli/logs.d.ts +4 -0
  61. package/dist/cli/logs.d.ts.map +1 -0
  62. package/dist/cli/logs.js +50 -0
  63. package/dist/cli/logs.js.map +1 -0
  64. package/dist/cli/monitor-cmd.d.ts +11 -0
  65. package/dist/cli/monitor-cmd.d.ts.map +1 -0
  66. package/dist/cli/monitor-cmd.js +59 -0
  67. package/dist/cli/monitor-cmd.js.map +1 -0
  68. package/dist/cli/start.d.ts +11 -0
  69. package/dist/cli/start.d.ts.map +1 -0
  70. package/dist/cli/start.js +103 -0
  71. package/dist/cli/start.js.map +1 -0
  72. package/dist/cli/status.d.ts +9 -0
  73. package/dist/cli/status.d.ts.map +1 -0
  74. package/dist/cli/status.js +49 -0
  75. package/dist/cli/status.js.map +1 -0
  76. package/dist/cli/stop.d.ts +2 -0
  77. package/dist/cli/stop.d.ts.map +1 -0
  78. package/dist/cli/stop.js +34 -0
  79. package/dist/cli/stop.js.map +1 -0
  80. package/dist/collectors/appstore.d.ts +51 -0
  81. package/dist/collectors/appstore.d.ts.map +1 -0
  82. package/dist/collectors/appstore.js +166 -0
  83. package/dist/collectors/appstore.js.map +1 -0
  84. package/dist/collectors/arden-tts.d.ts +60 -0
  85. package/dist/collectors/arden-tts.d.ts.map +1 -0
  86. package/dist/collectors/arden-tts.js +83 -0
  87. package/dist/collectors/arden-tts.js.map +1 -0
  88. package/dist/collectors/asomobile.d.ts +37 -0
  89. package/dist/collectors/asomobile.d.ts.map +1 -0
  90. package/dist/collectors/asomobile.js +88 -0
  91. package/dist/collectors/asomobile.js.map +1 -0
  92. package/dist/collectors/eodin-blog.d.ts +90 -0
  93. package/dist/collectors/eodin-blog.d.ts.map +1 -0
  94. package/dist/collectors/eodin-blog.js +238 -0
  95. package/dist/collectors/eodin-blog.js.map +1 -0
  96. package/dist/collectors/eodin-sdk.d.ts +60 -0
  97. package/dist/collectors/eodin-sdk.d.ts.map +1 -0
  98. package/dist/collectors/eodin-sdk.js +112 -0
  99. package/dist/collectors/eodin-sdk.js.map +1 -0
  100. package/dist/collectors/fridgify-recipes.d.ts +65 -0
  101. package/dist/collectors/fridgify-recipes.d.ts.map +1 -0
  102. package/dist/collectors/fridgify-recipes.js +111 -0
  103. package/dist/collectors/fridgify-recipes.js.map +1 -0
  104. package/dist/collectors/playstore.d.ts +46 -0
  105. package/dist/collectors/playstore.d.ts.map +1 -0
  106. package/dist/collectors/playstore.js +140 -0
  107. package/dist/collectors/playstore.js.map +1 -0
  108. package/dist/collectors/youtube.d.ts +44 -0
  109. package/dist/collectors/youtube.d.ts.map +1 -0
  110. package/dist/collectors/youtube.js +107 -0
  111. package/dist/collectors/youtube.js.map +1 -0
  112. package/dist/config/apps-schema.d.ts +94 -0
  113. package/dist/config/apps-schema.d.ts.map +1 -0
  114. package/dist/config/apps-schema.js +66 -0
  115. package/dist/config/apps-schema.js.map +1 -0
  116. package/dist/config/keychain.d.ts +14 -0
  117. package/dist/config/keychain.d.ts.map +1 -0
  118. package/dist/config/keychain.js +89 -0
  119. package/dist/config/keychain.js.map +1 -0
  120. package/dist/config/load-apps.d.ts +16 -0
  121. package/dist/config/load-apps.d.ts.map +1 -0
  122. package/dist/config/load-apps.js +38 -0
  123. package/dist/config/load-apps.js.map +1 -0
  124. package/dist/config/schema.d.ts +306 -0
  125. package/dist/config/schema.d.ts.map +1 -0
  126. package/dist/config/schema.js +220 -0
  127. package/dist/config/schema.js.map +1 -0
  128. package/dist/config/store.d.ts +38 -0
  129. package/dist/config/store.d.ts.map +1 -0
  130. package/dist/config/store.js +180 -0
  131. package/dist/config/store.js.map +1 -0
  132. package/dist/db/queries.d.ts +304 -0
  133. package/dist/db/queries.d.ts.map +1 -0
  134. package/dist/db/queries.js +327 -0
  135. package/dist/db/queries.js.map +1 -0
  136. package/dist/db/schema.d.ts +15 -0
  137. package/dist/db/schema.d.ts.map +1 -0
  138. package/dist/db/schema.js +252 -0
  139. package/dist/db/schema.js.map +1 -0
  140. package/dist/index.d.ts +3 -0
  141. package/dist/index.d.ts.map +1 -0
  142. package/dist/index.js +86 -0
  143. package/dist/index.js.map +1 -0
  144. package/dist/messenger/adapter.d.ts +63 -0
  145. package/dist/messenger/adapter.d.ts.map +1 -0
  146. package/dist/messenger/adapter.js +7 -0
  147. package/dist/messenger/adapter.js.map +1 -0
  148. package/dist/messenger/factory.d.ts +12 -0
  149. package/dist/messenger/factory.d.ts.map +1 -0
  150. package/dist/messenger/factory.js +9 -0
  151. package/dist/messenger/factory.js.map +1 -0
  152. package/dist/messenger/slack.d.ts +30 -0
  153. package/dist/messenger/slack.d.ts.map +1 -0
  154. package/dist/messenger/slack.js +309 -0
  155. package/dist/messenger/slack.js.map +1 -0
  156. package/dist/messenger/split.d.ts +17 -0
  157. package/dist/messenger/split.d.ts.map +1 -0
  158. package/dist/messenger/split.js +56 -0
  159. package/dist/messenger/split.js.map +1 -0
  160. package/dist/orchestrator/dashboard.d.ts +67 -0
  161. package/dist/orchestrator/dashboard.d.ts.map +1 -0
  162. package/dist/orchestrator/dashboard.js +113 -0
  163. package/dist/orchestrator/dashboard.js.map +1 -0
  164. package/dist/orchestrator/monitor.d.ts +37 -0
  165. package/dist/orchestrator/monitor.d.ts.map +1 -0
  166. package/dist/orchestrator/monitor.js +236 -0
  167. package/dist/orchestrator/monitor.js.map +1 -0
  168. package/dist/orchestrator/types.d.ts +82 -0
  169. package/dist/orchestrator/types.d.ts.map +1 -0
  170. package/dist/orchestrator/types.js +12 -0
  171. package/dist/orchestrator/types.js.map +1 -0
  172. package/dist/orchestrator/weekly.d.ts +66 -0
  173. package/dist/orchestrator/weekly.d.ts.map +1 -0
  174. package/dist/orchestrator/weekly.js +376 -0
  175. package/dist/orchestrator/weekly.js.map +1 -0
  176. package/dist/prompts/loader.d.ts +18 -0
  177. package/dist/prompts/loader.d.ts.map +1 -0
  178. package/dist/prompts/loader.js +28 -0
  179. package/dist/prompts/loader.js.map +1 -0
  180. package/dist/security/auth.d.ts +14 -0
  181. package/dist/security/auth.d.ts.map +1 -0
  182. package/dist/security/auth.js +14 -0
  183. package/dist/security/auth.js.map +1 -0
  184. package/dist/security/prompt-guard.d.ts +21 -0
  185. package/dist/security/prompt-guard.d.ts.map +1 -0
  186. package/dist/security/prompt-guard.js +54 -0
  187. package/dist/security/prompt-guard.js.map +1 -0
  188. package/dist/skills/aso.d.ts +60 -0
  189. package/dist/skills/aso.d.ts.map +1 -0
  190. package/dist/skills/aso.js +322 -0
  191. package/dist/skills/aso.js.map +1 -0
  192. package/dist/skills/content.d.ts +25 -0
  193. package/dist/skills/content.d.ts.map +1 -0
  194. package/dist/skills/content.js +90 -0
  195. package/dist/skills/content.js.map +1 -0
  196. package/dist/skills/index.d.ts +65 -0
  197. package/dist/skills/index.d.ts.map +1 -0
  198. package/dist/skills/index.js +90 -0
  199. package/dist/skills/index.js.map +1 -0
  200. package/dist/skills/onboarding.d.ts +58 -0
  201. package/dist/skills/onboarding.d.ts.map +1 -0
  202. package/dist/skills/onboarding.js +274 -0
  203. package/dist/skills/onboarding.js.map +1 -0
  204. package/dist/skills/registry.d.ts +24 -0
  205. package/dist/skills/registry.d.ts.map +1 -0
  206. package/dist/skills/registry.js +66 -0
  207. package/dist/skills/registry.js.map +1 -0
  208. package/dist/skills/review.d.ts +33 -0
  209. package/dist/skills/review.d.ts.map +1 -0
  210. package/dist/skills/review.js +236 -0
  211. package/dist/skills/review.js.map +1 -0
  212. package/dist/skills/sdk-request.d.ts +30 -0
  213. package/dist/skills/sdk-request.d.ts.map +1 -0
  214. package/dist/skills/sdk-request.js +72 -0
  215. package/dist/skills/sdk-request.js.map +1 -0
  216. package/dist/skills/seo-blog.d.ts +64 -0
  217. package/dist/skills/seo-blog.d.ts.map +1 -0
  218. package/dist/skills/seo-blog.js +268 -0
  219. package/dist/skills/seo-blog.js.map +1 -0
  220. package/dist/skills/short-form.d.ts +28 -0
  221. package/dist/skills/short-form.d.ts.map +1 -0
  222. package/dist/skills/short-form.js +121 -0
  223. package/dist/skills/short-form.js.map +1 -0
  224. package/dist/skills/social-publish.d.ts +32 -0
  225. package/dist/skills/social-publish.d.ts.map +1 -0
  226. package/dist/skills/social-publish.js +133 -0
  227. package/dist/skills/social-publish.js.map +1 -0
  228. package/dist/social/base.d.ts +47 -0
  229. package/dist/social/base.d.ts.map +1 -0
  230. package/dist/social/base.js +26 -0
  231. package/dist/social/base.js.map +1 -0
  232. package/dist/social/facebook.d.ts +27 -0
  233. package/dist/social/facebook.d.ts.map +1 -0
  234. package/dist/social/facebook.js +166 -0
  235. package/dist/social/facebook.js.map +1 -0
  236. package/dist/social/factory.d.ts +26 -0
  237. package/dist/social/factory.d.ts.map +1 -0
  238. package/dist/social/factory.js +32 -0
  239. package/dist/social/factory.js.map +1 -0
  240. package/dist/social/linkedin.d.ts +26 -0
  241. package/dist/social/linkedin.d.ts.map +1 -0
  242. package/dist/social/linkedin.js +190 -0
  243. package/dist/social/linkedin.js.map +1 -0
  244. package/dist/social/threads.d.ts +21 -0
  245. package/dist/social/threads.d.ts.map +1 -0
  246. package/dist/social/threads.js +122 -0
  247. package/dist/social/threads.js.map +1 -0
  248. package/dist/social/tiktok.d.ts +23 -0
  249. package/dist/social/tiktok.d.ts.map +1 -0
  250. package/dist/social/tiktok.js +110 -0
  251. package/dist/social/tiktok.js.map +1 -0
  252. package/dist/social/twitter.d.ts +30 -0
  253. package/dist/social/twitter.d.ts.map +1 -0
  254. package/dist/social/twitter.js +189 -0
  255. package/dist/social/twitter.js.map +1 -0
  256. package/dist/social/youtube.d.ts +21 -0
  257. package/dist/social/youtube.d.ts.map +1 -0
  258. package/dist/social/youtube.js +108 -0
  259. package/dist/social/youtube.js.map +1 -0
  260. package/dist/tools/app-info.d.ts +7 -0
  261. package/dist/tools/app-info.d.ts.map +1 -0
  262. package/dist/tools/app-info.js +53 -0
  263. package/dist/tools/app-info.js.map +1 -0
  264. package/dist/tools/collector-fetch.d.ts +11 -0
  265. package/dist/tools/collector-fetch.d.ts.map +1 -0
  266. package/dist/tools/collector-fetch.js +101 -0
  267. package/dist/tools/collector-fetch.js.map +1 -0
  268. package/dist/tools/db-query.d.ts +29 -0
  269. package/dist/tools/db-query.d.ts.map +1 -0
  270. package/dist/tools/db-query.js +159 -0
  271. package/dist/tools/db-query.js.map +1 -0
  272. package/dist/tools/skill-result.d.ts +8 -0
  273. package/dist/tools/skill-result.d.ts.map +1 -0
  274. package/dist/tools/skill-result.js +63 -0
  275. package/dist/tools/skill-result.js.map +1 -0
  276. package/dist/tools/tool-host.d.ts +12 -0
  277. package/dist/tools/tool-host.d.ts.map +1 -0
  278. package/dist/tools/tool-host.js +124 -0
  279. package/dist/tools/tool-host.js.map +1 -0
  280. package/dist/types/collectors.d.ts +198 -0
  281. package/dist/types/collectors.d.ts.map +1 -0
  282. package/dist/types/collectors.js +28 -0
  283. package/dist/types/collectors.js.map +1 -0
  284. package/dist/types/skill.d.ts +60 -0
  285. package/dist/types/skill.d.ts.map +1 -0
  286. package/dist/types/skill.js +9 -0
  287. package/dist/types/skill.js.map +1 -0
  288. package/dist/utils/circuit-breaker.d.ts +26 -0
  289. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  290. package/dist/utils/circuit-breaker.js +67 -0
  291. package/dist/utils/circuit-breaker.js.map +1 -0
  292. package/dist/utils/errors.d.ts +44 -0
  293. package/dist/utils/errors.d.ts.map +1 -0
  294. package/dist/utils/errors.js +75 -0
  295. package/dist/utils/errors.js.map +1 -0
  296. package/dist/utils/escape.d.ts +11 -0
  297. package/dist/utils/escape.d.ts.map +1 -0
  298. package/dist/utils/escape.js +19 -0
  299. package/dist/utils/escape.js.map +1 -0
  300. package/dist/utils/logger.d.ts +19 -0
  301. package/dist/utils/logger.d.ts.map +1 -0
  302. package/dist/utils/logger.js +93 -0
  303. package/dist/utils/logger.js.map +1 -0
  304. package/dist/utils/parse-json.d.ts +13 -0
  305. package/dist/utils/parse-json.d.ts.map +1 -0
  306. package/dist/utils/parse-json.js +61 -0
  307. package/dist/utils/parse-json.js.map +1 -0
  308. package/dist/utils/paths.d.ts +14 -0
  309. package/dist/utils/paths.d.ts.map +1 -0
  310. package/dist/utils/paths.js +19 -0
  311. package/dist/utils/paths.js.map +1 -0
  312. package/dist/utils/rate-limiter.d.ts +20 -0
  313. package/dist/utils/rate-limiter.d.ts.map +1 -0
  314. package/dist/utils/rate-limiter.js +47 -0
  315. package/dist/utils/rate-limiter.js.map +1 -0
  316. package/dist/utils/retry.d.ts +26 -0
  317. package/dist/utils/retry.d.ts.map +1 -0
  318. package/dist/utils/retry.js +61 -0
  319. package/dist/utils/retry.js.map +1 -0
  320. package/launchd/.gitkeep +0 -0
  321. package/launchd/com.adaria-ai.daemon.plist.template +62 -0
  322. package/launchd/com.adaria-ai.monitor.plist.template +41 -0
  323. package/launchd/com.adaria-ai.weekly.plist.template +43 -0
  324. package/package.json +72 -0
  325. package/prompts/aso-description.md +44 -0
  326. package/prompts/aso-inapp-events.md +20 -0
  327. package/prompts/aso-metadata.md +34 -0
  328. package/prompts/aso-screenshots.md +20 -0
  329. package/prompts/onboarding-hypotheses.md +38 -0
  330. package/prompts/onboarding-review-timing.md +24 -0
  331. package/prompts/review-clustering.md +19 -0
  332. package/prompts/review-replies.md +18 -0
  333. package/prompts/review-sentiment.md +16 -0
  334. package/prompts/seo-blog-fridgify-recipe.md +116 -0
  335. package/prompts/seo-blog.md +69 -0
  336. package/prompts/short-form-ideas.md +50 -0
  337. package/prompts/social-publish.md +46 -0
@@ -0,0 +1,107 @@
1
+ import { ExternalApiError } from "../utils/errors.js";
2
+ const DEFAULT_BASE_URL = "https://www.googleapis.com/youtube/v3";
3
+ const ALLOWED_HOSTS = new Set(["www.googleapis.com"]);
4
+ export class YouTubeCollector {
5
+ apiKey;
6
+ baseUrl;
7
+ constructor(options, testHooks) {
8
+ if (!options.apiKey) {
9
+ throw new Error("YouTubeCollector requires apiKey");
10
+ }
11
+ this.apiKey = options.apiKey;
12
+ this.baseUrl = testHooks?.baseUrl ?? DEFAULT_BASE_URL;
13
+ }
14
+ redact(text) {
15
+ return text.replaceAll(this.apiKey, "[REDACTED]");
16
+ }
17
+ async fetchJson(url) {
18
+ if (!ALLOWED_HOSTS.has(url.hostname)) {
19
+ throw new Error(`Untrusted YouTube host: ${url.hostname}. Allowed: ${[...ALLOWED_HOSTS].join(", ")}`);
20
+ }
21
+ let response;
22
+ try {
23
+ response = await fetch(url.toString());
24
+ }
25
+ catch (err) {
26
+ // Redact the key from any message undici or a polyfill may have
27
+ // inlined — error.cause / stack traces can carry the full URL
28
+ // including `?key=…` for DNS / TLS / TypeError failures.
29
+ const raw = err instanceof Error ? err.message : String(err);
30
+ throw new ExternalApiError(`YouTube API fetch failed: ${this.redact(raw).slice(0, 512)}`);
31
+ }
32
+ if (!response.ok) {
33
+ const rawBody = await response.text();
34
+ // Google echoes the API key back in error envelopes. Redact before
35
+ // the message reaches audit logs or Slack cards.
36
+ throw new ExternalApiError(`YouTube API ${String(response.status)}: ${this.redact(rawBody).slice(0, 512)}`, { statusCode: response.status });
37
+ }
38
+ return (await response.json());
39
+ }
40
+ /**
41
+ * Get recent Shorts videos from a channel.
42
+ *
43
+ * YouTube's `videoDuration=short` search filter returns clips under
44
+ * **4 minutes** (not 60 seconds). We cross-check the content-details
45
+ * duration against `maxDurationSeconds` (default 60) so callers get a
46
+ * correct "Shorts" bucket by default. Pass a larger value (e.g. 180)
47
+ * if you want YouTube's looser "short-form" definition.
48
+ */
49
+ async getRecentShorts(channelId, maxResults = 10, maxDurationSeconds = 60) {
50
+ if (!channelId)
51
+ return [];
52
+ const searchUrl = new URL(`${this.baseUrl}/search`);
53
+ searchUrl.searchParams.set("part", "id,snippet");
54
+ searchUrl.searchParams.set("channelId", channelId);
55
+ searchUrl.searchParams.set("type", "video");
56
+ searchUrl.searchParams.set("videoDuration", "short");
57
+ searchUrl.searchParams.set("order", "date");
58
+ searchUrl.searchParams.set("maxResults", String(maxResults));
59
+ searchUrl.searchParams.set("key", this.apiKey);
60
+ const data = await this.fetchJson(searchUrl);
61
+ const videoIds = (data.items ?? [])
62
+ .map((item) => item.id.videoId)
63
+ .filter((id) => typeof id === "string" && id.length > 0);
64
+ if (videoIds.length === 0)
65
+ return [];
66
+ const stats = await this.getVideoStats(videoIds);
67
+ return stats.filter((v) => parseIsoDurationSeconds(v.duration) <= maxDurationSeconds);
68
+ }
69
+ /**
70
+ * Get statistics for specific video IDs.
71
+ */
72
+ async getVideoStats(videoIds) {
73
+ if (videoIds.length === 0)
74
+ return [];
75
+ const url = new URL(`${this.baseUrl}/videos`);
76
+ url.searchParams.set("part", "snippet,statistics,contentDetails");
77
+ url.searchParams.set("id", videoIds.join(","));
78
+ url.searchParams.set("key", this.apiKey);
79
+ const data = await this.fetchJson(url);
80
+ return (data.items ?? []).map((item) => ({
81
+ videoId: item.id,
82
+ title: item.snippet?.title ?? "",
83
+ publishedAt: item.snippet?.publishedAt ?? null,
84
+ views: Number.parseInt(item.statistics?.viewCount ?? "0", 10),
85
+ likes: Number.parseInt(item.statistics?.likeCount ?? "0", 10),
86
+ comments: Number.parseInt(item.statistics?.commentCount ?? "0", 10),
87
+ duration: item.contentDetails?.duration ?? null,
88
+ }));
89
+ }
90
+ }
91
+ /**
92
+ * Parse an ISO 8601 duration like `PT1M30S` to seconds. Any unrecognized
93
+ * shape (including `null`, empty string, or strings containing hours via
94
+ * `PT…H…`) returns `Number.POSITIVE_INFINITY` so that the shorts filter
95
+ * treats the clip as *too long* rather than silently accepting it.
96
+ */
97
+ function parseIsoDurationSeconds(duration) {
98
+ if (!duration)
99
+ return Number.POSITIVE_INFINITY;
100
+ const match = /^PT(?:(\d+)M)?(?:(\d+)S)?$/.exec(duration);
101
+ if (!match)
102
+ return Number.POSITIVE_INFINITY;
103
+ const minutes = Number.parseInt(match[1] ?? "0", 10);
104
+ const seconds = Number.parseInt(match[2] ?? "0", 10);
105
+ return minutes * 60 + seconds;
106
+ }
107
+ //# sourceMappingURL=youtube.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/collectors/youtube.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `apps.yaml` schema.
4
+ *
5
+ * Lives at the repo root (dev) or `$ADARIA_HOME/apps.yaml` (installed)
6
+ * and holds the per-app metadata the skills and orchestrators iterate
7
+ * over. Global credentials stay in `config.yaml.collectors`; per-app
8
+ * identifiers (App Store numeric id, Play package name, YouTube channel
9
+ * id, primary keywords, etc.) belong here because the operator adds and
10
+ * removes apps independently from rotating secrets.
11
+ *
12
+ * Wire shape note: fields are camelCase even though the growth-agent
13
+ * predecessor used snake_case (`appstore_id`, `playstore_id`). The port
14
+ * is one-shot so users re-write `apps.yaml` from the example template
15
+ * once; the new names match TypeScript convention and the wire-shape
16
+ * delta rule in `src/types/collectors.ts`.
17
+ */
18
+ export declare const appPlatformSchema: z.ZodEnum<{
19
+ ios: "ios";
20
+ android: "android";
21
+ }>;
22
+ export declare const appSocialSchema: z.ZodDefault<z.ZodObject<{
23
+ twitter: z.ZodDefault<z.ZodBoolean>;
24
+ facebook: z.ZodDefault<z.ZodBoolean>;
25
+ threads: z.ZodDefault<z.ZodBoolean>;
26
+ tiktok: z.ZodDefault<z.ZodBoolean>;
27
+ youtube: z.ZodDefault<z.ZodBoolean>;
28
+ linkedin: z.ZodDefault<z.ZodBoolean>;
29
+ }, z.core.$strip>>;
30
+ export declare const appFeaturesSchema: z.ZodDefault<z.ZodObject<{
31
+ fridgifyRecipes: z.ZodDefault<z.ZodBoolean>;
32
+ }, z.core.$strip>>;
33
+ export declare const appConfigSchema: z.ZodObject<{
34
+ id: z.ZodString;
35
+ name: z.ZodString;
36
+ platform: z.ZodArray<z.ZodEnum<{
37
+ ios: "ios";
38
+ android: "android";
39
+ }>>;
40
+ appStoreId: z.ZodOptional<z.ZodString>;
41
+ playStorePackage: z.ZodOptional<z.ZodString>;
42
+ eodinSdkAppId: z.ZodOptional<z.ZodString>;
43
+ asoMobileId: z.ZodOptional<z.ZodString>;
44
+ youtubeChannelId: z.ZodOptional<z.ZodString>;
45
+ primaryKeywords: z.ZodDefault<z.ZodArray<z.ZodString>>;
46
+ competitors: z.ZodDefault<z.ZodArray<z.ZodString>>;
47
+ locale: z.ZodDefault<z.ZodArray<z.ZodString>>;
48
+ features: z.ZodDefault<z.ZodObject<{
49
+ fridgifyRecipes: z.ZodDefault<z.ZodBoolean>;
50
+ }, z.core.$strip>>;
51
+ social: z.ZodDefault<z.ZodObject<{
52
+ twitter: z.ZodDefault<z.ZodBoolean>;
53
+ facebook: z.ZodDefault<z.ZodBoolean>;
54
+ threads: z.ZodDefault<z.ZodBoolean>;
55
+ tiktok: z.ZodDefault<z.ZodBoolean>;
56
+ youtube: z.ZodDefault<z.ZodBoolean>;
57
+ linkedin: z.ZodDefault<z.ZodBoolean>;
58
+ }, z.core.$strip>>;
59
+ active: z.ZodDefault<z.ZodBoolean>;
60
+ }, z.core.$strip>;
61
+ export declare const appsFileSchema: z.ZodObject<{
62
+ apps: z.ZodArray<z.ZodObject<{
63
+ id: z.ZodString;
64
+ name: z.ZodString;
65
+ platform: z.ZodArray<z.ZodEnum<{
66
+ ios: "ios";
67
+ android: "android";
68
+ }>>;
69
+ appStoreId: z.ZodOptional<z.ZodString>;
70
+ playStorePackage: z.ZodOptional<z.ZodString>;
71
+ eodinSdkAppId: z.ZodOptional<z.ZodString>;
72
+ asoMobileId: z.ZodOptional<z.ZodString>;
73
+ youtubeChannelId: z.ZodOptional<z.ZodString>;
74
+ primaryKeywords: z.ZodDefault<z.ZodArray<z.ZodString>>;
75
+ competitors: z.ZodDefault<z.ZodArray<z.ZodString>>;
76
+ locale: z.ZodDefault<z.ZodArray<z.ZodString>>;
77
+ features: z.ZodDefault<z.ZodObject<{
78
+ fridgifyRecipes: z.ZodDefault<z.ZodBoolean>;
79
+ }, z.core.$strip>>;
80
+ social: z.ZodDefault<z.ZodObject<{
81
+ twitter: z.ZodDefault<z.ZodBoolean>;
82
+ facebook: z.ZodDefault<z.ZodBoolean>;
83
+ threads: z.ZodDefault<z.ZodBoolean>;
84
+ tiktok: z.ZodDefault<z.ZodBoolean>;
85
+ youtube: z.ZodDefault<z.ZodBoolean>;
86
+ linkedin: z.ZodDefault<z.ZodBoolean>;
87
+ }, z.core.$strip>>;
88
+ active: z.ZodDefault<z.ZodBoolean>;
89
+ }, z.core.$strip>>;
90
+ }, z.core.$strip>;
91
+ export type AppPlatform = z.infer<typeof appPlatformSchema>;
92
+ export type AppConfig = z.infer<typeof appConfigSchema>;
93
+ export type AppsFile = z.infer<typeof appsFileSchema>;
94
+ //# sourceMappingURL=apps-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps-schema.d.ts","sourceRoot":"","sources":["../../src/config/apps-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB;;;EAA6B,CAAC;AAE5D,eAAO,MAAM,eAAe;;;;;;;kBAgBxB,CAAC;AAEL,eAAO,MAAM,iBAAiB;;kBAKQ,CAAC;AAEvC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoB1B,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEzB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AACxD,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * `apps.yaml` schema.
4
+ *
5
+ * Lives at the repo root (dev) or `$ADARIA_HOME/apps.yaml` (installed)
6
+ * and holds the per-app metadata the skills and orchestrators iterate
7
+ * over. Global credentials stay in `config.yaml.collectors`; per-app
8
+ * identifiers (App Store numeric id, Play package name, YouTube channel
9
+ * id, primary keywords, etc.) belong here because the operator adds and
10
+ * removes apps independently from rotating secrets.
11
+ *
12
+ * Wire shape note: fields are camelCase even though the growth-agent
13
+ * predecessor used snake_case (`appstore_id`, `playstore_id`). The port
14
+ * is one-shot so users re-write `apps.yaml` from the example template
15
+ * once; the new names match TypeScript convention and the wire-shape
16
+ * delta rule in `src/types/collectors.ts`.
17
+ */
18
+ export const appPlatformSchema = z.enum(["ios", "android"]);
19
+ export const appSocialSchema = z
20
+ .object({
21
+ twitter: z.boolean().default(false),
22
+ facebook: z.boolean().default(false),
23
+ threads: z.boolean().default(false),
24
+ tiktok: z.boolean().default(false),
25
+ youtube: z.boolean().default(false),
26
+ linkedin: z.boolean().default(false),
27
+ })
28
+ .default({
29
+ twitter: false,
30
+ facebook: false,
31
+ threads: false,
32
+ tiktok: false,
33
+ youtube: false,
34
+ linkedin: false,
35
+ });
36
+ export const appFeaturesSchema = z
37
+ .object({
38
+ /** Enable the Fridgify recipe cascade in SeoBlogSkill (M5+). */
39
+ fridgifyRecipes: z.boolean().default(false),
40
+ })
41
+ .default({ fridgifyRecipes: false });
42
+ export const appConfigSchema = z.object({
43
+ id: z.string().min(1),
44
+ name: z.string().min(1),
45
+ platform: z.array(appPlatformSchema).min(1),
46
+ /** App Store numeric id (string to preserve leading zeros). */
47
+ appStoreId: z.string().optional(),
48
+ /** Google Play package name (e.g. `com.eodin.fridgify`). */
49
+ playStorePackage: z.string().optional(),
50
+ /** App id the Eodin SDK analytics service knows this app by. */
51
+ eodinSdkAppId: z.string().optional(),
52
+ /** ASOMobile id (usually the App Store numeric id reused). */
53
+ asoMobileId: z.string().optional(),
54
+ /** YouTube channel whose Shorts back this app's growth loop. */
55
+ youtubeChannelId: z.string().optional(),
56
+ primaryKeywords: z.array(z.string()).default([]),
57
+ competitors: z.array(z.string()).default([]),
58
+ locale: z.array(z.string()).default([]),
59
+ features: appFeaturesSchema,
60
+ social: appSocialSchema,
61
+ active: z.boolean().default(true),
62
+ });
63
+ export const appsFileSchema = z.object({
64
+ apps: z.array(appConfigSchema).min(1),
65
+ });
66
+ //# sourceMappingURL=apps-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps-schema.js","sourceRoot":"","sources":["../../src/config/apps-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Derive the Keychain service prefix from the current `ADARIA_HOME` so
3
+ * dev profiles (`ADARIA_HOME=$HOME/.adaria-dev`) cannot clobber the
4
+ * production secrets in `$HOME/.adaria`. Prod stays on `adaria-ai`
5
+ * (backwards-compatible) and any non-default home gets `adaria-ai-<slug>`.
6
+ *
7
+ * Split into a helper so tests can exercise it without touching the
8
+ * real macOS Keychain.
9
+ */
10
+ export declare function deriveServicePrefix(adariaHome?: string): string;
11
+ export declare function setSecret(key: string, value: string): Promise<void>;
12
+ export declare function getSecret(key: string): Promise<string | null>;
13
+ export declare function deleteSecret(key: string): Promise<void>;
14
+ //# sourceMappingURL=keychain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.d.ts","sourceRoot":"","sources":["../../src/config/keychain.ts"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB/D;AAWD,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBzE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAenE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO7D"}
@@ -0,0 +1,89 @@
1
+ import { execFile } from "node:child_process";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { promisify } from "node:util";
5
+ const execFileAsync = promisify(execFile);
6
+ const DEFAULT_ADARIA_HOME = path.join(os.homedir(), ".adaria");
7
+ /**
8
+ * Derive the Keychain service prefix from the current `ADARIA_HOME` so
9
+ * dev profiles (`ADARIA_HOME=$HOME/.adaria-dev`) cannot clobber the
10
+ * production secrets in `$HOME/.adaria`. Prod stays on `adaria-ai`
11
+ * (backwards-compatible) and any non-default home gets `adaria-ai-<slug>`.
12
+ *
13
+ * Split into a helper so tests can exercise it without touching the
14
+ * real macOS Keychain.
15
+ */
16
+ export function deriveServicePrefix(adariaHome) {
17
+ const home = adariaHome ?? process.env["ADARIA_HOME"] ?? DEFAULT_ADARIA_HOME;
18
+ if (path.resolve(home) === path.resolve(DEFAULT_ADARIA_HOME)) {
19
+ return "adaria-ai";
20
+ }
21
+ const basename = path.basename(home);
22
+ // Strip leading dot(s) and slugify — Keychain service names tolerate
23
+ // alphanumerics, hyphens, and underscores comfortably.
24
+ const slug = basename
25
+ .replace(/^\.+/, "")
26
+ .replace(/[^a-zA-Z0-9_-]/g, "-")
27
+ .toLowerCase();
28
+ if (slug.length === 0)
29
+ return "adaria-ai";
30
+ // Preserve the `adaria-ai` prefix and strip any redundant `adaria`
31
+ // fragment the user may have already put into their home name.
32
+ const trimmed = slug.replace(/^adaria[_-]?/, "");
33
+ if (trimmed.length === 0 || trimmed === "ai")
34
+ return "adaria-ai";
35
+ return `adaria-ai-${trimmed}`;
36
+ }
37
+ // Account name stays constant across profiles. The prod/dev distinction
38
+ // lives in the Keychain *service* name so both profiles can coexist while
39
+ // still being user-attributable to the same principal.
40
+ const KEYCHAIN_ACCOUNT = "adaria-ai";
41
+ function serviceKey(key) {
42
+ return `${deriveServicePrefix()}:${key}`;
43
+ }
44
+ export async function setSecret(key, value) {
45
+ const service = serviceKey(key);
46
+ try {
47
+ await execFileAsync("security", ["delete-generic-password", "-s", service]);
48
+ }
49
+ catch {
50
+ // Not found — expected on first write
51
+ }
52
+ await execFileAsync("security", [
53
+ "add-generic-password",
54
+ "-s",
55
+ service,
56
+ "-a",
57
+ KEYCHAIN_ACCOUNT,
58
+ "-w",
59
+ value,
60
+ "-U",
61
+ ]);
62
+ }
63
+ export async function getSecret(key) {
64
+ const service = serviceKey(key);
65
+ try {
66
+ const { stdout } = await execFileAsync("security", [
67
+ "find-generic-password",
68
+ "-s",
69
+ service,
70
+ "-a",
71
+ KEYCHAIN_ACCOUNT,
72
+ "-w",
73
+ ]);
74
+ return stdout.trim();
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ export async function deleteSecret(key) {
81
+ const service = serviceKey(key);
82
+ try {
83
+ await execFileAsync("security", ["delete-generic-password", "-s", service]);
84
+ }
85
+ catch {
86
+ // Not found — nothing to delete
87
+ }
88
+ }
89
+ //# sourceMappingURL=keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/config/keychain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type AppConfig, type AppsFile } from "./apps-schema.js";
2
+ export interface LoadAppsOptions {
3
+ /** Include `active: false` apps in the result. Default false. */
4
+ includeInactive?: boolean;
5
+ /** Override path for tests or one-off runs. */
6
+ path?: string;
7
+ }
8
+ /**
9
+ * Load and validate `apps.yaml`. Returns only active apps unless
10
+ * `includeInactive` is set. Missing file or schema mismatch throws
11
+ * `ConfigError` with a user-friendly hint.
12
+ */
13
+ export declare function loadApps(options?: LoadAppsOptions): Promise<AppsFile & {
14
+ apps: AppConfig[];
15
+ }>;
16
+ //# sourceMappingURL=load-apps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-apps.d.ts","sourceRoot":"","sources":["../../src/config/load-apps.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,QAAQ,GAAG;IAAE,IAAI,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CA6B3C"}
@@ -0,0 +1,38 @@
1
+ import fs from "node:fs/promises";
2
+ import yaml from "js-yaml";
3
+ import { APPS_PATH } from "../utils/paths.js";
4
+ import { ConfigError } from "../utils/errors.js";
5
+ import { appsFileSchema, } from "./apps-schema.js";
6
+ /**
7
+ * Load and validate `apps.yaml`. Returns only active apps unless
8
+ * `includeInactive` is set. Missing file or schema mismatch throws
9
+ * `ConfigError` with a user-friendly hint.
10
+ */
11
+ export async function loadApps(options = {}) {
12
+ const filePath = options.path ?? APPS_PATH;
13
+ let raw;
14
+ try {
15
+ raw = await fs.readFile(filePath, "utf-8");
16
+ }
17
+ catch (cause) {
18
+ throw new ConfigError(`Apps config file not found at ${filePath}`, {
19
+ cause,
20
+ userMessage: `apps.yaml not found at ${filePath}. Copy \`apps.example.yaml\` from the repo root and edit it, or re-run \`adaria-ai init\`.`,
21
+ });
22
+ }
23
+ const parsed = yaml.load(raw, { schema: yaml.JSON_SCHEMA });
24
+ const result = appsFileSchema.safeParse(parsed);
25
+ if (!result.success) {
26
+ const issues = result.error.issues
27
+ .map((i) => ` - ${i.path.join(".")}: ${i.message}`)
28
+ .join("\n");
29
+ throw new ConfigError(`Invalid apps.yaml:\n${issues}`, {
30
+ userMessage: `apps.yaml at ${filePath} is invalid. See details below.`,
31
+ });
32
+ }
33
+ const filtered = options.includeInactive
34
+ ? result.data.apps
35
+ : result.data.apps.filter((app) => app.active);
36
+ return { apps: filtered };
37
+ }
38
+ //# sourceMappingURL=load-apps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-apps.js","sourceRoot":"","sources":["../../src/config/load-apps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,SAAS,CAAC;AAE3B,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EACL,cAAc,GAGf,MAAM,kBAAkB,CAAC;AAS1B;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAA2B,EAAE;IAE7B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,SAAS,CAAC;IAE3C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,WAAW,CAAC,iCAAiC,QAAQ,EAAE,EAAE;YACjE,KAAK;YACL,WAAW,EAAE,0BAA0B,QAAQ,4FAA4F;SAC5I,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;aACnD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,uBAAuB,MAAM,EAAE,EAAE;YACrD,WAAW,EAAE,gBAAgB,QAAQ,iCAAiC;SACvE,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe;QACtC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;QAClB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEjD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5B,CAAC"}