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.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/apps.example.yaml +65 -0
- package/dist/agent/audit.d.ts +16 -0
- package/dist/agent/audit.d.ts.map +1 -0
- package/dist/agent/audit.js +42 -0
- package/dist/agent/audit.js.map +1 -0
- package/dist/agent/claude.d.ts +62 -0
- package/dist/agent/claude.d.ts.map +1 -0
- package/dist/agent/claude.js +297 -0
- package/dist/agent/claude.js.map +1 -0
- package/dist/agent/conversation-summary.d.ts +29 -0
- package/dist/agent/conversation-summary.d.ts.map +1 -0
- package/dist/agent/conversation-summary.js +221 -0
- package/dist/agent/conversation-summary.js.map +1 -0
- package/dist/agent/core.d.ts +81 -0
- package/dist/agent/core.d.ts.map +1 -0
- package/dist/agent/core.js +527 -0
- package/dist/agent/core.js.map +1 -0
- package/dist/agent/mcp-launcher.d.ts +42 -0
- package/dist/agent/mcp-launcher.d.ts.map +1 -0
- package/dist/agent/mcp-launcher.js +38 -0
- package/dist/agent/mcp-launcher.js.map +1 -0
- package/dist/agent/mcp-manager.d.ts +81 -0
- package/dist/agent/mcp-manager.d.ts.map +1 -0
- package/dist/agent/mcp-manager.js +136 -0
- package/dist/agent/mcp-manager.js.map +1 -0
- package/dist/agent/memory.d.ts +10 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +95 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/safety.d.ts +45 -0
- package/dist/agent/safety.d.ts.map +1 -0
- package/dist/agent/safety.js +71 -0
- package/dist/agent/safety.js.map +1 -0
- package/dist/agent/session.d.ts +27 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +124 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/tool-descriptions.d.ts +8 -0
- package/dist/agent/tool-descriptions.d.ts.map +1 -0
- package/dist/agent/tool-descriptions.js +26 -0
- package/dist/agent/tool-descriptions.js.map +1 -0
- package/dist/cli/analyze.d.ts +8 -0
- package/dist/cli/analyze.d.ts.map +1 -0
- package/dist/cli/analyze.js +114 -0
- package/dist/cli/analyze.js.map +1 -0
- package/dist/cli/daemon.d.ts +2 -0
- package/dist/cli/daemon.d.ts.map +1 -0
- package/dist/cli/daemon.js +91 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/doctor.d.ts +2 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +198 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +459 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/logs.d.ts +4 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +50 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/monitor-cmd.d.ts +11 -0
- package/dist/cli/monitor-cmd.d.ts.map +1 -0
- package/dist/cli/monitor-cmd.js +59 -0
- package/dist/cli/monitor-cmd.js.map +1 -0
- package/dist/cli/start.d.ts +11 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +103 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/status.d.ts +9 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +49 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/stop.d.ts +2 -0
- package/dist/cli/stop.d.ts.map +1 -0
- package/dist/cli/stop.js +34 -0
- package/dist/cli/stop.js.map +1 -0
- package/dist/collectors/appstore.d.ts +51 -0
- package/dist/collectors/appstore.d.ts.map +1 -0
- package/dist/collectors/appstore.js +166 -0
- package/dist/collectors/appstore.js.map +1 -0
- package/dist/collectors/arden-tts.d.ts +60 -0
- package/dist/collectors/arden-tts.d.ts.map +1 -0
- package/dist/collectors/arden-tts.js +83 -0
- package/dist/collectors/arden-tts.js.map +1 -0
- package/dist/collectors/asomobile.d.ts +37 -0
- package/dist/collectors/asomobile.d.ts.map +1 -0
- package/dist/collectors/asomobile.js +88 -0
- package/dist/collectors/asomobile.js.map +1 -0
- package/dist/collectors/eodin-blog.d.ts +90 -0
- package/dist/collectors/eodin-blog.d.ts.map +1 -0
- package/dist/collectors/eodin-blog.js +238 -0
- package/dist/collectors/eodin-blog.js.map +1 -0
- package/dist/collectors/eodin-sdk.d.ts +60 -0
- package/dist/collectors/eodin-sdk.d.ts.map +1 -0
- package/dist/collectors/eodin-sdk.js +112 -0
- package/dist/collectors/eodin-sdk.js.map +1 -0
- package/dist/collectors/fridgify-recipes.d.ts +65 -0
- package/dist/collectors/fridgify-recipes.d.ts.map +1 -0
- package/dist/collectors/fridgify-recipes.js +111 -0
- package/dist/collectors/fridgify-recipes.js.map +1 -0
- package/dist/collectors/playstore.d.ts +46 -0
- package/dist/collectors/playstore.d.ts.map +1 -0
- package/dist/collectors/playstore.js +140 -0
- package/dist/collectors/playstore.js.map +1 -0
- package/dist/collectors/youtube.d.ts +44 -0
- package/dist/collectors/youtube.d.ts.map +1 -0
- package/dist/collectors/youtube.js +107 -0
- package/dist/collectors/youtube.js.map +1 -0
- package/dist/config/apps-schema.d.ts +94 -0
- package/dist/config/apps-schema.d.ts.map +1 -0
- package/dist/config/apps-schema.js +66 -0
- package/dist/config/apps-schema.js.map +1 -0
- package/dist/config/keychain.d.ts +14 -0
- package/dist/config/keychain.d.ts.map +1 -0
- package/dist/config/keychain.js +89 -0
- package/dist/config/keychain.js.map +1 -0
- package/dist/config/load-apps.d.ts +16 -0
- package/dist/config/load-apps.d.ts.map +1 -0
- package/dist/config/load-apps.js +38 -0
- package/dist/config/load-apps.js.map +1 -0
- package/dist/config/schema.d.ts +306 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +220 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/store.d.ts +38 -0
- package/dist/config/store.d.ts.map +1 -0
- package/dist/config/store.js +180 -0
- package/dist/config/store.js.map +1 -0
- package/dist/db/queries.d.ts +304 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +327 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +15 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +252 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/messenger/adapter.d.ts +63 -0
- package/dist/messenger/adapter.d.ts.map +1 -0
- package/dist/messenger/adapter.js +7 -0
- package/dist/messenger/adapter.js.map +1 -0
- package/dist/messenger/factory.d.ts +12 -0
- package/dist/messenger/factory.d.ts.map +1 -0
- package/dist/messenger/factory.js +9 -0
- package/dist/messenger/factory.js.map +1 -0
- package/dist/messenger/slack.d.ts +30 -0
- package/dist/messenger/slack.d.ts.map +1 -0
- package/dist/messenger/slack.js +309 -0
- package/dist/messenger/slack.js.map +1 -0
- package/dist/messenger/split.d.ts +17 -0
- package/dist/messenger/split.d.ts.map +1 -0
- package/dist/messenger/split.js +56 -0
- package/dist/messenger/split.js.map +1 -0
- package/dist/orchestrator/dashboard.d.ts +67 -0
- package/dist/orchestrator/dashboard.d.ts.map +1 -0
- package/dist/orchestrator/dashboard.js +113 -0
- package/dist/orchestrator/dashboard.js.map +1 -0
- package/dist/orchestrator/monitor.d.ts +37 -0
- package/dist/orchestrator/monitor.d.ts.map +1 -0
- package/dist/orchestrator/monitor.js +236 -0
- package/dist/orchestrator/monitor.js.map +1 -0
- package/dist/orchestrator/types.d.ts +82 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +12 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/orchestrator/weekly.d.ts +66 -0
- package/dist/orchestrator/weekly.d.ts.map +1 -0
- package/dist/orchestrator/weekly.js +376 -0
- package/dist/orchestrator/weekly.js.map +1 -0
- package/dist/prompts/loader.d.ts +18 -0
- package/dist/prompts/loader.d.ts.map +1 -0
- package/dist/prompts/loader.js +28 -0
- package/dist/prompts/loader.js.map +1 -0
- package/dist/security/auth.d.ts +14 -0
- package/dist/security/auth.d.ts.map +1 -0
- package/dist/security/auth.js +14 -0
- package/dist/security/auth.js.map +1 -0
- package/dist/security/prompt-guard.d.ts +21 -0
- package/dist/security/prompt-guard.d.ts.map +1 -0
- package/dist/security/prompt-guard.js +54 -0
- package/dist/security/prompt-guard.js.map +1 -0
- package/dist/skills/aso.d.ts +60 -0
- package/dist/skills/aso.d.ts.map +1 -0
- package/dist/skills/aso.js +322 -0
- package/dist/skills/aso.js.map +1 -0
- package/dist/skills/content.d.ts +25 -0
- package/dist/skills/content.d.ts.map +1 -0
- package/dist/skills/content.js +90 -0
- package/dist/skills/content.js.map +1 -0
- package/dist/skills/index.d.ts +65 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +90 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/onboarding.d.ts +58 -0
- package/dist/skills/onboarding.d.ts.map +1 -0
- package/dist/skills/onboarding.js +274 -0
- package/dist/skills/onboarding.js.map +1 -0
- package/dist/skills/registry.d.ts +24 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +66 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/review.d.ts +33 -0
- package/dist/skills/review.d.ts.map +1 -0
- package/dist/skills/review.js +236 -0
- package/dist/skills/review.js.map +1 -0
- package/dist/skills/sdk-request.d.ts +30 -0
- package/dist/skills/sdk-request.d.ts.map +1 -0
- package/dist/skills/sdk-request.js +72 -0
- package/dist/skills/sdk-request.js.map +1 -0
- package/dist/skills/seo-blog.d.ts +64 -0
- package/dist/skills/seo-blog.d.ts.map +1 -0
- package/dist/skills/seo-blog.js +268 -0
- package/dist/skills/seo-blog.js.map +1 -0
- package/dist/skills/short-form.d.ts +28 -0
- package/dist/skills/short-form.d.ts.map +1 -0
- package/dist/skills/short-form.js +121 -0
- package/dist/skills/short-form.js.map +1 -0
- package/dist/skills/social-publish.d.ts +32 -0
- package/dist/skills/social-publish.d.ts.map +1 -0
- package/dist/skills/social-publish.js +133 -0
- package/dist/skills/social-publish.js.map +1 -0
- package/dist/social/base.d.ts +47 -0
- package/dist/social/base.d.ts.map +1 -0
- package/dist/social/base.js +26 -0
- package/dist/social/base.js.map +1 -0
- package/dist/social/facebook.d.ts +27 -0
- package/dist/social/facebook.d.ts.map +1 -0
- package/dist/social/facebook.js +166 -0
- package/dist/social/facebook.js.map +1 -0
- package/dist/social/factory.d.ts +26 -0
- package/dist/social/factory.d.ts.map +1 -0
- package/dist/social/factory.js +32 -0
- package/dist/social/factory.js.map +1 -0
- package/dist/social/linkedin.d.ts +26 -0
- package/dist/social/linkedin.d.ts.map +1 -0
- package/dist/social/linkedin.js +190 -0
- package/dist/social/linkedin.js.map +1 -0
- package/dist/social/threads.d.ts +21 -0
- package/dist/social/threads.d.ts.map +1 -0
- package/dist/social/threads.js +122 -0
- package/dist/social/threads.js.map +1 -0
- package/dist/social/tiktok.d.ts +23 -0
- package/dist/social/tiktok.d.ts.map +1 -0
- package/dist/social/tiktok.js +110 -0
- package/dist/social/tiktok.js.map +1 -0
- package/dist/social/twitter.d.ts +30 -0
- package/dist/social/twitter.d.ts.map +1 -0
- package/dist/social/twitter.js +189 -0
- package/dist/social/twitter.js.map +1 -0
- package/dist/social/youtube.d.ts +21 -0
- package/dist/social/youtube.d.ts.map +1 -0
- package/dist/social/youtube.js +108 -0
- package/dist/social/youtube.js.map +1 -0
- package/dist/tools/app-info.d.ts +7 -0
- package/dist/tools/app-info.d.ts.map +1 -0
- package/dist/tools/app-info.js +53 -0
- package/dist/tools/app-info.js.map +1 -0
- package/dist/tools/collector-fetch.d.ts +11 -0
- package/dist/tools/collector-fetch.d.ts.map +1 -0
- package/dist/tools/collector-fetch.js +101 -0
- package/dist/tools/collector-fetch.js.map +1 -0
- package/dist/tools/db-query.d.ts +29 -0
- package/dist/tools/db-query.d.ts.map +1 -0
- package/dist/tools/db-query.js +159 -0
- package/dist/tools/db-query.js.map +1 -0
- package/dist/tools/skill-result.d.ts +8 -0
- package/dist/tools/skill-result.d.ts.map +1 -0
- package/dist/tools/skill-result.js +63 -0
- package/dist/tools/skill-result.js.map +1 -0
- package/dist/tools/tool-host.d.ts +12 -0
- package/dist/tools/tool-host.d.ts.map +1 -0
- package/dist/tools/tool-host.js +124 -0
- package/dist/tools/tool-host.js.map +1 -0
- package/dist/types/collectors.d.ts +198 -0
- package/dist/types/collectors.d.ts.map +1 -0
- package/dist/types/collectors.js +28 -0
- package/dist/types/collectors.js.map +1 -0
- package/dist/types/skill.d.ts +60 -0
- package/dist/types/skill.d.ts.map +1 -0
- package/dist/types/skill.js +9 -0
- package/dist/types/skill.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +26 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +67 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/errors.d.ts +44 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +75 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/escape.d.ts +11 -0
- package/dist/utils/escape.d.ts.map +1 -0
- package/dist/utils/escape.js +19 -0
- package/dist/utils/escape.js.map +1 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +93 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/parse-json.d.ts +13 -0
- package/dist/utils/parse-json.d.ts.map +1 -0
- package/dist/utils/parse-json.js +61 -0
- package/dist/utils/parse-json.js.map +1 -0
- package/dist/utils/paths.d.ts +14 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +19 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/rate-limiter.d.ts +20 -0
- package/dist/utils/rate-limiter.d.ts.map +1 -0
- package/dist/utils/rate-limiter.js +47 -0
- package/dist/utils/rate-limiter.js.map +1 -0
- package/dist/utils/retry.d.ts +26 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +61 -0
- package/dist/utils/retry.js.map +1 -0
- package/launchd/.gitkeep +0 -0
- package/launchd/com.adaria-ai.daemon.plist.template +62 -0
- package/launchd/com.adaria-ai.monitor.plist.template +41 -0
- package/launchd/com.adaria-ai.weekly.plist.template +43 -0
- package/package.json +72 -0
- package/prompts/aso-description.md +44 -0
- package/prompts/aso-inapp-events.md +20 -0
- package/prompts/aso-metadata.md +34 -0
- package/prompts/aso-screenshots.md +20 -0
- package/prompts/onboarding-hypotheses.md +38 -0
- package/prompts/onboarding-review-timing.md +24 -0
- package/prompts/review-clustering.md +19 -0
- package/prompts/review-replies.md +18 -0
- package/prompts/review-sentiment.md +16 -0
- package/prompts/seo-blog-fridgify-recipe.md +116 -0
- package/prompts/seo-blog.md +69 -0
- package/prompts/short-form-ideas.md +50 -0
- 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"}
|