@gethmy/mcp 2.5.7 → 2.6.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 +46 -4
- package/dist/index.js +46 -4
- package/dist/lib/api-client.js +45 -0
- package/package.json +1 -1
- package/src/api-client.ts +88 -2
- package/src/auto-session.ts +8 -4
package/dist/cli.js
CHANGED
|
@@ -1479,6 +1479,51 @@ class HarmonyApiClient {
|
|
|
1479
1479
|
async updateMemoryEntity(entityId, updates) {
|
|
1480
1480
|
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
1481
1481
|
}
|
|
1482
|
+
async harmonyRecall(options) {
|
|
1483
|
+
const fetchLimit = Math.max(options.topK ?? 3, 50);
|
|
1484
|
+
let entities = [];
|
|
1485
|
+
if (options.query) {
|
|
1486
|
+
const search = await this.searchMemoryEntities(options.workspaceId, options.query, {
|
|
1487
|
+
project_id: options.projectId,
|
|
1488
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1489
|
+
limit: fetchLimit
|
|
1490
|
+
});
|
|
1491
|
+
entities = search.entities ?? [];
|
|
1492
|
+
} else {
|
|
1493
|
+
const list = await this.listMemoryEntities({
|
|
1494
|
+
workspace_id: options.workspaceId,
|
|
1495
|
+
project_id: options.projectId,
|
|
1496
|
+
scope: options.scope,
|
|
1497
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1498
|
+
tags: options.tags,
|
|
1499
|
+
min_confidence: options.minConfidence,
|
|
1500
|
+
limit: fetchLimit
|
|
1501
|
+
});
|
|
1502
|
+
entities = list.entities ?? [];
|
|
1503
|
+
}
|
|
1504
|
+
if (options.type && options.type.length > 1) {
|
|
1505
|
+
const allowed = new Set(options.type);
|
|
1506
|
+
entities = entities.filter((e) => allowed.has(e.type));
|
|
1507
|
+
}
|
|
1508
|
+
if (options.memory_tier) {
|
|
1509
|
+
entities = entities.filter((e) => e.memory_tier === options.memory_tier);
|
|
1510
|
+
}
|
|
1511
|
+
if (options.scope) {
|
|
1512
|
+
entities = entities.filter((e) => e.scope === options.scope);
|
|
1513
|
+
}
|
|
1514
|
+
if (options.tags?.length) {
|
|
1515
|
+
const wanted = new Set(options.tags);
|
|
1516
|
+
entities = entities.filter((e) => (e.tags ?? []).some((t) => wanted.has(t)));
|
|
1517
|
+
}
|
|
1518
|
+
if (typeof options.minConfidence === "number") {
|
|
1519
|
+
const threshold = options.minConfidence;
|
|
1520
|
+
entities = entities.filter((e) => typeof e.confidence === "number" && e.confidence >= threshold);
|
|
1521
|
+
}
|
|
1522
|
+
if (options.topK !== undefined) {
|
|
1523
|
+
entities = entities.slice(0, options.topK);
|
|
1524
|
+
}
|
|
1525
|
+
return { entities };
|
|
1526
|
+
}
|
|
1482
1527
|
async deleteMemoryEntity(entityId) {
|
|
1483
1528
|
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
1484
1529
|
}
|
|
@@ -1785,11 +1830,8 @@ function resolveAgentIdentity(info) {
|
|
|
1785
1830
|
var AUTO_START_TRIGGERS = new Set([
|
|
1786
1831
|
"harmony_generate_prompt",
|
|
1787
1832
|
"harmony_update_card",
|
|
1788
|
-
"harmony_move_card",
|
|
1789
1833
|
"harmony_create_subtask",
|
|
1790
|
-
"harmony_toggle_subtask"
|
|
1791
|
-
"harmony_add_label_to_card",
|
|
1792
|
-
"harmony_remove_label_from_card"
|
|
1834
|
+
"harmony_toggle_subtask"
|
|
1793
1835
|
]);
|
|
1794
1836
|
var INACTIVITY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
1795
1837
|
var CHECK_INTERVAL_MS = 60 * 1000;
|
package/dist/index.js
CHANGED
|
@@ -1475,6 +1475,51 @@ class HarmonyApiClient {
|
|
|
1475
1475
|
async updateMemoryEntity(entityId, updates) {
|
|
1476
1476
|
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
1477
1477
|
}
|
|
1478
|
+
async harmonyRecall(options) {
|
|
1479
|
+
const fetchLimit = Math.max(options.topK ?? 3, 50);
|
|
1480
|
+
let entities = [];
|
|
1481
|
+
if (options.query) {
|
|
1482
|
+
const search = await this.searchMemoryEntities(options.workspaceId, options.query, {
|
|
1483
|
+
project_id: options.projectId,
|
|
1484
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1485
|
+
limit: fetchLimit
|
|
1486
|
+
});
|
|
1487
|
+
entities = search.entities ?? [];
|
|
1488
|
+
} else {
|
|
1489
|
+
const list = await this.listMemoryEntities({
|
|
1490
|
+
workspace_id: options.workspaceId,
|
|
1491
|
+
project_id: options.projectId,
|
|
1492
|
+
scope: options.scope,
|
|
1493
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1494
|
+
tags: options.tags,
|
|
1495
|
+
min_confidence: options.minConfidence,
|
|
1496
|
+
limit: fetchLimit
|
|
1497
|
+
});
|
|
1498
|
+
entities = list.entities ?? [];
|
|
1499
|
+
}
|
|
1500
|
+
if (options.type && options.type.length > 1) {
|
|
1501
|
+
const allowed = new Set(options.type);
|
|
1502
|
+
entities = entities.filter((e) => allowed.has(e.type));
|
|
1503
|
+
}
|
|
1504
|
+
if (options.memory_tier) {
|
|
1505
|
+
entities = entities.filter((e) => e.memory_tier === options.memory_tier);
|
|
1506
|
+
}
|
|
1507
|
+
if (options.scope) {
|
|
1508
|
+
entities = entities.filter((e) => e.scope === options.scope);
|
|
1509
|
+
}
|
|
1510
|
+
if (options.tags?.length) {
|
|
1511
|
+
const wanted = new Set(options.tags);
|
|
1512
|
+
entities = entities.filter((e) => (e.tags ?? []).some((t) => wanted.has(t)));
|
|
1513
|
+
}
|
|
1514
|
+
if (typeof options.minConfidence === "number") {
|
|
1515
|
+
const threshold = options.minConfidence;
|
|
1516
|
+
entities = entities.filter((e) => typeof e.confidence === "number" && e.confidence >= threshold);
|
|
1517
|
+
}
|
|
1518
|
+
if (options.topK !== undefined) {
|
|
1519
|
+
entities = entities.slice(0, options.topK);
|
|
1520
|
+
}
|
|
1521
|
+
return { entities };
|
|
1522
|
+
}
|
|
1478
1523
|
async deleteMemoryEntity(entityId) {
|
|
1479
1524
|
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
1480
1525
|
}
|
|
@@ -1781,11 +1826,8 @@ function resolveAgentIdentity(info) {
|
|
|
1781
1826
|
var AUTO_START_TRIGGERS = new Set([
|
|
1782
1827
|
"harmony_generate_prompt",
|
|
1783
1828
|
"harmony_update_card",
|
|
1784
|
-
"harmony_move_card",
|
|
1785
1829
|
"harmony_create_subtask",
|
|
1786
|
-
"harmony_toggle_subtask"
|
|
1787
|
-
"harmony_add_label_to_card",
|
|
1788
|
-
"harmony_remove_label_from_card"
|
|
1830
|
+
"harmony_toggle_subtask"
|
|
1789
1831
|
]);
|
|
1790
1832
|
var INACTIVITY_TIMEOUT_MS = 10 * 60 * 1000;
|
|
1791
1833
|
var CHECK_INTERVAL_MS = 60 * 1000;
|
package/dist/lib/api-client.js
CHANGED
|
@@ -1082,6 +1082,51 @@ class HarmonyApiClient {
|
|
|
1082
1082
|
async updateMemoryEntity(entityId, updates) {
|
|
1083
1083
|
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
1084
1084
|
}
|
|
1085
|
+
async harmonyRecall(options) {
|
|
1086
|
+
const fetchLimit = Math.max(options.topK ?? 3, 50);
|
|
1087
|
+
let entities = [];
|
|
1088
|
+
if (options.query) {
|
|
1089
|
+
const search = await this.searchMemoryEntities(options.workspaceId, options.query, {
|
|
1090
|
+
project_id: options.projectId,
|
|
1091
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1092
|
+
limit: fetchLimit
|
|
1093
|
+
});
|
|
1094
|
+
entities = search.entities ?? [];
|
|
1095
|
+
} else {
|
|
1096
|
+
const list = await this.listMemoryEntities({
|
|
1097
|
+
workspace_id: options.workspaceId,
|
|
1098
|
+
project_id: options.projectId,
|
|
1099
|
+
scope: options.scope,
|
|
1100
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
1101
|
+
tags: options.tags,
|
|
1102
|
+
min_confidence: options.minConfidence,
|
|
1103
|
+
limit: fetchLimit
|
|
1104
|
+
});
|
|
1105
|
+
entities = list.entities ?? [];
|
|
1106
|
+
}
|
|
1107
|
+
if (options.type && options.type.length > 1) {
|
|
1108
|
+
const allowed = new Set(options.type);
|
|
1109
|
+
entities = entities.filter((e) => allowed.has(e.type));
|
|
1110
|
+
}
|
|
1111
|
+
if (options.memory_tier) {
|
|
1112
|
+
entities = entities.filter((e) => e.memory_tier === options.memory_tier);
|
|
1113
|
+
}
|
|
1114
|
+
if (options.scope) {
|
|
1115
|
+
entities = entities.filter((e) => e.scope === options.scope);
|
|
1116
|
+
}
|
|
1117
|
+
if (options.tags?.length) {
|
|
1118
|
+
const wanted = new Set(options.tags);
|
|
1119
|
+
entities = entities.filter((e) => (e.tags ?? []).some((t) => wanted.has(t)));
|
|
1120
|
+
}
|
|
1121
|
+
if (typeof options.minConfidence === "number") {
|
|
1122
|
+
const threshold = options.minConfidence;
|
|
1123
|
+
entities = entities.filter((e) => typeof e.confidence === "number" && e.confidence >= threshold);
|
|
1124
|
+
}
|
|
1125
|
+
if (options.topK !== undefined) {
|
|
1126
|
+
entities = entities.slice(0, options.topK);
|
|
1127
|
+
}
|
|
1128
|
+
return { entities };
|
|
1129
|
+
}
|
|
1085
1130
|
async deleteMemoryEntity(entityId) {
|
|
1086
1131
|
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
1087
1132
|
}
|
package/package.json
CHANGED
package/src/api-client.ts
CHANGED
|
@@ -743,15 +743,101 @@ export class HarmonyApiClient {
|
|
|
743
743
|
scope?: string;
|
|
744
744
|
type?: string;
|
|
745
745
|
memory_tier?: string;
|
|
746
|
-
//
|
|
747
|
-
//
|
|
746
|
+
// Supersede semantics — used by Phase 1.5 review-reject back-fill to
|
|
747
|
+
// tombstone the original implement episode without hard-deleting it.
|
|
748
|
+
// The backend sets superseded_at automatically when superseded_by lands.
|
|
748
749
|
superseded_by?: string | null;
|
|
750
|
+
superseded_at?: string | null;
|
|
749
751
|
version?: number;
|
|
750
752
|
},
|
|
751
753
|
): Promise<{ entity: unknown; warnings?: string[] }> {
|
|
752
754
|
return this.request("PUT", `/memory/entities/${entityId}`, updates);
|
|
753
755
|
}
|
|
754
756
|
|
|
757
|
+
/**
|
|
758
|
+
* Retrieve memories filtered by type/tier/scope, optionally ranked by a
|
|
759
|
+
* free-text query. Wraps `searchMemoryEntities` (when a query is given)
|
|
760
|
+
* or `listMemoryEntities` and applies client-side filters that the REST
|
|
761
|
+
* surface doesn't natively expose (multi-type, memory_tier).
|
|
762
|
+
*
|
|
763
|
+
* Used by the agent daemon's read hook to surface similar past episodes
|
|
764
|
+
* before building a new task prompt (Phase 1.5).
|
|
765
|
+
*/
|
|
766
|
+
async harmonyRecall(options: {
|
|
767
|
+
workspaceId: string;
|
|
768
|
+
projectId?: string;
|
|
769
|
+
query?: string;
|
|
770
|
+
type?: string[];
|
|
771
|
+
memory_tier?: string;
|
|
772
|
+
scope?: string;
|
|
773
|
+
tags?: string[];
|
|
774
|
+
minConfidence?: number;
|
|
775
|
+
topK?: number;
|
|
776
|
+
}): Promise<{ entities: unknown[] }> {
|
|
777
|
+
// Over-fetch beyond topK so client-side filters (multi-type, memory_tier,
|
|
778
|
+
// tags) have headroom — matches the MCP server's recall path (server.ts).
|
|
779
|
+
const fetchLimit = Math.max(options.topK ?? 3, 50);
|
|
780
|
+
let entities: Array<Record<string, unknown>> = [];
|
|
781
|
+
|
|
782
|
+
if (options.query) {
|
|
783
|
+
// searchMemoryEntities accepts a single type — refine client-side
|
|
784
|
+
// when the caller passed multiple.
|
|
785
|
+
const search = await this.searchMemoryEntities(
|
|
786
|
+
options.workspaceId,
|
|
787
|
+
options.query,
|
|
788
|
+
{
|
|
789
|
+
project_id: options.projectId,
|
|
790
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
791
|
+
limit: fetchLimit,
|
|
792
|
+
},
|
|
793
|
+
);
|
|
794
|
+
entities = (search.entities ?? []) as Array<Record<string, unknown>>;
|
|
795
|
+
} else {
|
|
796
|
+
const list = await this.listMemoryEntities({
|
|
797
|
+
workspace_id: options.workspaceId,
|
|
798
|
+
project_id: options.projectId,
|
|
799
|
+
scope: options.scope,
|
|
800
|
+
type: options.type?.length === 1 ? options.type[0] : undefined,
|
|
801
|
+
tags: options.tags,
|
|
802
|
+
min_confidence: options.minConfidence,
|
|
803
|
+
limit: fetchLimit,
|
|
804
|
+
});
|
|
805
|
+
entities = (list.entities ?? []) as Array<Record<string, unknown>>;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Client-side filters: REST surface lacks multi-type and memory_tier.
|
|
809
|
+
if (options.type && options.type.length > 1) {
|
|
810
|
+
const allowed = new Set(options.type);
|
|
811
|
+
entities = entities.filter((e) => allowed.has(e.type as string));
|
|
812
|
+
}
|
|
813
|
+
if (options.memory_tier) {
|
|
814
|
+
entities = entities.filter((e) => e.memory_tier === options.memory_tier);
|
|
815
|
+
}
|
|
816
|
+
if (options.scope) {
|
|
817
|
+
entities = entities.filter((e) => e.scope === options.scope);
|
|
818
|
+
}
|
|
819
|
+
if (options.tags?.length) {
|
|
820
|
+
const wanted = new Set(options.tags);
|
|
821
|
+
entities = entities.filter((e) =>
|
|
822
|
+
((e.tags as string[]) ?? []).some((t) => wanted.has(t)),
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
if (typeof options.minConfidence === "number") {
|
|
826
|
+
const threshold = options.minConfidence;
|
|
827
|
+
entities = entities.filter(
|
|
828
|
+
(e) =>
|
|
829
|
+
typeof e.confidence === "number" &&
|
|
830
|
+
(e.confidence as number) >= threshold,
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (options.topK !== undefined) {
|
|
835
|
+
entities = entities.slice(0, options.topK);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
return { entities };
|
|
839
|
+
}
|
|
840
|
+
|
|
755
841
|
async deleteMemoryEntity(entityId: string): Promise<{ success: boolean }> {
|
|
756
842
|
return this.request("DELETE", `/memory/entities/${entityId}`);
|
|
757
843
|
}
|
package/src/auto-session.ts
CHANGED
|
@@ -65,15 +65,19 @@ export function resolveAgentIdentity(info: ClientInfo | null): {
|
|
|
65
65
|
return { agentIdentifier: key, agentName: displayName };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Tools that trigger auto-start of a session.
|
|
70
|
+
*
|
|
71
|
+
* Restricted to tools that signal real work on a card. Board-management ops
|
|
72
|
+
* (move, label add/remove) are excluded — they're routinely used for triage
|
|
73
|
+
* and would create false-positive sessions whose side effect (the auto-added
|
|
74
|
+
* `agent` label on the card) confuses both UI and humans.
|
|
75
|
+
*/
|
|
69
76
|
export const AUTO_START_TRIGGERS = new Set([
|
|
70
77
|
"harmony_generate_prompt",
|
|
71
78
|
"harmony_update_card",
|
|
72
|
-
"harmony_move_card",
|
|
73
79
|
"harmony_create_subtask",
|
|
74
80
|
"harmony_toggle_subtask",
|
|
75
|
-
"harmony_add_label_to_card",
|
|
76
|
-
"harmony_remove_label_from_card",
|
|
77
81
|
]);
|
|
78
82
|
|
|
79
83
|
export const INACTIVITY_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
|