claude-memory-layer 1.0.26 → 1.0.28
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/.env.example +7 -0
- package/AGENTS.md +11 -0
- package/README.md +184 -41
- package/benchmarks/replay/anonymized-real-sessions.json +48 -0
- package/dist/cli/index.js +10097 -6003
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +9745 -5587
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +6545 -5270
- package/dist/hooks/post-tool-use.js.map +4 -4
- package/dist/hooks/semantic-daemon.js +6646 -5354
- package/dist/hooks/semantic-daemon.js.map +4 -4
- package/dist/hooks/session-end.js +6618 -5347
- package/dist/hooks/session-end.js.map +4 -4
- package/dist/hooks/session-start.js +6619 -5354
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +6614 -5325
- package/dist/hooks/stop.js.map +4 -4
- package/dist/hooks/user-prompt-submit.js +6702 -5356
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/index.js +13537 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp/index.js +20770 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/server/api/index.js +6632 -5319
- package/dist/server/api/index.js.map +4 -4
- package/dist/server/index.js +6667 -5340
- package/dist/server/index.js.map +4 -4
- package/dist/services/memory-service.js +6568 -5350
- package/dist/services/memory-service.js.map +4 -4
- package/dist/ui/assets/js/bootstrap.js +244 -0
- package/dist/ui/assets/js/chat.js +373 -0
- package/dist/ui/assets/js/disclosure.js +232 -0
- package/dist/ui/assets/js/modals.js +298 -0
- package/dist/ui/assets/js/overview.js +655 -0
- package/dist/ui/assets/js/state.js +72 -0
- package/dist/ui/assets/js/views.js +468 -0
- package/dist/ui/index.html +43 -1
- package/dist/ui/index.ts +3 -0
- package/dist/ui/style.css +222 -0
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +627 -0
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +440 -0
- package/docs/MEMORY_USEFULNESS_AUDIT.md +371 -0
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +80 -0
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +333 -0
- package/docs/PRODUCT_VALIDATION_MATRIX.md +82 -0
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +421 -0
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +501 -0
- package/docs/REFACTORING_PLAN_THIN_CORE.md +414 -0
- package/docs/REFERENCE_PROJECT_ANALYSES.md +25 -0
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +452 -0
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +446 -0
- package/docs/architecture/comparison-index.md +47 -0
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +46 -0
- package/package.json +9 -5
- package/scripts/build.ts +25 -8
- package/scripts/generate-session-qrels.ts +126 -0
- package/scripts/replay-retrieval-benchmark.ts +69 -0
- package/specs/thin-core-refactor/context.md +275 -0
- package/specs/thin-core-refactor/plan.md +536 -0
- package/specs/thin-core-refactor/spec.md +465 -0
- package/src/adapters/claude/capture/index.ts +3 -0
- package/src/adapters/claude/context/index.ts +3 -0
- package/src/adapters/claude/hooks/index.ts +21 -0
- package/src/adapters/claude/hooks/post-tool-use.ts +239 -0
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +104 -0
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +209 -0
- package/src/adapters/claude/hooks/semantic-daemon.ts +283 -0
- package/src/adapters/claude/hooks/session-end.ts +59 -0
- package/src/adapters/claude/hooks/session-start.ts +73 -0
- package/src/adapters/claude/hooks/stop.ts +128 -0
- package/src/adapters/claude/hooks/user-prompt-submit.ts +361 -0
- package/src/adapters/claude/index.ts +4 -0
- package/src/adapters/claude/transcript/index.ts +4 -0
- package/src/adapters/claude/transcript/transcript-reader.ts +57 -0
- package/src/adapters/claude/transcript/turn-reconstructor.ts +65 -0
- package/src/apps/cli/claude-settings-hooks.ts +138 -0
- package/src/apps/cli/codex-import-runner.ts +125 -0
- package/src/apps/cli/codex-validation-output.ts +95 -0
- package/src/apps/cli/hermes-import-runner.ts +130 -0
- package/src/apps/cli/hermes-validation-output.ts +91 -0
- package/src/apps/cli/index.ts +1731 -0
- package/src/apps/cli/mcp-install.ts +106 -0
- package/src/apps/cli/retrieval-disclosure-output.ts +196 -0
- package/src/apps/dashboard/assets/js/bootstrap.js +244 -0
- package/src/apps/dashboard/assets/js/chat.js +373 -0
- package/src/apps/dashboard/assets/js/disclosure.js +232 -0
- package/src/apps/dashboard/assets/js/modals.js +298 -0
- package/src/apps/dashboard/assets/js/overview.js +655 -0
- package/src/apps/dashboard/assets/js/state.js +72 -0
- package/src/apps/dashboard/assets/js/views.js +468 -0
- package/src/{ui → apps/dashboard}/index.html +43 -1
- package/src/apps/dashboard/index.ts +3 -0
- package/src/{ui → apps/dashboard}/style.css +222 -0
- package/src/apps/index.ts +5 -0
- package/src/apps/server/api/chat.ts +244 -0
- package/src/apps/server/api/citations.ts +105 -0
- package/src/apps/server/api/events.ts +137 -0
- package/src/apps/server/api/health.ts +53 -0
- package/src/apps/server/api/index.ts +26 -0
- package/src/apps/server/api/projects.ts +74 -0
- package/src/apps/server/api/search.ts +184 -0
- package/src/apps/server/api/sessions.ts +115 -0
- package/src/apps/server/api/stats.ts +723 -0
- package/src/apps/server/api/turns.ts +143 -0
- package/src/apps/server/api/utils.ts +65 -0
- package/src/apps/server/index.ts +111 -0
- package/src/cli/index.ts +2 -1311
- package/src/cli/retrieval-disclosure-output.ts +2 -0
- package/src/compat/index.ts +5 -0
- package/src/core/derive/fact-deriver.ts +170 -0
- package/src/core/derive/index.ts +2 -0
- package/src/core/derive/summary-deriver.ts +76 -0
- package/src/core/embedder.ts +4 -152
- package/src/core/engine/embedding-maintenance-service.ts +187 -0
- package/src/core/engine/endless-memory-services.ts +4 -0
- package/src/core/engine/index.ts +19 -0
- package/src/core/engine/memory-engine-services.ts +170 -0
- package/src/core/engine/memory-ingest-service.ts +317 -0
- package/src/core/engine/memory-query-service.ts +173 -0
- package/src/core/engine/memory-runtime-service.ts +162 -0
- package/src/core/engine/memory-service-composition.ts +231 -0
- package/src/core/engine/retrieval-analytics-service.ts +181 -0
- package/src/core/engine/retrieval-disclosure-service.ts +420 -0
- package/src/core/engine/retrieval-orchestrator.ts +377 -0
- package/src/core/engine/retrieval-services.ts +176 -0
- package/src/core/engine/shared-memory-services.ts +4 -0
- package/src/core/entity-repo.ts +1 -3
- package/src/core/event-store.ts +3 -3
- package/src/core/evidence-aligner.ts +2 -2
- package/src/core/external-market-context.ts +582 -0
- package/src/core/graduation.ts +2 -3
- package/src/core/index.ts +21 -0
- package/src/core/matcher.ts +2 -4
- package/src/core/model/memory-fact.ts +30 -0
- package/src/core/model/memory-rule.ts +14 -0
- package/src/core/model/memory-summary.ts +21 -0
- package/src/core/model/raw-event.ts +28 -0
- package/src/core/model/retrieval-result.ts +35 -0
- package/src/core/privacy/filter.ts +21 -10
- package/src/core/product-validation-matrix.ts +314 -0
- package/src/core/progressive-retriever.ts +1 -2
- package/src/core/registry/project-path.ts +54 -0
- package/src/core/registry/session-registry.ts +69 -0
- package/src/core/replay-evaluator.ts +625 -0
- package/src/core/retrieval-benchmark.ts +117 -0
- package/src/core/retrieval-quality.ts +109 -0
- package/src/core/retriever.ts +53 -15
- package/src/core/session-qrels.ts +360 -0
- package/src/core/shared-event-store.ts +1 -1
- package/src/core/sqlite-event-store.ts +35 -11
- package/src/core/task/blocker-resolver.ts +2 -2
- package/src/core/task/task-resolver.ts +0 -1
- package/src/core/vector-outbox.ts +1 -10
- package/src/core/vector-worker.ts +1 -1
- package/src/extensions/endless-memory/endless-memory-services.ts +350 -0
- package/src/extensions/endless-memory/index.ts +1 -0
- package/src/extensions/index.ts +5 -0
- package/src/extensions/mcp/handlers.ts +960 -0
- package/src/extensions/mcp/index.ts +48 -0
- package/src/extensions/mcp/tools.ts +252 -0
- package/src/extensions/shared-memory/index.ts +1 -0
- package/src/extensions/shared-memory/shared-memory-services.ts +211 -0
- package/src/extensions/vector/embedder.ts +197 -0
- package/src/extensions/vector/index.ts +1 -0
- package/src/hooks/post-tool-use.ts +3 -236
- package/src/hooks/semantic-daemon-client.ts +1 -208
- package/src/hooks/semantic-daemon.ts +6 -271
- package/src/hooks/session-end.ts +4 -79
- package/src/hooks/session-start.ts +4 -73
- package/src/hooks/stop.ts +3 -173
- package/src/hooks/user-prompt-submit.ts +3 -338
- package/src/index.ts +13 -0
- package/src/mcp/handlers.ts +2 -212
- package/src/mcp/index.ts +3 -46
- package/src/mcp/tools.ts +2 -78
- package/src/server/api/chat.ts +2 -244
- package/src/server/api/citations.ts +2 -105
- package/src/server/api/events.ts +2 -137
- package/src/server/api/health.ts +2 -53
- package/src/server/api/index.ts +2 -26
- package/src/server/api/projects.ts +2 -74
- package/src/server/api/search.ts +2 -102
- package/src/server/api/sessions.ts +2 -115
- package/src/server/api/stats.ts +2 -724
- package/src/server/api/turns.ts +2 -143
- package/src/server/api/utils.ts +2 -46
- package/src/server/index.ts +2 -100
- package/src/services/bootstrap-organizer.ts +46 -26
- package/src/services/codex-session-history-importer.ts +521 -29
- package/src/services/hermes-session-history-importer.ts +733 -0
- package/src/services/memory-service-config.ts +36 -0
- package/src/services/memory-service-registry.ts +150 -0
- package/src/services/memory-service.ts +211 -1325
- package/src/services/session-history-importer.ts +58 -14
- package/tests/README.md +23 -0
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +54 -0
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +98 -0
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +99 -0
- package/tests/apps/app-layer-boundary.test.ts +48 -0
- package/tests/apps/claude-settings-hooks.test.ts +107 -0
- package/tests/apps/cli-disclosure-output.test.ts +212 -0
- package/tests/apps/codex-import-runner.test.ts +99 -0
- package/tests/apps/codex-validation-output.test.ts +100 -0
- package/tests/apps/hermes-import-runner.test.ts +99 -0
- package/tests/apps/mcp-install-command.test.ts +59 -0
- package/tests/apps/package-build-entrypoints.test.ts +30 -0
- package/tests/apps/search-api-disclosure.test.ts +162 -0
- package/tests/apps/stats-api-lightweight.test.ts +67 -0
- package/tests/apps/ui-disclosure-output.test.ts +140 -0
- package/tests/{bootstrap-organizer.test.ts → core/bootstrap-organizer.test.ts} +1 -1
- package/tests/{canonical-key.test.ts → core/canonical-key.test.ts} +1 -1
- package/tests/core/codex-session-history-importer-validation.test.ts +185 -0
- package/tests/{consolidation-worker.test.ts → core/consolidation-worker.test.ts} +2 -2
- package/tests/core/embedding-maintenance-service.test.ts +282 -0
- package/tests/{evidence-aligner.test.ts → core/evidence-aligner.test.ts} +1 -1
- package/tests/core/external-market-context.test.ts +209 -0
- package/tests/core/fact-deriver.test.ts +79 -0
- package/tests/core/hermes-session-history-importer-validation.test.ts +609 -0
- package/tests/{ingest-interceptor.test.ts → core/ingest-interceptor.test.ts} +1 -1
- package/tests/{markdown-mirror.test.ts → core/markdown-mirror.test.ts} +2 -2
- package/tests/{matcher.test.ts → core/matcher.test.ts} +1 -1
- package/tests/{md-mirror.test.ts → core/md-mirror.test.ts} +2 -2
- package/tests/core/memory-engine-services.test.ts +240 -0
- package/tests/core/memory-ingest-service.test.ts +296 -0
- package/tests/core/memory-query-service.test.ts +129 -0
- package/tests/core/memory-runtime-service.test.ts +201 -0
- package/tests/core/memory-service-composition.test.ts +192 -0
- package/tests/core/memory-service-config.test.ts +41 -0
- package/tests/core/memory-service-facade.test.ts +30 -0
- package/tests/core/memory-service-registry.test.ts +206 -0
- package/tests/core/product-validation-matrix.test.ts +61 -0
- package/tests/core/project-registry.test.ts +78 -0
- package/tests/core/replay-evaluator.test.ts +181 -0
- package/tests/core/retrieval-analytics-service.test.ts +210 -0
- package/tests/core/retrieval-benchmark.test.ts +93 -0
- package/tests/core/retrieval-disclosure-service.test.ts +264 -0
- package/tests/core/retrieval-orchestrator.test.ts +403 -0
- package/tests/core/retrieval-quality.test.ts +31 -0
- package/tests/core/retrieval-services.test.ts +185 -0
- package/tests/{retriever-fallback-chain.test.ts → core/retriever-fallback-chain.test.ts} +3 -3
- package/tests/{retriever-strategy-scope.test.ts → core/retriever-strategy-scope.test.ts} +70 -3
- package/tests/{retriever.memu-adoption.test.ts → core/retriever.memu-adoption.test.ts} +3 -3
- package/tests/core/session-history-importer-filter.test.ts +78 -0
- package/tests/core/session-qrels.test.ts +250 -0
- package/tests/{sqlite-event-store-replication.test.ts → core/sqlite-event-store-replication.test.ts} +36 -1
- package/tests/core/summary-deriver.test.ts +66 -0
- package/tests/extensions/embedder-warning-suppression.test.ts +53 -0
- package/tests/extensions/endless-memory-extension-boundary.test.ts +17 -0
- package/tests/extensions/endless-memory-services.test.ts +325 -0
- package/tests/extensions/mcp-context-tools.test.ts +905 -0
- package/tests/extensions/mcp-extension-boundary.test.ts +21 -0
- package/tests/extensions/mcp-package-build.test.ts +22 -0
- package/tests/extensions/mcp-project-aware-tools.test.ts +102 -0
- package/tests/extensions/shared-memory-extension-boundary.test.ts +24 -0
- package/tests/extensions/shared-memory-services.test.ts +309 -0
- package/tests/extensions/vector-extension-boundary.test.ts +21 -0
- package/.claude/settings.local.json +0 -25
- package/.npm-cache/_cacache/content-v2/sha512/04/76/c098f88dfe584a2b80870bff7421b05d17d3d9ee1027f77772332a22d3f93a9a57101a2855107f6ad82077a818bba912b2bc317f2361b5ddb09ad284d9ce +0 -0
- package/.npm-cache/_cacache/content-v2/sha512/60/25/d2ecd39cfc7cab58351162814be77f935c6d6491c10c3745d456da7ddb2117ffd90c10e53fe3c0f1ed16b403307841543634504398b16ee4e6b6dd8e0c45 +0 -0
- package/.npm-cache/_cacache/index-v5/2b/9a/7f8f40206ed8a2e0a84efaa953ccaed1f5d001e14b931083f2e7a0738007 +0 -2
- package/.npm-cache/_cacache/index-v5/2e/d9/fcfa5c6a6abdc2a3644ab84a95936047298c465a2f47ee03db8f7fe1e946 +0 -3
- package/.npm-cache/_cacache/index-v5/a9/42/e519633356d12d3d2f19da66a8301016d496c8f5c3e0554124aaa62dc043 +0 -2
- package/.npm-cache/_logs/2026-02-26T12_04_52_729Z-debug-0.log +0 -256
- package/.npm-cache/_logs/2026-02-26T12_05_36_835Z-debug-0.log +0 -18
- package/.npm-cache/_logs/2026-02-26T12_05_45_982Z-debug-0.log +0 -32
- package/.npm-cache/_logs/2026-02-26T12_05_48_515Z-debug-0.log +0 -260
- package/.npm-cache/_logs/2026-02-26T12_05_53_567Z-debug-0.log +0 -69
- package/.npm-cache/_update-notifier-last-checked +0 -0
- package/bootstrap-kb/decisions/decisions.md +0 -244
- package/bootstrap-kb/glossary/glossary.md +0 -46
- package/bootstrap-kb/modules/.claude-plugin.md +0 -22
- package/bootstrap-kb/modules/agents.md.md +0 -15
- package/bootstrap-kb/modules/claude.md.md +0 -15
- package/bootstrap-kb/modules/context.md.md +0 -15
- package/bootstrap-kb/modules/docs.md +0 -18
- package/bootstrap-kb/modules/handoff.md.md +0 -15
- package/bootstrap-kb/modules/package-lock.json.md +0 -15
- package/bootstrap-kb/modules/package.json.md +0 -15
- package/bootstrap-kb/modules/plan.md.md +0 -15
- package/bootstrap-kb/modules/readme.md.md +0 -15
- package/bootstrap-kb/modules/scripts.md +0 -26
- package/bootstrap-kb/modules/spec.md.md +0 -15
- package/bootstrap-kb/modules/specs.md +0 -20
- package/bootstrap-kb/modules/src.md +0 -51
- package/bootstrap-kb/modules/tests.md +0 -42
- package/bootstrap-kb/modules/tsconfig.json.md +0 -15
- package/bootstrap-kb/modules/vitest.config.ts.md +0 -15
- package/bootstrap-kb/overview/overview.md +0 -40
- package/bootstrap-kb/sources/manifest.json +0 -950
- package/bootstrap-kb/sources/manifest.md +0 -227
- package/bootstrap-kb/timeline/timeline.md +0 -57
- package/claude-memory-layer-1.0.14.tgz +0 -0
- package/d.sh +0 -3
- package/deploy.sh +0 -3
- package/dist/ui/app.js +0 -2101
- package/memory/.claude-plugin/commands/2026-02-25.md +0 -263
- package/memory/_index.md +0 -418
- package/memory/agent_response/uncategorized/2026-02-26.md +0 -176
- package/memory/agent_response/uncategorized/2026-03-03.md +0 -14
- package/memory/agent_response/uncategorized/2026-03-04.md +0 -1421
- package/memory/agent_response/uncategorized/2026-03-05.md +0 -48
- package/memory/default/uncategorized/2026-02-25.md +0 -4839
- package/memory/session_summary/uncategorized/2026-02-26.md +0 -13
- package/memory/session_summary/uncategorized/2026-03-03.md +0 -5
- package/memory/session_summary/uncategorized/2026-03-04.md +0 -50
- package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +0 -142
- package/memory/specs/citations-system/2026-02-25.md +0 -1121
- package/memory/specs/endless-mode/2026-02-25.md +0 -1392
- package/memory/specs/entity-edge-model/2026-02-25.md +0 -1263
- package/memory/specs/evidence-aligner-v2/2026-02-25.md +0 -1028
- package/memory/specs/mcp-desktop-integration/2026-02-25.md +0 -1334
- package/memory/specs/post-tool-use-hook/2026-02-25.md +0 -1164
- package/memory/specs/private-tags/2026-02-25.md +0 -1057
- package/memory/specs/progressive-disclosure/2026-02-25.md +0 -1436
- package/memory/specs/task-entity-system/2026-02-25.md +0 -924
- package/memory/specs/vector-outbox-v2/2026-02-25.md +0 -1510
- package/memory/specs/web-viewer-ui/2026-02-25.md +0 -1709
- package/memory/tool_observation/uncategorized/2026-02-26.md +0 -209
- package/memory/tool_observation/uncategorized/2026-03-03.md +0 -21
- package/memory/tool_observation/uncategorized/2026-03-04.md +0 -1033
- package/memory/tool_observation/uncategorized/2026-03-05.md +0 -29
- package/memory/user_prompt/uncategorized/2026-02-26.md +0 -25
- package/memory/user_prompt/uncategorized/2026-03-04.md +0 -634
- package/specs/optional-duckdb/context.md +0 -77
- package/specs/optional-duckdb/plan.md +0 -142
- package/specs/optional-duckdb/spec.md +0 -35
- package/src/ui/app.js +0 -2101
package/src/server/api/turns.ts
CHANGED
|
@@ -1,143 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Endpoints for viewing events grouped by conversation turn
|
|
4
|
-
*
|
|
5
|
-
* A "turn" groups a user_prompt with its associated tool_observations
|
|
6
|
-
* and the final agent_response into a single logical unit.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { Hono } from 'hono';
|
|
10
|
-
import { getServiceFromQuery } from './utils.js';
|
|
11
|
-
|
|
12
|
-
export const turnsRouter = new Hono();
|
|
13
|
-
|
|
14
|
-
// GET /api/turns?sessionId=xxx - List turns for a session
|
|
15
|
-
turnsRouter.get('/', async (c) => {
|
|
16
|
-
const sessionId = c.req.query('sessionId');
|
|
17
|
-
const limit = parseInt(c.req.query('limit') || '20', 10);
|
|
18
|
-
const offset = parseInt(c.req.query('offset') || '0', 10);
|
|
19
|
-
|
|
20
|
-
if (!sessionId) {
|
|
21
|
-
return c.json({ error: 'sessionId is required' }, 400);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const memoryService = getServiceFromQuery(c);
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
await memoryService.initialize();
|
|
28
|
-
|
|
29
|
-
const turns = await memoryService.getSessionTurns(sessionId, { limit, offset });
|
|
30
|
-
const totalTurns = await memoryService.countSessionTurns(sessionId);
|
|
31
|
-
|
|
32
|
-
return c.json({
|
|
33
|
-
turns: turns.map(t => ({
|
|
34
|
-
turnId: t.turnId,
|
|
35
|
-
startedAt: t.startedAt.toISOString(),
|
|
36
|
-
promptPreview: t.promptPreview,
|
|
37
|
-
eventCount: t.eventCount,
|
|
38
|
-
toolCount: t.toolCount,
|
|
39
|
-
hasResponse: t.hasResponse,
|
|
40
|
-
events: t.events.map(e => ({
|
|
41
|
-
id: e.id,
|
|
42
|
-
eventType: e.eventType,
|
|
43
|
-
timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp,
|
|
44
|
-
preview: e.content.slice(0, 300) + (e.content.length > 300 ? '...' : ''),
|
|
45
|
-
contentLength: e.content.length
|
|
46
|
-
}))
|
|
47
|
-
})),
|
|
48
|
-
total: totalTurns,
|
|
49
|
-
limit,
|
|
50
|
-
offset,
|
|
51
|
-
hasMore: offset + limit < totalTurns
|
|
52
|
-
});
|
|
53
|
-
} catch (error) {
|
|
54
|
-
return c.json({ error: (error as Error).message }, 500);
|
|
55
|
-
} finally {
|
|
56
|
-
await memoryService.shutdown();
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// GET /api/turns/:turnId - Get full turn details
|
|
61
|
-
turnsRouter.get('/:turnId', async (c) => {
|
|
62
|
-
const { turnId } = c.req.param();
|
|
63
|
-
const memoryService = getServiceFromQuery(c);
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await memoryService.initialize();
|
|
67
|
-
|
|
68
|
-
const events = await memoryService.getEventsByTurn(turnId);
|
|
69
|
-
|
|
70
|
-
if (events.length === 0) {
|
|
71
|
-
return c.json({ error: 'Turn not found' }, 404);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const promptEvent = events.find(e => e.eventType === 'user_prompt');
|
|
75
|
-
const toolEvents = events.filter(e => e.eventType === 'tool_observation');
|
|
76
|
-
const responseEvents = events.filter(e => e.eventType === 'agent_response');
|
|
77
|
-
|
|
78
|
-
return c.json({
|
|
79
|
-
turnId,
|
|
80
|
-
sessionId: events[0].sessionId,
|
|
81
|
-
startedAt: events[0].timestamp instanceof Date
|
|
82
|
-
? events[0].timestamp.toISOString()
|
|
83
|
-
: events[0].timestamp,
|
|
84
|
-
prompt: promptEvent ? {
|
|
85
|
-
id: promptEvent.id,
|
|
86
|
-
content: promptEvent.content,
|
|
87
|
-
timestamp: promptEvent.timestamp instanceof Date
|
|
88
|
-
? promptEvent.timestamp.toISOString()
|
|
89
|
-
: promptEvent.timestamp
|
|
90
|
-
} : null,
|
|
91
|
-
tools: toolEvents.map(e => {
|
|
92
|
-
let toolName = '';
|
|
93
|
-
let success = true;
|
|
94
|
-
try {
|
|
95
|
-
const parsed = JSON.parse(e.content);
|
|
96
|
-
toolName = parsed.toolName || '';
|
|
97
|
-
success = parsed.success !== false;
|
|
98
|
-
} catch { /* ignore */ }
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
id: e.id,
|
|
102
|
-
toolName,
|
|
103
|
-
success,
|
|
104
|
-
timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp,
|
|
105
|
-
preview: e.content.slice(0, 500) + (e.content.length > 500 ? '...' : '')
|
|
106
|
-
};
|
|
107
|
-
}),
|
|
108
|
-
responses: responseEvents.map(e => ({
|
|
109
|
-
id: e.id,
|
|
110
|
-
content: e.content,
|
|
111
|
-
timestamp: e.timestamp instanceof Date ? e.timestamp.toISOString() : e.timestamp
|
|
112
|
-
})),
|
|
113
|
-
totalEvents: events.length
|
|
114
|
-
});
|
|
115
|
-
} catch (error) {
|
|
116
|
-
return c.json({ error: (error as Error).message }, 500);
|
|
117
|
-
} finally {
|
|
118
|
-
await memoryService.shutdown();
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// POST /api/turns/backfill - Backfill turn_ids from metadata
|
|
123
|
-
turnsRouter.post('/backfill', async (c) => {
|
|
124
|
-
const memoryService = getServiceFromQuery(c);
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await memoryService.initialize();
|
|
128
|
-
const updated = await memoryService.backfillTurnIds();
|
|
129
|
-
|
|
130
|
-
return c.json({
|
|
131
|
-
success: true,
|
|
132
|
-
updated,
|
|
133
|
-
message: `Backfilled turn_id for ${updated} events`
|
|
134
|
-
});
|
|
135
|
-
} catch (error) {
|
|
136
|
-
return c.json({
|
|
137
|
-
success: false,
|
|
138
|
-
error: (error as Error).message
|
|
139
|
-
}, 500);
|
|
140
|
-
} finally {
|
|
141
|
-
await memoryService.shutdown();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
1
|
+
/** Compatibility API module. Real app lives in src/apps/server/api. */
|
|
2
|
+
export * from '../../apps/server/api/turns.js';
|
package/src/server/api/utils.ts
CHANGED
|
@@ -1,46 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Shared helpers for API endpoints
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Context } from 'hono';
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
import * as os from 'os';
|
|
9
|
-
import { getReadOnlyMemoryService } from '../../services/memory-service.js';
|
|
10
|
-
import { MemoryService } from '../../services/memory-service.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Get the appropriate MemoryService based on the ?project= query parameter.
|
|
14
|
-
* - If ?project=<hash> is set (8 hex chars), resolves directly to project storage
|
|
15
|
-
* - If ?project=<path> is set, computes hash from path
|
|
16
|
-
* - Otherwise, returns the global read-only service
|
|
17
|
-
*
|
|
18
|
-
* Always creates read-only services for the dashboard API to avoid
|
|
19
|
-
* VectorWorker lifecycle issues with per-request services.
|
|
20
|
-
*/
|
|
21
|
-
export function getServiceFromQuery(c: Context): MemoryService {
|
|
22
|
-
const project = c.req.query('project') || c.req.query('projectId');
|
|
23
|
-
if (project) {
|
|
24
|
-
// Check if it's a hash (8 hex chars) or a path
|
|
25
|
-
const isHash = /^[a-f0-9]{8}$/.test(project);
|
|
26
|
-
let storagePath: string;
|
|
27
|
-
|
|
28
|
-
if (isHash) {
|
|
29
|
-
storagePath = path.join(os.homedir(), '.claude-code', 'memory', 'projects', project);
|
|
30
|
-
} else {
|
|
31
|
-
// Import hashProjectPath dynamically to compute the hash from path
|
|
32
|
-
const crypto = require('crypto');
|
|
33
|
-
const normalized = project.replace(/\/+$/, '') || '/';
|
|
34
|
-
const hash = crypto.createHash('sha256').update(normalized).digest('hex').slice(0, 8);
|
|
35
|
-
storagePath = path.join(os.homedir(), '.claude-code', 'memory', 'projects', hash);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return new MemoryService({
|
|
39
|
-
storagePath,
|
|
40
|
-
readOnly: true,
|
|
41
|
-
analyticsEnabled: false,
|
|
42
|
-
sharedStoreConfig: { enabled: false }
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return getReadOnlyMemoryService();
|
|
46
|
-
}
|
|
1
|
+
/** Compatibility API module. Real app lives in src/apps/server/api. */
|
|
2
|
+
export * from '../../apps/server/api/utils.js';
|
package/src/server/index.ts
CHANGED
|
@@ -1,100 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Provides REST API and serves static UI files
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// These are injected by the esbuild banner
|
|
7
|
-
declare const __dirname: string;
|
|
8
|
-
declare const __filename: string;
|
|
9
|
-
|
|
10
|
-
import { Hono } from 'hono';
|
|
11
|
-
import { cors } from 'hono/cors';
|
|
12
|
-
import { logger } from 'hono/logger';
|
|
13
|
-
import { serve } from '@hono/node-server';
|
|
14
|
-
import { serveStatic } from '@hono/node-server/serve-static';
|
|
15
|
-
import * as path from 'path';
|
|
16
|
-
import * as fs from 'fs';
|
|
17
|
-
import type { Server } from 'http';
|
|
18
|
-
|
|
19
|
-
import { apiRouter } from './api/index.js';
|
|
20
|
-
|
|
21
|
-
const app = new Hono();
|
|
22
|
-
|
|
23
|
-
// Middleware
|
|
24
|
-
app.use('/*', cors());
|
|
25
|
-
app.use('/*', logger());
|
|
26
|
-
|
|
27
|
-
// API routes
|
|
28
|
-
app.route('/api', apiRouter);
|
|
29
|
-
|
|
30
|
-
// Health check
|
|
31
|
-
app.get('/health', (c) => c.json({ status: 'ok', timestamp: new Date().toISOString() }));
|
|
32
|
-
|
|
33
|
-
// Static files (UI)
|
|
34
|
-
const uiPath = path.join(__dirname, '../../dist/ui');
|
|
35
|
-
if (fs.existsSync(uiPath)) {
|
|
36
|
-
app.use('/*', serveStatic({ root: uiPath }));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Fallback for SPA routing
|
|
40
|
-
app.get('*', (c) => {
|
|
41
|
-
const indexPath = path.join(uiPath, 'index.html');
|
|
42
|
-
if (fs.existsSync(indexPath)) {
|
|
43
|
-
return c.html(fs.readFileSync(indexPath, 'utf-8'));
|
|
44
|
-
}
|
|
45
|
-
return c.text('UI not built. Run "npm run build:ui" first.', 404);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
export { app };
|
|
49
|
-
|
|
50
|
-
let serverInstance: Server | null = null;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Start the HTTP server
|
|
54
|
-
*/
|
|
55
|
-
export function startServer(port: number = 37777): Server {
|
|
56
|
-
if (serverInstance) {
|
|
57
|
-
return serverInstance;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
serverInstance = serve({
|
|
61
|
-
fetch: app.fetch,
|
|
62
|
-
port,
|
|
63
|
-
hostname: '127.0.0.1'
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
console.log(`🧠 Code Memory viewer started at http://localhost:${port}`);
|
|
67
|
-
|
|
68
|
-
return serverInstance;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Stop the HTTP server
|
|
73
|
-
*/
|
|
74
|
-
export function stopServer(): void {
|
|
75
|
-
if (serverInstance) {
|
|
76
|
-
serverInstance.close();
|
|
77
|
-
serverInstance = null;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Check if server is running on given port
|
|
83
|
-
*/
|
|
84
|
-
export async function isServerRunning(port: number = 37777): Promise<boolean> {
|
|
85
|
-
try {
|
|
86
|
-
const response = await fetch(`http://127.0.0.1:${port}/health`);
|
|
87
|
-
return response.ok;
|
|
88
|
-
} catch {
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Start server if run directly
|
|
94
|
-
// Check if this file is being run directly (not imported)
|
|
95
|
-
const isMainModule = process.argv[1]?.includes('server/index') ||
|
|
96
|
-
process.argv[1]?.endsWith('server.js');
|
|
97
|
-
if (isMainModule) {
|
|
98
|
-
const port = parseInt(process.env.PORT || '37777', 10);
|
|
99
|
-
startServer(port);
|
|
100
|
-
}
|
|
1
|
+
/** Compatibility server entrypoint. Real app lives in src/apps/server. */
|
|
2
|
+
export * from '../apps/server/index.js';
|
|
@@ -103,37 +103,52 @@ function runGit(repoPath: string, command: string): string {
|
|
|
103
103
|
return execSync(`git -C ${JSON.stringify(repoPath)} ${command}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
function parseGitLog(raw: string): CommitInfo[] {
|
|
107
|
+
const lines = raw.split(/\r?\n/);
|
|
108
|
+
const commits: CommitInfo[] = [];
|
|
109
|
+
let current: CommitInfo | null = null;
|
|
110
|
+
|
|
111
|
+
for (const line of lines) {
|
|
112
|
+
if (!line.trim()) {
|
|
113
|
+
if (current) {
|
|
114
|
+
commits.push(current);
|
|
115
|
+
current = null;
|
|
116
|
+
}
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (line.includes('\t') && line.split('\t').length >= 4) {
|
|
121
|
+
if (current) commits.push(current);
|
|
122
|
+
const [hash, date, author, ...subjectRest] = line.split('\t');
|
|
123
|
+
current = { hash, date, author, subject: subjectRest.join('\t').trim(), files: [] };
|
|
124
|
+
} else if (current) {
|
|
125
|
+
current.files.push(line.trim());
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (current) commits.push(current);
|
|
130
|
+
return commits;
|
|
131
|
+
}
|
|
132
|
+
|
|
106
133
|
function getGitCommits(repoPath: string, since = '180 days ago', maxCommits = 1000): CommitInfo[] {
|
|
107
134
|
try {
|
|
108
135
|
const raw = runGit(
|
|
109
136
|
repoPath,
|
|
110
137
|
`log --since=${JSON.stringify(since)} -n ${Math.max(1, maxCommits)} --date=short --pretty=format:%H%x09%ad%x09%an%x09%s --name-only --reverse`
|
|
111
138
|
);
|
|
139
|
+
return parseGitLog(raw);
|
|
140
|
+
} catch {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
112
144
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
commits.push(current);
|
|
121
|
-
current = null;
|
|
122
|
-
}
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (line.includes('\t') && line.split('\t').length >= 4) {
|
|
127
|
-
if (current) commits.push(current);
|
|
128
|
-
const [hash, date, author, ...subjectRest] = line.split('\t');
|
|
129
|
-
current = { hash, date, author, subject: subjectRest.join('\t').trim(), files: [] };
|
|
130
|
-
} else if (current) {
|
|
131
|
-
current.files.push(line.trim());
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (current) commits.push(current);
|
|
136
|
-
return commits;
|
|
145
|
+
function getGitCommitsAfterHash(repoPath: string, hash: string, maxCommits = 1000): CommitInfo[] {
|
|
146
|
+
try {
|
|
147
|
+
const raw = runGit(
|
|
148
|
+
repoPath,
|
|
149
|
+
`log ${JSON.stringify(`${hash}..HEAD`)} -n ${Math.max(1, maxCommits)} --date=short --pretty=format:%H%x09%ad%x09%an%x09%s --name-only --reverse`
|
|
150
|
+
);
|
|
151
|
+
return parseGitLog(raw);
|
|
137
152
|
} catch {
|
|
138
153
|
return [];
|
|
139
154
|
}
|
|
@@ -194,6 +209,7 @@ function sourceLine(source: string): string {
|
|
|
194
209
|
interface ExistingManifest {
|
|
195
210
|
generatedAt?: string;
|
|
196
211
|
lastCommitDate?: string;
|
|
212
|
+
lastCommitHash?: string;
|
|
197
213
|
}
|
|
198
214
|
|
|
199
215
|
function loadExistingManifest(outDir: string): ExistingManifest | null {
|
|
@@ -238,7 +254,9 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
|
|
|
238
254
|
|
|
239
255
|
const codeFiles = walkCodeFiles(repoPath);
|
|
240
256
|
const modules = summarizeModules(repoPath, codeFiles);
|
|
241
|
-
const commits =
|
|
257
|
+
const commits = options.incremental && existingManifest?.lastCommitHash
|
|
258
|
+
? getGitCommitsAfterHash(repoPath, existingManifest.lastCommitHash, maxCommits)
|
|
259
|
+
: getGitCommits(repoPath, since, maxCommits);
|
|
242
260
|
const decisions = extractDecisions(commits);
|
|
243
261
|
const timeline = buildTimeline(commits);
|
|
244
262
|
const glossary = buildGlossary(codeFiles);
|
|
@@ -390,7 +408,8 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
|
|
|
390
408
|
...commits.slice(0, 400).map((c) => ({ type: 'commit', ref: c.hash, date: c.date, subject: c.subject }))
|
|
391
409
|
];
|
|
392
410
|
|
|
393
|
-
const latestCommitDate = commits.length > 0 ? commits[commits.length - 1].date :
|
|
411
|
+
const latestCommitDate = commits.length > 0 ? commits[commits.length - 1].date : existingManifest?.lastCommitDate;
|
|
412
|
+
const latestCommitHash = commits.length > 0 ? commits[commits.length - 1].hash : existingManifest?.lastCommitHash;
|
|
394
413
|
const manifest = {
|
|
395
414
|
generatedAt: new Date().toISOString(),
|
|
396
415
|
deterministicPipeline: true,
|
|
@@ -406,6 +425,7 @@ export async function bootstrapKnowledgeBase(options: BootstrapKnowledgeOptions)
|
|
|
406
425
|
glossaryTerms: glossary.length
|
|
407
426
|
},
|
|
408
427
|
lastCommitDate: latestCommitDate,
|
|
428
|
+
lastCommitHash: latestCommitHash,
|
|
409
429
|
outputs,
|
|
410
430
|
allOutputs,
|
|
411
431
|
sources: sourceItems
|