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 @@
|
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"AAsBA,eAAO,MAAM,YAAY,yBAAyB,CAAC;AACnD,eAAO,MAAM,YAAY,yBAAyB,CAAC;AACnD,eAAO,MAAM,aAAa,0BAA0B,CAAC;AAErD,qDAAqD;AACrD,eAAO,MAAM,UAAU,oFAAuD,CAAC;AAQ/E,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AA+BD,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAEvD;AAwBD,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA0B9C"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adaria-ai start` — load the daemon launchd plist.
|
|
3
|
+
*
|
|
4
|
+
* M1 only loads the reactive daemon. M6 will extend this to additionally
|
|
5
|
+
* load `com.adaria-ai.weekly` (cron Sun 23:00) and `com.adaria-ai.monitor`
|
|
6
|
+
* (cron daily 23:00). Each label is a separate plist; launchctl handles
|
|
7
|
+
* the three independently.
|
|
8
|
+
*/
|
|
9
|
+
import fs from "node:fs/promises";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { execFile } from "node:child_process";
|
|
13
|
+
import { promisify } from "node:util";
|
|
14
|
+
import { configExists } from "../config/store.js";
|
|
15
|
+
import { ADARIA_HOME, BUNDLED_LAUNCHD_DIR, LOGS_DIR, } from "../utils/paths.js";
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
export const DAEMON_LABEL = "com.adaria-ai.daemon";
|
|
18
|
+
export const WEEKLY_LABEL = "com.adaria-ai.weekly";
|
|
19
|
+
export const MONITOR_LABEL = "com.adaria-ai.monitor";
|
|
20
|
+
/** All three launchd labels managed by adaria-ai. */
|
|
21
|
+
export const ALL_LABELS = [DAEMON_LABEL, WEEKLY_LABEL, MONITOR_LABEL];
|
|
22
|
+
const LAUNCH_AGENTS_DIR = path.join(process.env["HOME"] ?? "", "Library", "LaunchAgents");
|
|
23
|
+
export function getPlistPath(label) {
|
|
24
|
+
return path.join(LAUNCH_AGENTS_DIR, `${label}.plist`);
|
|
25
|
+
}
|
|
26
|
+
export function getDaemonPlistPath() {
|
|
27
|
+
return getPlistPath(DAEMON_LABEL);
|
|
28
|
+
}
|
|
29
|
+
function getDaemonEntryScriptPath() {
|
|
30
|
+
// src/cli/start.ts at runtime lives at dist/cli/start.js. The CLI entry
|
|
31
|
+
// is dist/index.js, one directory up.
|
|
32
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
33
|
+
return path.resolve(path.dirname(thisFile), "..", "index.js");
|
|
34
|
+
}
|
|
35
|
+
async function renderPlist(label = DAEMON_LABEL) {
|
|
36
|
+
const templatePath = path.join(BUNDLED_LAUNCHD_DIR, `${label}.plist.template`);
|
|
37
|
+
const template = await fs.readFile(templatePath, "utf-8");
|
|
38
|
+
// launchd inherits a near-empty PATH, so we set an explicit one that
|
|
39
|
+
// matches a typical interactive shell. claude-cli usually lives in
|
|
40
|
+
// /opt/homebrew/bin (Apple Silicon) or /usr/local/bin (Intel).
|
|
41
|
+
const pathValue = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:" +
|
|
42
|
+
path.join(process.env["HOME"] ?? "", ".local", "bin");
|
|
43
|
+
return template
|
|
44
|
+
.replaceAll("__NODE_BIN__", process.execPath)
|
|
45
|
+
.replaceAll("__SCRIPT_PATH__", getDaemonEntryScriptPath())
|
|
46
|
+
.replaceAll("__ADARIA_HOME__", ADARIA_HOME)
|
|
47
|
+
.replaceAll("__LOG_DIR__", LOGS_DIR)
|
|
48
|
+
.replaceAll("__PATH__", pathValue);
|
|
49
|
+
}
|
|
50
|
+
export async function isLabelLoaded(label) {
|
|
51
|
+
try {
|
|
52
|
+
const { stdout } = await execFileAsync("launchctl", ["list"]);
|
|
53
|
+
return stdout.split("\n").some((l) => l.trim().split(/\s+/)[2] === label);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function isDaemonLoaded() {
|
|
60
|
+
return isLabelLoaded(DAEMON_LABEL);
|
|
61
|
+
}
|
|
62
|
+
async function loadLabel(label) {
|
|
63
|
+
if (await isLabelLoaded(label)) {
|
|
64
|
+
console.log(` ${label}: already loaded (skipped)`);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
const plistContent = await renderPlist(label);
|
|
68
|
+
const plistPath = getPlistPath(label);
|
|
69
|
+
await fs.writeFile(plistPath, plistContent, { mode: 0o644 });
|
|
70
|
+
try {
|
|
71
|
+
await execFileAsync("launchctl", ["load", plistPath]);
|
|
72
|
+
console.log(` ${label}: loaded`);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error(` ${label}: launchctl load failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export async function runStart() {
|
|
81
|
+
if (!(await configExists())) {
|
|
82
|
+
console.error('No configuration found. Run "adaria-ai init" first to create ~/.adaria/config.yaml.');
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await fs.mkdir(LOGS_DIR, { recursive: true, mode: 0o700 });
|
|
87
|
+
await fs.mkdir(LAUNCH_AGENTS_DIR, { recursive: true });
|
|
88
|
+
console.log("Loading adaria-ai launchd agents...");
|
|
89
|
+
let allOk = true;
|
|
90
|
+
for (const label of ALL_LABELS) {
|
|
91
|
+
const ok = await loadLabel(label);
|
|
92
|
+
if (!ok)
|
|
93
|
+
allOk = false;
|
|
94
|
+
}
|
|
95
|
+
if (allOk) {
|
|
96
|
+
console.log(`\nAll 3 agents loaded. Logs: ${LOGS_DIR}/`);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
console.error("\nSome agents failed to load. Check errors above.");
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/cli/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface JobStatus {
|
|
2
|
+
label: string;
|
|
3
|
+
running: boolean;
|
|
4
|
+
pid: number | null;
|
|
5
|
+
lastExitStatus: number | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function getJobStatus(label: string): Promise<JobStatus>;
|
|
8
|
+
export declare function runStatus(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA6BpE;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAe/C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { ALL_LABELS } from "./start.js";
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
export async function getJobStatus(label) {
|
|
6
|
+
try {
|
|
7
|
+
const { stdout } = await execFileAsync("launchctl", ["list"]);
|
|
8
|
+
// `launchctl list` is tab-separated: `<pid>\t<exit>\t<label>`. Use
|
|
9
|
+
// exact field match on column 3 so `com.adaria-ai.daemon` can't be
|
|
10
|
+
// substring-matched against a longer future label like
|
|
11
|
+
// `com.adaria-ai.daemon-replica` (M1 CLI review MED #2).
|
|
12
|
+
const line = stdout
|
|
13
|
+
.split("\n")
|
|
14
|
+
.find((l) => l.trim().split(/\s+/)[2] === label);
|
|
15
|
+
if (!line) {
|
|
16
|
+
return { label, running: false, pid: null, lastExitStatus: null };
|
|
17
|
+
}
|
|
18
|
+
const parts = line.trim().split(/\s+/);
|
|
19
|
+
const pidStr = parts[0];
|
|
20
|
+
const exitStr = parts[1];
|
|
21
|
+
const pid = pidStr === "-" || pidStr === undefined ? null : parseInt(pidStr, 10);
|
|
22
|
+
const lastExitStatus = exitStr === "-" || exitStr === undefined ? null : parseInt(exitStr, 10);
|
|
23
|
+
return {
|
|
24
|
+
label,
|
|
25
|
+
running: pid !== null,
|
|
26
|
+
pid,
|
|
27
|
+
lastExitStatus,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return { label, running: false, pid: null, lastExitStatus: null };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function runStatus() {
|
|
35
|
+
const labels = ALL_LABELS;
|
|
36
|
+
for (const label of labels) {
|
|
37
|
+
const status = await getJobStatus(label);
|
|
38
|
+
if (status.running) {
|
|
39
|
+
console.log(`${label}: running (PID ${String(status.pid)})`);
|
|
40
|
+
}
|
|
41
|
+
else if (status.lastExitStatus !== null) {
|
|
42
|
+
console.log(`${label}: stopped (last exit ${String(status.lastExitStatus)})`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log(`${label}: not loaded`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAS1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9D,mEAAmE;QACnE,mEAAmE;QACnE,uDAAuD;QACvD,yDAAyD;QACzD,MAAM,IAAI,GAAG,MAAM;aAChB,KAAK,CAAC,IAAI,CAAC;aACX,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;QACpE,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,GAAG,GACP,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACvE,MAAM,cAAc,GAClB,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC1E,OAAO;YACL,KAAK;YACL,OAAO,EAAE,GAAG,KAAK,IAAI;YACrB,GAAG;YACH,cAAc;SACf,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IACpE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,MAAM,GAAG,UAAU,CAAC;IAE1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,kBAAkB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;aAAM,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CACT,GAAG,KAAK,wBAAwB,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CACjE,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,cAAc,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/cli/stop.ts"],"names":[],"mappings":"AAiCA,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ7C"}
|
package/dist/cli/stop.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { ALL_LABELS, getPlistPath, isLabelLoaded } from "./start.js";
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
async function unloadLabel(label) {
|
|
7
|
+
if (!(await isLabelLoaded(label))) {
|
|
8
|
+
console.log(` ${label}: not loaded (skipped)`);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const plistPath = getPlistPath(label);
|
|
12
|
+
try {
|
|
13
|
+
await execFileAsync("launchctl", ["unload", plistPath]);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
console.error(` ${label}: launchctl unload failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
await fs.unlink(plistPath);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Plist already removed, ok.
|
|
24
|
+
}
|
|
25
|
+
console.log(` ${label}: unloaded`);
|
|
26
|
+
}
|
|
27
|
+
export async function runStop() {
|
|
28
|
+
console.log("Unloading adaria-ai launchd agents...");
|
|
29
|
+
for (const label of ALL_LABELS) {
|
|
30
|
+
await unloadLabel(label);
|
|
31
|
+
}
|
|
32
|
+
console.log("\nDone.");
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/cli/stop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,KAAK,UAAU,WAAW,CAAC,KAAa;IACtC,IAAI,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,wBAAwB,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CACX,KAAK,KAAK,8BAA8B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC3F,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IAErD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AppStoreLocalization, AppStoreLocalizationUpdate, StoreReview } from "../types/collectors.js";
|
|
2
|
+
/**
|
|
3
|
+
* App Store Connect API collector.
|
|
4
|
+
*
|
|
5
|
+
* @see https://developer.apple.com/documentation/appstoreconnectapi
|
|
6
|
+
*/
|
|
7
|
+
export interface AppStoreCollectorOptions {
|
|
8
|
+
keyId: string;
|
|
9
|
+
issuerId: string;
|
|
10
|
+
/** PEM-encoded private key (PKCS#8) for ES256 JWT signing. */
|
|
11
|
+
privateKey: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Test-only overrides. Deliberately kept off {@link AppStoreCollectorOptions}
|
|
15
|
+
* so that production config loaders (M3) cannot introduce a user-controlled
|
|
16
|
+
* base URL into the SSRF surface. Only passed from unit tests.
|
|
17
|
+
*/
|
|
18
|
+
export interface AppStoreCollectorTestHooks {
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
interface AppStoreInfoResponse {
|
|
22
|
+
data: {
|
|
23
|
+
id: string;
|
|
24
|
+
}[];
|
|
25
|
+
}
|
|
26
|
+
export declare class AppStoreCollector {
|
|
27
|
+
private readonly keyId;
|
|
28
|
+
private readonly issuerId;
|
|
29
|
+
private readonly privateKey;
|
|
30
|
+
private readonly baseUrl;
|
|
31
|
+
private cachedToken;
|
|
32
|
+
private tokenExpiresAt;
|
|
33
|
+
constructor(options: AppStoreCollectorOptions, testHooks?: AppStoreCollectorTestHooks);
|
|
34
|
+
private generateToken;
|
|
35
|
+
private request;
|
|
36
|
+
getAppInfo(appStoreId: string): Promise<AppStoreInfoResponse>;
|
|
37
|
+
getAppLocalizations(appStoreId: string, locale?: string): Promise<AppStoreLocalization | null>;
|
|
38
|
+
/**
|
|
39
|
+
* Update app localization metadata (title, subtitle, keywords, description).
|
|
40
|
+
* Requires App Store Connect API write permission and should only be
|
|
41
|
+
* called from an approval-gated write path.
|
|
42
|
+
*/
|
|
43
|
+
updateLocalization(localizationId: string, update: AppStoreLocalizationUpdate): Promise<unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Reply to a customer review. Approval-gated write path.
|
|
46
|
+
*/
|
|
47
|
+
replyToReview(reviewId: string, responseBody: string): Promise<unknown>;
|
|
48
|
+
getReviews(appStoreId: string, limit?: number): Promise<StoreReview[]>;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=appstore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appstore.d.ts","sourceRoot":"","sources":["../../src/collectors/appstore.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAC1B,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAEhC;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA4BD,UAAU,oBAAoB;IAC5B,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACxB;AAaD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAK;gBAGzB,OAAO,EAAE,wBAAwB,EACjC,SAAS,CAAC,EAAE,0BAA0B;YAa1B,aAAa;YAmBb,OAAO;IAmCf,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI7D,mBAAmB,CACvB,UAAU,EAAE,MAAM,EAClB,MAAM,SAAO,GACZ,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAyBvC;;;;OAIG;IACG,kBAAkB,CACtB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC,OAAO,CAAC;IAgDnB;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuBvE,UAAU,CACd,UAAU,EAAE,MAAM,EAClB,KAAK,SAAK,GACT,OAAO,CAAC,WAAW,EAAE,CAAC;CAW1B"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { SignJWT, importPKCS8 } from "jose";
|
|
2
|
+
import { ExternalApiError, RateLimitError } from "../utils/errors.js";
|
|
3
|
+
import { parseRetryAfter } from "../utils/retry.js";
|
|
4
|
+
const DEFAULT_BASE_URL = "https://api.appstoreconnect.apple.com/v1";
|
|
5
|
+
const TOKEN_LIFETIME_MS = 19 * 60 * 1000;
|
|
6
|
+
const NAME_LIMIT = 30;
|
|
7
|
+
const SUBTITLE_LIMIT = 30;
|
|
8
|
+
const KEYWORDS_LIMIT = 100;
|
|
9
|
+
const REVIEW_RESPONSE_LIMIT = 5970;
|
|
10
|
+
export class AppStoreCollector {
|
|
11
|
+
keyId;
|
|
12
|
+
issuerId;
|
|
13
|
+
privateKey;
|
|
14
|
+
baseUrl;
|
|
15
|
+
cachedToken = null;
|
|
16
|
+
tokenExpiresAt = 0;
|
|
17
|
+
constructor(options, testHooks) {
|
|
18
|
+
if (!options.keyId || !options.issuerId || !options.privateKey) {
|
|
19
|
+
throw new Error("AppStoreCollector requires keyId, issuerId, and privateKey");
|
|
20
|
+
}
|
|
21
|
+
this.keyId = options.keyId;
|
|
22
|
+
this.issuerId = options.issuerId;
|
|
23
|
+
this.privateKey = options.privateKey;
|
|
24
|
+
this.baseUrl = testHooks?.baseUrl ?? DEFAULT_BASE_URL;
|
|
25
|
+
}
|
|
26
|
+
async generateToken() {
|
|
27
|
+
if (this.cachedToken && Date.now() < this.tokenExpiresAt) {
|
|
28
|
+
return this.cachedToken;
|
|
29
|
+
}
|
|
30
|
+
const key = await importPKCS8(this.privateKey, "ES256");
|
|
31
|
+
const token = await new SignJWT({})
|
|
32
|
+
.setProtectedHeader({ alg: "ES256", kid: this.keyId, typ: "JWT" })
|
|
33
|
+
.setIssuer(this.issuerId)
|
|
34
|
+
.setIssuedAt()
|
|
35
|
+
.setExpirationTime("20m")
|
|
36
|
+
.setAudience("appstoreconnect-v1")
|
|
37
|
+
.sign(key);
|
|
38
|
+
this.cachedToken = token;
|
|
39
|
+
this.tokenExpiresAt = Date.now() + TOKEN_LIFETIME_MS;
|
|
40
|
+
return token;
|
|
41
|
+
}
|
|
42
|
+
async request(path, init) {
|
|
43
|
+
const token = await this.generateToken();
|
|
44
|
+
const url = `${this.baseUrl}${path}`;
|
|
45
|
+
const headers = {
|
|
46
|
+
Authorization: `Bearer ${token}`,
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
...(init?.headers ?? {}),
|
|
49
|
+
};
|
|
50
|
+
const fetchInit = { headers };
|
|
51
|
+
if (init?.method !== undefined)
|
|
52
|
+
fetchInit.method = init.method;
|
|
53
|
+
if (init?.body !== undefined)
|
|
54
|
+
fetchInit.body = init.body;
|
|
55
|
+
const response = await fetch(url, fetchInit);
|
|
56
|
+
if (response.status === 429) {
|
|
57
|
+
throw new RateLimitError("App Store API rate limited", {
|
|
58
|
+
retryAfterSeconds: parseRetryAfter(response.headers.get("Retry-After")),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
const body = await response.text();
|
|
63
|
+
throw new ExternalApiError(`App Store API ${String(response.status)}: ${body}`, { statusCode: response.status });
|
|
64
|
+
}
|
|
65
|
+
return (await response.json());
|
|
66
|
+
}
|
|
67
|
+
async getAppInfo(appStoreId) {
|
|
68
|
+
return this.request(`/apps/${appStoreId}/appInfos`);
|
|
69
|
+
}
|
|
70
|
+
async getAppLocalizations(appStoreId, locale = "ko") {
|
|
71
|
+
const infos = await this.getAppInfo(appStoreId);
|
|
72
|
+
const infoId = infos.data[0]?.id;
|
|
73
|
+
if (!infoId)
|
|
74
|
+
return null;
|
|
75
|
+
const localizations = await this.request(`/appInfos/${infoId}/appInfoLocalizations`);
|
|
76
|
+
const match = localizations.data.find((l) => l.attributes?.locale === locale);
|
|
77
|
+
if (!match)
|
|
78
|
+
return null;
|
|
79
|
+
const attrs = match.attributes ?? {};
|
|
80
|
+
return {
|
|
81
|
+
id: match.id,
|
|
82
|
+
locale: attrs.locale ?? locale,
|
|
83
|
+
name: attrs.name ?? "",
|
|
84
|
+
subtitle: attrs.subtitle ?? "",
|
|
85
|
+
keywords: attrs.keywords ?? "",
|
|
86
|
+
description: attrs.description ?? "",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Update app localization metadata (title, subtitle, keywords, description).
|
|
91
|
+
* Requires App Store Connect API write permission and should only be
|
|
92
|
+
* called from an approval-gated write path.
|
|
93
|
+
*/
|
|
94
|
+
async updateLocalization(localizationId, update) {
|
|
95
|
+
if (!localizationId) {
|
|
96
|
+
throw new Error("updateLocalization: localizationId is required");
|
|
97
|
+
}
|
|
98
|
+
if (update.name === undefined &&
|
|
99
|
+
update.subtitle === undefined &&
|
|
100
|
+
update.keywords === undefined &&
|
|
101
|
+
update.description === undefined) {
|
|
102
|
+
throw new Error("updateLocalization: at least one field must be provided");
|
|
103
|
+
}
|
|
104
|
+
if (update.name !== undefined && update.name.length > NAME_LIMIT) {
|
|
105
|
+
throw new Error(`updateLocalization: name exceeds ${String(NAME_LIMIT)} char limit (${String(update.name.length)})`);
|
|
106
|
+
}
|
|
107
|
+
if (update.subtitle !== undefined && update.subtitle.length > SUBTITLE_LIMIT) {
|
|
108
|
+
throw new Error(`updateLocalization: subtitle exceeds ${String(SUBTITLE_LIMIT)} char limit (${String(update.subtitle.length)})`);
|
|
109
|
+
}
|
|
110
|
+
if (update.keywords !== undefined && update.keywords.length > KEYWORDS_LIMIT) {
|
|
111
|
+
throw new Error(`updateLocalization: keywords exceeds ${String(KEYWORDS_LIMIT)} char limit (${String(update.keywords.length)})`);
|
|
112
|
+
}
|
|
113
|
+
const attributes = {};
|
|
114
|
+
if (update.name !== undefined)
|
|
115
|
+
attributes.name = update.name;
|
|
116
|
+
if (update.subtitle !== undefined)
|
|
117
|
+
attributes.subtitle = update.subtitle;
|
|
118
|
+
if (update.keywords !== undefined)
|
|
119
|
+
attributes.keywords = update.keywords;
|
|
120
|
+
if (update.description !== undefined)
|
|
121
|
+
attributes.description = update.description;
|
|
122
|
+
return this.request(`/appInfoLocalizations/${localizationId}`, {
|
|
123
|
+
method: "PATCH",
|
|
124
|
+
body: JSON.stringify({
|
|
125
|
+
data: {
|
|
126
|
+
type: "appInfoLocalizations",
|
|
127
|
+
id: localizationId,
|
|
128
|
+
attributes,
|
|
129
|
+
},
|
|
130
|
+
}),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Reply to a customer review. Approval-gated write path.
|
|
135
|
+
*/
|
|
136
|
+
async replyToReview(reviewId, responseBody) {
|
|
137
|
+
if (typeof responseBody !== "string" || responseBody.trim().length === 0) {
|
|
138
|
+
throw new Error("replyToReview: responseBody must be a non-empty string");
|
|
139
|
+
}
|
|
140
|
+
if (responseBody.length > REVIEW_RESPONSE_LIMIT) {
|
|
141
|
+
throw new Error(`replyToReview: responseBody exceeds App Store ${String(REVIEW_RESPONSE_LIMIT)} char limit (${String(responseBody.length)})`);
|
|
142
|
+
}
|
|
143
|
+
return this.request(`/customerReviewResponses`, {
|
|
144
|
+
method: "POST",
|
|
145
|
+
body: JSON.stringify({
|
|
146
|
+
data: {
|
|
147
|
+
type: "customerReviewResponses",
|
|
148
|
+
attributes: { responseBody },
|
|
149
|
+
relationships: {
|
|
150
|
+
review: { data: { type: "customerReviews", id: reviewId } },
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
async getReviews(appStoreId, limit = 50) {
|
|
157
|
+
const data = await this.request(`/apps/${appStoreId}/customerReviews?limit=${String(limit)}&sort=-createdDate`);
|
|
158
|
+
return (data.data ?? []).map((r) => ({
|
|
159
|
+
reviewId: r.id,
|
|
160
|
+
rating: r.attributes.rating,
|
|
161
|
+
body: r.attributes.body,
|
|
162
|
+
createdAt: r.attributes.createdDate,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=appstore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appstore.js","sourceRoot":"","sources":["../../src/collectors/appstore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arden TTS API client.
|
|
3
|
+
*
|
|
4
|
+
* Converts short-form scripts to voiceover MP3 buffers. This is an
|
|
5
|
+
* **internal** service owned by the same operator that runs adaria-ai,
|
|
6
|
+
* so unlike the external collectors (App Store / Play Store / ASOMobile)
|
|
7
|
+
* the endpoint is fully config-driven — there is no public production
|
|
8
|
+
* hostname to allowlist. Trust derives from config ownership, not from
|
|
9
|
+
* a baked-in allowlist. `config.yaml` is the source of truth.
|
|
10
|
+
*
|
|
11
|
+
* Cost: $0 (Eodin's own TTS service; cross-promotion effect).
|
|
12
|
+
*/
|
|
13
|
+
export interface ArdenTtsClientOptions {
|
|
14
|
+
/** Base endpoint URL from `config.yaml` (trusted source). */
|
|
15
|
+
endpoint: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SynthesizeOptions {
|
|
18
|
+
/** Voice identifier. Defaults to `default`. */
|
|
19
|
+
voice?: string;
|
|
20
|
+
/** Playback speed multiplier. Defaults to 1.0. */
|
|
21
|
+
speed?: number;
|
|
22
|
+
/** BCP-47 locale tag. Defaults to `ko`. */
|
|
23
|
+
locale?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SynthesizeScript {
|
|
26
|
+
title: string;
|
|
27
|
+
script: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SynthesizeResult {
|
|
30
|
+
title: string;
|
|
31
|
+
audio: Buffer;
|
|
32
|
+
}
|
|
33
|
+
export interface SynthesizeFailure {
|
|
34
|
+
title: string;
|
|
35
|
+
error: string;
|
|
36
|
+
statusCode?: number;
|
|
37
|
+
}
|
|
38
|
+
export interface SynthesizeBatchResult {
|
|
39
|
+
successes: SynthesizeResult[];
|
|
40
|
+
failures: SynthesizeFailure[];
|
|
41
|
+
}
|
|
42
|
+
export declare class ArdenTtsClient {
|
|
43
|
+
private readonly endpoint;
|
|
44
|
+
constructor(options: ArdenTtsClientOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Generate voiceover audio from a script.
|
|
47
|
+
*
|
|
48
|
+
* @returns an MP3 audio buffer.
|
|
49
|
+
*/
|
|
50
|
+
synthesize(text: string, options?: SynthesizeOptions): Promise<Buffer>;
|
|
51
|
+
/**
|
|
52
|
+
* Generate voiceovers for multiple scripts sequentially. Per-script
|
|
53
|
+
* failures are logged with the structured status code (so
|
|
54
|
+
* `ShortFormSkill` can tell a 429 from a 500) and collected in the
|
|
55
|
+
* `failures` array; the overall call never rejects, so one bad script
|
|
56
|
+
* cannot take down a whole short-form batch.
|
|
57
|
+
*/
|
|
58
|
+
synthesizeBatch(scripts: SynthesizeScript[], options?: SynthesizeOptions): Promise<SynthesizeBatchResult>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=arden-tts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arden-tts.d.ts","sourceRoot":"","sources":["../../src/collectors/arden-tts.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEtB,OAAO,EAAE,qBAAqB;IA4B1C;;;;OAIG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC;IAwBlB;;;;;;OAMG;IACG,eAAe,CACnB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC;CAwBlC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { ExternalApiError } from "../utils/errors.js";
|
|
2
|
+
import { error as logError } from "../utils/logger.js";
|
|
3
|
+
export class ArdenTtsClient {
|
|
4
|
+
endpoint;
|
|
5
|
+
constructor(options) {
|
|
6
|
+
if (!options.endpoint) {
|
|
7
|
+
throw new Error("ArdenTtsClient requires endpoint");
|
|
8
|
+
}
|
|
9
|
+
// Arden TTS is user-hosted so we cannot pin a host allowlist (see
|
|
10
|
+
// the file header). Enforce at least the scheme + parseability
|
|
11
|
+
// contract so mis-typed config.yaml values fail loudly at
|
|
12
|
+
// construction instead of deep inside undici with an opaque
|
|
13
|
+
// TypeError. javascript:, file:, etc. all get rejected here.
|
|
14
|
+
let parsed;
|
|
15
|
+
try {
|
|
16
|
+
parsed = new URL(options.endpoint.trim());
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
throw new Error(`ArdenTtsClient endpoint must be a valid URL, got: ${options.endpoint}`);
|
|
20
|
+
}
|
|
21
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
22
|
+
throw new Error(`ArdenTtsClient endpoint must use http(s), got: ${parsed.protocol}`);
|
|
23
|
+
}
|
|
24
|
+
// Trim trailing slashes on the base URL only. A user-provided
|
|
25
|
+
// subpath (e.g. `/api/v2`) is preserved intact — `synthesize` appends
|
|
26
|
+
// `/synthesize` to whatever path the caller configured.
|
|
27
|
+
this.endpoint = parsed.toString().replace(/\/+$/, "");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate voiceover audio from a script.
|
|
31
|
+
*
|
|
32
|
+
* @returns an MP3 audio buffer.
|
|
33
|
+
*/
|
|
34
|
+
async synthesize(text, options = {}) {
|
|
35
|
+
const response = await fetch(`${this.endpoint}/synthesize`, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: { "Content-Type": "application/json" },
|
|
38
|
+
body: JSON.stringify({
|
|
39
|
+
text,
|
|
40
|
+
voice: options.voice ?? "default",
|
|
41
|
+
speed: options.speed ?? 1.0,
|
|
42
|
+
locale: options.locale ?? "ko",
|
|
43
|
+
}),
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const body = await response.text();
|
|
47
|
+
throw new ExternalApiError(`Arden TTS API ${String(response.status)}: ${body.slice(0, 512)}`, { statusCode: response.status });
|
|
48
|
+
}
|
|
49
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
50
|
+
return Buffer.from(arrayBuffer);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate voiceovers for multiple scripts sequentially. Per-script
|
|
54
|
+
* failures are logged with the structured status code (so
|
|
55
|
+
* `ShortFormSkill` can tell a 429 from a 500) and collected in the
|
|
56
|
+
* `failures` array; the overall call never rejects, so one bad script
|
|
57
|
+
* cannot take down a whole short-form batch.
|
|
58
|
+
*/
|
|
59
|
+
async synthesizeBatch(scripts, options = {}) {
|
|
60
|
+
const successes = [];
|
|
61
|
+
const failures = [];
|
|
62
|
+
for (const { title, script } of scripts) {
|
|
63
|
+
try {
|
|
64
|
+
const audio = await this.synthesize(script, options);
|
|
65
|
+
successes.push({ title, audio });
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
const statusCode = err instanceof ExternalApiError ? err.statusCode : undefined;
|
|
69
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
70
|
+
const failure = { title, error: message };
|
|
71
|
+
if (statusCode !== undefined)
|
|
72
|
+
failure.statusCode = statusCode;
|
|
73
|
+
failures.push(failure);
|
|
74
|
+
logError(`[arden-tts] Failed to synthesize "${title}"`, {
|
|
75
|
+
statusCode,
|
|
76
|
+
error: message,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { successes, failures };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=arden-tts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arden-tts.js","sourceRoot":"","sources":["../../src/collectors/arden-tts.ts"],"names":[],"mappings":"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"}
|