@gethmy/mcp 2.3.2 → 2.3.4
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/dist/cli.js +199 -4
- package/dist/index.js +199 -4
- package/dist/lib/api-client.js +1 -433
- package/dist/lib/config.js +0 -18
- package/package.json +9 -5
- package/src/api-client.ts +6 -0
- package/src/memory-cleanup.ts +158 -0
- package/src/server.ts +140 -7
- package/dist/lib/active-learning.js +0 -974
- package/dist/lib/auto-session.js +0 -195
- package/dist/lib/cli.js +0 -34964
- package/dist/lib/consolidation.js +0 -388
- package/dist/lib/context-assembly.js +0 -1311
- package/dist/lib/graph-expansion.js +0 -147
- package/dist/lib/http.js +0 -1962
- package/dist/lib/index.js +0 -29527
- package/dist/lib/lifecycle-maintenance.js +0 -672
- package/dist/lib/memory-cleanup.js +0 -1361
- package/dist/lib/onboard.js +0 -2592
- package/dist/lib/prompt-builder.js +0 -481
- package/dist/lib/remote.js +0 -31756
- package/dist/lib/server.js +0 -29524
- package/dist/lib/skills.js +0 -776
- package/dist/lib/tui/agents.js +0 -137
- package/dist/lib/tui/docs.js +0 -1647
- package/dist/lib/tui/setup.js +0 -5828
- package/dist/lib/tui/theme.js +0 -192
- package/dist/lib/tui/writer.js +0 -1173
package/dist/lib/api-client.js
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
4
1
|
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
-
for (let key of __getOwnPropNames(mod))
|
|
11
|
-
if (!__hasOwnProp.call(to, key))
|
|
12
|
-
__defProp(to, key, {
|
|
13
|
-
get: () => mod[key],
|
|
14
|
-
enumerable: true
|
|
15
|
-
});
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
2
|
var __export = (target, all) => {
|
|
20
3
|
for (var name in all)
|
|
21
4
|
__defProp(target, name, {
|
|
@@ -26,7 +9,6 @@ var __export = (target, all) => {
|
|
|
26
9
|
});
|
|
27
10
|
};
|
|
28
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
29
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
30
12
|
|
|
31
13
|
// ../memory/dist/schema.js
|
|
32
14
|
var init_schema = () => {};
|
|
@@ -122,18 +104,6 @@ async function discoverRelatedContext(client, startIds, maxDepth = 2, maxEntitie
|
|
|
122
104
|
}
|
|
123
105
|
|
|
124
106
|
// ../memory/dist/lifecycle.js
|
|
125
|
-
function computeDecayScore(tier, lastAccessedAt, accessCount) {
|
|
126
|
-
const halfLife = DECAY_HALF_LIVES[tier];
|
|
127
|
-
const now = Date.now();
|
|
128
|
-
let daysSinceAccess = 0;
|
|
129
|
-
if (lastAccessedAt) {
|
|
130
|
-
daysSinceAccess = (now - new Date(lastAccessedAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
131
|
-
}
|
|
132
|
-
const timeDecay = 0.5 ** (daysSinceAccess / halfLife);
|
|
133
|
-
const accessBonus = Math.log10(accessCount + 1) * 0.1;
|
|
134
|
-
const score = Math.min(timeDecay + accessBonus, 1);
|
|
135
|
-
return { score, daysSinceAccess, halfLife, accessBonus };
|
|
136
|
-
}
|
|
137
107
|
function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
138
108
|
const ageDays = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
139
109
|
const base = {
|
|
@@ -169,29 +139,8 @@ function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
|
169
139
|
}
|
|
170
140
|
return base;
|
|
171
141
|
}
|
|
172
|
-
|
|
173
|
-
const decay = computeDecayScore(entity.memory_tier, entity.last_accessed_at, entity.access_count);
|
|
174
|
-
const promotion = checkPromotion(entity.memory_tier, entity.access_count, entity.confidence, entity.created_at);
|
|
175
|
-
const shouldArchive = entity.confidence < ARCHIVE_THRESHOLD;
|
|
176
|
-
const archiveReason = shouldArchive ? `Confidence ${entity.confidence} below threshold ${ARCHIVE_THRESHOLD}` : undefined;
|
|
177
|
-
const shouldFlagForReview = decay.daysSinceAccess >= STALE_DAYS && entity.access_count < STALE_MIN_ACCESS;
|
|
178
|
-
const reviewReason = shouldFlagForReview ? `Not accessed in ${Math.round(decay.daysSinceAccess)} days with only ${entity.access_count} accesses` : undefined;
|
|
179
|
-
return {
|
|
180
|
-
decay,
|
|
181
|
-
promotion,
|
|
182
|
-
shouldArchive,
|
|
183
|
-
shouldFlagForReview,
|
|
184
|
-
archiveReason,
|
|
185
|
-
reviewReason
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
var DECAY_HALF_LIVES, PROMOTION_RULES, ARCHIVE_THRESHOLD = 0.3, STALE_DAYS = 90, STALE_MIN_ACCESS = 3;
|
|
142
|
+
var PROMOTION_RULES;
|
|
189
143
|
var init_lifecycle = __esm(() => {
|
|
190
|
-
DECAY_HALF_LIVES = {
|
|
191
|
-
draft: 7,
|
|
192
|
-
episode: 30,
|
|
193
|
-
reference: 180
|
|
194
|
-
};
|
|
195
144
|
PROMOTION_RULES = {
|
|
196
145
|
draftToEpisode: {
|
|
197
146
|
minAccessCount: 5,
|
|
@@ -205,388 +154,7 @@ var init_lifecycle = __esm(() => {
|
|
|
205
154
|
}
|
|
206
155
|
};
|
|
207
156
|
});
|
|
208
|
-
|
|
209
|
-
// ../memory/dist/sync-storage.js
|
|
210
|
-
function parseSyncMarkdown(markdown) {
|
|
211
|
-
const trimmed = markdown.trim();
|
|
212
|
-
let frontmatter = {
|
|
213
|
-
type: "context",
|
|
214
|
-
scope: "project",
|
|
215
|
-
tier: "reference",
|
|
216
|
-
confidence: 1,
|
|
217
|
-
tags: []
|
|
218
|
-
};
|
|
219
|
-
let body = trimmed;
|
|
220
|
-
const fmMatch = trimmed.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
221
|
-
if (fmMatch) {
|
|
222
|
-
frontmatter = parseSyncYamlFrontmatter(fmMatch[1]);
|
|
223
|
-
body = fmMatch[2].trim();
|
|
224
|
-
}
|
|
225
|
-
let title = "";
|
|
226
|
-
const titleMatch = body.match(/^#\s+(.+)/m);
|
|
227
|
-
if (titleMatch) {
|
|
228
|
-
title = titleMatch[1].trim();
|
|
229
|
-
body = body.replace(/^#\s+.+\n?/, "").trim();
|
|
230
|
-
}
|
|
231
|
-
return { frontmatter, title, content: body };
|
|
232
|
-
}
|
|
233
|
-
function serializeSyncMarkdown(entity) {
|
|
234
|
-
const lines = ["---"];
|
|
235
|
-
lines.push(`id: ${entity.id}`);
|
|
236
|
-
lines.push(`workspace_id: ${entity.workspace_id}`);
|
|
237
|
-
if (entity.project_id) {
|
|
238
|
-
lines.push(`project_id: ${entity.project_id}`);
|
|
239
|
-
}
|
|
240
|
-
lines.push(`type: ${entity.type}`);
|
|
241
|
-
lines.push(`scope: ${entity.scope}`);
|
|
242
|
-
lines.push(`tier: ${entity.memory_tier || "reference"}`);
|
|
243
|
-
lines.push(`confidence: ${entity.confidence}`);
|
|
244
|
-
if (entity.tags.length > 0) {
|
|
245
|
-
lines.push(`tags: [${entity.tags.join(", ")}]`);
|
|
246
|
-
} else {
|
|
247
|
-
lines.push("tags: []");
|
|
248
|
-
}
|
|
249
|
-
if (entity.agent_identifier) {
|
|
250
|
-
lines.push(`agent: ${entity.agent_identifier}`);
|
|
251
|
-
}
|
|
252
|
-
lines.push(`created_at: ${entity.created_at}`);
|
|
253
|
-
lines.push(`updated_at: ${entity.updated_at}`);
|
|
254
|
-
lines.push("---");
|
|
255
|
-
lines.push("");
|
|
256
|
-
lines.push(`# ${entity.title}`);
|
|
257
|
-
lines.push("");
|
|
258
|
-
lines.push(entity.content);
|
|
259
|
-
return lines.join(`
|
|
260
|
-
`);
|
|
261
|
-
}
|
|
262
|
-
function parseSyncYamlFrontmatter(yaml) {
|
|
263
|
-
const result = {
|
|
264
|
-
type: "context",
|
|
265
|
-
scope: "project",
|
|
266
|
-
tier: "reference",
|
|
267
|
-
confidence: 1,
|
|
268
|
-
tags: []
|
|
269
|
-
};
|
|
270
|
-
for (const line of yaml.split(`
|
|
271
|
-
`)) {
|
|
272
|
-
const colonIndex = line.indexOf(":");
|
|
273
|
-
if (colonIndex === -1)
|
|
274
|
-
continue;
|
|
275
|
-
const key = line.slice(0, colonIndex).trim();
|
|
276
|
-
const value = line.slice(colonIndex + 1).trim();
|
|
277
|
-
switch (key) {
|
|
278
|
-
case "id":
|
|
279
|
-
result.id = value;
|
|
280
|
-
break;
|
|
281
|
-
case "workspace_id":
|
|
282
|
-
result.workspace_id = value;
|
|
283
|
-
break;
|
|
284
|
-
case "project_id":
|
|
285
|
-
result.project_id = value;
|
|
286
|
-
break;
|
|
287
|
-
case "type":
|
|
288
|
-
result.type = value;
|
|
289
|
-
break;
|
|
290
|
-
case "scope":
|
|
291
|
-
result.scope = value;
|
|
292
|
-
break;
|
|
293
|
-
case "tier":
|
|
294
|
-
result.tier = value;
|
|
295
|
-
break;
|
|
296
|
-
case "confidence":
|
|
297
|
-
result.confidence = parseFloat(value) || 1;
|
|
298
|
-
break;
|
|
299
|
-
case "tags":
|
|
300
|
-
result.tags = parseYamlArray(value);
|
|
301
|
-
break;
|
|
302
|
-
case "related":
|
|
303
|
-
result.related = parseYamlArray(value);
|
|
304
|
-
break;
|
|
305
|
-
case "agent":
|
|
306
|
-
result.agent = value;
|
|
307
|
-
break;
|
|
308
|
-
case "created_at":
|
|
309
|
-
result.created_at = value;
|
|
310
|
-
break;
|
|
311
|
-
case "updated_at":
|
|
312
|
-
result.updated_at = value;
|
|
313
|
-
break;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
return result;
|
|
317
|
-
}
|
|
318
|
-
function parseYamlArray(value) {
|
|
319
|
-
const match = value.match(/^\[(.*)]\s*$/);
|
|
320
|
-
if (!match)
|
|
321
|
-
return [];
|
|
322
|
-
return match[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
157
|
// ../memory/dist/sync.js
|
|
326
|
-
import { createHash } from "node:crypto";
|
|
327
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
328
|
-
import { join as join2, relative, sep } from "node:path";
|
|
329
|
-
function computeFileHash(content) {
|
|
330
|
-
return `sha256:${createHash("sha256").update(content).digest("hex")}`;
|
|
331
|
-
}
|
|
332
|
-
function slugifyTitle(title) {
|
|
333
|
-
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
334
|
-
}
|
|
335
|
-
function entityToFilename(entity) {
|
|
336
|
-
const slug = slugifyTitle(entity.title);
|
|
337
|
-
const shortId = entity.id.slice(0, 8);
|
|
338
|
-
return `${entity.type}--${slug}--${shortId}.md`;
|
|
339
|
-
}
|
|
340
|
-
function entityToDirectoryPath(entity, memoryDir) {
|
|
341
|
-
const wsDir = join2(memoryDir, entity.workspace_id);
|
|
342
|
-
if (entity.scope === "private") {
|
|
343
|
-
return join2(wsDir, "_private");
|
|
344
|
-
}
|
|
345
|
-
if (entity.scope === "workspace" || !entity.project_id) {
|
|
346
|
-
return join2(wsDir, "_workspace");
|
|
347
|
-
}
|
|
348
|
-
return join2(wsDir, entity.project_id);
|
|
349
|
-
}
|
|
350
|
-
function emptySyncState() {
|
|
351
|
-
return { version: 1, lastPullAt: null, entities: {} };
|
|
352
|
-
}
|
|
353
|
-
function loadSyncState(memoryDir) {
|
|
354
|
-
const statePath = join2(memoryDir, ".sync-state.json");
|
|
355
|
-
if (!existsSync2(statePath))
|
|
356
|
-
return emptySyncState();
|
|
357
|
-
try {
|
|
358
|
-
return JSON.parse(readFileSync2(statePath, "utf-8"));
|
|
359
|
-
} catch {
|
|
360
|
-
return emptySyncState();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
function saveSyncState(memoryDir, state) {
|
|
364
|
-
if (!existsSync2(memoryDir)) {
|
|
365
|
-
mkdirSync2(memoryDir, { recursive: true });
|
|
366
|
-
}
|
|
367
|
-
writeFileSync2(join2(memoryDir, ".sync-state.json"), JSON.stringify(state, null, 2));
|
|
368
|
-
}
|
|
369
|
-
function writeEntityFile(entity, memoryDir) {
|
|
370
|
-
const dir = entityToDirectoryPath(entity, memoryDir);
|
|
371
|
-
if (!existsSync2(dir))
|
|
372
|
-
mkdirSync2(dir, { recursive: true });
|
|
373
|
-
const filename = entityToFilename(entity);
|
|
374
|
-
const filePath = join2(dir, filename);
|
|
375
|
-
const markdown = serializeSyncMarkdown(entity);
|
|
376
|
-
writeFileSync2(filePath, markdown);
|
|
377
|
-
return relative(memoryDir, filePath);
|
|
378
|
-
}
|
|
379
|
-
function deleteEntityFile(relPath, memoryDir) {
|
|
380
|
-
const absPath = join2(memoryDir, relPath);
|
|
381
|
-
if (existsSync2(absPath)) {
|
|
382
|
-
rmSync(absPath);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
function findMarkdownFiles(dir) {
|
|
386
|
-
const results = [];
|
|
387
|
-
if (!existsSync2(dir))
|
|
388
|
-
return results;
|
|
389
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
390
|
-
const fullPath = join2(dir, entry.name);
|
|
391
|
-
if (entry.isDirectory()) {
|
|
392
|
-
results.push(...findMarkdownFiles(fullPath));
|
|
393
|
-
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
394
|
-
results.push(fullPath);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
return results;
|
|
398
|
-
}
|
|
399
|
-
async function syncPull(client, config, workspaceId, projectId) {
|
|
400
|
-
const { memoryDir } = config;
|
|
401
|
-
const state = loadSyncState(memoryDir);
|
|
402
|
-
const result = {
|
|
403
|
-
pulled: 0,
|
|
404
|
-
pushed: 0,
|
|
405
|
-
deleted: 0,
|
|
406
|
-
conflicts: 0,
|
|
407
|
-
errors: []
|
|
408
|
-
};
|
|
409
|
-
const allEntities = [];
|
|
410
|
-
let offset = 0;
|
|
411
|
-
const batchSize = 100;
|
|
412
|
-
while (true) {
|
|
413
|
-
try {
|
|
414
|
-
const resp = await client.listMemoryEntities({
|
|
415
|
-
workspace_id: workspaceId,
|
|
416
|
-
project_id: projectId,
|
|
417
|
-
limit: batchSize,
|
|
418
|
-
offset
|
|
419
|
-
});
|
|
420
|
-
const batch = resp.entities;
|
|
421
|
-
allEntities.push(...batch);
|
|
422
|
-
if (batch.length < batchSize)
|
|
423
|
-
break;
|
|
424
|
-
offset += batchSize;
|
|
425
|
-
} catch (err) {
|
|
426
|
-
result.errors.push(`Failed to fetch entities: ${err}`);
|
|
427
|
-
return result;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
const remoteIds = new Set(allEntities.map((e) => e.id));
|
|
431
|
-
for (const entity of allEntities) {
|
|
432
|
-
const existing = state.entities[entity.id];
|
|
433
|
-
const markdown = serializeSyncMarkdown(entity);
|
|
434
|
-
const hash = computeFileHash(markdown);
|
|
435
|
-
if (!existing) {
|
|
436
|
-
const relPath = writeEntityFile(entity, memoryDir);
|
|
437
|
-
state.entities[entity.id] = {
|
|
438
|
-
filePath: relPath,
|
|
439
|
-
remoteUpdatedAt: entity.updated_at,
|
|
440
|
-
lastSyncedHash: hash
|
|
441
|
-
};
|
|
442
|
-
result.pulled++;
|
|
443
|
-
} else {
|
|
444
|
-
const remoteChanged = entity.updated_at > existing.remoteUpdatedAt;
|
|
445
|
-
if (!remoteChanged)
|
|
446
|
-
continue;
|
|
447
|
-
const absPath = join2(memoryDir, existing.filePath);
|
|
448
|
-
let localChanged = false;
|
|
449
|
-
if (existsSync2(absPath)) {
|
|
450
|
-
const localContent = readFileSync2(absPath, "utf-8");
|
|
451
|
-
const localHash = computeFileHash(localContent);
|
|
452
|
-
localChanged = localHash !== existing.lastSyncedHash;
|
|
453
|
-
}
|
|
454
|
-
if (localChanged) {
|
|
455
|
-
result.conflicts++;
|
|
456
|
-
}
|
|
457
|
-
const newRelPath = writeEntityFile(entity, memoryDir);
|
|
458
|
-
if (existing.filePath !== newRelPath) {
|
|
459
|
-
deleteEntityFile(existing.filePath, memoryDir);
|
|
460
|
-
}
|
|
461
|
-
state.entities[entity.id] = {
|
|
462
|
-
filePath: newRelPath,
|
|
463
|
-
remoteUpdatedAt: entity.updated_at,
|
|
464
|
-
lastSyncedHash: hash
|
|
465
|
-
};
|
|
466
|
-
result.pulled++;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
for (const [entityId, entry] of Object.entries(state.entities)) {
|
|
470
|
-
if (!remoteIds.has(entityId)) {
|
|
471
|
-
deleteEntityFile(entry.filePath, memoryDir);
|
|
472
|
-
delete state.entities[entityId];
|
|
473
|
-
result.deleted++;
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
state.lastPullAt = new Date().toISOString();
|
|
477
|
-
saveSyncState(memoryDir, state);
|
|
478
|
-
return result;
|
|
479
|
-
}
|
|
480
|
-
async function syncPush(client, config, workspaceId) {
|
|
481
|
-
const { memoryDir } = config;
|
|
482
|
-
const state = loadSyncState(memoryDir);
|
|
483
|
-
const result = {
|
|
484
|
-
pulled: 0,
|
|
485
|
-
pushed: 0,
|
|
486
|
-
deleted: 0,
|
|
487
|
-
conflicts: 0,
|
|
488
|
-
errors: []
|
|
489
|
-
};
|
|
490
|
-
const mdFiles = findMarkdownFiles(memoryDir);
|
|
491
|
-
for (const absPath of mdFiles) {
|
|
492
|
-
const content = readFileSync2(absPath, "utf-8");
|
|
493
|
-
const hash = computeFileHash(content);
|
|
494
|
-
const parsed = parseSyncMarkdown(content);
|
|
495
|
-
if (parsed.frontmatter.id) {
|
|
496
|
-
const entityId = parsed.frontmatter.id;
|
|
497
|
-
const existing = state.entities[entityId];
|
|
498
|
-
if (existing && hash === existing.lastSyncedHash)
|
|
499
|
-
continue;
|
|
500
|
-
try {
|
|
501
|
-
const resp = await client.updateMemoryEntity(entityId, {
|
|
502
|
-
title: parsed.title || "Untitled",
|
|
503
|
-
content: parsed.content,
|
|
504
|
-
type: parsed.frontmatter.type,
|
|
505
|
-
scope: parsed.frontmatter.scope,
|
|
506
|
-
confidence: parsed.frontmatter.confidence,
|
|
507
|
-
tags: parsed.frontmatter.tags
|
|
508
|
-
});
|
|
509
|
-
const updated = resp.entity;
|
|
510
|
-
const newMarkdown = serializeSyncMarkdown(updated);
|
|
511
|
-
writeFileSync2(absPath, newMarkdown);
|
|
512
|
-
const relPath = relative(memoryDir, absPath);
|
|
513
|
-
state.entities[entityId] = {
|
|
514
|
-
filePath: relPath,
|
|
515
|
-
remoteUpdatedAt: updated.updated_at,
|
|
516
|
-
lastSyncedHash: computeFileHash(newMarkdown)
|
|
517
|
-
};
|
|
518
|
-
result.pushed++;
|
|
519
|
-
} catch (err) {
|
|
520
|
-
result.errors.push(`Failed to update ${entityId}: ${err}`);
|
|
521
|
-
}
|
|
522
|
-
} else {
|
|
523
|
-
const relPath = relative(memoryDir, absPath);
|
|
524
|
-
const parts = relPath.split(sep);
|
|
525
|
-
const fileWorkspaceId = parts.length >= 2 ? parts[0] : workspaceId;
|
|
526
|
-
let fileProjectId;
|
|
527
|
-
if (parts.length >= 3) {
|
|
528
|
-
const scopeDir = parts[1];
|
|
529
|
-
if (scopeDir !== "_workspace" && scopeDir !== "_private") {
|
|
530
|
-
fileProjectId = scopeDir;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
let scope = parsed.frontmatter.scope || "project";
|
|
534
|
-
if (parts.length >= 3) {
|
|
535
|
-
const scopeDir = parts[1];
|
|
536
|
-
if (scopeDir === "_private")
|
|
537
|
-
scope = "private";
|
|
538
|
-
else if (scopeDir === "_workspace")
|
|
539
|
-
scope = "workspace";
|
|
540
|
-
}
|
|
541
|
-
try {
|
|
542
|
-
const resp = await client.createMemoryEntity({
|
|
543
|
-
workspace_id: fileWorkspaceId,
|
|
544
|
-
project_id: fileProjectId,
|
|
545
|
-
type: parsed.frontmatter.type,
|
|
546
|
-
scope,
|
|
547
|
-
title: parsed.title || "Untitled",
|
|
548
|
-
content: parsed.content,
|
|
549
|
-
confidence: parsed.frontmatter.confidence,
|
|
550
|
-
tags: parsed.frontmatter.tags,
|
|
551
|
-
agent_identifier: parsed.frontmatter.agent
|
|
552
|
-
});
|
|
553
|
-
const created = resp.entity;
|
|
554
|
-
const dir = entityToDirectoryPath(created, memoryDir);
|
|
555
|
-
if (!existsSync2(dir))
|
|
556
|
-
mkdirSync2(dir, { recursive: true });
|
|
557
|
-
const newFilename = entityToFilename(created);
|
|
558
|
-
const newAbsPath = join2(dir, newFilename);
|
|
559
|
-
const newMarkdown = serializeSyncMarkdown(created);
|
|
560
|
-
writeFileSync2(newAbsPath, newMarkdown);
|
|
561
|
-
if (absPath !== newAbsPath && existsSync2(absPath)) {
|
|
562
|
-
rmSync(absPath);
|
|
563
|
-
}
|
|
564
|
-
const newRelPath = relative(memoryDir, newAbsPath);
|
|
565
|
-
state.entities[created.id] = {
|
|
566
|
-
filePath: newRelPath,
|
|
567
|
-
remoteUpdatedAt: created.updated_at,
|
|
568
|
-
lastSyncedHash: computeFileHash(newMarkdown)
|
|
569
|
-
};
|
|
570
|
-
result.pushed++;
|
|
571
|
-
} catch (err) {
|
|
572
|
-
result.errors.push(`Failed to create entity from ${relPath}: ${err}`);
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
saveSyncState(memoryDir, state);
|
|
577
|
-
return result;
|
|
578
|
-
}
|
|
579
|
-
async function syncFull(client, config, workspaceId, projectId) {
|
|
580
|
-
const pullResult = await syncPull(client, config, workspaceId, projectId);
|
|
581
|
-
const pushResult = await syncPush(client, config, workspaceId);
|
|
582
|
-
return {
|
|
583
|
-
pulled: pullResult.pulled,
|
|
584
|
-
pushed: pushResult.pushed,
|
|
585
|
-
deleted: pullResult.deleted,
|
|
586
|
-
conflicts: pullResult.conflicts,
|
|
587
|
-
errors: [...pullResult.errors, ...pushResult.errors]
|
|
588
|
-
};
|
|
589
|
-
}
|
|
590
158
|
var init_sync = () => {};
|
|
591
159
|
|
|
592
160
|
// ../memory/dist/index.js
|
package/dist/lib/config.js
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
4
1
|
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
-
for (let key of __getOwnPropNames(mod))
|
|
11
|
-
if (!__hasOwnProp.call(to, key))
|
|
12
|
-
__defProp(to, key, {
|
|
13
|
-
get: () => mod[key],
|
|
14
|
-
enumerable: true
|
|
15
|
-
});
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
19
2
|
var __export = (target, all) => {
|
|
20
3
|
for (var name in all)
|
|
21
4
|
__defProp(target, name, {
|
|
@@ -26,7 +9,6 @@ var __export = (target, all) => {
|
|
|
26
9
|
});
|
|
27
10
|
};
|
|
28
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
29
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
30
12
|
|
|
31
13
|
// src/config.ts
|
|
32
14
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethmy/mcp",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
4
4
|
"description": "MCP server for Harmony Kanban board - enables AI coding agents to manage your boards",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -9,9 +9,13 @@
|
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"exports": {
|
|
11
11
|
".": "./dist/index.js",
|
|
12
|
-
"./src
|
|
13
|
-
"types": "./src
|
|
14
|
-
"default": "./dist/lib
|
|
12
|
+
"./src/api-client.js": {
|
|
13
|
+
"types": "./src/api-client.ts",
|
|
14
|
+
"default": "./dist/lib/api-client.js"
|
|
15
|
+
},
|
|
16
|
+
"./src/config.js": {
|
|
17
|
+
"types": "./src/config.ts",
|
|
18
|
+
"default": "./dist/lib/config.js"
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
21
|
"bin": {
|
|
@@ -50,7 +54,7 @@
|
|
|
50
54
|
"bun": ">=1.0.0"
|
|
51
55
|
},
|
|
52
56
|
"scripts": {
|
|
53
|
-
"build": "bun build src/index.ts src/cli.ts --outdir dist --target node && bun build src
|
|
57
|
+
"build": "bun build src/index.ts src/cli.ts --outdir dist --target node && bun build src/api-client.ts src/config.ts --outdir dist/lib --root src --target node",
|
|
54
58
|
"build:bun": "bun build src/index.ts src/http.ts src/remote.ts src/cli.ts --outdir dist --target bun",
|
|
55
59
|
"serve:remote": "bun src/remote.ts",
|
|
56
60
|
"dev": "bun --watch src/index.ts",
|
package/src/api-client.ts
CHANGED
|
@@ -502,6 +502,9 @@ export class HarmonyApiClient {
|
|
|
502
502
|
phase?: string;
|
|
503
503
|
filesChanged?: number;
|
|
504
504
|
costCents?: number;
|
|
505
|
+
inputTokens?: number;
|
|
506
|
+
outputTokens?: number;
|
|
507
|
+
recentActions?: { action: string; ts: string }[];
|
|
505
508
|
},
|
|
506
509
|
): Promise<{ session: unknown; created: boolean }> {
|
|
507
510
|
return this.request("POST", `/cards/${cardId}/agent-context`, data);
|
|
@@ -512,6 +515,9 @@ export class HarmonyApiClient {
|
|
|
512
515
|
data?: {
|
|
513
516
|
status?: "completed" | "paused";
|
|
514
517
|
progressPercent?: number;
|
|
518
|
+
costCents?: number;
|
|
519
|
+
inputTokens?: number;
|
|
520
|
+
outputTokens?: number;
|
|
515
521
|
},
|
|
516
522
|
): Promise<{ session: unknown }> {
|
|
517
523
|
return this.request("DELETE", `/cards/${cardId}/agent-context`, data);
|