@hermespilot/link 0.8.4 → 0.8.5-beta.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.
|
@@ -7721,7 +7721,7 @@ function isConversationMissingError(error) {
|
|
|
7721
7721
|
}
|
|
7722
7722
|
|
|
7723
7723
|
// src/constants.ts
|
|
7724
|
-
var LINK_VERSION = "0.8.
|
|
7724
|
+
var LINK_VERSION = "0.8.5-beta.0";
|
|
7725
7725
|
var LINK_COMMAND = "hermeslink";
|
|
7726
7726
|
var LINK_DEFAULT_PORT = 52379;
|
|
7727
7727
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -15932,6 +15932,9 @@ function collectHermesSessionIds(manifest, snapshot) {
|
|
|
15932
15932
|
return normalizeHermesSessionIds([
|
|
15933
15933
|
manifest.hermes_session_id,
|
|
15934
15934
|
...manifest.hermes_session_ids ?? [],
|
|
15935
|
+
manifest.hermes_lineage?.root_session_id,
|
|
15936
|
+
manifest.hermes_lineage?.current_session_id,
|
|
15937
|
+
...manifest.hermes_lineage?.session_ids ?? [],
|
|
15935
15938
|
...Object.values(manifest.profile_session_ids ?? {}),
|
|
15936
15939
|
...snapshot.runs.map((run) => run.hermes_session_id)
|
|
15937
15940
|
]);
|
|
@@ -15960,6 +15963,11 @@ function collectHermesSessionDeleteTargets(manifest, snapshot) {
|
|
|
15960
15963
|
for (const sessionId of manifest.hermes_session_ids ?? []) {
|
|
15961
15964
|
add(sessionId, defaultProfile);
|
|
15962
15965
|
}
|
|
15966
|
+
add(manifest.hermes_lineage?.root_session_id, defaultProfile);
|
|
15967
|
+
add(manifest.hermes_lineage?.current_session_id, defaultProfile);
|
|
15968
|
+
for (const sessionId of manifest.hermes_lineage?.session_ids ?? []) {
|
|
15969
|
+
add(sessionId, defaultProfile);
|
|
15970
|
+
}
|
|
15963
15971
|
for (const [profileName, sessionId] of Object.entries(
|
|
15964
15972
|
manifest.profile_session_ids ?? {}
|
|
15965
15973
|
)) {
|
|
@@ -21675,15 +21683,6 @@ async function syncHermesConversationMessages(paths, logger, input) {
|
|
|
21675
21683
|
for (const candidate of candidates) {
|
|
21676
21684
|
try {
|
|
21677
21685
|
const candidateMessages = await readHermesLineageMessages(candidate);
|
|
21678
|
-
if (candidateMessages.length === 0) {
|
|
21679
|
-
continue;
|
|
21680
|
-
}
|
|
21681
|
-
const missingCandidateMessages = candidateMessages.filter(
|
|
21682
|
-
(message, index) => !isRepresentedHermesRow(representedRows, message, index)
|
|
21683
|
-
);
|
|
21684
|
-
if (missingCandidateMessages.length === 0) {
|
|
21685
|
-
continue;
|
|
21686
|
-
}
|
|
21687
21686
|
const profile = await resolveConversationProfileTarget(
|
|
21688
21687
|
paths,
|
|
21689
21688
|
candidate.profileName
|
|
@@ -21693,6 +21692,15 @@ async function syncHermesConversationMessages(paths, logger, input) {
|
|
|
21693
21692
|
profileUid: profile.profileUid,
|
|
21694
21693
|
profileName: profile.profileName
|
|
21695
21694
|
});
|
|
21695
|
+
if (candidateMessages.length === 0) {
|
|
21696
|
+
continue;
|
|
21697
|
+
}
|
|
21698
|
+
const missingCandidateMessages = candidateMessages.filter(
|
|
21699
|
+
(message, index) => !isRepresentedHermesRow(representedRows, message, index)
|
|
21700
|
+
);
|
|
21701
|
+
if (missingCandidateMessages.length === 0) {
|
|
21702
|
+
continue;
|
|
21703
|
+
}
|
|
21696
21704
|
projectedMessages.push(
|
|
21697
21705
|
...toLinkMessages({
|
|
21698
21706
|
conversationId: input.conversationId,
|
|
@@ -21726,13 +21734,36 @@ async function syncHermesConversationMessages(paths, logger, input) {
|
|
|
21726
21734
|
exactKeys.forEach((key) => knownExactKeys.add(key));
|
|
21727
21735
|
}
|
|
21728
21736
|
if (appendedMessages.length === 0) {
|
|
21737
|
+
let nextManifest2 = candidateProfiles.size > 0 || duplicateCleanup.removedCount > 0 ? await store.readManifest(input.conversationId) : null;
|
|
21738
|
+
const currentManifest = nextManifest2;
|
|
21739
|
+
if (nextManifest2) {
|
|
21740
|
+
for (const profile of candidateProfiles.values()) {
|
|
21741
|
+
nextManifest2 = mergeHermesLineageIntoManifest({
|
|
21742
|
+
manifest: nextManifest2,
|
|
21743
|
+
candidate: profile.candidate,
|
|
21744
|
+
snapshot,
|
|
21745
|
+
profileUid: profile.profileUid,
|
|
21746
|
+
profileName: profile.profileName,
|
|
21747
|
+
updatedAt: isoFromHermesTime(profile.candidate.session.last_active) ?? nextManifest2.updated_at
|
|
21748
|
+
});
|
|
21749
|
+
}
|
|
21750
|
+
if (duplicateCleanup.removedCount > 0) {
|
|
21751
|
+
nextManifest2 = {
|
|
21752
|
+
...nextManifest2,
|
|
21753
|
+
stats: buildConversationStats(nextManifest2, snapshot)
|
|
21754
|
+
};
|
|
21755
|
+
}
|
|
21756
|
+
}
|
|
21729
21757
|
if (duplicateCleanup.removedCount > 0) {
|
|
21730
21758
|
await store.writeSnapshot(input.conversationId, snapshot);
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
const
|
|
21759
|
+
}
|
|
21760
|
+
if (nextManifest2 && currentManifest && (duplicateCleanup.removedCount > 0 || !manifestEquivalent(currentManifest, nextManifest2))) {
|
|
21761
|
+
const stats2 = buildConversationStats(nextManifest2, snapshot);
|
|
21762
|
+
nextManifest2 = { ...nextManifest2, stats: stats2 };
|
|
21734
21763
|
await store.writeManifest(nextManifest2);
|
|
21735
21764
|
await upsertConversationStats(paths, toStatsIndexRecord(nextManifest2, stats2));
|
|
21765
|
+
result.hermes_session_ids = manifestHermesSessionIds(nextManifest2);
|
|
21766
|
+
result.changed = true;
|
|
21736
21767
|
}
|
|
21737
21768
|
return result;
|
|
21738
21769
|
}
|
|
@@ -21773,6 +21804,7 @@ async function syncHermesConversationMessages(paths, logger, input) {
|
|
|
21773
21804
|
};
|
|
21774
21805
|
await store.writeManifest(nextManifest);
|
|
21775
21806
|
await upsertConversationStats(paths, toStatsIndexRecord(nextManifest, stats));
|
|
21807
|
+
result.hermes_session_ids = manifestHermesSessionIds(nextManifest);
|
|
21776
21808
|
const appendEvent = input.appendEvent ?? ((conversationId, event) => store.appendEvent(conversationId, event));
|
|
21777
21809
|
let lastEventSeq;
|
|
21778
21810
|
for (const message of hydratedAppendedMessages) {
|
|
@@ -22474,6 +22506,16 @@ function lineageSessionIds(candidate) {
|
|
|
22474
22506
|
candidate.session.id
|
|
22475
22507
|
]);
|
|
22476
22508
|
}
|
|
22509
|
+
function manifestHermesSessionIds(manifest) {
|
|
22510
|
+
return normalizeSessionIds([
|
|
22511
|
+
manifest.hermes_session_id,
|
|
22512
|
+
...manifest.hermes_session_ids ?? [],
|
|
22513
|
+
manifest.hermes_lineage?.root_session_id,
|
|
22514
|
+
manifest.hermes_lineage?.current_session_id,
|
|
22515
|
+
...manifest.hermes_lineage?.session_ids ?? [],
|
|
22516
|
+
...Object.values(manifest.profile_session_ids ?? {})
|
|
22517
|
+
]);
|
|
22518
|
+
}
|
|
22477
22519
|
function lineageTitle(candidate) {
|
|
22478
22520
|
const explicitLineageTitle = normalizeOptionalTitle(
|
|
22479
22521
|
candidate.session._lineage_title
|
|
@@ -29665,6 +29707,123 @@ ${resolved}` : resolved;
|
|
|
29665
29707
|
return true;
|
|
29666
29708
|
});
|
|
29667
29709
|
}
|
|
29710
|
+
async repairStaleAutomaticContextCompression(conversationId) {
|
|
29711
|
+
const terminalRepaired = await this.deps.withConversationLock(
|
|
29712
|
+
conversationId,
|
|
29713
|
+
async () => {
|
|
29714
|
+
const snapshot = await this.deps.readSnapshot(conversationId);
|
|
29715
|
+
const cleared = [];
|
|
29716
|
+
for (const run of snapshot.runs) {
|
|
29717
|
+
const status = staleAutomaticContextCompressionStatus(run);
|
|
29718
|
+
if (!status) {
|
|
29719
|
+
continue;
|
|
29720
|
+
}
|
|
29721
|
+
const result = this.clearAutomaticContextCompressionInSnapshot({
|
|
29722
|
+
snapshot,
|
|
29723
|
+
run,
|
|
29724
|
+
status,
|
|
29725
|
+
completedAt: run.completed_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
29726
|
+
});
|
|
29727
|
+
if (result) {
|
|
29728
|
+
cleared.push({ run, ...result });
|
|
29729
|
+
}
|
|
29730
|
+
}
|
|
29731
|
+
if (cleared.length === 0) {
|
|
29732
|
+
return false;
|
|
29733
|
+
}
|
|
29734
|
+
await this.deps.writeSnapshot(conversationId, snapshot);
|
|
29735
|
+
for (const item of cleared) {
|
|
29736
|
+
await this.appendAutomaticContextCompressionClearedEvent({
|
|
29737
|
+
conversationId,
|
|
29738
|
+
run: item.run,
|
|
29739
|
+
marker: item.marker,
|
|
29740
|
+
metadata: item.metadata
|
|
29741
|
+
});
|
|
29742
|
+
}
|
|
29743
|
+
await this.deps.persistConversationStats(conversationId, snapshot);
|
|
29744
|
+
return true;
|
|
29745
|
+
}
|
|
29746
|
+
);
|
|
29747
|
+
const detachedRunningRepaired = await this.repairDetachedRunningAutomaticContextCompression(conversationId);
|
|
29748
|
+
return terminalRepaired || detachedRunningRepaired;
|
|
29749
|
+
}
|
|
29750
|
+
async repairDetachedRunningAutomaticContextCompression(conversationId) {
|
|
29751
|
+
const snapshot = await this.deps.readSnapshot(conversationId).catch(() => null);
|
|
29752
|
+
const candidates = snapshot?.runs.filter(
|
|
29753
|
+
(run) => isRunningAutomaticContextCompression(run) && !this.deps.activeRunControllers.has(run.id)
|
|
29754
|
+
) ?? [];
|
|
29755
|
+
let repaired = false;
|
|
29756
|
+
for (const run of candidates) {
|
|
29757
|
+
if (this.deps.activeRunControllers.has(run.id)) {
|
|
29758
|
+
continue;
|
|
29759
|
+
}
|
|
29760
|
+
const previousSessionId = run.context_compression?.previous_session_id?.trim() || run.hermes_session_id;
|
|
29761
|
+
const nextSessionId = await readHermesCompressionTip(
|
|
29762
|
+
previousSessionId,
|
|
29763
|
+
this.deps.paths,
|
|
29764
|
+
run.profile
|
|
29765
|
+
).catch(() => void 0);
|
|
29766
|
+
if (!nextSessionId || nextSessionId === previousSessionId) {
|
|
29767
|
+
continue;
|
|
29768
|
+
}
|
|
29769
|
+
const finished = await this.finishAutomaticContextCompressionFromEvent({
|
|
29770
|
+
conversationId,
|
|
29771
|
+
runId: run.id,
|
|
29772
|
+
previousSessionId,
|
|
29773
|
+
nextSessionId
|
|
29774
|
+
});
|
|
29775
|
+
if (!finished) {
|
|
29776
|
+
continue;
|
|
29777
|
+
}
|
|
29778
|
+
await this.completeRun(conversationId, run.id);
|
|
29779
|
+
repaired = true;
|
|
29780
|
+
}
|
|
29781
|
+
return repaired;
|
|
29782
|
+
}
|
|
29783
|
+
clearAutomaticContextCompressionInSnapshot(input) {
|
|
29784
|
+
if (input.run.context_compression?.status !== "compressing" || input.run.context_compression.source !== "auto") {
|
|
29785
|
+
return null;
|
|
29786
|
+
}
|
|
29787
|
+
const marker = findContextCompressionMarker(
|
|
29788
|
+
input.snapshot,
|
|
29789
|
+
input.run.context_compression.operation_id
|
|
29790
|
+
);
|
|
29791
|
+
if (!marker) {
|
|
29792
|
+
return null;
|
|
29793
|
+
}
|
|
29794
|
+
const metadata = {
|
|
29795
|
+
...input.run.context_compression,
|
|
29796
|
+
status: input.status,
|
|
29797
|
+
completed_at: input.completedAt
|
|
29798
|
+
};
|
|
29799
|
+
input.run.context_compression = metadata;
|
|
29800
|
+
updateContextCompressionMarker({
|
|
29801
|
+
message: marker,
|
|
29802
|
+
metadata,
|
|
29803
|
+
language: input.run.language === "en" ? "en" : "zh-CN"
|
|
29804
|
+
});
|
|
29805
|
+
return { marker, metadata };
|
|
29806
|
+
}
|
|
29807
|
+
async appendAutomaticContextCompressionClearedEvent(input) {
|
|
29808
|
+
await this.deps.appendEvent(input.conversationId, {
|
|
29809
|
+
type: contextCompressionClearedEventType(input.metadata.status),
|
|
29810
|
+
message_id: input.marker.id,
|
|
29811
|
+
run_id: input.run.id,
|
|
29812
|
+
payload: {
|
|
29813
|
+
message: input.marker,
|
|
29814
|
+
run: input.run,
|
|
29815
|
+
operation: input.metadata,
|
|
29816
|
+
automatic: true,
|
|
29817
|
+
session_rotated: false
|
|
29818
|
+
},
|
|
29819
|
+
...input.event ? {
|
|
29820
|
+
raw: {
|
|
29821
|
+
format: "hermes-run-event",
|
|
29822
|
+
payload: input.event.rawPayload
|
|
29823
|
+
}
|
|
29824
|
+
} : {}
|
|
29825
|
+
});
|
|
29826
|
+
}
|
|
29668
29827
|
async runHasAssistantOutput(conversationId, runId) {
|
|
29669
29828
|
const snapshot = await this.deps.readSnapshot(conversationId).catch(() => null);
|
|
29670
29829
|
const run = snapshot?.runs.find((item) => item.id === runId);
|
|
@@ -30228,6 +30387,12 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30228
30387
|
);
|
|
30229
30388
|
}
|
|
30230
30389
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30390
|
+
const clearedCompression = this.clearAutomaticContextCompressionInSnapshot({
|
|
30391
|
+
snapshot,
|
|
30392
|
+
run,
|
|
30393
|
+
status: "completed",
|
|
30394
|
+
completedAt
|
|
30395
|
+
});
|
|
30231
30396
|
const usage = readUsage(source?.payload);
|
|
30232
30397
|
const responseId = readResponseId(source?.payload);
|
|
30233
30398
|
const hermesRunId = readRunId(source?.payload);
|
|
@@ -30328,6 +30493,15 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30328
30493
|
runId,
|
|
30329
30494
|
expiredInputRequests
|
|
30330
30495
|
);
|
|
30496
|
+
if (clearedCompression) {
|
|
30497
|
+
await this.appendAutomaticContextCompressionClearedEvent({
|
|
30498
|
+
conversationId,
|
|
30499
|
+
run,
|
|
30500
|
+
marker: clearedCompression.marker,
|
|
30501
|
+
metadata: clearedCompression.metadata,
|
|
30502
|
+
event: source
|
|
30503
|
+
});
|
|
30504
|
+
}
|
|
30331
30505
|
if (assistant) {
|
|
30332
30506
|
await this.deps.appendEvent(conversationId, {
|
|
30333
30507
|
type: "message.completed",
|
|
@@ -30404,6 +30578,12 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30404
30578
|
}
|
|
30405
30579
|
run.status = "failed";
|
|
30406
30580
|
run.completed_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
30581
|
+
const clearedCompression = this.clearAutomaticContextCompressionInSnapshot({
|
|
30582
|
+
snapshot,
|
|
30583
|
+
run,
|
|
30584
|
+
status: "failed",
|
|
30585
|
+
completedAt: run.completed_at
|
|
30586
|
+
});
|
|
30407
30587
|
run.error_message = message;
|
|
30408
30588
|
run.error_detail = source ? readErrorMessage4(source.payload) ?? void 0 : void 0;
|
|
30409
30589
|
const language = run.language === "en" ? "en" : "zh-CN";
|
|
@@ -30454,6 +30634,15 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30454
30634
|
runId,
|
|
30455
30635
|
expiredInputRequests
|
|
30456
30636
|
);
|
|
30637
|
+
if (clearedCompression) {
|
|
30638
|
+
await this.appendAutomaticContextCompressionClearedEvent({
|
|
30639
|
+
conversationId,
|
|
30640
|
+
run,
|
|
30641
|
+
marker: clearedCompression.marker,
|
|
30642
|
+
metadata: clearedCompression.metadata,
|
|
30643
|
+
event: source
|
|
30644
|
+
});
|
|
30645
|
+
}
|
|
30457
30646
|
const contextUsage = contextUsagePayloadForSnapshot(snapshot);
|
|
30458
30647
|
await this.deps.appendEvent(conversationId, {
|
|
30459
30648
|
type: "run.failed",
|
|
@@ -30682,6 +30871,12 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30682
30871
|
const cancelledAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30683
30872
|
run.status = "cancelled";
|
|
30684
30873
|
run.completed_at = cancelledAt;
|
|
30874
|
+
const clearedCompression = this.clearAutomaticContextCompressionInSnapshot({
|
|
30875
|
+
snapshot,
|
|
30876
|
+
run,
|
|
30877
|
+
status: "cancelled",
|
|
30878
|
+
completedAt: cancelledAt
|
|
30879
|
+
});
|
|
30685
30880
|
run.error_message = options.reason;
|
|
30686
30881
|
const cancelledByGoalPause = options.reason === "goal paused by app";
|
|
30687
30882
|
const assistant = snapshot.messages.find(
|
|
@@ -30723,6 +30918,14 @@ ${details.join("\n")}` : localizedEmptyHermesResponseMessage(language);
|
|
|
30723
30918
|
runId,
|
|
30724
30919
|
cancelledInputRequests
|
|
30725
30920
|
);
|
|
30921
|
+
if (clearedCompression) {
|
|
30922
|
+
await this.appendAutomaticContextCompressionClearedEvent({
|
|
30923
|
+
conversationId,
|
|
30924
|
+
run,
|
|
30925
|
+
marker: clearedCompression.marker,
|
|
30926
|
+
metadata: clearedCompression.metadata
|
|
30927
|
+
});
|
|
30928
|
+
}
|
|
30726
30929
|
if (assistant) {
|
|
30727
30930
|
await this.deps.appendEvent(conversationId, {
|
|
30728
30931
|
type: "message.completed",
|
|
@@ -30975,6 +31178,36 @@ function contextCompressionGeneration(message) {
|
|
|
30975
31178
|
function readPreviousSessionId(payload) {
|
|
30976
31179
|
return readString21(payload, "old_session_id") ?? readString21(payload, "oldSessionId") ?? readString21(payload, "previous_session_id") ?? readString21(payload, "previousSessionId");
|
|
30977
31180
|
}
|
|
31181
|
+
function contextCompressionClearedEventType(status) {
|
|
31182
|
+
if (status === "completed") {
|
|
31183
|
+
return "context_compression.completed";
|
|
31184
|
+
}
|
|
31185
|
+
if (status === "cancelled") {
|
|
31186
|
+
return "context_compression.cancelled";
|
|
31187
|
+
}
|
|
31188
|
+
if (status === "timed_out") {
|
|
31189
|
+
return "context_compression.timed_out";
|
|
31190
|
+
}
|
|
31191
|
+
return "context_compression.failed";
|
|
31192
|
+
}
|
|
31193
|
+
function staleAutomaticContextCompressionStatus(run) {
|
|
31194
|
+
if (run.context_compression?.status !== "compressing" || run.context_compression.source !== "auto") {
|
|
31195
|
+
return null;
|
|
31196
|
+
}
|
|
31197
|
+
if (run.status === "completed") {
|
|
31198
|
+
return "completed";
|
|
31199
|
+
}
|
|
31200
|
+
if (run.status === "failed") {
|
|
31201
|
+
return "failed";
|
|
31202
|
+
}
|
|
31203
|
+
if (run.status === "cancelled") {
|
|
31204
|
+
return "cancelled";
|
|
31205
|
+
}
|
|
31206
|
+
return null;
|
|
31207
|
+
}
|
|
31208
|
+
function isRunningAutomaticContextCompression(run) {
|
|
31209
|
+
return run.status === "running" && run.context_compression?.status === "compressing" && run.context_compression.source === "auto";
|
|
31210
|
+
}
|
|
30978
31211
|
function readNextSessionId(payload) {
|
|
30979
31212
|
const info = toRecord19(payload.info);
|
|
30980
31213
|
return readString21(payload, "session_key") ?? readString21(payload, "sessionKey") ?? readString21(payload, "stored_session_id") ?? readString21(payload, "storedSessionId") ?? readString21(payload, "session_id") ?? readString21(payload, "sessionId") ?? readString21(info, "session_key") ?? readString21(info, "sessionKey");
|
|
@@ -32286,6 +32519,11 @@ var ConversationService = class {
|
|
|
32286
32519
|
}
|
|
32287
32520
|
);
|
|
32288
32521
|
}
|
|
32522
|
+
if (!options.beforeMessageId) {
|
|
32523
|
+
await this.runLifecycle.repairStaleAutomaticContextCompression(
|
|
32524
|
+
conversationId
|
|
32525
|
+
);
|
|
32526
|
+
}
|
|
32289
32527
|
return this.queries.getMessages(conversationId, options);
|
|
32290
32528
|
}
|
|
32291
32529
|
async setConversationModel(conversationId, input) {
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED