@hermespilot/link 0.3.2 → 0.3.3
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.
|
@@ -353,7 +353,7 @@ async function readLinkUsageStatistics(paths, filter = {}) {
|
|
|
353
353
|
FROM run_usage_facts
|
|
354
354
|
${where.sql}
|
|
355
355
|
GROUP BY COALESCE(NULLIF(model, ''), 'unknown'), provider
|
|
356
|
-
HAVING total_tokens > 0
|
|
356
|
+
HAVING SUM(total_tokens) > 0
|
|
357
357
|
ORDER BY total_tokens DESC, run_count DESC, model ASC
|
|
358
358
|
LIMIT 12
|
|
359
359
|
`).all(...where.params);
|
|
@@ -379,7 +379,7 @@ async function readLinkUsageStatistics(paths, filter = {}) {
|
|
|
379
379
|
NULLIF(profile_uid, ''),
|
|
380
380
|
'unknown'
|
|
381
381
|
)
|
|
382
|
-
HAVING total_tokens > 0
|
|
382
|
+
HAVING SUM(total_tokens) > 0
|
|
383
383
|
ORDER BY total_tokens DESC, run_count DESC, profile ASC
|
|
384
384
|
LIMIT 12
|
|
385
385
|
`).all(...where.params);
|
|
@@ -3724,7 +3724,7 @@ import os2 from "os";
|
|
|
3724
3724
|
import path5 from "path";
|
|
3725
3725
|
|
|
3726
3726
|
// src/constants.ts
|
|
3727
|
-
var LINK_VERSION = "0.3.
|
|
3727
|
+
var LINK_VERSION = "0.3.3";
|
|
3728
3728
|
var LINK_COMMAND = "hermeslink";
|
|
3729
3729
|
var LINK_DEFAULT_PORT = 52379;
|
|
3730
3730
|
var LINK_RUNTIME_DIR_NAME = ".hermeslink";
|
|
@@ -12851,7 +12851,7 @@ function registerConversationRoutes(router, options) {
|
|
|
12851
12851
|
ctx.set("cache-control", "private, max-age=86400");
|
|
12852
12852
|
ctx.set(
|
|
12853
12853
|
"content-disposition",
|
|
12854
|
-
|
|
12854
|
+
contentDispositionInline(blob.filename)
|
|
12855
12855
|
);
|
|
12856
12856
|
ctx.body = blob.bytes;
|
|
12857
12857
|
}
|
|
@@ -12870,6 +12870,34 @@ function registerConversationRoutes(router, options) {
|
|
|
12870
12870
|
}
|
|
12871
12871
|
);
|
|
12872
12872
|
}
|
|
12873
|
+
function contentDispositionInline(filename) {
|
|
12874
|
+
const fallback = asciiFilenameFallback(filename);
|
|
12875
|
+
return `inline; filename="${fallback}"; filename*=UTF-8''${encodeRfc5987Value(filename)}`;
|
|
12876
|
+
}
|
|
12877
|
+
function asciiFilenameFallback(filename) {
|
|
12878
|
+
const basename = filename.trim().split(/[\\/]/u).pop()?.trim() ?? "";
|
|
12879
|
+
const extension = safeAsciiExtension(basename);
|
|
12880
|
+
const stem = extension ? basename.slice(0, -extension.length) : basename;
|
|
12881
|
+
const asciiStem = stem.replace(/[^\x20-\x7E]/gu, "_").replace(/["\\]/gu, "_").replace(/[^A-Za-z0-9._ -]/gu, "_").replace(/_+/gu, "_").trim();
|
|
12882
|
+
if (/[A-Za-z0-9]/u.test(asciiStem)) {
|
|
12883
|
+
return `${asciiStem.slice(0, 120)}${extension}`;
|
|
12884
|
+
}
|
|
12885
|
+
return `attachment${extension}`;
|
|
12886
|
+
}
|
|
12887
|
+
function safeAsciiExtension(filename) {
|
|
12888
|
+
const dotIndex = filename.lastIndexOf(".");
|
|
12889
|
+
if (dotIndex < 0 || dotIndex === filename.length - 1) {
|
|
12890
|
+
return "";
|
|
12891
|
+
}
|
|
12892
|
+
const extension = filename.slice(dotIndex).toLowerCase();
|
|
12893
|
+
return /^\.[a-z0-9]{1,12}$/u.test(extension) ? extension : "";
|
|
12894
|
+
}
|
|
12895
|
+
function encodeRfc5987Value(value) {
|
|
12896
|
+
return encodeURIComponent(value).replace(
|
|
12897
|
+
/['()*]/gu,
|
|
12898
|
+
(char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`
|
|
12899
|
+
);
|
|
12900
|
+
}
|
|
12873
12901
|
function isConversationNotificationEvent(event) {
|
|
12874
12902
|
const type = event.type.toLowerCase();
|
|
12875
12903
|
return type === "conversation.created" || type === "conversation.updated" || type === "conversation.deleted" || type === "message.created" || type === "message.completed" || type === "message.failed" || type === "run.completed" || type === "run.failed" || type === "run.cancelled" || type === "run.canceled" || type === "approval.requested" || readPayloadBool(event.payload, "requires_action") || readPayloadBool(event.payload, "requires_user_action") || readPayloadBool(event.payload, "requires_approval");
|
|
@@ -14650,8 +14678,8 @@ import {
|
|
|
14650
14678
|
import path18 from "path";
|
|
14651
14679
|
import YAML4 from "yaml";
|
|
14652
14680
|
var ENTRY_DELIMITER = "\n\xA7\n";
|
|
14653
|
-
var
|
|
14654
|
-
var
|
|
14681
|
+
var DEFAULT_MEMORY_LIMIT = 2200;
|
|
14682
|
+
var DEFAULT_USER_LIMIT = 1375;
|
|
14655
14683
|
var CUSTOM_PROVIDER_CARD_ID = "__custom__";
|
|
14656
14684
|
var CUSTOM_PROVIDER_REGISTRY_FILE = "memory-providers.json";
|
|
14657
14685
|
var HINDSIGHT_DEFAULT_API_URL = "https://api.hindsight.vectorize.io";
|
|
@@ -14734,9 +14762,10 @@ var HermesMemoryError = class extends Error {
|
|
|
14734
14762
|
};
|
|
14735
14763
|
async function readHermesProfileMemory(profileName = "default") {
|
|
14736
14764
|
const memoryDir = resolveMemoryDir(profileName);
|
|
14765
|
+
const limits = await readMemoryLimits(profileName);
|
|
14737
14766
|
const [memoryStore, userStore, settings] = await Promise.all([
|
|
14738
|
-
readMemoryStore(profileName, "memory"),
|
|
14739
|
-
readMemoryStore(profileName, "user"),
|
|
14767
|
+
readMemoryStore(profileName, "memory", limits),
|
|
14768
|
+
readMemoryStore(profileName, "user", limits),
|
|
14740
14769
|
readMemorySettings(profileName)
|
|
14741
14770
|
]);
|
|
14742
14771
|
return {
|
|
@@ -14754,9 +14783,7 @@ async function addHermesMemoryEntry(profileName, target, content) {
|
|
|
14754
14783
|
if (entries.includes(normalized)) {
|
|
14755
14784
|
return entries;
|
|
14756
14785
|
}
|
|
14757
|
-
|
|
14758
|
-
assertWithinLimit(target, next);
|
|
14759
|
-
return next;
|
|
14786
|
+
return [...entries, normalized];
|
|
14760
14787
|
});
|
|
14761
14788
|
return readHermesProfileMemory(profileName);
|
|
14762
14789
|
}
|
|
@@ -14767,7 +14794,6 @@ async function replaceHermesMemoryEntry(profileName, target, oldText, content) {
|
|
|
14767
14794
|
const index = findSingleMatch(entries, needle);
|
|
14768
14795
|
const next = [...entries];
|
|
14769
14796
|
next[index] = normalized;
|
|
14770
|
-
assertWithinLimit(target, next);
|
|
14771
14797
|
return next;
|
|
14772
14798
|
});
|
|
14773
14799
|
return readHermesProfileMemory(profileName);
|
|
@@ -15040,7 +15066,7 @@ async function patchHermesMemoryProvider(profileName, provider) {
|
|
|
15040
15066
|
function resolveMemoryDir(profileName) {
|
|
15041
15067
|
return path18.join(resolveHermesProfileDir(profileName), "memories");
|
|
15042
15068
|
}
|
|
15043
|
-
async function readMemoryStore(profileName, target) {
|
|
15069
|
+
async function readMemoryStore(profileName, target, limits) {
|
|
15044
15070
|
const filePath = memoryFilePath(profileName, target);
|
|
15045
15071
|
const entries = await readMemoryEntries(filePath);
|
|
15046
15072
|
const fileStat = await stat12(filePath).catch((error) => {
|
|
@@ -15050,7 +15076,7 @@ async function readMemoryStore(profileName, target) {
|
|
|
15050
15076
|
throw error;
|
|
15051
15077
|
});
|
|
15052
15078
|
const chars = entries.length ? entries.join(ENTRY_DELIMITER).length : 0;
|
|
15053
|
-
const limit = target
|
|
15079
|
+
const limit = memoryLimitForTarget(limits, target);
|
|
15054
15080
|
return {
|
|
15055
15081
|
target,
|
|
15056
15082
|
label: target === "user" ? "\u5173\u4E8E\u7528\u6237" : "Agent \u7B14\u8BB0",
|
|
@@ -15091,7 +15117,7 @@ async function mutateMemoryEntries(profileName, target, mutate) {
|
|
|
15091
15117
|
await writeMemoryEntries(profileName, target, mutate([...new Set(current)]));
|
|
15092
15118
|
}
|
|
15093
15119
|
async function writeMemoryEntries(profileName, target, entries) {
|
|
15094
|
-
assertWithinLimit(target, entries);
|
|
15120
|
+
assertWithinLimit(target, entries, await readMemoryLimits(profileName));
|
|
15095
15121
|
const filePath = memoryFilePath(profileName, target);
|
|
15096
15122
|
const dir = path18.dirname(filePath);
|
|
15097
15123
|
await mkdir12(dir, { recursive: true, mode: 448 });
|
|
@@ -15904,8 +15930,28 @@ function selectSetting(key, label, value, options, editable = true) {
|
|
|
15904
15930
|
const stringValue = readString13(value) ?? options[0] ?? null;
|
|
15905
15931
|
return { key, label, value: stringValue, editable, kind: "select", options };
|
|
15906
15932
|
}
|
|
15907
|
-
function
|
|
15908
|
-
const
|
|
15933
|
+
async function readMemoryLimits(profileName) {
|
|
15934
|
+
const raw = await readFile13(
|
|
15935
|
+
resolveHermesConfigPath(profileName),
|
|
15936
|
+
"utf8"
|
|
15937
|
+
).catch((error) => {
|
|
15938
|
+
if (isNodeError13(error, "ENOENT")) {
|
|
15939
|
+
return "";
|
|
15940
|
+
}
|
|
15941
|
+
throw error;
|
|
15942
|
+
});
|
|
15943
|
+
const config = raw ? toRecord12(YAML4.parse(raw)) : {};
|
|
15944
|
+
const memory = toRecord12(config.memory);
|
|
15945
|
+
return {
|
|
15946
|
+
memory: readPositiveInteger3(memory.memory_char_limit) ?? DEFAULT_MEMORY_LIMIT,
|
|
15947
|
+
user: readPositiveInteger3(memory.user_char_limit) ?? DEFAULT_USER_LIMIT
|
|
15948
|
+
};
|
|
15949
|
+
}
|
|
15950
|
+
function memoryLimitForTarget(limits, target) {
|
|
15951
|
+
return target === "user" ? limits.user : limits.memory;
|
|
15952
|
+
}
|
|
15953
|
+
function assertWithinLimit(target, entries, limits) {
|
|
15954
|
+
const limit = memoryLimitForTarget(limits, target);
|
|
15909
15955
|
const chars = entries.length ? entries.join(ENTRY_DELIMITER).length : 0;
|
|
15910
15956
|
if (chars > limit) {
|
|
15911
15957
|
throw new HermesMemoryError(
|
|
@@ -15957,6 +16003,10 @@ function toRecord12(value) {
|
|
|
15957
16003
|
function readString13(value) {
|
|
15958
16004
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
15959
16005
|
}
|
|
16006
|
+
function readPositiveInteger3(value) {
|
|
16007
|
+
const numberValue = typeof value === "number" ? value : typeof value === "string" ? Number(value.trim()) : NaN;
|
|
16008
|
+
return Number.isFinite(numberValue) && numberValue > 0 ? Math.floor(numberValue) : void 0;
|
|
16009
|
+
}
|
|
15960
16010
|
function readBoolean2(value) {
|
|
15961
16011
|
if (typeof value === "boolean") {
|
|
15962
16012
|
return value;
|
package/dist/cli/index.js
CHANGED
package/dist/http/app.js
CHANGED