@runcore-sh/runcore 0.4.0 → 0.5.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/dictionary.json +2 -2
- package/dist/activity/log.js +2 -2
- package/dist/activity/log.js.map +1 -1
- package/dist/agents/governed-spawn.d.ts.map +1 -1
- package/dist/cli.js +101 -11
- package/dist/cli.js.map +1 -1
- package/dist/extensions/cache.d.ts +57 -0
- package/dist/extensions/cache.d.ts.map +1 -0
- package/dist/extensions/cache.js +173 -0
- package/dist/extensions/cache.js.map +1 -0
- package/dist/extensions/client.d.ts +55 -0
- package/dist/extensions/client.d.ts.map +1 -0
- package/dist/extensions/client.js +120 -0
- package/dist/extensions/client.js.map +1 -0
- package/dist/extensions/index.d.ts +13 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +12 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +50 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +166 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/manifest.d.ts +38 -0
- package/dist/extensions/manifest.d.ts.map +1 -0
- package/dist/extensions/manifest.js +17 -0
- package/dist/extensions/manifest.js.map +1 -0
- package/dist/extensions/stubs.d.ts +27 -0
- package/dist/extensions/stubs.d.ts.map +1 -0
- package/dist/extensions/stubs.js +45 -0
- package/dist/extensions/stubs.js.map +1 -0
- package/dist/lib/audit.js +2 -2
- package/dist/lib/audit.js.map +1 -1
- package/dist/lib/brain-migrate.d.ts +21 -0
- package/dist/lib/brain-migrate.d.ts.map +1 -0
- package/dist/lib/brain-migrate.js +137 -0
- package/dist/lib/brain-migrate.js.map +1 -0
- package/dist/lib/paths.d.ts +27 -0
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +65 -0
- package/dist/lib/paths.js.map +1 -1
- package/dist/llm/call-log.d.ts +40 -0
- package/dist/llm/call-log.d.ts.map +1 -0
- package/dist/llm/call-log.js +35 -0
- package/dist/llm/call-log.js.map +1 -0
- package/dist/llm/complete.d.ts +6 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +27 -0
- package/dist/llm/complete.js.map +1 -1
- package/dist/mcp-server.js +118 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/memory/file-backed.d.ts +4 -0
- package/dist/memory/file-backed.d.ts.map +1 -1
- package/dist/memory/file-backed.js +4 -0
- package/dist/memory/file-backed.js.map +1 -1
- package/dist/memory/vector-index.d.ts +4 -12
- package/dist/memory/vector-index.d.ts.map +1 -1
- package/dist/memory/vector-index.js +11 -93
- package/dist/memory/vector-index.js.map +1 -1
- package/dist/search/brain-docs.d.ts +17 -7
- package/dist/search/brain-docs.d.ts.map +1 -1
- package/dist/search/brain-docs.js +170 -52
- package/dist/search/brain-docs.js.map +1 -1
- package/dist/search/brain-rag.d.ts +45 -0
- package/dist/search/brain-rag.d.ts.map +1 -0
- package/dist/search/brain-rag.js +275 -0
- package/dist/search/brain-rag.js.map +1 -0
- package/dist/search/chunker.d.ts +24 -0
- package/dist/search/chunker.d.ts.map +1 -0
- package/dist/search/chunker.js +95 -0
- package/dist/search/chunker.js.map +1 -0
- package/dist/search/embedder.d.ts +16 -0
- package/dist/search/embedder.d.ts.map +1 -0
- package/dist/search/embedder.js +108 -0
- package/dist/search/embedder.js.map +1 -0
- package/dist/search/file-watcher.d.ts +11 -0
- package/dist/search/file-watcher.d.ts.map +1 -0
- package/dist/search/file-watcher.js +86 -0
- package/dist/search/file-watcher.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +168 -20
- package/dist/server.js.map +1 -1
- package/dist/sessions/store.d.ts +9 -0
- package/dist/sessions/store.d.ts.map +1 -1
- package/dist/sessions/store.js.map +1 -1
- package/dist/settings.d.ts +26 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +78 -2
- package/dist/settings.js.map +1 -1
- package/dist/tracing/init.d.ts +1 -1
- package/dist/tracing/init.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -2
- package/dist/utils/logger.js.map +1 -1
- package/module-tiers.json +164 -0
- package/package.json +9 -13
- package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
- package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
- package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
- package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
- package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
- package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
- package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
- package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
- package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
- package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
- package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
- package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
- package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
- package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
- package/public/index.html +379 -59
- package/dist/agents/autonomous.js +0 -749
- package/dist/agents/autonomous.js.map +0 -1
- package/dist/agents/commit.js +0 -113
- package/dist/agents/commit.js.map +0 -1
- package/dist/agents/continue.js +0 -158
- package/dist/agents/continue.js.map +0 -1
- package/dist/agents/cooldown.js +0 -397
- package/dist/agents/cooldown.js.map +0 -1
- package/dist/agents/dedup-guard.js +0 -131
- package/dist/agents/dedup-guard.js.map +0 -1
- package/dist/agents/feed.js +0 -176
- package/dist/agents/feed.js.map +0 -1
- package/dist/agents/governance.js +0 -292
- package/dist/agents/governance.js.map +0 -1
- package/dist/agents/governed-spawn.js +0 -192
- package/dist/agents/governed-spawn.js.map +0 -1
- package/dist/agents/heartbeat.js +0 -324
- package/dist/agents/heartbeat.js.map +0 -1
- package/dist/agents/instance-manager.js +0 -850
- package/dist/agents/instance-manager.js.map +0 -1
- package/dist/agents/issue-reporter.js +0 -123
- package/dist/agents/issue-reporter.js.map +0 -1
- package/dist/agents/issues.js +0 -141
- package/dist/agents/issues.js.map +0 -1
- package/dist/agents/locks.js +0 -234
- package/dist/agents/locks.js.map +0 -1
- package/dist/agents/memory.js +0 -93
- package/dist/agents/memory.js.map +0 -1
- package/dist/agents/monitor.js +0 -235
- package/dist/agents/monitor.js.map +0 -1
- package/dist/agents/orchestration.js +0 -715
- package/dist/agents/orchestration.js.map +0 -1
- package/dist/agents/recover.js +0 -166
- package/dist/agents/recover.js.map +0 -1
- package/dist/agents/reflection.js +0 -199
- package/dist/agents/reflection.js.map +0 -1
- package/dist/agents/runtime/bus.js +0 -174
- package/dist/agents/runtime/bus.js.map +0 -1
- package/dist/agents/runtime/config.js +0 -101
- package/dist/agents/runtime/config.js.map +0 -1
- package/dist/agents/runtime/driver.js +0 -214
- package/dist/agents/runtime/driver.js.map +0 -1
- package/dist/agents/runtime/errors.js +0 -40
- package/dist/agents/runtime/errors.js.map +0 -1
- package/dist/agents/runtime/index.js +0 -54
- package/dist/agents/runtime/index.js.map +0 -1
- package/dist/agents/runtime/lifecycle.js +0 -116
- package/dist/agents/runtime/lifecycle.js.map +0 -1
- package/dist/agents/runtime/manager.js +0 -948
- package/dist/agents/runtime/manager.js.map +0 -1
- package/dist/agents/runtime/registry.js +0 -195
- package/dist/agents/runtime/registry.js.map +0 -1
- package/dist/agents/runtime/resources.js +0 -146
- package/dist/agents/runtime/resources.js.map +0 -1
- package/dist/agents/runtime/types.js +0 -24
- package/dist/agents/runtime/types.js.map +0 -1
- package/dist/agents/spawn-policy.js +0 -202
- package/dist/agents/spawn-policy.js.map +0 -1
- package/dist/agents/spawn.js +0 -970
- package/dist/agents/spawn.js.map +0 -1
- package/dist/agents/triage.js +0 -81
- package/dist/agents/triage.js.map +0 -1
- package/dist/agents/workflow.js +0 -543
- package/dist/agents/workflow.js.map +0 -1
- package/dist/avatar/client.js +0 -172
- package/dist/avatar/client.js.map +0 -1
- package/dist/avatar/sidecar.js +0 -125
- package/dist/avatar/sidecar.js.map +0 -1
- package/dist/browser/sessions.js +0 -122
- package/dist/browser/sessions.js.map +0 -1
- package/dist/capabilities/definitions/browser.js +0 -242
- package/dist/capabilities/definitions/browser.js.map +0 -1
- package/dist/channels/whatsapp.js +0 -200
- package/dist/channels/whatsapp.js.map +0 -1
- package/dist/credentials/store.js +0 -189
- package/dist/credentials/store.js.map +0 -1
- package/dist/files/deep-index.js +0 -337
- package/dist/files/deep-index.js.map +0 -1
- package/dist/files/extract.js +0 -33
- package/dist/files/extract.js.map +0 -1
- package/dist/files/gdrive.js +0 -246
- package/dist/files/gdrive.js.map +0 -1
- package/dist/github/client.js +0 -408
- package/dist/github/client.js.map +0 -1
- package/dist/github/commit-analysis.js +0 -276
- package/dist/github/commit-analysis.js.map +0 -1
- package/dist/github/contributor-stats.js +0 -119
- package/dist/github/contributor-stats.js.map +0 -1
- package/dist/github/issue-sla.js +0 -220
- package/dist/github/issue-sla.js.map +0 -1
- package/dist/github/issue-triage.js +0 -286
- package/dist/github/issue-triage.js.map +0 -1
- package/dist/github/pr-readiness.js +0 -197
- package/dist/github/pr-readiness.js.map +0 -1
- package/dist/github/pr-review.js +0 -410
- package/dist/github/pr-review.js.map +0 -1
- package/dist/github/release-notes.js +0 -227
- package/dist/github/release-notes.js.map +0 -1
- package/dist/github/repo-health.js +0 -303
- package/dist/github/repo-health.js.map +0 -1
- package/dist/github/retry.js +0 -117
- package/dist/github/retry.js.map +0 -1
- package/dist/github/types.js +0 -8
- package/dist/github/types.js.map +0 -1
- package/dist/github/webhooks.js +0 -153
- package/dist/github/webhooks.js.map +0 -1
- package/dist/google/auth.js +0 -325
- package/dist/google/auth.js.map +0 -1
- package/dist/google/calendar-timer.js +0 -91
- package/dist/google/calendar-timer.js.map +0 -1
- package/dist/google/calendar.js +0 -270
- package/dist/google/calendar.js.map +0 -1
- package/dist/google/docs.js +0 -309
- package/dist/google/docs.js.map +0 -1
- package/dist/google/gmail-send.js +0 -219
- package/dist/google/gmail-send.js.map +0 -1
- package/dist/google/gmail-timer.js +0 -223
- package/dist/google/gmail-timer.js.map +0 -1
- package/dist/google/gmail.js +0 -470
- package/dist/google/gmail.js.map +0 -1
- package/dist/google/plugin.js +0 -169
- package/dist/google/plugin.js.map +0 -1
- package/dist/google/tasks-timer.js +0 -107
- package/dist/google/tasks-timer.js.map +0 -1
- package/dist/google/tasks.js +0 -331
- package/dist/google/tasks.js.map +0 -1
- package/dist/google/temporal.js +0 -176
- package/dist/google/temporal.js.map +0 -1
- package/dist/integrations/gate.js +0 -100
- package/dist/integrations/gate.js.map +0 -1
- package/dist/integrations/github.js +0 -331
- package/dist/integrations/github.js.map +0 -1
- package/dist/integrations/google-tasks.js +0 -432
- package/dist/integrations/google-tasks.js.map +0 -1
- package/dist/mdns.js +0 -110
- package/dist/mdns.js.map +0 -1
- package/dist/notifications/channel.js +0 -83
- package/dist/notifications/channel.js.map +0 -1
- package/dist/notifications/channels/adapter.js +0 -55
- package/dist/notifications/channels/adapter.js.map +0 -1
- package/dist/notifications/channels/index.js +0 -6
- package/dist/notifications/channels/index.js.map +0 -1
- package/dist/notifications/channels/log.js +0 -29
- package/dist/notifications/channels/log.js.map +0 -1
- package/dist/notifications/email.js +0 -72
- package/dist/notifications/email.js.map +0 -1
- package/dist/notifications/engine.js +0 -198
- package/dist/notifications/engine.js.map +0 -1
- package/dist/notifications/index.js +0 -24
- package/dist/notifications/index.js.map +0 -1
- package/dist/notifications/phone.js +0 -48
- package/dist/notifications/phone.js.map +0 -1
- package/dist/notifications/sms.js +0 -65
- package/dist/notifications/sms.js.map +0 -1
- package/dist/notifications/types.js +0 -14
- package/dist/notifications/types.js.map +0 -1
- package/dist/notifications/webhook.js +0 -65
- package/dist/notifications/webhook.js.map +0 -1
- package/dist/resend/inbox.js +0 -199
- package/dist/resend/inbox.js.map +0 -1
- package/dist/resend/webhooks.js +0 -244
- package/dist/resend/webhooks.js.map +0 -1
- package/dist/search/browse.js +0 -225
- package/dist/search/browse.js.map +0 -1
- package/dist/search/perplexity.js +0 -41
- package/dist/search/perplexity.js.map +0 -1
- package/dist/slack/channels.js +0 -277
- package/dist/slack/channels.js.map +0 -1
- package/dist/slack/client.js +0 -468
- package/dist/slack/client.js.map +0 -1
- package/dist/slack/retry.js +0 -100
- package/dist/slack/retry.js.map +0 -1
- package/dist/slack/types.js +0 -52
- package/dist/slack/types.js.map +0 -1
- package/dist/slack/webhooks.js +0 -285
- package/dist/slack/webhooks.js.map +0 -1
- package/dist/stt/client.js +0 -66
- package/dist/stt/client.js.map +0 -1
- package/dist/stt/sidecar.js +0 -115
- package/dist/stt/sidecar.js.map +0 -1
- package/dist/tracing/bridge.js +0 -70
- package/dist/tracing/bridge.js.map +0 -1
- package/dist/tracing/correlation.js +0 -49
- package/dist/tracing/correlation.js.map +0 -1
- package/dist/tracing/index.js +0 -18
- package/dist/tracing/index.js.map +0 -1
- package/dist/tracing/init.js +0 -81
- package/dist/tracing/init.js.map +0 -1
- package/dist/tracing/instrument.js +0 -145
- package/dist/tracing/instrument.js.map +0 -1
- package/dist/tracing/middleware.js +0 -69
- package/dist/tracing/middleware.js.map +0 -1
- package/dist/tracing/tracer.js +0 -327
- package/dist/tracing/tracer.js.map +0 -1
- package/dist/tts/client.js +0 -48
- package/dist/tts/client.js.map +0 -1
- package/dist/tts/sidecar.js +0 -148
- package/dist/tts/sidecar.js.map +0 -1
- package/dist/twilio/call.js +0 -79
- package/dist/twilio/call.js.map +0 -1
- package/dist/vault/matcher.js +0 -197
- package/dist/vault/matcher.js.map +0 -1
- package/dist/vault/personal.js +0 -163
- package/dist/vault/personal.js.map +0 -1
- package/dist/vault/policy.js +0 -159
- package/dist/vault/policy.js.map +0 -1
- package/dist/vault/store.js +0 -122
- package/dist/vault/store.js.map +0 -1
- package/dist/vault/transfer.js +0 -188
- package/dist/vault/transfer.js.map +0 -1
- package/dist/volumes/index.js +0 -2
- package/dist/volumes/index.js.map +0 -1
- package/dist/volumes/manager.js +0 -462
- package/dist/volumes/manager.js.map +0 -1
- package/dist/volumes/types.js +0 -8
- package/dist/volumes/types.js.map +0 -1
- package/dist/webhooks/config.js +0 -214
- package/dist/webhooks/config.js.map +0 -1
- package/dist/webhooks/event-log.js +0 -132
- package/dist/webhooks/event-log.js.map +0 -1
- package/dist/webhooks/handler.js +0 -103
- package/dist/webhooks/handler.js.map +0 -1
- package/dist/webhooks/handlers.js +0 -231
- package/dist/webhooks/handlers.js.map +0 -1
- package/dist/webhooks/index.js +0 -33
- package/dist/webhooks/index.js.map +0 -1
- package/dist/webhooks/mount.js +0 -400
- package/dist/webhooks/mount.js.map +0 -1
- package/dist/webhooks/registry.js +0 -143
- package/dist/webhooks/registry.js.map +0 -1
- package/dist/webhooks/relay.js +0 -53
- package/dist/webhooks/relay.js.map +0 -1
- package/dist/webhooks/retry.js +0 -270
- package/dist/webhooks/retry.js.map +0 -1
- package/dist/webhooks/router.js +0 -290
- package/dist/webhooks/router.js.map +0 -1
- package/dist/webhooks/twilio.js +0 -129
- package/dist/webhooks/twilio.js.map +0 -1
- package/dist/webhooks/types.js +0 -8
- package/dist/webhooks/types.js.map +0 -1
- package/dist/webhooks/verify.js +0 -154
- package/dist/webhooks/verify.js.map +0 -1
package/dist/avatar/client.js
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Avatar client — communicates with the MuseTalk FastAPI sidecar.
|
|
3
|
-
* Handles photo preparation, video generation, and MP4 caching.
|
|
4
|
-
*/
|
|
5
|
-
import { createHash } from "node:crypto";
|
|
6
|
-
import { readFile, writeFile, readdir, stat, unlink, mkdir } from "node:fs/promises";
|
|
7
|
-
import { join } from "node:path";
|
|
8
|
-
import { getAvatarConfig } from "../settings.js";
|
|
9
|
-
import { createLogger } from "../utils/logger.js";
|
|
10
|
-
const log = createLogger("avatar-client");
|
|
11
|
-
const CACHE_DIR = join(process.cwd(), "public", "avatar", "cache");
|
|
12
|
-
const MAX_CACHE_ENTRIES = 50;
|
|
13
|
-
/** In-flight guard — only one generate request at a time. */
|
|
14
|
-
let generating = false;
|
|
15
|
-
function baseUrl() {
|
|
16
|
-
return `http://127.0.0.1:${getAvatarConfig().port}`;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Health probe — GET /health, 3-second timeout.
|
|
20
|
-
*/
|
|
21
|
-
export async function checkAvatarSidecar() {
|
|
22
|
-
try {
|
|
23
|
-
const res = await fetch(`${baseUrl()}/health`, {
|
|
24
|
-
signal: AbortSignal.timeout(3000),
|
|
25
|
-
});
|
|
26
|
-
if (!res.ok)
|
|
27
|
-
return false;
|
|
28
|
-
const data = await res.json();
|
|
29
|
-
return !!data.ready;
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Prepare a reference photo for lip-sync generation.
|
|
37
|
-
* POST /prepare with the photo file. Runs face detection + VAE encode (cached on sidecar side).
|
|
38
|
-
*/
|
|
39
|
-
export async function preparePhoto(photoPath) {
|
|
40
|
-
try {
|
|
41
|
-
const photoBytes = await readFile(photoPath);
|
|
42
|
-
const formData = new FormData();
|
|
43
|
-
formData.append("photo", new Blob([photoBytes]), "photo.png");
|
|
44
|
-
const res = await fetch(`${baseUrl()}/prepare`, {
|
|
45
|
-
method: "POST",
|
|
46
|
-
body: formData,
|
|
47
|
-
signal: AbortSignal.timeout(120_000),
|
|
48
|
-
});
|
|
49
|
-
if (!res.ok) {
|
|
50
|
-
const err = await res.json().catch(() => ({}));
|
|
51
|
-
log.warn(` Prepare failed: ${err.error ?? res.statusText}`);
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
58
|
-
log.warn(` Prepare error: ${msg}`);
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Generate a lip-synced MP4 from WAV audio.
|
|
64
|
-
* POST /generate with WAV bytes. Returns MP4 Buffer or null.
|
|
65
|
-
* Timeout: 120s (generation time ≈ audio duration).
|
|
66
|
-
*/
|
|
67
|
-
export async function generateVideo(wavBuffer) {
|
|
68
|
-
if (generating) {
|
|
69
|
-
log.warn(` Skipped — generation already in flight`);
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
generating = true;
|
|
73
|
-
try {
|
|
74
|
-
const formData = new FormData();
|
|
75
|
-
formData.append("audio", new Blob([wavBuffer]), "audio.wav");
|
|
76
|
-
const res = await fetch(`${baseUrl()}/generate`, {
|
|
77
|
-
method: "POST",
|
|
78
|
-
body: formData,
|
|
79
|
-
signal: AbortSignal.timeout(120_000),
|
|
80
|
-
});
|
|
81
|
-
if (!res.ok) {
|
|
82
|
-
const err = await res.json().catch(() => ({}));
|
|
83
|
-
log.warn(` Generate failed: ${err.error ?? res.statusText}`);
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
const arrayBuf = await res.arrayBuffer();
|
|
87
|
-
return Buffer.from(arrayBuf);
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
91
|
-
log.warn(` Generate error: ${msg}`);
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
finally {
|
|
95
|
-
generating = false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
/** Compute SHA-256 hash of a buffer (for cache keys). */
|
|
99
|
-
function hashBuffer(buf) {
|
|
100
|
-
return createHash("sha256").update(buf).digest("hex").slice(0, 16);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Check if a video is already cached for the given WAV audio.
|
|
104
|
-
* Returns the cache filename (hash.mp4) if found, null otherwise.
|
|
105
|
-
*/
|
|
106
|
-
export async function getCachedVideo(wavBuffer) {
|
|
107
|
-
const hash = hashBuffer(wavBuffer);
|
|
108
|
-
const cachePath = join(CACHE_DIR, `${hash}.mp4`);
|
|
109
|
-
try {
|
|
110
|
-
await stat(cachePath);
|
|
111
|
-
return `${hash}.mp4`;
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
return null;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Cache an MP4 video, keyed by WAV audio hash.
|
|
119
|
-
* Returns the cache filename (hash.mp4).
|
|
120
|
-
*/
|
|
121
|
-
export async function cacheVideo(mp4Buffer, wavBuffer) {
|
|
122
|
-
await mkdir(CACHE_DIR, { recursive: true });
|
|
123
|
-
const hash = hashBuffer(wavBuffer);
|
|
124
|
-
const filename = `${hash}.mp4`;
|
|
125
|
-
await writeFile(join(CACHE_DIR, filename), mp4Buffer);
|
|
126
|
-
await pruneCache();
|
|
127
|
-
return filename;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Prune the cache directory to keep at most MAX_CACHE_ENTRIES files.
|
|
131
|
-
* Removes oldest files by modification time.
|
|
132
|
-
*/
|
|
133
|
-
async function pruneCache() {
|
|
134
|
-
try {
|
|
135
|
-
const files = await readdir(CACHE_DIR);
|
|
136
|
-
const mp4Files = files.filter((f) => f.endsWith(".mp4"));
|
|
137
|
-
if (mp4Files.length <= MAX_CACHE_ENTRIES)
|
|
138
|
-
return;
|
|
139
|
-
// Get mtimes for sorting
|
|
140
|
-
const withStats = await Promise.all(mp4Files.map(async (f) => {
|
|
141
|
-
const s = await stat(join(CACHE_DIR, f));
|
|
142
|
-
return { name: f, mtime: s.mtimeMs };
|
|
143
|
-
}));
|
|
144
|
-
// Sort oldest first
|
|
145
|
-
withStats.sort((a, b) => a.mtime - b.mtime);
|
|
146
|
-
// Remove oldest entries beyond the limit
|
|
147
|
-
const toRemove = withStats.slice(0, withStats.length - MAX_CACHE_ENTRIES);
|
|
148
|
-
for (const f of toRemove) {
|
|
149
|
-
await unlink(join(CACHE_DIR, f.name)).catch(() => { });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
// Cache dir may not exist yet — that's fine
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Clear all cached videos. Used when the reference photo changes.
|
|
158
|
-
*/
|
|
159
|
-
export async function clearVideoCache() {
|
|
160
|
-
try {
|
|
161
|
-
const files = await readdir(CACHE_DIR);
|
|
162
|
-
for (const f of files) {
|
|
163
|
-
if (f.endsWith(".mp4")) {
|
|
164
|
-
await unlink(join(CACHE_DIR, f)).catch(() => { });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
// Cache dir may not exist yet
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
//# sourceMappingURL=client.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/avatar/client.ts"],"names":[],"mappings":"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"}
|
package/dist/avatar/sidecar.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Avatar sidecar lifecycle manager.
|
|
3
|
-
* Spawns the MuseTalk FastAPI server and monitors its health.
|
|
4
|
-
* Graceful degradation — if MuseTalk isn't installed, Core falls back to TalkingHead/placeholder.
|
|
5
|
-
*/
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
7
|
-
import { access } from "node:fs/promises";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { getAvatarConfig } from "../settings.js";
|
|
10
|
-
import { checkAvatarSidecar } from "./client.js";
|
|
11
|
-
import { createLogger } from "../utils/logger.js";
|
|
12
|
-
const log = createLogger("avatar-sidecar");
|
|
13
|
-
const HEALTH_POLL_INTERVAL = 1000; // ms
|
|
14
|
-
const HEALTH_POLL_TIMEOUT = 60_000; // ms — model loading is slow on first run
|
|
15
|
-
let sidecarProcess = null;
|
|
16
|
-
let available = false;
|
|
17
|
-
function pythonCommand() {
|
|
18
|
-
// Use the MuseTalk venv Python if it exists (has all the right deps)
|
|
19
|
-
const config = getAvatarConfig();
|
|
20
|
-
if (config.musetalkPath) {
|
|
21
|
-
const venvPython = process.platform === "win32"
|
|
22
|
-
? join(config.musetalkPath, ".venv", "Scripts", "python.exe")
|
|
23
|
-
: join(config.musetalkPath, ".venv", "bin", "python");
|
|
24
|
-
return venvPython;
|
|
25
|
-
}
|
|
26
|
-
return process.platform === "win32" ? "python" : "python3";
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Start the MuseTalk avatar sidecar.
|
|
30
|
-
* Verifies the MuseTalk path exists, spawns the FastAPI server, polls for health.
|
|
31
|
-
* Returns true if sidecar is available after startup.
|
|
32
|
-
*/
|
|
33
|
-
export async function startAvatarSidecar() {
|
|
34
|
-
const config = getAvatarConfig();
|
|
35
|
-
if (!config.enabled) {
|
|
36
|
-
available = false;
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
if (!config.musetalkPath) {
|
|
40
|
-
log.info(" No musetalkPath configured — avatar disabled");
|
|
41
|
-
available = false;
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
// Check if already running externally
|
|
45
|
-
if (await checkAvatarSidecar()) {
|
|
46
|
-
available = true;
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
// Verify MuseTalk path exists
|
|
50
|
-
try {
|
|
51
|
-
await access(config.musetalkPath);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
log.info(` MuseTalk path not found: ${config.musetalkPath}`);
|
|
55
|
-
available = false;
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const python = pythonCommand();
|
|
59
|
-
const port = String(config.port);
|
|
60
|
-
const serverScript = join(process.cwd(), "sidecar", "avatar", "server.py");
|
|
61
|
-
try {
|
|
62
|
-
sidecarProcess = spawn(python, [serverScript, "--port", port, "--musetalk-path", config.musetalkPath], {
|
|
63
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
64
|
-
detached: false,
|
|
65
|
-
env: { ...process.env, PYTHONUTF8: "1", PYTHONIOENCODING: "utf-8" },
|
|
66
|
-
});
|
|
67
|
-
sidecarProcess.stdout?.on("data", (data) => {
|
|
68
|
-
const msg = data.toString().trim();
|
|
69
|
-
if (msg)
|
|
70
|
-
log.info(` ${msg}`);
|
|
71
|
-
});
|
|
72
|
-
sidecarProcess.stderr?.on("data", (data) => {
|
|
73
|
-
const msg = data.toString().trim();
|
|
74
|
-
if (msg)
|
|
75
|
-
log.info(` ${msg}`);
|
|
76
|
-
});
|
|
77
|
-
sidecarProcess.on("error", (err) => {
|
|
78
|
-
log.info(` Failed to start: ${err.message}`);
|
|
79
|
-
available = false;
|
|
80
|
-
sidecarProcess = null;
|
|
81
|
-
});
|
|
82
|
-
sidecarProcess.on("exit", (code) => {
|
|
83
|
-
if (code !== null && code !== 0) {
|
|
84
|
-
log.info(` Exited with code ${code}`);
|
|
85
|
-
}
|
|
86
|
-
available = false;
|
|
87
|
-
sidecarProcess = null;
|
|
88
|
-
});
|
|
89
|
-
// Poll until ready or timeout
|
|
90
|
-
const start = Date.now();
|
|
91
|
-
while (Date.now() - start < HEALTH_POLL_TIMEOUT) {
|
|
92
|
-
if (await checkAvatarSidecar()) {
|
|
93
|
-
available = true;
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
await new Promise((r) => setTimeout(r, HEALTH_POLL_INTERVAL));
|
|
97
|
-
}
|
|
98
|
-
log.info(" Timed out waiting for health check");
|
|
99
|
-
stopAvatarSidecar();
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
104
|
-
log.info(` Spawn failed: ${msg}`);
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
/** Check if the avatar sidecar is currently available. */
|
|
109
|
-
export function isAvatarAvailable() {
|
|
110
|
-
return available;
|
|
111
|
-
}
|
|
112
|
-
/** Stop the avatar sidecar process. */
|
|
113
|
-
export function stopAvatarSidecar() {
|
|
114
|
-
if (sidecarProcess) {
|
|
115
|
-
try {
|
|
116
|
-
sidecarProcess.kill();
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
// Already dead
|
|
120
|
-
}
|
|
121
|
-
sidecarProcess = null;
|
|
122
|
-
}
|
|
123
|
-
available = false;
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=sidecar.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar.js","sourceRoot":"","sources":["../../src/avatar/sidecar.ts"],"names":[],"mappings":"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"}
|
package/dist/browser/sessions.js
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser session manager — persist and reuse Playwright storageState per domain.
|
|
3
|
-
*
|
|
4
|
-
* Sessions are stored as AES-256-GCM encrypted JSON in brain/browser/sessions/.
|
|
5
|
-
* Each session is keyed by domain with a 7-day expiry.
|
|
6
|
-
*/
|
|
7
|
-
import { readFile, writeFile, readdir, unlink, mkdir } from "node:fs/promises";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
10
|
-
import { createLogger } from "../utils/logger.js";
|
|
11
|
-
import { getEncryptionKey } from "../lib/key-store.js";
|
|
12
|
-
import { BRAIN_DIR } from "../lib/paths.js";
|
|
13
|
-
const log = createLogger("browser-sessions");
|
|
14
|
-
const SESSIONS_DIR = join(BRAIN_DIR, "browser", "sessions");
|
|
15
|
-
const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
|
|
16
|
-
// ── Crypto helpers ───────────────────────────────────────────────────────────
|
|
17
|
-
function deriveSessionKey() {
|
|
18
|
-
const masterKey = getEncryptionKey();
|
|
19
|
-
if (!masterKey)
|
|
20
|
-
throw new Error("No encryption key available — not authenticated");
|
|
21
|
-
// Use first 32 bytes of the master key (AES-256)
|
|
22
|
-
return masterKey.subarray(0, 32);
|
|
23
|
-
}
|
|
24
|
-
function encrypt(plaintext) {
|
|
25
|
-
const key = deriveSessionKey();
|
|
26
|
-
const iv = randomBytes(16);
|
|
27
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
28
|
-
const encrypted = Buffer.concat([cipher.update(plaintext, "utf-8"), cipher.final()]);
|
|
29
|
-
const tag = cipher.getAuthTag();
|
|
30
|
-
return { iv: iv.toString("hex"), tag: tag.toString("hex"), data: encrypted.toString("hex") };
|
|
31
|
-
}
|
|
32
|
-
function decrypt(iv, tag, data) {
|
|
33
|
-
const key = deriveSessionKey();
|
|
34
|
-
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "hex"));
|
|
35
|
-
decipher.setAuthTag(Buffer.from(tag, "hex"));
|
|
36
|
-
return decipher.update(data, "hex", "utf-8") + decipher.final("utf-8");
|
|
37
|
-
}
|
|
38
|
-
// ── File helpers ─────────────────────────────────────────────────────────────
|
|
39
|
-
function sessionPath(domain) {
|
|
40
|
-
// Sanitize domain for filesystem: replace dots/colons with underscores
|
|
41
|
-
const safe = domain.replace(/[^a-zA-Z0-9-]/g, "_");
|
|
42
|
-
return join(SESSIONS_DIR, `${safe}.session.json`);
|
|
43
|
-
}
|
|
44
|
-
async function ensureDir() {
|
|
45
|
-
await mkdir(SESSIONS_DIR, { recursive: true });
|
|
46
|
-
}
|
|
47
|
-
// ── Public API ───────────────────────────────────────────────────────────────
|
|
48
|
-
/**
|
|
49
|
-
* Save a Playwright storageState (cookies, localStorage, etc.) for a domain.
|
|
50
|
-
*/
|
|
51
|
-
export async function saveSession(domain, storageState) {
|
|
52
|
-
await ensureDir();
|
|
53
|
-
const plaintext = JSON.stringify(storageState);
|
|
54
|
-
const { iv, tag, data } = encrypt(plaintext);
|
|
55
|
-
const now = new Date();
|
|
56
|
-
const envelope = {
|
|
57
|
-
domain,
|
|
58
|
-
createdAt: now.toISOString(),
|
|
59
|
-
expiresAt: new Date(now.getTime() + SESSION_TTL_MS).toISOString(),
|
|
60
|
-
iv,
|
|
61
|
-
tag,
|
|
62
|
-
data,
|
|
63
|
-
};
|
|
64
|
-
await writeFile(sessionPath(domain), JSON.stringify(envelope, null, 2), "utf-8");
|
|
65
|
-
log.info(`Saved browser session for ${domain}`);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Load a stored session for a domain, or null if missing/expired/corrupted.
|
|
69
|
-
*/
|
|
70
|
-
export async function loadSession(domain) {
|
|
71
|
-
try {
|
|
72
|
-
const raw = await readFile(sessionPath(domain), "utf-8");
|
|
73
|
-
const envelope = JSON.parse(raw);
|
|
74
|
-
// Check expiry
|
|
75
|
-
if (new Date(envelope.expiresAt).getTime() < Date.now()) {
|
|
76
|
-
log.info(`Session expired for ${domain} — removing`);
|
|
77
|
-
await unlink(sessionPath(domain)).catch(() => { });
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
const plaintext = decrypt(envelope.iv, envelope.tag, envelope.data);
|
|
81
|
-
return JSON.parse(plaintext);
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Delete a stored session for a domain.
|
|
89
|
-
*/
|
|
90
|
-
export async function deleteSession(domain) {
|
|
91
|
-
await unlink(sessionPath(domain)).catch(() => { });
|
|
92
|
-
log.info(`Deleted browser session for ${domain}`);
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Purge all expired sessions from disk.
|
|
96
|
-
*/
|
|
97
|
-
export async function purgeExpiredSessions() {
|
|
98
|
-
await ensureDir();
|
|
99
|
-
let purged = 0;
|
|
100
|
-
const files = await readdir(SESSIONS_DIR);
|
|
101
|
-
for (const file of files) {
|
|
102
|
-
if (!file.endsWith(".session.json"))
|
|
103
|
-
continue;
|
|
104
|
-
try {
|
|
105
|
-
const raw = await readFile(join(SESSIONS_DIR, file), "utf-8");
|
|
106
|
-
const envelope = JSON.parse(raw);
|
|
107
|
-
if (new Date(envelope.expiresAt).getTime() < Date.now()) {
|
|
108
|
-
await unlink(join(SESSIONS_DIR, file));
|
|
109
|
-
purged++;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
// Corrupted file — remove it
|
|
114
|
-
await unlink(join(SESSIONS_DIR, file)).catch(() => { });
|
|
115
|
-
purged++;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (purged > 0)
|
|
119
|
-
log.info(`Purged ${purged} expired browser session(s)`);
|
|
120
|
-
return purged;
|
|
121
|
-
}
|
|
122
|
-
//# sourceMappingURL=sessions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/browser/sessions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,GAAG,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;AAE7C,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAC5D,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,SAAS;AAczD,gFAAgF;AAEhF,SAAS,gBAAgB;IACvB,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;IACrC,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACnF,iDAAiD;IACjD,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,OAAO,CAAC,SAAiB;IAChC,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrF,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAChC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC/F,CAAC;AAED,SAAS,OAAO,CAAC,EAAU,EAAE,GAAW,EAAE,IAAY;IACpD,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9E,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACzE,CAAC;AAED,gFAAgF;AAEhF,SAAS,WAAW,CAAC,MAAc;IACjC,uEAAuE;IACvE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,IAAI,CAAC,YAAY,EAAE,GAAG,IAAI,eAAe,CAAC,CAAC;AACpD,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,gFAAgF;AAEhF;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,YAAqB;IACrE,MAAM,SAAS,EAAE,CAAC;IAClB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAoB;QAChC,MAAM;QACN,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;QAC5B,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,cAAc,CAAC,CAAC,WAAW,EAAE;QACjE,EAAE;QACF,GAAG;QACH,IAAI;KACL,CAAC;IACF,MAAM,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjF,GAAG,CAAC,IAAI,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAc;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAoB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElD,eAAe;QACf,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACxD,GAAG,CAAC,IAAI,CAAC,uBAAuB,MAAM,aAAa,CAAC,CAAC;YACrD,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc;IAChD,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAClD,GAAG,CAAC,IAAI,CAAC,+BAA+B,MAAM,EAAE,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,SAAS,EAAE,CAAC;IAClB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;YAAE,SAAS;QAC9C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;YAC9D,MAAM,QAAQ,GAAoB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClD,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBACxD,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;gBACvC,MAAM,EAAE,CAAC;YACX,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;YAC7B,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACvD,MAAM,EAAE,CAAC;QACX,CAAC;IACH,CAAC;IACD,IAAI,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,UAAU,MAAM,6BAA6B,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|