@skillrecordings/cli 0.1.0 → 0.2.1

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 (136) hide show
  1. package/bin/skill.mjs +21 -0
  2. package/dist/chunk-2NCCVTEE.js +22342 -0
  3. package/dist/chunk-2NCCVTEE.js.map +1 -0
  4. package/dist/chunk-3E3GYSZR.js +7071 -0
  5. package/dist/chunk-3E3GYSZR.js.map +1 -0
  6. package/dist/chunk-F4EM72IH.js +86 -0
  7. package/dist/chunk-F4EM72IH.js.map +1 -0
  8. package/dist/chunk-FGP7KUQW.js +432 -0
  9. package/dist/chunk-FGP7KUQW.js.map +1 -0
  10. package/dist/chunk-H3D6VCME.js +55 -0
  11. package/dist/chunk-H3D6VCME.js.map +1 -0
  12. package/dist/chunk-HK3PEWFD.js +208 -0
  13. package/dist/chunk-HK3PEWFD.js.map +1 -0
  14. package/dist/chunk-KEV3QKXP.js +4495 -0
  15. package/dist/chunk-KEV3QKXP.js.map +1 -0
  16. package/dist/chunk-MG37YDAK.js +882 -0
  17. package/dist/chunk-MG37YDAK.js.map +1 -0
  18. package/dist/chunk-MLNDSBZ4.js +482 -0
  19. package/dist/chunk-MLNDSBZ4.js.map +1 -0
  20. package/dist/chunk-N2WIV2JV.js +22 -0
  21. package/dist/chunk-N2WIV2JV.js.map +1 -0
  22. package/dist/chunk-PWWRCN5W.js +2067 -0
  23. package/dist/chunk-PWWRCN5W.js.map +1 -0
  24. package/dist/chunk-SKHBM3XP.js +7746 -0
  25. package/dist/chunk-SKHBM3XP.js.map +1 -0
  26. package/dist/chunk-WFANXVQG.js +64 -0
  27. package/dist/chunk-WFANXVQG.js.map +1 -0
  28. package/dist/chunk-WYKL32C3.js +275 -0
  29. package/dist/chunk-WYKL32C3.js.map +1 -0
  30. package/dist/chunk-ZNF7XD2S.js +134 -0
  31. package/dist/chunk-ZNF7XD2S.js.map +1 -0
  32. package/dist/config-AUAIYDSI.js +20 -0
  33. package/dist/config-AUAIYDSI.js.map +1 -0
  34. package/dist/fileFromPath-XN7LXIBI.js +134 -0
  35. package/dist/fileFromPath-XN7LXIBI.js.map +1 -0
  36. package/dist/getMachineId-bsd-KW2E7VK3.js +42 -0
  37. package/dist/getMachineId-bsd-KW2E7VK3.js.map +1 -0
  38. package/dist/getMachineId-darwin-ROXJUJX5.js +42 -0
  39. package/dist/getMachineId-darwin-ROXJUJX5.js.map +1 -0
  40. package/dist/getMachineId-linux-KVZEHQSU.js +34 -0
  41. package/dist/getMachineId-linux-KVZEHQSU.js.map +1 -0
  42. package/dist/getMachineId-unsupported-PPRILPPA.js +25 -0
  43. package/dist/getMachineId-unsupported-PPRILPPA.js.map +1 -0
  44. package/dist/getMachineId-win-IIF36LEJ.js +44 -0
  45. package/dist/getMachineId-win-IIF36LEJ.js.map +1 -0
  46. package/dist/index.js +112703 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/lib-R6DEEJCP.js +7623 -0
  49. package/dist/lib-R6DEEJCP.js.map +1 -0
  50. package/dist/pipeline-IAVVAKTU.js +120 -0
  51. package/dist/pipeline-IAVVAKTU.js.map +1 -0
  52. package/dist/query-NTP5NVXN.js +25 -0
  53. package/dist/query-NTP5NVXN.js.map +1 -0
  54. package/dist/routing-BAEPFB7V.js +390 -0
  55. package/dist/routing-BAEPFB7V.js.map +1 -0
  56. package/dist/stripe-lookup-charge-EPRUMZDL.js +56 -0
  57. package/dist/stripe-lookup-charge-EPRUMZDL.js.map +1 -0
  58. package/dist/stripe-payment-history-SJPKA63N.js +67 -0
  59. package/dist/stripe-payment-history-SJPKA63N.js.map +1 -0
  60. package/dist/stripe-subscription-status-L4Z65GB3.js +58 -0
  61. package/dist/stripe-subscription-status-L4Z65GB3.js.map +1 -0
  62. package/dist/stripe-verify-refund-FZDKCIUQ.js +54 -0
  63. package/dist/stripe-verify-refund-FZDKCIUQ.js.map +1 -0
  64. package/dist/support-memory-WSG7SDKG.js +10 -0
  65. package/dist/support-memory-WSG7SDKG.js.map +1 -0
  66. package/package.json +10 -7
  67. package/.env.encrypted +0 -0
  68. package/CHANGELOG.md +0 -35
  69. package/data/tt-archive-dataset.json +0 -1
  70. package/data/validate-test-dataset.json +0 -97
  71. package/docs/CLI-AUTH.md +0 -504
  72. package/preload.ts +0 -18
  73. package/src/__tests__/init.test.ts +0 -74
  74. package/src/alignment-test.ts +0 -64
  75. package/src/check-apps.ts +0 -16
  76. package/src/commands/auth/decrypt.ts +0 -123
  77. package/src/commands/auth/encrypt.ts +0 -81
  78. package/src/commands/auth/index.ts +0 -50
  79. package/src/commands/auth/keygen.ts +0 -41
  80. package/src/commands/auth/status.ts +0 -164
  81. package/src/commands/axiom/forensic.ts +0 -868
  82. package/src/commands/axiom/index.ts +0 -697
  83. package/src/commands/build-dataset.ts +0 -311
  84. package/src/commands/db-status.ts +0 -47
  85. package/src/commands/deploys.ts +0 -219
  86. package/src/commands/eval-local/compare.ts +0 -171
  87. package/src/commands/eval-local/health.ts +0 -212
  88. package/src/commands/eval-local/index.ts +0 -76
  89. package/src/commands/eval-local/real-tools.ts +0 -416
  90. package/src/commands/eval-local/run.ts +0 -1168
  91. package/src/commands/eval-local/score-production.ts +0 -256
  92. package/src/commands/eval-local/seed.ts +0 -276
  93. package/src/commands/eval-pipeline/index.ts +0 -53
  94. package/src/commands/eval-pipeline/real-tools.ts +0 -492
  95. package/src/commands/eval-pipeline/run.ts +0 -1316
  96. package/src/commands/eval-pipeline/seed.ts +0 -395
  97. package/src/commands/eval-prompt.ts +0 -496
  98. package/src/commands/eval.test.ts +0 -253
  99. package/src/commands/eval.ts +0 -108
  100. package/src/commands/faq-classify.ts +0 -460
  101. package/src/commands/faq-cluster.ts +0 -135
  102. package/src/commands/faq-extract.ts +0 -249
  103. package/src/commands/faq-mine.ts +0 -432
  104. package/src/commands/faq-review.ts +0 -426
  105. package/src/commands/front/index.ts +0 -351
  106. package/src/commands/front/pull-conversations.ts +0 -275
  107. package/src/commands/front/tags.ts +0 -825
  108. package/src/commands/front-cache.ts +0 -1277
  109. package/src/commands/front-stats.ts +0 -75
  110. package/src/commands/health.test.ts +0 -82
  111. package/src/commands/health.ts +0 -362
  112. package/src/commands/init.test.ts +0 -89
  113. package/src/commands/init.ts +0 -106
  114. package/src/commands/inngest/client.ts +0 -294
  115. package/src/commands/inngest/events.ts +0 -296
  116. package/src/commands/inngest/investigate.ts +0 -382
  117. package/src/commands/inngest/runs.ts +0 -149
  118. package/src/commands/inngest/signal.ts +0 -143
  119. package/src/commands/kb-sync.ts +0 -498
  120. package/src/commands/memory/find.ts +0 -135
  121. package/src/commands/memory/get.ts +0 -87
  122. package/src/commands/memory/index.ts +0 -97
  123. package/src/commands/memory/stats.ts +0 -163
  124. package/src/commands/memory/store.ts +0 -49
  125. package/src/commands/memory/vote.ts +0 -159
  126. package/src/commands/pipeline.ts +0 -127
  127. package/src/commands/responses.ts +0 -856
  128. package/src/commands/tools.ts +0 -293
  129. package/src/commands/wizard.ts +0 -319
  130. package/src/index.ts +0 -172
  131. package/src/lib/crypto.ts +0 -56
  132. package/src/lib/env-loader.ts +0 -206
  133. package/src/lib/onepassword.ts +0 -137
  134. package/src/test-agent-local.ts +0 -115
  135. package/tsconfig.json +0 -11
  136. package/vitest.config.ts +0 -10
@@ -0,0 +1,55 @@
1
+ import {
2
+ Index2
3
+ } from "./chunk-MG37YDAK.js";
4
+ import {
5
+ init_esm_shims
6
+ } from "./chunk-WFANXVQG.js";
7
+
8
+ // ../core/src/vector/client.ts
9
+ init_esm_shims();
10
+ var _index = null;
11
+ function getVectorIndex() {
12
+ if (!_index) {
13
+ const url = process.env.UPSTASH_VECTOR_REST_URL;
14
+ const token = process.env.UPSTASH_VECTOR_REST_TOKEN;
15
+ if (!url) {
16
+ throw new Error(
17
+ "UPSTASH_VECTOR_REST_URL environment variable is required"
18
+ );
19
+ }
20
+ if (!token) {
21
+ throw new Error(
22
+ "UPSTASH_VECTOR_REST_TOKEN environment variable is required"
23
+ );
24
+ }
25
+ _index = new Index2({
26
+ url,
27
+ token
28
+ });
29
+ }
30
+ return _index;
31
+ }
32
+ async function upsertVector(document) {
33
+ const index = getVectorIndex();
34
+ return index.upsert({
35
+ id: document.id,
36
+ data: document.data,
37
+ metadata: document.metadata
38
+ });
39
+ }
40
+ async function queryVectors(options) {
41
+ const index = getVectorIndex();
42
+ const results = await index.query(options);
43
+ return results.map((result) => ({
44
+ id: String(result.id),
45
+ score: result.score,
46
+ data: result.data,
47
+ metadata: result.metadata
48
+ }));
49
+ }
50
+
51
+ export {
52
+ upsertVector,
53
+ queryVectors
54
+ };
55
+ //# sourceMappingURL=chunk-H3D6VCME.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../core/src/vector/client.ts"],"sourcesContent":["import { Index } from '@upstash/vector'\nimport type {\n VectorDocument,\n VectorDocumentMetadata,\n VectorQueryResult,\n} from './types'\n\n/**\n * Lazy-initialized Upstash Vector index singleton.\n * Use this pattern to avoid creating connections at import time in serverless environments.\n */\nlet _index: Index | null = null\n\n/**\n * Get or create the Upstash Vector index instance.\n * Uses lazy initialization to defer connection until first use.\n *\n * @throws {Error} If UPSTASH_VECTOR_REST_URL or UPSTASH_VECTOR_REST_TOKEN env vars are missing\n */\nexport function getVectorIndex(): Index {\n if (!_index) {\n const url = process.env.UPSTASH_VECTOR_REST_URL\n const token = process.env.UPSTASH_VECTOR_REST_TOKEN\n\n if (!url) {\n throw new Error(\n 'UPSTASH_VECTOR_REST_URL environment variable is required'\n )\n }\n if (!token) {\n throw new Error(\n 'UPSTASH_VECTOR_REST_TOKEN environment variable is required'\n )\n }\n\n _index = new Index({\n url,\n token,\n })\n }\n\n return _index\n}\n\n/**\n * Options for querying vectors\n */\nexport interface QueryVectorsOptions {\n /** The search query text */\n data: string\n /** Number of results to return */\n topK: number\n /** Include metadata in results */\n includeMetadata?: boolean\n /** Include data in results */\n includeData?: boolean\n /** Metadata filter expression */\n filter?: string\n}\n\n/**\n * Upsert a vector document into the index.\n *\n * @param document - The vector document to upsert\n * @returns Promise resolving to the upsert result\n */\nexport async function upsertVector(document: VectorDocument): Promise<unknown> {\n const index = getVectorIndex()\n return index.upsert({\n id: document.id,\n data: document.data,\n metadata: document.metadata,\n })\n}\n\n/**\n * Query vectors by semantic similarity.\n *\n * @param options - Query options including search text, topK, and filters\n * @returns Promise resolving to array of query results\n */\nexport async function queryVectors(\n options: QueryVectorsOptions\n): Promise<VectorQueryResult[]> {\n const index = getVectorIndex()\n const results = await index.query(options)\n\n return results.map((result) => ({\n id: String(result.id),\n score: result.score,\n data: result.data,\n metadata: result.metadata as VectorDocumentMetadata | undefined,\n }))\n}\n"],"mappings":";;;;;;;;AAAA;AAWA,IAAI,SAAuB;AAQpB,SAAS,iBAAwB;AACtC,MAAI,CAAC,QAAQ;AACX,UAAM,MAAM,QAAQ,IAAI;AACxB,UAAM,QAAQ,QAAQ,IAAI;AAE1B,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,aAAS,IAAI,OAAM;AAAA,MACjB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAwBA,eAAsB,aAAa,UAA4C;AAC7E,QAAM,QAAQ,eAAe;AAC7B,SAAO,MAAM,OAAO;AAAA,IAClB,IAAI,SAAS;AAAA,IACb,MAAM,SAAS;AAAA,IACf,UAAU,SAAS;AAAA,EACrB,CAAC;AACH;AAQA,eAAsB,aACpB,SAC8B;AAC9B,QAAM,QAAQ,eAAe;AAC7B,QAAM,UAAU,MAAM,MAAM,MAAM,OAAO;AAEzC,SAAO,QAAQ,IAAI,CAAC,YAAY;AAAA,IAC9B,IAAI,OAAO,OAAO,EAAE;AAAA,IACpB,OAAO,OAAO;AAAA,IACd,MAAM,OAAO;AAAA,IACb,UAAU,OAAO;AAAA,EACnB,EAAE;AACJ;","names":[]}
@@ -0,0 +1,208 @@
1
+ import {
2
+ SupportMemoryService
3
+ } from "./chunk-WYKL32C3.js";
4
+ import {
5
+ init_esm_shims
6
+ } from "./chunk-WFANXVQG.js";
7
+
8
+ // ../core/src/memory/query.ts
9
+ init_esm_shims();
10
+ async function queryMemoriesForStage(options) {
11
+ const {
12
+ appId,
13
+ stage,
14
+ situation,
15
+ category,
16
+ limit = 5,
17
+ threshold = 0.6,
18
+ includeStale = false
19
+ } = options;
20
+ const results = await SupportMemoryService.findSimilar(situation, {
21
+ app_slug: appId,
22
+ stage,
23
+ category,
24
+ limit,
25
+ threshold,
26
+ include_stale: includeStale
27
+ });
28
+ return results.map(transformResult);
29
+ }
30
+ async function queryMemoriesForSituation(options) {
31
+ const {
32
+ appId,
33
+ situation,
34
+ category,
35
+ limit = 10,
36
+ threshold = 0.5,
37
+ includeStale = false
38
+ } = options;
39
+ const results = await SupportMemoryService.findSimilar(situation, {
40
+ app_slug: appId,
41
+ category,
42
+ limit,
43
+ threshold,
44
+ include_stale: includeStale
45
+ });
46
+ return results.map(transformResult);
47
+ }
48
+ async function queryCorrectedMemories(options) {
49
+ const { appId, situation, stage, limit = 5 } = options;
50
+ const results = await SupportMemoryService.findSimilar(situation, {
51
+ app_slug: appId,
52
+ stage,
53
+ outcome: "corrected",
54
+ limit,
55
+ threshold: 0.5,
56
+ include_stale: true
57
+ // Include older corrections for learning
58
+ });
59
+ return results.map(transformResult);
60
+ }
61
+ function formatMemoriesForPrompt(memories) {
62
+ if (memories.length === 0) {
63
+ return "";
64
+ }
65
+ const sections = [
66
+ "## Relevant Past Decisions",
67
+ "",
68
+ "The following similar situations were handled before. Use these as guidance:",
69
+ ""
70
+ ];
71
+ for (const memory of memories) {
72
+ sections.push(formatSingleMemory(memory));
73
+ sections.push("");
74
+ }
75
+ return sections.join("\n");
76
+ }
77
+ function formatMemoriesCompact(memories) {
78
+ if (memories.length === 0) {
79
+ return "";
80
+ }
81
+ const lines = ["## Prior Decisions (for reference):", ""];
82
+ for (const memory of memories) {
83
+ const outcomeIcon = getOutcomeIcon(memory.outcome);
84
+ const correctionNote = memory.correction ? ` [Correction: ${memory.correction}]` : "";
85
+ lines.push(
86
+ `${outcomeIcon} **Situation**: ${truncate(memory.situation, 100)}`
87
+ );
88
+ lines.push(
89
+ ` **Decision**: ${truncate(memory.decision, 150)}${correctionNote}`
90
+ );
91
+ lines.push("");
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+ function formatMemoriesForValidation(memories) {
96
+ const corrections = memories.filter((m) => m.outcome === "corrected");
97
+ const failures = memories.filter((m) => m.outcome === "failed");
98
+ if (corrections.length === 0 && failures.length === 0) {
99
+ return "";
100
+ }
101
+ const sections = [
102
+ "## \u26A0\uFE0F Learned Corrections",
103
+ "",
104
+ "These similar situations had issues. Avoid repeating these mistakes:",
105
+ ""
106
+ ];
107
+ for (const memory of [...corrections, ...failures]) {
108
+ sections.push(`**Situation**: ${truncate(memory.situation, 150)}`);
109
+ sections.push(`**Original Decision**: ${truncate(memory.decision, 150)}`);
110
+ if (memory.correction) {
111
+ sections.push(`**Correction**: ${memory.correction}`);
112
+ } else {
113
+ sections.push(`**Outcome**: Failed (no specific correction recorded)`);
114
+ }
115
+ sections.push("");
116
+ }
117
+ return sections.join("\n");
118
+ }
119
+ async function citeMemories(memoryIds, runId, appId) {
120
+ if (memoryIds.length === 0) return;
121
+ await SupportMemoryService.cite(memoryIds, runId, appId);
122
+ }
123
+ async function recordCitationOutcome(memoryIds, runId, outcome, appId) {
124
+ if (memoryIds.length === 0) return;
125
+ await SupportMemoryService.recordCitationOutcome(
126
+ memoryIds,
127
+ runId,
128
+ outcome,
129
+ appId
130
+ );
131
+ }
132
+ function transformResult(result) {
133
+ const { situation, decision } = SupportMemoryService.parseContent(
134
+ result.memory.content
135
+ );
136
+ return {
137
+ id: result.memory.id,
138
+ situation,
139
+ decision,
140
+ score: result.score,
141
+ rawScore: result.raw_score,
142
+ ageDays: result.age_days,
143
+ outcome: result.memory.metadata.outcome,
144
+ correction: result.memory.metadata.correction,
145
+ category: result.memory.metadata.category,
146
+ confidence: result.memory.metadata.confidence
147
+ };
148
+ }
149
+ function formatSingleMemory(memory) {
150
+ const lines = [];
151
+ const outcomeLabel = formatOutcomeLabel(memory.outcome);
152
+ const ageLabel = formatAge(memory.ageDays);
153
+ const scoreLabel = `${Math.round(memory.score * 100)}% match`;
154
+ lines.push(`### ${outcomeLabel} (${scoreLabel}, ${ageLabel})`);
155
+ lines.push("");
156
+ lines.push(`**Situation**: ${memory.situation}`);
157
+ lines.push("");
158
+ lines.push(`**Decision**: ${memory.decision}`);
159
+ if (memory.correction) {
160
+ lines.push("");
161
+ lines.push(`**\u26A0\uFE0F Correction**: ${memory.correction}`);
162
+ }
163
+ return lines.join("\n");
164
+ }
165
+ function formatOutcomeLabel(outcome) {
166
+ switch (outcome) {
167
+ case "success":
168
+ return "\u2705 Successful Decision";
169
+ case "corrected":
170
+ return "\u{1F504} Corrected Decision";
171
+ case "failed":
172
+ return "\u274C Failed Decision";
173
+ }
174
+ }
175
+ function getOutcomeIcon(outcome) {
176
+ switch (outcome) {
177
+ case "success":
178
+ return "\u2705";
179
+ case "corrected":
180
+ return "\u{1F504}";
181
+ case "failed":
182
+ return "\u274C";
183
+ }
184
+ }
185
+ function formatAge(days) {
186
+ if (days < 1) return "today";
187
+ if (days < 2) return "yesterday";
188
+ if (days < 7) return `${Math.round(days)} days ago`;
189
+ if (days < 30) return `${Math.round(days / 7)} weeks ago`;
190
+ if (days < 365) return `${Math.round(days / 30)} months ago`;
191
+ return `${Math.round(days / 365)} years ago`;
192
+ }
193
+ function truncate(text, maxLength) {
194
+ if (text.length <= maxLength) return text;
195
+ return text.slice(0, maxLength - 3) + "...";
196
+ }
197
+
198
+ export {
199
+ queryMemoriesForStage,
200
+ queryMemoriesForSituation,
201
+ queryCorrectedMemories,
202
+ formatMemoriesForPrompt,
203
+ formatMemoriesCompact,
204
+ formatMemoriesForValidation,
205
+ citeMemories,
206
+ recordCitationOutcome
207
+ };
208
+ //# sourceMappingURL=chunk-HK3PEWFD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../core/src/memory/query.ts"],"sourcesContent":["/**\n * Memory Query Layer\n *\n * Query helper for per-stage memory retrieval in the support pipeline.\n * Each pipeline stage can retrieve relevant memories before making decisions.\n */\n\nimport { SupportMemoryService } from '@skillrecordings/memory/support-memory'\nimport type {\n SupportSearchResult,\n SupportStage,\n} from '@skillrecordings/memory/support-schemas'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface QueryMemoriesOptions {\n /** App identifier for scoped memories */\n appId: string\n /** Pipeline stage to filter memories */\n stage: SupportStage\n /** Current ticket context (subject + body, or situation description) */\n situation: string\n /** Category filter if known (e.g., 'refund', 'access') */\n category?: string\n /** Maximum number of memories to return (default: 5) */\n limit?: number\n /** Minimum similarity threshold (default: 0.6) */\n threshold?: number\n /** Include memories with low confidence (default: false) */\n includeStale?: boolean\n}\n\n/**\n * A memory relevant to the current context, ready for prompt injection\n */\nexport interface RelevantMemory {\n /** Memory ID (for citation tracking) */\n id: string\n /** Original situation that was similar */\n situation: string\n /** Decision that was made */\n decision: string\n /** Similarity score (0-1), decay-adjusted */\n score: number\n /** Raw similarity score before decay */\n rawScore: number\n /** How old the memory is (days since created/validated) */\n ageDays: number\n /** Outcome from feedback: success, corrected, or failed */\n outcome: 'success' | 'corrected' | 'failed'\n /** If corrected, what should have happened */\n correction?: string\n /** Category tag */\n category?: string\n /** Original confidence before decay */\n confidence: number\n}\n\n// ============================================================================\n// Query Functions\n// ============================================================================\n\n/**\n * Query memories relevant to current ticket context for a specific pipeline stage.\n *\n * @example\n * ```typescript\n * // In classify stage\n * const memories = await queryMemoriesForStage({\n * appId: 'total-typescript',\n * stage: 'classify',\n * situation: `Customer email: ${subject}\\n${body}`,\n * limit: 5\n * })\n * ```\n */\nexport async function queryMemoriesForStage(\n options: QueryMemoriesOptions\n): Promise<RelevantMemory[]> {\n const {\n appId,\n stage,\n situation,\n category,\n limit = 5,\n threshold = 0.6,\n includeStale = false,\n } = options\n\n // Query the memory service\n const results = await SupportMemoryService.findSimilar(situation, {\n app_slug: appId,\n stage,\n category,\n limit,\n threshold,\n include_stale: includeStale,\n })\n\n // Transform to RelevantMemory format\n return results.map(transformResult)\n}\n\n/**\n * Query memories across all stages for a situation.\n * Useful for gathering broad context before processing.\n *\n * @example\n * ```typescript\n * // Gather all relevant memories regardless of stage\n * const memories = await queryMemoriesForSituation({\n * appId: 'total-typescript',\n * situation: `Refund request after 3 months`,\n * limit: 10\n * })\n * ```\n */\nexport async function queryMemoriesForSituation(options: {\n appId: string\n situation: string\n category?: string\n limit?: number\n threshold?: number\n includeStale?: boolean\n}): Promise<RelevantMemory[]> {\n const {\n appId,\n situation,\n category,\n limit = 10,\n threshold = 0.5,\n includeStale = false,\n } = options\n\n // Query without stage filter\n const results = await SupportMemoryService.findSimilar(situation, {\n app_slug: appId,\n category,\n limit,\n threshold,\n include_stale: includeStale,\n })\n\n return results.map(transformResult)\n}\n\n/**\n * Query memories that were corrected (to learn from mistakes).\n * Useful for validation stage to catch potential errors.\n */\nexport async function queryCorrectedMemories(options: {\n appId: string\n situation: string\n stage?: SupportStage\n limit?: number\n}): Promise<RelevantMemory[]> {\n const { appId, situation, stage, limit = 5 } = options\n\n const results = await SupportMemoryService.findSimilar(situation, {\n app_slug: appId,\n stage,\n outcome: 'corrected',\n limit,\n threshold: 0.5,\n include_stale: true, // Include older corrections for learning\n })\n\n return results.map(transformResult)\n}\n\n// ============================================================================\n// Formatting Functions\n// ============================================================================\n\n/**\n * Format memories for injection into LLM prompts.\n *\n * @example\n * ```typescript\n * const memories = await queryMemoriesForStage({ ... })\n * const prompt = `\n * ${formatMemoriesForPrompt(memories)}\n *\n * Now classify this ticket...\n * `\n * ```\n */\nexport function formatMemoriesForPrompt(memories: RelevantMemory[]): string {\n if (memories.length === 0) {\n return ''\n }\n\n const sections: string[] = [\n '## Relevant Past Decisions',\n '',\n 'The following similar situations were handled before. Use these as guidance:',\n '',\n ]\n\n for (const memory of memories) {\n sections.push(formatSingleMemory(memory))\n sections.push('')\n }\n\n return sections.join('\\n')\n}\n\n/**\n * Format memories as a concise context block (shorter format).\n * Use when token budget is tight.\n */\nexport function formatMemoriesCompact(memories: RelevantMemory[]): string {\n if (memories.length === 0) {\n return ''\n }\n\n const lines = ['## Prior Decisions (for reference):', '']\n\n for (const memory of memories) {\n const outcomeIcon = getOutcomeIcon(memory.outcome)\n const correctionNote = memory.correction\n ? ` [Correction: ${memory.correction}]`\n : ''\n lines.push(\n `${outcomeIcon} **Situation**: ${truncate(memory.situation, 100)}`\n )\n lines.push(\n ` **Decision**: ${truncate(memory.decision, 150)}${correctionNote}`\n )\n lines.push('')\n }\n\n return lines.join('\\n')\n}\n\n/**\n * Format memories for the validation stage (focus on corrections/failures).\n * Helps catch potential errors by showing what went wrong before.\n */\nexport function formatMemoriesForValidation(\n memories: RelevantMemory[]\n): string {\n const corrections = memories.filter((m) => m.outcome === 'corrected')\n const failures = memories.filter((m) => m.outcome === 'failed')\n\n if (corrections.length === 0 && failures.length === 0) {\n return ''\n }\n\n const sections: string[] = [\n '## ⚠️ Learned Corrections',\n '',\n 'These similar situations had issues. Avoid repeating these mistakes:',\n '',\n ]\n\n for (const memory of [...corrections, ...failures]) {\n sections.push(`**Situation**: ${truncate(memory.situation, 150)}`)\n sections.push(`**Original Decision**: ${truncate(memory.decision, 150)}`)\n if (memory.correction) {\n sections.push(`**Correction**: ${memory.correction}`)\n } else {\n sections.push(`**Outcome**: Failed (no specific correction recorded)`)\n }\n sections.push('')\n }\n\n return sections.join('\\n')\n}\n\n// ============================================================================\n// Citation Tracking\n// ============================================================================\n\n/**\n * Record that memories were used in a decision.\n * Call this after using memories in a pipeline stage.\n *\n * @param memoryIds - IDs of memories that were cited\n * @param runId - Current pipeline run/trace ID\n * @param appId - App identifier\n */\nexport async function citeMemories(\n memoryIds: string[],\n runId: string,\n appId: string\n): Promise<void> {\n if (memoryIds.length === 0) return\n await SupportMemoryService.cite(memoryIds, runId, appId)\n}\n\n/**\n * Record outcome for cited memories after human review.\n * Call this when a human approves or rejects a response.\n *\n * @param memoryIds - IDs of memories that were cited\n * @param runId - Pipeline run/trace ID\n * @param outcome - Whether the decision was successful\n * @param appId - App identifier\n */\nexport async function recordCitationOutcome(\n memoryIds: string[],\n runId: string,\n outcome: 'success' | 'failure',\n appId: string\n): Promise<void> {\n if (memoryIds.length === 0) return\n await SupportMemoryService.recordCitationOutcome(\n memoryIds,\n runId,\n outcome,\n appId\n )\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\nfunction transformResult(result: SupportSearchResult): RelevantMemory {\n const { situation, decision } = SupportMemoryService.parseContent(\n result.memory.content\n )\n\n return {\n id: result.memory.id,\n situation,\n decision,\n score: result.score,\n rawScore: result.raw_score,\n ageDays: result.age_days,\n outcome: result.memory.metadata.outcome,\n correction: result.memory.metadata.correction,\n category: result.memory.metadata.category,\n confidence: result.memory.metadata.confidence,\n }\n}\n\nfunction formatSingleMemory(memory: RelevantMemory): string {\n const lines: string[] = []\n const outcomeLabel = formatOutcomeLabel(memory.outcome)\n const ageLabel = formatAge(memory.ageDays)\n const scoreLabel = `${Math.round(memory.score * 100)}% match`\n\n lines.push(`### ${outcomeLabel} (${scoreLabel}, ${ageLabel})`)\n lines.push('')\n lines.push(`**Situation**: ${memory.situation}`)\n lines.push('')\n lines.push(`**Decision**: ${memory.decision}`)\n\n if (memory.correction) {\n lines.push('')\n lines.push(`**⚠️ Correction**: ${memory.correction}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction formatOutcomeLabel(\n outcome: 'success' | 'corrected' | 'failed'\n): string {\n switch (outcome) {\n case 'success':\n return '✅ Successful Decision'\n case 'corrected':\n return '🔄 Corrected Decision'\n case 'failed':\n return '❌ Failed Decision'\n }\n}\n\nfunction getOutcomeIcon(outcome: 'success' | 'corrected' | 'failed'): string {\n switch (outcome) {\n case 'success':\n return '✅'\n case 'corrected':\n return '🔄'\n case 'failed':\n return '❌'\n }\n}\n\nfunction formatAge(days: number): string {\n if (days < 1) return 'today'\n if (days < 2) return 'yesterday'\n if (days < 7) return `${Math.round(days)} days ago`\n if (days < 30) return `${Math.round(days / 7)} weeks ago`\n if (days < 365) return `${Math.round(days / 30)} months ago`\n return `${Math.round(days / 365)} years ago`\n}\n\nfunction truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text\n return text.slice(0, maxLength - 3) + '...'\n}\n"],"mappings":"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","names":[]}