@memberjunction/ai-agents 5.43.0 → 5.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +8 -0
  2. package/dist/DuplicateReasoningAgentProvider.d.ts +35 -0
  3. package/dist/DuplicateReasoningAgentProvider.d.ts.map +1 -0
  4. package/dist/DuplicateReasoningAgentProvider.js +95 -0
  5. package/dist/DuplicateReasoningAgentProvider.js.map +1 -0
  6. package/dist/MJAIAgentRequestEntityServer.d.ts +7 -0
  7. package/dist/MJAIAgentRequestEntityServer.d.ts.map +1 -1
  8. package/dist/MJAIAgentRequestEntityServer.js +28 -1
  9. package/dist/MJAIAgentRequestEntityServer.js.map +1 -1
  10. package/dist/SkillImportExportService.d.ts +63 -0
  11. package/dist/SkillImportExportService.d.ts.map +1 -0
  12. package/dist/SkillImportExportService.js +148 -0
  13. package/dist/SkillImportExportService.js.map +1 -0
  14. package/dist/SkillMarkdownConverter.d.ts +82 -0
  15. package/dist/SkillMarkdownConverter.d.ts.map +1 -0
  16. package/dist/SkillMarkdownConverter.js +145 -0
  17. package/dist/SkillMarkdownConverter.js.map +1 -0
  18. package/dist/agent-types/loop-agent-response-type.d.ts +17 -2
  19. package/dist/agent-types/loop-agent-response-type.d.ts.map +1 -1
  20. package/dist/agent-types/loop-agent-response-type.js.map +1 -1
  21. package/dist/agent-types/loop-agent-type.d.ts.map +1 -1
  22. package/dist/agent-types/loop-agent-type.js +33 -1
  23. package/dist/agent-types/loop-agent-type.js.map +1 -1
  24. package/dist/base-agent.d.ts +373 -12
  25. package/dist/base-agent.d.ts.map +1 -1
  26. package/dist/base-agent.js +1007 -78
  27. package/dist/base-agent.js.map +1 -1
  28. package/dist/index.d.ts +11 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +11 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/memory-manager-agent.d.ts +39 -0
  33. package/dist/memory-manager-agent.d.ts.map +1 -1
  34. package/dist/memory-manager-agent.js +118 -5
  35. package/dist/memory-manager-agent.js.map +1 -1
  36. package/dist/operations/AISkillMarkdownOperations.d.ts +11 -0
  37. package/dist/operations/AISkillMarkdownOperations.d.ts.map +1 -0
  38. package/dist/operations/AISkillMarkdownOperations.js +57 -0
  39. package/dist/operations/AISkillMarkdownOperations.js.map +1 -0
  40. package/dist/prompt-component-resolver.d.ts +73 -0
  41. package/dist/prompt-component-resolver.d.ts.map +1 -0
  42. package/dist/prompt-component-resolver.js +166 -0
  43. package/dist/prompt-component-resolver.js.map +1 -0
  44. package/dist/realtime/agent-media-library.d.ts +65 -0
  45. package/dist/realtime/agent-media-library.d.ts.map +1 -0
  46. package/dist/realtime/agent-media-library.js +160 -0
  47. package/dist/realtime/agent-media-library.js.map +1 -0
  48. package/dist/realtime/client-context-channel-server.d.ts +59 -0
  49. package/dist/realtime/client-context-channel-server.d.ts.map +1 -0
  50. package/dist/realtime/client-context-channel-server.js +78 -0
  51. package/dist/realtime/client-context-channel-server.js.map +1 -0
  52. package/dist/realtime/media-channel-server.d.ts +73 -0
  53. package/dist/realtime/media-channel-server.d.ts.map +1 -0
  54. package/dist/realtime/media-channel-server.js +145 -0
  55. package/dist/realtime/media-channel-server.js.map +1 -0
  56. package/dist/realtime/realtime-channel-server-data-context.d.ts +42 -0
  57. package/dist/realtime/realtime-channel-server-data-context.d.ts.map +1 -0
  58. package/dist/realtime/realtime-channel-server-data-context.js +29 -0
  59. package/dist/realtime/realtime-channel-server-data-context.js.map +1 -0
  60. package/dist/realtime/realtime-channel-server-host.d.ts.map +1 -1
  61. package/dist/realtime/realtime-channel-server-host.js +8 -2
  62. package/dist/realtime/realtime-channel-server-host.js.map +1 -1
  63. package/dist/realtime/realtime-client-session-service.d.ts +85 -5
  64. package/dist/realtime/realtime-client-session-service.d.ts.map +1 -1
  65. package/dist/realtime/realtime-client-session-service.js +234 -25
  66. package/dist/realtime/realtime-client-session-service.js.map +1 -1
  67. package/dist/realtime/realtime-coagent-config.d.ts +82 -3
  68. package/dist/realtime/realtime-coagent-config.d.ts.map +1 -1
  69. package/dist/realtime/realtime-coagent-config.js +147 -6
  70. package/dist/realtime/realtime-coagent-config.js.map +1 -1
  71. package/dist/realtime/realtime-recording-capture.d.ts +125 -0
  72. package/dist/realtime/realtime-recording-capture.d.ts.map +1 -0
  73. package/dist/realtime/realtime-recording-capture.js +317 -0
  74. package/dist/realtime/realtime-recording-capture.js.map +1 -0
  75. package/dist/realtime/realtime-recording-store.d.ts +105 -0
  76. package/dist/realtime/realtime-recording-store.d.ts.map +1 -0
  77. package/dist/realtime/realtime-recording-store.js +216 -0
  78. package/dist/realtime/realtime-recording-store.js.map +1 -0
  79. package/dist/realtime/realtime-session-runner.d.ts +33 -2
  80. package/dist/realtime/realtime-session-runner.d.ts.map +1 -1
  81. package/dist/realtime/realtime-session-runner.js +45 -2
  82. package/dist/realtime/realtime-session-runner.js.map +1 -1
  83. package/dist/realtime/realtime-tool-broker.d.ts +41 -3
  84. package/dist/realtime/realtime-tool-broker.d.ts.map +1 -1
  85. package/dist/realtime/realtime-tool-broker.js +67 -3
  86. package/dist/realtime/realtime-tool-broker.js.map +1 -1
  87. package/package.json +18 -17
@@ -0,0 +1,73 @@
1
+ import { MJScopedPromptPartEntity } from "@memberjunction/core-entities";
2
+ import { ChatMessage, ChatMessageRole } from "@memberjunction/ai";
3
+ import { SecondaryScopeValue } from "@memberjunction/ai-core-plus";
4
+ /**
5
+ * The scope a prompt-component resolution runs in. Mirrors the polymorphic scope the agent
6
+ * runtime already carries for memory (PrimaryScopeEntity/Record + SecondaryScopes).
7
+ */
8
+ export interface PromptComponentScope {
9
+ primaryScopeEntityId?: string;
10
+ primaryScopeRecordId?: string;
11
+ secondaryScopes?: Record<string, SecondaryScopeValue>;
12
+ }
13
+ /**
14
+ * PromptComponentResolver — decides which `MJ: Scoped Prompt Parts` are included for a given
15
+ * prompt under a given scope, and assembles them into a role-faithful `ChatMessage[]`.
16
+ *
17
+ * **Pluggable (ClassFactory) + metadata-driven (template method).**
18
+ * The public {@link Resolve} / {@link AssembleMessages} fix the orchestration; the protected hooks
19
+ * ({@link getCandidates}, {@link isInScope}, {@link score}, {@link selectIncluded}, {@link order})
20
+ * are the extension points. MJ core obtains the resolver via
21
+ * `MJGlobal.Instance.ClassFactory.CreateInstance(PromptComponentResolver)`, which returns this base
22
+ * by default (no registration ⇒ base instance) or the highest-priority registered subclass. So any
23
+ * downstream consumer can plug in custom inclusion logic with **no core change**:
24
+ *
25
+ * ```ts
26
+ * @RegisterClass(PromptComponentResolver) // priority auto-increments by import order
27
+ * export class MyResolver extends PromptComponentResolver {
28
+ * protected override score(p, scope) { ... } // custom ranking
29
+ * protected override selectIncluded(parts, scope) { ... } // custom merge rules
30
+ * }
31
+ * ```
32
+ *
33
+ * Base (metadata-driven) defaults:
34
+ * - **Additive across part `Name`s** — distinct names all survive.
35
+ * - **Within a `Name`**, the row's `MergeBehavior` decides: `'Override'` (default) ⇒ the
36
+ * most-specific part wins (replace), `'Append'` ⇒ all in-scope same-named parts are included.
37
+ * - Specificity (the override ranking): SecondaryScopes match (+4) > PrimaryScopeRecord (+2) >
38
+ * Global (+1), tie-broken by `Priority`.
39
+ * - Final order: `Sort` ASC, then `Priority` DESC.
40
+ * - Roles are preserved (System/User/Assistant) so the assembled messages drive the model directly.
41
+ */
42
+ export declare class PromptComponentResolver {
43
+ /** Resolve the included, ordered parts for `promptID` under `scope`. */
44
+ Resolve(promptID: string, scope: PromptComponentScope): MJScopedPromptPartEntity[];
45
+ /** Assemble resolved parts into role-faithful messages, coalescing adjacent same-role. */
46
+ AssembleMessages(parts: MJScopedPromptPartEntity[]): ChatMessage[];
47
+ /** Candidate parts for a prompt: same PromptID + resolvable Status. Override to widen/narrow. */
48
+ protected getCandidates(promptID: string): MJScopedPromptPartEntity[];
49
+ /** Is this part compatible with the run scope? (cascading: a part may only require dims the run has) */
50
+ protected isInScope(p: MJScopedPromptPartEntity, scope: PromptComponentScope): boolean;
51
+ /** Specificity score: SecondaryScopes match (+4) > PrimaryScopeRecord (+2) > Global (+1). */
52
+ protected score(p: MJScopedPromptPartEntity): number;
53
+ /**
54
+ * From in-scope candidates, decide inclusion per `Name`:
55
+ * - rank a Name's parts by specificity (score) then `Priority`;
56
+ * - the top part's `MergeBehavior` governs the group — `'Override'` keeps only the top,
57
+ * `'Append'` keeps all (additive within the Name).
58
+ * Distinct names always coexist (additive across names).
59
+ */
60
+ protected selectIncluded(candidates: MJScopedPromptPartEntity[], _scope: PromptComponentScope): MJScopedPromptPartEntity[];
61
+ /** Final assembly order: Sort ASC, then Priority DESC, then Name. */
62
+ protected order(parts: MJScopedPromptPartEntity[]): MJScopedPromptPartEntity[];
63
+ protected parseScopes(raw: string | null): Record<string, unknown>;
64
+ protected coerceRole(raw: string | null): ChatMessageRole;
65
+ }
66
+ /**
67
+ * Convenience used by the agent runtime: obtain the (possibly overridden) resolver via the
68
+ * class factory, resolve + assemble for `promptID`/`scope`, and unshift the role-faithful messages
69
+ * onto the front of `conversationMessages` (mirroring how memory/RAG inject). No-op when nothing
70
+ * resolves. Returns the included parts (for observability).
71
+ */
72
+ export declare function InjectScopedPromptParts(resolver: PromptComponentResolver, promptID: string, scope: PromptComponentScope, conversationMessages: ChatMessage[]): MJScopedPromptPartEntity[];
73
+ //# sourceMappingURL=prompt-component-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-component-resolver.d.ts","sourceRoot":"","sources":["../src/prompt-component-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;CACzD;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,uBAAuB;IAGhC,wEAAwE;IACjE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,oBAAoB,GAAG,wBAAwB,EAAE;IAMzF,0FAA0F;IACnF,gBAAgB,CAAC,KAAK,EAAE,wBAAwB,EAAE,GAAG,WAAW,EAAE;IAkBzE,iGAAiG;IACjG,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,wBAAwB,EAAE;IAMrE,wGAAwG;IACxG,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,wBAAwB,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO;IA0BtF,6FAA6F;IAC7F,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,wBAAwB,GAAG,MAAM;IAOpD;;;;;;OAMG;IACH,SAAS,CAAC,cAAc,CACpB,UAAU,EAAE,wBAAwB,EAAE,EACtC,MAAM,EAAE,oBAAoB,GAC7B,wBAAwB,EAAE;IAmB7B,qEAAqE;IACrE,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,wBAAwB,EAAE,GAAG,wBAAwB,EAAE;IAQ9E,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUlE,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,eAAe;CAM5D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACnC,QAAQ,EAAE,uBAAuB,EACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,oBAAoB,EAC3B,oBAAoB,EAAE,WAAW,EAAE,GACpC,wBAAwB,EAAE,CAW5B"}
@@ -0,0 +1,166 @@
1
+ import { LogStatus } from "@memberjunction/core";
2
+ import { UUIDsEqual } from "@memberjunction/global";
3
+ import { AIEngine } from "@memberjunction/aiengine";
4
+ /** Statuses eligible for resolution. Archived parts are excluded. */
5
+ const RESOLVABLE_STATUSES = new Set(["Active", "Provisional"]);
6
+ /**
7
+ * PromptComponentResolver — decides which `MJ: Scoped Prompt Parts` are included for a given
8
+ * prompt under a given scope, and assembles them into a role-faithful `ChatMessage[]`.
9
+ *
10
+ * **Pluggable (ClassFactory) + metadata-driven (template method).**
11
+ * The public {@link Resolve} / {@link AssembleMessages} fix the orchestration; the protected hooks
12
+ * ({@link getCandidates}, {@link isInScope}, {@link score}, {@link selectIncluded}, {@link order})
13
+ * are the extension points. MJ core obtains the resolver via
14
+ * `MJGlobal.Instance.ClassFactory.CreateInstance(PromptComponentResolver)`, which returns this base
15
+ * by default (no registration ⇒ base instance) or the highest-priority registered subclass. So any
16
+ * downstream consumer can plug in custom inclusion logic with **no core change**:
17
+ *
18
+ * ```ts
19
+ * @RegisterClass(PromptComponentResolver) // priority auto-increments by import order
20
+ * export class MyResolver extends PromptComponentResolver {
21
+ * protected override score(p, scope) { ... } // custom ranking
22
+ * protected override selectIncluded(parts, scope) { ... } // custom merge rules
23
+ * }
24
+ * ```
25
+ *
26
+ * Base (metadata-driven) defaults:
27
+ * - **Additive across part `Name`s** — distinct names all survive.
28
+ * - **Within a `Name`**, the row's `MergeBehavior` decides: `'Override'` (default) ⇒ the
29
+ * most-specific part wins (replace), `'Append'` ⇒ all in-scope same-named parts are included.
30
+ * - Specificity (the override ranking): SecondaryScopes match (+4) > PrimaryScopeRecord (+2) >
31
+ * Global (+1), tie-broken by `Priority`.
32
+ * - Final order: `Sort` ASC, then `Priority` DESC.
33
+ * - Roles are preserved (System/User/Assistant) so the assembled messages drive the model directly.
34
+ */
35
+ export class PromptComponentResolver {
36
+ // ── Public template methods ────────────────────────────────────────────────
37
+ /** Resolve the included, ordered parts for `promptID` under `scope`. */
38
+ Resolve(promptID, scope) {
39
+ const inScope = this.getCandidates(promptID).filter((p) => this.isInScope(p, scope));
40
+ const included = this.selectIncluded(inScope, scope);
41
+ return this.order(included);
42
+ }
43
+ /** Assemble resolved parts into role-faithful messages, coalescing adjacent same-role. */
44
+ AssembleMessages(parts) {
45
+ const out = [];
46
+ for (const p of parts) {
47
+ const content = (p.Text ?? "").trim();
48
+ if (!content)
49
+ continue;
50
+ const role = this.coerceRole(p.Role);
51
+ const last = out[out.length - 1];
52
+ if (last && last.role === role) {
53
+ last.content = `${last.content}\n\n${content}`;
54
+ }
55
+ else {
56
+ out.push({ role, content });
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+ // ── Protected hooks (override points) ──────────────────────────────────────
62
+ /** Candidate parts for a prompt: same PromptID + resolvable Status. Override to widen/narrow. */
63
+ getCandidates(promptID) {
64
+ return AIEngine.Instance.ScopedPromptParts.filter((p) => UUIDsEqual(p.PromptID, promptID) && RESOLVABLE_STATUSES.has(p.Status));
65
+ }
66
+ /** Is this part compatible with the run scope? (cascading: a part may only require dims the run has) */
67
+ isInScope(p, scope) {
68
+ if (p.PrimaryScopeRecordID) {
69
+ if (!scope.primaryScopeRecordId ||
70
+ p.PrimaryScopeRecordID.toLowerCase() !== scope.primaryScopeRecordId.toLowerCase()) {
71
+ return false;
72
+ }
73
+ if (p.PrimaryScopeEntityID &&
74
+ scope.primaryScopeEntityId &&
75
+ !UUIDsEqual(p.PrimaryScopeEntityID, scope.primaryScopeEntityId)) {
76
+ return false;
77
+ }
78
+ }
79
+ const partScopes = this.parseScopes(p.SecondaryScopes);
80
+ for (const key of Object.keys(partScopes)) {
81
+ const runValue = scope.secondaryScopes?.[key];
82
+ if (runValue === undefined || String(runValue) !== String(partScopes[key])) {
83
+ return false;
84
+ }
85
+ }
86
+ return true;
87
+ }
88
+ /** Specificity score: SecondaryScopes match (+4) > PrimaryScopeRecord (+2) > Global (+1). */
89
+ score(p) {
90
+ let s = 1;
91
+ if (p.PrimaryScopeRecordID)
92
+ s += 2;
93
+ if (Object.keys(this.parseScopes(p.SecondaryScopes)).length > 0)
94
+ s += 4;
95
+ return s;
96
+ }
97
+ /**
98
+ * From in-scope candidates, decide inclusion per `Name`:
99
+ * - rank a Name's parts by specificity (score) then `Priority`;
100
+ * - the top part's `MergeBehavior` governs the group — `'Override'` keeps only the top,
101
+ * `'Append'` keeps all (additive within the Name).
102
+ * Distinct names always coexist (additive across names).
103
+ */
104
+ selectIncluded(candidates, _scope) {
105
+ const byName = new Map();
106
+ for (const p of candidates) {
107
+ const arr = byName.get(p.Name) ?? [];
108
+ arr.push(p);
109
+ byName.set(p.Name, arr);
110
+ }
111
+ const result = [];
112
+ for (const group of byName.values()) {
113
+ group.sort((a, b) => this.score(b) - this.score(a) || b.Priority - a.Priority);
114
+ if (group[0].MergeBehavior === "Append") {
115
+ result.push(...group);
116
+ }
117
+ else {
118
+ result.push(group[0]);
119
+ }
120
+ }
121
+ return result;
122
+ }
123
+ /** Final assembly order: Sort ASC, then Priority DESC, then Name. */
124
+ order(parts) {
125
+ return [...parts].sort((a, b) => a.Sort - b.Sort || b.Priority - a.Priority || a.Name.localeCompare(b.Name));
126
+ }
127
+ // ── Helpers ────────────────────────────────────────────────────────────────
128
+ parseScopes(raw) {
129
+ if (!raw)
130
+ return {};
131
+ try {
132
+ const o = JSON.parse(raw);
133
+ return o && typeof o === "object" ? o : {};
134
+ }
135
+ catch {
136
+ return {};
137
+ }
138
+ }
139
+ coerceRole(raw) {
140
+ const lower = typeof raw === "string" ? raw.toLowerCase() : "";
141
+ if (lower === "user")
142
+ return "user";
143
+ if (lower === "assistant")
144
+ return "assistant";
145
+ return "system";
146
+ }
147
+ }
148
+ /**
149
+ * Convenience used by the agent runtime: obtain the (possibly overridden) resolver via the
150
+ * class factory, resolve + assemble for `promptID`/`scope`, and unshift the role-faithful messages
151
+ * onto the front of `conversationMessages` (mirroring how memory/RAG inject). No-op when nothing
152
+ * resolves. Returns the included parts (for observability).
153
+ */
154
+ export function InjectScopedPromptParts(resolver, promptID, scope, conversationMessages) {
155
+ const parts = resolver.Resolve(promptID, scope);
156
+ if (parts.length === 0)
157
+ return [];
158
+ const messages = resolver.AssembleMessages(parts);
159
+ if (messages.length === 0)
160
+ return [];
161
+ conversationMessages.unshift(...messages);
162
+ LogStatus(`PromptComponentResolver: injected ${messages.length} message(s) from ${parts.length} ` +
163
+ `part(s) for prompt ${promptID} (scope record=${scope.primaryScopeRecordId ?? "global"})`);
164
+ return parts;
165
+ }
166
+ //# sourceMappingURL=prompt-component-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-component-resolver.js","sourceRoot":"","sources":["../src/prompt-component-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @fileoverview Resolves an agent's curated **media kit** — a `MJ: Collections` of `MJ: Artifacts`
3
+ * bound to the agent (or supplied as a per-session override) — into a compact, model-readable
4
+ * manifest the realtime agent reasons over to decide what to show on the Media channel.
5
+ *
6
+ * Design: a Collection IS the kit; each `MJ: Collection Artifacts` membership row carries the
7
+ * per-kit `Sequence` (priority), `ContextDescription` (agent "when to show it") and `Preload`
8
+ * (eager hint). The artifact's current version supplies the actual media (`FileID` -> `MJ: Files`,
9
+ * `MimeType`, display name). We add NO new top-level entity — the agent reuses the existing
10
+ * `Media_ShowMedia({ fileId, mediaType, displayName })` client tool to surface a chosen item, which
11
+ * streams through the authenticated `/media` route. Nothing here duplicates `MJ: Files`.
12
+ *
13
+ * Pure helpers ({@link mediaTypeFromMimeType}, {@link formatAgentMediaManifest}) are exported for
14
+ * unit testing; the DB-touching resolvers accept an explicit `provider` + `contextUser` so they are
15
+ * multi-provider safe and mockable.
16
+ *
17
+ * @module @memberjunction/ai-agents
18
+ * @author MemberJunction.com
19
+ */
20
+ import { IMetadataProvider, UserInfo } from '@memberjunction/core';
21
+ /** The media kinds the realtime Media channel can render (mirrors the client `Media_ShowMedia` enum). */
22
+ export type AgentMediaKind = 'image' | 'video' | 'audio' | 'pdf' | 'web';
23
+ /** One resolved, model-readable media item in an agent's kit (ordered by its membership `Sequence`). */
24
+ export interface AgentMediaManifestItem {
25
+ /** The `MJ: Collection Artifacts` membership id (stable per kit). */
26
+ ResourceID: string;
27
+ /** The `MJ: Files` id to show — streamed securely via the `/media` route by `Media_ShowMedia`. */
28
+ FileID: string;
29
+ /** The media kind derived from the artifact version's MIME type. */
30
+ MediaType: AgentMediaKind;
31
+ /** Short label for the item's tab (the artifact version's name). */
32
+ DisplayName: string;
33
+ /** Agent-facing "what this is / when to show it" (membership override, else the version description). */
34
+ ContextDescription: string | null;
35
+ /** When true, the agent is told to show this at session start rather than waiting for relevance. */
36
+ Preload: boolean;
37
+ }
38
+ /**
39
+ * Maps an artifact version's MIME type to a Media-channel kind. Returns `null` for types the Media
40
+ * surface can't render as media (so the caller drops the item from the kit).
41
+ */
42
+ export declare function mediaTypeFromMimeType(mimeType: string | null | undefined): AgentMediaKind | null;
43
+ /**
44
+ * Resolves the Collection id that is the agent's media kit for this session:
45
+ * `override > AIAgent.DefaultMediaCollectionID > null`.
46
+ */
47
+ export declare function resolveAgentMediaCollectionID(provider: IMetadataProvider, contextUser: UserInfo, agentID: string, overrideCollectionID?: string | null): Promise<string | null>;
48
+ /**
49
+ * Loads a Collection's artifacts (ordered by membership `Sequence`) and resolves each to a media
50
+ * manifest item, dropping memberships whose current version has no `FileID` or a non-media MIME type.
51
+ */
52
+ export declare function resolveAgentMediaManifest(provider: IMetadataProvider, contextUser: UserInfo, collectionID: string): Promise<AgentMediaManifestItem[]>;
53
+ /**
54
+ * Formats a media manifest into a single background context note for the realtime agent. Lists each
55
+ * item with its `fileId`, media type, display name and when-to-show guidance, and instructs the agent
56
+ * to surface items with the existing `Media_ShowMedia` tool. Returns `null` for an empty manifest.
57
+ */
58
+ export declare function formatAgentMediaManifest(items: AgentMediaManifestItem[]): string | null;
59
+ /**
60
+ * End-to-end: resolves the agent's media kit (override > agent default) and returns the formatted
61
+ * agent context note, or `null` when there is no kit / no showable items. Best-effort: logs and
62
+ * returns `null` on any failure so it can never break session start.
63
+ */
64
+ export declare function buildAgentMediaContextNote(provider: IMetadataProvider, contextUser: UserInfo, agentID: string, overrideCollectionID?: string | null): Promise<string | null>;
65
+ //# sourceMappingURL=agent-media-library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-media-library.d.ts","sourceRoot":"","sources":["../../src/realtime/agent-media-library.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,iBAAiB,EAAW,QAAQ,EAAY,MAAM,sBAAsB,CAAC;AAItF,yGAAyG;AACzG,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;AAEzE,wGAAwG;AACxG,MAAM,WAAW,sBAAsB;IACnC,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,kGAAkG;IAClG,MAAM,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,SAAS,EAAE,cAAc,CAAC;IAC1B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,yGAAyG;IACzG,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oGAAoG;IACpG,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,cAAc,GAAG,IAAI,CAQhG;AAED;;;GAGG;AACH,wBAAsB,6BAA6B,CAC/C,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,QAAQ,EACrB,OAAO,EAAE,MAAM,EACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,GACrC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBxB;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC3C,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,QAAQ,EACrB,YAAY,EAAE,MAAM,GACrB,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAwBnC;AAgDD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,MAAM,GAAG,IAAI,CAevF;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC5C,QAAQ,EAAE,iBAAiB,EAC3B,WAAW,EAAE,QAAQ,EACrB,OAAO,EAAE,MAAM,EACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,GACrC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @fileoverview Resolves an agent's curated **media kit** — a `MJ: Collections` of `MJ: Artifacts`
3
+ * bound to the agent (or supplied as a per-session override) — into a compact, model-readable
4
+ * manifest the realtime agent reasons over to decide what to show on the Media channel.
5
+ *
6
+ * Design: a Collection IS the kit; each `MJ: Collection Artifacts` membership row carries the
7
+ * per-kit `Sequence` (priority), `ContextDescription` (agent "when to show it") and `Preload`
8
+ * (eager hint). The artifact's current version supplies the actual media (`FileID` -> `MJ: Files`,
9
+ * `MimeType`, display name). We add NO new top-level entity — the agent reuses the existing
10
+ * `Media_ShowMedia({ fileId, mediaType, displayName })` client tool to surface a chosen item, which
11
+ * streams through the authenticated `/media` route. Nothing here duplicates `MJ: Files`.
12
+ *
13
+ * Pure helpers ({@link mediaTypeFromMimeType}, {@link formatAgentMediaManifest}) are exported for
14
+ * unit testing; the DB-touching resolvers accept an explicit `provider` + `contextUser` so they are
15
+ * multi-provider safe and mockable.
16
+ *
17
+ * @module @memberjunction/ai-agents
18
+ * @author MemberJunction.com
19
+ */
20
+ import { RunView, LogError } from '@memberjunction/core';
21
+ import { IsValidUUID } from '@memberjunction/global';
22
+ /**
23
+ * Maps an artifact version's MIME type to a Media-channel kind. Returns `null` for types the Media
24
+ * surface can't render as media (so the caller drops the item from the kit).
25
+ */
26
+ export function mediaTypeFromMimeType(mimeType) {
27
+ const mime = (mimeType ?? '').trim().toLowerCase();
28
+ if (mime.startsWith('image/'))
29
+ return 'image';
30
+ if (mime.startsWith('video/'))
31
+ return 'video';
32
+ if (mime.startsWith('audio/'))
33
+ return 'audio';
34
+ if (mime === 'application/pdf')
35
+ return 'pdf';
36
+ if (mime === 'text/html' || mime === 'application/xhtml+xml')
37
+ return 'web';
38
+ return null;
39
+ }
40
+ /**
41
+ * Resolves the Collection id that is the agent's media kit for this session:
42
+ * `override > AIAgent.DefaultMediaCollectionID > null`.
43
+ */
44
+ export async function resolveAgentMediaCollectionID(provider, contextUser, agentID, overrideCollectionID) {
45
+ if (overrideCollectionID) {
46
+ // The override may come from a calling app / per-session input, so validate it as a UUID before it
47
+ // ever reaches a filter. A malformed override is ignored (logged) and resolution falls back to the
48
+ // agent default — never a broken or injected query.
49
+ const trimmed = overrideCollectionID.trim();
50
+ if (IsValidUUID(trimmed)) {
51
+ return trimmed;
52
+ }
53
+ LogError(`[agent-media-library] Ignoring malformed overrideCollectionID '${overrideCollectionID}' — ` +
54
+ 'falling back to the agent default media kit.');
55
+ }
56
+ const rv = RunView.FromMetadataProvider(provider);
57
+ const result = await rv.RunView({ EntityName: 'AI Agents', ExtraFilter: `ID='${agentID}'`, ResultType: 'entity_object' }, contextUser);
58
+ if (!result.Success || result.Results.length === 0) {
59
+ return null;
60
+ }
61
+ return result.Results[0].DefaultMediaCollectionID ?? null;
62
+ }
63
+ /**
64
+ * Loads a Collection's artifacts (ordered by membership `Sequence`) and resolves each to a media
65
+ * manifest item, dropping memberships whose current version has no `FileID` or a non-media MIME type.
66
+ */
67
+ export async function resolveAgentMediaManifest(provider, contextUser, collectionID) {
68
+ const rv = RunView.FromMetadataProvider(provider);
69
+ const memberships = await rv.RunView({
70
+ EntityName: 'MJ: Collection Artifacts',
71
+ ExtraFilter: `CollectionID='${collectionID}'`,
72
+ OrderBy: 'Sequence ASC',
73
+ ResultType: 'entity_object',
74
+ }, contextUser);
75
+ if (!memberships.Success || memberships.Results.length === 0) {
76
+ return [];
77
+ }
78
+ const versionsByID = await loadArtifactVersions(rv, contextUser, memberships.Results.map((m) => m.ArtifactVersionID));
79
+ const items = [];
80
+ for (const membership of memberships.Results) {
81
+ const item = toManifestItem(membership, versionsByID.get(membership.ArtifactVersionID));
82
+ if (item) {
83
+ items.push(item);
84
+ }
85
+ }
86
+ return items;
87
+ }
88
+ /** Loads the artifact versions referenced by a kit's memberships, keyed by id. */
89
+ async function loadArtifactVersions(rv, contextUser, versionIDs) {
90
+ const byID = new Map();
91
+ const uniqueIDs = [...new Set(versionIDs.filter((id) => !!id))];
92
+ if (uniqueIDs.length === 0) {
93
+ return byID;
94
+ }
95
+ const inList = uniqueIDs.map((id) => `'${id}'`).join(',');
96
+ const result = await rv.RunView({ EntityName: 'MJ: Artifact Versions', ExtraFilter: `ID IN (${inList})`, ResultType: 'entity_object' }, contextUser);
97
+ if (result.Success) {
98
+ for (const version of result.Results) {
99
+ byID.set(version.ID, version);
100
+ }
101
+ }
102
+ return byID;
103
+ }
104
+ /** Resolves one membership + its artifact version to a manifest item, or `null` if not showable. */
105
+ function toManifestItem(membership, version) {
106
+ if (!version || !version.FileID) {
107
+ return null; // text-only / unresolved versions can't be shown as media
108
+ }
109
+ const mediaType = mediaTypeFromMimeType(version.MimeType);
110
+ if (!mediaType) {
111
+ return null; // non-media MIME type — drop from the kit
112
+ }
113
+ return {
114
+ ResourceID: membership.ID,
115
+ FileID: version.FileID,
116
+ MediaType: mediaType,
117
+ DisplayName: version.Name?.trim() || 'Media',
118
+ ContextDescription: membership.ContextDescription?.trim() || version.Description?.trim() || null,
119
+ Preload: !!membership.Preload,
120
+ };
121
+ }
122
+ /**
123
+ * Formats a media manifest into a single background context note for the realtime agent. Lists each
124
+ * item with its `fileId`, media type, display name and when-to-show guidance, and instructs the agent
125
+ * to surface items with the existing `Media_ShowMedia` tool. Returns `null` for an empty manifest.
126
+ */
127
+ export function formatAgentMediaManifest(items) {
128
+ if (items.length === 0) {
129
+ return null;
130
+ }
131
+ const lines = items.map((item, index) => {
132
+ const when = item.ContextDescription ? ` — ${item.ContextDescription}` : '';
133
+ const preload = item.Preload ? ' [PRELOAD: show at the start of the call]' : '';
134
+ return `${index + 1}. "${item.DisplayName}" (${item.MediaType})${when} fileId: ${item.FileID}${preload}`;
135
+ });
136
+ return ('[media-library] You have a curated media kit you can show on the shared Media surface during this call. ' +
137
+ 'To show an item, call Media_ShowMedia with its fileId, mediaType and displayName. Show an item only when ' +
138
+ 'it is relevant (or now, if it is marked PRELOAD). Do NOT read this list aloud. Available items, in priority order:\n' +
139
+ lines.join('\n'));
140
+ }
141
+ /**
142
+ * End-to-end: resolves the agent's media kit (override > agent default) and returns the formatted
143
+ * agent context note, or `null` when there is no kit / no showable items. Best-effort: logs and
144
+ * returns `null` on any failure so it can never break session start.
145
+ */
146
+ export async function buildAgentMediaContextNote(provider, contextUser, agentID, overrideCollectionID) {
147
+ try {
148
+ const collectionID = await resolveAgentMediaCollectionID(provider, contextUser, agentID, overrideCollectionID);
149
+ if (!collectionID) {
150
+ return null;
151
+ }
152
+ const items = await resolveAgentMediaManifest(provider, contextUser, collectionID);
153
+ return formatAgentMediaManifest(items);
154
+ }
155
+ catch (error) {
156
+ LogError(`[agent-media-library] Failed to build media manifest for agent ${agentID}: ${error instanceof Error ? error.message : String(error)}`);
157
+ return null;
158
+ }
159
+ }
160
+ //# sourceMappingURL=agent-media-library.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-media-library.js","sourceRoot":"","sources":["../../src/realtime/agent-media-library.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview Server-side channel plugin for the **headless** Client Context channel — the live
3
+ * wire that streams the user's app context (where they are, what they see, the available client-tool
4
+ * and agent manifest) to the realtime co-agent, and through which the model's single stable
5
+ * `ContextTool` proxy drives in-app actions.
6
+ *
7
+ * Paired with the browser's `ClientContextChannel` client plugin through the seeded
8
+ * `MJ: AI Agent Channels` row (`Name: 'ClientContextChannel'`, `IsHeadless: 1`,
9
+ * `ServerPluginClass: 'ClientContextChannelServer'`, `ClientPluginClass: 'ClientContextChannel'`).
10
+ *
11
+ * **Why the server half is intentionally thin.** This channel is *headless* (it never mounts a tab)
12
+ * and *ephemeral* (it persists no state of record — it is a live wire, not a document like the
13
+ * whiteboard). In the client-direct topology the work lives in the browser: the client plugin
14
+ * publishes context deltas via the provider's `SendContextNote` and executes `ContextTool` calls
15
+ * locally through the unified client-tool resolver (`ResolveClientTools` in
16
+ * `@memberjunction/ai-core-plus`) with no server round-trip. The server half exists to (a) complete
17
+ * the channel registry pairing so the channel is discoverable/loadable like every other channel, and
18
+ * (b) be the home for any *future* server-side context tooling. It contributes no server tools today
19
+ * and saves no state — both base defaults, made explicit here.
20
+ *
21
+ * @module @memberjunction/ai-agents
22
+ * @author MemberJunction.com
23
+ */
24
+ import { BaseRealtimeChannelServer, RealtimeToolDefinition } from '@memberjunction/ai';
25
+ /** The stable channel name, matching the seeded `MJ: AI Agent Channels` row. */
26
+ export declare const CLIENT_CONTEXT_CHANNEL_NAME = "ClientContextChannel";
27
+ /**
28
+ * Server half of the headless Client Context channel. One instance per realtime session (created by
29
+ * `RealtimeChannelServerHost` from the channel registry — never construct directly).
30
+ *
31
+ * Contributes **no server tools** ({@link GetServerToolDefinitions} returns `[]`) — the channel's
32
+ * `ContextTool` and client tools execute client-side — and persists **no state of record**
33
+ * ({@link OnChannelStateSave} returns `null`, the "keep nothing / live-only" posture), so a session
34
+ * resume never tries to rehydrate it.
35
+ */
36
+ export declare class ClientContextChannelServer extends BaseRealtimeChannelServer {
37
+ /** Matches the seeded `MJ: AI Agent Channels` row's `Name`. */
38
+ get ChannelName(): string;
39
+ /**
40
+ * No server-executed tools: the channel's stable `ContextTool` proxy and all surface client tools
41
+ * execute in the browser via the unified client-tool resolver. Explicit `[]` documents the intent.
42
+ */
43
+ GetServerToolDefinitions(): RealtimeToolDefinition[];
44
+ /**
45
+ * Live-only channel: it carries no state of record (it is a wire, not a document), so a landed
46
+ * state save is intentionally not persisted. Returning `null` keeps nothing — a session resume
47
+ * never rehydrates this channel.
48
+ *
49
+ * @returns `null` — never persist.
50
+ */
51
+ OnChannelStateSave(): Promise<string | null>;
52
+ }
53
+ /**
54
+ * Tree-shaking prevention for {@link ClientContextChannelServer}'s `@RegisterClass` registration.
55
+ * Called from a static code path in the server host so the registration always executes — mirroring
56
+ * every other `Load...()` in the realtime stack.
57
+ */
58
+ export declare function LoadClientContextChannelServer(): void;
59
+ //# sourceMappingURL=client-context-channel-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-context-channel-server.d.ts","sourceRoot":"","sources":["../../src/realtime/client-context-channel-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAGvF,gFAAgF;AAChF,eAAO,MAAM,2BAA2B,yBAAyB,CAAC;AAElE;;;;;;;;GAQG;AACH,qBACa,0BAA2B,SAAQ,yBAAyB;IACrE,+DAA+D;IAC/D,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED;;;OAGG;IACa,wBAAwB,IAAI,sBAAsB,EAAE;IAIpE;;;;;;OAMG;IACmB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAGrE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @fileoverview Server-side channel plugin for the **headless** Client Context channel — the live
3
+ * wire that streams the user's app context (where they are, what they see, the available client-tool
4
+ * and agent manifest) to the realtime co-agent, and through which the model's single stable
5
+ * `ContextTool` proxy drives in-app actions.
6
+ *
7
+ * Paired with the browser's `ClientContextChannel` client plugin through the seeded
8
+ * `MJ: AI Agent Channels` row (`Name: 'ClientContextChannel'`, `IsHeadless: 1`,
9
+ * `ServerPluginClass: 'ClientContextChannelServer'`, `ClientPluginClass: 'ClientContextChannel'`).
10
+ *
11
+ * **Why the server half is intentionally thin.** This channel is *headless* (it never mounts a tab)
12
+ * and *ephemeral* (it persists no state of record — it is a live wire, not a document like the
13
+ * whiteboard). In the client-direct topology the work lives in the browser: the client plugin
14
+ * publishes context deltas via the provider's `SendContextNote` and executes `ContextTool` calls
15
+ * locally through the unified client-tool resolver (`ResolveClientTools` in
16
+ * `@memberjunction/ai-core-plus`) with no server round-trip. The server half exists to (a) complete
17
+ * the channel registry pairing so the channel is discoverable/loadable like every other channel, and
18
+ * (b) be the home for any *future* server-side context tooling. It contributes no server tools today
19
+ * and saves no state — both base defaults, made explicit here.
20
+ *
21
+ * @module @memberjunction/ai-agents
22
+ * @author MemberJunction.com
23
+ */
24
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
25
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
26
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
27
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
29
+ };
30
+ import { BaseRealtimeChannelServer } from '@memberjunction/ai';
31
+ import { RegisterClass } from '@memberjunction/global';
32
+ /** The stable channel name, matching the seeded `MJ: AI Agent Channels` row. */
33
+ export const CLIENT_CONTEXT_CHANNEL_NAME = 'ClientContextChannel';
34
+ /**
35
+ * Server half of the headless Client Context channel. One instance per realtime session (created by
36
+ * `RealtimeChannelServerHost` from the channel registry — never construct directly).
37
+ *
38
+ * Contributes **no server tools** ({@link GetServerToolDefinitions} returns `[]`) — the channel's
39
+ * `ContextTool` and client tools execute client-side — and persists **no state of record**
40
+ * ({@link OnChannelStateSave} returns `null`, the "keep nothing / live-only" posture), so a session
41
+ * resume never tries to rehydrate it.
42
+ */
43
+ let ClientContextChannelServer = class ClientContextChannelServer extends BaseRealtimeChannelServer {
44
+ /** Matches the seeded `MJ: AI Agent Channels` row's `Name`. */
45
+ get ChannelName() {
46
+ return CLIENT_CONTEXT_CHANNEL_NAME;
47
+ }
48
+ /**
49
+ * No server-executed tools: the channel's stable `ContextTool` proxy and all surface client tools
50
+ * execute in the browser via the unified client-tool resolver. Explicit `[]` documents the intent.
51
+ */
52
+ GetServerToolDefinitions() {
53
+ return [];
54
+ }
55
+ /**
56
+ * Live-only channel: it carries no state of record (it is a wire, not a document), so a landed
57
+ * state save is intentionally not persisted. Returning `null` keeps nothing — a session resume
58
+ * never rehydrates this channel.
59
+ *
60
+ * @returns `null` — never persist.
61
+ */
62
+ async OnChannelStateSave() {
63
+ return null;
64
+ }
65
+ };
66
+ ClientContextChannelServer = __decorate([
67
+ RegisterClass(BaseRealtimeChannelServer, 'ClientContextChannelServer')
68
+ ], ClientContextChannelServer);
69
+ export { ClientContextChannelServer };
70
+ /**
71
+ * Tree-shaking prevention for {@link ClientContextChannelServer}'s `@RegisterClass` registration.
72
+ * Called from a static code path in the server host so the registration always executes — mirroring
73
+ * every other `Load...()` in the realtime stack.
74
+ */
75
+ export function LoadClientContextChannelServer() {
76
+ // no-op — the import + call create a static reference bundlers cannot eliminate
77
+ }
78
+ //# sourceMappingURL=client-context-channel-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-context-channel-server.js","sourceRoot":"","sources":["../../src/realtime/client-context-channel-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;AAEH,OAAO,EAAE,yBAAyB,EAA0B,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,gFAAgF;AAChF,MAAM,CAAC,MAAM,2BAA2B,GAAG,sBAAsB,CAAC;AAElE;;;;;;;;GAQG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,yBAAyB;IACrE,+DAA+D;IAC/D,IAAW,WAAW;QAClB,OAAO,2BAA2B,CAAC;IACvC,CAAC;IAED;;;OAGG;IACa,wBAAwB;QACpC,OAAO,EAAE,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACa,KAAK,CAAC,kBAAkB;QACpC,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAA;AAxBY,0BAA0B;IADtC,aAAa,CAAC,yBAAyB,EAAE,4BAA4B,CAAC;GAC1D,0BAA0B,CAwBtC;;AAED;;;;GAIG;AACH,MAAM,UAAU,8BAA8B;IAC1C,gFAAgF;AACpF,CAAC"}