@symerian/symi 3.0.18 → 3.0.19

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 (116) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  3. package/package.json +1 -1
  4. package/extensions/copilot-proxy/README.md +0 -24
  5. package/extensions/copilot-proxy/index.ts +0 -154
  6. package/extensions/copilot-proxy/node_modules/.bin/symi +0 -21
  7. package/extensions/copilot-proxy/package.json +0 -15
  8. package/extensions/copilot-proxy/symi.plugin.json +0 -9
  9. package/extensions/device-pair/index.ts +0 -642
  10. package/extensions/device-pair/symi.plugin.json +0 -20
  11. package/extensions/diagnostics-otel/index.ts +0 -15
  12. package/extensions/diagnostics-otel/node_modules/.bin/acorn +0 -21
  13. package/extensions/diagnostics-otel/node_modules/.bin/symi +0 -21
  14. package/extensions/diagnostics-otel/package.json +0 -27
  15. package/extensions/diagnostics-otel/src/service.test.ts +0 -290
  16. package/extensions/diagnostics-otel/src/service.ts +0 -666
  17. package/extensions/diagnostics-otel/symi.plugin.json +0 -8
  18. package/extensions/google-antigravity-auth/README.md +0 -24
  19. package/extensions/google-antigravity-auth/index.ts +0 -424
  20. package/extensions/google-antigravity-auth/node_modules/.bin/symi +0 -21
  21. package/extensions/google-antigravity-auth/package.json +0 -15
  22. package/extensions/google-antigravity-auth/symi.plugin.json +0 -9
  23. package/extensions/google-gemini-cli-auth/README.md +0 -35
  24. package/extensions/google-gemini-cli-auth/index.ts +0 -75
  25. package/extensions/google-gemini-cli-auth/node_modules/.bin/symi +0 -21
  26. package/extensions/google-gemini-cli-auth/oauth.test.ts +0 -162
  27. package/extensions/google-gemini-cli-auth/oauth.ts +0 -636
  28. package/extensions/google-gemini-cli-auth/package.json +0 -15
  29. package/extensions/google-gemini-cli-auth/symi.plugin.json +0 -9
  30. package/extensions/learning-loop/index.ts +0 -159
  31. package/extensions/learning-loop/node_modules/.bin/symi +0 -21
  32. package/extensions/learning-loop/package.json +0 -18
  33. package/extensions/learning-loop/src/analytics/gateway-methods.ts +0 -230
  34. package/extensions/learning-loop/src/analytics/metrics-aggregator.ts +0 -153
  35. package/extensions/learning-loop/src/capture/run-tracker.ts +0 -181
  36. package/extensions/learning-loop/src/capture/serializer.ts +0 -74
  37. package/extensions/learning-loop/src/db.ts +0 -583
  38. package/extensions/learning-loop/src/feedback/explicit-feedback.ts +0 -58
  39. package/extensions/learning-loop/src/feedback/implicit-signals.ts +0 -89
  40. package/extensions/learning-loop/src/graph/edge-inference.ts +0 -189
  41. package/extensions/learning-loop/src/graph/graph-retrieval.ts +0 -144
  42. package/extensions/learning-loop/src/graph/graph-store.ts +0 -183
  43. package/extensions/learning-loop/src/hooks.ts +0 -244
  44. package/extensions/learning-loop/src/injection/cache.ts +0 -73
  45. package/extensions/learning-loop/src/injection/context-injector.ts +0 -104
  46. package/extensions/learning-loop/src/injection/prompt-builder.ts +0 -43
  47. package/extensions/learning-loop/src/learning/embedding-bridge.ts +0 -54
  48. package/extensions/learning-loop/src/learning/learning-extractor.ts +0 -217
  49. package/extensions/learning-loop/src/learning/learning-store.ts +0 -158
  50. package/extensions/learning-loop/src/learning/retrieval.ts +0 -87
  51. package/extensions/learning-loop/src/math/confidence-intervals.ts +0 -62
  52. package/extensions/learning-loop/src/math/ewma.ts +0 -51
  53. package/extensions/learning-loop/src/math/weighted-scorer.ts +0 -42
  54. package/extensions/learning-loop/src/schema.ts +0 -176
  55. package/extensions/learning-loop/src/scoring/normalization.ts +0 -32
  56. package/extensions/learning-loop/src/scoring/quality-engine.ts +0 -78
  57. package/extensions/learning-loop/src/scoring/signal-extractors.ts +0 -155
  58. package/extensions/learning-loop/src/test/context-injector.test.ts +0 -142
  59. package/extensions/learning-loop/src/test/fixes.test.ts +0 -1286
  60. package/extensions/learning-loop/src/test/graph.test.ts +0 -711
  61. package/extensions/learning-loop/src/test/integration.test.ts +0 -312
  62. package/extensions/learning-loop/src/test/learning-store.test.ts +0 -191
  63. package/extensions/learning-loop/src/test/math.test.ts +0 -148
  64. package/extensions/learning-loop/src/test/quality-engine.test.ts +0 -231
  65. package/extensions/learning-loop/src/test/run-tracker.test.ts +0 -143
  66. package/extensions/learning-loop/src/types.ts +0 -281
  67. package/extensions/learning-loop/symi.plugin.json +0 -46
  68. package/extensions/llm-task/README.md +0 -97
  69. package/extensions/llm-task/index.ts +0 -6
  70. package/extensions/llm-task/package.json +0 -12
  71. package/extensions/llm-task/src/llm-task-tool.test.ts +0 -138
  72. package/extensions/llm-task/src/llm-task-tool.ts +0 -249
  73. package/extensions/llm-task/symi.plugin.json +0 -21
  74. package/extensions/memory-lancedb/config.ts +0 -161
  75. package/extensions/memory-lancedb/index.test.ts +0 -330
  76. package/extensions/memory-lancedb/index.ts +0 -670
  77. package/extensions/memory-lancedb/node_modules/.bin/arrow2csv +0 -21
  78. package/extensions/memory-lancedb/node_modules/.bin/openai +0 -21
  79. package/extensions/memory-lancedb/node_modules/.bin/symi +0 -21
  80. package/extensions/memory-lancedb/package.json +0 -20
  81. package/extensions/memory-lancedb/symi.plugin.json +0 -71
  82. package/extensions/minimax-portal-auth/README.md +0 -33
  83. package/extensions/minimax-portal-auth/index.ts +0 -161
  84. package/extensions/minimax-portal-auth/node_modules/.bin/symi +0 -21
  85. package/extensions/minimax-portal-auth/oauth.ts +0 -247
  86. package/extensions/minimax-portal-auth/package.json +0 -15
  87. package/extensions/minimax-portal-auth/symi.plugin.json +0 -9
  88. package/extensions/model-equalizer/index.ts +0 -80
  89. package/extensions/model-equalizer/skills/model-equalizer/SKILL.md +0 -58
  90. package/extensions/model-equalizer/src/detection.ts +0 -62
  91. package/extensions/model-equalizer/src/enhancer.ts +0 -63
  92. package/extensions/model-equalizer/src/test/detection.test.ts +0 -218
  93. package/extensions/model-equalizer/src/test/enhancer.test.ts +0 -137
  94. package/extensions/model-equalizer/src/test/integration.test.ts +0 -185
  95. package/extensions/model-equalizer/src/types.ts +0 -24
  96. package/extensions/model-equalizer/symi.plugin.json +0 -12
  97. package/extensions/phone-control/index.ts +0 -421
  98. package/extensions/phone-control/symi.plugin.json +0 -10
  99. package/extensions/pipeline/README.md +0 -75
  100. package/extensions/pipeline/SKILL.md +0 -97
  101. package/extensions/pipeline/index.ts +0 -18
  102. package/extensions/pipeline/package.json +0 -11
  103. package/extensions/pipeline/src/pipeline-tool.test.ts +0 -345
  104. package/extensions/pipeline/src/pipeline-tool.ts +0 -266
  105. package/extensions/pipeline/src/windows-spawn.test.ts +0 -148
  106. package/extensions/pipeline/src/windows-spawn.ts +0 -193
  107. package/extensions/pipeline/symi.plugin.json +0 -10
  108. package/extensions/qwen-portal-auth/README.md +0 -24
  109. package/extensions/qwen-portal-auth/index.ts +0 -134
  110. package/extensions/qwen-portal-auth/oauth.ts +0 -190
  111. package/extensions/qwen-portal-auth/symi.plugin.json +0 -9
  112. package/extensions/talk-voice/index.ts +0 -150
  113. package/extensions/talk-voice/symi.plugin.json +0 -10
  114. package/extensions/thread-ownership/index.test.ts +0 -180
  115. package/extensions/thread-ownership/index.ts +0 -133
  116. package/extensions/thread-ownership/symi.plugin.json +0 -28
@@ -1,244 +0,0 @@
1
- /**
2
- * Hook registration for the learning loop plugin.
3
- *
4
- * | Priority | Hook | Role |
5
- * |----------|---------------------|-----------------------------------------|
6
- * | 200 | before_prompt_build | Inject learnings (runs first) |
7
- * | 100 | llm_input | Capture run start metadata |
8
- * | 100 | llm_output | Capture usage + response data |
9
- * | 100 | after_tool_call | Capture tool call traces |
10
- * | 100 | subagent_ended | Capture subagent outcomes |
11
- * | 50 | agent_end | Score run, extract learnings, persist |
12
- * | 50 | message_received | Detect implicit feedback |
13
- */
14
-
15
- import { hashText } from "../../../src/memory/internal.js";
16
- import type { SymiPluginApi, PluginLogger } from "../../../src/plugins/types.js";
17
- import type { MetricsAggregator } from "./analytics/metrics-aggregator.js";
18
- import type { RunTracker } from "./capture/run-tracker.js";
19
- import { normalizeCompletedRun, reconstructCompletedRun } from "./capture/serializer.js";
20
- import type { DatabaseManager } from "./db.js";
21
- import type { ImplicitSignals } from "./feedback/implicit-signals.js";
22
- import type { EdgeInference } from "./graph/edge-inference.js";
23
- import type { ContextInjector } from "./injection/context-injector.js";
24
- import type { LearningExtractor } from "./learning/learning-extractor.js";
25
- import type { LearningStore } from "./learning/learning-store.js";
26
- import type { QualityEngine } from "./scoring/quality-engine.js";
27
- import type { LearningLoopConfig } from "./types.js";
28
-
29
- export function registerHooks(
30
- api: SymiPluginApi,
31
- deps: {
32
- config: LearningLoopConfig;
33
- logger: PluginLogger;
34
- db: DatabaseManager;
35
- tracker: RunTracker;
36
- qualityEngine: QualityEngine;
37
- learningStore: LearningStore;
38
- extractor: LearningExtractor;
39
- injector: ContextInjector;
40
- metrics: MetricsAggregator;
41
- implicit: ImplicitSignals;
42
- edgeInference?: EdgeInference;
43
- },
44
- ) {
45
- const {
46
- config,
47
- logger,
48
- db,
49
- tracker,
50
- qualityEngine,
51
- learningStore,
52
- extractor,
53
- injector,
54
- metrics,
55
- implicit,
56
- edgeInference,
57
- } = deps;
58
-
59
- // -----------------------------------------------------------------------
60
- // before_prompt_build (priority 200) -- Inject learnings
61
- // -----------------------------------------------------------------------
62
- api.on(
63
- "before_prompt_build",
64
- async (event, ctx) => {
65
- try {
66
- const context = await injector.getContext(event.prompt);
67
- if (context) {
68
- return { prependContext: context };
69
- }
70
- } catch (err) {
71
- logger.warn(`[learning-loop] before_prompt_build failed: ${String(err)}`);
72
- }
73
- return undefined;
74
- },
75
- { priority: 200 },
76
- );
77
-
78
- // -----------------------------------------------------------------------
79
- // llm_input (priority 100) -- Capture run start metadata
80
- // -----------------------------------------------------------------------
81
- api.on(
82
- "llm_input",
83
- (event, ctx) => {
84
- try {
85
- tracker.onLlmInput({
86
- runId: event.runId,
87
- sessionId: event.sessionId,
88
- provider: event.provider,
89
- model: event.model,
90
- prompt: event.prompt,
91
- sessionKey: ctx.sessionKey,
92
- agentId: ctx.agentId,
93
- });
94
-
95
- // Record prompt for implicit feedback analysis
96
- implicit.recordPrompt(event.runId, event.prompt);
97
- } catch (err) {
98
- logger.warn(`[learning-loop] llm_input handler failed: ${String(err)}`);
99
- }
100
- },
101
- { priority: 100 },
102
- );
103
-
104
- // -----------------------------------------------------------------------
105
- // llm_output (priority 100) -- Capture usage + response data
106
- // -----------------------------------------------------------------------
107
- api.on(
108
- "llm_output",
109
- (event, ctx) => {
110
- try {
111
- tracker.onLlmOutput({
112
- runId: event.runId,
113
- sessionId: event.sessionId,
114
- assistantTexts: event.assistantTexts,
115
- usage: event.usage,
116
- });
117
- } catch (err) {
118
- logger.warn(`[learning-loop] llm_output handler failed: ${String(err)}`);
119
- }
120
- },
121
- { priority: 100 },
122
- );
123
-
124
- // -----------------------------------------------------------------------
125
- // after_tool_call (priority 100) -- Capture tool call traces
126
- // -----------------------------------------------------------------------
127
- api.on(
128
- "after_tool_call",
129
- (event, ctx) => {
130
- try {
131
- tracker.onToolCall({
132
- toolName: event.toolName,
133
- durationMs: event.durationMs,
134
- success: !event.error,
135
- error: event.error,
136
- paramHash: hashText(JSON.stringify(event.params)),
137
- sessionKey: ctx.sessionKey,
138
- });
139
- } catch (err) {
140
- logger.warn(`[learning-loop] after_tool_call handler failed: ${String(err)}`);
141
- }
142
- },
143
- { priority: 100 },
144
- );
145
-
146
- // -----------------------------------------------------------------------
147
- // subagent_ended (priority 100) -- Capture subagent outcomes
148
- // -----------------------------------------------------------------------
149
- api.on(
150
- "subagent_ended",
151
- (event, ctx) => {
152
- // Subagent outcomes are tracked as metadata; no separate storage needed.
153
- // The parent agent's agent_end will finalize the run.
154
- },
155
- { priority: 100 },
156
- );
157
-
158
- // -----------------------------------------------------------------------
159
- // agent_end (priority 50) -- Score run, extract learnings, persist
160
- // -----------------------------------------------------------------------
161
- api.on(
162
- "agent_end",
163
- async (event, ctx) => {
164
- try {
165
- const completedRaw = tracker.finalize({
166
- sessionKey: ctx.sessionKey,
167
- agentId: ctx.agentId,
168
- sessionId: ctx.sessionId,
169
- success: event.success,
170
- error: event.error,
171
- durationMs: event.durationMs,
172
- });
173
-
174
- if (!completedRaw) return;
175
-
176
- const completed = normalizeCompletedRun(completedRaw);
177
-
178
- // Score the run
179
- const score = qualityEngine.scoreRun(completed);
180
-
181
- // Persist run with score
182
- db.insertRun(completed, score);
183
-
184
- // Update metrics bucket
185
- metrics.recordRun(completed, score);
186
-
187
- // Track which learnings were injected into this run
188
- injector.trackRunAppliedIds(completed.runId);
189
- const appliedIds = injector.getAppliedIds(completed.runId);
190
-
191
- // Extract learnings (async: embeds content if bridge is available)
192
- const extractedIds = await extractor.extract(completed, score);
193
-
194
- // Infer graph edges from run scoring
195
- if (edgeInference) {
196
- edgeInference.onRunScored(completed.runId, appliedIds, extractedIds);
197
- }
198
-
199
- // Prune old runs if needed (learnings are preserved with run_id='__pruned__')
200
- db.pruneOldRuns(config.capture.maxRuns);
201
-
202
- // Prune genuinely stale learnings (unapplied, low-confidence, >90 days old)
203
- db.pruneStaleLearnings(90 * 24 * 60 * 60 * 1000);
204
-
205
- logger.debug?.(
206
- `[learning-loop] run ${completed.runId}: score=${score.score.toFixed(3)} ` +
207
- `(${completed.provider}/${completed.model}, ${completed.toolCalls.length} tool calls)`,
208
- );
209
- } catch (err) {
210
- logger.warn(`[learning-loop] agent_end handler failed: ${String(err)}`);
211
- }
212
- },
213
- { priority: 50 },
214
- );
215
-
216
- // -----------------------------------------------------------------------
217
- // message_received (priority 50) -- Detect implicit feedback
218
- // -----------------------------------------------------------------------
219
- api.on(
220
- "message_received",
221
- (event, ctx) => {
222
- try {
223
- const feedback = implicit.analyzeMessage(event.content, event.timestamp ?? Date.now());
224
-
225
- // Close the feedback loop: rescore the associated run
226
- if (feedback) {
227
- const runRow = db.getRun(feedback.runId);
228
- if (runRow) {
229
- const toolCalls = db.getToolCalls(feedback.runId);
230
- const completedRun = reconstructCompletedRun(runRow, toolCalls);
231
- const newScore = qualityEngine.rescoreWithFeedback(completedRun, {
232
- source: feedback.source as "explicit" | "implicit",
233
- score: feedback.score,
234
- });
235
- db.updateRunScore(feedback.runId, newScore.score);
236
- }
237
- }
238
- } catch (err) {
239
- logger.warn(`[learning-loop] message_received handler failed: ${String(err)}`);
240
- }
241
- },
242
- { priority: 50 },
243
- );
244
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * LRU cache for context injection results.
3
- * Target: >85% hit rate, O(1) lookup.
4
- */
5
-
6
- export type CacheEntry<T> = {
7
- value: T;
8
- expiresAt: number;
9
- };
10
-
11
- export type LRUCache<T> = ReturnType<typeof createLRUCache<T>>;
12
-
13
- export function createLRUCache<T>(maxSize: number = 128, ttlMs: number = 60_000) {
14
- const cache = new Map<string, CacheEntry<T>>();
15
- let hits = 0;
16
- let misses = 0;
17
-
18
- function get(key: string): T | undefined {
19
- const entry = cache.get(key);
20
- if (!entry) {
21
- misses++;
22
- return undefined;
23
- }
24
-
25
- if (Date.now() > entry.expiresAt) {
26
- cache.delete(key);
27
- misses++;
28
- return undefined;
29
- }
30
-
31
- // Move to end (most recently used) by re-inserting
32
- cache.delete(key);
33
- cache.set(key, entry);
34
- hits++;
35
- return entry.value;
36
- }
37
-
38
- function set(key: string, value: T): void {
39
- // Evict oldest if at capacity
40
- if (cache.size >= maxSize) {
41
- const oldest = cache.keys().next().value;
42
- if (oldest !== undefined) {
43
- cache.delete(oldest);
44
- }
45
- }
46
-
47
- cache.set(key, {
48
- value,
49
- expiresAt: Date.now() + ttlMs,
50
- });
51
- }
52
-
53
- function invalidate(key: string): void {
54
- cache.delete(key);
55
- }
56
-
57
- function clear(): void {
58
- cache.clear();
59
- hits = 0;
60
- misses = 0;
61
- }
62
-
63
- function getHitRate(): number {
64
- const total = hits + misses;
65
- return total === 0 ? 0 : hits / total;
66
- }
67
-
68
- function getStats(): { size: number; hits: number; misses: number; hitRate: number } {
69
- return { size: cache.size, hits, misses, hitRate: getHitRate() };
70
- }
71
-
72
- return { get, set, invalidate, clear, getHitRate, getStats };
73
- }
@@ -1,104 +0,0 @@
1
- /**
2
- * Context injection for before_prompt_build hook.
3
- *
4
- * On each prompt build:
5
- * 1. Hash prompt -> check LRU cache (target >85% hit rate, O(1))
6
- * 2. Cache miss: query learnings via cosine similarity or FTS5 fallback
7
- * 3. Apply temporal decay and MMR rerank for diversity
8
- * 4. Format top N as <learnings> context block
9
- * 5. Return { prependContext }
10
- */
11
-
12
- import { hashText } from "../../../../src/memory/internal.js";
13
- import type { DatabaseManager } from "../db.js";
14
- import type { GraphRetrieval } from "../graph/graph-retrieval.js";
15
- import type { EmbeddingBridge } from "../learning/embedding-bridge.js";
16
- import type { LearningStore } from "../learning/learning-store.js";
17
- import { retrieveLearnings, type RetrievalResult } from "../learning/retrieval.js";
18
- import type { LearningLoopConfig, RunId } from "../types.js";
19
- import { createLRUCache } from "./cache.js";
20
- import { formatLearningsContext } from "./prompt-builder.js";
21
-
22
- export type ContextInjector = ReturnType<typeof createContextInjector>;
23
-
24
- export function createContextInjector(params: {
25
- db: DatabaseManager;
26
- learningStore: LearningStore;
27
- config: LearningLoopConfig;
28
- embeddingBridge?: EmbeddingBridge;
29
- graphRetrieval?: GraphRetrieval;
30
- }) {
31
- const { db, learningStore, config, embeddingBridge, graphRetrieval } = params;
32
- const cache = createLRUCache<string>(128, config.injection.cacheTtlMs);
33
- const appliedIdsMap = new Map<RunId, string[]>();
34
- let lastAppliedIds: string[] = [];
35
-
36
- /**
37
- * Generate context to prepend to the agent prompt.
38
- * Returns empty string if no relevant learnings exist.
39
- */
40
- async function getContext(prompt: string): Promise<string> {
41
- const promptKey = hashText(prompt);
42
-
43
- // Check cache first
44
- const cached = cache.get(promptKey);
45
- if (cached !== undefined) return cached;
46
-
47
- // Get query embedding if bridge is available
48
- let queryEmbedding: number[] | null = null;
49
- if (embeddingBridge?.available()) {
50
- queryEmbedding = await embeddingBridge.embed(prompt);
51
- }
52
-
53
- // Retrieve relevant learnings
54
- const results = retrieveLearnings({
55
- learningStore,
56
- config,
57
- queryEmbedding,
58
- queryText: prompt,
59
- graphRetrieval,
60
- });
61
-
62
- // Record applications and track applied IDs
63
- const appliedIds: string[] = [];
64
- for (const result of results) {
65
- learningStore.recordApplication(result.learning.id);
66
- appliedIds.push(result.learning.id);
67
- }
68
- lastAppliedIds = appliedIds;
69
-
70
- // Format context
71
- const context = formatLearningsContext(results, config);
72
-
73
- // Cache result
74
- cache.set(promptKey, context);
75
-
76
- return context;
77
- }
78
-
79
- /**
80
- * Associate the most recently injected learning IDs with a run ID.
81
- */
82
- function trackRunAppliedIds(runId: RunId): void {
83
- if (lastAppliedIds.length > 0) {
84
- appliedIdsMap.set(runId, [...lastAppliedIds]);
85
- }
86
- }
87
-
88
- /**
89
- * Get the learning IDs that were injected into a specific run.
90
- */
91
- function getAppliedIds(runId: RunId): string[] {
92
- return appliedIdsMap.get(runId) ?? [];
93
- }
94
-
95
- function getCacheStats() {
96
- return cache.getStats();
97
- }
98
-
99
- function clearCache(): void {
100
- cache.clear();
101
- }
102
-
103
- return { getContext, trackRunAppliedIds, getAppliedIds, getCacheStats, clearCache };
104
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * Format retrieved learnings into context text for prompt injection.
3
- */
4
-
5
- import type { RetrievalResult } from "../learning/retrieval.js";
6
- import type { LearningLoopConfig } from "../types.js";
7
-
8
- /**
9
- * Format learnings into a context block that will be prepended to the agent prompt.
10
- *
11
- * Respects maxTokens by estimating token count (chars / 4) and truncating.
12
- * Returns empty string if no learnings pass the threshold.
13
- */
14
- export function formatLearningsContext(
15
- results: RetrievalResult[],
16
- config: LearningLoopConfig,
17
- ): string {
18
- if (results.length === 0) return "";
19
-
20
- const maxTokens = config.injection.maxTokens;
21
- const lines: string[] = [];
22
- let estimatedTokens = 0;
23
-
24
- // Header
25
- const header = "<learnings>";
26
- const footer = "</learnings>";
27
- estimatedTokens += (header.length + footer.length) / 4;
28
-
29
- for (const result of results) {
30
- const contested = result.contested ? " [CONTESTED]" : "";
31
- const line = `- [${result.learning.category}] ${result.learning.content}${contested}`;
32
- const lineTokens = line.length / 4;
33
-
34
- if (estimatedTokens + lineTokens > maxTokens) break;
35
-
36
- lines.push(line);
37
- estimatedTokens += lineTokens;
38
- }
39
-
40
- if (lines.length === 0) return "";
41
-
42
- return `${header}\n${lines.join("\n")}\n${footer}`;
43
- }
@@ -1,54 +0,0 @@
1
- /**
2
- * Bridge to the existing embedding provider system.
3
- * Uses the same multi-provider system (OpenAI, Gemini, Voyage, local ONNX)
4
- * that the memory system uses.
5
- */
6
-
7
- import type { EmbeddingProvider } from "../../../../src/memory/embeddings.js";
8
- import type { PluginLogger } from "../../../../src/plugins/types.js";
9
-
10
- export type EmbeddingBridge = {
11
- embed: (text: string) => Promise<number[] | null>;
12
- embedBatch: (texts: string[]) => Promise<Array<number[] | null>>;
13
- available: () => boolean;
14
- };
15
-
16
- /**
17
- * Create an embedding bridge that wraps an existing EmbeddingProvider.
18
- * If no provider is available, embed() returns null gracefully.
19
- */
20
- export function createEmbeddingBridge(params: {
21
- provider: EmbeddingProvider | null;
22
- logger: PluginLogger;
23
- }): EmbeddingBridge {
24
- const { provider, logger } = params;
25
-
26
- async function embed(text: string): Promise<number[] | null> {
27
- if (!provider) return null;
28
-
29
- try {
30
- return await provider.embedQuery(text);
31
- } catch (err) {
32
- logger.warn(`[learning-loop] embedding failed: ${String(err)}`);
33
- return null;
34
- }
35
- }
36
-
37
- async function embedBatch(texts: string[]): Promise<Array<number[] | null>> {
38
- if (!provider) return texts.map(() => null);
39
-
40
- try {
41
- const results = await provider.embedBatch(texts);
42
- return results;
43
- } catch (err) {
44
- logger.warn(`[learning-loop] batch embedding failed: ${String(err)}`);
45
- return texts.map(() => null);
46
- }
47
- }
48
-
49
- function available(): boolean {
50
- return provider !== null;
51
- }
52
-
53
- return { embed, embedBatch, available };
54
- }