@saleso.innovations/bridge 0.1.16 → 0.1.18
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/README.md +1 -1
- package/dist/client.d.ts +4 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +43 -6
- package/dist/convexRelay.d.ts +24 -0
- package/dist/convexRelay.d.ts.map +1 -0
- package/dist/convexRelay.js +70 -0
- package/dist/cronWatcher.d.ts.map +1 -1
- package/dist/cronWatcher.js +16 -2
- package/dist/hermesCommands.d.ts +1 -1
- package/dist/hermesCommands.d.ts.map +1 -1
- package/dist/hermesCommands.js +41 -0
- package/dist/hermesFileCommands.d.ts +19 -0
- package/dist/hermesFileCommands.d.ts.map +1 -0
- package/dist/hermesFileCommands.js +61 -0
- package/dist/hermesFiles.d.ts +60 -0
- package/dist/hermesFiles.d.ts.map +1 -0
- package/dist/hermesFiles.js +266 -0
- package/dist/hermesForwarder.d.ts +4 -1
- package/dist/hermesForwarder.d.ts.map +1 -1
- package/dist/hermesForwarder.js +82 -4
- package/dist/hermesSessionDb.d.ts +21 -0
- package/dist/hermesSessionDb.d.ts.map +1 -0
- package/dist/hermesSessionDb.js +174 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/runtimeVersion.d.ts +14 -0
- package/dist/runtimeVersion.d.ts.map +1 -0
- package/dist/runtimeVersion.js +105 -0
- package/dist/skillsList.d.ts +9 -0
- package/dist/skillsList.d.ts.map +1 -0
- package/dist/skillsList.js +187 -0
- package/package.json +14 -3
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ This installs the latest package, refreshes the CLI symlink, and restarts `cleos
|
|
|
34
34
|
To pin a specific release (e.g. after a Cleos update):
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
-
curl -fsSL https://amicable-elephant-407.convex.site/update-bridge.sh | bash -s -- 0.1.
|
|
37
|
+
curl -fsSL https://amicable-elephant-407.convex.site/update-bridge.sh | bash -s -- 0.1.18
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
## Manual usage
|
package/dist/client.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ export type UserMessageAttachment = {
|
|
|
18
18
|
export type UserMessageMeta = {
|
|
19
19
|
agentId: string;
|
|
20
20
|
conversationId: string;
|
|
21
|
-
|
|
21
|
+
clientMessageId: string;
|
|
22
|
+
replyMessageId: string;
|
|
22
23
|
attachments?: UserMessageAttachment[];
|
|
23
24
|
};
|
|
24
25
|
export type AgentActivityPayload = {
|
|
@@ -36,7 +37,7 @@ export type AgentFailedPayload = {
|
|
|
36
37
|
export type AgentReply = {
|
|
37
38
|
delta: (text: string, sequence: number) => void;
|
|
38
39
|
activity: (activity: AgentActivityPayload) => void;
|
|
39
|
-
complete: (text: string, sequence: number) => void;
|
|
40
|
+
complete: (text: string, sequence: number, attachments?: UserMessageAttachment[], hermesAssistantMessageId?: string) => void;
|
|
40
41
|
failed: (failure: AgentFailedPayload) => void;
|
|
41
42
|
};
|
|
42
43
|
export type CronDeliveryMeta = {
|
|
@@ -50,7 +51,7 @@ export type ConnectResult = {
|
|
|
50
51
|
agentToken: string;
|
|
51
52
|
close: () => void;
|
|
52
53
|
closed: Promise<void>;
|
|
53
|
-
deliverCronResult: (content: string, meta: CronDeliveryMeta) => void
|
|
54
|
+
deliverCronResult: (content: string, meta: CronDeliveryMeta) => Promise<void>;
|
|
54
55
|
};
|
|
55
56
|
export declare function pairCleosAgent(options: Omit<ConnectOptions, "onUserMessage">): Promise<{
|
|
56
57
|
agentId: string;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoC,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAYhG,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACrG,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -29,12 +29,13 @@ function parseUserMessageAttachments(raw) {
|
|
|
29
29
|
}
|
|
30
30
|
return attachments.length > 0 ? attachments : undefined;
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
const CRON_DELIVERY_TIMEOUT_MS = 45_000;
|
|
33
|
+
function sendCronResult(ws, agentId, messageId, content, meta) {
|
|
33
34
|
ws.send(JSON.stringify({
|
|
34
35
|
type: "agent.message",
|
|
35
36
|
agentId,
|
|
36
37
|
conversationId: meta.conversationId,
|
|
37
|
-
messageId
|
|
38
|
+
messageId,
|
|
38
39
|
content,
|
|
39
40
|
sequence: 0,
|
|
40
41
|
final: true,
|
|
@@ -72,7 +73,7 @@ function createReplySender(ws, agentId, conversationId, messageId) {
|
|
|
72
73
|
sequence: activity.sequence,
|
|
73
74
|
}));
|
|
74
75
|
},
|
|
75
|
-
complete(text, sequence) {
|
|
76
|
+
complete(text, sequence, attachments, hermesAssistantMessageId) {
|
|
76
77
|
ws.send(JSON.stringify({
|
|
77
78
|
type: "agent.message",
|
|
78
79
|
agentId,
|
|
@@ -81,6 +82,10 @@ function createReplySender(ws, agentId, conversationId, messageId) {
|
|
|
81
82
|
content: text,
|
|
82
83
|
sequence,
|
|
83
84
|
final: true,
|
|
85
|
+
...(attachments && attachments.length > 0 ? { attachments } : {}),
|
|
86
|
+
...(hermesAssistantMessageId
|
|
87
|
+
? { metadata: { hermes: { assistantMessageId: hermesAssistantMessageId } } }
|
|
88
|
+
: {}),
|
|
84
89
|
}));
|
|
85
90
|
},
|
|
86
91
|
failed(failure) {
|
|
@@ -165,6 +170,7 @@ function userSafeHermesError(error) {
|
|
|
165
170
|
}
|
|
166
171
|
async function openAgentConnection(options) {
|
|
167
172
|
const ws = new WebSocket(options.relayWsUrl);
|
|
173
|
+
const pendingAcks = new Map();
|
|
168
174
|
let closedResolve = null;
|
|
169
175
|
const closed = new Promise((resolve) => {
|
|
170
176
|
closedResolve = resolve;
|
|
@@ -182,6 +188,15 @@ async function openAgentConnection(options) {
|
|
|
182
188
|
ws.on("message", (raw) => {
|
|
183
189
|
void (async () => {
|
|
184
190
|
const envelope = JSON.parse(raw.toString());
|
|
191
|
+
if (envelope.type === "ack") {
|
|
192
|
+
const requestId = typeof envelope.requestId === "string" ? envelope.requestId : "";
|
|
193
|
+
const resolveAck = requestId ? pendingAcks.get(requestId) : undefined;
|
|
194
|
+
if (resolveAck) {
|
|
195
|
+
pendingAcks.delete(requestId);
|
|
196
|
+
resolveAck(envelope.ok === true);
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
185
200
|
if (envelope.type === "hermes.command") {
|
|
186
201
|
await handleHermesCommandEnvelope(ws, envelope, options.agentId);
|
|
187
202
|
return;
|
|
@@ -195,11 +210,14 @@ async function openAgentConnection(options) {
|
|
|
195
210
|
rememberConversationId(conversationId);
|
|
196
211
|
}
|
|
197
212
|
const attachments = parseUserMessageAttachments(envelope.attachments);
|
|
213
|
+
const clientMessageId = typeof envelope.clientMessageId === "string" && envelope.clientMessageId.trim().length > 0
|
|
214
|
+
? envelope.clientMessageId.trim()
|
|
215
|
+
: randomUUID();
|
|
198
216
|
const replyMessageId = randomUUID();
|
|
199
217
|
const reply = createReplySender(ws, agentId, conversationId, replyMessageId);
|
|
200
218
|
if (options.onUserMessage) {
|
|
201
219
|
try {
|
|
202
|
-
await options.onUserMessage(content, { agentId, conversationId,
|
|
220
|
+
await options.onUserMessage(content, { agentId, conversationId, clientMessageId, replyMessageId, attachments }, reply);
|
|
203
221
|
}
|
|
204
222
|
catch (error) {
|
|
205
223
|
const { message, code } = userSafeHermesError(error);
|
|
@@ -220,6 +238,10 @@ async function openAgentConnection(options) {
|
|
|
220
238
|
}, 30_000);
|
|
221
239
|
ws.on("close", () => {
|
|
222
240
|
clearInterval(heartbeat);
|
|
241
|
+
for (const [requestId, resolveAck] of pendingAcks.entries()) {
|
|
242
|
+
pendingAcks.delete(requestId);
|
|
243
|
+
resolveAck(false);
|
|
244
|
+
}
|
|
223
245
|
closedResolve?.();
|
|
224
246
|
});
|
|
225
247
|
return {
|
|
@@ -230,11 +252,26 @@ async function openAgentConnection(options) {
|
|
|
230
252
|
ws.close();
|
|
231
253
|
},
|
|
232
254
|
closed,
|
|
233
|
-
deliverCronResult(content, meta) {
|
|
255
|
+
async deliverCronResult(content, meta) {
|
|
234
256
|
if (ws.readyState !== WebSocket.OPEN) {
|
|
235
257
|
throw new Error("Cleos relay connection is not open");
|
|
236
258
|
}
|
|
237
|
-
|
|
259
|
+
const messageId = randomUUID();
|
|
260
|
+
await new Promise((resolve, reject) => {
|
|
261
|
+
const timer = setTimeout(() => {
|
|
262
|
+
pendingAcks.delete(messageId);
|
|
263
|
+
reject(new Error("Cron delivery ack timed out"));
|
|
264
|
+
}, CRON_DELIVERY_TIMEOUT_MS);
|
|
265
|
+
pendingAcks.set(messageId, (ok) => {
|
|
266
|
+
clearTimeout(timer);
|
|
267
|
+
if (ok) {
|
|
268
|
+
resolve();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
reject(new Error("Cron delivery persist failed"));
|
|
272
|
+
});
|
|
273
|
+
sendCronResult(ws, options.agentId, messageId, content, meta);
|
|
274
|
+
});
|
|
238
275
|
},
|
|
239
276
|
};
|
|
240
277
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ConvexUploadedFile = {
|
|
2
|
+
storageId: string;
|
|
3
|
+
url: string | null;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
fileName: string;
|
|
6
|
+
size: number;
|
|
7
|
+
};
|
|
8
|
+
export type HermesMessageLink = {
|
|
9
|
+
clientMessageId?: string;
|
|
10
|
+
externalMessageId?: string;
|
|
11
|
+
hermesMessageId: string;
|
|
12
|
+
};
|
|
13
|
+
export declare function linkHermesMessageIds(args: {
|
|
14
|
+
agentId: string;
|
|
15
|
+
conversationId: string;
|
|
16
|
+
links: HermesMessageLink[];
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export declare function uploadFileToConvex(args: {
|
|
19
|
+
agentId: string;
|
|
20
|
+
fileName: string;
|
|
21
|
+
mimeType: string;
|
|
22
|
+
contentBase64: string;
|
|
23
|
+
}): Promise<ConvexUploadedFile>;
|
|
24
|
+
//# sourceMappingURL=convexRelay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convexRelay.d.ts","sourceRoot":"","sources":["../src/convexRelay.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,EAAE,CAAC;CAC5B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4C9B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { loadCredentials } from "./credentials.js";
|
|
2
|
+
import { MAX_RELAY_UPLOAD_BYTES } from "./hermesFiles.js";
|
|
3
|
+
import { convexSiteUrlFromEnv } from "./resolve.js";
|
|
4
|
+
export async function linkHermesMessageIds(args) {
|
|
5
|
+
if (args.links.length === 0)
|
|
6
|
+
return;
|
|
7
|
+
const credentials = loadCredentials();
|
|
8
|
+
const convexSiteUrl = credentials?.convexSiteUrl ?? convexSiteUrlFromEnv();
|
|
9
|
+
const relaySecret = process.env.CLEOS_RELAY_SECRET?.trim() || "dev-relay-secret";
|
|
10
|
+
const response = await fetch(`${convexSiteUrl.replace(/\/$/, "")}/relay/messages`, {
|
|
11
|
+
method: "POST",
|
|
12
|
+
headers: {
|
|
13
|
+
"content-type": "application/json",
|
|
14
|
+
"x-cleos-relay-secret": relaySecret,
|
|
15
|
+
},
|
|
16
|
+
body: JSON.stringify({
|
|
17
|
+
envelope: {
|
|
18
|
+
type: "hermes.link",
|
|
19
|
+
agentId: args.agentId,
|
|
20
|
+
conversationId: args.conversationId,
|
|
21
|
+
links: args.links,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
if (!response.ok) {
|
|
26
|
+
const text = await response.text();
|
|
27
|
+
throw new Error(`Failed to link Hermes message IDs (${response.status}): ${text}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function uploadFileToConvex(args) {
|
|
31
|
+
if (args.contentBase64.length === 0) {
|
|
32
|
+
throw new Error("contentBase64 is required");
|
|
33
|
+
}
|
|
34
|
+
const byteLength = Buffer.byteLength(args.contentBase64, "base64");
|
|
35
|
+
if (byteLength > MAX_RELAY_UPLOAD_BYTES) {
|
|
36
|
+
throw new Error(`File exceeds maximum upload size (${MAX_RELAY_UPLOAD_BYTES} bytes)`);
|
|
37
|
+
}
|
|
38
|
+
const credentials = loadCredentials();
|
|
39
|
+
const convexSiteUrl = credentials?.convexSiteUrl ?? convexSiteUrlFromEnv();
|
|
40
|
+
const relaySecret = process.env.CLEOS_RELAY_SECRET?.trim() || "dev-relay-secret";
|
|
41
|
+
const response = await fetch(`${convexSiteUrl.replace(/\/$/, "")}/relay/files`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
"content-type": "application/json",
|
|
45
|
+
"x-cleos-relay-secret": relaySecret,
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
agentId: args.agentId,
|
|
49
|
+
fileName: args.fileName,
|
|
50
|
+
mimeType: args.mimeType,
|
|
51
|
+
contentBase64: args.contentBase64,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
const text = await response.text();
|
|
56
|
+
throw new Error(`Failed to upload file to Convex (${response.status}): ${text}`);
|
|
57
|
+
}
|
|
58
|
+
const payload = (await response.json());
|
|
59
|
+
const storageId = typeof payload.storageId === "string" ? payload.storageId : "";
|
|
60
|
+
if (!storageId) {
|
|
61
|
+
throw new Error("Upload response missing storageId");
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
storageId,
|
|
65
|
+
url: typeof payload.url === "string" ? payload.url : null,
|
|
66
|
+
mimeType: args.mimeType,
|
|
67
|
+
fileName: args.fileName,
|
|
68
|
+
size: byteLength,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cronWatcher.d.ts","sourceRoot":"","sources":["../src/cronWatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,eAAO,MAAM,sBAAsB,QAA+C,CAAC;AAEnF,eAAO,MAAM,oBAAoB,QAAmD,CAAC;AASrF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,aAAa,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,GAAG,CAAC,MAAM,CAAC,CAQhD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAGhE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,MAA+B,GAAG,MAAM,EAAE,CAoBtF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,SAAS,GAAE,GAAG,CAAC,MAAM,CAAwB,GAAG,MAAM,EAAE,CAE5F;
|
|
1
|
+
{"version":3,"file":"cronWatcher.d.ts","sourceRoot":"","sources":["../src/cronWatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,eAAO,MAAM,sBAAsB,QAA+C,CAAC;AAEnF,eAAO,MAAM,oBAAoB,QAAmD,CAAC;AASrF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,aAAa,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,GAAG,CAAC,MAAM,CAAC,CAQhD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAGhE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,MAA+B,GAAG,MAAM,EAAE,CAoBtF;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,SAAS,GAAE,GAAG,CAAC,MAAM,CAAwB,GAAG,MAAM,EAAE,CAE5F;AAsID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI,CA8BxE;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1F,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAsBD"}
|
package/dist/cronWatcher.js
CHANGED
|
@@ -83,6 +83,13 @@ function parseRunAtFromFileName(filePath) {
|
|
|
83
83
|
const base = filePath.split("/").pop()?.replace(/\.md$/i, "") ?? "";
|
|
84
84
|
if (!base)
|
|
85
85
|
return undefined;
|
|
86
|
+
const underscoreMatch = /^(\d{4}-\d{2}-\d{2})_(\d{2})-(\d{2})-(\d{2})$/.exec(base);
|
|
87
|
+
if (underscoreMatch) {
|
|
88
|
+
const [, datePart, hour, minute, second] = underscoreMatch;
|
|
89
|
+
const parsed = Date.parse(`${datePart}T${hour}:${minute}:${second}`);
|
|
90
|
+
if (Number.isFinite(parsed))
|
|
91
|
+
return parsed;
|
|
92
|
+
}
|
|
86
93
|
const asNumber = Number(base);
|
|
87
94
|
if (Number.isFinite(asNumber) && asNumber > 0)
|
|
88
95
|
return asNumber;
|
|
@@ -130,7 +137,7 @@ async function deliverPendingFiles(session, delivered, conversationId, options)
|
|
|
130
137
|
continue;
|
|
131
138
|
}
|
|
132
139
|
try {
|
|
133
|
-
session.deliverCronResult(content, {
|
|
140
|
+
await session.deliverCronResult(content, {
|
|
134
141
|
conversationId,
|
|
135
142
|
jobId,
|
|
136
143
|
jobName,
|
|
@@ -146,7 +153,14 @@ async function deliverPendingFiles(session, delivered, conversationId, options)
|
|
|
146
153
|
}));
|
|
147
154
|
return;
|
|
148
155
|
}
|
|
149
|
-
|
|
156
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
157
|
+
options.onError?.(message);
|
|
158
|
+
console.error(JSON.stringify({
|
|
159
|
+
event: "cleos-bridge.cron-delivery-failed",
|
|
160
|
+
file: key,
|
|
161
|
+
message,
|
|
162
|
+
}));
|
|
163
|
+
continue;
|
|
150
164
|
}
|
|
151
165
|
delivered.add(key);
|
|
152
166
|
writeDeliveredIndex(delivered);
|
package/dist/hermesCommands.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const HERMES_COMMAND_NAMES: readonly ["runtime.health", "runtime.detailedHealth", "runtime.capabilities", "models.list", "model.set", "responses.create", "runs.create", "runs.status", "runs.stop", "jobs.list", "jobs.get", "jobs.create", "jobs.update", "jobs.pause", "jobs.resume", "jobs.runNow", "jobs.delete", "profiles.list", "profiles.create", "gateway.start", "gateway.stop", "gateway.restart", "hermes.update"];
|
|
1
|
+
export declare const HERMES_COMMAND_NAMES: readonly ["runtime.health", "runtime.detailedHealth", "runtime.version", "runtime.capabilities", "models.list", "model.set", "responses.create", "runs.create", "runs.status", "runs.stop", "jobs.list", "jobs.get", "jobs.create", "jobs.update", "jobs.pause", "jobs.resume", "jobs.runNow", "jobs.delete", "profiles.list", "profiles.create", "gateway.start", "gateway.stop", "gateway.restart", "hermes.update", "sessions.messages.list", "sessions.messages.countSent", "skills.list", "files.list", "files.read"];
|
|
2
2
|
export type HermesCommandName = (typeof HERMES_COMMAND_NAMES)[number];
|
|
3
3
|
export declare function isHermesCommandName(value: string): value is HermesCommandName;
|
|
4
4
|
export type HermesCommandErrorCode = "command_unsupported" | "hermes_unreachable" | "hermes_request_failed" | "invalid_command_args" | "unsupported_by_http";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hermesCommands.d.ts","sourceRoot":"","sources":["../src/hermesCommands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hermesCommands.d.ts","sourceRoot":"","sources":["../src/hermesCommands.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,oBAAoB,4fA8BvB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,iBAAiB,CAE7E;AAED,MAAM,MAAM,sBAAsB,GAC9B,qBAAqB,GACrB,oBAAoB,GACpB,uBAAuB,GACvB,sBAAsB,GACtB,qBAAqB,CAAC;AAE1B,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;gBAE1B,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM;CAI1D;AAgGD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACjE,OAAO,CAAC,OAAO,CAAC,CAwLlB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAetG"}
|
package/dist/hermesCommands.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { resolveHermesApiConfig } from "./hermesForwarder.js";
|
|
2
2
|
import { restartHermesGateway, startHermesGateway, stopHermesGateway } from "./gatewayControl.js";
|
|
3
3
|
import { listHermesCronJobs } from "./cronList.js";
|
|
4
|
+
import { listSessionMessages, countUserMessagesSent } from "./hermesSessionDb.js";
|
|
5
|
+
import { listHermesSkills } from "./skillsList.js";
|
|
4
6
|
import { runHermesUpdate } from "./hermesUpdate.js";
|
|
7
|
+
import { executeFilesList, executeFilesRead } from "./hermesFileCommands.js";
|
|
8
|
+
import { fetchHermesRuntimeVersion } from "./runtimeVersion.js";
|
|
5
9
|
export const HERMES_COMMAND_NAMES = [
|
|
6
10
|
"runtime.health",
|
|
7
11
|
"runtime.detailedHealth",
|
|
12
|
+
"runtime.version",
|
|
8
13
|
"runtime.capabilities",
|
|
9
14
|
"models.list",
|
|
10
15
|
"model.set",
|
|
@@ -26,6 +31,11 @@ export const HERMES_COMMAND_NAMES = [
|
|
|
26
31
|
"gateway.stop",
|
|
27
32
|
"gateway.restart",
|
|
28
33
|
"hermes.update",
|
|
34
|
+
"sessions.messages.list",
|
|
35
|
+
"sessions.messages.countSent",
|
|
36
|
+
"skills.list",
|
|
37
|
+
"files.list",
|
|
38
|
+
"files.read",
|
|
29
39
|
];
|
|
30
40
|
export function isHermesCommandName(value) {
|
|
31
41
|
return HERMES_COMMAND_NAMES.includes(value);
|
|
@@ -71,6 +81,15 @@ function optionalRecord(args, key) {
|
|
|
71
81
|
}
|
|
72
82
|
return value;
|
|
73
83
|
}
|
|
84
|
+
function optionalNumber(args, key) {
|
|
85
|
+
const value = args[key];
|
|
86
|
+
if (value === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
89
|
+
throw new HermesCommandError("invalid_command_args", `Invalid "${key}"`);
|
|
90
|
+
}
|
|
91
|
+
return Math.floor(value);
|
|
92
|
+
}
|
|
74
93
|
async function hermesFetchJson(config, path, init = {}) {
|
|
75
94
|
const url = `${hermesBaseUrl(config.apiUrl)}${path}`;
|
|
76
95
|
const headers = {
|
|
@@ -109,6 +128,8 @@ export async function executeHermesCommand(command, args, options = {}) {
|
|
|
109
128
|
return await hermesFetchJson(config, "/health");
|
|
110
129
|
case "runtime.detailedHealth":
|
|
111
130
|
return await hermesFetchJson(config, "/health/detailed");
|
|
131
|
+
case "runtime.version":
|
|
132
|
+
return await fetchHermesRuntimeVersion();
|
|
112
133
|
case "runtime.capabilities":
|
|
113
134
|
return await hermesFetchJson(config, "/v1/capabilities");
|
|
114
135
|
case "models.list":
|
|
@@ -256,6 +277,26 @@ export async function executeHermesCommand(command, args, options = {}) {
|
|
|
256
277
|
const restartGateway = args.restartGateway === true || args.restart_gateway === true;
|
|
257
278
|
return await runHermesUpdate({ restartGateway });
|
|
258
279
|
}
|
|
280
|
+
case "sessions.messages.list": {
|
|
281
|
+
const sessionId = requireString(args, "sessionId");
|
|
282
|
+
const limit = optionalNumber(args, "limit");
|
|
283
|
+
const offset = optionalNumber(args, "offset");
|
|
284
|
+
const offsetFromEnd = optionalNumber(args, "offsetFromEnd");
|
|
285
|
+
return listSessionMessages(sessionId, { limit, offset, offsetFromEnd });
|
|
286
|
+
}
|
|
287
|
+
case "sessions.messages.countSent":
|
|
288
|
+
return countUserMessagesSent();
|
|
289
|
+
case "skills.list":
|
|
290
|
+
return await listHermesSkills();
|
|
291
|
+
case "files.list":
|
|
292
|
+
return await executeFilesList(args);
|
|
293
|
+
case "files.read": {
|
|
294
|
+
const path = optionalString(args, "path");
|
|
295
|
+
if (!path) {
|
|
296
|
+
throw new HermesCommandError("invalid_command_args", 'Missing "path"');
|
|
297
|
+
}
|
|
298
|
+
return await executeFilesRead({ ...args, path });
|
|
299
|
+
}
|
|
259
300
|
default: {
|
|
260
301
|
const _exhaustive = command;
|
|
261
302
|
throw new HermesCommandError("command_unsupported", `Unsupported command: ${String(_exhaustive)}`);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function executeFilesList(args: Record<string, unknown>): Promise<{
|
|
2
|
+
files: import("./hermesFiles.js").HermesFileEntry[];
|
|
3
|
+
}>;
|
|
4
|
+
export declare function executeFilesRead(args: Record<string, unknown>): Promise<{
|
|
5
|
+
fileName: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
size: number;
|
|
8
|
+
contentBase64: string;
|
|
9
|
+
storageId?: undefined;
|
|
10
|
+
url?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
fileName: string;
|
|
13
|
+
mimeType: string;
|
|
14
|
+
size: number;
|
|
15
|
+
storageId: string;
|
|
16
|
+
url: string | undefined;
|
|
17
|
+
contentBase64?: undefined;
|
|
18
|
+
}>;
|
|
19
|
+
//# sourceMappingURL=hermesFileCommands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermesFileCommands.d.ts","sourceRoot":"","sources":["../src/hermesFileCommands.ts"],"names":[],"mappings":"AA6BA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;GAKnE;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;GAkCnE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { DEFAULT_FILES_READ_MAX_BYTES, listHermesFiles, readHermesFileBytes, } from "./hermesFiles.js";
|
|
2
|
+
import { uploadFileToConvex } from "./convexRelay.js";
|
|
3
|
+
import { loadCredentials } from "./credentials.js";
|
|
4
|
+
function optionalNumber(args, key) {
|
|
5
|
+
const value = args[key];
|
|
6
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
7
|
+
return value;
|
|
8
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
9
|
+
const parsed = Number.parseInt(value, 10);
|
|
10
|
+
if (Number.isFinite(parsed))
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
function optionalCategory(args) {
|
|
16
|
+
const value = args.category;
|
|
17
|
+
if (typeof value !== "string")
|
|
18
|
+
return "all";
|
|
19
|
+
const normalized = value.trim().toLowerCase();
|
|
20
|
+
if (normalized === "image" || normalized === "video" || normalized === "document") {
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
return "all";
|
|
24
|
+
}
|
|
25
|
+
export async function executeFilesList(args) {
|
|
26
|
+
const limit = optionalNumber(args, "limit");
|
|
27
|
+
const offset = optionalNumber(args, "offset");
|
|
28
|
+
const category = optionalCategory(args);
|
|
29
|
+
return listHermesFiles({ limit, offset, category });
|
|
30
|
+
}
|
|
31
|
+
export async function executeFilesRead(args) {
|
|
32
|
+
const path = typeof args.path === "string" ? args.path.trim() : "";
|
|
33
|
+
const maxBytes = optionalNumber(args, "maxBytes") ?? DEFAULT_FILES_READ_MAX_BYTES;
|
|
34
|
+
const { bytes, mimeType, fileName, size } = readHermesFileBytes(path);
|
|
35
|
+
if (size <= maxBytes) {
|
|
36
|
+
return {
|
|
37
|
+
fileName,
|
|
38
|
+
mimeType,
|
|
39
|
+
size,
|
|
40
|
+
contentBase64: bytes.toString("base64"),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const credentials = loadCredentials();
|
|
44
|
+
const agentId = credentials?.agentId;
|
|
45
|
+
if (!agentId) {
|
|
46
|
+
throw new Error("Large files require bridge credentials with agentId for Convex upload.");
|
|
47
|
+
}
|
|
48
|
+
const uploaded = await uploadFileToConvex({
|
|
49
|
+
agentId,
|
|
50
|
+
fileName,
|
|
51
|
+
mimeType,
|
|
52
|
+
contentBase64: bytes.toString("base64"),
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
fileName,
|
|
56
|
+
mimeType,
|
|
57
|
+
size,
|
|
58
|
+
storageId: uploaded.storageId,
|
|
59
|
+
url: uploaded.url ?? undefined,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const MAX_RELAY_UPLOAD_BYTES: number;
|
|
2
|
+
export declare const DEFAULT_FILES_READ_MAX_BYTES: number;
|
|
3
|
+
export type HermesFileCategory = "image" | "video" | "document" | "other";
|
|
4
|
+
export type HermesFileEntry = {
|
|
5
|
+
relativePath: string;
|
|
6
|
+
fileName: string;
|
|
7
|
+
size: number;
|
|
8
|
+
mtime: number;
|
|
9
|
+
mimeType: string;
|
|
10
|
+
category: HermesFileCategory;
|
|
11
|
+
};
|
|
12
|
+
export type HermesFileReadResult = {
|
|
13
|
+
fileName: string;
|
|
14
|
+
mimeType: string;
|
|
15
|
+
size: number;
|
|
16
|
+
contentBase64?: string;
|
|
17
|
+
storageId?: string;
|
|
18
|
+
url?: string;
|
|
19
|
+
};
|
|
20
|
+
export type MediaReference = {
|
|
21
|
+
kind: "local";
|
|
22
|
+
absolutePath: string;
|
|
23
|
+
raw: string;
|
|
24
|
+
} | {
|
|
25
|
+
kind: "url";
|
|
26
|
+
url: string;
|
|
27
|
+
raw: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function resolveHermesHome(): string;
|
|
30
|
+
export declare function inferMimeType(fileName: string): string;
|
|
31
|
+
export declare function inferCategory(fileName: string): HermesFileCategory;
|
|
32
|
+
export declare function resolveSandboxedPath(inputPath: string): string;
|
|
33
|
+
export declare function listHermesFiles(options?: {
|
|
34
|
+
limit?: number;
|
|
35
|
+
offset?: number;
|
|
36
|
+
category?: HermesFileCategory | "all";
|
|
37
|
+
}): {
|
|
38
|
+
files: HermesFileEntry[];
|
|
39
|
+
};
|
|
40
|
+
export declare function readHermesFileBytes(inputPath: string): {
|
|
41
|
+
bytes: Buffer;
|
|
42
|
+
mimeType: string;
|
|
43
|
+
fileName: string;
|
|
44
|
+
size: number;
|
|
45
|
+
};
|
|
46
|
+
export declare function parseMediaReferences(text: string): MediaReference[];
|
|
47
|
+
export declare function stripMediaReferences(text: string, refs: MediaReference[]): string;
|
|
48
|
+
export declare function downloadUrlToBytes(url: string, timeoutMs?: number): Promise<{
|
|
49
|
+
bytes: Buffer;
|
|
50
|
+
mimeType: string;
|
|
51
|
+
fileName: string;
|
|
52
|
+
size: number;
|
|
53
|
+
}>;
|
|
54
|
+
export declare function resolveMediaReferenceBytes(ref: MediaReference): Promise<{
|
|
55
|
+
bytes: Buffer;
|
|
56
|
+
mimeType: string;
|
|
57
|
+
fileName: string;
|
|
58
|
+
size: number;
|
|
59
|
+
} | null>;
|
|
60
|
+
//# sourceMappingURL=hermesFiles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermesFiles.d.ts","sourceRoot":"","sources":["../src/hermesFiles.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,QAAmB,CAAC;AACvD,eAAO,MAAM,4BAA4B,QAAa,CAAC;AAgCvD,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9C,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiCtD;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAMlE;AAQD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAe9D;AA8DD,wBAAgB,eAAe,CAAC,OAAO,GAAE;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,kBAAkB,GAAG,KAAK,CAAC;CAClC,GAAG;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,CAepC;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAe1H;AAMD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CA6BnE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,MAAM,CAMjF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAS,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBtJ;AAED,wBAAsB,0BAA0B,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CASzJ"}
|