@psiclawops/hypermem 0.5.0 → 0.5.2
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/ARCHITECTURE.md +12 -3
- package/README.md +30 -6
- package/bin/hypermem-status.mjs +166 -0
- package/dist/background-indexer.d.ts +132 -0
- package/dist/background-indexer.d.ts.map +1 -0
- package/dist/background-indexer.js +1044 -0
- package/dist/cache.d.ts +110 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +495 -0
- package/dist/compaction-fence.d.ts +89 -0
- package/dist/compaction-fence.d.ts.map +1 -0
- package/dist/compaction-fence.js +153 -0
- package/dist/compositor.d.ts +226 -0
- package/dist/compositor.d.ts.map +1 -0
- package/dist/compositor.js +2558 -0
- package/dist/content-type-classifier.d.ts +41 -0
- package/dist/content-type-classifier.d.ts.map +1 -0
- package/dist/content-type-classifier.js +181 -0
- package/dist/cross-agent.d.ts +62 -0
- package/dist/cross-agent.d.ts.map +1 -0
- package/dist/cross-agent.js +259 -0
- package/dist/db.d.ts +131 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +402 -0
- package/dist/desired-state-store.d.ts +100 -0
- package/dist/desired-state-store.d.ts.map +1 -0
- package/dist/desired-state-store.js +222 -0
- package/dist/doc-chunk-store.d.ts +140 -0
- package/dist/doc-chunk-store.d.ts.map +1 -0
- package/dist/doc-chunk-store.js +391 -0
- package/dist/doc-chunker.d.ts +99 -0
- package/dist/doc-chunker.d.ts.map +1 -0
- package/dist/doc-chunker.js +324 -0
- package/dist/dreaming-promoter.d.ts +86 -0
- package/dist/dreaming-promoter.d.ts.map +1 -0
- package/dist/dreaming-promoter.js +381 -0
- package/dist/episode-store.d.ts +49 -0
- package/dist/episode-store.d.ts.map +1 -0
- package/dist/episode-store.js +135 -0
- package/dist/fact-store.d.ts +75 -0
- package/dist/fact-store.d.ts.map +1 -0
- package/dist/fact-store.js +236 -0
- package/dist/fleet-store.d.ts +144 -0
- package/dist/fleet-store.d.ts.map +1 -0
- package/dist/fleet-store.js +276 -0
- package/dist/fos-mod.d.ts +178 -0
- package/dist/fos-mod.d.ts.map +1 -0
- package/dist/fos-mod.js +416 -0
- package/dist/hybrid-retrieval.d.ts +64 -0
- package/dist/hybrid-retrieval.d.ts.map +1 -0
- package/dist/hybrid-retrieval.js +344 -0
- package/dist/image-eviction.d.ts +49 -0
- package/dist/image-eviction.d.ts.map +1 -0
- package/dist/image-eviction.js +251 -0
- package/dist/index.d.ts +650 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1072 -0
- package/dist/keystone-scorer.d.ts +51 -0
- package/dist/keystone-scorer.d.ts.map +1 -0
- package/dist/keystone-scorer.js +52 -0
- package/dist/knowledge-graph.d.ts +110 -0
- package/dist/knowledge-graph.d.ts.map +1 -0
- package/dist/knowledge-graph.js +305 -0
- package/dist/knowledge-lint.d.ts +29 -0
- package/dist/knowledge-lint.d.ts.map +1 -0
- package/dist/knowledge-lint.js +116 -0
- package/dist/knowledge-store.d.ts +72 -0
- package/dist/knowledge-store.d.ts.map +1 -0
- package/dist/knowledge-store.js +247 -0
- package/dist/library-schema.d.ts +22 -0
- package/dist/library-schema.d.ts.map +1 -0
- package/dist/library-schema.js +1038 -0
- package/dist/message-store.d.ts +89 -0
- package/dist/message-store.d.ts.map +1 -0
- package/dist/message-store.js +323 -0
- package/dist/metrics-dashboard.d.ts +114 -0
- package/dist/metrics-dashboard.d.ts.map +1 -0
- package/dist/metrics-dashboard.js +260 -0
- package/dist/obsidian-exporter.d.ts +57 -0
- package/dist/obsidian-exporter.d.ts.map +1 -0
- package/dist/obsidian-exporter.js +274 -0
- package/dist/obsidian-watcher.d.ts +147 -0
- package/dist/obsidian-watcher.d.ts.map +1 -0
- package/dist/obsidian-watcher.js +403 -0
- package/dist/open-domain.d.ts +46 -0
- package/dist/open-domain.d.ts.map +1 -0
- package/dist/open-domain.js +125 -0
- package/dist/preference-store.d.ts +54 -0
- package/dist/preference-store.d.ts.map +1 -0
- package/dist/preference-store.js +109 -0
- package/dist/preservation-gate.d.ts +82 -0
- package/dist/preservation-gate.d.ts.map +1 -0
- package/dist/preservation-gate.js +150 -0
- package/dist/proactive-pass.d.ts +63 -0
- package/dist/proactive-pass.d.ts.map +1 -0
- package/dist/proactive-pass.js +239 -0
- package/dist/profiles.d.ts +44 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +227 -0
- package/dist/provider-translator.d.ts +50 -0
- package/dist/provider-translator.d.ts.map +1 -0
- package/dist/provider-translator.js +403 -0
- package/dist/rate-limiter.d.ts +76 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +179 -0
- package/dist/repair-tool-pairs.d.ts +38 -0
- package/dist/repair-tool-pairs.d.ts.map +1 -0
- package/dist/repair-tool-pairs.js +138 -0
- package/dist/retrieval-policy.d.ts +51 -0
- package/dist/retrieval-policy.d.ts.map +1 -0
- package/dist/retrieval-policy.js +77 -0
- package/dist/schema.d.ts +15 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +229 -0
- package/dist/secret-scanner.d.ts +51 -0
- package/dist/secret-scanner.d.ts.map +1 -0
- package/dist/secret-scanner.js +248 -0
- package/dist/seed.d.ts +108 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +177 -0
- package/dist/session-flusher.d.ts +53 -0
- package/dist/session-flusher.d.ts.map +1 -0
- package/dist/session-flusher.js +69 -0
- package/dist/session-topic-map.d.ts +41 -0
- package/dist/session-topic-map.d.ts.map +1 -0
- package/dist/session-topic-map.js +77 -0
- package/dist/spawn-context.d.ts +54 -0
- package/dist/spawn-context.d.ts.map +1 -0
- package/dist/spawn-context.js +159 -0
- package/dist/system-store.d.ts +73 -0
- package/dist/system-store.d.ts.map +1 -0
- package/dist/system-store.js +182 -0
- package/dist/temporal-store.d.ts +80 -0
- package/dist/temporal-store.d.ts.map +1 -0
- package/dist/temporal-store.js +149 -0
- package/dist/topic-detector.d.ts +35 -0
- package/dist/topic-detector.d.ts.map +1 -0
- package/dist/topic-detector.js +249 -0
- package/dist/topic-store.d.ts +45 -0
- package/dist/topic-store.d.ts.map +1 -0
- package/dist/topic-store.js +136 -0
- package/dist/topic-synthesizer.d.ts +51 -0
- package/dist/topic-synthesizer.d.ts.map +1 -0
- package/dist/topic-synthesizer.js +315 -0
- package/dist/trigger-registry.d.ts +63 -0
- package/dist/trigger-registry.d.ts.map +1 -0
- package/dist/trigger-registry.js +163 -0
- package/dist/types.d.ts +537 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/vector-store.d.ts +170 -0
- package/dist/vector-store.d.ts.map +1 -0
- package/dist/vector-store.js +677 -0
- package/dist/version.d.ts +34 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +34 -0
- package/dist/wiki-page-emitter.d.ts +65 -0
- package/dist/wiki-page-emitter.d.ts.map +1 -0
- package/dist/wiki-page-emitter.js +258 -0
- package/dist/work-store.d.ts +112 -0
- package/dist/work-store.d.ts.map +1 -0
- package/dist/work-store.js +273 -0
- package/package.json +4 -1
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hypermem Work Item Store
|
|
3
|
+
*
|
|
4
|
+
* Fleet kanban board in SQL. Replaces WORKQUEUE.md.
|
|
5
|
+
* Lives in the central library DB.
|
|
6
|
+
*/
|
|
7
|
+
function nowIso() {
|
|
8
|
+
return new Date().toISOString();
|
|
9
|
+
}
|
|
10
|
+
function parseItemRow(row) {
|
|
11
|
+
return {
|
|
12
|
+
id: row.id,
|
|
13
|
+
title: row.title,
|
|
14
|
+
description: row.description || null,
|
|
15
|
+
status: row.status,
|
|
16
|
+
priority: row.priority,
|
|
17
|
+
agentId: row.agent_id || null,
|
|
18
|
+
createdBy: row.created_by,
|
|
19
|
+
domain: row.domain || null,
|
|
20
|
+
parentId: row.parent_id || null,
|
|
21
|
+
blockedBy: row.blocked_by || null,
|
|
22
|
+
sessionKey: row.session_key || null,
|
|
23
|
+
createdAt: row.created_at,
|
|
24
|
+
updatedAt: row.updated_at,
|
|
25
|
+
startedAt: row.started_at || null,
|
|
26
|
+
completedAt: row.completed_at || null,
|
|
27
|
+
dueAt: row.due_at || null,
|
|
28
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : null,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function parseEventRow(row) {
|
|
32
|
+
return {
|
|
33
|
+
id: row.id,
|
|
34
|
+
workItemId: row.work_item_id,
|
|
35
|
+
eventType: row.event_type,
|
|
36
|
+
oldStatus: row.old_status || null,
|
|
37
|
+
newStatus: row.new_status || null,
|
|
38
|
+
agentId: row.agent_id || null,
|
|
39
|
+
comment: row.comment || null,
|
|
40
|
+
createdAt: row.created_at,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Generate a work item ID candidate.
|
|
45
|
+
* Uses a 6-hex random suffix (~16.7M daily space).
|
|
46
|
+
*/
|
|
47
|
+
function generateIdCandidate() {
|
|
48
|
+
const date = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
49
|
+
const suffix = Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
|
|
50
|
+
return `WQ-${date}-${suffix}`;
|
|
51
|
+
}
|
|
52
|
+
export class WorkStore {
|
|
53
|
+
db;
|
|
54
|
+
constructor(db) {
|
|
55
|
+
this.db = db;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a new work item.
|
|
59
|
+
*/
|
|
60
|
+
create(data) {
|
|
61
|
+
const now = nowIso();
|
|
62
|
+
// Use caller-supplied ID if provided, otherwise generate with retry-on-conflict.
|
|
63
|
+
// Random suffix collisions are rare but possible under bulk creation — retry
|
|
64
|
+
// up to 10 times before giving up. Each retry picks a new random suffix.
|
|
65
|
+
const callerSuppliedId = data.metadata?.id;
|
|
66
|
+
let id = callerSuppliedId || generateIdCandidate();
|
|
67
|
+
let attempts = 0;
|
|
68
|
+
while (attempts < 10) {
|
|
69
|
+
const existing = this.db
|
|
70
|
+
.prepare('SELECT id FROM work_items WHERE id = ?')
|
|
71
|
+
.get(id);
|
|
72
|
+
if (!existing)
|
|
73
|
+
break;
|
|
74
|
+
if (callerSuppliedId) {
|
|
75
|
+
throw new Error(`Work item ID already exists: ${id}`);
|
|
76
|
+
}
|
|
77
|
+
id = generateIdCandidate();
|
|
78
|
+
attempts++;
|
|
79
|
+
}
|
|
80
|
+
this.db.prepare(`
|
|
81
|
+
INSERT INTO work_items (id, title, description, status, priority, agent_id,
|
|
82
|
+
created_by, domain, parent_id, created_at, updated_at, due_at, metadata)
|
|
83
|
+
VALUES (?, ?, ?, 'incoming', ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
84
|
+
`).run(id, data.title, data.description || null, data.priority || 3, data.agentId || null, data.createdBy, data.domain || null, data.parentId || null, now, now, data.dueAt || null, data.metadata ? JSON.stringify(data.metadata) : null);
|
|
85
|
+
this.recordEvent(id, 'created', null, 'incoming', data.createdBy);
|
|
86
|
+
return this.getItem(id);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Update the status of a work item.
|
|
90
|
+
*/
|
|
91
|
+
updateStatus(id, newStatus, agentId, comment) {
|
|
92
|
+
const now = nowIso();
|
|
93
|
+
const current = this.getItem(id);
|
|
94
|
+
if (!current)
|
|
95
|
+
return null;
|
|
96
|
+
const updates = ['status = ?', 'updated_at = ?'];
|
|
97
|
+
const params = [newStatus, now];
|
|
98
|
+
if (newStatus === 'active' && !current.startedAt) {
|
|
99
|
+
updates.push('started_at = ?');
|
|
100
|
+
params.push(now);
|
|
101
|
+
}
|
|
102
|
+
if (newStatus === 'completed' || newStatus === 'cancelled') {
|
|
103
|
+
updates.push('completed_at = ?');
|
|
104
|
+
params.push(now);
|
|
105
|
+
}
|
|
106
|
+
params.push(id);
|
|
107
|
+
this.db.prepare(`UPDATE work_items SET ${updates.join(', ')} WHERE id = ?`).run(...params);
|
|
108
|
+
this.recordEvent(id, 'status_changed', current.status, newStatus, agentId, comment);
|
|
109
|
+
return this.getItem(id);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Assign a work item to an agent.
|
|
113
|
+
*/
|
|
114
|
+
assign(id, agentId, assignedBy) {
|
|
115
|
+
const now = nowIso();
|
|
116
|
+
this.db.prepare('UPDATE work_items SET agent_id = ?, updated_at = ? WHERE id = ?').run(agentId, now, id);
|
|
117
|
+
this.recordEvent(id, 'assigned', null, null, assignedBy, `Assigned to ${agentId}`);
|
|
118
|
+
return this.getItem(id);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Block a work item.
|
|
122
|
+
*/
|
|
123
|
+
block(id, blockedBy, agentId, reason) {
|
|
124
|
+
const now = nowIso();
|
|
125
|
+
const current = this.getItem(id);
|
|
126
|
+
if (!current)
|
|
127
|
+
return null;
|
|
128
|
+
this.db.prepare("UPDATE work_items SET status = 'blocked', blocked_by = ?, updated_at = ? WHERE id = ?").run(blockedBy, now, id);
|
|
129
|
+
this.recordEvent(id, 'blocked', current.status, 'blocked', agentId, reason || `Blocked by ${blockedBy}`);
|
|
130
|
+
return this.getItem(id);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get a work item by ID.
|
|
134
|
+
*/
|
|
135
|
+
getItem(id) {
|
|
136
|
+
const row = this.db.prepare('SELECT * FROM work_items WHERE id = ?')
|
|
137
|
+
.get(id);
|
|
138
|
+
return row ? parseItemRow(row) : null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get active work for an agent.
|
|
142
|
+
*/
|
|
143
|
+
getAgentWork(agentId, status) {
|
|
144
|
+
let sql = 'SELECT * FROM work_items WHERE agent_id = ?';
|
|
145
|
+
const params = [agentId];
|
|
146
|
+
if (status) {
|
|
147
|
+
sql += ' AND status = ?';
|
|
148
|
+
params.push(status);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
sql += " AND status NOT IN ('completed', 'cancelled')";
|
|
152
|
+
}
|
|
153
|
+
sql += ' ORDER BY priority, created_at';
|
|
154
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
155
|
+
return rows.map(parseItemRow);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get the fleet kanban — all active work grouped by status.
|
|
159
|
+
*/
|
|
160
|
+
getKanban(opts) {
|
|
161
|
+
let sql = "SELECT * FROM work_items WHERE status NOT IN ('completed', 'cancelled')";
|
|
162
|
+
const params = [];
|
|
163
|
+
if (opts?.domain) {
|
|
164
|
+
sql += ' AND domain = ?';
|
|
165
|
+
params.push(opts.domain);
|
|
166
|
+
}
|
|
167
|
+
if (opts?.agentId) {
|
|
168
|
+
sql += ' AND agent_id = ?';
|
|
169
|
+
params.push(opts.agentId);
|
|
170
|
+
}
|
|
171
|
+
sql += ' ORDER BY status, priority, created_at';
|
|
172
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
173
|
+
return rows.map(parseItemRow);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get blocked items across the fleet.
|
|
177
|
+
*/
|
|
178
|
+
getBlocked() {
|
|
179
|
+
const rows = this.db.prepare("SELECT * FROM work_items WHERE status = 'blocked' ORDER BY priority, created_at").all();
|
|
180
|
+
return rows.map(parseItemRow);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get completion stats for the fleet.
|
|
184
|
+
*/
|
|
185
|
+
getStats(opts) {
|
|
186
|
+
let sql = 'SELECT status, COUNT(*) as cnt FROM work_items';
|
|
187
|
+
const params = [];
|
|
188
|
+
const conditions = [];
|
|
189
|
+
if (opts?.agentId) {
|
|
190
|
+
conditions.push('agent_id = ?');
|
|
191
|
+
params.push(opts.agentId);
|
|
192
|
+
}
|
|
193
|
+
if (opts?.since) {
|
|
194
|
+
conditions.push('created_at >= ?');
|
|
195
|
+
params.push(opts.since);
|
|
196
|
+
}
|
|
197
|
+
if (conditions.length)
|
|
198
|
+
sql += ' WHERE ' + conditions.join(' AND ');
|
|
199
|
+
sql += ' GROUP BY status';
|
|
200
|
+
const rows = this.db.prepare(sql).all(...params);
|
|
201
|
+
const counts = {};
|
|
202
|
+
let total = 0;
|
|
203
|
+
for (const r of rows) {
|
|
204
|
+
counts[r.status] = r.cnt;
|
|
205
|
+
total += r.cnt;
|
|
206
|
+
}
|
|
207
|
+
// Avg duration for completed items
|
|
208
|
+
let avgSql = `
|
|
209
|
+
SELECT AVG(julianday(completed_at) - julianday(started_at)) * 24 as avg_hours
|
|
210
|
+
FROM work_items WHERE status = 'completed' AND started_at IS NOT NULL
|
|
211
|
+
`;
|
|
212
|
+
const avgParams = [];
|
|
213
|
+
if (opts?.agentId) {
|
|
214
|
+
avgSql += ' AND agent_id = ?';
|
|
215
|
+
avgParams.push(opts.agentId);
|
|
216
|
+
}
|
|
217
|
+
if (opts?.since) {
|
|
218
|
+
avgSql += ' AND completed_at >= ?';
|
|
219
|
+
avgParams.push(opts.since);
|
|
220
|
+
}
|
|
221
|
+
const avgRow = this.db.prepare(avgSql).get(...avgParams);
|
|
222
|
+
return {
|
|
223
|
+
total,
|
|
224
|
+
incoming: counts['incoming'] || 0,
|
|
225
|
+
active: counts['active'] || 0,
|
|
226
|
+
blocked: counts['blocked'] || 0,
|
|
227
|
+
review: counts['review'] || 0,
|
|
228
|
+
completed: counts['completed'] || 0,
|
|
229
|
+
cancelled: counts['cancelled'] || 0,
|
|
230
|
+
avgDurationHours: avgRow?.avg_hours || null,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get events for a work item.
|
|
235
|
+
*/
|
|
236
|
+
getEvents(workItemId, limit = 50) {
|
|
237
|
+
const rows = this.db.prepare('SELECT * FROM work_events WHERE work_item_id = ? ORDER BY created_at DESC LIMIT ?').all(workItemId, limit);
|
|
238
|
+
return rows.map(parseEventRow);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Search work items.
|
|
242
|
+
*/
|
|
243
|
+
search(query, limit = 20) {
|
|
244
|
+
try {
|
|
245
|
+
const rows = this.db.prepare(`
|
|
246
|
+
SELECT w.* FROM work_items w
|
|
247
|
+
JOIN work_items_fts fts ON w.rowid = fts.rowid
|
|
248
|
+
WHERE work_items_fts MATCH ?
|
|
249
|
+
ORDER BY rank
|
|
250
|
+
LIMIT ?
|
|
251
|
+
`).all(query, limit);
|
|
252
|
+
return rows.map(parseItemRow);
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
// FTS fallback
|
|
256
|
+
const rows = this.db.prepare(`
|
|
257
|
+
SELECT * FROM work_items
|
|
258
|
+
WHERE title LIKE ? OR description LIKE ?
|
|
259
|
+
ORDER BY priority, created_at DESC
|
|
260
|
+
LIMIT ?
|
|
261
|
+
`).all(`%${query}%`, `%${query}%`, limit);
|
|
262
|
+
return rows.map(parseItemRow);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// ── Private helpers ─────────────────────────────────────────
|
|
266
|
+
recordEvent(workItemId, eventType, oldStatus, newStatus, agentId, comment) {
|
|
267
|
+
this.db.prepare(`
|
|
268
|
+
INSERT INTO work_events (work_item_id, event_type, old_status, new_status, agent_id, comment, created_at)
|
|
269
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
270
|
+
`).run(workItemId, eventType, oldStatus, newStatus, agentId || null, comment || null, nowIso());
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=work-store.js.map
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@psiclawops/hypermem",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Agent-centric memory and context composition engine for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"hypermem-status": "bin/hypermem-status.mjs"
|
|
10
|
+
},
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
13
|
"import": "./dist/index.js",
|