claude-memory-layer 1.0.31 → 1.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/cli/index.js +1110 -72
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +414 -25
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +416 -27
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +416 -27
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +416 -27
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +416 -27
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +416 -27
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +504 -34
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +416 -27
- package/dist/index.js.map +2 -2
- package/dist/mcp/index.js +407 -32
- package/dist/mcp/index.js.map +2 -2
- package/dist/server/api/index.js +850 -44
- package/dist/server/api/index.js.map +3 -3
- package/dist/server/index.js +1073 -64
- package/dist/server/index.js.map +3 -3
- package/dist/services/memory-service.js +416 -27
- package/dist/services/memory-service.js.map +2 -2
- package/dist/ui/assets/js/bootstrap.js +2 -0
- package/dist/ui/assets/js/overview.js +166 -3
- package/dist/ui/assets/js/state.js +3 -0
- package/dist/ui/index.html +20 -0
- package/dist/ui/style.css +193 -0
- package/package.json +15 -2
- package/scripts/postinstall-embedding-backend.cjs +16 -12
- package/AGENTS.md +0 -71
- package/CLAUDE.md +0 -30
- package/HANDOFF.md +0 -92
- package/Memo.txt +0 -558
- package/benchmarks/replay/anonymized-real-sessions.json +0 -48
- package/config/kpi-thresholds.json +0 -7
- package/context.md +0 -636
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +0 -627
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +0 -440
- package/docs/MCP_MEMORY_SERVICE_COMPARATIVE_REVIEW.md +0 -271
- package/docs/MEMORY_USEFULNESS_AUDIT.md +0 -371
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +0 -80
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +0 -333
- package/docs/MEMU_ADOPTION.md +0 -40
- package/docs/OPERATIONS.md +0 -18
- package/docs/PRODUCT_VALIDATION_MATRIX.md +0 -82
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +0 -421
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +0 -501
- package/docs/REFACTORING_PLAN_THIN_CORE.md +0 -414
- package/docs/REFERENCE_PROJECT_ANALYSES.md +0 -25
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +0 -452
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +0 -446
- package/docs/architecture/comparison-index.md +0 -47
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +0 -46
- package/plan.md +0 -1642
- package/scripts/build.ts +0 -159
- package/scripts/bump-patch-version.sh +0 -18
- package/scripts/delete-unknown-projects.js +0 -154
- package/scripts/fix-sync-gap.js +0 -32
- package/scripts/generate-session-qrels.ts +0 -126
- package/scripts/heartbeat-memory-orchestrator.sh +0 -28
- package/scripts/replay-retrieval-benchmark.ts +0 -69
- package/scripts/report-sync-gap.js +0 -26
- package/scripts/review-queue-auto-resolve.js +0 -21
- package/scripts/sync-gap-auto-heal.sh +0 -17
- package/spec.md +0 -624
- package/specs/20260207-dashboard-upgrade/context.md +0 -38
- package/specs/20260207-dashboard-upgrade/spec.md +0 -96
- package/specs/citations-system/context.md +0 -243
- package/specs/citations-system/plan.md +0 -495
- package/specs/citations-system/spec.md +0 -371
- package/specs/endless-mode/context.md +0 -305
- package/specs/endless-mode/plan.md +0 -620
- package/specs/endless-mode/spec.md +0 -455
- package/specs/entity-edge-model/context.md +0 -401
- package/specs/entity-edge-model/plan.md +0 -459
- package/specs/entity-edge-model/spec.md +0 -391
- package/specs/evidence-aligner-v2/context.md +0 -401
- package/specs/evidence-aligner-v2/plan.md +0 -303
- package/specs/evidence-aligner-v2/spec.md +0 -312
- package/specs/mcp-desktop-integration/context.md +0 -278
- package/specs/mcp-desktop-integration/plan.md +0 -550
- package/specs/mcp-desktop-integration/spec.md +0 -494
- package/specs/memory-utilization-improvements/context.md +0 -145
- package/specs/memory-utilization-improvements/plan.md +0 -361
- package/specs/memory-utilization-improvements/spec.md +0 -361
- package/specs/post-tool-use-hook/context.md +0 -319
- package/specs/post-tool-use-hook/plan.md +0 -469
- package/specs/post-tool-use-hook/spec.md +0 -364
- package/specs/private-tags/context.md +0 -288
- package/specs/private-tags/plan.md +0 -412
- package/specs/private-tags/spec.md +0 -345
- package/specs/progressive-disclosure/context.md +0 -346
- package/specs/progressive-disclosure/plan.md +0 -663
- package/specs/progressive-disclosure/spec.md +0 -415
- package/specs/selective-tool-observation/context.md +0 -100
- package/specs/selective-tool-observation/plan.md +0 -158
- package/specs/selective-tool-observation/spec.md +0 -127
- package/specs/task-entity-system/context.md +0 -297
- package/specs/task-entity-system/plan.md +0 -301
- package/specs/task-entity-system/spec.md +0 -314
- package/specs/thin-core-refactor/context.md +0 -275
- package/specs/thin-core-refactor/plan.md +0 -536
- package/specs/thin-core-refactor/spec.md +0 -465
- package/specs/vector-outbox-v2/context.md +0 -470
- package/specs/vector-outbox-v2/plan.md +0 -562
- package/specs/vector-outbox-v2/spec.md +0 -466
- package/specs/web-viewer-ui/context.md +0 -384
- package/specs/web-viewer-ui/plan.md +0 -797
- package/specs/web-viewer-ui/spec.md +0 -516
- package/src/adapters/claude/capture/index.ts +0 -3
- package/src/adapters/claude/context/index.ts +0 -3
- package/src/adapters/claude/hooks/index.ts +0 -21
- package/src/adapters/claude/hooks/post-tool-use.ts +0 -239
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +0 -104
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +0 -209
- package/src/adapters/claude/hooks/semantic-daemon.ts +0 -283
- package/src/adapters/claude/hooks/session-end.ts +0 -59
- package/src/adapters/claude/hooks/session-start.ts +0 -73
- package/src/adapters/claude/hooks/stop.ts +0 -128
- package/src/adapters/claude/hooks/user-prompt-submit.ts +0 -361
- package/src/adapters/claude/index.ts +0 -4
- package/src/adapters/claude/transcript/index.ts +0 -4
- package/src/adapters/claude/transcript/transcript-reader.ts +0 -57
- package/src/adapters/claude/transcript/turn-reconstructor.ts +0 -65
- package/src/apps/cli/claude-settings-hooks.ts +0 -138
- package/src/apps/cli/codex-import-runner.ts +0 -125
- package/src/apps/cli/codex-validation-output.ts +0 -95
- package/src/apps/cli/hermes-import-runner.ts +0 -130
- package/src/apps/cli/hermes-validation-output.ts +0 -91
- package/src/apps/cli/index.ts +0 -1735
- package/src/apps/cli/mcp-install.ts +0 -106
- package/src/apps/cli/retrieval-disclosure-output.ts +0 -196
- package/src/apps/dashboard/assets/js/bootstrap.js +0 -244
- package/src/apps/dashboard/assets/js/chat.js +0 -373
- package/src/apps/dashboard/assets/js/disclosure.js +0 -232
- package/src/apps/dashboard/assets/js/modals.js +0 -298
- package/src/apps/dashboard/assets/js/overview.js +0 -655
- package/src/apps/dashboard/assets/js/state.js +0 -72
- package/src/apps/dashboard/assets/js/views.js +0 -468
- package/src/apps/dashboard/index.html +0 -543
- package/src/apps/dashboard/index.ts +0 -3
- package/src/apps/dashboard/style.css +0 -1750
- package/src/apps/index.ts +0 -5
- package/src/apps/server/api/chat.ts +0 -244
- package/src/apps/server/api/citations.ts +0 -105
- package/src/apps/server/api/events.ts +0 -137
- package/src/apps/server/api/health.ts +0 -53
- package/src/apps/server/api/index.ts +0 -26
- package/src/apps/server/api/projects.ts +0 -74
- package/src/apps/server/api/search.ts +0 -184
- package/src/apps/server/api/sessions.ts +0 -115
- package/src/apps/server/api/stats.ts +0 -723
- package/src/apps/server/api/turns.ts +0 -143
- package/src/apps/server/api/utils.ts +0 -65
- package/src/apps/server/index.ts +0 -111
- package/src/cli/index.ts +0 -3
- package/src/cli/retrieval-disclosure-output.ts +0 -2
- package/src/compat/index.ts +0 -5
- package/src/core/canonical-key.ts +0 -186
- package/src/core/citation-generator.ts +0 -63
- package/src/core/consolidated-store.ts +0 -356
- package/src/core/consolidation-worker.ts +0 -493
- package/src/core/context-formatter.ts +0 -276
- package/src/core/continuity-manager.ts +0 -341
- package/src/core/db-wrapper.ts +0 -64
- package/src/core/derive/fact-deriver.ts +0 -170
- package/src/core/derive/index.ts +0 -2
- package/src/core/derive/summary-deriver.ts +0 -76
- package/src/core/edge-repo.ts +0 -333
- package/src/core/embedder.ts +0 -4
- package/src/core/engine/embedding-maintenance-service.ts +0 -187
- package/src/core/engine/endless-memory-services.ts +0 -4
- package/src/core/engine/index.ts +0 -19
- package/src/core/engine/memory-engine-services.ts +0 -170
- package/src/core/engine/memory-ingest-service.ts +0 -317
- package/src/core/engine/memory-query-service.ts +0 -173
- package/src/core/engine/memory-runtime-service.ts +0 -162
- package/src/core/engine/memory-service-composition.ts +0 -231
- package/src/core/engine/retrieval-analytics-service.ts +0 -181
- package/src/core/engine/retrieval-disclosure-service.ts +0 -420
- package/src/core/engine/retrieval-orchestrator.ts +0 -377
- package/src/core/engine/retrieval-services.ts +0 -176
- package/src/core/engine/shared-memory-services.ts +0 -4
- package/src/core/entity-repo.ts +0 -349
- package/src/core/event-store.ts +0 -779
- package/src/core/evidence-aligner.ts +0 -635
- package/src/core/external-market-context.ts +0 -582
- package/src/core/graduation-worker.ts +0 -171
- package/src/core/graduation.ts +0 -377
- package/src/core/index.ts +0 -64
- package/src/core/ingest-interceptor.ts +0 -80
- package/src/core/markdown-mirror.ts +0 -70
- package/src/core/matcher.ts +0 -208
- package/src/core/md-mirror.ts +0 -92
- package/src/core/metadata-extractor.ts +0 -203
- package/src/core/model/memory-fact.ts +0 -30
- package/src/core/model/memory-rule.ts +0 -14
- package/src/core/model/memory-summary.ts +0 -21
- package/src/core/model/raw-event.ts +0 -28
- package/src/core/model/retrieval-result.ts +0 -35
- package/src/core/mongo-sync-config.ts +0 -165
- package/src/core/mongo-sync-worker.ts +0 -381
- package/src/core/privacy/filter.ts +0 -190
- package/src/core/privacy/index.ts +0 -20
- package/src/core/privacy/tag-parser.ts +0 -145
- package/src/core/product-validation-matrix.ts +0 -314
- package/src/core/progressive-retriever.ts +0 -414
- package/src/core/registry/project-path.ts +0 -54
- package/src/core/registry/session-registry.ts +0 -69
- package/src/core/replay-evaluator.ts +0 -625
- package/src/core/retrieval-benchmark.ts +0 -117
- package/src/core/retrieval-quality.ts +0 -109
- package/src/core/retriever.ts +0 -800
- package/src/core/session-qrels.ts +0 -360
- package/src/core/shared-event-store.ts +0 -114
- package/src/core/shared-promoter.ts +0 -249
- package/src/core/shared-store.ts +0 -289
- package/src/core/shared-vector-store.ts +0 -203
- package/src/core/sqlite-event-store.ts +0 -1846
- package/src/core/sqlite-wrapper.ts +0 -116
- package/src/core/sync-worker.ts +0 -228
- package/src/core/tag-taxonomy.ts +0 -51
- package/src/core/task/blocker-resolver.ts +0 -333
- package/src/core/task/index.ts +0 -9
- package/src/core/task/task-matcher.ts +0 -240
- package/src/core/task/task-projector.ts +0 -358
- package/src/core/task/task-resolver.ts +0 -421
- package/src/core/turn-state.ts +0 -207
- package/src/core/types.ts +0 -952
- package/src/core/vector-outbox.ts +0 -299
- package/src/core/vector-store.ts +0 -231
- package/src/core/vector-worker.ts +0 -521
- package/src/core/working-set-store.ts +0 -257
- package/src/extensions/endless-memory/endless-memory-services.ts +0 -350
- package/src/extensions/endless-memory/index.ts +0 -1
- package/src/extensions/index.ts +0 -5
- package/src/extensions/mcp/handlers.ts +0 -960
- package/src/extensions/mcp/index.ts +0 -48
- package/src/extensions/mcp/tools.ts +0 -252
- package/src/extensions/shared-memory/index.ts +0 -1
- package/src/extensions/shared-memory/shared-memory-services.ts +0 -211
- package/src/extensions/vector/embedder.ts +0 -234
- package/src/extensions/vector/index.ts +0 -1
- package/src/hooks/post-tool-use.ts +0 -9
- package/src/hooks/semantic-daemon-client.ts +0 -1
- package/src/hooks/semantic-daemon.ts +0 -11
- package/src/hooks/session-end.ts +0 -9
- package/src/hooks/session-start.ts +0 -9
- package/src/hooks/stop.ts +0 -9
- package/src/hooks/user-prompt-submit.ts +0 -9
- package/src/index.ts +0 -13
- package/src/mcp/handlers.ts +0 -2
- package/src/mcp/index.ts +0 -4
- package/src/mcp/tools.ts +0 -2
- package/src/server/api/chat.ts +0 -2
- package/src/server/api/citations.ts +0 -2
- package/src/server/api/events.ts +0 -2
- package/src/server/api/health.ts +0 -2
- package/src/server/api/index.ts +0 -2
- package/src/server/api/projects.ts +0 -2
- package/src/server/api/search.ts +0 -2
- package/src/server/api/sessions.ts +0 -2
- package/src/server/api/stats.ts +0 -2
- package/src/server/api/turns.ts +0 -2
- package/src/server/api/utils.ts +0 -2
- package/src/server/index.ts +0 -2
- package/src/services/bootstrap-organizer.ts +0 -463
- package/src/services/codex-session-history-importer.ts +0 -966
- package/src/services/hermes-session-history-importer.ts +0 -733
- package/src/services/memory-service-config.ts +0 -36
- package/src/services/memory-service-registry.ts +0 -150
- package/src/services/memory-service.ts +0 -688
- package/src/services/session-history-importer.ts +0 -629
- package/tests/README.md +0 -23
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +0 -54
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +0 -98
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +0 -99
- package/tests/apps/app-layer-boundary.test.ts +0 -48
- package/tests/apps/claude-settings-hooks.test.ts +0 -107
- package/tests/apps/cli-disclosure-output.test.ts +0 -212
- package/tests/apps/codex-import-runner.test.ts +0 -99
- package/tests/apps/codex-validation-output.test.ts +0 -100
- package/tests/apps/hermes-import-runner.test.ts +0 -99
- package/tests/apps/mcp-install-command.test.ts +0 -59
- package/tests/apps/package-build-entrypoints.test.ts +0 -30
- package/tests/apps/postinstall-embedding-backend.test.ts +0 -185
- package/tests/apps/search-api-disclosure.test.ts +0 -162
- package/tests/apps/stats-api-lightweight.test.ts +0 -67
- package/tests/apps/ui-disclosure-output.test.ts +0 -140
- package/tests/core/bootstrap-organizer.test.ts +0 -111
- package/tests/core/canonical-key.test.ts +0 -101
- package/tests/core/codex-session-history-importer-validation.test.ts +0 -185
- package/tests/core/consolidation-worker.test.ts +0 -75
- package/tests/core/embedding-maintenance-service.test.ts +0 -282
- package/tests/core/evidence-aligner.test.ts +0 -152
- package/tests/core/external-market-context.test.ts +0 -209
- package/tests/core/fact-deriver.test.ts +0 -79
- package/tests/core/hermes-session-history-importer-validation.test.ts +0 -609
- package/tests/core/ingest-interceptor.test.ts +0 -38
- package/tests/core/markdown-mirror.test.ts +0 -85
- package/tests/core/matcher.test.ts +0 -112
- package/tests/core/md-mirror.test.ts +0 -50
- package/tests/core/memory-engine-services.test.ts +0 -240
- package/tests/core/memory-ingest-service.test.ts +0 -296
- package/tests/core/memory-query-service.test.ts +0 -129
- package/tests/core/memory-runtime-service.test.ts +0 -201
- package/tests/core/memory-service-composition.test.ts +0 -192
- package/tests/core/memory-service-config.test.ts +0 -41
- package/tests/core/memory-service-facade.test.ts +0 -30
- package/tests/core/memory-service-registry.test.ts +0 -206
- package/tests/core/product-validation-matrix.test.ts +0 -61
- package/tests/core/project-registry.test.ts +0 -78
- package/tests/core/replay-evaluator.test.ts +0 -181
- package/tests/core/retrieval-analytics-service.test.ts +0 -210
- package/tests/core/retrieval-benchmark.test.ts +0 -93
- package/tests/core/retrieval-disclosure-service.test.ts +0 -264
- package/tests/core/retrieval-orchestrator.test.ts +0 -403
- package/tests/core/retrieval-quality.test.ts +0 -31
- package/tests/core/retrieval-services.test.ts +0 -185
- package/tests/core/retriever-fallback-chain.test.ts +0 -223
- package/tests/core/retriever-strategy-scope.test.ts +0 -164
- package/tests/core/retriever.memu-adoption.test.ts +0 -122
- package/tests/core/session-history-importer-filter.test.ts +0 -78
- package/tests/core/session-qrels.test.ts +0 -250
- package/tests/core/sqlite-event-store-replication.test.ts +0 -127
- package/tests/core/summary-deriver.test.ts +0 -66
- package/tests/extensions/embedder-warning-suppression.test.ts +0 -84
- package/tests/extensions/endless-memory-extension-boundary.test.ts +0 -17
- package/tests/extensions/endless-memory-services.test.ts +0 -325
- package/tests/extensions/mcp-context-tools.test.ts +0 -905
- package/tests/extensions/mcp-extension-boundary.test.ts +0 -21
- package/tests/extensions/mcp-package-build.test.ts +0 -22
- package/tests/extensions/mcp-project-aware-tools.test.ts +0 -102
- package/tests/extensions/shared-memory-extension-boundary.test.ts +0 -24
- package/tests/extensions/shared-memory-services.test.ts +0 -309
- package/tests/extensions/vector-extension-boundary.test.ts +0 -21
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -15
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context Formatter
|
|
3
|
-
* Formats progressive search results for Claude context injection
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ProgressiveSearchResult,
|
|
8
|
-
SearchIndexItem,
|
|
9
|
-
TimelineItem,
|
|
10
|
-
FullDetail,
|
|
11
|
-
CitedSearchResult
|
|
12
|
-
} from './types.js';
|
|
13
|
-
import { formatCitationId } from './citation-generator.js';
|
|
14
|
-
|
|
15
|
-
export interface FormatOptions {
|
|
16
|
-
format?: 'inline' | 'footnote' | 'reference';
|
|
17
|
-
showTokens?: boolean;
|
|
18
|
-
maxWidth?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class ContextFormatter {
|
|
22
|
-
/**
|
|
23
|
-
* Format progressive search result for Claude context
|
|
24
|
-
*/
|
|
25
|
-
formatProgressiveResult(
|
|
26
|
-
result: ProgressiveSearchResult,
|
|
27
|
-
options?: FormatOptions
|
|
28
|
-
): string {
|
|
29
|
-
const parts: string[] = [];
|
|
30
|
-
|
|
31
|
-
// Layer 1: Always included (index)
|
|
32
|
-
parts.push(this.formatLayer1(result.index));
|
|
33
|
-
|
|
34
|
-
// Layer 2: Timeline (if expanded)
|
|
35
|
-
if (result.timeline && result.timeline.length > 0) {
|
|
36
|
-
parts.push(this.formatLayer2(result.timeline));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Layer 3: Details (if expanded)
|
|
40
|
-
if (result.details && result.details.length > 0) {
|
|
41
|
-
parts.push(this.formatLayer3(result.details, options));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Meta information
|
|
45
|
-
if (options?.showTokens !== false) {
|
|
46
|
-
parts.push(this.formatMeta(result.meta));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return parts.join('\n\n');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Format Layer 1: Search Index
|
|
54
|
-
*/
|
|
55
|
-
private formatLayer1(items: SearchIndexItem[]): string {
|
|
56
|
-
if (items.length === 0) {
|
|
57
|
-
return '## Related Memories\n\nNo relevant memories found.';
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const header = `## Related Memories (${items.length} matches)\n`;
|
|
61
|
-
const rows = items.map((item, i) => {
|
|
62
|
-
const date = item.timestamp.toISOString().split('T')[0];
|
|
63
|
-
return `${i + 1}. **[${item.id.slice(0, 8)}]** ${item.summary} _(${date}, score: ${item.score.toFixed(2)})_`;
|
|
64
|
-
}).join('\n');
|
|
65
|
-
|
|
66
|
-
return header + rows;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Format Layer 2: Timeline
|
|
71
|
-
*/
|
|
72
|
-
private formatLayer2(items: TimelineItem[]): string {
|
|
73
|
-
const header = '## Timeline Context\n';
|
|
74
|
-
const timeline = items.map(item => {
|
|
75
|
-
const marker = item.isTarget ? '**→**' : ' ';
|
|
76
|
-
const time = item.timestamp.toLocaleTimeString('en-US', {
|
|
77
|
-
hour: '2-digit',
|
|
78
|
-
minute: '2-digit'
|
|
79
|
-
});
|
|
80
|
-
const typeIcon = this.getTypeIcon(item.type);
|
|
81
|
-
return `${marker} ${time} ${typeIcon} ${item.preview}`;
|
|
82
|
-
}).join('\n');
|
|
83
|
-
|
|
84
|
-
return header + timeline;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Format Layer 3: Full Details
|
|
89
|
-
*/
|
|
90
|
-
private formatLayer3(items: FullDetail[], options?: FormatOptions): string {
|
|
91
|
-
const format = options?.format ?? 'inline';
|
|
92
|
-
|
|
93
|
-
switch (format) {
|
|
94
|
-
case 'inline':
|
|
95
|
-
return this.formatDetailsInline(items);
|
|
96
|
-
case 'footnote':
|
|
97
|
-
return this.formatDetailsFootnote(items);
|
|
98
|
-
case 'reference':
|
|
99
|
-
return this.formatDetailsReference(items);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Inline format for details
|
|
105
|
-
*/
|
|
106
|
-
private formatDetailsInline(items: FullDetail[]): string {
|
|
107
|
-
return items.map(item => {
|
|
108
|
-
const date = item.timestamp.toLocaleDateString();
|
|
109
|
-
const session = item.sessionId.slice(0, 8);
|
|
110
|
-
const citation = item.citationId ? formatCitationId(item.citationId) : '';
|
|
111
|
-
|
|
112
|
-
const header = `## Detail: ${item.id.slice(0, 8)}`;
|
|
113
|
-
const meta = `_${item.type} | Session: ${session} | ${date}_`;
|
|
114
|
-
const content = item.content;
|
|
115
|
-
const footer = citation ? `\n${citation}` : '';
|
|
116
|
-
|
|
117
|
-
return [header, meta, '', content, footer].join('\n');
|
|
118
|
-
}).join('\n\n---\n\n');
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Footnote format for details
|
|
123
|
-
*/
|
|
124
|
-
private formatDetailsFootnote(items: FullDetail[]): string {
|
|
125
|
-
const content = items.map((item, i) => {
|
|
126
|
-
return `${item.content} [${i + 1}]`;
|
|
127
|
-
}).join('\n\n');
|
|
128
|
-
|
|
129
|
-
const footnotes = items.map((item, i) => {
|
|
130
|
-
const citation = item.citationId ? formatCitationId(item.citationId) : `[${item.id.slice(0, 8)}]`;
|
|
131
|
-
const date = item.timestamp.toLocaleDateString();
|
|
132
|
-
return `[${i + 1}] ${citation} - ${date}`;
|
|
133
|
-
}).join('\n');
|
|
134
|
-
|
|
135
|
-
return `${content}\n\n---\n**References:**\n${footnotes}`;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Reference format for details
|
|
140
|
-
*/
|
|
141
|
-
private formatDetailsReference(items: FullDetail[]): string {
|
|
142
|
-
const content = items.map(item => {
|
|
143
|
-
return `### ${item.type}\n${item.content}`;
|
|
144
|
-
}).join('\n\n');
|
|
145
|
-
|
|
146
|
-
const references = items.map(item => {
|
|
147
|
-
const citation = item.citationId ? formatCitationId(item.citationId) : `[${item.id.slice(0, 8)}]`;
|
|
148
|
-
const date = item.timestamp.toLocaleDateString();
|
|
149
|
-
return `- ${citation} Session ${item.sessionId.slice(0, 8)}, ${date}`;
|
|
150
|
-
}).join('\n');
|
|
151
|
-
|
|
152
|
-
return `## Content\n\n${content}\n\n## References\n${references}`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Format meta information
|
|
157
|
-
*/
|
|
158
|
-
private formatMeta(meta: ProgressiveSearchResult['meta']): string {
|
|
159
|
-
const parts: string[] = [];
|
|
160
|
-
|
|
161
|
-
if (meta.expansionReason) {
|
|
162
|
-
const reasonText = this.getExpansionReasonText(meta.expansionReason);
|
|
163
|
-
parts.push(`_${reasonText}_`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
parts.push(`_~${meta.estimatedTokens} tokens | ${meta.expandedCount} expanded_`);
|
|
167
|
-
|
|
168
|
-
return parts.join(' | ');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Get icon for event type
|
|
173
|
-
*/
|
|
174
|
-
private getTypeIcon(type: string): string {
|
|
175
|
-
switch (type) {
|
|
176
|
-
case 'user_prompt':
|
|
177
|
-
return '👤';
|
|
178
|
-
case 'agent_response':
|
|
179
|
-
return '🤖';
|
|
180
|
-
case 'session_summary':
|
|
181
|
-
return '📋';
|
|
182
|
-
case 'tool_observation':
|
|
183
|
-
return '🔧';
|
|
184
|
-
default:
|
|
185
|
-
return '📄';
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Get human-readable expansion reason
|
|
191
|
-
*/
|
|
192
|
-
private getExpansionReasonText(reason: string): string {
|
|
193
|
-
switch (reason) {
|
|
194
|
-
case 'high_confidence_single':
|
|
195
|
-
return 'High confidence match - auto-expanded';
|
|
196
|
-
case 'clear_winner':
|
|
197
|
-
return 'Clear best match found';
|
|
198
|
-
case 'ambiguous_multiple_high':
|
|
199
|
-
return 'Multiple relevant results - showing timeline';
|
|
200
|
-
case 'low_confidence':
|
|
201
|
-
return 'No high confidence matches';
|
|
202
|
-
case 'no_results':
|
|
203
|
-
return 'No matches found';
|
|
204
|
-
default:
|
|
205
|
-
return reason;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Format context with citations (for cited search results)
|
|
212
|
-
*/
|
|
213
|
-
export function formatContextWithCitations(
|
|
214
|
-
results: CitedSearchResult[],
|
|
215
|
-
options?: FormatOptions
|
|
216
|
-
): string {
|
|
217
|
-
const format = options?.format ?? 'inline';
|
|
218
|
-
|
|
219
|
-
switch (format) {
|
|
220
|
-
case 'inline':
|
|
221
|
-
return formatCitedInline(results);
|
|
222
|
-
case 'footnote':
|
|
223
|
-
return formatCitedFootnote(results);
|
|
224
|
-
case 'reference':
|
|
225
|
-
return formatCitedReference(results);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function formatCitedInline(results: CitedSearchResult[]): string {
|
|
230
|
-
return results.map(r => {
|
|
231
|
-
const date = r.event.timestamp.toLocaleDateString();
|
|
232
|
-
const session = r.event.sessionId.slice(0, 8);
|
|
233
|
-
const citation = formatCitationId(r.citation.citationId);
|
|
234
|
-
|
|
235
|
-
return [
|
|
236
|
-
`> ${r.event.content}`,
|
|
237
|
-
`>`,
|
|
238
|
-
`> ${citation} - ${date}, Session ${session}`
|
|
239
|
-
].join('\n');
|
|
240
|
-
}).join('\n\n---\n\n');
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function formatCitedFootnote(results: CitedSearchResult[]): string {
|
|
244
|
-
const content = results.map((r, i) => {
|
|
245
|
-
return `${r.event.content} [${i + 1}]`;
|
|
246
|
-
}).join('\n\n');
|
|
247
|
-
|
|
248
|
-
const footnotes = results.map((r, i) => {
|
|
249
|
-
const citation = formatCitationId(r.citation.citationId);
|
|
250
|
-
const date = r.event.timestamp.toLocaleDateString();
|
|
251
|
-
return `[${i + 1}] ${citation} - ${date}`;
|
|
252
|
-
}).join('\n');
|
|
253
|
-
|
|
254
|
-
return `${content}\n\n---\n**References:**\n${footnotes}`;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function formatCitedReference(results: CitedSearchResult[]): string {
|
|
258
|
-
const content = results.map(r => {
|
|
259
|
-
return `### ${r.event.eventType}\n${r.event.content}`;
|
|
260
|
-
}).join('\n\n');
|
|
261
|
-
|
|
262
|
-
const references = results.map(r => {
|
|
263
|
-
const citation = formatCitationId(r.citation.citationId);
|
|
264
|
-
const date = r.event.timestamp.toLocaleDateString();
|
|
265
|
-
return `- ${citation} Session ${r.event.sessionId.slice(0, 8)}, ${date}`;
|
|
266
|
-
}).join('\n');
|
|
267
|
-
|
|
268
|
-
return `## Content\n\n${content}\n\n## References\n${references}`;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Create a context formatter instance
|
|
273
|
-
*/
|
|
274
|
-
export function createContextFormatter(): ContextFormatter {
|
|
275
|
-
return new ContextFormatter();
|
|
276
|
-
}
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Continuity Manager
|
|
3
|
-
* Tracks and calculates context continuity between interactions
|
|
4
|
-
* Biomimetic: Simulates context-dependent memory retrieval
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { randomUUID } from 'crypto';
|
|
8
|
-
import { dbRun, dbAll, toDate, type Database } from './db-wrapper.js';
|
|
9
|
-
import type {
|
|
10
|
-
EndlessModeConfig,
|
|
11
|
-
ContextSnapshot,
|
|
12
|
-
ContinuityScore,
|
|
13
|
-
TransitionType,
|
|
14
|
-
ContinuityLog
|
|
15
|
-
} from './types.js';
|
|
16
|
-
import { EventStore } from './event-store.js';
|
|
17
|
-
|
|
18
|
-
export class ContinuityManager {
|
|
19
|
-
private lastContext: ContextSnapshot | null = null;
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
private eventStore: EventStore,
|
|
23
|
-
private config: EndlessModeConfig
|
|
24
|
-
) {}
|
|
25
|
-
|
|
26
|
-
private get db(): Database {
|
|
27
|
-
return this.eventStore.getDatabase();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Calculate continuity score between current and previous context
|
|
32
|
-
*/
|
|
33
|
-
async calculateScore(
|
|
34
|
-
currentContext: ContextSnapshot,
|
|
35
|
-
previousContext?: ContextSnapshot
|
|
36
|
-
): Promise<ContinuityScore> {
|
|
37
|
-
const prev = previousContext || this.lastContext;
|
|
38
|
-
|
|
39
|
-
if (!prev) {
|
|
40
|
-
// No previous context - this is a fresh start
|
|
41
|
-
this.lastContext = currentContext;
|
|
42
|
-
return { score: 0.5, transitionType: 'break' };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
let score = 0;
|
|
46
|
-
|
|
47
|
-
// Topic continuity (30%)
|
|
48
|
-
const topicOverlap = this.calculateOverlap(
|
|
49
|
-
currentContext.topics,
|
|
50
|
-
prev.topics
|
|
51
|
-
);
|
|
52
|
-
score += topicOverlap * 0.3;
|
|
53
|
-
|
|
54
|
-
// File continuity (20%)
|
|
55
|
-
const fileOverlap = this.calculateOverlap(
|
|
56
|
-
currentContext.files,
|
|
57
|
-
prev.files
|
|
58
|
-
);
|
|
59
|
-
score += fileOverlap * 0.2;
|
|
60
|
-
|
|
61
|
-
// Time proximity (30%)
|
|
62
|
-
const timeDiff = currentContext.timestamp - prev.timestamp;
|
|
63
|
-
const decayHours = this.config.continuity.topicDecayHours;
|
|
64
|
-
const timeScore = Math.exp(-timeDiff / (decayHours * 3600000));
|
|
65
|
-
score += timeScore * 0.3;
|
|
66
|
-
|
|
67
|
-
// Entity continuity (20%)
|
|
68
|
-
const entityOverlap = this.calculateOverlap(
|
|
69
|
-
currentContext.entities,
|
|
70
|
-
prev.entities
|
|
71
|
-
);
|
|
72
|
-
score += entityOverlap * 0.2;
|
|
73
|
-
|
|
74
|
-
// Determine transition type
|
|
75
|
-
const transitionType = this.determineTransitionType(score);
|
|
76
|
-
|
|
77
|
-
// Log the transition
|
|
78
|
-
await this.logTransition(currentContext, prev, score, transitionType);
|
|
79
|
-
|
|
80
|
-
// Update last context
|
|
81
|
-
this.lastContext = currentContext;
|
|
82
|
-
|
|
83
|
-
return { score, transitionType };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Create a context snapshot from current state
|
|
88
|
-
*/
|
|
89
|
-
createSnapshot(
|
|
90
|
-
id: string,
|
|
91
|
-
content: string,
|
|
92
|
-
metadata?: {
|
|
93
|
-
files?: string[];
|
|
94
|
-
entities?: string[];
|
|
95
|
-
}
|
|
96
|
-
): ContextSnapshot {
|
|
97
|
-
return {
|
|
98
|
-
id,
|
|
99
|
-
timestamp: Date.now(),
|
|
100
|
-
topics: this.extractTopics(content),
|
|
101
|
-
files: metadata?.files || this.extractFiles(content),
|
|
102
|
-
entities: metadata?.entities || this.extractEntities(content)
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Get recent continuity logs
|
|
108
|
-
*/
|
|
109
|
-
async getRecentLogs(limit: number = 10): Promise<ContinuityLog[]> {
|
|
110
|
-
const rows = await dbAll<Record<string, unknown>>(
|
|
111
|
-
this.db,
|
|
112
|
-
`SELECT * FROM continuity_log
|
|
113
|
-
ORDER BY created_at DESC
|
|
114
|
-
LIMIT ?`,
|
|
115
|
-
[limit]
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
return rows.map(row => ({
|
|
119
|
-
logId: row.log_id as string,
|
|
120
|
-
fromContextId: row.from_context_id as string | undefined,
|
|
121
|
-
toContextId: row.to_context_id as string | undefined,
|
|
122
|
-
continuityScore: row.continuity_score as number,
|
|
123
|
-
transitionType: row.transition_type as TransitionType,
|
|
124
|
-
createdAt: toDate(row.created_at)
|
|
125
|
-
}));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Get average continuity score over time period
|
|
130
|
-
*/
|
|
131
|
-
async getAverageScore(hours: number = 1): Promise<number> {
|
|
132
|
-
const result = await dbAll<{ avg_score: number | null }>(
|
|
133
|
-
this.db,
|
|
134
|
-
`SELECT AVG(continuity_score) as avg_score
|
|
135
|
-
FROM continuity_log
|
|
136
|
-
WHERE created_at > datetime('now', '-${hours} hours')`
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
return result[0]?.avg_score ?? 0.5;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Get transition type distribution
|
|
144
|
-
*/
|
|
145
|
-
async getTransitionStats(hours: number = 24): Promise<Record<TransitionType, number>> {
|
|
146
|
-
const rows = await dbAll<{ transition_type: string; count: number }>(
|
|
147
|
-
this.db,
|
|
148
|
-
`SELECT transition_type, COUNT(*) as count
|
|
149
|
-
FROM continuity_log
|
|
150
|
-
WHERE created_at > datetime('now', '-${hours} hours')
|
|
151
|
-
GROUP BY transition_type`
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
const stats: Record<TransitionType, number> = {
|
|
155
|
-
seamless: 0,
|
|
156
|
-
topic_shift: 0,
|
|
157
|
-
break: 0
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
for (const row of rows) {
|
|
161
|
-
stats[row.transition_type as TransitionType] = row.count;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return stats;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Clear old continuity logs
|
|
169
|
-
*/
|
|
170
|
-
async cleanup(olderThanDays: number = 7): Promise<number> {
|
|
171
|
-
const result = await dbAll<{ changes: number }>(
|
|
172
|
-
this.db,
|
|
173
|
-
`DELETE FROM continuity_log
|
|
174
|
-
WHERE created_at < datetime('now', '-${olderThanDays} days')
|
|
175
|
-
RETURNING COUNT(*) as changes`
|
|
176
|
-
);
|
|
177
|
-
|
|
178
|
-
return result[0]?.changes || 0;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Calculate overlap between two arrays
|
|
183
|
-
*/
|
|
184
|
-
private calculateOverlap(a: string[], b: string[]): number {
|
|
185
|
-
if (a.length === 0 || b.length === 0) return 0;
|
|
186
|
-
|
|
187
|
-
const setA = new Set(a.map(s => s.toLowerCase()));
|
|
188
|
-
const setB = new Set(b.map(s => s.toLowerCase()));
|
|
189
|
-
|
|
190
|
-
const intersection = [...setA].filter(x => setB.has(x));
|
|
191
|
-
const union = new Set([...setA, ...setB]);
|
|
192
|
-
|
|
193
|
-
return intersection.length / union.size; // Jaccard similarity
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Determine transition type based on score
|
|
198
|
-
*/
|
|
199
|
-
private determineTransitionType(score: number): TransitionType {
|
|
200
|
-
if (score >= this.config.continuity.minScoreForSeamless) {
|
|
201
|
-
return 'seamless';
|
|
202
|
-
} else if (score >= 0.4) {
|
|
203
|
-
return 'topic_shift';
|
|
204
|
-
} else {
|
|
205
|
-
return 'break';
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Log a context transition
|
|
211
|
-
*/
|
|
212
|
-
private async logTransition(
|
|
213
|
-
current: ContextSnapshot,
|
|
214
|
-
previous: ContextSnapshot,
|
|
215
|
-
score: number,
|
|
216
|
-
type: TransitionType
|
|
217
|
-
): Promise<void> {
|
|
218
|
-
await dbRun(
|
|
219
|
-
this.db,
|
|
220
|
-
`INSERT INTO continuity_log
|
|
221
|
-
(log_id, from_context_id, to_context_id, continuity_score, transition_type, created_at)
|
|
222
|
-
VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)`,
|
|
223
|
-
[randomUUID(), previous.id, current.id, score, type]
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Extract topics from content
|
|
229
|
-
*/
|
|
230
|
-
private extractTopics(content: string): string[] {
|
|
231
|
-
const topics: string[] = [];
|
|
232
|
-
const contentLower = content.toLowerCase();
|
|
233
|
-
|
|
234
|
-
// Programming language keywords
|
|
235
|
-
const langPatterns = [
|
|
236
|
-
{ pattern: /typescript|\.ts\b/i, topic: 'typescript' },
|
|
237
|
-
{ pattern: /javascript|\.js\b/i, topic: 'javascript' },
|
|
238
|
-
{ pattern: /python|\.py\b/i, topic: 'python' },
|
|
239
|
-
{ pattern: /rust|\.rs\b/i, topic: 'rust' },
|
|
240
|
-
{ pattern: /go\b|golang/i, topic: 'go' }
|
|
241
|
-
];
|
|
242
|
-
|
|
243
|
-
for (const { pattern, topic } of langPatterns) {
|
|
244
|
-
if (pattern.test(content)) {
|
|
245
|
-
topics.push(topic);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Common development topics
|
|
250
|
-
const devTopics = [
|
|
251
|
-
'api', 'database', 'test', 'bug', 'feature', 'refactor',
|
|
252
|
-
'component', 'function', 'class', 'module', 'hook',
|
|
253
|
-
'deploy', 'build', 'config', 'docker', 'git'
|
|
254
|
-
];
|
|
255
|
-
|
|
256
|
-
for (const topic of devTopics) {
|
|
257
|
-
if (contentLower.includes(topic)) {
|
|
258
|
-
topics.push(topic);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return [...new Set(topics)].slice(0, 10);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Extract file paths from content
|
|
267
|
-
*/
|
|
268
|
-
private extractFiles(content: string): string[] {
|
|
269
|
-
const filePatterns = [
|
|
270
|
-
/(?:^|\s)([a-zA-Z0-9_\-./]+\.[a-zA-Z0-9]+)(?:\s|$|:)/gm,
|
|
271
|
-
/['"](\.?\/[^'"]+\.[a-zA-Z0-9]+)['"]/g,
|
|
272
|
-
/file[:\s]+([^\s,]+)/gi
|
|
273
|
-
];
|
|
274
|
-
|
|
275
|
-
const files = new Set<string>();
|
|
276
|
-
|
|
277
|
-
for (const pattern of filePatterns) {
|
|
278
|
-
let match;
|
|
279
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
280
|
-
const file = match[1];
|
|
281
|
-
if (file && file.length > 3 && file.length < 100) {
|
|
282
|
-
// Filter out common non-file patterns
|
|
283
|
-
if (!file.match(/^(https?:|mailto:|ftp:)/i)) {
|
|
284
|
-
files.add(file);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return Array.from(files).slice(0, 10);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Extract entity names from content (functions, classes, variables)
|
|
295
|
-
*/
|
|
296
|
-
private extractEntities(content: string): string[] {
|
|
297
|
-
const entities = new Set<string>();
|
|
298
|
-
|
|
299
|
-
const entityPatterns = [
|
|
300
|
-
/\b(function|const|let|var|class|interface|type)\s+([a-zA-Z_][a-zA-Z0-9_]*)/g,
|
|
301
|
-
/\b([A-Z][a-zA-Z0-9_]*(?:Component|Service|Store|Manager|Handler|Factory|Provider))\b/g,
|
|
302
|
-
/\b(use[A-Z][a-zA-Z0-9_]*)\b/g // React hooks
|
|
303
|
-
];
|
|
304
|
-
|
|
305
|
-
for (const pattern of entityPatterns) {
|
|
306
|
-
let match;
|
|
307
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
308
|
-
const entity = match[2] || match[1];
|
|
309
|
-
if (entity && entity.length > 2) {
|
|
310
|
-
entities.add(entity);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return Array.from(entities).slice(0, 20);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Reset the last context (for testing or manual reset)
|
|
320
|
-
*/
|
|
321
|
-
resetLastContext(): void {
|
|
322
|
-
this.lastContext = null;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Get the last context snapshot
|
|
327
|
-
*/
|
|
328
|
-
getLastContext(): ContextSnapshot | null {
|
|
329
|
-
return this.lastContext;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Create a Continuity Manager instance
|
|
335
|
-
*/
|
|
336
|
-
export function createContinuityManager(
|
|
337
|
-
eventStore: EventStore,
|
|
338
|
-
config: EndlessModeConfig
|
|
339
|
-
): ContinuityManager {
|
|
340
|
-
return new ContinuityManager(eventStore, config);
|
|
341
|
-
}
|
package/src/core/db-wrapper.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SQLite Database Wrapper
|
|
3
|
-
* Provides Promise-based interface over better-sqlite3 synchronous API
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import BetterSqlite3 from 'better-sqlite3';
|
|
7
|
-
|
|
8
|
-
export type Database = BetterSqlite3.Database;
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Safely converts a value to a Date object
|
|
12
|
-
*/
|
|
13
|
-
export function toDate(value: unknown): Date {
|
|
14
|
-
if (value instanceof Date) return value;
|
|
15
|
-
if (typeof value === 'string') return new Date(value);
|
|
16
|
-
if (typeof value === 'number') return new Date(value);
|
|
17
|
-
return new Date(String(value));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface DatabaseOptions {
|
|
21
|
-
readOnly?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Creates a new SQLite database connection
|
|
26
|
-
*/
|
|
27
|
-
export function createDatabase(dbPath: string, options?: DatabaseOptions): Database {
|
|
28
|
-
return new BetterSqlite3(dbPath, { readonly: options?.readOnly });
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Executes a statement that doesn't return rows
|
|
33
|
-
*/
|
|
34
|
-
export function dbRun(db: Database, sql: string, params: unknown[] = []): Promise<void> {
|
|
35
|
-
db.prepare(sql).run(...(params as never[]));
|
|
36
|
-
return Promise.resolve();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Executes a query and returns all rows
|
|
41
|
-
*/
|
|
42
|
-
export function dbAll<T = Record<string, unknown>>(
|
|
43
|
-
db: Database,
|
|
44
|
-
sql: string,
|
|
45
|
-
params: unknown[] = []
|
|
46
|
-
): Promise<T[]> {
|
|
47
|
-
return Promise.resolve(db.prepare(sql).all(...(params as never[])) as T[]);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Closes the database connection
|
|
52
|
-
*/
|
|
53
|
-
export function dbClose(db: Database): Promise<void> {
|
|
54
|
-
db.close();
|
|
55
|
-
return Promise.resolve();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Executes multiple statements
|
|
60
|
-
*/
|
|
61
|
-
export function dbExec(db: Database, sql: string): Promise<void> {
|
|
62
|
-
db.exec(sql);
|
|
63
|
-
return Promise.resolve();
|
|
64
|
-
}
|