hypercore-cli 1.1.0

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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/api-XGC7D5AW.js +162 -0
  4. package/dist/auth-DNQWYQKT.js +21 -0
  5. package/dist/background-2EGCAAQH.js +14 -0
  6. package/dist/backlog-Q2NZCLNY.js +24 -0
  7. package/dist/chunk-2CMSCWQW.js +162 -0
  8. package/dist/chunk-2LJ2DVEB.js +167 -0
  9. package/dist/chunk-3RPFCQKJ.js +288 -0
  10. package/dist/chunk-43OLRXM5.js +263 -0
  11. package/dist/chunk-4DVYJAJL.js +57 -0
  12. package/dist/chunk-6OL3GA3P.js +173 -0
  13. package/dist/chunk-AUHU7ALH.js +2023 -0
  14. package/dist/chunk-B6A2AKLN.js +139 -0
  15. package/dist/chunk-BE46C7JW.js +46 -0
  16. package/dist/chunk-CUVAUOXL.js +58 -0
  17. package/dist/chunk-GH7E2OJE.js +223 -0
  18. package/dist/chunk-GOOTEPBK.js +271 -0
  19. package/dist/chunk-GPPMJYSM.js +133 -0
  20. package/dist/chunk-GU2FZQ6A.js +69 -0
  21. package/dist/chunk-IOPKN5GD.js +190 -0
  22. package/dist/chunk-IXOIOGR5.js +1505 -0
  23. package/dist/chunk-KRPOPWGA.js +251 -0
  24. package/dist/chunk-MGLJ53QN.js +219 -0
  25. package/dist/chunk-MV4TTRYX.js +533 -0
  26. package/dist/chunk-OPZYEVYR.js +150 -0
  27. package/dist/chunk-QTSLP47C.js +166 -0
  28. package/dist/chunk-R3GPQC7I.js +393 -0
  29. package/dist/chunk-RKB2JOV2.js +43 -0
  30. package/dist/chunk-RNG3K465.js +80 -0
  31. package/dist/chunk-TGTYKBGC.js +86 -0
  32. package/dist/chunk-U5SGAIMM.js +681 -0
  33. package/dist/chunk-V5UHPPSY.js +140 -0
  34. package/dist/chunk-WHLVZCQY.js +245 -0
  35. package/dist/chunk-XDRCBMZZ.js +66 -0
  36. package/dist/chunk-XOS6HPEF.js +134 -0
  37. package/dist/chunk-ZSBHUGWR.js +262 -0
  38. package/dist/claude-NSQ442XD.js +12 -0
  39. package/dist/commands-CK3WFAGI.js +128 -0
  40. package/dist/commands-U63OEO5J.js +1044 -0
  41. package/dist/commands-ZE6GD3WC.js +232 -0
  42. package/dist/config-4EW42BSF.js +8 -0
  43. package/dist/config-loader-SXO674TF.js +24 -0
  44. package/dist/diagnose-AFW3ZTZ4.js +12 -0
  45. package/dist/display-IIUBEYWN.js +58 -0
  46. package/dist/extractor-QV53W2YJ.js +129 -0
  47. package/dist/history-WMSCHERZ.js +180 -0
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.js +406 -0
  50. package/dist/instance-registry-YSIJXSO7.js +15 -0
  51. package/dist/keybindings-JAAMLH3G.js +15 -0
  52. package/dist/loader-WHNTZTLP.js +58 -0
  53. package/dist/network-MM6YWPGO.js +279 -0
  54. package/dist/notify-HPTALZDC.js +14 -0
  55. package/dist/openai-compat-UQWJXBEK.js +12 -0
  56. package/dist/permissions-JUKXMNDH.js +10 -0
  57. package/dist/prompt-QV45TXRL.js +166 -0
  58. package/dist/quality-ST7PPNFR.js +16 -0
  59. package/dist/repl-RT3AHL7M.js +3375 -0
  60. package/dist/roadmap-5OBEKROY.js +17 -0
  61. package/dist/server-PORT7OEG.js +57 -0
  62. package/dist/session-4VUNDWLH.js +21 -0
  63. package/dist/skills-V4A35XKG.js +175 -0
  64. package/dist/store-Y4LU5QTO.js +25 -0
  65. package/dist/team-HO7Z4SIM.js +385 -0
  66. package/dist/telemetry-6R4EIE6O.js +30 -0
  67. package/dist/test-runner-ZQH5Y6OJ.js +619 -0
  68. package/dist/theme-3SYJ3UQA.js +14 -0
  69. package/dist/upgrade-7TGI3SXO.js +83 -0
  70. package/dist/verify-JUDKTPKZ.js +14 -0
  71. package/dist/web/static/app.js +562 -0
  72. package/dist/web/static/index.html +132 -0
  73. package/dist/web/static/mirror.css +1001 -0
  74. package/dist/web/static/mirror.html +184 -0
  75. package/dist/web/static/mirror.js +1125 -0
  76. package/dist/web/static/onboard.css +302 -0
  77. package/dist/web/static/onboard.html +140 -0
  78. package/dist/web/static/onboard.js +260 -0
  79. package/dist/web/static/style.css +602 -0
  80. package/dist/web/static/workspace.css +1568 -0
  81. package/dist/web/static/workspace.html +408 -0
  82. package/dist/web/static/workspace.js +1683 -0
  83. package/dist/web-Z5HSCQHW.js +39 -0
  84. package/package.json +67 -0
@@ -0,0 +1,251 @@
1
+ import {
2
+ HYPERCORE_DIR
3
+ } from "./chunk-V5UHPPSY.js";
4
+
5
+ // src/memory/store.ts
6
+ import { randomBytes } from "crypto";
7
+ import { readFile, writeFile, mkdir } from "fs/promises";
8
+ import { existsSync } from "fs";
9
+ import { join } from "path";
10
+
11
+ // src/memory/types.ts
12
+ var DEFAULT_EXTRACTION_CONFIG = {
13
+ extractEveryNRounds: 3,
14
+ maxMemoriesPerExtraction: 5,
15
+ minConfidence: 0.6,
16
+ maxPersonalMemories: 100,
17
+ maxProjectMemories: 150,
18
+ maxSystemPromptChars: 3e3
19
+ };
20
+ function createEmptyStore(layer) {
21
+ return {
22
+ version: "1",
23
+ layer,
24
+ records: [],
25
+ totalExtractions: 0,
26
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
27
+ };
28
+ }
29
+ var CATEGORY_LABELS = {
30
+ preference: "\u504F\u597D",
31
+ decision: "\u51B3\u7B56",
32
+ entity: "\u5B9E\u4F53",
33
+ pattern: "\u6A21\u5F0F",
34
+ fact: "\u4E8B\u5B9E",
35
+ convention: "\u7EA6\u5B9A",
36
+ insight: "\u6D1E\u5BDF",
37
+ manual: "\u624B\u52A8"
38
+ };
39
+ var CATEGORY_MD_HEADERS = {
40
+ preference: "User Preferences",
41
+ decision: "Key Decisions",
42
+ entity: "Named Entities",
43
+ pattern: "Patterns & Solutions",
44
+ fact: "Known Facts",
45
+ convention: "Conventions",
46
+ insight: "Team Insights",
47
+ manual: "User Notes"
48
+ };
49
+
50
+ // src/memory/store.ts
51
+ function memoryDir(layer, opts) {
52
+ switch (layer) {
53
+ case "personal":
54
+ return join(HYPERCORE_DIR, "memory");
55
+ case "project":
56
+ return join(opts?.projectPath || process.cwd(), ".hypercore", "memory");
57
+ case "team":
58
+ if (!opts?.teamId) throw new Error("team layer requires teamId");
59
+ return join(HYPERCORE_DIR, "teams", opts.teamId, "memory");
60
+ }
61
+ }
62
+ function jsonPath(layer, opts) {
63
+ return join(memoryDir(layer, opts), `${layer}.json`);
64
+ }
65
+ function mdPath(layer, opts) {
66
+ return join(memoryDir(layer, opts), `${layer}.md`);
67
+ }
68
+ function generateMemoryId() {
69
+ const ts = Date.now();
70
+ const rand = randomBytes(2).toString("hex");
71
+ return `mem_${ts}_${rand}`;
72
+ }
73
+ async function loadStore(layer, opts) {
74
+ const fp = jsonPath(layer, opts);
75
+ if (!existsSync(fp)) return createEmptyStore(layer);
76
+ try {
77
+ const raw = await readFile(fp, "utf-8");
78
+ return JSON.parse(raw);
79
+ } catch {
80
+ return createEmptyStore(layer);
81
+ }
82
+ }
83
+ async function saveStore(store, opts) {
84
+ const dir = memoryDir(store.layer, opts);
85
+ await mkdir(dir, { recursive: true });
86
+ store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
87
+ await writeFile(jsonPath(store.layer, opts), JSON.stringify(store, null, 2), "utf-8");
88
+ await rebuildMarkdown(store, opts);
89
+ }
90
+ async function addMemory(layer, record, opts) {
91
+ const store = await loadStore(layer, opts);
92
+ const config = DEFAULT_EXTRACTION_CONFIG;
93
+ const maxRecords = layer === "personal" ? config.maxPersonalMemories : config.maxProjectMemories;
94
+ const existingIdx = findDuplicate(store.records, record.content);
95
+ if (existingIdx >= 0) {
96
+ const existing = store.records[existingIdx];
97
+ existing.content = record.content;
98
+ existing.tags = record.tags;
99
+ existing.confidence = Math.max(existing.confidence, record.confidence);
100
+ existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
101
+ existing.accessCount++;
102
+ await saveStore(store, opts);
103
+ return existing;
104
+ }
105
+ if (store.records.length >= maxRecords) {
106
+ store.records.sort((a, b) => a.confidence - b.confidence || a.updatedAt.localeCompare(b.updatedAt));
107
+ store.records.shift();
108
+ }
109
+ const now = (/* @__PURE__ */ new Date()).toISOString();
110
+ const newRecord = {
111
+ ...record,
112
+ id: generateMemoryId(),
113
+ layer,
114
+ createdAt: now,
115
+ updatedAt: now,
116
+ accessCount: 0
117
+ };
118
+ store.records.push(newRecord);
119
+ await saveStore(store, opts);
120
+ return newRecord;
121
+ }
122
+ async function removeMemory(layer, memoryId, opts) {
123
+ const store = await loadStore(layer, opts);
124
+ const idx = store.records.findIndex((r) => r.id === memoryId);
125
+ if (idx < 0) return false;
126
+ store.records.splice(idx, 1);
127
+ await saveStore(store, opts);
128
+ return true;
129
+ }
130
+ async function searchMemories(layer, query, opts) {
131
+ const store = await loadStore(layer, opts);
132
+ let records = store.records;
133
+ if (opts?.category) {
134
+ records = records.filter((r) => r.category === opts.category);
135
+ }
136
+ const queryLower = query.toLowerCase();
137
+ const queryTerms = queryLower.split(/\s+/).filter(Boolean);
138
+ const scored = records.map((record) => {
139
+ const contentLower = record.content.toLowerCase();
140
+ const tagsLower = record.tags.join(" ").toLowerCase();
141
+ const combined = contentLower + " " + tagsLower;
142
+ let matchedTerms = 0;
143
+ for (const term of queryTerms) {
144
+ if (combined.includes(term)) matchedTerms++;
145
+ }
146
+ const score = queryTerms.length > 0 ? matchedTerms / queryTerms.length : 0;
147
+ return { record, score };
148
+ });
149
+ const results = scored.filter((r) => r.score > 0).sort((a, b) => b.score - a.score || b.record.confidence - a.record.confidence);
150
+ for (const r of results) {
151
+ r.record.accessCount++;
152
+ r.record.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
153
+ }
154
+ if (results.length > 0) {
155
+ await saveStore(store, opts);
156
+ }
157
+ return results.slice(0, opts?.limit || 20);
158
+ }
159
+ async function listMemories(layer, opts) {
160
+ const store = await loadStore(layer, opts);
161
+ return [...store.records].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
162
+ }
163
+ async function getMemoryStats(layer, opts) {
164
+ const store = await loadStore(layer, opts);
165
+ const byCategory = {};
166
+ for (const r of store.records) {
167
+ byCategory[r.category] = (byCategory[r.category] || 0) + 1;
168
+ }
169
+ return {
170
+ total: store.records.length,
171
+ byCategory,
172
+ lastExtractionAt: store.lastExtractionAt,
173
+ totalExtractions: store.totalExtractions
174
+ };
175
+ }
176
+ async function markExtraction(layer, opts) {
177
+ const store = await loadStore(layer, opts);
178
+ store.lastExtractionAt = (/* @__PURE__ */ new Date()).toISOString();
179
+ store.totalExtractions++;
180
+ await saveStore(store, opts);
181
+ }
182
+ function findDuplicate(records, content) {
183
+ const normalized = content.toLowerCase().replace(/\s+/g, " ").trim();
184
+ for (let i = 0; i < records.length; i++) {
185
+ const existing = records[i].content.toLowerCase().replace(/\s+/g, " ").trim();
186
+ if (similarityRatio(existing, normalized) > 0.8) return i;
187
+ }
188
+ return -1;
189
+ }
190
+ function similarityRatio(a, b) {
191
+ if (a === b) return 1;
192
+ if (!a || !b) return 0;
193
+ const bigramsA = /* @__PURE__ */ new Set();
194
+ for (let i = 0; i < a.length - 1; i++) bigramsA.add(a.slice(i, i + 2));
195
+ const bigramsB = /* @__PURE__ */ new Set();
196
+ for (let i = 0; i < b.length - 1; i++) bigramsB.add(b.slice(i, i + 2));
197
+ let intersection = 0;
198
+ for (const bg of bigramsA) {
199
+ if (bigramsB.has(bg)) intersection++;
200
+ }
201
+ const union = bigramsA.size + bigramsB.size - intersection;
202
+ return union > 0 ? intersection / union : 0;
203
+ }
204
+ async function rebuildMarkdown(store, opts) {
205
+ const lines = [
206
+ `--- Memory Context (${store.layer}) ---`,
207
+ ""
208
+ ];
209
+ const grouped = {};
210
+ for (const r of store.records) {
211
+ if (!grouped[r.category]) grouped[r.category] = [];
212
+ grouped[r.category].push(r);
213
+ }
214
+ for (const [category, records] of Object.entries(grouped)) {
215
+ const header = CATEGORY_MD_HEADERS[category] || category;
216
+ lines.push(`[${header}]`);
217
+ const sorted = records.sort((a, b) => b.confidence - a.confidence);
218
+ for (const r of sorted) {
219
+ const tags = r.tags.map((t) => `#${t}`).join(" ");
220
+ lines.push(`- ${r.content} ${tags}`);
221
+ }
222
+ lines.push("");
223
+ }
224
+ lines.push(`--- End Memory Context ---`);
225
+ const fp = mdPath(store.layer, opts);
226
+ await writeFile(fp, lines.join("\n"), "utf-8");
227
+ }
228
+ async function readMemoryMarkdown(layer, opts) {
229
+ const fp = mdPath(layer, opts);
230
+ if (!existsSync(fp)) return "";
231
+ try {
232
+ return await readFile(fp, "utf-8");
233
+ } catch {
234
+ return "";
235
+ }
236
+ }
237
+
238
+ export {
239
+ DEFAULT_EXTRACTION_CONFIG,
240
+ CATEGORY_LABELS,
241
+ generateMemoryId,
242
+ loadStore,
243
+ saveStore,
244
+ addMemory,
245
+ removeMemory,
246
+ searchMemories,
247
+ listMemories,
248
+ getMemoryStats,
249
+ markExtraction,
250
+ readMemoryMarkdown
251
+ };
@@ -0,0 +1,219 @@
1
+ // src/admin/backlog.ts
2
+ import { join } from "path";
3
+ import { readFile, writeFile, mkdir } from "fs/promises";
4
+ import { existsSync } from "fs";
5
+ var HYPERCORE_DIR = join(process.env.HOME || "~", ".hypercore");
6
+ var ADMIN_DIR = join(HYPERCORE_DIR, "admin");
7
+ var BACKLOG_FILE = join(ADMIN_DIR, "backlog.json");
8
+ var DEFAULT_METRICS = {
9
+ baselineKey: null,
10
+ baselineValue: null,
11
+ baselineDate: null,
12
+ afterValue: null,
13
+ afterDate: null,
14
+ verified: false
15
+ };
16
+ function normalizeMetrics(metrics) {
17
+ return {
18
+ baselineKey: typeof metrics?.baselineKey === "string" ? metrics.baselineKey : null,
19
+ baselineValue: typeof metrics?.baselineValue === "number" && Number.isFinite(metrics.baselineValue) ? metrics.baselineValue : null,
20
+ baselineDate: typeof metrics?.baselineDate === "string" ? metrics.baselineDate : null,
21
+ afterValue: typeof metrics?.afterValue === "number" && Number.isFinite(metrics.afterValue) ? metrics.afterValue : null,
22
+ afterDate: typeof metrics?.afterDate === "string" ? metrics.afterDate : null,
23
+ verified: typeof metrics?.verified === "boolean" ? metrics.verified : false
24
+ };
25
+ }
26
+ function normalizeItem(raw, fallbackId) {
27
+ if (!raw || typeof raw !== "object") return null;
28
+ const item = raw;
29
+ const now = (/* @__PURE__ */ new Date()).toISOString();
30
+ const type = item.type === "feature" || item.type === "improvement" || item.type === "idea" || item.type === "bugfix" ? item.type : "feature";
31
+ const wuxing = item.wuxing === "\u6728" || item.wuxing === "\u706B" || item.wuxing === "\u6C34" || item.wuxing === "\u91D1" || item.wuxing === "\u571F" ? item.wuxing : "\u6728";
32
+ const priority = item.priority === "S" || item.priority === "A" || item.priority === "B" || item.priority === "C" ? item.priority : "B";
33
+ const status = item.status === "idea" || item.status === "planned" || item.status === "developing" || item.status === "done" || item.status === "archived" ? item.status : "idea";
34
+ const source = item.source === "auto-diagnose" ? "auto-diagnose" : "manual";
35
+ const createdAt = typeof item.createdAt === "string" ? item.createdAt : now;
36
+ const id = typeof item.id === "number" && Number.isFinite(item.id) ? Math.floor(item.id) : fallbackId;
37
+ return {
38
+ id: id > 0 ? id : fallbackId,
39
+ title: typeof item.title === "string" ? item.title : `Untitled #${fallbackId}`,
40
+ description: typeof item.description === "string" ? item.description : "",
41
+ type,
42
+ wuxing,
43
+ priority,
44
+ status,
45
+ source,
46
+ sourceDetail: typeof item.sourceDetail === "string" ? item.sourceDetail : "",
47
+ evidence: typeof item.evidence === "string" ? item.evidence : "",
48
+ targetVersion: typeof item.targetVersion === "string" ? item.targetVersion : "",
49
+ tags: Array.isArray(item.tags) ? item.tags.filter((t) => typeof t === "string") : [],
50
+ createdAt,
51
+ updatedAt: typeof item.updatedAt === "string" ? item.updatedAt : createdAt,
52
+ startedAt: typeof item.startedAt === "string" ? item.startedAt : null,
53
+ resolvedAt: typeof item.resolvedAt === "string" ? item.resolvedAt : null,
54
+ metrics: normalizeMetrics(item.metrics)
55
+ };
56
+ }
57
+ async function ensureDir() {
58
+ if (!existsSync(ADMIN_DIR)) {
59
+ await mkdir(ADMIN_DIR, { recursive: true });
60
+ }
61
+ }
62
+ async function loadStore() {
63
+ await ensureDir();
64
+ if (!existsSync(BACKLOG_FILE)) {
65
+ return { nextId: 1, items: [] };
66
+ }
67
+ try {
68
+ const raw = await readFile(BACKLOG_FILE, "utf-8");
69
+ const parsed = JSON.parse(raw);
70
+ const rawItems = Array.isArray(parsed.items) ? parsed.items : [];
71
+ const items = [];
72
+ for (let i = 0; i < rawItems.length; i++) {
73
+ const normalized = normalizeItem(rawItems[i], i + 1);
74
+ if (normalized) items.push(normalized);
75
+ }
76
+ const maxId = items.reduce((max, item) => item.id > max ? item.id : max, 0);
77
+ const nextIdFromFile = typeof parsed.nextId === "number" && Number.isFinite(parsed.nextId) ? Math.floor(parsed.nextId) : maxId + 1;
78
+ return {
79
+ nextId: Math.max(nextIdFromFile, maxId + 1, 1),
80
+ items
81
+ };
82
+ } catch {
83
+ return { nextId: 1, items: [] };
84
+ }
85
+ }
86
+ async function saveStore(store) {
87
+ await ensureDir();
88
+ await writeFile(BACKLOG_FILE, JSON.stringify(store, null, 2), "utf-8");
89
+ }
90
+ async function addItem(opts) {
91
+ const store = await loadStore();
92
+ const now = (/* @__PURE__ */ new Date()).toISOString();
93
+ const item = {
94
+ id: store.nextId++,
95
+ title: opts.title,
96
+ description: opts.description || "",
97
+ type: opts.type || "feature",
98
+ wuxing: opts.wuxing || "\u6728",
99
+ priority: opts.priority || "B",
100
+ status: "idea",
101
+ source: opts.source || "manual",
102
+ sourceDetail: "",
103
+ evidence: opts.evidence || "",
104
+ targetVersion: opts.targetVersion || "",
105
+ tags: opts.tags || [],
106
+ createdAt: now,
107
+ updatedAt: now,
108
+ startedAt: null,
109
+ resolvedAt: null,
110
+ metrics: { ...DEFAULT_METRICS }
111
+ };
112
+ store.items.push(item);
113
+ await saveStore(store);
114
+ return item;
115
+ }
116
+ async function listItems(filters) {
117
+ const store = await loadStore();
118
+ let items = store.items.filter((i) => i.status !== "archived");
119
+ if (filters) {
120
+ if (filters.status) items = items.filter((i) => i.status === filters.status);
121
+ if (filters.wuxing) items = items.filter((i) => i.wuxing === filters.wuxing);
122
+ if (filters.priority) items = items.filter((i) => i.priority === filters.priority);
123
+ if (filters.version) items = items.filter((i) => i.targetVersion === filters.version);
124
+ if (filters.type) items = items.filter((i) => i.type === filters.type);
125
+ }
126
+ const priorityOrder = { S: 0, A: 1, B: 2, C: 3 };
127
+ return items.sort((a, b) => {
128
+ const pd = priorityOrder[a.priority] - priorityOrder[b.priority];
129
+ if (pd !== 0) return pd;
130
+ return a.id - b.id;
131
+ });
132
+ }
133
+ async function getItem(id) {
134
+ const store = await loadStore();
135
+ return store.items.find((i) => i.id === id) || null;
136
+ }
137
+ async function updateItem(id, updates) {
138
+ const store = await loadStore();
139
+ const item = store.items.find((i) => i.id === id);
140
+ if (!item) return null;
141
+ Object.assign(item, updates);
142
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
143
+ await saveStore(store);
144
+ return item;
145
+ }
146
+ async function updateItemMetrics(id, metrics) {
147
+ const store = await loadStore();
148
+ const item = store.items.find((i) => i.id === id);
149
+ if (!item) return null;
150
+ item.metrics = normalizeMetrics(metrics);
151
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
152
+ await saveStore(store);
153
+ return item;
154
+ }
155
+ async function pickItem(id) {
156
+ const store = await loadStore();
157
+ const item = store.items.find((i) => i.id === id);
158
+ if (!item) return null;
159
+ item.status = "developing";
160
+ item.startedAt = (/* @__PURE__ */ new Date()).toISOString();
161
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
162
+ await saveStore(store);
163
+ return item;
164
+ }
165
+ async function doneItem(id) {
166
+ const store = await loadStore();
167
+ const item = store.items.find((i) => i.id === id);
168
+ if (!item) return null;
169
+ item.status = "done";
170
+ item.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
171
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
172
+ await saveStore(store);
173
+ return item;
174
+ }
175
+ async function archiveItem(id) {
176
+ const store = await loadStore();
177
+ const item = store.items.find((i) => i.id === id);
178
+ if (!item) return null;
179
+ item.status = "archived";
180
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
181
+ await saveStore(store);
182
+ return item;
183
+ }
184
+ async function reopenItem(id) {
185
+ const store = await loadStore();
186
+ const item = store.items.find((i) => i.id === id);
187
+ if (!item) return null;
188
+ item.status = "planned";
189
+ item.resolvedAt = null;
190
+ item.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
191
+ await saveStore(store);
192
+ return item;
193
+ }
194
+ async function getStats() {
195
+ const store = await loadStore();
196
+ const active = store.items.filter((i) => i.status !== "archived");
197
+ const byStatus = {};
198
+ const byPriority = {};
199
+ const byWuxing = {};
200
+ for (const item of active) {
201
+ byStatus[item.status] = (byStatus[item.status] || 0) + 1;
202
+ byPriority[item.priority] = (byPriority[item.priority] || 0) + 1;
203
+ byWuxing[item.wuxing] = (byWuxing[item.wuxing] || 0) + 1;
204
+ }
205
+ return { total: active.length, byStatus, byPriority, byWuxing };
206
+ }
207
+
208
+ export {
209
+ addItem,
210
+ listItems,
211
+ getItem,
212
+ updateItem,
213
+ updateItemMetrics,
214
+ pickItem,
215
+ doneItem,
216
+ archiveItem,
217
+ reopenItem,
218
+ getStats
219
+ };