monomind 2.7.8 → 2.7.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monomind",
3
- "version": "2.7.8",
3
+ "version": "2.7.10",
4
4
  "description": "Open-source CLI extension for Claude Code. Adds an MCP server with a codebase knowledge graph, persistent memory, multi-agent coordination, and reusable slash commands. MIT licensed, runs locally, no data leaves your machine.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -76,7 +76,7 @@
76
76
  },
77
77
  "optionalDependencies": {
78
78
  "@huggingface/transformers": "^3.8.1",
79
- "@monoes/hooks": "^1.0.0",
79
+ "@monoes/hooks": "^1.0.1",
80
80
  "@monoes/mcp": "^1.0.1",
81
81
  "@monoes/memory": "^1.0.10",
82
82
  "@monoes/routing": "^1.0.1",
@@ -79,13 +79,38 @@ async function getSystemStatus() {
79
79
  catch {
80
80
  // MCP not running
81
81
  }
82
- // Memory status — no MCP tool available; use defaults
82
+ // Memory status — measured, not assumed.
83
+ //
84
+ // This block used to be hardcoded literals ({entries: 0, size: 0, backend:
85
+ // 'sqlite', ...}) behind the comment "no MCP tool available; use defaults".
86
+ // Every number in the Memory panel was therefore a constant presented as
87
+ // telemetry: a project with a 139KB store and retrievable entries was told
88
+ // "Entries 0, Size 0 B". Worse, the derived Memory Backend health check
89
+ // compared against the same hardcoded 'sqlite', so it could never fail.
90
+ //
91
+ // On failure we report backend 'unknown' rather than a plausible-looking
92
+ // zero, so "cannot measure" is distinguishable from "measured empty".
83
93
  const memoryStatus = {
84
94
  entries: 0,
85
95
  size: 0,
86
- backend: 'sqlite',
96
+ backend: 'unknown',
87
97
  performance: { avgSearchTime: 0, cacheHitRate: 0 },
88
98
  };
99
+ try {
100
+ const { bridgeListEntries, bridgeGetDbPath } = await import('../memory/memory-bridge.js');
101
+ const listed = await bridgeListEntries({ limit: 100_000 });
102
+ if (listed?.success) {
103
+ memoryStatus.entries = listed.entries?.length ?? 0;
104
+ memoryStatus.backend = 'sqlite';
105
+ try {
106
+ const { statSync } = await import('node:fs');
107
+ const { join } = await import('node:path');
108
+ memoryStatus.size = statSync(join(bridgeGetDbPath(), 'memory.db')).size;
109
+ }
110
+ catch { /* size is a nicety; entries and backend are the load-bearing parts */ }
111
+ }
112
+ }
113
+ catch { /* leaves backend 'unknown' — an honest "could not read" */ }
89
114
  // Get task status
90
115
  const taskStatus = await callMCPTool('task_summary', {});
91
116
  return {
@@ -94,10 +119,15 @@ async function getSystemStatus() {
94
119
  swarm: {
95
120
  id: swarmStatus.swarmId,
96
121
  topology: swarmStatus.topology,
122
+ // swarm_status omits `agents` entirely when no swarm has been
123
+ // initialised — the common case in a fresh project. Reading
124
+ // .agents.total threw, and the catch below turned that into an
125
+ // all-zero "system not running" report for EVERY panel, including
126
+ // memory and tasks that were perfectly readable.
97
127
  agents: {
98
- total: swarmStatus.agents.total,
99
- active: swarmStatus.agents.active,
100
- idle: swarmStatus.agents.idle
128
+ total: swarmStatus.agents?.total ?? 0,
129
+ active: swarmStatus.agents?.active ?? 0,
130
+ idle: swarmStatus.agents?.idle ?? 0
101
131
  },
102
132
  health: swarmStatus.health,
103
133
  uptime: swarmStatus.uptime
@@ -121,7 +151,18 @@ async function getSystemStatus() {
121
151
  };
122
152
  }
123
153
  catch (error) {
124
- // System not running
154
+ // Reaching here does NOT prove the system is stopped — it means reading its
155
+ // state threw. The block below reports zeros for every panel, so swallowing
156
+ // the cause made a failed read indistinguishable from a genuinely idle
157
+ // project: a repo with a populated memory store and a live agent was told
158
+ // "Total 0 / Entries 0 / Backend none".
159
+ if (process.env.DEBUG || process.env.MONOMIND_DEBUG) {
160
+ console.error('[status] could not read system state:', error);
161
+ }
162
+ else {
163
+ output.writeln(output.warning(`Could not read full system state (${error instanceof Error ? error.message : String(error)}) — ` +
164
+ 'the figures below are defaults, not measurements. Re-run with DEBUG=1 for detail.'));
165
+ }
125
166
  return {
126
167
  initialized: true,
127
168
  running: false,
@@ -177,10 +177,15 @@ export const taskTools = [
177
177
  const store = loadTaskStore();
178
178
  let tasks = Object.values(store.tasks);
179
179
  // Apply filters
180
- if (input.status) {
180
+ // 'all' is a sentinel meaning "do not filter", not a status any task has.
181
+ // Without this, `task list --all` and `monomind status tasks` — both of
182
+ // which pass status:'all' — matched nothing and reported an empty store
183
+ // while tasks existed on disk.
184
+ if (input.status && input.status !== 'all') {
181
185
  // Support comma-separated status values
182
- const statuses = input.status.split(',').map(s => s.trim());
183
- tasks = tasks.filter(t => statuses.includes(t.status));
186
+ const statuses = input.status.split(',').map(s => s.trim()).filter(s => s !== 'all');
187
+ if (statuses.length > 0)
188
+ tasks = tasks.filter(t => statuses.includes(t.status));
184
189
  }
185
190
  if (input.type) {
186
191
  tasks = tasks.filter(t => t.type === input.type);
@@ -344,7 +344,22 @@ export async function deleteEntry(options) {
344
344
  if (bridgeResult.deleted) {
345
345
  rebuildSearchIndex();
346
346
  }
347
- return { ...bridgeResult, key: options.key, namespace: options.namespace ?? 'default', remainingEntries: 0 };
347
+ // Count what is actually left rather than asserting zero. This returned a
348
+ // hardcoded 0 on the default bridge path (the sql.js fallback below always
349
+ // computed it), so every successful delete printed "Remaining entries: 0"
350
+ // — telling the user their namespace was empty when it was not, and
351
+ // handing any script reading data.remainingEntries a false "done".
352
+ const ns = options.namespace ?? 'default';
353
+ let remainingEntries = 0;
354
+ try {
355
+ const listed = await bridge.bridgeListEntries({ namespace: ns, limit: 100_000, dbPath: options.dbPath });
356
+ remainingEntries = listed?.entries?.length ?? 0;
357
+ }
358
+ catch {
359
+ // Counting is best-effort; a failed count must not fail the delete that
360
+ // already succeeded. 0 here means "unknown", same as before this fix.
361
+ }
362
+ return { ...bridgeResult, key: options.key, namespace: ns, remainingEntries };
348
363
  }
349
364
  }
350
365
  // Fallback: raw sql.js
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "2.7.8",
3
+ "version": "2.7.10",
4
4
  "type": "module",
5
5
  "description": "CLI engine for Monomind \u2014 an open-source MCP server that extends Claude Code with a codebase knowledge graph (tree-sitter + SQLite), persistent memory, multi-agent task coordination, and session hooks. MIT licensed, fully local.",
6
6
  "main": "dist/src/index.js",
@@ -110,7 +110,7 @@
110
110
  },
111
111
  "optionalDependencies": {
112
112
  "@huggingface/transformers": "^3.8.1",
113
- "@monoes/hooks": "^1.0.0",
113
+ "@monoes/hooks": "^1.0.1",
114
114
  "@monoes/mcp": "^1.0.1",
115
115
  "@monoes/memory": "^1.0.10",
116
116
  "@monoes/routing": "^1.0.1",