@telora/daemon 0.13.17 → 0.13.18

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.
@@ -0,0 +1,80 @@
1
+ /**
2
+ * LLM client for loop data updates.
3
+ *
4
+ * Calls the Anthropic API using the organization's LLM secret
5
+ * (fetched via edge function RPC). One call per strategy per cycle maximum.
6
+ */
7
+ import { callApi } from './queries/shared.js';
8
+ // ---------------------------------------------------------------------------
9
+ // API key retrieval
10
+ // ---------------------------------------------------------------------------
11
+ /**
12
+ * Fetch the organization's Anthropic API key via the edge function.
13
+ * Falls back to ANTHROPIC_API_KEY env var if not configured in the org.
14
+ */
15
+ async function getApiKey(_organizationId) {
16
+ try {
17
+ const result = await callApi('llm_secret_get', {
18
+ provider: 'anthropic',
19
+ });
20
+ if (result.apiKey)
21
+ return result.apiKey;
22
+ }
23
+ catch {
24
+ // Fall through to env var
25
+ }
26
+ return process.env.ANTHROPIC_API_KEY ?? null;
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // LLM call
30
+ // ---------------------------------------------------------------------------
31
+ /** Default model for loop evaluations. */
32
+ const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
33
+ /** Max tokens for the loop update response. */
34
+ const MAX_TOKENS = 4096;
35
+ /**
36
+ * Call the Anthropic API for a loop data update.
37
+ *
38
+ * @param organizationId - Organization owning the LLM secret
39
+ * @param prompt - System + user prompt assembled by the prompt builder
40
+ * @returns Raw text response, or null if the call failed
41
+ */
42
+ export async function callLoopLLM(organizationId, prompt) {
43
+ const apiKey = await getApiKey(organizationId);
44
+ if (!apiKey) {
45
+ console.log('[Loop] No Anthropic API key available -- skipping LLM evaluation');
46
+ return null;
47
+ }
48
+ const messages = [
49
+ { role: 'user', content: prompt.user },
50
+ ];
51
+ try {
52
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
53
+ method: 'POST',
54
+ headers: {
55
+ 'Content-Type': 'application/json',
56
+ 'x-api-key': apiKey,
57
+ 'anthropic-version': '2023-06-01',
58
+ },
59
+ body: JSON.stringify({
60
+ model: DEFAULT_MODEL,
61
+ max_tokens: MAX_TOKENS,
62
+ system: prompt.system,
63
+ messages,
64
+ }),
65
+ });
66
+ if (!response.ok) {
67
+ const errorBody = await response.text().catch(() => 'unknown error');
68
+ console.log(`[Loop] Anthropic API error (${response.status}): ${errorBody.slice(0, 200)}`);
69
+ return null;
70
+ }
71
+ const result = await response.json();
72
+ const textBlock = result.content?.find(c => c.type === 'text');
73
+ return textBlock?.text ?? null;
74
+ }
75
+ catch (err) {
76
+ console.log(`[Loop] Anthropic API call failed: ${err instanceof Error ? err.message : String(err)}`);
77
+ return null;
78
+ }
79
+ }
80
+ //# sourceMappingURL=loop-llm-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-llm-client.js","sourceRoot":"","sources":["../src/loop-llm-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAqB9C,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;GAGG;AACH,KAAK,UAAU,SAAS,CAAC,eAAuB;IAC9C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAoB,gBAAgB,EAAE;YAChE,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC,MAAM,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC;AAC/C,CAAC;AAED,8EAA8E;AAC9E,WAAW;AACX,8EAA8E;AAE9E,0CAA0C;AAC1C,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAEjD,+CAA+C;AAC/C,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,cAAsB,EACtB,MAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAuB;QACnC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE;KACvC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,uCAAuC,EAAE;YACpE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,WAAW,EAAE,MAAM;gBACnB,mBAAmB,EAAE,YAAY;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,aAAa;gBACpB,UAAU,EAAE,UAAU;gBACtB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,QAAQ;aACT,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,+BAA+B,QAAQ,CAAC,MAAM,MAAM,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3F,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAuB,CAAC;QAC1D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;QAC/D,OAAO,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrG,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Loop update prompt assembler.
3
+ *
4
+ * Builds the LLM prompt for loop data re-evaluation and parses
5
+ * the structured response into typed updates.
6
+ */
7
+ import type { LoopIntentData, RealityData, VarianceResult } from './loop-variance.js';
8
+ export interface LoopUpdatePrompt {
9
+ system: string;
10
+ user: string;
11
+ }
12
+ export interface LoopUpdateResult {
13
+ /** Ordered document IDs (first = highest priority). Empty = no change. */
14
+ documentReorders: string[];
15
+ /** Answer updates. */
16
+ answerUpdates: Array<{
17
+ questionId: string;
18
+ content: string;
19
+ }>;
20
+ /** New questions to create. */
21
+ newQuestions: Array<{
22
+ text: string;
23
+ }>;
24
+ /** Proposed persona adjustment (null = no change). */
25
+ personaProposal: string | null;
26
+ }
27
+ /**
28
+ * Build the LLM prompt for loop data re-evaluation.
29
+ *
30
+ * System = loop persona (how to think at this layer).
31
+ * User = intent data + reality data + variance + instructions.
32
+ */
33
+ export declare function buildLoopUpdatePrompt(intent: LoopIntentData, reality: RealityData, variance: VarianceResult): LoopUpdatePrompt;
34
+ /**
35
+ * Parse the LLM response into structured loop updates.
36
+ * Handles JSON extraction from markdown code blocks.
37
+ */
38
+ export declare function parseLoopUpdateResponse(rawResponse: string): LoopUpdateResult;
39
+ //# sourceMappingURL=loop-prompt-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-prompt-builder.d.ts","sourceRoot":"","sources":["../src/loop-prompt-builder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMtF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,sBAAsB;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,+BAA+B;IAC/B,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtC,sDAAsD;IACtD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,cAAc,GACvB,gBAAgB,CAyGlB;AAMD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAwC7E"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Loop update prompt assembler.
3
+ *
4
+ * Builds the LLM prompt for loop data re-evaluation and parses
5
+ * the structured response into typed updates.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Prompt builder
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Build the LLM prompt for loop data re-evaluation.
12
+ *
13
+ * System = loop persona (how to think at this layer).
14
+ * User = intent data + reality data + variance + instructions.
15
+ */
16
+ export function buildLoopUpdatePrompt(intent, reality, variance) {
17
+ // System prompt: the persona defines the agent's thinking altitude
18
+ const system = intent.persona
19
+ ? intent.persona
20
+ : 'You are a strategic analyst evaluating the alignment between declared intent and forecasted operational reality. Think in terms of directional priorities, risk, and whether execution is converging toward or diverging from the intended outcome.';
21
+ // Build the user message
22
+ const parts = [];
23
+ // Section 1: Current loop documents (ranked)
24
+ parts.push('## Current Loop Documents (force-ranked, highest priority first)\n');
25
+ if (intent.documents.length === 0) {
26
+ parts.push('_No loop documents exist yet. Create initial documents based on the reality data below._\n');
27
+ }
28
+ else {
29
+ for (const doc of intent.documents) {
30
+ parts.push(`### ${doc.sortOrder + 1}. ${doc.title}\n`);
31
+ parts.push(doc.content);
32
+ parts.push(`\n_Document ID: ${doc.id}_\n`);
33
+ }
34
+ }
35
+ // Section 2: Questions and current answers
36
+ parts.push('\n## Loop Questions\n');
37
+ const fixedQuestions = intent.questions.filter(q => q.questionType === 'fixed' && !q.isRetired);
38
+ const generatedQuestions = intent.questions.filter(q => q.questionType === 'generated' && !q.isRetired);
39
+ if (fixedQuestions.length > 0) {
40
+ parts.push('### Fixed Questions\n');
41
+ for (const q of fixedQuestions) {
42
+ parts.push(`**Q (${q.id}):** ${q.text}`);
43
+ parts.push(`**A:** ${q.answer || '_No answer yet._'}\n`);
44
+ }
45
+ }
46
+ if (generatedQuestions.length > 0) {
47
+ parts.push('### Agent-Generated Questions (ranked)\n');
48
+ for (const q of generatedQuestions) {
49
+ parts.push(`**Q (${q.id}):** ${q.text}`);
50
+ parts.push(`**A:** ${q.answer || '_No answer yet._'}\n`);
51
+ }
52
+ }
53
+ // Section 3: Reality data
54
+ parts.push('\n## Execution Reality (Wire B)\n');
55
+ const metrics = reality.metrics;
56
+ if (metrics) {
57
+ const m = metrics;
58
+ parts.push(`- Deliveries: planning=${m.deliveries_planning ?? 0}, queued=${m.deliveries_queued ?? 0}, coding=${m.deliveries_coding ?? 0}, verify=${m.deliveries_verify ?? 0}, done=${m.deliveries_done ?? 0}`);
59
+ parts.push(`- Issues: total=${m.total_issues ?? 0}, todo=${m.issues_todo ?? 0}, in_progress=${m.issues_in_progress ?? 0}, done=${m.issues_done ?? 0}, blocked=${m.issues_blocked ?? 0}`);
60
+ parts.push(`- Throughput: ${m.issues_done_7d ?? 0} (7d), ${m.issues_done_14d ?? 0} (14d), ${m.issues_done_30d ?? 0} (30d)`);
61
+ if (m.avg_cycle_time_days)
62
+ parts.push(`- Avg cycle time: ${m.avg_cycle_time_days} days`);
63
+ parts.push(`- Agent sessions: ${m.session_count ?? 0}, cost: $${Number(m.total_agent_cost ?? 0).toFixed(2)}, escalations: ${m.escalation_count ?? 0}`);
64
+ }
65
+ else {
66
+ parts.push('_No reality metrics available yet._');
67
+ }
68
+ // Projections
69
+ const comp = reality.projections.completion;
70
+ const cost = reality.projections.cost;
71
+ if (comp) {
72
+ parts.push(`\n### Completion Projection`);
73
+ parts.push(`- Status: ${comp.status}`);
74
+ if (comp.projectedCompletionDate)
75
+ parts.push(`- Projected completion: ${comp.projectedCompletionDate}`);
76
+ if (comp.velocity)
77
+ parts.push(`- Velocity: ${comp.velocity} issues/day`);
78
+ if (comp.confidence)
79
+ parts.push(`- Confidence: ${comp.confidence}`);
80
+ if (comp.remainingIssues)
81
+ parts.push(`- Remaining: ${comp.remainingIssues} issues`);
82
+ }
83
+ if (cost) {
84
+ parts.push(`\n### Cost Projection`);
85
+ parts.push(`- Cost to date: $${Number(cost.costToDate ?? 0).toFixed(2)}`);
86
+ parts.push(`- Burn rate: $${Number(cost.burnRatePerDay ?? 0).toFixed(2)}/day`);
87
+ if (cost.projectedTotalCost)
88
+ parts.push(`- Projected total: $${Number(cost.projectedTotalCost).toFixed(2)}`);
89
+ }
90
+ // Section 4: Computed variance
91
+ parts.push(`\n## Computed Variance\n`);
92
+ parts.push(`**Lock status:** ${variance.lockStatus}`);
93
+ parts.push(`**Summary:** ${variance.summary}`);
94
+ if (variance.noiseFlags.activityWithoutProgress)
95
+ parts.push('**Noise flag:** High activity without progress detected');
96
+ if (variance.noiseFlags.extendedCodingNoVerify)
97
+ parts.push('**Noise flag:** Extended coding phase without verification');
98
+ if (variance.noiseFlags.highEscalationRate)
99
+ parts.push('**Noise flag:** High escalation rate');
100
+ // Section 5: Instructions
101
+ parts.push(`\n## Instructions\n`);
102
+ parts.push('Given the intent data (loop documents, questions, answers) and the reality data (metrics, projections, variance), update the loop layer:\n');
103
+ parts.push('1. **Re-rank documents** if priorities have shifted based on new reality data. Return the ordered list of document IDs (highest priority first). Return empty array if no reordering needed.');
104
+ parts.push('2. **Revise answers** to questions based on the latest data. Only include answers that need updating.');
105
+ parts.push('3. **Generate new questions** if emerging concerns are not covered by existing questions. Questions should surface what matters but is not being asked.');
106
+ parts.push('4. **Propose persona adjustment** if the thinking mode needs recalibration. Return null if no adjustment needed.\n');
107
+ parts.push('**CRITICAL: This system is asymmetric.** You must NEVER suggest lowering targets, accommodating drift, or adjusting intent downward. If the gap between intent and forecasted reality is large, surface it as a concern and escalation signal -- do not normalize it. Only humans adjust intent.\n');
108
+ parts.push('Respond with a JSON object in this exact format:\n');
109
+ parts.push('```json');
110
+ parts.push('{');
111
+ parts.push(' "documentReorders": ["doc-id-1", "doc-id-2", ...],');
112
+ parts.push(' "answerUpdates": [{"questionId": "q-id", "content": "updated answer"}],');
113
+ parts.push(' "newQuestions": [{"text": "question text"}],');
114
+ parts.push(' "personaProposal": null');
115
+ parts.push('}');
116
+ parts.push('```');
117
+ return {
118
+ system,
119
+ user: parts.join('\n'),
120
+ };
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Response parser
124
+ // ---------------------------------------------------------------------------
125
+ /**
126
+ * Parse the LLM response into structured loop updates.
127
+ * Handles JSON extraction from markdown code blocks.
128
+ */
129
+ export function parseLoopUpdateResponse(rawResponse) {
130
+ const empty = {
131
+ documentReorders: [],
132
+ answerUpdates: [],
133
+ newQuestions: [],
134
+ personaProposal: null,
135
+ };
136
+ // Extract JSON from code block if present
137
+ let jsonStr = rawResponse.trim();
138
+ const codeBlockMatch = jsonStr.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
139
+ if (codeBlockMatch) {
140
+ jsonStr = codeBlockMatch[1].trim();
141
+ }
142
+ try {
143
+ const parsed = JSON.parse(jsonStr);
144
+ return {
145
+ documentReorders: Array.isArray(parsed.documentReorders)
146
+ ? parsed.documentReorders.filter(id => typeof id === 'string')
147
+ : [],
148
+ answerUpdates: Array.isArray(parsed.answerUpdates)
149
+ ? parsed.answerUpdates
150
+ .filter(a => typeof a.questionId === 'string' && typeof a.content === 'string')
151
+ .map(a => ({ questionId: a.questionId, content: a.content }))
152
+ : [],
153
+ newQuestions: Array.isArray(parsed.newQuestions)
154
+ ? parsed.newQuestions
155
+ .filter(q => typeof q.text === 'string')
156
+ .map(q => ({ text: q.text }))
157
+ : [],
158
+ personaProposal: typeof parsed.personaProposal === 'string'
159
+ ? parsed.personaProposal
160
+ : null,
161
+ };
162
+ }
163
+ catch {
164
+ console.log('[Loop] Failed to parse LLM response as JSON');
165
+ return empty;
166
+ }
167
+ }
168
+ //# sourceMappingURL=loop-prompt-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-prompt-builder.js","sourceRoot":"","sources":["../src/loop-prompt-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Variance computation for the Loop Agent differential receiver.
3
+ *
4
+ * Compares intent (loop data) against forecasted reality (metrics + projections)
5
+ * and produces a structured VarianceResult. Pure function, no side effects.
6
+ */
7
+ export interface LoopIntentData {
8
+ documents: Array<{
9
+ id: string;
10
+ title: string;
11
+ content: string;
12
+ sortOrder: number;
13
+ }>;
14
+ questions: Array<{
15
+ id: string;
16
+ text: string;
17
+ questionType: string;
18
+ sortOrder: number | null;
19
+ isRetired: boolean;
20
+ answer: string | null;
21
+ }>;
22
+ persona: string | null;
23
+ proposedPersona: string | null;
24
+ }
25
+ export interface RealityData {
26
+ metrics: Record<string, unknown> | null;
27
+ projections: {
28
+ completion: Record<string, unknown> | null;
29
+ cost: Record<string, unknown> | null;
30
+ };
31
+ }
32
+ export interface ScheduleVariance {
33
+ targetDate: string | null;
34
+ projectedDate: string | null;
35
+ varianceDays: number;
36
+ direction: 'ahead' | 'behind' | 'on_track' | 'unknown';
37
+ }
38
+ export interface ThroughputVariance {
39
+ currentVelocity: number;
40
+ requiredVelocity: number | null;
41
+ trend: 'accelerating' | 'steady' | 'decelerating' | 'stalled';
42
+ remainingIssues: number;
43
+ }
44
+ export interface CostVariance {
45
+ costToDate: number;
46
+ projectedTotal: number | null;
47
+ burnRatePerDay: number;
48
+ }
49
+ export interface StalenessVariance {
50
+ /** Whether loop data may be outdated relative to reality changes. */
51
+ isStale: boolean;
52
+ /** Human-readable reason. */
53
+ reason: string | null;
54
+ }
55
+ export interface VarianceDimensions {
56
+ schedule: ScheduleVariance | null;
57
+ throughput: ThroughputVariance | null;
58
+ cost: CostVariance | null;
59
+ staleness: StalenessVariance | null;
60
+ completionConfidence: number | null;
61
+ }
62
+ export interface NoiseFlags {
63
+ /** High activity but no throughput change. */
64
+ activityWithoutProgress: boolean;
65
+ /** All deliveries coding for extended period with no verify transitions. */
66
+ extendedCodingNoVerify: boolean;
67
+ /** High escalation rate relative to session count. */
68
+ highEscalationRate: boolean;
69
+ }
70
+ export type LockStatus = 'locked' | 'drifting' | 'unlocked';
71
+ export type TrendDirection = 'converging' | 'diverging' | 'stable';
72
+ export interface VarianceResult {
73
+ lockStatus: LockStatus;
74
+ dimensions: VarianceDimensions;
75
+ noiseFlags: NoiseFlags;
76
+ summary: string;
77
+ trendDirection: TrendDirection;
78
+ }
79
+ /**
80
+ * Compute variance between intent and forecasted reality.
81
+ *
82
+ * @param intent - Loop data (documents, questions, answers, persona)
83
+ * @param reality - Reality metrics and projections
84
+ * @param targetDate - Strategy target date (ISO string or null)
85
+ * @param previousVariance - Previous variance result for trend computation (optional)
86
+ * @returns Structured variance result
87
+ */
88
+ export declare function computeVariance(intent: LoopIntentData, reality: RealityData, targetDate: string | null, previousVariance?: VarianceResult | null): VarianceResult;
89
+ //# sourceMappingURL=loop-variance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop-variance.d.ts","sourceRoot":"","sources":["../src/loop-variance.ts"],"names":[],"mappings":"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"}