memhouse 0.0.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +72 -3
  3. package/bin/memhouse.js +559 -0
  4. package/cache.js +850 -0
  5. package/ch-ingest.js +329 -0
  6. package/ch-schema.js +152 -0
  7. package/clickhouse.js +87 -0
  8. package/editors/adapter-errors.js +52 -0
  9. package/editors/antigravity.js +1048 -0
  10. package/editors/base.js +321 -0
  11. package/editors/claude.js +386 -0
  12. package/editors/codebuff.js +338 -0
  13. package/editors/codex.js +537 -0
  14. package/editors/commandcode.js +166 -0
  15. package/editors/copilot-jetbrains.js +207 -0
  16. package/editors/copilot.js +260 -0
  17. package/editors/cursor-agent.js +202 -0
  18. package/editors/cursor.js +498 -0
  19. package/editors/gemini.js +231 -0
  20. package/editors/goose.js +386 -0
  21. package/editors/gsd.js +366 -0
  22. package/editors/index.js +274 -0
  23. package/editors/kiro.js +315 -0
  24. package/editors/opencode.js +432 -0
  25. package/editors/vscode.js +413 -0
  26. package/editors/windsurf.js +634 -0
  27. package/editors/zed.js +229 -0
  28. package/index.js +424 -2
  29. package/mcp-server.js +294 -0
  30. package/mem-house/DESIGN.md +119 -0
  31. package/mem-house/delivery/AGENT-INSTALL.md +87 -0
  32. package/mem-house/delivery/PROMPT.md +42 -0
  33. package/mem-house/delivery/install.sh +181 -0
  34. package/mem-house/delivery/kernel-install.md +83 -0
  35. package/mem-house/delivery/plugin/.claude-plugin/plugin.json +8 -0
  36. package/mem-house/delivery/skills/memhouse-search/SKILL.md +104 -0
  37. package/mem-house/delivery/skills/memhouse-sessions/SKILL.md +94 -0
  38. package/mem-house/delivery/skills/memhouse-sql/SKILL.md +115 -0
  39. package/mem-house/rls.sql +17 -0
  40. package/mem-house/schema.sql +145 -0
  41. package/mem-house/server/queries.js +878 -0
  42. package/mem-house/server/server.js +228 -0
  43. package/mem-house/shipper/ship.js +461 -0
  44. package/misc/syntax-check.js +38 -0
  45. package/package.json +59 -7
  46. package/pricing.js +88 -0
  47. package/pricing.json +992 -0
  48. package/public/assets/index-CCPh7a2Z.js +75 -0
  49. package/public/assets/index-DV6ONi_F.css +2 -0
  50. package/public/index.html +16 -0
  51. package/relay-client.js +306 -0
  52. package/relay-server.js +577 -0
  53. package/server.js +860 -0
  54. package/share-image.js +367 -0
  55. package/ui/eslint.config.js +29 -0
  56. package/ui/index.html +15 -0
  57. package/ui/package-lock.json +4229 -0
  58. package/ui/package.json +38 -0
  59. package/ui/src/App.jsx +364 -0
  60. package/ui/src/components/ActivityHeatmap.jsx +206 -0
  61. package/ui/src/components/AiAuditCard.jsx +254 -0
  62. package/ui/src/components/AnimatedLoader.jsx +14 -0
  63. package/ui/src/components/AnimatedLogo.jsx +96 -0
  64. package/ui/src/components/ChatSidebar.jsx +226 -0
  65. package/ui/src/components/DateRangePicker.jsx +104 -0
  66. package/ui/src/components/EditorDot.jsx +11 -0
  67. package/ui/src/components/EditorIcon.jsx +117 -0
  68. package/ui/src/components/KpiCard.jsx +9 -0
  69. package/ui/src/components/LiveFeed.jsx +128 -0
  70. package/ui/src/components/LoginScreen.jsx +81 -0
  71. package/ui/src/components/MessageRenderer.jsx +148 -0
  72. package/ui/src/components/PageHeader.jsx +11 -0
  73. package/ui/src/components/SectionTitle.jsx +3 -0
  74. package/ui/src/components/ShareModal.jsx +305 -0
  75. package/ui/src/components/TokenTimeline.jsx +258 -0
  76. package/ui/src/hooks/useLive.jsx +15 -0
  77. package/ui/src/index.css +83 -0
  78. package/ui/src/lib/api.js +343 -0
  79. package/ui/src/lib/constants.js +88 -0
  80. package/ui/src/lib/theme.jsx +23 -0
  81. package/ui/src/main.jsx +16 -0
  82. package/ui/src/pages/Artifacts.jsx +575 -0
  83. package/ui/src/pages/Compare.jsx +232 -0
  84. package/ui/src/pages/CostAnalysis.jsx +354 -0
  85. package/ui/src/pages/Dashboard.jsx +529 -0
  86. package/ui/src/pages/DeepAnalysis.jsx +495 -0
  87. package/ui/src/pages/GSD.jsx +726 -0
  88. package/ui/src/pages/MCPs.jsx +744 -0
  89. package/ui/src/pages/ProjectDetail.jsx +325 -0
  90. package/ui/src/pages/Projects.jsx +249 -0
  91. package/ui/src/pages/RelayDashboard.jsx +590 -0
  92. package/ui/src/pages/RelayUserDetail.jsx +466 -0
  93. package/ui/src/pages/Sessions.jsx +535 -0
  94. package/ui/src/pages/Settings.jsx +241 -0
  95. package/ui/src/pages/SqlViewer.jsx +370 -0
  96. package/ui/src/pages/Subscriptions.jsx +411 -0
  97. package/ui/vite.config.js +18 -0
@@ -0,0 +1,145 @@
1
+ -- mem-house HOUSE schema — the typed common session store (see DESIGN.md).
2
+ --
3
+ -- Applied by the agency OWNER (`memhouse_root`) inside its own house; names are
4
+ -- UNQUALIFIED so this works whatever the operator named the house. Requires
5
+ -- ClickHouse >= 26.2 natively; 25.11 also works because the shipper passes
6
+ -- allow_experimental_full_text_index=1 per-query when applying this file
7
+ -- (the messages text indexes are still gated on 25.x; 26.x+ ignores the flag).
8
+ --
9
+ -- Parse-on-client: the shipper runs the 17 editor adapters and ships TYPED rows —
10
+ -- these tables are the contract. `extra JSON` on each table is the escape hatch for
11
+ -- adapter fields not yet normalized (never lose data to the schema).
12
+ --
13
+ -- Versioning/idempotency: ReplacingMergeTree(ingested_at) everywhere. `messages` is
14
+ -- keyed (session_id, user_id, seq): re-shipping a grown or corrected session
15
+ -- REPLACES stale rows (latest-wins) instead of accumulating variants, and the
16
+ -- user_id in every key means two members shipping the same adapter-local
17
+ -- session_id can never collapse or overwrite each other's rows. Identity is
18
+ -- server-stamped (`user_id MATERIALIZED currentUser()`; writers must use
19
+ -- async_insert=0) and is the RLS anchor (rls.sql). Readers should query with the
20
+ -- `final=1` setting.
21
+ --
22
+ -- session_id is CANONICAL and globally unique: '<source>:<adapter-local id>',
23
+ -- stamped by the shipper. Adapter-local ids are only unique within one editor;
24
+ -- the source prefix makes every key, incremental comparison, delete, view join,
25
+ -- and API id collision-free across editors. `source` remains a plain column for
26
+ -- filtering.
27
+ --
28
+ -- BREAKING (pre-release): the user_id-in-key change alters ORDER BY, which
29
+ -- CREATE TABLE IF NOT EXISTS will NOT apply to an existing house — recreate with
30
+ -- `memhouse reset` (or DROP the tables and re-run --ensure-schema). The
31
+ -- source-prefixed session_id change needs no DDL, but rows shipped before it
32
+ -- linger under their old bare ids — run `memhouse reset` once after upgrading.
33
+
34
+ -- One row per session (adapter-level metadata; aggregates live in sessions_v).
35
+ CREATE TABLE IF NOT EXISTS sessions
36
+ (
37
+ session_id String,
38
+ source LowCardinality(String),
39
+ host LowCardinality(String),
40
+ name String DEFAULT '',
41
+ mode LowCardinality(String) DEFAULT '',
42
+ folder String DEFAULT '',
43
+ project String DEFAULT '',
44
+ git_branch String DEFAULT '',
45
+ created_at Nullable(DateTime64(3, 'UTC')),
46
+ last_updated_at Nullable(DateTime64(3, 'UTC')),
47
+ message_count UInt32 DEFAULT 0,
48
+ path String DEFAULT '',
49
+ extra JSON,
50
+ user_id String MATERIALIZED currentUser(),
51
+ ingested_at DateTime64(3, 'UTC') DEFAULT now64(3)
52
+ )
53
+ ENGINE = ReplacingMergeTree(ingested_at)
54
+ ORDER BY (session_id, user_id);
55
+
56
+ -- One row per message. FTS: two lower(text) materialized columns each carry one
57
+ -- text index (ngram for substring/LIKE, word for token match) — query with
58
+ -- lowercased terms, SELECT `text` for display.
59
+ CREATE TABLE IF NOT EXISTS messages
60
+ (
61
+ session_id String,
62
+ seq UInt32,
63
+ source LowCardinality(String),
64
+ host LowCardinality(String),
65
+ ts DateTime64(3, 'UTC'),
66
+ role LowCardinality(String),
67
+ model LowCardinality(String) DEFAULT '',
68
+ input_tokens UInt64 DEFAULT 0,
69
+ output_tokens UInt64 DEFAULT 0,
70
+ cache_read_tokens UInt64 DEFAULT 0,
71
+ cache_write_tokens UInt64 DEFAULT 0,
72
+ text String,
73
+ project String DEFAULT '',
74
+ folder String DEFAULT '',
75
+ is_subagent Bool DEFAULT false,
76
+ extra JSON,
77
+ line_hash UInt64,
78
+ user_id String MATERIALIZED currentUser(),
79
+ ingested_at DateTime64(3, 'UTC') DEFAULT now64(3),
80
+ text_ngram String MATERIALIZED lower(text),
81
+ text_word String MATERIALIZED lower(text),
82
+ INDEX idx_text_ngram text_ngram TYPE text(tokenizer = ngrams(3)) GRANULARITY 1,
83
+ INDEX idx_text_word text_word TYPE text(tokenizer = splitByNonAlpha) GRANULARITY 1
84
+ )
85
+ ENGINE = ReplacingMergeTree(ingested_at)
86
+ ORDER BY (session_id, user_id, seq);
87
+
88
+ -- One row per tool call (memory-house has no equivalent; this powers the tool
89
+ -- analytics). `seq` = owning message's seq; `idx` = call index within the session.
90
+ CREATE TABLE IF NOT EXISTS tool_calls
91
+ (
92
+ session_id String,
93
+ seq UInt32,
94
+ idx UInt32,
95
+ source LowCardinality(String),
96
+ host LowCardinality(String),
97
+ tool_name LowCardinality(String),
98
+ args String DEFAULT '{}',
99
+ ts DateTime64(3, 'UTC'),
100
+ project String DEFAULT '',
101
+ folder String DEFAULT '',
102
+ user_id String MATERIALIZED currentUser(),
103
+ ingested_at DateTime64(3, 'UTC') DEFAULT now64(3)
104
+ )
105
+ ENGINE = ReplacingMergeTree(ingested_at)
106
+ ORDER BY (session_id, user_id, idx);
107
+
108
+ -- Analytics-ready rollup: session metadata + message aggregates. Query with final=1.
109
+ -- LEFT JOIN (not INNER): stable-empty sessions are deliberately stored (the row
110
+ -- absorbs the incremental skip) and must stay visible with zero aggregates, not
111
+ -- vanish from every dashboard count. join_use_nulls makes unmatched message
112
+ -- columns NULL so count(m.seq)/coalesce produce true zeros instead of counting
113
+ -- the placeholder row.
114
+ CREATE OR REPLACE VIEW sessions_v AS
115
+ SELECT
116
+ s.session_id AS session_id,
117
+ any(s.source) AS source,
118
+ any(s.host) AS host,
119
+ any(s.name) AS name,
120
+ any(s.mode) AS mode,
121
+ any(s.folder) AS folder,
122
+ any(s.project) AS project,
123
+ any(s.git_branch) AS git_branch,
124
+ s.user_id AS user_id,
125
+ any(s.created_at) AS created_at,
126
+ any(s.last_updated_at) AS last_updated_at,
127
+ min(m.ts) AS started,
128
+ max(m.ts) AS ended,
129
+ coalesce(dateDiff('second', min(m.ts), max(m.ts)), 0) AS duration_sec,
130
+ count(m.seq) AS total_msgs,
131
+ countIf(m.role = 'user') AS user_msgs,
132
+ countIf(m.role = 'assistant') AS assistant_msgs,
133
+ countIf(m.is_subagent) AS subagent_msgs,
134
+ groupUniqArrayIf(m.model, m.model NOT IN ('', '<synthetic>')) AS models,
135
+ coalesce(sum(m.input_tokens), 0) AS input_tokens,
136
+ coalesce(sum(m.output_tokens), 0) AS output_tokens,
137
+ coalesce(sum(m.cache_read_tokens), 0) AS cache_read_tokens,
138
+ coalesce(sum(m.cache_write_tokens), 0) AS cache_write_tokens,
139
+ coalesce(sumIf(length(m.text), m.role = 'user'), 0) AS user_chars,
140
+ coalesce(sumIf(length(m.text), m.role = 'assistant'), 0) AS assistant_chars,
141
+ coalesce(substring(argMinIf(m.text, m.seq, m.role = 'user' AND m.text != ''), 1, 200), '') AS first_prompt
142
+ FROM sessions AS s
143
+ LEFT JOIN messages AS m ON m.session_id = s.session_id AND m.user_id = s.user_id
144
+ GROUP BY s.session_id, s.user_id
145
+ SETTINGS join_use_nulls = 1;