mumpix 1.0.19 → 1.1.3

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 (38) hide show
  1. package/CHANGELOG.md +82 -11
  2. package/README.md +278 -8
  3. package/bin/mumpix.js +1 -405
  4. package/examples/agent-memory.js +1 -1
  5. package/examples/basic.js +1 -1
  6. package/examples/behavioral-primitives.js +50 -0
  7. package/examples/recall-quality-suite.js +156 -0
  8. package/examples/verified-mode.js +1 -1
  9. package/package.json +24 -13
  10. package/scripts/bench-semantic.cjs +76 -0
  11. package/scripts/test-license-modes.cjs +87 -0
  12. package/scripts/test-phase0.cjs +137 -0
  13. package/scripts/test-semantic.cjs +411 -0
  14. package/src/brp/index.js +1 -0
  15. package/src/collapse/index.js +1 -0
  16. package/src/core/MumpixDB.js +264 -323
  17. package/src/core/audit.js +1 -173
  18. package/src/core/auth.js +1 -232
  19. package/src/core/inverted-index.js +249 -0
  20. package/src/core/license.js +1 -267
  21. package/src/core/ml-dsa.mjs +1 -25
  22. package/src/core/ml-kem.mjs +1 -32
  23. package/src/core/recall.js +226 -112
  24. package/src/core/semantic-sidecar.js +312 -0
  25. package/src/core/store.js +365 -288
  26. package/src/core/wal-writer.js +83 -0
  27. package/src/index.js +20 -34
  28. package/src/integrations/developer-sdk.js +1 -165
  29. package/src/integrations/langchain-official.js +1 -0
  30. package/src/integrations/langchain.js +1 -131
  31. package/src/integrations/llamaindex-official.js +1 -0
  32. package/src/integrations/llamaindex.js +1 -86
  33. package/src/integrations/vector-sidecar.js +325 -0
  34. package/src/rlp/index.js +1 -0
  35. package/src/temporal/engine.js +1 -1894
  36. package/src/temporal/indexes.js +1 -178
  37. package/src/temporal/operators.js +1 -186
  38. package/scripts/postinstall-auth.js +0 -101
@@ -1,178 +1 @@
1
- 'use strict';
2
-
3
- const { dedupeEvents, normalizeText } = require('./operators');
4
-
5
- function addToMapSet(map, key, value) {
6
- if (!key) return;
7
- if (!map.has(key)) map.set(key, []);
8
- map.get(key).push(value);
9
- }
10
-
11
- function uniqueWords(value) {
12
- return Array.from(new Set(
13
- normalizeText(value)
14
- .split(' ')
15
- .filter(Boolean)
16
- .filter((token) => token.length > 2)
17
- ));
18
- }
19
-
20
- function buildEventIndex(events) {
21
- const normalized = dedupeEvents(events);
22
- const keys = new Set();
23
- const byId = new Map();
24
- const byTitle = new Map();
25
- const byAlias = new Map();
26
- const byEntity = new Map();
27
- const byType = new Map();
28
- const byKind = new Map();
29
- const byDate = new Map();
30
- const byWord = new Map();
31
- const byWorkspace = new Map();
32
- const byRepo = new Map();
33
- const bySource = new Map();
34
-
35
- for (const event of normalized) {
36
- keys.add(signatureForEvent(event));
37
- if (event.event_id) byId.set(event.event_id, event);
38
-
39
- addToMapSet(byTitle, normalizeText(event.title), event);
40
- for (const alias of event.aliases || []) addToMapSet(byAlias, normalizeText(alias), event);
41
- for (const entity of event.entities || []) addToMapSet(byEntity, normalizeText(entity), event);
42
- addToMapSet(byType, normalizeText(event.event_type), event);
43
- addToMapSet(byKind, normalizeText(event.event_kind), event);
44
- if (event.event_date) addToMapSet(byDate, event.event_date, event);
45
- if (event.workspace) addToMapSet(byWorkspace, normalizeText(event.workspace), event);
46
- if (event.repo) addToMapSet(byRepo, normalizeText(event.repo), event);
47
- if (event.source) addToMapSet(bySource, normalizeText(event.source), event);
48
-
49
- for (const token of uniqueWords([
50
- event.title,
51
- (event.aliases || []).join(' '),
52
- (event.entities || []).join(' '),
53
- event.event_type,
54
- event.event_kind,
55
- event.workspace,
56
- event.repo,
57
- event.source,
58
- ].join(' '))) {
59
- addToMapSet(byWord, token, event);
60
- }
61
- }
62
-
63
- return {
64
- events: normalized,
65
- byId,
66
- byTitle,
67
- byAlias,
68
- byEntity,
69
- byType,
70
- byKind,
71
- byDate,
72
- byWord,
73
- byWorkspace,
74
- byRepo,
75
- bySource,
76
- _keys: keys,
77
- stats: {
78
- events: normalized.length,
79
- titles: byTitle.size,
80
- aliases: byAlias.size,
81
- entities: byEntity.size,
82
- types: byType.size,
83
- kinds: byKind.size,
84
- dates: byDate.size,
85
- words: byWord.size,
86
- workspaces: byWorkspace.size,
87
- repos: byRepo.size,
88
- sources: bySource.size,
89
- },
90
- };
91
- }
92
-
93
- function signatureForEvent(event) {
94
- return [
95
- event.event_type,
96
- event.event_kind,
97
- normalizeText(event.title),
98
- event.event_date || '',
99
- event.mention_date || '',
100
- event.workspace || '',
101
- event.repo || '',
102
- event.source || '',
103
- event.source_message_key || '',
104
- ].join('|');
105
- }
106
-
107
- function appendEventIndex(index, events) {
108
- const target = index || buildEventIndex([]);
109
- const additions = dedupeEvents(events);
110
- for (const event of additions) {
111
- const key = signatureForEvent(event);
112
- if (target._keys.has(key)) continue;
113
- target._keys.add(key);
114
- target.events.push(event);
115
- if (event.event_id) target.byId.set(event.event_id, event);
116
- addToMapSet(target.byTitle, normalizeText(event.title), event);
117
- for (const alias of event.aliases || []) addToMapSet(target.byAlias, normalizeText(alias), event);
118
- for (const entity of event.entities || []) addToMapSet(target.byEntity, normalizeText(entity), event);
119
- addToMapSet(target.byType, normalizeText(event.event_type), event);
120
- addToMapSet(target.byKind, normalizeText(event.event_kind), event);
121
- if (event.event_date) addToMapSet(target.byDate, event.event_date, event);
122
- if (event.workspace) addToMapSet(target.byWorkspace, normalizeText(event.workspace), event);
123
- if (event.repo) addToMapSet(target.byRepo, normalizeText(event.repo), event);
124
- if (event.source) addToMapSet(target.bySource, normalizeText(event.source), event);
125
-
126
- for (const token of uniqueWords([
127
- event.title,
128
- (event.aliases || []).join(' '),
129
- (event.entities || []).join(' '),
130
- event.event_type,
131
- event.event_kind,
132
- event.workspace,
133
- event.repo,
134
- event.source,
135
- ].join(' '))) {
136
- addToMapSet(target.byWord, token, event);
137
- }
138
- }
139
-
140
- target.stats = {
141
- events: target.events.length,
142
- titles: target.byTitle.size,
143
- aliases: target.byAlias.size,
144
- entities: target.byEntity.size,
145
- types: target.byType.size,
146
- kinds: target.byKind.size,
147
- dates: target.byDate.size,
148
- words: target.byWord.size,
149
- workspaces: target.byWorkspace.size,
150
- repos: target.byRepo.size,
151
- sources: target.bySource.size,
152
- };
153
-
154
- return target;
155
- }
156
-
157
- function eventCandidatesForQuery(index, query) {
158
- if (!index) return [];
159
- const tokens = uniqueWords(query);
160
- const seen = new Map();
161
-
162
- for (const token of tokens) {
163
- const matches = index.byWord.get(token) || [];
164
- for (const event of matches) {
165
- const key = event.event_id || `${event.title}|${event.event_date || event.mention_date || ''}`;
166
- if (!seen.has(key)) seen.set(key, event);
167
- }
168
- }
169
-
170
- return Array.from(seen.values());
171
- }
172
-
173
- module.exports = {
174
- buildEventIndex,
175
- appendEventIndex,
176
- eventCandidatesForQuery,
177
- uniqueWords,
178
- };
1
+ "use strict";const{dedupeEvents:e,normalizeText:t}=require("./operators");function s(e,t,s){t&&(e.has(t)||e.set(t,[]),e.get(t).push(s))}function n(e){return Array.from(new Set(t(e).split(" ").filter(Boolean).filter(e=>e.length>2)))}function o(o){const r=e(o),a=new Set,p=new Map,y=new Map,c=new Map,d=new Map,u=new Map,b=new Map,f=new Map,l=new Map,v=new Map,_=new Map,w=new Map;for(const e of r){a.add(i(e)),e.event_id&&p.set(e.event_id,e),s(y,t(e.title),e);for(const n of e.aliases||[])s(c,t(n),e);for(const n of e.entities||[])s(d,t(n),e);s(u,t(e.event_type),e),s(b,t(e.event_kind),e),e.event_date&&s(f,e.event_date,e),e.workspace&&s(v,t(e.workspace),e),e.repo&&s(_,t(e.repo),e),e.source&&s(w,t(e.source),e);for(const t of n([e.title,(e.aliases||[]).join(" "),(e.entities||[]).join(" "),e.event_type,e.event_kind,e.workspace,e.repo,e.source].join(" ")))s(l,t,e)}return{events:r,byId:p,byTitle:y,byAlias:c,byEntity:d,byType:u,byKind:b,byDate:f,byWord:l,byWorkspace:v,byRepo:_,bySource:w,_keys:a,stats:{events:r.length,titles:y.size,aliases:c.size,entities:d.size,types:u.size,kinds:b.size,dates:f.size,words:l.size,workspaces:v.size,repos:_.size,sources:w.size}}}function i(e){return[e.event_type,e.event_kind,t(e.title),e.event_date||"",e.mention_date||"",e.workspace||"",e.repo||"",e.source||"",e.source_message_key||""].join("|")}module.exports={buildEventIndex:o,appendEventIndex:function(r,a){const p=r||o([]),y=e(a);for(const e of y){const o=i(e);if(!p._keys.has(o)){p._keys.add(o),p.events.push(e),e.event_id&&p.byId.set(e.event_id,e),s(p.byTitle,t(e.title),e);for(const n of e.aliases||[])s(p.byAlias,t(n),e);for(const n of e.entities||[])s(p.byEntity,t(n),e);s(p.byType,t(e.event_type),e),s(p.byKind,t(e.event_kind),e),e.event_date&&s(p.byDate,e.event_date,e),e.workspace&&s(p.byWorkspace,t(e.workspace),e),e.repo&&s(p.byRepo,t(e.repo),e),e.source&&s(p.bySource,t(e.source),e);for(const t of n([e.title,(e.aliases||[]).join(" "),(e.entities||[]).join(" "),e.event_type,e.event_kind,e.workspace,e.repo,e.source].join(" ")))s(p.byWord,t,e)}}return p.stats={events:p.events.length,titles:p.byTitle.size,aliases:p.byAlias.size,entities:p.byEntity.size,types:p.byType.size,kinds:p.byKind.size,dates:p.byDate.size,words:p.byWord.size,workspaces:p.byWorkspace.size,repos:p.byRepo.size,sources:p.bySource.size},p},eventCandidatesForQuery:function(e,t){if(!e)return[];const s=n(t),o=new Map;for(const t of s){const s=e.byWord.get(t)||[];for(const e of s){const t=e.event_id||`${e.title}|${e.event_date||e.mention_date||""}`;o.has(t)||o.set(t,e)}}return Array.from(o.values())},uniqueWords:n};
@@ -1,186 +1 @@
1
- 'use strict';
2
-
3
- // Generated by scripts/build-package.cjs from src/memory/events/operators.js
4
- // Do not edit this file directly in the publish tree.
5
- function normalizeText(value) {
6
- return String(value || "")
7
- .toLowerCase()
8
- .replace(/["'“”‘’]/g, "")
9
- .replace(/[^a-z0-9\s/.-]/g, " ")
10
- .replace(/\s+/g, " ")
11
- .trim();
12
- }
13
-
14
- function toEpochDay(isoDate) {
15
- if (!isoDate) return null;
16
- const ts = Date.parse(`${isoDate}T00:00:00Z`);
17
- return Number.isFinite(ts) ? Math.floor(ts / 86400000) : null;
18
- }
19
-
20
- function normalizeEventRecord(record) {
21
- const eventDate = record && record.event_date ? record.event_date : null;
22
- const mentionDate = record && record.mention_date ? record.mention_date : null;
23
- const observedAt = record && record.observed_at ? record.observed_at : (mentionDate || null);
24
- const referencedAt = record && record.referenced_at ? record.referenced_at : (eventDate || mentionDate || null);
25
- return {
26
- ...record,
27
- title: String(record && record.title ? record.title : "").trim(),
28
- event_type: String(record && record.event_type ? record.event_type : "other").trim() || "other",
29
- event_kind: String(record && (record.event_kind || record.event_type) ? (record.event_kind || record.event_type) : "other").trim() || "other",
30
- aliases: Array.isArray(record && record.aliases) ? record.aliases.filter(Boolean).map(String) : [],
31
- entities: Array.isArray(record && record.entities) ? record.entities.filter(Boolean).map(String) : [],
32
- event_date: eventDate,
33
- mention_date: mentionDate,
34
- observed_at: observedAt,
35
- referenced_at: referencedAt,
36
- relative_offset: record && record.relative_offset ? String(record.relative_offset) : null,
37
- event_phase: record && record.event_phase ? String(record.event_phase) : null,
38
- time_granularity: record && record.time_granularity ? String(record.time_granularity) : "day",
39
- temporal_confidence: record && typeof record.temporal_confidence === "number" ? record.temporal_confidence : null,
40
- source_span: record && record.source_span ? String(record.source_span) : null,
41
- epoch_day: record && typeof record.epoch_day === "number" ? record.epoch_day : toEpochDay(referencedAt),
42
- date_source: record && record.date_source ? String(record.date_source) : "implicit",
43
- };
44
- }
45
-
46
- function dedupeEvents(events) {
47
- const seen = new Set();
48
- const out = [];
49
- for (const event of (events || []).map(normalizeEventRecord)) {
50
- const key = [
51
- event.event_type,
52
- event.event_kind,
53
- normalizeText(event.title),
54
- event.event_date || "",
55
- event.mention_date || "",
56
- ].join("|");
57
- if (seen.has(key)) continue;
58
- seen.add(key);
59
- out.push(event);
60
- }
61
- return out;
62
- }
63
-
64
- function scoreEventMatch(event, anchor, options = {}) {
65
- const anchorNorm = normalizeText(anchor);
66
- if (!anchorNorm) return 0;
67
-
68
- const titleNorm = normalizeText(event.title);
69
- const aliasNorms = event.aliases.map(normalizeText);
70
- const entityNorms = event.entities.map(normalizeText);
71
- let score = 0;
72
-
73
- if (titleNorm === anchorNorm) score += 100;
74
- else if (titleNorm.includes(anchorNorm) || anchorNorm.includes(titleNorm)) score += 45;
75
-
76
- for (const alias of aliasNorms) {
77
- if (alias === anchorNorm) score += 80;
78
- else if (alias.includes(anchorNorm) || anchorNorm.includes(alias)) score += 25;
79
- }
80
-
81
- for (const entity of entityNorms) {
82
- if (entity === anchorNorm) score += 50;
83
- else if (entity.includes(anchorNorm) || anchorNorm.includes(entity)) score += 15;
84
- }
85
-
86
- if (options.type && event.event_type === options.type) score += 15;
87
- if (options.kind && event.event_kind === options.kind) score += 15;
88
- if (options.semantics === "acquired" && event.event_type === "preorder") score -= 1000;
89
- if (options.preferEventPhase && event.event_phase === options.preferEventPhase) score += 12;
90
- if (event.event_phase === "preparation" && !/\bprepar/i.test(anchorNorm)) score -= 18;
91
- if (event.event_phase === "scheduled") score += 4;
92
-
93
- if (event.date_source === "explicit") score += 10;
94
- else if (event.date_source === "derived") score += 6;
95
- else if (event.date_source === "mention") score += 2;
96
-
97
- if (typeof event.temporal_confidence === "number") {
98
- score += Math.round(event.temporal_confidence * 4);
99
- }
100
-
101
- return score;
102
- }
103
-
104
- function resolveEvent(events, anchor, options = {}) {
105
- const candidates = dedupeEvents(events).filter((event) => {
106
- if (!event.title || event.epoch_day == null) return false;
107
- if (options.type && event.event_type !== options.type) return false;
108
- if (options.kind && event.event_kind !== options.kind) return false;
109
- if (options.excludeType && event.event_type === options.excludeType) return false;
110
- if (options.semantics === "acquired" && event.event_type === "preorder") return false;
111
- return scoreEventMatch(event, anchor, options) > 0;
112
- });
113
-
114
- const ranked = candidates.sort((a, b) => {
115
- const scoreDiff = scoreEventMatch(b, anchor, options) - scoreEventMatch(a, anchor, options);
116
- if (scoreDiff !== 0) return scoreDiff;
117
- if (options.preferLatest) return b.epoch_day - a.epoch_day;
118
- return a.epoch_day - b.epoch_day;
119
- });
120
-
121
- return ranked[0] || null;
122
- }
123
-
124
- function first(events, options = {}) {
125
- return dedupeEvents(events)
126
- .filter((event) => event.epoch_day != null)
127
- .filter((event) => !options.type || event.event_type === options.type)
128
- .filter((event) => !options.kind || event.event_kind === options.kind)
129
- .sort((a, b) => a.epoch_day - b.epoch_day)[0] || null;
130
- }
131
-
132
- function last(events, options = {}) {
133
- return dedupeEvents(events)
134
- .filter((event) => event.epoch_day != null)
135
- .filter((event) => !options.type || event.event_type === options.type)
136
- .filter((event) => !options.kind || event.event_kind === options.kind)
137
- .sort((a, b) => b.epoch_day - a.epoch_day)[0] || null;
138
- }
139
-
140
- function firstAfter(events, query = {}) {
141
- const anchor = query.anchor || first(events, { type: query.anchorType, kind: query.anchorKind });
142
- if (!anchor || anchor.epoch_day == null) return null;
143
-
144
- return dedupeEvents(events)
145
- .filter((event) => event.epoch_day != null && event.epoch_day > anchor.epoch_day)
146
- .filter((event) => !query.targetType || event.event_type === query.targetType)
147
- .filter((event) => !query.targetKind || event.event_kind === query.targetKind)
148
- .sort((a, b) => a.epoch_day - b.epoch_day)[0] || null;
149
- }
150
-
151
- function daysBetween(left, right) {
152
- if (!left || !right || left.epoch_day == null || right.epoch_day == null) return null;
153
- return Math.abs(right.epoch_day - left.epoch_day);
154
- }
155
-
156
- function monthsSince(event, referenceDate) {
157
- if (!event || !referenceDate) return null;
158
- const [yearA, monthA] = String(event.referenced_at || event.event_date || event.mention_date || "").split("-").map(Number);
159
- const [yearB, monthB] = String(referenceDate).split("-").map(Number);
160
- if (!yearA || !monthA || !yearB || !monthB) return null;
161
- return ((yearB - yearA) * 12) + (monthB - monthA);
162
- }
163
-
164
- function countBefore(events, pivot, options = {}) {
165
- if (!pivot || pivot.epoch_day == null) return null;
166
- return dedupeEvents(events)
167
- .filter((event) => event.epoch_day != null && event.epoch_day < pivot.epoch_day)
168
- .filter((event) => !options.type || event.event_type === options.type)
169
- .filter((event) => !options.kind || event.event_kind === options.kind)
170
- .length;
171
- }
172
-
173
- module.exports = {
174
- normalizeText,
175
- toEpochDay,
176
- normalizeEventRecord,
177
- dedupeEvents,
178
- scoreEventMatch,
179
- resolveEvent,
180
- first,
181
- last,
182
- firstAfter,
183
- daysBetween,
184
- monthsSince,
185
- countBefore,
186
- };
1
+ "use strict";function e(e){return String(e||"").toLowerCase().replace(/["'\u201c\u201d\u2018\u2019]/g,"").replace(/[^a-z0-9\s/.-]/g," ").replace(/\s+/g," ").trim()}function t(t){return e(t).split(" ").filter(Boolean).filter(e=>e.length>2)}function n(e,n){const r=t(e),i=new Set(t(n));if(!r.length||!i.size)return 0;return r.filter(e=>i.has(e)).length/r.length}function r(e){if(!e)return null;const t=Date.parse(`${e}T00:00:00Z`);return Number.isFinite(t)?Math.floor(t/864e5):null}function i(e){const t=String(e||"").match(/^(\d{4})-(\d{2})-(\d{2})$/);return t?{year:Number(t[1]),month:Number(t[2]),day:Number(t[3])}:null}function a(e){const t=e&&e.event_date?e.event_date:null,n=e&&e.mention_date?e.mention_date:null,i=e&&e.observed_at?e.observed_at:n||null,a=e&&e.referenced_at?e.referenced_at:t||n||null;return{...e,title:String(e&&e.title?e.title:"").trim(),event_type:String(e&&e.event_type?e.event_type:"other").trim()||"other",event_kind:String(e&&(e.event_kind||e.event_type)?e.event_kind||e.event_type:"other").trim()||"other",aliases:Array.isArray(e&&e.aliases)?e.aliases.filter(Boolean).map(String):[],entities:Array.isArray(e&&e.entities)?e.entities.filter(Boolean).map(String):[],event_date:t,mention_date:n,observed_at:i,referenced_at:a,relative_offset:e&&e.relative_offset?String(e.relative_offset):null,event_phase:e&&e.event_phase?String(e.event_phase):null,time_granularity:e&&e.time_granularity?String(e.time_granularity):"day",temporal_confidence:e&&"number"==typeof e.temporal_confidence?e.temporal_confidence:null,source_span:e&&e.source_span?String(e.source_span):null,epoch_day:e&&"number"==typeof e.epoch_day?e.epoch_day:r(a),date_source:e&&e.date_source?String(e.date_source):"implicit"}}function o(t){const n=new Set,r=[];for(const i of(t||[]).map(a)){const t=[i.canonical_event_id||"",i.event_type,i.event_kind,e(i.title),i.referenced_at||i.event_date||"",i.mention_date||""].join("|");n.has(t)||(n.add(t),r.push(i))}return r}function l(t,r,i={}){const a=e(r);if(!a)return 0;const o=e(t.title),l=t.aliases.map(e),c=t.entities.map(e),d=e(t.source_span),p=e(t.raw),u=function(t){return[t.title,...t.aliases||[],...t.entities||[],t.source_span,t.raw].filter(Boolean).map(e).join(" ")}(t);let s=0;o===a?s+=100:(o.includes(a)||a.includes(o))&&(s+=45);for(const e of l)e===a?s+=80:(e.includes(a)||a.includes(e))&&(s+=25);for(const e of c)e===a?s+=50:(e.includes(a)||a.includes(e))&&(s+=15);return d&&((d.includes(a)||a.includes(d))&&(s+=24),s+=Math.round(18*n(a,d))),p&&(p.includes(a)&&(s+=16),s+=Math.round(12*n(a,p))),u&&(s+=Math.round(20*n(a,u))),i.type&&t.event_type===i.type&&(s+=15),i.kind&&t.event_kind===i.kind&&(s+=15),i.preferType&&t.event_type===i.preferType&&(s+=12),i.preferKind&&t.event_kind===i.preferKind&&(s+=12),"acquired"===i.semantics&&"preorder"===t.event_type&&(s-=1e3),i.preferEventPhase&&t.event_phase===i.preferEventPhase&&(s+=12),"preparation"!==t.event_phase||/\bprepar/i.test(a)||(s-=18),"scheduled"===t.event_phase&&(s+=4),"attended_at"===t.event_phase&&/\b(workshop|webinar|meetup|festival|event|service|mass)\b/.test(a)&&(s+=6),"start"===t.event_type&&/\b(start|using|working|watching|reading|learning|taking|member|use|been)\b/.test(a)&&(s+=8),"explicit"===t.date_source?s+=10:"derived"===t.date_source?s+=6:"mention"===t.date_source&&(s+=2),"number"==typeof t.temporal_confidence&&(s+=Math.round(4*t.temporal_confidence)),s}function c(e,t={}){return o(e).filter(e=>null!=e.epoch_day).filter(e=>!t.type||e.event_type===t.type).filter(e=>!t.kind||e.event_kind===t.kind).sort((e,t)=>e.epoch_day-t.epoch_day)[0]||null}function d(e,t){if(!e||!t)return null;const n=i(e.referenced_at||e.event_date||e.mention_date||""),r=i(t);if(!n||!r)return null;let a=12*(r.year-n.year)+(r.month-n.month);return r.day<n.day&&(a-=1),a}module.exports={normalizeText:e,tokenizeText:t,toEpochDay:r,normalizeEventRecord:a,dedupeEvents:o,scoreEventMatch:l,resolveEvent:function(e,t,n={}){let r=o(e).filter(e=>!(!e.title||null==e.epoch_day)&&((!n.type||e.event_type===n.type)&&((!n.kind||e.event_kind===n.kind)&&((!n.excludeType||e.event_type!==n.excludeType)&&(("acquired"!==n.semantics||"preorder"!==e.event_type)&&l(e,t,n)>0)))));if(n.preferType){const e=r.filter(e=>e.event_type===n.preferType);e.length&&(r=e)}if(n.preferKind){const e=r.filter(e=>e.event_kind===n.preferKind);e.length&&(r=e)}if(n.preferEventPhase){const e=r.filter(e=>e.event_phase===n.preferEventPhase);e.length&&(r=e)}return r.sort((e,r)=>{const i=l(r,t,n)-l(e,t,n);return 0!==i?i:n.preferLatest?r.epoch_day-e.epoch_day:e.epoch_day-r.epoch_day})[0]||null},first:c,last:function(e,t={}){return o(e).filter(e=>null!=e.epoch_day).filter(e=>!t.type||e.event_type===t.type).filter(e=>!t.kind||e.event_kind===t.kind).sort((e,t)=>t.epoch_day-e.epoch_day)[0]||null},firstAfter:function(e,t={}){const n=t.anchor||c(e,{type:t.anchorType,kind:t.anchorKind});return n&&null!=n.epoch_day&&o(e).filter(e=>null!=e.epoch_day&&e.epoch_day>n.epoch_day).filter(e=>!t.targetType||e.event_type===t.targetType).filter(e=>!t.targetKind||e.event_kind===t.targetKind).sort((e,t)=>e.epoch_day-t.epoch_day)[0]||null},daysBetween:function(e,t){return e&&t&&null!=e.epoch_day&&null!=t.epoch_day?Math.abs(t.epoch_day-e.epoch_day):null},daysDifference:function(e,t){return e&&t&&null!=e.epoch_day&&null!=t.epoch_day?t.epoch_day-e.epoch_day:null},monthsSince:d,monthsBetween:function(e,t){if(!e||!t)return null;const n=e.referenced_at||e.event_date||e.mention_date||"",r=d(e,t.referenced_at||t.event_date||t.mention_date||"");if(null!=r)return Math.abs(r);const i=d(t,n);return null==i?null:Math.abs(i)},countBefore:function(e,t,n={}){return t&&null!=t.epoch_day?o(e).filter(e=>null!=e.epoch_day&&e.epoch_day<t.epoch_day).filter(e=>!n.type||e.event_type===n.type).filter(e=>!n.kind||e.event_kind===n.kind).reduce((e,t)=>e+("number"==typeof t.event_count?t.event_count:1),0):null},sumEventCounts:function(e,t={}){return o(e).filter(e=>!t.type||e.event_type===t.type).filter(e=>!t.kind||e.event_kind===t.kind).filter(e=>!t.afterEpochDay||null!=e.epoch_day&&e.epoch_day>=t.afterEpochDay).filter(e=>!t.beforeEpochDay||null!=e.epoch_day&&e.epoch_day<=t.beforeEpochDay).reduce((e,t)=>e+("number"==typeof t.event_count?t.event_count:1),0)}};
@@ -1,101 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const readline = require('readline');
5
- const { spawn } = require('child_process');
6
- const {
7
- loginWithDeviceFlow,
8
- exchangeTokenForLicense,
9
- authStatePath,
10
- } = require('../src/core/auth');
11
-
12
- function isInteractive() {
13
- return Boolean(process.stdin.isTTY && process.stdout.isTTY && process.env.CI !== 'true');
14
- }
15
-
16
- function fmtExpiry(ts) {
17
- if (!ts) return '-';
18
- const d = new Date(Number(ts));
19
- if (Number.isNaN(d.getTime())) return '-';
20
- return d.toISOString();
21
- }
22
-
23
- function openBrowser(url) {
24
- if (!url) return false;
25
- try {
26
- if (process.platform === 'darwin') {
27
- spawn('open', [url], { stdio: 'ignore', detached: true }).unref();
28
- return true;
29
- }
30
- if (process.platform === 'win32') {
31
- spawn('cmd', ['/c', 'start', '', url], { stdio: 'ignore', detached: true }).unref();
32
- return true;
33
- }
34
- spawn('xdg-open', [url], { stdio: 'ignore', detached: true }).unref();
35
- return true;
36
- } catch {
37
- return false;
38
- }
39
- }
40
-
41
- function ask(question) {
42
- return new Promise((resolve) => {
43
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
44
- rl.question(question, (answer) => {
45
- rl.close();
46
- resolve(String(answer || ''));
47
- });
48
- });
49
- }
50
-
51
- async function run() {
52
- try {
53
- if (String(process.env.MUMPIX_POSTINSTALL_AUTH || '1') === '0') return;
54
-
55
- const token = String(process.env.MUMPIX_AUTH_TOKEN || '').trim();
56
- if (token) {
57
- const state = await exchangeTokenForLicense(token, {});
58
- console.log(`[mumpix] account linked via token. tier=${state.license.tier || '-'} exp=${fmtExpiry(state.license.exp)}`);
59
- return;
60
- }
61
-
62
- if (!isInteractive()) {
63
- console.log('[mumpix] install complete. auth skipped (non-interactive).');
64
- console.log('[mumpix] run "mumpix auth login" later to unlock strict/verified. default mode remains eventual.');
65
- return;
66
- }
67
-
68
- console.log('\n[mumpix] press Enter to login and link your account.');
69
- const answer = await ask('[mumpix] press Enter to continue, or press any other key to install free (eventual mode): ');
70
- if (String(answer).trim().length > 0) {
71
- console.log('[mumpix] auth skipped. default mode is eventual.');
72
- return;
73
- }
74
- console.log('[mumpix] opening Mumpix in your browser to verify account access...');
75
-
76
- const state = await loginWithDeviceFlow({
77
- onPrompt: ({ userCode, verifyUrl, expiresInSec, intervalSec }) => {
78
- const opened = openBrowser(verifyUrl);
79
- if (opened) {
80
- console.log(`[mumpix] opened browser: ${verifyUrl}`);
81
- } else {
82
- console.log(`[mumpix] open this URL in your browser: ${verifyUrl}`);
83
- }
84
- console.log('[mumpix] browser approval will run automatically when signed in.');
85
- console.log(`[mumpix] waiting for approval (expires in ${expiresInSec}s, polling ${intervalSec}s)...`);
86
- }
87
- });
88
-
89
- console.log(`[mumpix] auth success. tier=${state.license.tier || state.account.tier || '-'} exp=${fmtExpiry(state.license.exp)}`);
90
- console.log(`[mumpix] saved auth: ${authStatePath()}`);
91
- } catch (err) {
92
- const msg = err && err.message ? err.message : 'unknown error';
93
- console.log(`[mumpix] auth step failed (${msg}).`);
94
- if (String(msg).includes('404')) {
95
- console.log('[mumpix] auth endpoints not found on this host. check MUMPIX_AUTH_BASE_URL or server auth routes.');
96
- }
97
- console.log('[mumpix] continuing install in eventual mode. run "mumpix auth login" later.');
98
- }
99
- }
100
-
101
- run();