harmony-mcp 1.10.0 → 1.11.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.
- package/dist/cli.js +272 -202
- package/dist/index.js +265 -195
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -14371,6 +14371,187 @@ function getMemoryDir() {
|
|
|
14371
14371
|
return config.memoryDir;
|
|
14372
14372
|
return join(homedir(), ".harmony", "memory");
|
|
14373
14373
|
}
|
|
14374
|
+
// ../memory/src/graph-walk.ts
|
|
14375
|
+
async function discoverRelatedContext(client, startIds, maxDepth = 2, maxEntities = 20, minConfidence = 0.5) {
|
|
14376
|
+
const visited = new Set;
|
|
14377
|
+
const collectedEntities = [];
|
|
14378
|
+
const collectedRelations = [];
|
|
14379
|
+
let truncated = false;
|
|
14380
|
+
const queue = startIds.map((id) => [id, 0]);
|
|
14381
|
+
for (const id of startIds) {
|
|
14382
|
+
visited.add(id);
|
|
14383
|
+
}
|
|
14384
|
+
while (queue.length > 0) {
|
|
14385
|
+
const [entityId, depth] = queue.shift();
|
|
14386
|
+
if (collectedEntities.length >= maxEntities) {
|
|
14387
|
+
truncated = true;
|
|
14388
|
+
break;
|
|
14389
|
+
}
|
|
14390
|
+
if (depth > maxDepth)
|
|
14391
|
+
continue;
|
|
14392
|
+
try {
|
|
14393
|
+
const entityResult = await client.getMemoryEntity(entityId);
|
|
14394
|
+
const entity = entityResult.entity;
|
|
14395
|
+
if (entity) {
|
|
14396
|
+
collectedEntities.push({
|
|
14397
|
+
id: entity.id,
|
|
14398
|
+
type: entity.type,
|
|
14399
|
+
title: entity.title,
|
|
14400
|
+
confidence: entity.confidence ?? 1,
|
|
14401
|
+
memory_tier: entity.memory_tier || "reference"
|
|
14402
|
+
});
|
|
14403
|
+
}
|
|
14404
|
+
if (depth >= maxDepth)
|
|
14405
|
+
continue;
|
|
14406
|
+
const related = await client.getRelatedEntities(entityId);
|
|
14407
|
+
for (const raw of related.outgoing || []) {
|
|
14408
|
+
const rel = raw;
|
|
14409
|
+
const relConfidence = rel.confidence ?? 1;
|
|
14410
|
+
if (relConfidence < minConfidence)
|
|
14411
|
+
continue;
|
|
14412
|
+
const target = rel.target;
|
|
14413
|
+
const targetId = target?.id ?? rel.target_id;
|
|
14414
|
+
if (targetId && !visited.has(targetId)) {
|
|
14415
|
+
visited.add(targetId);
|
|
14416
|
+
queue.push([targetId, depth + 1]);
|
|
14417
|
+
collectedRelations.push({
|
|
14418
|
+
id: rel.id,
|
|
14419
|
+
source_id: entityId,
|
|
14420
|
+
target_id: targetId,
|
|
14421
|
+
relation_type: rel.relation_type,
|
|
14422
|
+
confidence: relConfidence
|
|
14423
|
+
});
|
|
14424
|
+
}
|
|
14425
|
+
}
|
|
14426
|
+
for (const raw of related.incoming || []) {
|
|
14427
|
+
const rel = raw;
|
|
14428
|
+
const relConfidence = rel.confidence ?? 1;
|
|
14429
|
+
if (relConfidence < minConfidence)
|
|
14430
|
+
continue;
|
|
14431
|
+
const source = rel.source;
|
|
14432
|
+
const sourceId = source?.id ?? rel.source_id;
|
|
14433
|
+
if (sourceId && !visited.has(sourceId)) {
|
|
14434
|
+
visited.add(sourceId);
|
|
14435
|
+
queue.push([sourceId, depth + 1]);
|
|
14436
|
+
collectedRelations.push({
|
|
14437
|
+
id: rel.id,
|
|
14438
|
+
source_id: sourceId,
|
|
14439
|
+
target_id: entityId,
|
|
14440
|
+
relation_type: rel.relation_type,
|
|
14441
|
+
confidence: relConfidence
|
|
14442
|
+
});
|
|
14443
|
+
}
|
|
14444
|
+
}
|
|
14445
|
+
} catch {}
|
|
14446
|
+
}
|
|
14447
|
+
return {
|
|
14448
|
+
entities: collectedEntities,
|
|
14449
|
+
relations: collectedRelations,
|
|
14450
|
+
depth: maxDepth,
|
|
14451
|
+
truncated
|
|
14452
|
+
};
|
|
14453
|
+
}
|
|
14454
|
+
// ../memory/src/lifecycle.ts
|
|
14455
|
+
var DECAY_HALF_LIVES = {
|
|
14456
|
+
draft: 7,
|
|
14457
|
+
episode: 30,
|
|
14458
|
+
reference: 180
|
|
14459
|
+
};
|
|
14460
|
+
var PROMOTION_RULES = {
|
|
14461
|
+
draftToEpisode: {
|
|
14462
|
+
minAccessCount: 5,
|
|
14463
|
+
minConfidence: 0.8,
|
|
14464
|
+
minAgeDays: 1
|
|
14465
|
+
},
|
|
14466
|
+
episodeToReference: {
|
|
14467
|
+
minAccessCount: 10,
|
|
14468
|
+
minConfidence: 0.9,
|
|
14469
|
+
minAgeDays: 7
|
|
14470
|
+
}
|
|
14471
|
+
};
|
|
14472
|
+
var ARCHIVE_THRESHOLD = 0.3;
|
|
14473
|
+
var STALE_DAYS = 90;
|
|
14474
|
+
var STALE_MIN_ACCESS = 3;
|
|
14475
|
+
function computeDecayScore(tier, lastAccessedAt, accessCount) {
|
|
14476
|
+
const halfLife = DECAY_HALF_LIVES[tier];
|
|
14477
|
+
const now = Date.now();
|
|
14478
|
+
let daysSinceAccess = 0;
|
|
14479
|
+
if (lastAccessedAt) {
|
|
14480
|
+
daysSinceAccess = (now - new Date(lastAccessedAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
14481
|
+
}
|
|
14482
|
+
const timeDecay = 0.5 ** (daysSinceAccess / halfLife);
|
|
14483
|
+
const accessBonus = Math.log10(accessCount + 1) * 0.1;
|
|
14484
|
+
const score = Math.min(timeDecay + accessBonus, 1);
|
|
14485
|
+
return { score, daysSinceAccess, halfLife, accessBonus };
|
|
14486
|
+
}
|
|
14487
|
+
function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
14488
|
+
const ageDays = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
14489
|
+
const base = {
|
|
14490
|
+
eligible: false,
|
|
14491
|
+
targetTier: null,
|
|
14492
|
+
reason: null,
|
|
14493
|
+
currentTier,
|
|
14494
|
+
accessCount,
|
|
14495
|
+
confidence,
|
|
14496
|
+
ageDays
|
|
14497
|
+
};
|
|
14498
|
+
if (currentTier === "draft") {
|
|
14499
|
+
const rules = PROMOTION_RULES.draftToEpisode;
|
|
14500
|
+
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
14501
|
+
return {
|
|
14502
|
+
...base,
|
|
14503
|
+
eligible: true,
|
|
14504
|
+
targetTier: "episode",
|
|
14505
|
+
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
14506
|
+
};
|
|
14507
|
+
}
|
|
14508
|
+
}
|
|
14509
|
+
if (currentTier === "episode") {
|
|
14510
|
+
const rules = PROMOTION_RULES.episodeToReference;
|
|
14511
|
+
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
14512
|
+
return {
|
|
14513
|
+
...base,
|
|
14514
|
+
eligible: true,
|
|
14515
|
+
targetTier: "reference",
|
|
14516
|
+
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
14517
|
+
};
|
|
14518
|
+
}
|
|
14519
|
+
}
|
|
14520
|
+
return base;
|
|
14521
|
+
}
|
|
14522
|
+
function evaluateLifecycle(entity) {
|
|
14523
|
+
const decay = computeDecayScore(entity.memory_tier, entity.last_accessed_at, entity.access_count);
|
|
14524
|
+
const promotion = checkPromotion(entity.memory_tier, entity.access_count, entity.confidence, entity.created_at);
|
|
14525
|
+
const shouldArchive = entity.confidence < ARCHIVE_THRESHOLD;
|
|
14526
|
+
const archiveReason = shouldArchive ? `Confidence ${entity.confidence} below threshold ${ARCHIVE_THRESHOLD}` : undefined;
|
|
14527
|
+
const shouldFlagForReview = decay.daysSinceAccess >= STALE_DAYS && entity.access_count < STALE_MIN_ACCESS;
|
|
14528
|
+
const reviewReason = shouldFlagForReview ? `Not accessed in ${Math.round(decay.daysSinceAccess)} days with only ${entity.access_count} accesses` : undefined;
|
|
14529
|
+
return {
|
|
14530
|
+
decay,
|
|
14531
|
+
promotion,
|
|
14532
|
+
shouldArchive,
|
|
14533
|
+
shouldFlagForReview,
|
|
14534
|
+
archiveReason,
|
|
14535
|
+
reviewReason
|
|
14536
|
+
};
|
|
14537
|
+
}
|
|
14538
|
+
function buildContradictionQuery(type, tags) {
|
|
14539
|
+
if (tags.length === 0)
|
|
14540
|
+
return null;
|
|
14541
|
+
return { type, tags };
|
|
14542
|
+
}
|
|
14543
|
+
// ../memory/src/sync.ts
|
|
14544
|
+
import { createHash } from "node:crypto";
|
|
14545
|
+
import {
|
|
14546
|
+
existsSync as existsSync2,
|
|
14547
|
+
mkdirSync as mkdirSync2,
|
|
14548
|
+
readdirSync,
|
|
14549
|
+
readFileSync as readFileSync2,
|
|
14550
|
+
rmSync,
|
|
14551
|
+
writeFileSync as writeFileSync2
|
|
14552
|
+
} from "node:fs";
|
|
14553
|
+
import { join as join2, relative, sep } from "node:path";
|
|
14554
|
+
|
|
14374
14555
|
// ../memory/src/sync-storage.ts
|
|
14375
14556
|
function parseSyncMarkdown(markdown) {
|
|
14376
14557
|
const trimmed = markdown.trim();
|
|
@@ -14486,17 +14667,8 @@ function parseYamlArray(value) {
|
|
|
14486
14667
|
return [];
|
|
14487
14668
|
return match[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
14488
14669
|
}
|
|
14670
|
+
|
|
14489
14671
|
// ../memory/src/sync.ts
|
|
14490
|
-
import { createHash } from "node:crypto";
|
|
14491
|
-
import {
|
|
14492
|
-
existsSync as existsSync2,
|
|
14493
|
-
mkdirSync as mkdirSync2,
|
|
14494
|
-
readdirSync,
|
|
14495
|
-
readFileSync as readFileSync2,
|
|
14496
|
-
rmSync,
|
|
14497
|
-
writeFileSync as writeFileSync2
|
|
14498
|
-
} from "node:fs";
|
|
14499
|
-
import { join as join2, relative, sep } from "node:path";
|
|
14500
14672
|
function computeFileHash(content) {
|
|
14501
14673
|
return `sha256:${createHash("sha256").update(content).digest("hex")}`;
|
|
14502
14674
|
}
|
|
@@ -14758,177 +14930,6 @@ async function syncFull(client, config, workspaceId, projectId) {
|
|
|
14758
14930
|
errors: [...pullResult.errors, ...pushResult.errors]
|
|
14759
14931
|
};
|
|
14760
14932
|
}
|
|
14761
|
-
// ../memory/src/lifecycle.ts
|
|
14762
|
-
var DECAY_HALF_LIVES = {
|
|
14763
|
-
draft: 7,
|
|
14764
|
-
episode: 30,
|
|
14765
|
-
reference: 180
|
|
14766
|
-
};
|
|
14767
|
-
var PROMOTION_RULES = {
|
|
14768
|
-
draftToEpisode: {
|
|
14769
|
-
minAccessCount: 5,
|
|
14770
|
-
minConfidence: 0.8,
|
|
14771
|
-
minAgeDays: 1
|
|
14772
|
-
},
|
|
14773
|
-
episodeToReference: {
|
|
14774
|
-
minAccessCount: 10,
|
|
14775
|
-
minConfidence: 0.9,
|
|
14776
|
-
minAgeDays: 7
|
|
14777
|
-
}
|
|
14778
|
-
};
|
|
14779
|
-
var ARCHIVE_THRESHOLD = 0.3;
|
|
14780
|
-
var STALE_DAYS = 90;
|
|
14781
|
-
var STALE_MIN_ACCESS = 3;
|
|
14782
|
-
function computeDecayScore(tier, lastAccessedAt, accessCount) {
|
|
14783
|
-
const halfLife = DECAY_HALF_LIVES[tier];
|
|
14784
|
-
const now = Date.now();
|
|
14785
|
-
let daysSinceAccess = 0;
|
|
14786
|
-
if (lastAccessedAt) {
|
|
14787
|
-
daysSinceAccess = (now - new Date(lastAccessedAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
14788
|
-
}
|
|
14789
|
-
const timeDecay = Math.pow(0.5, daysSinceAccess / halfLife);
|
|
14790
|
-
const accessBonus = Math.log10(accessCount + 1) * 0.1;
|
|
14791
|
-
const score = Math.min(timeDecay + accessBonus, 1);
|
|
14792
|
-
return { score, daysSinceAccess, halfLife, accessBonus };
|
|
14793
|
-
}
|
|
14794
|
-
function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
14795
|
-
const ageDays = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
14796
|
-
const base = {
|
|
14797
|
-
eligible: false,
|
|
14798
|
-
targetTier: null,
|
|
14799
|
-
reason: null,
|
|
14800
|
-
currentTier,
|
|
14801
|
-
accessCount,
|
|
14802
|
-
confidence,
|
|
14803
|
-
ageDays
|
|
14804
|
-
};
|
|
14805
|
-
if (currentTier === "draft") {
|
|
14806
|
-
const rules = PROMOTION_RULES.draftToEpisode;
|
|
14807
|
-
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
14808
|
-
return {
|
|
14809
|
-
...base,
|
|
14810
|
-
eligible: true,
|
|
14811
|
-
targetTier: "episode",
|
|
14812
|
-
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
14813
|
-
};
|
|
14814
|
-
}
|
|
14815
|
-
}
|
|
14816
|
-
if (currentTier === "episode") {
|
|
14817
|
-
const rules = PROMOTION_RULES.episodeToReference;
|
|
14818
|
-
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
14819
|
-
return {
|
|
14820
|
-
...base,
|
|
14821
|
-
eligible: true,
|
|
14822
|
-
targetTier: "reference",
|
|
14823
|
-
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
14824
|
-
};
|
|
14825
|
-
}
|
|
14826
|
-
}
|
|
14827
|
-
return base;
|
|
14828
|
-
}
|
|
14829
|
-
function evaluateLifecycle(entity) {
|
|
14830
|
-
const decay = computeDecayScore(entity.memory_tier, entity.last_accessed_at, entity.access_count);
|
|
14831
|
-
const promotion = checkPromotion(entity.memory_tier, entity.access_count, entity.confidence, entity.created_at);
|
|
14832
|
-
const shouldArchive = entity.confidence < ARCHIVE_THRESHOLD;
|
|
14833
|
-
const archiveReason = shouldArchive ? `Confidence ${entity.confidence} below threshold ${ARCHIVE_THRESHOLD}` : undefined;
|
|
14834
|
-
const shouldFlagForReview = decay.daysSinceAccess >= STALE_DAYS && entity.access_count < STALE_MIN_ACCESS;
|
|
14835
|
-
const reviewReason = shouldFlagForReview ? `Not accessed in ${Math.round(decay.daysSinceAccess)} days with only ${entity.access_count} accesses` : undefined;
|
|
14836
|
-
return {
|
|
14837
|
-
decay,
|
|
14838
|
-
promotion,
|
|
14839
|
-
shouldArchive,
|
|
14840
|
-
shouldFlagForReview,
|
|
14841
|
-
archiveReason,
|
|
14842
|
-
reviewReason
|
|
14843
|
-
};
|
|
14844
|
-
}
|
|
14845
|
-
function buildContradictionQuery(type, tags) {
|
|
14846
|
-
if (tags.length === 0)
|
|
14847
|
-
return null;
|
|
14848
|
-
return { type, tags };
|
|
14849
|
-
}
|
|
14850
|
-
// ../memory/src/graph-walk.ts
|
|
14851
|
-
async function discoverRelatedContext(client, startIds, maxDepth = 2, maxEntities = 20, minConfidence = 0.5) {
|
|
14852
|
-
const visited = new Set;
|
|
14853
|
-
const collectedEntities = [];
|
|
14854
|
-
const collectedRelations = [];
|
|
14855
|
-
let truncated = false;
|
|
14856
|
-
const queue = startIds.map((id) => [id, 0]);
|
|
14857
|
-
for (const id of startIds) {
|
|
14858
|
-
visited.add(id);
|
|
14859
|
-
}
|
|
14860
|
-
while (queue.length > 0) {
|
|
14861
|
-
const [entityId, depth] = queue.shift();
|
|
14862
|
-
if (collectedEntities.length >= maxEntities) {
|
|
14863
|
-
truncated = true;
|
|
14864
|
-
break;
|
|
14865
|
-
}
|
|
14866
|
-
if (depth > maxDepth)
|
|
14867
|
-
continue;
|
|
14868
|
-
try {
|
|
14869
|
-
const entityResult = await client.getMemoryEntity(entityId);
|
|
14870
|
-
const entity = entityResult.entity;
|
|
14871
|
-
if (entity) {
|
|
14872
|
-
collectedEntities.push({
|
|
14873
|
-
id: entity.id,
|
|
14874
|
-
type: entity.type,
|
|
14875
|
-
title: entity.title,
|
|
14876
|
-
confidence: entity.confidence ?? 1,
|
|
14877
|
-
memory_tier: entity.memory_tier || "reference"
|
|
14878
|
-
});
|
|
14879
|
-
}
|
|
14880
|
-
if (depth >= maxDepth)
|
|
14881
|
-
continue;
|
|
14882
|
-
const related = await client.getRelatedEntities(entityId);
|
|
14883
|
-
for (const raw of related.outgoing || []) {
|
|
14884
|
-
const rel = raw;
|
|
14885
|
-
const relConfidence = rel.confidence ?? 1;
|
|
14886
|
-
if (relConfidence < minConfidence)
|
|
14887
|
-
continue;
|
|
14888
|
-
const target = rel.target;
|
|
14889
|
-
const targetId = target?.id ?? rel.target_id;
|
|
14890
|
-
if (targetId && !visited.has(targetId)) {
|
|
14891
|
-
visited.add(targetId);
|
|
14892
|
-
queue.push([targetId, depth + 1]);
|
|
14893
|
-
collectedRelations.push({
|
|
14894
|
-
id: rel.id,
|
|
14895
|
-
source_id: entityId,
|
|
14896
|
-
target_id: targetId,
|
|
14897
|
-
relation_type: rel.relation_type,
|
|
14898
|
-
confidence: relConfidence
|
|
14899
|
-
});
|
|
14900
|
-
}
|
|
14901
|
-
}
|
|
14902
|
-
for (const raw of related.incoming || []) {
|
|
14903
|
-
const rel = raw;
|
|
14904
|
-
const relConfidence = rel.confidence ?? 1;
|
|
14905
|
-
if (relConfidence < minConfidence)
|
|
14906
|
-
continue;
|
|
14907
|
-
const source = rel.source;
|
|
14908
|
-
const sourceId = source?.id ?? rel.source_id;
|
|
14909
|
-
if (sourceId && !visited.has(sourceId)) {
|
|
14910
|
-
visited.add(sourceId);
|
|
14911
|
-
queue.push([sourceId, depth + 1]);
|
|
14912
|
-
collectedRelations.push({
|
|
14913
|
-
id: rel.id,
|
|
14914
|
-
source_id: sourceId,
|
|
14915
|
-
target_id: entityId,
|
|
14916
|
-
relation_type: rel.relation_type,
|
|
14917
|
-
confidence: relConfidence
|
|
14918
|
-
});
|
|
14919
|
-
}
|
|
14920
|
-
}
|
|
14921
|
-
} catch {
|
|
14922
|
-
continue;
|
|
14923
|
-
}
|
|
14924
|
-
}
|
|
14925
|
-
return {
|
|
14926
|
-
entities: collectedEntities,
|
|
14927
|
-
relations: collectedRelations,
|
|
14928
|
-
depth: maxDepth,
|
|
14929
|
-
truncated
|
|
14930
|
-
};
|
|
14931
|
-
}
|
|
14932
14933
|
// ../../node_modules/zod/v4/core/index.js
|
|
14933
14934
|
var exports_core2 = {};
|
|
14934
14935
|
__export(exports_core2, {
|
|
@@ -30731,7 +30732,7 @@ class StdioServerTransport {
|
|
|
30731
30732
|
}
|
|
30732
30733
|
}
|
|
30733
30734
|
// src/graph-expansion.ts
|
|
30734
|
-
async function autoExpandGraph(client2, entityId, title, content,
|
|
30735
|
+
async function autoExpandGraph(client2, entityId, title, content, _tags, workspaceId, projectId, maxRelations = 5) {
|
|
30735
30736
|
try {
|
|
30736
30737
|
const contentSnippet = content.slice(0, 200).trim();
|
|
30737
30738
|
const query = [title, contentSnippet].filter(Boolean).join(" ");
|
|
@@ -30809,7 +30810,11 @@ Agent: ${session.agentName}`
|
|
|
30809
30810
|
type: "lesson",
|
|
30810
30811
|
tier: "episode",
|
|
30811
30812
|
confidence: 0.7,
|
|
30812
|
-
tags: [
|
|
30813
|
+
tags: [
|
|
30814
|
+
"auto-extracted",
|
|
30815
|
+
"session-summary",
|
|
30816
|
+
...session.cardLabels.slice(0, 3)
|
|
30817
|
+
],
|
|
30813
30818
|
metadata: {
|
|
30814
30819
|
source: "active_learning",
|
|
30815
30820
|
card_id: session.cardId,
|
|
@@ -31003,7 +31008,7 @@ function isRetryableError(error48, status) {
|
|
|
31003
31008
|
return msg.includes("ECONNRESET") || msg.includes("ETIMEDOUT") || msg.includes("fetch failed");
|
|
31004
31009
|
}
|
|
31005
31010
|
function getRetryDelay(attempt) {
|
|
31006
|
-
const delay = Math.min(RETRY_CONFIG.baseDelayMs *
|
|
31011
|
+
const delay = Math.min(RETRY_CONFIG.baseDelayMs * 2 ** attempt, RETRY_CONFIG.maxDelayMs);
|
|
31007
31012
|
return Math.round(delay + delay * 0.25 * (Math.random() * 2 - 1));
|
|
31008
31013
|
}
|
|
31009
31014
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -31122,7 +31127,6 @@ class HarmonyApiClient {
|
|
|
31122
31127
|
throw lastError;
|
|
31123
31128
|
if (attempt < RETRY_CONFIG.maxRetries) {
|
|
31124
31129
|
await sleep(getRetryDelay(attempt));
|
|
31125
|
-
continue;
|
|
31126
31130
|
}
|
|
31127
31131
|
}
|
|
31128
31132
|
}
|
|
@@ -31169,7 +31173,6 @@ class HarmonyApiClient {
|
|
|
31169
31173
|
throw lastError;
|
|
31170
31174
|
if (attempt < RETRY_CONFIG.maxRetries) {
|
|
31171
31175
|
await sleep(getRetryDelay(attempt));
|
|
31172
|
-
continue;
|
|
31173
31176
|
}
|
|
31174
31177
|
}
|
|
31175
31178
|
}
|
|
@@ -31194,6 +31197,8 @@ class HarmonyApiClient {
|
|
|
31194
31197
|
params.set("column_id", options.columnId);
|
|
31195
31198
|
if (options?.summary)
|
|
31196
31199
|
params.set("summary", "true");
|
|
31200
|
+
if (options?.includeArchived)
|
|
31201
|
+
params.set("include_archived", "true");
|
|
31197
31202
|
const query = params.toString() ? `?${params.toString()}` : "";
|
|
31198
31203
|
return this.request("GET", `/board/${projectId}${query}`);
|
|
31199
31204
|
}
|
|
@@ -31209,6 +31214,12 @@ class HarmonyApiClient {
|
|
|
31209
31214
|
position
|
|
31210
31215
|
});
|
|
31211
31216
|
}
|
|
31217
|
+
async archiveCard(cardId) {
|
|
31218
|
+
return this.updateCard(cardId, { archivedAt: new Date().toISOString() });
|
|
31219
|
+
}
|
|
31220
|
+
async unarchiveCard(cardId) {
|
|
31221
|
+
return this.updateCard(cardId, { archivedAt: null });
|
|
31222
|
+
}
|
|
31212
31223
|
async deleteCard(cardId) {
|
|
31213
31224
|
return this.request("DELETE", `/cards/${cardId}`);
|
|
31214
31225
|
}
|
|
@@ -31567,7 +31578,7 @@ function computeRelevanceScore(entity, taskContext, cardLabels) {
|
|
|
31567
31578
|
if (entity.last_accessed_at) {
|
|
31568
31579
|
const daysSinceAccess = (Date.now() - new Date(entity.last_accessed_at).getTime()) / (1000 * 60 * 60 * 24);
|
|
31569
31580
|
const halfLife = { draft: 7, episode: 30, reference: 180 }[entity.memory_tier];
|
|
31570
|
-
const recencyScore =
|
|
31581
|
+
const recencyScore = 0.5 ** (daysSinceAccess / halfLife) * 0.1;
|
|
31571
31582
|
score += recencyScore;
|
|
31572
31583
|
if (daysSinceAccess < 7)
|
|
31573
31584
|
reasons.push("recently_accessed");
|
|
@@ -31644,7 +31655,11 @@ async function assembleContext(options) {
|
|
|
31644
31655
|
episode: Math.floor(tokenBudget * TIER_BUDGET_ALLOCATION.episode),
|
|
31645
31656
|
draft: Math.floor(tokenBudget * TIER_BUDGET_ALLOCATION.draft)
|
|
31646
31657
|
};
|
|
31647
|
-
const tierUsed = {
|
|
31658
|
+
const tierUsed = {
|
|
31659
|
+
reference: 0,
|
|
31660
|
+
episode: 0,
|
|
31661
|
+
draft: 0
|
|
31662
|
+
};
|
|
31648
31663
|
const included = [];
|
|
31649
31664
|
let totalUsed = 0;
|
|
31650
31665
|
let referenceCount = 0;
|
|
@@ -31714,9 +31729,18 @@ ${text}`);
|
|
|
31714
31729
|
}
|
|
31715
31730
|
manifest.budgetUsed = totalUsed;
|
|
31716
31731
|
manifest.tierBreakdown = {
|
|
31717
|
-
reference: {
|
|
31718
|
-
|
|
31719
|
-
|
|
31732
|
+
reference: {
|
|
31733
|
+
count: included.filter((i) => i.entity.memory_tier === "reference").length,
|
|
31734
|
+
tokens: tierUsed.reference
|
|
31735
|
+
},
|
|
31736
|
+
episode: {
|
|
31737
|
+
count: included.filter((i) => i.entity.memory_tier === "episode").length,
|
|
31738
|
+
tokens: tierUsed.episode
|
|
31739
|
+
},
|
|
31740
|
+
draft: {
|
|
31741
|
+
count: included.filter((i) => i.entity.memory_tier === "draft").length,
|
|
31742
|
+
tokens: tierUsed.draft
|
|
31743
|
+
}
|
|
31720
31744
|
};
|
|
31721
31745
|
for (const item of included) {
|
|
31722
31746
|
manifest.included.push({
|
|
@@ -32008,7 +32032,15 @@ ${lines.join(`
|
|
|
32008
32032
|
`)}`;
|
|
32009
32033
|
}
|
|
32010
32034
|
function generatePrompt(options) {
|
|
32011
|
-
const {
|
|
32035
|
+
const {
|
|
32036
|
+
card,
|
|
32037
|
+
column,
|
|
32038
|
+
variant,
|
|
32039
|
+
customConstraints,
|
|
32040
|
+
memories,
|
|
32041
|
+
assembledContext,
|
|
32042
|
+
assemblyId
|
|
32043
|
+
} = options;
|
|
32012
32044
|
const contextOpts = {
|
|
32013
32045
|
includeTitle: true,
|
|
32014
32046
|
includeDescription: true,
|
|
@@ -32162,7 +32194,8 @@ var TOOLS = {
|
|
|
32162
32194
|
description: { type: "string" },
|
|
32163
32195
|
priority: { type: "string", enum: ["low", "medium", "high", "urgent"] },
|
|
32164
32196
|
assigneeId: { type: "string", nullable: true },
|
|
32165
|
-
dueDate: { type: "string", nullable: true }
|
|
32197
|
+
dueDate: { type: "string", nullable: true },
|
|
32198
|
+
done: { type: "boolean", description: "Mark card as done or not done" }
|
|
32166
32199
|
},
|
|
32167
32200
|
required: ["cardId"]
|
|
32168
32201
|
}
|
|
@@ -32182,6 +32215,26 @@ var TOOLS = {
|
|
|
32182
32215
|
required: ["cardId", "columnId"]
|
|
32183
32216
|
}
|
|
32184
32217
|
},
|
|
32218
|
+
harmony_archive_card: {
|
|
32219
|
+
description: "Archive a card (soft-delete). Card can be restored later with unarchive.",
|
|
32220
|
+
inputSchema: {
|
|
32221
|
+
type: "object",
|
|
32222
|
+
properties: {
|
|
32223
|
+
cardId: { type: "string", description: "Card ID to archive" }
|
|
32224
|
+
},
|
|
32225
|
+
required: ["cardId"]
|
|
32226
|
+
}
|
|
32227
|
+
},
|
|
32228
|
+
harmony_unarchive_card: {
|
|
32229
|
+
description: "Restore an archived card back to the board.",
|
|
32230
|
+
inputSchema: {
|
|
32231
|
+
type: "object",
|
|
32232
|
+
properties: {
|
|
32233
|
+
cardId: { type: "string", description: "Card ID to unarchive" }
|
|
32234
|
+
},
|
|
32235
|
+
required: ["cardId"]
|
|
32236
|
+
}
|
|
32237
|
+
},
|
|
32185
32238
|
harmony_delete_card: {
|
|
32186
32239
|
description: "Delete a card",
|
|
32187
32240
|
inputSchema: {
|
|
@@ -32424,6 +32477,10 @@ var TOOLS = {
|
|
|
32424
32477
|
summary: {
|
|
32425
32478
|
type: "boolean",
|
|
32426
32479
|
description: "Return only columns with card counts, no card details"
|
|
32480
|
+
},
|
|
32481
|
+
includeArchived: {
|
|
32482
|
+
type: "boolean",
|
|
32483
|
+
description: "Include archived cards in results (default: false). Archived cards are excluded by default."
|
|
32427
32484
|
}
|
|
32428
32485
|
}
|
|
32429
32486
|
}
|
|
@@ -33482,7 +33539,8 @@ async function handleToolCall(name, args, deps) {
|
|
|
33482
33539
|
description: args.description,
|
|
33483
33540
|
priority: args.priority,
|
|
33484
33541
|
assigneeId: args.assigneeId,
|
|
33485
|
-
dueDate: args.dueDate
|
|
33542
|
+
dueDate: args.dueDate,
|
|
33543
|
+
done: args.done
|
|
33486
33544
|
});
|
|
33487
33545
|
return { success: true, ...result };
|
|
33488
33546
|
}
|
|
@@ -33512,6 +33570,16 @@ async function handleToolCall(name, args, deps) {
|
|
|
33512
33570
|
} catch {}
|
|
33513
33571
|
return { success: true, sessionEnded, ...result };
|
|
33514
33572
|
}
|
|
33573
|
+
case "harmony_archive_card": {
|
|
33574
|
+
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
33575
|
+
const result = await client3.archiveCard(cardId);
|
|
33576
|
+
return { success: true, ...result };
|
|
33577
|
+
}
|
|
33578
|
+
case "harmony_unarchive_card": {
|
|
33579
|
+
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
33580
|
+
const result = await client3.unarchiveCard(cardId);
|
|
33581
|
+
return { success: true, ...result };
|
|
33582
|
+
}
|
|
33515
33583
|
case "harmony_delete_card": {
|
|
33516
33584
|
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
33517
33585
|
await client3.deleteCard(cardId);
|
|
@@ -33635,6 +33703,8 @@ async function handleToolCall(name, args, deps) {
|
|
|
33635
33703
|
options.columnId = String(args.columnId);
|
|
33636
33704
|
if (args.summary === true || args.summary === "true")
|
|
33637
33705
|
options.summary = true;
|
|
33706
|
+
if (args.includeArchived === true || args.includeArchived === "true")
|
|
33707
|
+
options.includeArchived = true;
|
|
33638
33708
|
const result = await client3.getBoard(projectId, options);
|
|
33639
33709
|
return { success: true, board: result };
|
|
33640
33710
|
}
|
|
@@ -34299,7 +34369,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
34299
34369
|
const card = cardResult.card;
|
|
34300
34370
|
await client3.updatePlanTask(planId, task.id, { cardId: card.id });
|
|
34301
34371
|
cardsCreated++;
|
|
34302
|
-
} catch (
|
|
34372
|
+
} catch (_e) {}
|
|
34303
34373
|
}
|
|
34304
34374
|
results.cardsCreated = cardsCreated;
|
|
34305
34375
|
}
|
|
@@ -34783,7 +34853,7 @@ import {
|
|
|
34783
34853
|
unlinkSync
|
|
34784
34854
|
} from "node:fs";
|
|
34785
34855
|
import { homedir as homedir4 } from "node:os";
|
|
34786
|
-
import { dirname as
|
|
34856
|
+
import { dirname as dirname2, join as join4 } from "node:path";
|
|
34787
34857
|
|
|
34788
34858
|
// ../../node_modules/@clack/core/dist/index.mjs
|
|
34789
34859
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
@@ -35617,7 +35687,7 @@ function formatPath(path, homeDir) {
|
|
|
35617
35687
|
// src/tui/writer.ts
|
|
35618
35688
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
35619
35689
|
import { homedir as homedir3 } from "node:os";
|
|
35620
|
-
import { dirname
|
|
35690
|
+
import { dirname } from "node:path";
|
|
35621
35691
|
function ensureDir(dirPath) {
|
|
35622
35692
|
if (!existsSync4(dirPath)) {
|
|
35623
35693
|
mkdirSync3(dirPath, { recursive: true, mode: 493 });
|
|
@@ -35629,7 +35699,7 @@ function writeFile(filePath, content, options = {}) {
|
|
|
35629
35699
|
return { path: filePath, action: "skip" };
|
|
35630
35700
|
}
|
|
35631
35701
|
try {
|
|
35632
|
-
ensureDir(
|
|
35702
|
+
ensureDir(dirname(filePath));
|
|
35633
35703
|
const mode = filePath.includes(".harmony-mcp") ? 384 : 420;
|
|
35634
35704
|
writeFileSync3(filePath, content, { mode });
|
|
35635
35705
|
return { path: filePath, action: exists ? "update" : "create" };
|
|
@@ -35645,7 +35715,7 @@ function mergeJsonFile(filePath, updates, options = {}) {
|
|
|
35645
35715
|
const exists = existsSync4(filePath);
|
|
35646
35716
|
if (!exists) {
|
|
35647
35717
|
try {
|
|
35648
|
-
ensureDir(
|
|
35718
|
+
ensureDir(dirname(filePath));
|
|
35649
35719
|
writeFileSync3(filePath, JSON.stringify(updates, null, 2), {
|
|
35650
35720
|
mode: 420
|
|
35651
35721
|
});
|
|
@@ -35695,7 +35765,7 @@ function appendToToml(filePath, section, content, options = {}) {
|
|
|
35695
35765
|
const exists = existsSync4(filePath);
|
|
35696
35766
|
if (!exists) {
|
|
35697
35767
|
try {
|
|
35698
|
-
ensureDir(
|
|
35768
|
+
ensureDir(dirname(filePath));
|
|
35699
35769
|
writeFileSync3(filePath, content, { mode: 420 });
|
|
35700
35770
|
return { path: filePath, action: "create" };
|
|
35701
35771
|
} catch (error48) {
|
|
@@ -36010,7 +36080,7 @@ async function registerMcpServer() {
|
|
|
36010
36080
|
async function writeMcpConfigFallback(home) {
|
|
36011
36081
|
const { readFileSync: readFileSync4, writeFileSync: writeFileSync4, mkdirSync: mkdirSync5, existsSync: existsSync6 } = await import("node:fs");
|
|
36012
36082
|
const settingsPath = join4(home, ".claude", "settings.json");
|
|
36013
|
-
const settingsDir =
|
|
36083
|
+
const settingsDir = dirname2(settingsPath);
|
|
36014
36084
|
if (!existsSync6(settingsDir)) {
|
|
36015
36085
|
mkdirSync5(settingsDir, { recursive: true });
|
|
36016
36086
|
}
|
|
@@ -36578,7 +36648,7 @@ async function runSetup(options = {}) {
|
|
|
36578
36648
|
if (allSymlinks.length > 0) {
|
|
36579
36649
|
for (const symlink of allSymlinks) {
|
|
36580
36650
|
try {
|
|
36581
|
-
const linkDir =
|
|
36651
|
+
const linkDir = dirname2(symlink.link);
|
|
36582
36652
|
if (!existsSync5(linkDir)) {
|
|
36583
36653
|
mkdirSync4(linkDir, { recursive: true });
|
|
36584
36654
|
}
|
package/dist/index.js
CHANGED
|
@@ -11946,6 +11946,187 @@ var require_dist = __commonJS((exports, module) => {
|
|
|
11946
11946
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11947
11947
|
exports.default = formatsPlugin;
|
|
11948
11948
|
});
|
|
11949
|
+
// ../memory/src/graph-walk.ts
|
|
11950
|
+
async function discoverRelatedContext(client, startIds, maxDepth = 2, maxEntities = 20, minConfidence = 0.5) {
|
|
11951
|
+
const visited = new Set;
|
|
11952
|
+
const collectedEntities = [];
|
|
11953
|
+
const collectedRelations = [];
|
|
11954
|
+
let truncated = false;
|
|
11955
|
+
const queue = startIds.map((id) => [id, 0]);
|
|
11956
|
+
for (const id of startIds) {
|
|
11957
|
+
visited.add(id);
|
|
11958
|
+
}
|
|
11959
|
+
while (queue.length > 0) {
|
|
11960
|
+
const [entityId, depth] = queue.shift();
|
|
11961
|
+
if (collectedEntities.length >= maxEntities) {
|
|
11962
|
+
truncated = true;
|
|
11963
|
+
break;
|
|
11964
|
+
}
|
|
11965
|
+
if (depth > maxDepth)
|
|
11966
|
+
continue;
|
|
11967
|
+
try {
|
|
11968
|
+
const entityResult = await client.getMemoryEntity(entityId);
|
|
11969
|
+
const entity = entityResult.entity;
|
|
11970
|
+
if (entity) {
|
|
11971
|
+
collectedEntities.push({
|
|
11972
|
+
id: entity.id,
|
|
11973
|
+
type: entity.type,
|
|
11974
|
+
title: entity.title,
|
|
11975
|
+
confidence: entity.confidence ?? 1,
|
|
11976
|
+
memory_tier: entity.memory_tier || "reference"
|
|
11977
|
+
});
|
|
11978
|
+
}
|
|
11979
|
+
if (depth >= maxDepth)
|
|
11980
|
+
continue;
|
|
11981
|
+
const related = await client.getRelatedEntities(entityId);
|
|
11982
|
+
for (const raw of related.outgoing || []) {
|
|
11983
|
+
const rel = raw;
|
|
11984
|
+
const relConfidence = rel.confidence ?? 1;
|
|
11985
|
+
if (relConfidence < minConfidence)
|
|
11986
|
+
continue;
|
|
11987
|
+
const target = rel.target;
|
|
11988
|
+
const targetId = target?.id ?? rel.target_id;
|
|
11989
|
+
if (targetId && !visited.has(targetId)) {
|
|
11990
|
+
visited.add(targetId);
|
|
11991
|
+
queue.push([targetId, depth + 1]);
|
|
11992
|
+
collectedRelations.push({
|
|
11993
|
+
id: rel.id,
|
|
11994
|
+
source_id: entityId,
|
|
11995
|
+
target_id: targetId,
|
|
11996
|
+
relation_type: rel.relation_type,
|
|
11997
|
+
confidence: relConfidence
|
|
11998
|
+
});
|
|
11999
|
+
}
|
|
12000
|
+
}
|
|
12001
|
+
for (const raw of related.incoming || []) {
|
|
12002
|
+
const rel = raw;
|
|
12003
|
+
const relConfidence = rel.confidence ?? 1;
|
|
12004
|
+
if (relConfidence < minConfidence)
|
|
12005
|
+
continue;
|
|
12006
|
+
const source = rel.source;
|
|
12007
|
+
const sourceId = source?.id ?? rel.source_id;
|
|
12008
|
+
if (sourceId && !visited.has(sourceId)) {
|
|
12009
|
+
visited.add(sourceId);
|
|
12010
|
+
queue.push([sourceId, depth + 1]);
|
|
12011
|
+
collectedRelations.push({
|
|
12012
|
+
id: rel.id,
|
|
12013
|
+
source_id: sourceId,
|
|
12014
|
+
target_id: entityId,
|
|
12015
|
+
relation_type: rel.relation_type,
|
|
12016
|
+
confidence: relConfidence
|
|
12017
|
+
});
|
|
12018
|
+
}
|
|
12019
|
+
}
|
|
12020
|
+
} catch {}
|
|
12021
|
+
}
|
|
12022
|
+
return {
|
|
12023
|
+
entities: collectedEntities,
|
|
12024
|
+
relations: collectedRelations,
|
|
12025
|
+
depth: maxDepth,
|
|
12026
|
+
truncated
|
|
12027
|
+
};
|
|
12028
|
+
}
|
|
12029
|
+
// ../memory/src/lifecycle.ts
|
|
12030
|
+
var DECAY_HALF_LIVES = {
|
|
12031
|
+
draft: 7,
|
|
12032
|
+
episode: 30,
|
|
12033
|
+
reference: 180
|
|
12034
|
+
};
|
|
12035
|
+
var PROMOTION_RULES = {
|
|
12036
|
+
draftToEpisode: {
|
|
12037
|
+
minAccessCount: 5,
|
|
12038
|
+
minConfidence: 0.8,
|
|
12039
|
+
minAgeDays: 1
|
|
12040
|
+
},
|
|
12041
|
+
episodeToReference: {
|
|
12042
|
+
minAccessCount: 10,
|
|
12043
|
+
minConfidence: 0.9,
|
|
12044
|
+
minAgeDays: 7
|
|
12045
|
+
}
|
|
12046
|
+
};
|
|
12047
|
+
var ARCHIVE_THRESHOLD = 0.3;
|
|
12048
|
+
var STALE_DAYS = 90;
|
|
12049
|
+
var STALE_MIN_ACCESS = 3;
|
|
12050
|
+
function computeDecayScore(tier, lastAccessedAt, accessCount) {
|
|
12051
|
+
const halfLife = DECAY_HALF_LIVES[tier];
|
|
12052
|
+
const now = Date.now();
|
|
12053
|
+
let daysSinceAccess = 0;
|
|
12054
|
+
if (lastAccessedAt) {
|
|
12055
|
+
daysSinceAccess = (now - new Date(lastAccessedAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
12056
|
+
}
|
|
12057
|
+
const timeDecay = 0.5 ** (daysSinceAccess / halfLife);
|
|
12058
|
+
const accessBonus = Math.log10(accessCount + 1) * 0.1;
|
|
12059
|
+
const score = Math.min(timeDecay + accessBonus, 1);
|
|
12060
|
+
return { score, daysSinceAccess, halfLife, accessBonus };
|
|
12061
|
+
}
|
|
12062
|
+
function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
12063
|
+
const ageDays = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
12064
|
+
const base = {
|
|
12065
|
+
eligible: false,
|
|
12066
|
+
targetTier: null,
|
|
12067
|
+
reason: null,
|
|
12068
|
+
currentTier,
|
|
12069
|
+
accessCount,
|
|
12070
|
+
confidence,
|
|
12071
|
+
ageDays
|
|
12072
|
+
};
|
|
12073
|
+
if (currentTier === "draft") {
|
|
12074
|
+
const rules = PROMOTION_RULES.draftToEpisode;
|
|
12075
|
+
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
12076
|
+
return {
|
|
12077
|
+
...base,
|
|
12078
|
+
eligible: true,
|
|
12079
|
+
targetTier: "episode",
|
|
12080
|
+
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
12081
|
+
};
|
|
12082
|
+
}
|
|
12083
|
+
}
|
|
12084
|
+
if (currentTier === "episode") {
|
|
12085
|
+
const rules = PROMOTION_RULES.episodeToReference;
|
|
12086
|
+
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
12087
|
+
return {
|
|
12088
|
+
...base,
|
|
12089
|
+
eligible: true,
|
|
12090
|
+
targetTier: "reference",
|
|
12091
|
+
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
12092
|
+
};
|
|
12093
|
+
}
|
|
12094
|
+
}
|
|
12095
|
+
return base;
|
|
12096
|
+
}
|
|
12097
|
+
function evaluateLifecycle(entity) {
|
|
12098
|
+
const decay = computeDecayScore(entity.memory_tier, entity.last_accessed_at, entity.access_count);
|
|
12099
|
+
const promotion = checkPromotion(entity.memory_tier, entity.access_count, entity.confidence, entity.created_at);
|
|
12100
|
+
const shouldArchive = entity.confidence < ARCHIVE_THRESHOLD;
|
|
12101
|
+
const archiveReason = shouldArchive ? `Confidence ${entity.confidence} below threshold ${ARCHIVE_THRESHOLD}` : undefined;
|
|
12102
|
+
const shouldFlagForReview = decay.daysSinceAccess >= STALE_DAYS && entity.access_count < STALE_MIN_ACCESS;
|
|
12103
|
+
const reviewReason = shouldFlagForReview ? `Not accessed in ${Math.round(decay.daysSinceAccess)} days with only ${entity.access_count} accesses` : undefined;
|
|
12104
|
+
return {
|
|
12105
|
+
decay,
|
|
12106
|
+
promotion,
|
|
12107
|
+
shouldArchive,
|
|
12108
|
+
shouldFlagForReview,
|
|
12109
|
+
archiveReason,
|
|
12110
|
+
reviewReason
|
|
12111
|
+
};
|
|
12112
|
+
}
|
|
12113
|
+
function buildContradictionQuery(type, tags) {
|
|
12114
|
+
if (tags.length === 0)
|
|
12115
|
+
return null;
|
|
12116
|
+
return { type, tags };
|
|
12117
|
+
}
|
|
12118
|
+
// ../memory/src/sync.ts
|
|
12119
|
+
import { createHash } from "node:crypto";
|
|
12120
|
+
import {
|
|
12121
|
+
existsSync,
|
|
12122
|
+
mkdirSync,
|
|
12123
|
+
readdirSync,
|
|
12124
|
+
readFileSync,
|
|
12125
|
+
rmSync,
|
|
12126
|
+
writeFileSync
|
|
12127
|
+
} from "node:fs";
|
|
12128
|
+
import { join, relative, sep } from "node:path";
|
|
12129
|
+
|
|
11949
12130
|
// ../memory/src/sync-storage.ts
|
|
11950
12131
|
function parseSyncMarkdown(markdown) {
|
|
11951
12132
|
const trimmed = markdown.trim();
|
|
@@ -12061,17 +12242,8 @@ function parseYamlArray(value) {
|
|
|
12061
12242
|
return [];
|
|
12062
12243
|
return match[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
12063
12244
|
}
|
|
12245
|
+
|
|
12064
12246
|
// ../memory/src/sync.ts
|
|
12065
|
-
import { createHash } from "node:crypto";
|
|
12066
|
-
import {
|
|
12067
|
-
existsSync,
|
|
12068
|
-
mkdirSync,
|
|
12069
|
-
readdirSync,
|
|
12070
|
-
readFileSync,
|
|
12071
|
-
rmSync,
|
|
12072
|
-
writeFileSync
|
|
12073
|
-
} from "node:fs";
|
|
12074
|
-
import { join, relative, sep } from "node:path";
|
|
12075
12247
|
function computeFileHash(content) {
|
|
12076
12248
|
return `sha256:${createHash("sha256").update(content).digest("hex")}`;
|
|
12077
12249
|
}
|
|
@@ -12333,177 +12505,6 @@ async function syncFull(client, config, workspaceId, projectId) {
|
|
|
12333
12505
|
errors: [...pullResult.errors, ...pushResult.errors]
|
|
12334
12506
|
};
|
|
12335
12507
|
}
|
|
12336
|
-
// ../memory/src/lifecycle.ts
|
|
12337
|
-
var DECAY_HALF_LIVES = {
|
|
12338
|
-
draft: 7,
|
|
12339
|
-
episode: 30,
|
|
12340
|
-
reference: 180
|
|
12341
|
-
};
|
|
12342
|
-
var PROMOTION_RULES = {
|
|
12343
|
-
draftToEpisode: {
|
|
12344
|
-
minAccessCount: 5,
|
|
12345
|
-
minConfidence: 0.8,
|
|
12346
|
-
minAgeDays: 1
|
|
12347
|
-
},
|
|
12348
|
-
episodeToReference: {
|
|
12349
|
-
minAccessCount: 10,
|
|
12350
|
-
minConfidence: 0.9,
|
|
12351
|
-
minAgeDays: 7
|
|
12352
|
-
}
|
|
12353
|
-
};
|
|
12354
|
-
var ARCHIVE_THRESHOLD = 0.3;
|
|
12355
|
-
var STALE_DAYS = 90;
|
|
12356
|
-
var STALE_MIN_ACCESS = 3;
|
|
12357
|
-
function computeDecayScore(tier, lastAccessedAt, accessCount) {
|
|
12358
|
-
const halfLife = DECAY_HALF_LIVES[tier];
|
|
12359
|
-
const now = Date.now();
|
|
12360
|
-
let daysSinceAccess = 0;
|
|
12361
|
-
if (lastAccessedAt) {
|
|
12362
|
-
daysSinceAccess = (now - new Date(lastAccessedAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
12363
|
-
}
|
|
12364
|
-
const timeDecay = Math.pow(0.5, daysSinceAccess / halfLife);
|
|
12365
|
-
const accessBonus = Math.log10(accessCount + 1) * 0.1;
|
|
12366
|
-
const score = Math.min(timeDecay + accessBonus, 1);
|
|
12367
|
-
return { score, daysSinceAccess, halfLife, accessBonus };
|
|
12368
|
-
}
|
|
12369
|
-
function checkPromotion(currentTier, accessCount, confidence, createdAt) {
|
|
12370
|
-
const ageDays = (Date.now() - new Date(createdAt).getTime()) / (1000 * 60 * 60 * 24);
|
|
12371
|
-
const base = {
|
|
12372
|
-
eligible: false,
|
|
12373
|
-
targetTier: null,
|
|
12374
|
-
reason: null,
|
|
12375
|
-
currentTier,
|
|
12376
|
-
accessCount,
|
|
12377
|
-
confidence,
|
|
12378
|
-
ageDays
|
|
12379
|
-
};
|
|
12380
|
-
if (currentTier === "draft") {
|
|
12381
|
-
const rules = PROMOTION_RULES.draftToEpisode;
|
|
12382
|
-
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
12383
|
-
return {
|
|
12384
|
-
...base,
|
|
12385
|
-
eligible: true,
|
|
12386
|
-
targetTier: "episode",
|
|
12387
|
-
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
12388
|
-
};
|
|
12389
|
-
}
|
|
12390
|
-
}
|
|
12391
|
-
if (currentTier === "episode") {
|
|
12392
|
-
const rules = PROMOTION_RULES.episodeToReference;
|
|
12393
|
-
if (accessCount >= rules.minAccessCount && confidence >= rules.minConfidence && ageDays >= rules.minAgeDays) {
|
|
12394
|
-
return {
|
|
12395
|
-
...base,
|
|
12396
|
-
eligible: true,
|
|
12397
|
-
targetTier: "reference",
|
|
12398
|
-
reason: `Accessed ${accessCount} times (≥${rules.minAccessCount}), confidence ${confidence} (≥${rules.minConfidence}), age ${Math.round(ageDays)}d (≥${rules.minAgeDays}d)`
|
|
12399
|
-
};
|
|
12400
|
-
}
|
|
12401
|
-
}
|
|
12402
|
-
return base;
|
|
12403
|
-
}
|
|
12404
|
-
function evaluateLifecycle(entity) {
|
|
12405
|
-
const decay = computeDecayScore(entity.memory_tier, entity.last_accessed_at, entity.access_count);
|
|
12406
|
-
const promotion = checkPromotion(entity.memory_tier, entity.access_count, entity.confidence, entity.created_at);
|
|
12407
|
-
const shouldArchive = entity.confidence < ARCHIVE_THRESHOLD;
|
|
12408
|
-
const archiveReason = shouldArchive ? `Confidence ${entity.confidence} below threshold ${ARCHIVE_THRESHOLD}` : undefined;
|
|
12409
|
-
const shouldFlagForReview = decay.daysSinceAccess >= STALE_DAYS && entity.access_count < STALE_MIN_ACCESS;
|
|
12410
|
-
const reviewReason = shouldFlagForReview ? `Not accessed in ${Math.round(decay.daysSinceAccess)} days with only ${entity.access_count} accesses` : undefined;
|
|
12411
|
-
return {
|
|
12412
|
-
decay,
|
|
12413
|
-
promotion,
|
|
12414
|
-
shouldArchive,
|
|
12415
|
-
shouldFlagForReview,
|
|
12416
|
-
archiveReason,
|
|
12417
|
-
reviewReason
|
|
12418
|
-
};
|
|
12419
|
-
}
|
|
12420
|
-
function buildContradictionQuery(type, tags) {
|
|
12421
|
-
if (tags.length === 0)
|
|
12422
|
-
return null;
|
|
12423
|
-
return { type, tags };
|
|
12424
|
-
}
|
|
12425
|
-
// ../memory/src/graph-walk.ts
|
|
12426
|
-
async function discoverRelatedContext(client, startIds, maxDepth = 2, maxEntities = 20, minConfidence = 0.5) {
|
|
12427
|
-
const visited = new Set;
|
|
12428
|
-
const collectedEntities = [];
|
|
12429
|
-
const collectedRelations = [];
|
|
12430
|
-
let truncated = false;
|
|
12431
|
-
const queue = startIds.map((id) => [id, 0]);
|
|
12432
|
-
for (const id of startIds) {
|
|
12433
|
-
visited.add(id);
|
|
12434
|
-
}
|
|
12435
|
-
while (queue.length > 0) {
|
|
12436
|
-
const [entityId, depth] = queue.shift();
|
|
12437
|
-
if (collectedEntities.length >= maxEntities) {
|
|
12438
|
-
truncated = true;
|
|
12439
|
-
break;
|
|
12440
|
-
}
|
|
12441
|
-
if (depth > maxDepth)
|
|
12442
|
-
continue;
|
|
12443
|
-
try {
|
|
12444
|
-
const entityResult = await client.getMemoryEntity(entityId);
|
|
12445
|
-
const entity = entityResult.entity;
|
|
12446
|
-
if (entity) {
|
|
12447
|
-
collectedEntities.push({
|
|
12448
|
-
id: entity.id,
|
|
12449
|
-
type: entity.type,
|
|
12450
|
-
title: entity.title,
|
|
12451
|
-
confidence: entity.confidence ?? 1,
|
|
12452
|
-
memory_tier: entity.memory_tier || "reference"
|
|
12453
|
-
});
|
|
12454
|
-
}
|
|
12455
|
-
if (depth >= maxDepth)
|
|
12456
|
-
continue;
|
|
12457
|
-
const related = await client.getRelatedEntities(entityId);
|
|
12458
|
-
for (const raw of related.outgoing || []) {
|
|
12459
|
-
const rel = raw;
|
|
12460
|
-
const relConfidence = rel.confidence ?? 1;
|
|
12461
|
-
if (relConfidence < minConfidence)
|
|
12462
|
-
continue;
|
|
12463
|
-
const target = rel.target;
|
|
12464
|
-
const targetId = target?.id ?? rel.target_id;
|
|
12465
|
-
if (targetId && !visited.has(targetId)) {
|
|
12466
|
-
visited.add(targetId);
|
|
12467
|
-
queue.push([targetId, depth + 1]);
|
|
12468
|
-
collectedRelations.push({
|
|
12469
|
-
id: rel.id,
|
|
12470
|
-
source_id: entityId,
|
|
12471
|
-
target_id: targetId,
|
|
12472
|
-
relation_type: rel.relation_type,
|
|
12473
|
-
confidence: relConfidence
|
|
12474
|
-
});
|
|
12475
|
-
}
|
|
12476
|
-
}
|
|
12477
|
-
for (const raw of related.incoming || []) {
|
|
12478
|
-
const rel = raw;
|
|
12479
|
-
const relConfidence = rel.confidence ?? 1;
|
|
12480
|
-
if (relConfidence < minConfidence)
|
|
12481
|
-
continue;
|
|
12482
|
-
const source = rel.source;
|
|
12483
|
-
const sourceId = source?.id ?? rel.source_id;
|
|
12484
|
-
if (sourceId && !visited.has(sourceId)) {
|
|
12485
|
-
visited.add(sourceId);
|
|
12486
|
-
queue.push([sourceId, depth + 1]);
|
|
12487
|
-
collectedRelations.push({
|
|
12488
|
-
id: rel.id,
|
|
12489
|
-
source_id: sourceId,
|
|
12490
|
-
target_id: entityId,
|
|
12491
|
-
relation_type: rel.relation_type,
|
|
12492
|
-
confidence: relConfidence
|
|
12493
|
-
});
|
|
12494
|
-
}
|
|
12495
|
-
}
|
|
12496
|
-
} catch {
|
|
12497
|
-
continue;
|
|
12498
|
-
}
|
|
12499
|
-
}
|
|
12500
|
-
return {
|
|
12501
|
-
entities: collectedEntities,
|
|
12502
|
-
relations: collectedRelations,
|
|
12503
|
-
depth: maxDepth,
|
|
12504
|
-
truncated
|
|
12505
|
-
};
|
|
12506
|
-
}
|
|
12507
12508
|
// ../../node_modules/zod/v4/core/index.js
|
|
12508
12509
|
var exports_core2 = {};
|
|
12509
12510
|
__export(exports_core2, {
|
|
@@ -28491,7 +28492,7 @@ function getMemoryDir() {
|
|
|
28491
28492
|
}
|
|
28492
28493
|
|
|
28493
28494
|
// src/graph-expansion.ts
|
|
28494
|
-
async function autoExpandGraph(client2, entityId, title, content,
|
|
28495
|
+
async function autoExpandGraph(client2, entityId, title, content, _tags, workspaceId, projectId, maxRelations = 5) {
|
|
28495
28496
|
try {
|
|
28496
28497
|
const contentSnippet = content.slice(0, 200).trim();
|
|
28497
28498
|
const query = [title, contentSnippet].filter(Boolean).join(" ");
|
|
@@ -28569,7 +28570,11 @@ Agent: ${session.agentName}`
|
|
|
28569
28570
|
type: "lesson",
|
|
28570
28571
|
tier: "episode",
|
|
28571
28572
|
confidence: 0.7,
|
|
28572
|
-
tags: [
|
|
28573
|
+
tags: [
|
|
28574
|
+
"auto-extracted",
|
|
28575
|
+
"session-summary",
|
|
28576
|
+
...session.cardLabels.slice(0, 3)
|
|
28577
|
+
],
|
|
28573
28578
|
metadata: {
|
|
28574
28579
|
source: "active_learning",
|
|
28575
28580
|
card_id: session.cardId,
|
|
@@ -28763,7 +28768,7 @@ function isRetryableError(error48, status) {
|
|
|
28763
28768
|
return msg.includes("ECONNRESET") || msg.includes("ETIMEDOUT") || msg.includes("fetch failed");
|
|
28764
28769
|
}
|
|
28765
28770
|
function getRetryDelay(attempt) {
|
|
28766
|
-
const delay = Math.min(RETRY_CONFIG.baseDelayMs *
|
|
28771
|
+
const delay = Math.min(RETRY_CONFIG.baseDelayMs * 2 ** attempt, RETRY_CONFIG.maxDelayMs);
|
|
28767
28772
|
return Math.round(delay + delay * 0.25 * (Math.random() * 2 - 1));
|
|
28768
28773
|
}
|
|
28769
28774
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -28882,7 +28887,6 @@ class HarmonyApiClient {
|
|
|
28882
28887
|
throw lastError;
|
|
28883
28888
|
if (attempt < RETRY_CONFIG.maxRetries) {
|
|
28884
28889
|
await sleep(getRetryDelay(attempt));
|
|
28885
|
-
continue;
|
|
28886
28890
|
}
|
|
28887
28891
|
}
|
|
28888
28892
|
}
|
|
@@ -28929,7 +28933,6 @@ class HarmonyApiClient {
|
|
|
28929
28933
|
throw lastError;
|
|
28930
28934
|
if (attempt < RETRY_CONFIG.maxRetries) {
|
|
28931
28935
|
await sleep(getRetryDelay(attempt));
|
|
28932
|
-
continue;
|
|
28933
28936
|
}
|
|
28934
28937
|
}
|
|
28935
28938
|
}
|
|
@@ -28954,6 +28957,8 @@ class HarmonyApiClient {
|
|
|
28954
28957
|
params.set("column_id", options.columnId);
|
|
28955
28958
|
if (options?.summary)
|
|
28956
28959
|
params.set("summary", "true");
|
|
28960
|
+
if (options?.includeArchived)
|
|
28961
|
+
params.set("include_archived", "true");
|
|
28957
28962
|
const query = params.toString() ? `?${params.toString()}` : "";
|
|
28958
28963
|
return this.request("GET", `/board/${projectId}${query}`);
|
|
28959
28964
|
}
|
|
@@ -28969,6 +28974,12 @@ class HarmonyApiClient {
|
|
|
28969
28974
|
position
|
|
28970
28975
|
});
|
|
28971
28976
|
}
|
|
28977
|
+
async archiveCard(cardId) {
|
|
28978
|
+
return this.updateCard(cardId, { archivedAt: new Date().toISOString() });
|
|
28979
|
+
}
|
|
28980
|
+
async unarchiveCard(cardId) {
|
|
28981
|
+
return this.updateCard(cardId, { archivedAt: null });
|
|
28982
|
+
}
|
|
28972
28983
|
async deleteCard(cardId) {
|
|
28973
28984
|
return this.request("DELETE", `/cards/${cardId}`);
|
|
28974
28985
|
}
|
|
@@ -29327,7 +29338,7 @@ function computeRelevanceScore(entity, taskContext, cardLabels) {
|
|
|
29327
29338
|
if (entity.last_accessed_at) {
|
|
29328
29339
|
const daysSinceAccess = (Date.now() - new Date(entity.last_accessed_at).getTime()) / (1000 * 60 * 60 * 24);
|
|
29329
29340
|
const halfLife = { draft: 7, episode: 30, reference: 180 }[entity.memory_tier];
|
|
29330
|
-
const recencyScore =
|
|
29341
|
+
const recencyScore = 0.5 ** (daysSinceAccess / halfLife) * 0.1;
|
|
29331
29342
|
score += recencyScore;
|
|
29332
29343
|
if (daysSinceAccess < 7)
|
|
29333
29344
|
reasons.push("recently_accessed");
|
|
@@ -29404,7 +29415,11 @@ async function assembleContext(options) {
|
|
|
29404
29415
|
episode: Math.floor(tokenBudget * TIER_BUDGET_ALLOCATION.episode),
|
|
29405
29416
|
draft: Math.floor(tokenBudget * TIER_BUDGET_ALLOCATION.draft)
|
|
29406
29417
|
};
|
|
29407
|
-
const tierUsed = {
|
|
29418
|
+
const tierUsed = {
|
|
29419
|
+
reference: 0,
|
|
29420
|
+
episode: 0,
|
|
29421
|
+
draft: 0
|
|
29422
|
+
};
|
|
29408
29423
|
const included = [];
|
|
29409
29424
|
let totalUsed = 0;
|
|
29410
29425
|
let referenceCount = 0;
|
|
@@ -29474,9 +29489,18 @@ ${text}`);
|
|
|
29474
29489
|
}
|
|
29475
29490
|
manifest.budgetUsed = totalUsed;
|
|
29476
29491
|
manifest.tierBreakdown = {
|
|
29477
|
-
reference: {
|
|
29478
|
-
|
|
29479
|
-
|
|
29492
|
+
reference: {
|
|
29493
|
+
count: included.filter((i) => i.entity.memory_tier === "reference").length,
|
|
29494
|
+
tokens: tierUsed.reference
|
|
29495
|
+
},
|
|
29496
|
+
episode: {
|
|
29497
|
+
count: included.filter((i) => i.entity.memory_tier === "episode").length,
|
|
29498
|
+
tokens: tierUsed.episode
|
|
29499
|
+
},
|
|
29500
|
+
draft: {
|
|
29501
|
+
count: included.filter((i) => i.entity.memory_tier === "draft").length,
|
|
29502
|
+
tokens: tierUsed.draft
|
|
29503
|
+
}
|
|
29480
29504
|
};
|
|
29481
29505
|
for (const item of included) {
|
|
29482
29506
|
manifest.included.push({
|
|
@@ -29768,7 +29792,15 @@ ${lines.join(`
|
|
|
29768
29792
|
`)}`;
|
|
29769
29793
|
}
|
|
29770
29794
|
function generatePrompt(options) {
|
|
29771
|
-
const {
|
|
29795
|
+
const {
|
|
29796
|
+
card,
|
|
29797
|
+
column,
|
|
29798
|
+
variant,
|
|
29799
|
+
customConstraints,
|
|
29800
|
+
memories,
|
|
29801
|
+
assembledContext,
|
|
29802
|
+
assemblyId
|
|
29803
|
+
} = options;
|
|
29772
29804
|
const contextOpts = {
|
|
29773
29805
|
includeTitle: true,
|
|
29774
29806
|
includeDescription: true,
|
|
@@ -29922,7 +29954,8 @@ var TOOLS = {
|
|
|
29922
29954
|
description: { type: "string" },
|
|
29923
29955
|
priority: { type: "string", enum: ["low", "medium", "high", "urgent"] },
|
|
29924
29956
|
assigneeId: { type: "string", nullable: true },
|
|
29925
|
-
dueDate: { type: "string", nullable: true }
|
|
29957
|
+
dueDate: { type: "string", nullable: true },
|
|
29958
|
+
done: { type: "boolean", description: "Mark card as done or not done" }
|
|
29926
29959
|
},
|
|
29927
29960
|
required: ["cardId"]
|
|
29928
29961
|
}
|
|
@@ -29942,6 +29975,26 @@ var TOOLS = {
|
|
|
29942
29975
|
required: ["cardId", "columnId"]
|
|
29943
29976
|
}
|
|
29944
29977
|
},
|
|
29978
|
+
harmony_archive_card: {
|
|
29979
|
+
description: "Archive a card (soft-delete). Card can be restored later with unarchive.",
|
|
29980
|
+
inputSchema: {
|
|
29981
|
+
type: "object",
|
|
29982
|
+
properties: {
|
|
29983
|
+
cardId: { type: "string", description: "Card ID to archive" }
|
|
29984
|
+
},
|
|
29985
|
+
required: ["cardId"]
|
|
29986
|
+
}
|
|
29987
|
+
},
|
|
29988
|
+
harmony_unarchive_card: {
|
|
29989
|
+
description: "Restore an archived card back to the board.",
|
|
29990
|
+
inputSchema: {
|
|
29991
|
+
type: "object",
|
|
29992
|
+
properties: {
|
|
29993
|
+
cardId: { type: "string", description: "Card ID to unarchive" }
|
|
29994
|
+
},
|
|
29995
|
+
required: ["cardId"]
|
|
29996
|
+
}
|
|
29997
|
+
},
|
|
29945
29998
|
harmony_delete_card: {
|
|
29946
29999
|
description: "Delete a card",
|
|
29947
30000
|
inputSchema: {
|
|
@@ -30184,6 +30237,10 @@ var TOOLS = {
|
|
|
30184
30237
|
summary: {
|
|
30185
30238
|
type: "boolean",
|
|
30186
30239
|
description: "Return only columns with card counts, no card details"
|
|
30240
|
+
},
|
|
30241
|
+
includeArchived: {
|
|
30242
|
+
type: "boolean",
|
|
30243
|
+
description: "Include archived cards in results (default: false). Archived cards are excluded by default."
|
|
30187
30244
|
}
|
|
30188
30245
|
}
|
|
30189
30246
|
}
|
|
@@ -31242,7 +31299,8 @@ async function handleToolCall(name, args, deps) {
|
|
|
31242
31299
|
description: args.description,
|
|
31243
31300
|
priority: args.priority,
|
|
31244
31301
|
assigneeId: args.assigneeId,
|
|
31245
|
-
dueDate: args.dueDate
|
|
31302
|
+
dueDate: args.dueDate,
|
|
31303
|
+
done: args.done
|
|
31246
31304
|
});
|
|
31247
31305
|
return { success: true, ...result };
|
|
31248
31306
|
}
|
|
@@ -31272,6 +31330,16 @@ async function handleToolCall(name, args, deps) {
|
|
|
31272
31330
|
} catch {}
|
|
31273
31331
|
return { success: true, sessionEnded, ...result };
|
|
31274
31332
|
}
|
|
31333
|
+
case "harmony_archive_card": {
|
|
31334
|
+
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
31335
|
+
const result = await client3.archiveCard(cardId);
|
|
31336
|
+
return { success: true, ...result };
|
|
31337
|
+
}
|
|
31338
|
+
case "harmony_unarchive_card": {
|
|
31339
|
+
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
31340
|
+
const result = await client3.unarchiveCard(cardId);
|
|
31341
|
+
return { success: true, ...result };
|
|
31342
|
+
}
|
|
31275
31343
|
case "harmony_delete_card": {
|
|
31276
31344
|
const cardId = exports_external.string().uuid().parse(args.cardId);
|
|
31277
31345
|
await client3.deleteCard(cardId);
|
|
@@ -31395,6 +31463,8 @@ async function handleToolCall(name, args, deps) {
|
|
|
31395
31463
|
options.columnId = String(args.columnId);
|
|
31396
31464
|
if (args.summary === true || args.summary === "true")
|
|
31397
31465
|
options.summary = true;
|
|
31466
|
+
if (args.includeArchived === true || args.includeArchived === "true")
|
|
31467
|
+
options.includeArchived = true;
|
|
31398
31468
|
const result = await client3.getBoard(projectId, options);
|
|
31399
31469
|
return { success: true, board: result };
|
|
31400
31470
|
}
|
|
@@ -32059,7 +32129,7 @@ async function handleToolCall(name, args, deps) {
|
|
|
32059
32129
|
const card = cardResult.card;
|
|
32060
32130
|
await client3.updatePlanTask(planId, task.id, { cardId: card.id });
|
|
32061
32131
|
cardsCreated++;
|
|
32062
|
-
} catch (
|
|
32132
|
+
} catch (_e) {}
|
|
32063
32133
|
}
|
|
32064
32134
|
results.cardsCreated = cardsCreated;
|
|
32065
32135
|
}
|